Merged with development

This commit is contained in:
WBHarry 2025-08-23 18:17:32 +02:00
commit bd76e22e8d
1096 changed files with 11080 additions and 5102 deletions

View file

@ -26,7 +26,8 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
hasResource: false,
isQuantifiable: false,
isInventoryItem: false,
hasActions: false
hasActions: false,
hasAttribution: true
};
}
@ -37,7 +38,13 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
/** @inheritDoc */
static defineSchema() {
const schema = {};
const schema = {
attribution: new fields.SchemaField({
source: new fields.StringField(),
page: new fields.NumberField(),
artist: new fields.StringField()
})
};
if (this.metadata.hasDescription) schema.description = new fields.HTMLField({ required: true, nullable: true });
@ -110,6 +117,13 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
return [];
}
get attributionLabel() {
if (!this.attribution) return;
const { source, page } = this.attribution;
return [source, page ? `pg ${page}.` : null].filter(x => x).join('. ');
}
/**
* Obtain a data object used to evaluate any dice rolls associated with this Item Type
* @param {object} [options] - Options which modify the getRollData method.
@ -144,50 +158,30 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
}
if (this.actor && this.actor.type === 'character' && this.features) {
const featureUpdates = {};
const features = [];
for (let f of this.features) {
const fBase = f.item ?? f;
const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid);
const createData = foundry.utils.mergeObject(
feature.toObject(),
{
system: {
originItemType: this.parent.type,
originId: data._id,
identifier: this.isMulticlass ? 'multiclass' : null
}
},
{ inplace: false }
const multiclass = this.isMulticlass ? 'multiclass' : null;
features.push(
foundry.utils.mergeObject(
feature.toObject(),
{
_stats: { compendiumSource: fBase.uuid },
system: {
originItemType: this.parent.type,
identifier: multiclass ?? (f.item ? f.type : null)
}
},
{ inplace: false }
)
);
const [doc] = await this.actor.createEmbeddedDocuments('Item', [createData]);
if (!featureUpdates.features)
featureUpdates.features = this.features.map(x => (x.item ? { ...x, item: x.item.uuid } : x.uuid));
if (f.item) {
const existingFeature = featureUpdates.features.find(x => x.item === f.item.uuid);
existingFeature.item = doc.uuid;
} else {
const replaceIndex = featureUpdates.features.findIndex(x => x === f.uuid);
featureUpdates.features.splice(replaceIndex, 1, doc.uuid);
}
}
await this.updateSource(featureUpdates);
await this.actor.createEmbeddedDocuments('Item', features);
}
}
async _preDelete() {
if (!this.actor || this.actor.type !== 'character') return;
const items = this.actor.items.filter(item => item.system.originId === this.parent.id);
if (items.length > 0)
await this.actor.deleteEmbeddedDocuments(
'Item',
items.map(x => x.id)
);
}
async _preUpdate(changed, options, userId) {
const allowed = await super._preUpdate(changed, options, userId);
if (allowed === false) return false;
@ -207,6 +201,8 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
super._onUpdate(changed, options, userId);
updateLinkedItemApps(options, this.parent.sheet);
createScrollText(this.parent?.parent, options.scrollingTextData);
if (this.parent?.parent && options.scrollingTextData)
this.parent.parent.queueScrollText(options.scrollingTextData);
}
}

View file

@ -1,5 +1,4 @@
import BaseDataItem from './base.mjs';
import { ActionField, ActionsField } from '../fields/actionField.mjs';
export default class DHFeature extends BaseDataItem {
/** @inheritDoc */
@ -30,24 +29,7 @@ export default class DHFeature extends BaseDataItem {
nullable: true,
initial: null
}),
originId: new fields.StringField({ nullable: true, initial: null }),
identifier: new fields.StringField()
};
}
get spellcastingModifier() {
let traitValue = 0;
if (this.actor && this.originId && ['class', 'subclass'].includes(this.originItemType)) {
if (this.originItemType === 'subclass') {
traitValue =
this.actor.system.traits[this.actor.items.get(this.originId).system.spellcastingTrait]?.value ?? 0;
} else {
const { value: multiclass, subclass } = this.actor.system.multiclass;
const selectedSubclass = multiclass?.id === this.originId ? subclass : this.actor.system.class.subclass;
traitValue = this.actor.system.traits[selectedSubclass.system.spellcastingTrait]?.value ?? 0;
}
}
return traitValue;
}
}

View file

@ -199,8 +199,8 @@ export default class DHWeapon extends AttachableItem {
];
for (const { value, type } of attack.damage.parts) {
const parts = [value.dice];
if (value.bonus) parts.push(value.bonus.signedString());
const parts = value.custom.enabled ? [game.i18n.localize('DAGGERHEART.GENERAL.custom')] : [value.dice];
if (!value.custom.enabled && value.bonus) parts.push(value.bonus.signedString());
if (type.size > 0) {
const typeTags = Array.from(type)