mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-22 23:43:37 +02:00
Added so that beastform actions can have trait bonuses to be selected while transforming
This commit is contained in:
parent
a4fff56461
commit
9ca1c85dad
8 changed files with 177 additions and 17 deletions
11
lang/en.json
11
lang/en.json
|
|
@ -87,9 +87,14 @@
|
||||||
},
|
},
|
||||||
"Config": {
|
"Config": {
|
||||||
"beastform": {
|
"beastform": {
|
||||||
"exact": "Beastform Max Tier",
|
"exact": { "label": "Beastform Max Tier", "hint": "The Character's Tier is used if empty" },
|
||||||
"exactHint": "The Character's Tier is used if empty",
|
"modifications": {
|
||||||
"label": "Beastform"
|
"traitBonuses": {
|
||||||
|
"label": { "single": "Trait Bonus", "plural": "Trait Bonuses" },
|
||||||
|
"hint": "Pick bonuses you apply to freely chosen traits at the time of transforming",
|
||||||
|
"bonus": "Bonus Amount"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"countdown": {
|
"countdown": {
|
||||||
"defaultOwnership": "Default Ownership",
|
"defaultOwnership": "Default Ownership",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
this.selected = null;
|
this.selected = null;
|
||||||
this.evolved = { form: null };
|
this.evolved = { form: null };
|
||||||
this.hybrid = { forms: {}, advantages: {}, features: {} };
|
this.hybrid = { forms: {}, advantages: {}, features: {} };
|
||||||
|
this.modifications = {
|
||||||
|
traitBonuses: configData.modifications.traitBonuses.map(x => ({
|
||||||
|
trait: null,
|
||||||
|
bonus: x.bonus
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
this._dragDrop = this._createDragDropHandlers();
|
this._dragDrop = this._createDragDropHandlers();
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +34,7 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
selectBeastform: this.selectBeastform,
|
selectBeastform: this.selectBeastform,
|
||||||
toggleHybridFeature: this.toggleHybridFeature,
|
toggleHybridFeature: this.toggleHybridFeature,
|
||||||
toggleHybridAdvantage: this.toggleHybridAdvantage,
|
toggleHybridAdvantage: this.toggleHybridAdvantage,
|
||||||
|
toggleTraitBonus: this.toggleTraitBonus,
|
||||||
submitBeastform: this.submitBeastform
|
submitBeastform: this.submitBeastform
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
|
|
@ -48,6 +55,7 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' },
|
tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' },
|
||||||
beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.hbs' },
|
beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.hbs' },
|
||||||
advanced: { template: 'systems/daggerheart/templates/dialogs/beastform/advanced.hbs' },
|
advanced: { template: 'systems/daggerheart/templates/dialogs/beastform/advanced.hbs' },
|
||||||
|
modifications: { template: 'systems/daggerheart/templates/dialogs/beastform/modifications.hbs' },
|
||||||
footer: { template: 'systems/daggerheart/templates/dialogs/beastform/footer.hbs' }
|
footer: { template: 'systems/daggerheart/templates/dialogs/beastform/footer.hbs' }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -146,6 +154,9 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
context.modifications = this.modifications;
|
||||||
|
context.traits = CONFIG.DH.ACTOR.abilities;
|
||||||
|
|
||||||
context.tier = beastformTiers[this.tabGroups.primary];
|
context.tier = beastformTiers[this.tabGroups.primary];
|
||||||
context.tierKey = this.tabGroups.primary;
|
context.tierKey = this.tabGroups.primary;
|
||||||
|
|
||||||
|
|
@ -156,11 +167,14 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
|
|
||||||
canSubmit() {
|
canSubmit() {
|
||||||
if (this.selected) {
|
if (this.selected) {
|
||||||
|
const modificationsFinished =
|
||||||
|
!this.modifications.traitBonuses.length || this.modifications.traitBonuses.every(x => x.trait);
|
||||||
|
|
||||||
switch (this.selected.system.beastformType) {
|
switch (this.selected.system.beastformType) {
|
||||||
case 'normal':
|
case 'normal':
|
||||||
return true;
|
return modificationsFinished;
|
||||||
case 'evolved':
|
case 'evolved':
|
||||||
return this.evolved.form;
|
return modificationsFinished && this.evolved.form;
|
||||||
case 'hybrid':
|
case 'hybrid':
|
||||||
const selectedAdvantages = Object.values(this.hybrid.advantages).reduce(
|
const selectedAdvantages = Object.values(this.hybrid.advantages).reduce(
|
||||||
(acc, form) => acc + Object.values(form).length,
|
(acc, form) => acc + Object.values(form).length,
|
||||||
|
|
@ -173,7 +187,7 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
|
|
||||||
const advantagesSelected = selectedAdvantages === this.selected.system.hybrid.advantages;
|
const advantagesSelected = selectedAdvantages === this.selected.system.hybrid.advantages;
|
||||||
const featuresSelected = selectedFeatures === this.selected.system.hybrid.features;
|
const featuresSelected = selectedFeatures === this.selected.system.hybrid.features;
|
||||||
return advantagesSelected && featuresSelected;
|
return modificationsFinished && advantagesSelected && featuresSelected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,6 +275,13 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toggleTraitBonus(_, button) {
|
||||||
|
const { index, trait } = button.dataset;
|
||||||
|
this.modifications.traitBonuses[index].trait =
|
||||||
|
this.modifications.traitBonuses[index].trait === trait ? null : trait;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
static async submitBeastform() {
|
static async submitBeastform() {
|
||||||
await this.close({ submitted: true });
|
await this.close({ submitted: true });
|
||||||
}
|
}
|
||||||
|
|
@ -292,6 +313,24 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const beastformEffect = selected.effects.find(x => x.type === 'beastform');
|
||||||
|
while (app.modifications.traitBonuses.length) {
|
||||||
|
const traitBonus = app.modifications.traitBonuses.pop();
|
||||||
|
const existingChange = beastformEffect.changes.find(
|
||||||
|
x => x.key === `system.traits.${traitBonus.trait}.value`
|
||||||
|
);
|
||||||
|
if (existingChange) {
|
||||||
|
existingChange.value = Number.parseInt(existingChange.value) + traitBonus.bonus;
|
||||||
|
} else {
|
||||||
|
beastformEffect.changes.push({
|
||||||
|
key: `system.traits.${traitBonus.trait}.value`,
|
||||||
|
mode: 2,
|
||||||
|
priority: null,
|
||||||
|
value: traitBonus.bonus
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
selected: selected,
|
selected: selected,
|
||||||
evolved: { ...app.evolved, form: evolved },
|
evolved: { ...app.evolved, form: evolved },
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
editDoc: this.editDoc,
|
editDoc: this.editDoc,
|
||||||
addTrigger: this.addTrigger,
|
addTrigger: this.addTrigger,
|
||||||
removeTrigger: this.removeTrigger,
|
removeTrigger: this.removeTrigger,
|
||||||
expandTrigger: this.expandTrigger
|
expandTrigger: this.expandTrigger,
|
||||||
|
addBeastformTraitBonus: this.addBeastformTraitBonus,
|
||||||
|
removeBeastformTraitBonus: this.removeBeastformTraitBonus
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
handler: this.updateForm,
|
handler: this.updateForm,
|
||||||
|
|
@ -360,6 +362,21 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async addBeastformTraitBonus() {
|
||||||
|
const data = this.action.toObject();
|
||||||
|
data.beastform.modifications.traitBonuses = [
|
||||||
|
...data.beastform.modifications.traitBonuses,
|
||||||
|
this.action.schema.fields.beastform.fields.modifications.fields.traitBonuses.element.getInitialValue()
|
||||||
|
];
|
||||||
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeBeastformTraitBonus(_event, button) {
|
||||||
|
const data = this.action.toObject();
|
||||||
|
data.beastform.modifications.traitBonuses.splice(button.dataset.index, 1);
|
||||||
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
}
|
||||||
|
|
||||||
updateSummonCount(event) {
|
updateSummonCount(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const wrapper = event.target.closest('.summon-count-wrapper');
|
const wrapper = event.target.closest('.summon-count-wrapper');
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,21 @@ export default class BeastformField extends fields.SchemaField {
|
||||||
{ 1: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') }
|
{ 1: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
hint: 'DAGGERHEART.ACTIONS.Config.beastform.exactHint'
|
label: 'DAGGERHEART.ACTIONS.Config.beastform.exact.label',
|
||||||
|
hint: 'DAGGERHEART.ACTIONS.Config.beastform.exact.hint'
|
||||||
})
|
})
|
||||||
|
}),
|
||||||
|
modifications: new fields.SchemaField({
|
||||||
|
traitBonuses: new fields.ArrayField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
bonus: new fields.NumberField({
|
||||||
|
integer: true,
|
||||||
|
initial: 1,
|
||||||
|
min: 1,
|
||||||
|
label: 'DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.bonus'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
super(beastformFields, options, context);
|
super(beastformFields, options, context);
|
||||||
|
|
@ -66,15 +79,9 @@ export default class BeastformField extends fields.SchemaField {
|
||||||
) ?? 1;
|
) ?? 1;
|
||||||
|
|
||||||
config.tierLimit = this.beastform.tierAccess.exact ?? actorTier;
|
config.tierLimit = this.beastform.tierAccess.exact ?? actorTier;
|
||||||
|
config.modifications = this.beastform.modifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO by Harry
|
|
||||||
* @param {*} selectedForm
|
|
||||||
* @param {*} evolvedData
|
|
||||||
* @param {*} hybridData
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
static async transform(selectedForm, evolvedData, hybridData) {
|
static async transform(selectedForm, evolvedData, hybridData) {
|
||||||
const formData = evolvedData?.form ?? selectedForm;
|
const formData = evolvedData?.form ?? selectedForm;
|
||||||
const beastformEffect = formData.effects.find(x => x.type === 'beastform');
|
const beastformEffect = formData.effects.find(x => x.type === 'beastform');
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,44 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modifications-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.trait-bonuses-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.bonus-separator {
|
||||||
|
background: light-dark(@dark-blue, @golden);
|
||||||
|
mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%);
|
||||||
|
height: 2px;
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trait-bonus-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.trait-card {
|
||||||
|
border: 1px solid light-dark(@dark-blue, @golden);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 2px;
|
||||||
|
opacity: 0.4;
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -133,4 +133,18 @@
|
||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.deletable-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: end;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding-bottom: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
|
{{formGroup fields.tierAccess.fields.exact value=source.tierAccess.exact name="beastform.tierAccess.exact" labelAttr="label" valueAttr="key" localize=true blank=""}}
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{localize "DAGGERHEART.ACTIONS.Config.beastform.label"}}</legend>
|
<legend>{{localize "DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.label.plural"}} <a data-action="addBeastformTraitBonus"><i class="fa-solid fa-plus"></i></a></legend>
|
||||||
{{formGroup fields.tierAccess.fields.exact value=source.tierAccess.exact name="beastform.tierAccess.exact" labelAttr="label" valueAttr="key" localize=true blank=""}}
|
|
||||||
|
{{#if source.modifications.traitBonuses.length}}
|
||||||
|
{{#each source.modifications.traitBonuses as |traitBonus index|}}
|
||||||
|
<div class="deletable-row">
|
||||||
|
{{formGroup ../fields.modifications.fields.traitBonuses.element.fields.bonus value=traitBonus.bonus name=(concat "beastform.modifications.traitBonuses." index ".bonus") localize=true}}
|
||||||
|
<a data-action="removeBeastformTraitBonus" data-index="{{index}}"><i class="fa-solid fa-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<span class="hint">{{localize "DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.hint"}}</span>
|
||||||
|
{{/if}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
28
templates/dialogs/beastform/modifications.hbs
Normal file
28
templates/dialogs/beastform/modifications.hbs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<div class="modifications-container">
|
||||||
|
{{#if modifications.traitBonuses.length}}
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
{{#if (gt modifications.traitBonuses.length 1)}}
|
||||||
|
{{localize "DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.label.plural"}}
|
||||||
|
{{else}}
|
||||||
|
{{localize "DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.label.single"}}
|
||||||
|
{{/if}}
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
<div class="trait-bonuses-container">
|
||||||
|
{{#each modifications.traitBonuses as |traitBonus index|}}
|
||||||
|
<div class="trait-bonus-container">
|
||||||
|
{{#each @root.traits as |trait|}}
|
||||||
|
<a class="trait-card {{#if (eq trait.id traitBonus.trait)}}selected{{/if}}"
|
||||||
|
data-action="toggleTraitBonus" data-index="{{index}}" data-trait="{{trait.id}}"
|
||||||
|
>
|
||||||
|
{{localize trait.label}} +{{traitBonus.bonus}}
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{#unless @last}}<div class="bonus-separator"></div>{{/unless}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue