mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
[Feature] Roll Difficulty Support (#393)
* Added difficulty support in rollDialog/rollMessage and [[/dr]] * Fixed /dr chat command
This commit is contained in:
parent
42a705a870
commit
3d723e7d8c
7 changed files with 89 additions and 54 deletions
|
|
@ -8,7 +8,7 @@ import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs'
|
||||||
import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs';
|
import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs';
|
||||||
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
|
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
|
||||||
import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs';
|
import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs';
|
||||||
import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs';
|
import { enrichedDualityRoll, renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs';
|
||||||
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
|
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
|
||||||
import { registerCountdownHooks } from './module/data/countdowns.mjs';
|
import { registerCountdownHooks } from './module/data/countdowns.mjs';
|
||||||
import {
|
import {
|
||||||
|
|
@ -188,49 +188,21 @@ Hooks.on('chatMessage', (_, message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const traitValue = rollCommand.trait?.toLowerCase();
|
const traitValue = rollCommand.trait?.toLowerCase();
|
||||||
const advantageState = rollCommand.advantage ? true : rollCommand.disadvantage ? false : null;
|
const advantage = rollCommand.advantage
|
||||||
|
? CONFIG.DH.ACTIONS.advandtageState.advantage.value
|
||||||
|
: rollCommand.disadvantage
|
||||||
|
? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
|
||||||
|
: undefined;
|
||||||
|
const difficulty = rollCommand.difficulty;
|
||||||
|
|
||||||
// Target not required if an attribute is not used.
|
const target = getCommandTarget();
|
||||||
const target = traitValue ? getCommandTarget() : undefined;
|
const title = traitValue
|
||||||
if (target || !traitValue) {
|
? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
new Promise(async (resolve, reject) => {
|
ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label)
|
||||||
const trait = target ? target.system.traits[traitValue] : undefined;
|
})
|
||||||
if (traitValue && !trait) {
|
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.attributeFaulty'));
|
|
||||||
reject();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = traitValue
|
|
||||||
? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
|
||||||
ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label)
|
|
||||||
})
|
|
||||||
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
title: title,
|
|
||||||
roll: {
|
|
||||||
trait: traitValue
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
traits: {
|
|
||||||
[traitValue]: trait
|
|
||||||
}
|
|
||||||
},
|
|
||||||
source: target,
|
|
||||||
hasSave: false,
|
|
||||||
dialog: { configure: false },
|
|
||||||
evaluate: true,
|
|
||||||
advantage: rollCommand.advantage == true,
|
|
||||||
disadvantage: rollCommand.disadvantage == true
|
|
||||||
};
|
|
||||||
|
|
||||||
await CONFIG.Dice.daggerheart['DualityRoll'].build(config);
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
enrichedDualityRoll({ traitValue, target, difficulty, title, label: 'test', actionType: null, advantage });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1196,6 +1196,7 @@
|
||||||
},
|
},
|
||||||
"Roll": {
|
"Roll": {
|
||||||
"attack": "Attack Roll",
|
"attack": "Attack Roll",
|
||||||
|
"difficulty": "Roll (Difficulty {difficulty})",
|
||||||
"primaryWeaponAttack": "Primary Weapon Attack Roll",
|
"primaryWeaponAttack": "Primary Weapon Attack Roll",
|
||||||
"secondaryWeaponAttack": "Secondary Weapon Attack Roll",
|
"secondaryWeaponAttack": "Secondary Weapon Attack Roll",
|
||||||
"spellcast": "Spellcast Roll",
|
"spellcast": "Spellcast Roll",
|
||||||
|
|
@ -1310,6 +1311,7 @@
|
||||||
"single": "Experience",
|
"single": "Experience",
|
||||||
"plural": "Experiences"
|
"plural": "Experiences"
|
||||||
},
|
},
|
||||||
|
"failure": "Failure",
|
||||||
"fear": "Fear",
|
"fear": "Fear",
|
||||||
"features": "Features",
|
"features": "Features",
|
||||||
"formula": "Formula",
|
"formula": "Formula",
|
||||||
|
|
@ -1345,6 +1347,7 @@
|
||||||
"scalable": "Scalable",
|
"scalable": "Scalable",
|
||||||
"situationalBonus": "Situational Bonus",
|
"situationalBonus": "Situational Bonus",
|
||||||
"stress": "Stress",
|
"stress": "Stress",
|
||||||
|
"success": "Success",
|
||||||
"take": "Take",
|
"take": "Take",
|
||||||
"Target": {
|
"Target": {
|
||||||
"single": "Target",
|
"single": "Target",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
async renderHTML() {
|
async renderHTML() {
|
||||||
if (this.system.messageTemplate)
|
if (this.system.messageTemplate)
|
||||||
this.content = await foundry.applications.handlebars.renderTemplate(
|
this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, {
|
||||||
this.system.messageTemplate,
|
...this.system,
|
||||||
this.system
|
_source: this.system._source
|
||||||
);
|
});
|
||||||
|
|
||||||
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
|
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
|
||||||
const html = await super.renderHTML();
|
const html = await super.renderHTML();
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,34 @@ function getDualityMessage(roll) {
|
||||||
? game.i18n.localize(abilities[roll.trait].label)
|
? game.i18n.localize(abilities[roll.trait].label)
|
||||||
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
||||||
|
|
||||||
|
const advantage = roll.advantage
|
||||||
|
? CONFIG.DH.ACTIONS.advandtageState.advantage.value
|
||||||
|
: roll.disadvantage
|
||||||
|
? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
|
||||||
|
: undefined;
|
||||||
|
const advantageLabel =
|
||||||
|
advantage === CONFIG.DH.ACTIONS.advandtageState.advantage.value
|
||||||
|
? 'Advantage'
|
||||||
|
: advantage === CONFIG.DH.ACTIONS.advandtageState.disadvantage.value
|
||||||
|
? 'Disadvantage'
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const dualityElement = document.createElement('span');
|
const dualityElement = document.createElement('span');
|
||||||
dualityElement.innerHTML = `
|
dualityElement.innerHTML = `
|
||||||
<button class="duality-roll-button"
|
<button class="duality-roll-button"
|
||||||
data-title="${label}"
|
data-title="${label}"
|
||||||
data-label="${dataLabel}"
|
data-label="${dataLabel}"
|
||||||
data-hope="${roll.hope ?? 'd12'}"
|
data-hope="${roll.hope ?? 'd12'}"
|
||||||
data-fear="${roll.fear ?? 'd12'}"
|
data-fear="${roll.fear ?? 'd12'}"
|
||||||
|
${advantage ? `data-advantage="${advantage}"` : ''}
|
||||||
|
${roll.difficulty !== undefined ? `data-difficulty="${roll.difficulty}"` : ''}
|
||||||
${roll.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''}
|
${roll.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''}
|
||||||
${roll.advantage ? 'data-advantage="true"' : ''}
|
${roll.advantage ? 'data-advantage="true"' : ''}
|
||||||
${roll.disadvantage ? 'data-disadvantage="true"' : ''}
|
${roll.disadvantage ? 'data-disadvantage="true"' : ''}
|
||||||
>
|
>
|
||||||
<i class="fa-solid fa-circle-half-stroke"></i>
|
<i class="fa-solid fa-circle-half-stroke"></i>
|
||||||
${label}
|
${label}
|
||||||
|
${roll.difficulty || advantageLabel ? `(${[roll.difficulty, game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`)].filter(x => x).join(' ')})` : ''}
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
@ -43,16 +58,39 @@ function getDualityMessage(roll) {
|
||||||
export const renderDualityButton = async event => {
|
export const renderDualityButton = async event => {
|
||||||
const button = event.currentTarget,
|
const button = event.currentTarget,
|
||||||
traitValue = button.dataset.trait?.toLowerCase(),
|
traitValue = button.dataset.trait?.toLowerCase(),
|
||||||
target = getCommandTarget();
|
target = getCommandTarget(),
|
||||||
|
difficulty = button.dataset.difficulty,
|
||||||
|
advantage = button.dataset.advantage ? Number(button.dataset.advantage) : undefined;
|
||||||
|
|
||||||
|
await enrichedDualityRoll(
|
||||||
|
{
|
||||||
|
traitValue,
|
||||||
|
target,
|
||||||
|
difficulty,
|
||||||
|
title: button.dataset.title,
|
||||||
|
label: button.dataset.label,
|
||||||
|
actionType: button.dataset.actionType,
|
||||||
|
advantage
|
||||||
|
},
|
||||||
|
event
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const enrichedDualityRoll = async (
|
||||||
|
{ traitValue, target, difficulty, title, label, actionType, advantage },
|
||||||
|
event
|
||||||
|
) => {
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
event: event,
|
event: event ?? {},
|
||||||
title: button.dataset.title,
|
title: title,
|
||||||
roll: {
|
roll: {
|
||||||
modifier: traitValue ? target.system.traits[traitValue].value : null,
|
modifier: traitValue ? target.system.traits[traitValue].value : null,
|
||||||
label: button.dataset.label,
|
label: label,
|
||||||
type: button.dataset.actionType ?? null // Need check
|
difficulty: difficulty,
|
||||||
|
advantage,
|
||||||
|
type: actionType ?? null // Need check,
|
||||||
},
|
},
|
||||||
chatMessage: {
|
chatMessage: {
|
||||||
template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'
|
template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'
|
||||||
|
|
|
||||||
|
|
@ -131,13 +131,17 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
.roll-mode-select {
|
.roll-mode-select {
|
||||||
width: min-content;
|
width: min-content;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
font-family: @font-body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,14 +136,22 @@
|
||||||
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
<span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span>
|
<span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span>
|
||||||
|
|
||||||
<div class="roll-dialog-controls">
|
<div class="roll-dialog-controls">
|
||||||
<select class="roll-mode-select" name="selectedRollMode">
|
<select class="roll-mode-select" name="selectedRollMode">
|
||||||
{{selectOptions rollModes selected=selectedRollMode valueAttr="action" labelAttr="label" localize=true}}
|
{{selectOptions rollModes selected=selectedRollMode valueAttr="action" labelAttr="label" localize=true}}
|
||||||
</select>
|
</select>
|
||||||
<button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>
|
<button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>
|
||||||
<i class="fa-solid fa-dice"></i>
|
<i class="fa-solid fa-dice"></i>
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.roll"}}</span>
|
<span class="label">
|
||||||
|
{{#if @root.rollConfig.roll.difficulty}}
|
||||||
|
{{localize "DAGGERHEART.GENERAL.Roll.difficulty" difficulty=@root.rollConfig.roll.difficulty}}
|
||||||
|
{{else}}
|
||||||
|
{{localize "DAGGERHEART.GENERAL.roll"}}
|
||||||
|
{{/if}}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dice-total duality {{#if (eq roll.result.duality 1)}}hope{{else}}{{#if (eq roll.result.duality -1)}}fear{{else}}critical{{/if}}{{/if}}">
|
<div class="dice-total duality {{#if (eq roll.result.duality 1)}}hope{{else}}{{#if (eq roll.result.duality -1)}}fear{{else}}critical{{/if}}{{/if}}">
|
||||||
<div class="dice-total-label">{{roll.result.label}}</div>
|
<div class="dice-total-label">
|
||||||
|
{{#unless (eq _source.roll.success undefined)}}
|
||||||
|
{{#if _source.roll.success}}
|
||||||
|
{{localize "DAGGERHEART.GENERAL.success"}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.result.label}}
|
||||||
|
{{else}}
|
||||||
|
{{localize "DAGGERHEART.GENERAL.failure"}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.result.label}}
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{roll.result.label}}
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
<div class="dice-total-value">
|
<div class="dice-total-value">
|
||||||
{{roll.total}}
|
{{roll.total}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue