diff --git a/lang/en.json b/lang/en.json index 49f696ca..9c1bf3e6 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1666,8 +1666,8 @@ "Config": { "Beastform": { "label": "Beastform", - "exact": "Exact", - "exactPlaceholder": "Character tier is used" + "exact": "Beastform Max Tier", + "exactHint": "The Character's Tier is used if empty" } } }, diff --git a/module/applications/config/Action.mjs b/module/applications/config/Action.mjs index 6b5f7b41..803f22fe 100644 --- a/module/applications/config/Action.mjs +++ b/module/applications/config/Action.mjs @@ -38,7 +38,7 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { } }; - static CLEAN_ARRAYS = ["damage.parts", "cost", "effects"]; + static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects']; _getTabs() { const tabs = { @@ -69,7 +69,13 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { context.disableOption = this.disableOption.bind(this); context.isNPC = this.action.actor && this.action.actor.type !== 'character'; context.hasRoll = this.action.hasRoll; - console.log(context) + + const settingsTiers = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers).tiers; + context.tierOptions = [ + { key: 1, label: game.i18n.localize('DAGGERHEART.Tiers.tier1') }, + ...Object.values(settingsTiers).map(x => ({ key: x.tier, label: x.name })) + ]; + return context; } @@ -97,9 +103,9 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { _prepareSubmitData(event, formData) { const submitData = foundry.utils.expandObject(formData.object); - for ( const keyPath of this.constructor.CLEAN_ARRAYS ) { + for (const keyPath of this.constructor.CLEAN_ARRAYS) { const data = foundry.utils.getProperty(submitData, keyPath); - if ( data ) foundry.utils.setProperty(submitData, keyPath, Object.values(data)); + if (data) foundry.utils.setProperty(submitData, keyPath, Object.values(data)); } return submitData; } diff --git a/module/applications/sheets/applications/adversary-settings.mjs b/module/applications/sheets/applications/adversary-settings.mjs index 70fae0cb..2ecdcb60 100644 --- a/module/applications/sheets/applications/adversary-settings.mjs +++ b/module/applications/sheets/applications/adversary-settings.mjs @@ -103,7 +103,6 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl context.systemFields = this.actor.system.schema.fields; context.systemFields.attack.fields = this.actor.system.attack.schema.fields; context.isNPC = true; - console.log(context); return context; } diff --git a/module/applications/sheets/items/beastform.mjs b/module/applications/sheets/items/beastform.mjs index ab01b9d5..b04671ec 100644 --- a/module/applications/sheets/items/beastform.mjs +++ b/module/applications/sheets/items/beastform.mjs @@ -44,7 +44,7 @@ export default class BeastformSheet extends DHBaseItemSheet { static editFeature(event) { const target = event.target.closest('[data-action="editFeature"]'); const feature = this.document.system.features[target.dataset.index]; - feature.sheet.render(true); + feature.sheet.render({ force: true }); } static async removeFeature(_, target) { @@ -52,7 +52,6 @@ export default class BeastformSheet extends DHBaseItemSheet { await this.document.update({ 'system.features': current.filter((_, index) => index !== Number(target.dataset.index)) }); - this.render(); } async _onDrop(event) { diff --git a/module/data/action/action.mjs b/module/data/action/action.mjs index bf06a10c..3643125f 100644 --- a/module/data/action/action.mjs +++ b/module/data/action/action.mjs @@ -275,18 +275,6 @@ export class DHBaseAction extends foundry.abstract.DataModel { }) */ } - if (this instanceof DhBeastformAction) { - config.beastform = this.prepareBeastformConfig(); - - const abort = await this.handleActiveTransformations(); - if (abort) return; - - const beastformUuid = await BeastformDialog.configure(config); - if (!beastformUuid) return; - - await this.transform(beastformUuid); - } - if (this.doFollowUp()) { if (this.rollDamage) await this.rollDamage(event, config); if (this.rollHealing) await this.rollHealing(event, config); @@ -779,11 +767,23 @@ export class DHMacroAction extends DHBaseAction { export class DhBeastformAction extends DHBaseAction { static extraSchemas = ['beastform']; + async use(event, ...args) { + const beastformConfig = this.prepareBeastformConfig(); + + const abort = await this.handleActiveTransformations(); + if (abort) return; + + const beastformUuid = await BeastformDialog.configure(beastformConfig); + if (!beastformUuid) return; + + await this.transform(beastformUuid); + } + prepareBeastformConfig(config) { - const settingsTier = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers).tiers; + const settingsTiers = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers).tiers; const actorLevel = this.actor.system.levelData.level.current; const actorTier = - Object.values(settingsTier).find( + Object.values(settingsTiers).find( tier => actorLevel >= tier.levels.start && actorLevel <= tier.levels.end ) ?? 1; diff --git a/module/data/activeEffect/beastformEffect.mjs b/module/data/activeEffect/beastformEffect.mjs index 5cb19b7d..3aa25bef 100644 --- a/module/data/activeEffect/beastformEffect.mjs +++ b/module/data/activeEffect/beastformEffect.mjs @@ -4,7 +4,6 @@ export default class BeastformEffect extends foundry.abstract.TypeDataModel { static defineSchema() { const fields = foundry.data.fields; return { - isBeastform: new fields.BooleanField({ initial: false }), characterTokenData: new fields.SchemaField({ tokenImg: new fields.FilePathField({ categories: ['IMAGE'], @@ -34,13 +33,8 @@ export default class BeastformEffect extends foundry.abstract.TypeDataModel { await updateActorTokens(this.parent.parent, update); - for (var feature of this.parent.parent.items.filter(x => this.featureIds.includes(x.id))) { - await feature.delete(); - } - - for (var effect of this.parent.parent.effects.filter(x => this.effectIds.includes(x.id))) { - await effect.delete(); - } + await this.parent.parent.deleteEmbeddedDocuments('Item', this.featureIds); + await this.parent.parent.deleteEmbeddedDocuments('ActiveEffect', this.effectIds); } } } diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index 899d4355..e90af930 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -43,14 +43,16 @@ export default class DHBeastform extends BaseDataItem { const allowed = await super._preCreate(data, options, user); if (allowed === false) return; - if (this.actor?.type !== 'character') { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.beastformInapplicable')); - return; + if (!this.actor) return; + + if (this.actor.type !== 'character') { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.notifications.beastformInapplicable')); + return false; } if (this.actor.items.find(x => x.type === 'beastform')) { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.beastformAlreadyApplied')); - return; + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.notifications.beastformAlreadyApplied')); + return false; } const features = await this.parent.parent.createEmbeddedDocuments( diff --git a/module/dialogs/beastformDialog.mjs b/module/dialogs/beastformDialog.mjs index d9c5d4b4..34b71c24 100644 --- a/module/dialogs/beastformDialog.mjs +++ b/module/dialogs/beastformDialog.mjs @@ -12,7 +12,6 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat static DEFAULT_OPTIONS = { tag: 'form', - id: 'beastform-selection', classes: ['daggerheart', 'views', 'dh-style', 'beastform-selection'], position: { width: 600, @@ -42,11 +41,10 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat async _prepareContext(_options) { const context = await super._prepareContext(_options); - context.configData = this.configData; context.beastformTiers = game.items.reduce((acc, x) => { const tier = tiers[x.system.tier]; - if (x.type !== 'beastform' || tier.value > context.configData.beastform.tierLimit) return acc; + if (x.type !== 'beastform' || tier.value > this.configData.tierLimit) return acc; if (!acc[tier.value]) acc[tier.value] = { label: game.i18n.localize(tier.label), values: {} }; acc[tier.value].values[x.uuid] = { selected: this.selected == x.uuid, value: x }; diff --git a/module/dialogs/d20RollDialog.mjs b/module/dialogs/d20RollDialog.mjs index 08792c40..9ea35fce 100644 --- a/module/dialogs/d20RollDialog.mjs +++ b/module/dialogs/d20RollDialog.mjs @@ -51,7 +51,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio }; async _prepareContext(_options) { - console.log(this.config, this.roll); const context = await super._prepareContext(_options); context.hasRoll = !!this.config.roll; context.roll = this.roll; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 88bb7f3c..3dd4abc2 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -299,12 +299,10 @@ export const updateActorTokens = async (actor, update) => { await actor.prototypeToken.update(update); /* Update the tokens in all scenes belonging to Actor */ - for (let scene of game.scenes) { - for (let token of scene.tokens) { - const tokenActor = token.baseActor ?? token.actor; - if (tokenActor?.id === actor.id) { - await token.update(update); - } + for (let token of actor.getDependentTokens()) { + const tokenActor = token.baseActor ?? token.actor; + if (tokenActor?.id === actor.id) { + await token.update(update); } } }; diff --git a/styles/application.less b/styles/application.less index 66735594..24b6a7d4 100644 --- a/styles/application.less +++ b/styles/application.less @@ -227,7 +227,7 @@ div.daggerheart.views.multiclass { filter: invert(0%) sepia(100%) saturate(0%) hue-rotate(21deg) brightness(17%) contrast(103%); } } - + #roll-selection-costSelection footer { display: none; } @@ -372,7 +372,6 @@ div.daggerheart.views.multiclass { } } - .roll-dialog-experience-container { display: flex; align-items: flex-start; @@ -509,6 +508,34 @@ div.daggerheart.views.multiclass { } } + .hint-group { + display: flex; + flex-direction: column; + align-items: end; + + .form-fields { + width: 100%; + display: flex; + align-items: center; + + label { + flex: 1; + } + + input, + select { + flex: 3; + } + } + + .hint { + margin: 4px 0 0 0; + font-size: 12px; + font-style: italic; + opacity: 0.6; + } + } + .data-form-array { border: 1px solid var(--color-fieldset-border); padding: 0.5rem; diff --git a/styles/daggerheart.css b/styles/daggerheart.css index 6319f3ea..02a4d248 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -2329,6 +2329,29 @@ div.daggerheart.views.multiclass { width: 1.5rem; height: 1.5rem; } +.daggerheart.views.action .action-category .action-category-data .hint-group { + display: flex; + flex-direction: column; + align-items: end; +} +.daggerheart.views.action .action-category .action-category-data .hint-group .form-fields { + width: 100%; + display: flex; + align-items: center; +} +.daggerheart.views.action .action-category .action-category-data .hint-group .form-fields label { + flex: 1; +} +.daggerheart.views.action .action-category .action-category-data .hint-group .form-fields input, +.daggerheart.views.action .action-category .action-category-data .hint-group .form-fields select { + flex: 3; +} +.daggerheart.views.action .action-category .action-category-data .hint-group .hint { + margin: 4px 0 0 0; + font-size: 12px; + font-style: italic; + opacity: 0.6; +} .daggerheart.views.action .action-category .action-category-data .data-form-array { border: 1px solid var(--color-fieldset-border); padding: 0.5rem; diff --git a/templates/views/actionTypes/beastform.hbs b/templates/views/actionTypes/beastform.hbs index fa692927..3ff4b0f1 100644 --- a/templates/views/actionTypes/beastform.hbs +++ b/templates/views/actionTypes/beastform.hbs @@ -4,9 +4,14 @@
{{localize "DAGGERHEART.Actions.Config.Beastform.exactHint"}}
+