Remade branch

This commit is contained in:
WBHarry 2026-03-28 00:36:40 +01:00
parent c730cc3d4d
commit 3dd78e3e53
9 changed files with 182 additions and 275 deletions

View file

@ -89,9 +89,14 @@
},
"Config": {
"beastform": {
"exact": "Beastform Max Tier",
"exactHint": "The Character's Tier is used if empty",
"label": "Beastform"
"exact": { "label": "Beastform Max Tier", "hint": "The Character's Tier is used if empty" },
"modifications": {
"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": {
"defaultOwnership": "Default Ownership",

View file

@ -10,6 +10,12 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
this.selected = null;
this.evolved = { form: null };
this.hybrid = { forms: {}, advantages: {}, features: {} };
this.modifications = {
traitBonuses: configData.modifications.traitBonuses.map(x => ({
trait: null,
bonus: x.bonus
}))
};
this._dragDrop = this._createDragDropHandlers();
}
@ -28,6 +34,7 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
selectBeastform: this.selectBeastform,
toggleHybridFeature: this.toggleHybridFeature,
toggleHybridAdvantage: this.toggleHybridAdvantage,
toggleTraitBonus: this.toggleTraitBonus,
submitBeastform: this.submitBeastform
},
form: {
@ -48,6 +55,7 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' },
beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.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' }
};
@ -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.tierKey = this.tabGroups.primary;
@ -155,6 +166,9 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
}
canSubmit() {
const modificationsFinished = this.modifications.traitBonuses.every(x => x.trait);
if (!modificationsFinished) return false;
if (this.selected) {
switch (this.selected.system.beastformType) {
case 'normal':
@ -261,6 +275,13 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
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() {
await this.close({ submitted: true });
}
@ -292,6 +313,23 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
}
}
const beastformEffect = selected.effects.find(x => x.type === 'beastform');
for (const traitBonus of app.modifications.traitBonuses) {
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({
selected: selected,
evolved: { ...app.evolved, form: evolved },

View file

@ -36,7 +36,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
editDoc: this.editDoc,
addTrigger: this.addTrigger,
removeTrigger: this.removeTrigger,
expandTrigger: this.expandTrigger
expandTrigger: this.expandTrigger,
addBeastformTraitBonus: this.addBeastformTraitBonus,
removeBeastformTraitBonus: this.removeBeastformTraitBonus
},
form: {
handler: this.updateForm,
@ -412,6 +414,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) {
event.stopPropagation();
const wrapper = event.target.closest('.summon-count-wrapper');

View file

@ -28,8 +28,21 @@ export default class BeastformField extends fields.SchemaField {
{ 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);
@ -66,15 +79,9 @@ export default class BeastformField extends fields.SchemaField {
) ?? 1;
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) {
const formData = evolvedData?.form ?? selectedForm;
const beastformEffect = formData.effects.find(x => x.type === 'beastform');

View file

@ -5,7 +5,7 @@
"_id": "6rlxhrRwFaVgq9fe",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"system": {
"description": "<p><strong>Spend 3 Hope</strong> to transform into a Beastform without marking a Stress. When you do, choose one trait to raise by +1 until you drop out of that Beastform.<br /><br /><strong>Note: Toggle one of the Evolution Traits in the effects tab to raise a trait by 1, e.g. Evolution: Agility</strong></p>",
"description": "<p><strong>Spend 3 Hope</strong> to transform into a Beastform without marking a Stress. When you do, choose one trait to raise by +1 until you drop out of that Beastform.</p>",
"resource": null,
"actions": {
"bj4m9E8ObFT0xDQ4": {
@ -31,6 +31,13 @@
"beastform": {
"tierAccess": {
"exact": null
},
"modifications": {
"traitBonuses": [
{
"bonus": 1
}
]
}
},
"name": "Beastform",
@ -46,266 +53,7 @@
"artist": ""
}
},
"effects": [
{
"name": "Evolution: Agility",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "vQOqLZAxOltAzsVv",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.agility.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Agility when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.vQOqLZAxOltAzsVv"
},
{
"name": "Evolution: Strength",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "cwEsO1NZpkQHuoTT",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.strength.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Strength when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.cwEsO1NZpkQHuoTT"
},
{
"name": "Evolution: Finesse",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "8P0nwRHNsVnHVPjq",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.finesse.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Finesse when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.8P0nwRHNsVnHVPjq"
},
{
"name": "Evolution: Instinct",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "i2GhNGo5TnGtLuA0",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.instinct.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Instinct when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.i2GhNGo5TnGtLuA0"
},
{
"name": "Evolution: Presence",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "APQF1in1LXjBZh9n",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.presence.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Presence when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.APQF1in1LXjBZh9n"
},
{
"name": "Evolution: Knowledge",
"type": "base",
"system": {
"rangeDependence": {
"enabled": false,
"type": "withinRange",
"target": "hostile",
"range": "melee"
}
},
"_id": "WwOvGJYJb4d37cOy",
"img": "icons/magic/nature/wolf-paw-glow-large-orange.webp",
"changes": [
{
"key": "system.traits.knowledge.value",
"mode": 2,
"value": "1",
"priority": null
}
],
"disabled": true,
"duration": {
"startTime": null,
"combat": null,
"seconds": null,
"rounds": null,
"turns": null,
"startRound": null,
"startTurn": null
},
"description": "<p>Toggle this for +1 to Knowledge when using Evolution. Turn it off when you leave Beastform.</p>",
"origin": null,
"tint": "#ffffff",
"transfer": true,
"statuses": [],
"sort": 0,
"flags": {},
"_stats": {
"compendiumSource": null
},
"_key": "!items.effects!6rlxhrRwFaVgq9fe.WwOvGJYJb4d37cOy"
}
],
"effects": [],
"sort": 100000,
"ownership": {
"default": 0,

View file

@ -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 {
margin-top: 8px;
display: flex;

View file

@ -133,4 +133,18 @@
height: 300px;
}
}
.deletable-row {
display: flex;
align-items: end;
gap: 8px;
input {
flex: 1;
}
a {
padding-bottom: 7px;
}
}
}

View file

@ -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>
<legend>{{localize "DAGGERHEART.ACTIONS.Config.beastform.label"}}</legend>
{{formGroup fields.tierAccess.fields.exact value=source.tierAccess.exact name="beastform.tierAccess.exact" labelAttr="label" valueAttr="key" localize=true blank=""}}
<legend>{{localize "DAGGERHEART.ACTIONS.Config.beastform.modifications.traitBonuses.label.plural"}} <a data-action="addBeastformTraitBonus"><i class="fa-solid fa-plus"></i></a></legend>
{{#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>

View 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>