Added support for adversary actor sizes

This commit is contained in:
WBHarry 2025-12-15 19:58:23 +01:00
parent 9b4249b100
commit d38b924cad
15 changed files with 180 additions and 5 deletions

View file

@ -44,6 +44,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
deleteAdversaryType: this.deleteAdversaryType,
selectAdversaryType: this.selectAdversaryType,
save: this.save,
resetTokenSizes: this.resetTokenSizes,
reset: this.reset
},
form: { handler: this.updateData, submitOnChange: true }
@ -424,6 +425,17 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
this.close();
}
static async resetTokenSizes() {
await this.settings.updateSource({
tokenSizes: Object.values(this.settings.schema.fields.tokenSizes.fields).reduce(
(acc, field) => ({ ...acc, [field.name]: field.initial }),
{}
)
});
this.render();
}
static async reset() {
const confirmed = await foundry.applications.api.DialogV2.confirm({
window: {

View file

@ -211,6 +211,39 @@ export const adversaryTraits = {
}
};
export const tokenSize = {
tiny: {
id: 'tiny',
value: 1,
label: 'DAGGERHEART.CONFIG.TokenSize.tiny'
},
small: {
id: 'small',
value: 2,
label: 'DAGGERHEART.CONFIG.TokenSize.small'
},
medium: {
id: 'medium',
value: 3,
label: 'DAGGERHEART.CONFIG.TokenSize.medium'
},
large: {
id: 'large',
value: 4,
label: 'DAGGERHEART.CONFIG.TokenSize.large'
},
huge: {
id: 'huge',
value: 5,
label: 'DAGGERHEART.CONFIG.TokenSize.huge'
},
gargantuan: {
id: 'gargantuan',
value: 6,
label: 'DAGGERHEART.CONFIG.TokenSize.gargantuan'
}
};
export const levelChoices = {
attributes: {
name: 'attributes',

View file

@ -41,7 +41,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
settingSheet: null,
hasResistances: true,
hasAttribution: false,
hasLimitedView: true
hasLimitedView: true,
usesSize: true
};
}
@ -76,6 +77,13 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
'DAGGERHEART.GENERAL.DamageResistance.magicalReduction'
)
});
if (this.metadata.usesSize)
schema.size = new fields.StringField({
required: true,
nullable: false,
choices: CONFIG.DH.ACTOR.tokenSize,
initial: CONFIG.DH.ACTOR.tokenSize.medium.id
});
return schema;
}
@ -138,6 +146,14 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
options.scrollingTextData = textData;
}
if (!this.parent.isToken && changes.system?.size) {
const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes;
this.parent.prototypeToken.update({
width: tokenSizes[changes.system.size],
height: tokenSizes[changes.system.size]
});
}
if (changes.system?.resources) {
const defeatedSettings = game.settings.get(
CONFIG.DH.id,

View file

@ -2,6 +2,13 @@ import BaseDataActor from './base.mjs';
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
export default class DhParty extends BaseDataActor {
/**@inheritdoc */
static get metadata() {
return foundry.utils.mergeObject(super.metadata, {
usesSize: false
});
}
/**@inheritdoc */
static defineSchema() {
const fields = foundry.data.fields;
@ -26,7 +33,7 @@ export default class DhParty extends BaseDataActor {
/* -------------------------------------------- */
isItemValid(source) {
return ["weapon", "armor", "consumable", "loot"].includes(source.type);
return ['weapon', 'armor', 'consumable', 'loot'].includes(source.type);
}
prepareBaseData() {

View file

@ -40,6 +40,38 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
traitArray: new fields.ArrayField(new fields.NumberField({ required: true, integer: true }), {
initial: () => [2, 1, 1, 0, 0, -1]
}),
tokenSizes: new fields.SchemaField({
tiny: new fields.NumberField({
integer: false,
initial: 0.4,
label: 'DAGGERHEART.CONFIG.TokenSize.tiny'
}),
small: new fields.NumberField({
integer: false,
initial: 0.6,
label: 'DAGGERHEART.CONFIG.TokenSize.small'
}),
medium: new fields.NumberField({
integer: false,
initial: 1,
label: 'DAGGERHEART.CONFIG.TokenSize.medium'
}),
large: new fields.NumberField({
integer: false,
initial: 2,
label: 'DAGGERHEART.CONFIG.TokenSize.large'
}),
huge: new fields.NumberField({
integer: false,
initial: 3,
label: 'DAGGERHEART.CONFIG.TokenSize.huge'
}),
gargantuan: new fields.NumberField({
integer: false,
initial: 4,
label: 'DAGGERHEART.CONFIG.TokenSize.gargantuan'
})
}),
currency: new fields.SchemaField({
title: new fields.StringField({
required: true,

View file

@ -4,6 +4,7 @@ export { default as DhpCombat } from './combat.mjs';
export { default as DHCombatant } from './combatant.mjs';
export { default as DhActiveEffect } from './activeEffect.mjs';
export { default as DhChatMessage } from './chatMessage.mjs';
export { default as DhScene } from './scene.mjs';
export { default as DhToken } from './token.mjs';
export { default as DhTooltipManager } from './tooltipManager.mjs';
export { default as DhTemplateManager } from './templateManager.mjs';

View file

@ -0,0 +1,22 @@
export default class DhScene extends Scene {
/** A map of `TokenDocument` IDs embedded in this scene long with new dimensions from actor size-category changes */
#sizeSyncBatch = new Map();
/** Synchronize a token's dimensions with its actor's size category. */
syncTokenDimensions(tokenDoc, dimensions) {
if (!tokenDoc.parent?.tokens.has(tokenDoc.id)) return;
this.#sizeSyncBatch.set(tokenDoc.id, dimensions);
this.#processSyncBatch();
}
/** Retrieve size and clear size-sync batch, make updates. */
#processSyncBatch = foundry.utils.debounce(() => {
const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes;
const entries = this.#sizeSyncBatch
.entries()
.toArray()
.map(([_id, { width, height }]) => ({ _id, width: tokenSizes[width], height: tokenSizes[height] }));
this.#sizeSyncBatch.clear();
this.updateEmbeddedDocuments('Token', entries, { animation: { movementSpeed: 1 } });
}, 0);
}

View file

@ -100,4 +100,18 @@ export default class DHToken extends TokenDocument {
}
super.deleteCombatants(tokens, combat ?? {});
}
/**@inheritdoc */
_onRelatedUpdate(update = {}, operation = {}) {
super._onRelatedUpdate(update, operation);
if (!this.actor?.isOwner) return;
const activeGM = game.users.activeGM; // Let the active GM take care of updates if available
if (this.actor.system.metadata.usesSize && activeGM && game.user.id === activeGM.id) {
const dimensions = { height: this.actor.system.size, width: this.actor.system.size };
if (dimensions.width !== this.width || dimensions.height !== this.height) {
this.parent?.syncTokenDimensions(this, dimensions);
}
}
}
}