mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Feature/666 experience hope cost (#728)
* h * Character & Companion Experience Hope Cost
This commit is contained in:
parent
f9cb0954f9
commit
45b3569cba
7 changed files with 61 additions and 13 deletions
|
|
@ -45,6 +45,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
return this.config.title;
|
return this.config.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get actor() {
|
||||||
|
return this.config?.data?.parent;
|
||||||
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
header: {
|
header: {
|
||||||
|
|
@ -69,9 +73,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
icon
|
icon
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this.config.costs ??= [];
|
||||||
if (this.config.costs?.length) {
|
if (this.config.costs?.length) {
|
||||||
const updatedCosts = game.system.api.fields.ActionFields.CostField.calcCosts.call(
|
const updatedCosts = game.system.api.fields.ActionFields.CostField.calcCosts.call(
|
||||||
this.action,
|
this.action ?? { actor: this.actor },
|
||||||
this.config.costs
|
this.config.costs
|
||||||
);
|
);
|
||||||
context.costs = updatedCosts.map(x => ({
|
context.costs = updatedCosts.map(x => ({
|
||||||
|
|
@ -80,7 +85,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
? this.action.parent.parent.name
|
? this.action.parent.parent.name
|
||||||
: game.i18n.localize(CONFIG.DH.GENERAL.abilityCosts[x.key].label)
|
: game.i18n.localize(CONFIG.DH.GENERAL.abilityCosts[x.key].label)
|
||||||
}));
|
}));
|
||||||
context.canRoll = game.system.api.fields.ActionFields.CostField.hasCost.call(this.action, updatedCosts);
|
context.canRoll = game.system.api.fields.ActionFields.CostField.hasCost.call(
|
||||||
|
this.action ?? { actor: this.actor },
|
||||||
|
updatedCosts
|
||||||
|
);
|
||||||
this.config.data.scale = this.config.costs[0].total;
|
this.config.data.scale = this.config.costs[0].total;
|
||||||
}
|
}
|
||||||
if (this.config.uses?.max) {
|
if (this.config.uses?.max) {
|
||||||
|
|
@ -143,6 +151,12 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.config.experiences.indexOf(button.dataset.key) > -1
|
this.config.experiences.indexOf(button.dataset.key) > -1
|
||||||
? this.config.experiences.filter(x => x !== button.dataset.key)
|
? this.config.experiences.filter(x => x !== button.dataset.key)
|
||||||
: [...this.config.experiences, button.dataset.key];
|
: [...this.config.experiences, button.dataset.key];
|
||||||
|
if(this.config?.data?.parent?.type === 'character' || this.config?.data?.parent?.type === 'companion') {
|
||||||
|
this.config.costs =
|
||||||
|
this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1
|
||||||
|
? this.config.costs.filter(x => x.extKey !== button.dataset.key)
|
||||||
|
: [...this.config.costs, { extKey: button.dataset.key, key: 'hope', value: 1, name: this.config.data?.experiences?.[button.dataset.key]?.name }];
|
||||||
|
}
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -631,13 +631,34 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
},
|
},
|
||||||
hasRoll: true
|
hasRoll: true
|
||||||
};
|
};
|
||||||
this.document.diceRoll({
|
const result = await this.document.diceRoll({
|
||||||
...config,
|
...config,
|
||||||
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`,
|
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`,
|
||||||
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
ability: abilityLabel
|
ability: abilityLabel
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.consumeResource(result?.costs);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
async consumeResource(costs) {
|
||||||
|
if(!costs?.length) return;
|
||||||
|
const usefulResources = foundry.utils.deepClone(this.actor.system.resources);
|
||||||
|
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 this.actor.modifyResource(resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: redo toggleEquipItem method
|
//TODO: redo toggleEquipItem method
|
||||||
|
|
|
||||||
|
|
@ -221,12 +221,11 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resources = config.costs
|
const resources = game.system.api.fields.ActionFields.CostField.getRealCosts(config.costs)
|
||||||
.filter(
|
.filter(
|
||||||
c =>
|
c =>
|
||||||
c.enabled !== false &&
|
(!successCost && (!c.consumeOnSuccess || config.roll?.success)) ||
|
||||||
((!successCost && (!c.consumeOnSuccess || config.roll?.success)) ||
|
(successCost && c.consumeOnSuccess)
|
||||||
(successCost && c.consumeOnSuccess))
|
|
||||||
)
|
)
|
||||||
.map(c => {
|
.map(c => {
|
||||||
const resource = usefulResources[c.key];
|
const resource = usefulResources[c.key];
|
||||||
|
|
@ -238,7 +237,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.actor.modifyResource(resources);
|
await (this.actor.system.partner ?? this.actor).modifyResource(resources);
|
||||||
if (
|
if (
|
||||||
config.uses?.enabled &&
|
config.uses?.enabled &&
|
||||||
((!successCost && (!config.uses?.consumeOnSuccess || config.roll?.success)) ||
|
((!successCost && (!config.uses?.consumeOnSuccess || config.roll?.success)) ||
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ export default class CostField extends fields.ArrayField {
|
||||||
static hasCost(costs) {
|
static hasCost(costs) {
|
||||||
const realCosts = CostField.getRealCosts.call(this, costs),
|
const realCosts = CostField.getRealCosts.call(this, costs),
|
||||||
hasFearCost = realCosts.findIndex(c => c.key === 'fear');
|
hasFearCost = realCosts.findIndex(c => c.key === 'fear');
|
||||||
|
|
||||||
if (hasFearCost > -1) {
|
if (hasFearCost > -1) {
|
||||||
const fearCost = realCosts.splice(hasFearCost, 1)[0];
|
const fearCost = realCosts.splice(hasFearCost, 1)[0];
|
||||||
if (
|
if (
|
||||||
|
|
@ -70,7 +71,8 @@ export default class CostField extends fields.ArrayField {
|
||||||
}
|
}
|
||||||
|
|
||||||
static getResources(costs) {
|
static getResources(costs) {
|
||||||
const actorResources = this.actor.system.resources;
|
const actorResources = foundry.utils.deepClone(this.actor.system.resources);
|
||||||
|
if(this.actor.system.partner) actorResources.hope = foundry.utils.deepClone(this.actor.system.partner.system.resources.hope);
|
||||||
const itemResources = {};
|
const itemResources = {};
|
||||||
for (let itemResource of costs) {
|
for (let itemResource of costs) {
|
||||||
if (itemResource.keyIsID) {
|
if (itemResource.keyIsID) {
|
||||||
|
|
@ -89,7 +91,13 @@ export default class CostField extends fields.ArrayField {
|
||||||
|
|
||||||
static getRealCosts(costs) {
|
static getRealCosts(costs) {
|
||||||
const realCosts = costs?.length ? costs.filter(c => c.enabled) : [];
|
const realCosts = costs?.length ? costs.filter(c => c.enabled) : [];
|
||||||
return realCosts;
|
let mergedCosts = [];
|
||||||
|
realCosts.forEach(c => {
|
||||||
|
const getCost = Object.values(mergedCosts).find(gc => gc.key === c.key);
|
||||||
|
if(getCost) getCost.total += c.total;
|
||||||
|
else mergedCosts.push(c);
|
||||||
|
});
|
||||||
|
return mergedCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static formatMax(max) {
|
static formatMax(max) {
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,9 @@ export const registerRollDiceHooks = () => {
|
||||||
if (updates.length) {
|
if (updates.length) {
|
||||||
const target = actor.system.partner ?? actor;
|
const target = actor.system.partner ?? actor;
|
||||||
if (!['dead', 'unconcious'].some(x => actor.statuses.has(x))) {
|
if (!['dead', 'unconcious'].some(x => actor.statuses.has(x))) {
|
||||||
|
setTimeout(() => {
|
||||||
target.modifyResource(updates);
|
target.modifyResource(updates);
|
||||||
|
}, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@
|
||||||
<div class="form-group{{#unless (and scalable maxStep)}} span-2{{/unless}}">
|
<div class="form-group{{#unless (and scalable maxStep)}} span-2{{/unless}}">
|
||||||
<div class="form-fields nest-inputs">
|
<div class="form-fields nest-inputs">
|
||||||
<input id="action-costs-{{index}}" name="costs.{{index}}.enabled" type="checkbox"{{#if enabled}} checked{{/if}}>
|
<input id="action-costs-{{index}}" name="costs.{{index}}.enabled" type="checkbox"{{#if enabled}} checked{{/if}}>
|
||||||
<label for="action-costs-{{index}}">{{label}}{{#if cost.consumeOnSuccess}}<span class="hint">{{localize "DAGGERHEART.ACTIONS.Settings.consumeOnSuccess.short"}}</span>{{/if}}</label>
|
<label for="action-costs-{{index}}">
|
||||||
|
{{label}}
|
||||||
|
{{#if cost.consumeOnSuccess}}<span class="hint">{{localize "DAGGERHEART.ACTIONS.Settings.consumeOnSuccess.short"}}</span>{{/if}}
|
||||||
|
{{#if cost.extKey}}<span class="hint">{{name}}</span>{{/if}}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{#if (and scalable maxStep)}}
|
{{#if (and scalable maxStep)}}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Parameters:
|
||||||
<legend>
|
<legend>
|
||||||
{{localize title}}
|
{{localize title}}
|
||||||
{{#if canCreate}}
|
{{#if canCreate}}
|
||||||
<a data-action="{{ifThen (or (eq type 'effect') (eq type 'feature')) 'createDoc' 'addNewItem' }}" data-document-class="{{ifThen (eq type 'effect') 'ActiveEffect' 'Item' }}"
|
<a data-action="{{ifThen (or (eq type 'effect') (eq type 'feature') (eq type 'action')) 'createDoc' 'addNewItem' }}" data-document-class="{{ifThen (eq type 'effect') 'ActiveEffect' 'Item' }}"
|
||||||
data-type="{{ifThen (eq type 'effect') 'base' type}}"
|
data-type="{{ifThen (eq type 'effect') 'base' type}}"
|
||||||
{{#if inVault}}data-in-vault="{{inVault}}"{{/if}}
|
{{#if inVault}}data-in-vault="{{inVault}}"{{/if}}
|
||||||
{{#if disabled}} data-disabled="{{disabled}}"{{/if}}
|
{{#if disabled}} data-disabled="{{disabled}}"{{/if}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue