diff --git a/lang/en.json b/lang/en.json index cd8d10ae..1d4544b9 100755 --- a/lang/en.json +++ b/lang/en.json @@ -611,6 +611,9 @@ "insufficientHope": "The initiating character doesn't have enough hope", "createTagTeam": "Create TagTeam Roll", "chatMessageRollTitle": "Roll" + }, + "TokenConfig": { + "actorSizeUsed": "Actor size is set, determining the dimensions" } }, "CLASS": { diff --git a/module/applications/sheets-configs/prototype-token-config.mjs b/module/applications/sheets-configs/prototype-token-config.mjs index 24c9dabb..0bb9703a 100644 --- a/module/applications/sheets-configs/prototype-token-config.mjs +++ b/module/applications/sheets-configs/prototype-token-config.mjs @@ -1,4 +1,18 @@ export default class DhPrototypeTokenConfig extends foundry.applications.sheets.PrototypeTokenConfig { + /** @override */ + static PARTS = { + tabs: super.PARTS.tabs, + identity: super.PARTS.identity, + appearance: { + template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs', + scrollable: [''] + }, + vision: super.PARTS.vision, + light: super.PARTS.light, + resources: super.PARTS.resources, + footer: super.PARTS.footer + }; + /** @inheritDoc */ async _prepareResourcesTab() { const token = this.token; @@ -17,4 +31,11 @@ export default class DhPrototypeTokenConfig extends foundry.applications.sheets. turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations }; } + + async _prepareAppearanceTab() { + const context = await super._prepareAppearanceTab(); + context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false; + + return context; + } } diff --git a/module/applications/sheets-configs/token-config.mjs b/module/applications/sheets-configs/token-config.mjs index ee573e5d..5f4e4f56 100644 --- a/module/applications/sheets-configs/token-config.mjs +++ b/module/applications/sheets-configs/token-config.mjs @@ -1,4 +1,18 @@ export default class DhTokenConfig extends foundry.applications.sheets.TokenConfig { + /** @override */ + static PARTS = { + tabs: super.PARTS.tabs, + identity: super.PARTS.identity, + appearance: { + template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs', + scrollable: [''] + }, + vision: super.PARTS.vision, + light: super.PARTS.light, + resources: super.PARTS.resources, + footer: super.PARTS.footer + }; + /** @inheritDoc */ async _prepareResourcesTab() { const token = this.token; @@ -17,4 +31,11 @@ export default class DhTokenConfig extends foundry.applications.sheets.TokenConf turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations }; } + + async _prepareAppearanceTab() { + const context = await super._prepareAppearanceTab(); + context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false; + + return context; + } } diff --git a/module/config/actorConfig.mjs b/module/config/actorConfig.mjs index 6496a459..fdef7d03 100644 --- a/module/config/actorConfig.mjs +++ b/module/config/actorConfig.mjs @@ -212,6 +212,11 @@ export const adversaryTraits = { }; export const tokenSize = { + custom: { + id: 'custom', + value: 0, + label: 'DAGGERHEART.GENERAL.custom' + }, tiny: { id: 'tiny', value: 1, diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index e1b40785..37f9c5c8 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -80,9 +80,9 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { if (this.metadata.usesSize) schema.size = new fields.StringField({ required: true, - nullable: true, + nullable: false, choices: CONFIG.DH.ACTOR.tokenSize, - initial: null + initial: CONFIG.DH.ACTOR.tokenSize.custom.id }); return schema; } diff --git a/module/documents/scene.mjs b/module/documents/scene.mjs index 50f520a9..c6cdd2c2 100644 --- a/module/documents/scene.mjs +++ b/module/documents/scene.mjs @@ -7,8 +7,10 @@ export default class DhScene extends Scene { /** Synchronize a token's dimensions with its actor's size category. */ syncTokenDimensions(tokenDoc, tokenSize) { if (!tokenDoc.parent?.tokens.has(tokenDoc.id)) return; + const prototype = tokenDoc.actor?.prototypeToken ?? tokenDoc; this.#sizeSyncBatch.set(tokenDoc.id, { size: tokenSize, + prototypeSize: { width: prototype.width, height: prototype.height }, position: { x: tokenDoc.x, y: tokenDoc.y, elevation: tokenDoc.elevation } }); this.#processSyncBatch(); @@ -20,18 +22,15 @@ export default class DhScene extends Scene { const entries = this.#sizeSyncBatch .entries() .toArray() - .map(([_id, { size, position }]) => { + .map(([_id, { size, prototypeSize, position }]) => { const tokenSize = tokenSizes[size]; - const updatedPosition = DHToken.getSnappedPositionInSquareGrid( - this.grid, - position, - tokenSize, - tokenSize - ); + const width = size !== CONFIG.DH.ACTOR.tokenSize.custom.id ? tokenSize : prototypeSize.width; + const height = size !== CONFIG.DH.ACTOR.tokenSize.custom.id ? tokenSize : prototypeSize.height; + const updatedPosition = DHToken.getSnappedPositionInSquareGrid(this.grid, position, width, height); return { _id, - width: tokenSize, - height: tokenSize, + width, + height, ...updatedPosition }; }); diff --git a/module/documents/token.mjs b/module/documents/token.mjs index b85e46a7..35a86671 100644 --- a/module/documents/token.mjs +++ b/module/documents/token.mjs @@ -111,7 +111,7 @@ export default class DHToken extends CONFIG.Token.documentClass { const actor = document.actor; if (actor?.system.metadata.usesSize) { const tokenSize = tokenSizes[actor.system.size]; - if (tokenSize) { + if (tokenSize && tokenSize !== CONFIG.DH.ACTOR.tokenSize.custom.id) { document.updateSource({ width: tokenSize, height: tokenSize @@ -126,12 +126,21 @@ export default class DHToken extends CONFIG.Token.documentClass { super._onRelatedUpdate(update, operation); if (!this.actor?.isOwner) return; + + const updates = Array.isArray(update) ? update : [update]; const activeGM = game.users.activeGM; // Let the active GM take care of updates if available - if (this.actor.system.metadata.usesSize && update.system?.size && activeGM && game.user.id === activeGM.id) { - const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; - const tokenSize = tokenSizes[update.system.size]; - if (tokenSize !== this.width || tokenSize !== this.height) { - this.parent?.syncTokenDimensions(this, update.system.size); + for (let update of updates) { + if ( + this.actor.system.metadata.usesSize && + update.system?.size && + activeGM && + game.user.id === activeGM.id + ) { + const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; + const tokenSize = tokenSizes[update.system.size]; + if (tokenSize !== this.width || tokenSize !== this.height) { + this.parent?.syncTokenDimensions(this, update.system.size); + } } } } @@ -156,8 +165,10 @@ export default class DHToken extends CONFIG.Token.documentClass { if (this.actor?.system.metadata.usesSize) { const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; const tokenSize = tokenSizes[this.actor.system.size]; - width = tokenSize ?? width; - height = tokenSize ?? height; + if (tokenSize && tokenSize !== CONFIG.DH.ACTOR.tokenSize.custom.id) { + width = tokenSize ?? width; + height = tokenSize ?? height; + } } // Round width and height to nearest multiple of 0.5 if not small diff --git a/templates/sheets-settings/token-config/appearance.hbs b/templates/sheets-settings/token-config/appearance.hbs new file mode 100644 index 00000000..0f6019ba --- /dev/null +++ b/templates/sheets-settings/token-config/appearance.hbs @@ -0,0 +1,82 @@ +
+ {{formGroup fields.texture.fields.src value=source.texture.src rootId=rootId}} + {{#if randomImgEnabled}} + {{formGroup fields.randomImg value=source.randomImg classes="slim" rootId=rootId}} + {{else if hasAlternates}} +
+ + +
+ {{/if}} + + +
+ +
+ + {{formInput fields.width value=source.width id=(concat rootId "-width") disabled=actorSizeUsed}} + + {{formInput fields.height value=source.height id=(concat rootId "-height") disabled=actorSizeUsed}} +
+
+ + {{#if shapes}} + {{formGroup fields.shape value=source.shape choices=shapes classes="slim" rootId=rootId}} + {{/if}} + {{formGroup fields.texture.fields.fit value=source.texture.fit choices=textureFitModes classes="slim" rootId=rootId}} + +
+ +
+ + {{formInput fields.texture.fields.anchorX value=source.texture.anchorX id=(concat rootId "-anchorX") + placeholder="0.5"}} + + {{formInput fields.texture.fields.anchorY value=source.texture.anchorY id=(concat rootId "-anchorY") + placeholder="0.5"}} +
+

{{localize "TOKEN.AnchorHint"}}

+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ + {{formGroup fields.texture.fields.tint value=source.texture.tint placeholder="#ffffff" rootId=rootId}} + {{formGroup fields.alpha value=source.alpha step=0.05 rootId=rootId}} + {{formGroup fields.lockRotation value=source.lockRotation rootId=rootId}} + +
+ {{localize "TOKEN.RING.SHEET.legend"}} + {{formGroup fields.ring.fields.enabled value=source.ring.enabled rootId=rootId}} + {{formGroup fields.ring.fields.colors.fields.ring value=source.ring.colors.ring rootId=rootId}} + {{formGroup fields.ring.fields.colors.fields.background value=source.ring.colors.background rootId=rootId}} + {{formGroup fields.ring.fields.subject.fields.texture value=source.ring.subject.texture rootId=rootId}} + {{formGroup fields.ring.fields.subject.fields.scale value=source.ring.subject.scale max=3 step=0.02 rootId=rootId}} + {{formGroup fields.ring.fields.effects value=source.ring.effects input=ringEffectsInput stacked=true rootId=rootId}} +
+
diff --git a/templates/sheets/actors/adversary/header.hbs b/templates/sheets/actors/adversary/header.hbs index 7de8e45b..512a3980 100644 --- a/templates/sheets/actors/adversary/header.hbs +++ b/templates/sheets/actors/adversary/header.hbs @@ -23,11 +23,11 @@ {{/if}}
- {{#if source.system.size}} + {{#unless (eq source.system.size 'custom')}} {{localize (concat "DAGGERHEART.CONFIG.TokenSize." source.system.size)}} {{else}} {{source.prototypeToken.width}}x{{source.prototypeToken.height}} - {{/if}} + {{/unless}}