[Feature] 687 - Companion Improvements (#1049)

* Companions can't be put into CombatState anymore. Companions now have a Action Roll button

* Added handling for multiselect toggleCombat
This commit is contained in:
WBHarry 2025-08-24 02:24:57 +02:00 committed by GitHub
parent a72d4583cd
commit 16173363d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 1 deletions

View file

@ -1,6 +1,9 @@
export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
static DEFAULT_OPTIONS = {
classes: ['daggerheart']
classes: ['daggerheart'],
actions: {
combat: DHTokenHUD.#onToggleCombat
}
};
/** @override */
@ -11,8 +14,14 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
}
};
static #nonCombatTypes = ['environment', 'companion'];
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.canToggleCombat = DHTokenHUD.#nonCombatTypes.includes(this.actor.type)
? false
: context.canToggleCombat;
context.systemStatusEffects = Object.keys(context.statusEffects).reduce((acc, key) => {
const effect = context.statusEffects[key];
if (effect.systemEffect) acc[key] = effect;
@ -36,6 +45,20 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
return context;
}
static async #onToggleCombat() {
const tokens = canvas.tokens.controlled
.filter(t => !t.actor || !DHTokenHUD.#nonCombatTypes.includes(t.actor.type))
.map(t => t.document);
if (!this.object.controlled) tokens.push(this.document);
try {
if (this.document.inCombat) await TokenDocument.implementation.deleteCombatants(tokens);
else await TokenDocument.implementation.createCombatants(tokens);
} catch (err) {
ui.notifications.warn(err.message);
}
}
_getStatusEffectChoices() {
// Include all HUD-enabled status effects
const choices = {};

View file

@ -8,6 +8,7 @@ export default class DhCompanionSheet extends DHBaseActorSheet {
classes: ['actor', 'companion'],
position: { width: 340 },
actions: {
actionRoll: DhCompanionSheet.#actionRoll,
levelManagement: DhCompanionSheet.#levelManagement
}
};
@ -45,6 +46,52 @@ export default class DhCompanionSheet extends DHBaseActorSheet {
/* Application Clicks Actions */
/* -------------------------------------------- */
/**
*
*/
static async #actionRoll(event) {
const partner = this.actor.system.partner;
const config = {
event,
title: `${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}: ${this.actor.name}`,
headerTitle: `Companion ${game.i18n.localize('DAGGERHEART.GENERAL.Roll.action')}`,
roll: {
trait: partner.system.spellcastModifierTrait?.key
},
hasRoll: true,
data: partner.getRollData()
};
const result = await partner.diceRoll(config);
this.consumeResource(result?.costs);
}
// Remove when Action Refactor part #2 done
async consumeResource(costs) {
if (!costs?.length) return;
const partner = this.actor.system.partner;
const usefulResources = {
...foundry.utils.deepClone(partner.system.resources),
fear: {
value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear),
max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear,
reversed: false
}
};
const resources = game.system.api.fields.ActionFields.CostField.getRealCosts(costs).map(c => {
const resource = usefulResources[c.key];
return {
key: c.key,
value: (c.total ?? c.value) * (resource.isReversed ? 1 : -1),
target: resource.target,
keyIsID: resource.keyIsID
};
});
await partner.modifyResource(resources);
}
/**
* Opens the companions level management window.
* @type {ApplicationClickAction}

View file

@ -77,4 +77,17 @@
}
}
}
.action-section {
display: flex;
padding: 0 10px;
margin-top: 20px;
width: 100%;
button {
height: 40px;
width: 100%;
font-weight: 600;
}
}
}

View file

@ -56,4 +56,7 @@
</div>
{{/each}}
</div>
<div class="action-section">
<button type="button" data-action="actionRoll">{{localize "DAGGERHEART.GENERAL.Roll.action"}}</button>
</div>
</section>