Show notification when invalid item types are added to actors (#1807)

This commit is contained in:
Carlos Fernandez 2026-04-16 02:23:25 -04:00 committed by GitHub
parent 7d5cdeb09d
commit aa8771bf0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 41 additions and 25 deletions

View file

@ -213,6 +213,9 @@
"headerTitle": "Adversary Reaction Roll" "headerTitle": "Adversary Reaction Roll"
} }
}, },
"Base": {
"CannotAddType": "Cannot add {itemType} items to {actorType} actors."
},
"Character": { "Character": {
"advantageSources": { "advantageSources": {
"label": "Advantage Sources", "label": "Advantage Sources",

View file

@ -73,7 +73,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
.hideAttribution; .hideAttribution;
// Prepare inventory data // Prepare inventory data
if (['party', 'character'].includes(this.document.type)) { if (this.document.system.metadata.hasInventory) {
context.inventory = { context.inventory = {
currencies: {}, currencies: {},
weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort), weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort),
@ -283,11 +283,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
async _onDropItem(event, item) { async _onDropItem(event, item) {
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
const originActor = item.actor; const originActor = item.actor;
if ( if (!originActor || originActor.uuid === this.document.uuid || !this.document.system.metadata.hasInventory) {
item.actor?.uuid === this.document.uuid ||
!originActor ||
!['character', 'party'].includes(this.document.type)
) {
return super._onDropItem(event, item); return super._onDropItem(event, item);
} }

View file

@ -31,11 +31,12 @@ export default class AncestrySheet extends DHHeritageSheet {
if (data.type === 'ActiveEffect') return super._onDrop(event); if (data.type === 'ActiveEffect') return super._onDrop(event);
const target = event.target.closest('fieldset.drop-section'); const target = event.target.closest('fieldset.drop-section');
const typeField = if (target) {
this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature']; const typeField =
this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature'];
if (!typeField) { if (!typeField) {
super._onDrop(event); super._onDrop(event);
}
} }
} }
} }

View file

@ -133,7 +133,7 @@ export default class DhpAdversary extends DhCreature {
} }
isItemValid(source) { isItemValid(source) {
return source.type === 'feature'; return super.isItemValid(source) || source.type === 'feature';
} }
async _preUpdate(changes, options, user) { async _preUpdate(changes, options, user) {

View file

@ -107,7 +107,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
hasResistances: true, hasResistances: true,
hasAttribution: false, hasAttribution: false,
hasLimitedView: true, hasLimitedView: true,
usesSize: false usesSize: false,
hasInventory: false
}; };
} }
@ -168,6 +169,11 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
/* -------------------------------------------- */ /* -------------------------------------------- */
isItemValid(source) {
const inventoryTypes = ['weapon', 'armor', 'consumable', 'loot'];
return this.metadata.hasInventory && inventoryTypes.includes(source.type);
}
/** /**
* Obtain a data object used to evaluate any dice rolls associated with this Item Type * Obtain a data object used to evaluate any dice rolls associated with this Item Type
* @param {object} [options] - Options which modify the getRollData method. * @param {object} [options] - Options which modify the getRollData method.

View file

@ -18,7 +18,8 @@ export default class DhCharacter extends DhCreature {
label: 'TYPES.Actor.character', label: 'TYPES.Actor.character',
type: 'character', type: 'character',
settingSheet: DHCharacterSettings, settingSheet: DHCharacterSettings,
isNPC: false isNPC: false,
hasInventory: true
}); });
} }
@ -429,6 +430,11 @@ export default class DhCharacter extends DhCreature {
return attack; return attack;
} }
/* All items are valid on characters */
isItemValid() {
return true;
}
/** @inheritDoc */ /** @inheritDoc */
isItemAvailable(item) { isItemAvailable(item) {
if (!super.isItemAvailable(this)) return false; if (!super.isItemAvailable(this)) return false;

View file

@ -118,10 +118,6 @@ export default class DhCompanion extends DhCreature {
return this.levelupChoicesLeft > 0; return this.levelupChoicesLeft > 0;
} }
isItemValid() {
return false;
}
prepareBaseData() { prepareBaseData() {
super.prepareBaseData(); super.prepareBaseData();
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0; this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;

View file

@ -56,7 +56,7 @@ export default class DhEnvironment extends BaseDataActor {
} }
isItemValid(source) { isItemValid(source) {
return source.type === 'feature'; return super.isItemValid(source) || source.type === 'feature';
} }
_onUpdate(changes, options, userId) { _onUpdate(changes, options, userId) {

View file

@ -5,6 +5,13 @@ import GroupRollData from '../groupRollData.mjs';
import { GoldField } from '../fields/actorField.mjs'; import { GoldField } from '../fields/actorField.mjs';
export default class DhParty extends BaseDataActor { export default class DhParty extends BaseDataActor {
/** @inheritdoc */
static get metadata() {
return foundry.utils.mergeObject(super.metadata, {
hasInventory: true
});
}
/**@inheritdoc */ /**@inheritdoc */
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
@ -29,10 +36,6 @@ export default class DhParty extends BaseDataActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
isItemValid(source) {
return ['weapon', 'armor', 'consumable', 'loot'].includes(source.type);
}
prepareBaseData() { prepareBaseData() {
super.prepareBaseData(); super.prepareBaseData();

View file

@ -31,8 +31,13 @@ export default class DHItem extends foundry.documents.Item {
static async createDocuments(sources, operation) { static async createDocuments(sources, operation) {
// Ensure that items being created are valid to the actor its being added to // Ensure that items being created are valid to the actor its being added to
const actor = operation.parent; const actor = operation.parent;
sources = actor?.system?.isItemValid ? sources.filter(s => actor.system.isItemValid(s)) : sources; const filtered = actor ? sources.filter(s => actor.system.isItemValid(s)) : sources;
return super.createDocuments(sources, operation); if (actor && filtered.length === 0 && sources.length > 0) {
const itemType = _loc(`TYPES.Item.${sources[0].type}`);
const actorType = _loc(`TYPES.Actor.${actor.type}`);
ui.notifications.error('DAGGERHEART.ACTORS.Base.CannotAddType', { format: { itemType, actorType } });
}
return super.createDocuments(filtered, operation);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */