mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
[V14] Message Rolls Rework (#1757)
* Basic rework to the roll data in messages * . * Fixed advantage/disadvantage * . * . * Fixed TagTeamDialog * Reuse getter in faces setter * Simplify fate roll type css class * Add more caution to the dualityRoll fromData function * Apply suggestion from @CarlosFdez * Compute modifiers using deterministic terms (#1758) --------- Co-authored-by: Carlos Fernandez <cfern1990@gmail.com> Co-authored-by: Carlos Fernandez <CarlosFdez@users.noreply.github.com>
This commit is contained in:
parent
dbd5ef8bb0
commit
f156b12d79
20 changed files with 267 additions and 249 deletions
|
|
@ -35,6 +35,8 @@ CONFIG.Dice.daggerheart = {
|
||||||
FateRoll: FateRoll
|
FateRoll: FateRoll
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.assign(CONFIG.Dice.termTypes, dice.diceTypes);
|
||||||
|
|
||||||
CONFIG.Actor.documentClass = documents.DhpActor;
|
CONFIG.Actor.documentClass = documents.DhpActor;
|
||||||
CONFIG.Actor.dataModels = models.actors.config;
|
CONFIG.Actor.dataModels = models.actors.config;
|
||||||
CONFIG.Actor.collection = collections.DhActorCollection;
|
CONFIG.Actor.collection = collections.DhActorCollection;
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
|
|
||||||
partContext.members[partId] = {
|
partContext.members[partId] = {
|
||||||
...data,
|
...data,
|
||||||
|
roll: data.roll,
|
||||||
isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER),
|
isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER),
|
||||||
key: partId,
|
key: partId,
|
||||||
readyToRoll: Boolean(data.rollChoice),
|
readyToRoll: Boolean(data.rollChoice),
|
||||||
|
|
@ -448,24 +449,19 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
const { member, diceType } = button.dataset;
|
const { member, diceType } = button.dataset;
|
||||||
const memberData = this.party.system.tagTeam.members[member];
|
const memberData = this.party.system.tagTeam.members[member];
|
||||||
|
|
||||||
const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 2 : 4;
|
const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 1 : 2;
|
||||||
|
const newRoll = game.system.api.dice.DualityRoll.fromData(memberData.rollData);
|
||||||
const { parsedRoll, newRoll } = await game.system.api.dice.DualityRoll.reroll(
|
const dice = newRoll.dice[dieIndex];
|
||||||
memberData.rollData,
|
await dice.reroll(`/r1=${dice.total}`, {
|
||||||
dieIndex,
|
liveRoll: {
|
||||||
diceType,
|
roll: newRoll,
|
||||||
false
|
isReaction: true
|
||||||
);
|
}
|
||||||
const rollData = parsedRoll.toJSON();
|
});
|
||||||
|
const rollData = newRoll.toJSON();
|
||||||
this.updatePartyData(
|
this.updatePartyData(
|
||||||
{
|
{
|
||||||
[`system.tagTeam.members.${member}.rollData`]: {
|
[`system.tagTeam.members.${member}.rollData`]: rollData
|
||||||
...rollData,
|
|
||||||
options: {
|
|
||||||
...rollData.options,
|
|
||||||
roll: newRoll
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
this.getUpdatingParts(button)
|
this.getUpdatingParts(button)
|
||||||
);
|
);
|
||||||
|
|
@ -700,7 +696,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
const error = this.checkInitiatorHopeError(this.party.system.tagTeam.initiator);
|
const error = this.checkInitiatorHopeError(this.party.system.tagTeam.initiator);
|
||||||
if (error) return error;
|
if (error) return error;
|
||||||
|
|
||||||
const mainRoll = (await this.getJoinedRoll()).rollData;
|
const joinedRoll = await this.getJoinedRoll();
|
||||||
|
const mainRoll = joinedRoll.rollData;
|
||||||
|
const finalRoll = foundry.utils.deepClone(joinedRoll.roll);
|
||||||
|
|
||||||
const mainActor = this.party.system.partyMembers.find(x => x.uuid === mainRoll.options.source.actor);
|
const mainActor = this.party.system.partyMembers.find(x => x.uuid === mainRoll.options.source.actor);
|
||||||
mainRoll.options.title = game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.chatMessageRollTitle');
|
mainRoll.options.title = game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.chatMessageRollTitle');
|
||||||
|
|
@ -711,7 +709,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
title: game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.title'),
|
title: game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.title'),
|
||||||
speaker: cls.getSpeaker({ actor: mainActor }),
|
speaker: cls.getSpeaker({ actor: mainActor }),
|
||||||
system: mainRoll.options,
|
system: mainRoll.options,
|
||||||
rolls: [mainRoll],
|
rolls: [JSON.stringify(joinedRoll.roll)],
|
||||||
sound: null,
|
sound: null,
|
||||||
flags: { core: { RollTable: true } }
|
flags: { core: { RollTable: true } }
|
||||||
};
|
};
|
||||||
|
|
@ -723,7 +721,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
const fearUpdate = { key: 'fear', value: null, total: null, enabled: true };
|
const fearUpdate = { key: 'fear', value: null, total: null, enabled: true };
|
||||||
for (let memberId in tagTeamData.members) {
|
for (let memberId in tagTeamData.members) {
|
||||||
const resourceUpdates = [];
|
const resourceUpdates = [];
|
||||||
const rollGivesHope = mainRoll.options.roll.isCritical || mainRoll.options.roll.result.duality === 1;
|
const rollGivesHope = finalRoll.isCritical || finalRoll.withHope;
|
||||||
if (memberId === tagTeamData.initiator.memberId) {
|
if (memberId === tagTeamData.initiator.memberId) {
|
||||||
const value = tagTeamData.initiator.cost
|
const value = tagTeamData.initiator.cost
|
||||||
? rollGivesHope
|
? rollGivesHope
|
||||||
|
|
@ -734,9 +732,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
} else if (rollGivesHope) {
|
} else if (rollGivesHope) {
|
||||||
resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
||||||
}
|
}
|
||||||
if (mainRoll.options.roll.isCritical)
|
if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
||||||
resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
if (finalRoll.withFear) {
|
||||||
if (mainRoll.options.roll.result.duality === -1) {
|
|
||||||
fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1;
|
fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1;
|
||||||
fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1;
|
fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
action.use(event);
|
action.use(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
async rerollEvent(event, message) {
|
async rerollEvent(event, messageData) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (!event.shiftKey) {
|
if (!event.shiftKey) {
|
||||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
|
@ -187,6 +187,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const message = game.messages.get(messageData._id);
|
||||||
const target = event.target.closest('[data-die-index]');
|
const target = event.target.closest('[data-die-index]');
|
||||||
|
|
||||||
if (target.dataset.type === 'damage') {
|
if (target.dataset.type === 'damage') {
|
||||||
|
|
@ -209,27 +210,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let originalRoll_parsed = message.rolls.map(roll => JSON.parse(roll))[0];
|
const rerollDice = message.system.roll.dice[target.dataset.dieIndex];
|
||||||
const rollClass =
|
await rerollDice.reroll(`/r1=${rerollDice.total}`, {
|
||||||
game.system.api.dice[
|
liveRoll: {
|
||||||
message.type === 'dualityRoll'
|
roll: message.system.roll,
|
||||||
? 'DualityRoll'
|
actor: message.system.actionActor,
|
||||||
: target.dataset.type === 'damage'
|
isReaction: message.system.roll.options.actionType === 'reaction'
|
||||||
? 'DHRoll'
|
}
|
||||||
: 'D20Roll'
|
});
|
||||||
];
|
await message.update({
|
||||||
|
rolls: [message.system.roll.toJSON()]
|
||||||
if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
|
|
||||||
|
|
||||||
const { newRoll, parsedRoll } = await rollClass.reroll(
|
|
||||||
originalRoll_parsed,
|
|
||||||
target.dataset.dieIndex,
|
|
||||||
target.dataset.type
|
|
||||||
);
|
|
||||||
|
|
||||||
await game.messages.get(message._id).update({
|
|
||||||
'system.roll': newRoll,
|
|
||||||
'rolls': [parsedRoll]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
return {
|
return {
|
||||||
title: new fields.StringField(),
|
title: new fields.StringField(),
|
||||||
actionDescription: new fields.HTMLField(),
|
actionDescription: new fields.HTMLField(),
|
||||||
roll: new fields.ObjectField(),
|
|
||||||
targets: targetsField(),
|
targets: targetsField(),
|
||||||
hasRoll: new fields.BooleanField({ initial: false }),
|
hasRoll: new fields.BooleanField({ initial: false }),
|
||||||
hasDamage: new fields.BooleanField({ initial: false }),
|
hasDamage: new fields.BooleanField({ initial: false }),
|
||||||
|
|
@ -55,6 +54,16 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get roll() {
|
||||||
|
if (this.parent.type === 'dualityRoll')
|
||||||
|
return this.parent.rolls.find(x => x instanceof game.system.api.dice.DualityRoll);
|
||||||
|
|
||||||
|
if (this.parent.type === 'fateRoll')
|
||||||
|
return this.parent.rolls.find(x => x instanceof game.system.api.dice.FateRoll);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
get actionActor() {
|
get actionActor() {
|
||||||
if (!this.source.actor) return null;
|
if (!this.source.actor) return null;
|
||||||
return fromUuidSync(this.source.actor);
|
return fromUuidSync(this.source.actor);
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ export { default as DamageRoll } from './damageRoll.mjs';
|
||||||
export { default as DHRoll } from './dhRoll.mjs';
|
export { default as DHRoll } from './dhRoll.mjs';
|
||||||
export { default as DualityRoll } from './dualityRoll.mjs';
|
export { default as DualityRoll } from './dualityRoll.mjs';
|
||||||
export { default as FateRoll } from './fateRoll.mjs';
|
export { default as FateRoll } from './fateRoll.mjs';
|
||||||
|
export { diceTypes } from './die/_module.mjs';
|
||||||
|
|
|
||||||
|
|
@ -217,49 +217,11 @@ export default class D20Roll extends DHRoll {
|
||||||
results: d.results
|
results: d.results
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
data.modifierTotal = this.calculateTotalModifiers(roll);
|
data.modifierTotal = roll.modifierTotal;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFormula() {
|
resetFormula() {
|
||||||
return (this._formula = this.constructor.getFormula(this.terms));
|
return (this._formula = this.constructor.getFormula(this.terms));
|
||||||
}
|
}
|
||||||
|
|
||||||
static async reroll(rollString, _target, message) {
|
|
||||||
let parsedRoll = game.system.api.dice.D20Roll.fromData(rollString);
|
|
||||||
parsedRoll = await parsedRoll.reroll();
|
|
||||||
const newRoll = game.system.api.dice.D20Roll.postEvaluate(parsedRoll, {
|
|
||||||
targets: message.system.targets,
|
|
||||||
roll: {
|
|
||||||
advantage: message.system.roll.advantage?.type,
|
|
||||||
difficulty: message.system.roll.difficulty ? Number(message.system.roll.difficulty) : null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (game.modules.get('dice-so-nice')?.active) {
|
|
||||||
await game.dice3d.showForRoll(parsedRoll, game.user, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rerolled = {
|
|
||||||
any: true,
|
|
||||||
rerolls: [
|
|
||||||
...(message.system.roll.dice[0].rerolled?.rerolls?.length > 0
|
|
||||||
? [message.system.roll.dice[0].rerolled?.rerolls]
|
|
||||||
: []),
|
|
||||||
rollString.terms[0].results
|
|
||||||
]
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
newRoll: {
|
|
||||||
...newRoll,
|
|
||||||
dice: [
|
|
||||||
{
|
|
||||||
...newRoll.dice[0],
|
|
||||||
rerolled: rerolled
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
parsedRoll
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@ export default class DHRoll extends Roll {
|
||||||
return game.i18n.localize('DAGGERHEART.GENERAL.Roll.basic');
|
return game.i18n.localize('DAGGERHEART.GENERAL.Roll.basic');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modifierTotal() {
|
||||||
|
return this.constructor.calculateTotalModifiers(this);
|
||||||
|
}
|
||||||
|
|
||||||
static messageType = 'adversaryRoll';
|
static messageType = 'adversaryRoll';
|
||||||
|
|
||||||
static CHAT_TEMPLATE = 'systems/daggerheart/templates/ui/chat/roll.hbs';
|
static CHAT_TEMPLATE = 'systems/daggerheart/templates/ui/chat/roll.hbs';
|
||||||
|
|
@ -138,6 +142,7 @@ export default class DHRoll extends Roll {
|
||||||
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
||||||
return foundry.applications.handlebars.renderTemplate(template, {
|
return foundry.applications.handlebars.renderTemplate(template, {
|
||||||
...chatData,
|
...chatData,
|
||||||
|
roll: this,
|
||||||
parent: chatData.parent,
|
parent: chatData.parent,
|
||||||
targetMode: chatData.targetMode,
|
targetMode: chatData.targetMode,
|
||||||
metagamingSettings
|
metagamingSettings
|
||||||
|
|
@ -241,16 +246,21 @@ export default class DHRoll extends Roll {
|
||||||
return (this._formula = this.constructor.getFormula(this.terms));
|
return (this._formula = this.constructor.getFormula(this.terms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate total modifiers of any rolls, including non-dh rolls.
|
||||||
|
* This exists because damage rolls still may receive base roll classes
|
||||||
|
*/
|
||||||
static calculateTotalModifiers(roll) {
|
static calculateTotalModifiers(roll) {
|
||||||
let modifierTotal = 0;
|
let modifierTotal = 0;
|
||||||
for (let i = 0; i < roll.terms.length; i++) {
|
for (let i = 0; i < roll.terms.length; i++) {
|
||||||
if (
|
if (!roll.terms[i].isDeterministic) continue;
|
||||||
roll.terms[i] instanceof foundry.dice.terms.NumericTerm &&
|
const termTotal = roll.terms[i].total;
|
||||||
!!roll.terms[i - 1] &&
|
if (typeof termTotal === 'number') {
|
||||||
roll.terms[i - 1] instanceof foundry.dice.terms.OperatorTerm
|
const multiplier = roll.terms[i - 1]?.operator === " - " ? -1 : 1;
|
||||||
)
|
modifierTotal += multiplier * termTotal;
|
||||||
modifierTotal += Number(`${roll.terms[i - 1].operator}${roll.terms[i].total}`);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return modifierTotal;
|
return modifierTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
9
module/dice/die/_module.mjs
Normal file
9
module/dice/die/_module.mjs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import DualityDie from './dualityDie.mjs';
|
||||||
|
import AdvantageDie from './advantageDie.mjs';
|
||||||
|
import DisadvantageDie from './disadvantageDie.mjs';
|
||||||
|
|
||||||
|
export const diceTypes = {
|
||||||
|
DualityDie,
|
||||||
|
AdvantageDie,
|
||||||
|
DisadvantageDie
|
||||||
|
};
|
||||||
7
module/dice/die/advantageDie.mjs
Normal file
7
module/dice/die/advantageDie.mjs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export default class AdvantageDie extends foundry.dice.terms.Die {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this.modifiers = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
7
module/dice/die/disadvantageDie.mjs
Normal file
7
module/dice/die/disadvantageDie.mjs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export default class DisadvantageDie extends foundry.dice.terms.Die {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this.modifiers = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
62
module/dice/die/dualityDie.mjs
Normal file
62
module/dice/die/dualityDie.mjs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
||||||
|
|
||||||
|
export default class DualityDie extends foundry.dice.terms.Die {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this.modifiers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
#getDualityState(roll) {
|
||||||
|
if (!roll) return null;
|
||||||
|
return roll.withHope ? 1 : roll.withFear ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateResources(oldDuality, newDuality, actor) {
|
||||||
|
const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
|
||||||
|
if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return;
|
||||||
|
|
||||||
|
const updates = [];
|
||||||
|
const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0);
|
||||||
|
const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
|
||||||
|
const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
|
||||||
|
|
||||||
|
if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
|
||||||
|
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
|
||||||
|
if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
|
||||||
|
|
||||||
|
const resourceUpdates = new ResourceUpdateMap(actor);
|
||||||
|
resourceUpdates.addResources(updates);
|
||||||
|
resourceUpdates.updateResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
async reroll(modifier, options) {
|
||||||
|
const oldDuality = this.#getDualityState(options.liveRoll.roll);
|
||||||
|
await super.reroll(modifier, options);
|
||||||
|
|
||||||
|
if (options?.liveRoll) {
|
||||||
|
/* Can't currently test since DiceSoNice is not v14. Might need to set the appearance earlier if a roll is triggered by super.reroll */
|
||||||
|
if (game.modules.get('dice-so-nice')?.active) {
|
||||||
|
const diceSoNiceRoll = {
|
||||||
|
_evaluated: true,
|
||||||
|
dice: [this],
|
||||||
|
options: { appearance: {} }
|
||||||
|
};
|
||||||
|
|
||||||
|
const preset = await getDiceSoNicePreset(diceSoNice[key], faces);
|
||||||
|
diceSoNiceRoll.dice[0].options.appearance = preset.appearance;
|
||||||
|
diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile;
|
||||||
|
|
||||||
|
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
|
||||||
|
} else {
|
||||||
|
foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
|
||||||
|
}
|
||||||
|
|
||||||
|
await options.liveRoll.roll._evaluate();
|
||||||
|
if (options.liveRoll.isReaction) return;
|
||||||
|
|
||||||
|
const newDuality = this.#getDualityState(options.liveRoll.roll);
|
||||||
|
this.#updateResources(oldDuality, newDuality, options.liveRoll.actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
|
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
|
||||||
import D20Roll from './d20Roll.mjs';
|
import D20Roll from './d20Roll.mjs';
|
||||||
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
||||||
import { getDiceSoNicePresets } from '../config/generalConfig.mjs';
|
|
||||||
import { ResourceUpdateMap } from '../data/action/baseAction.mjs';
|
|
||||||
|
|
||||||
export default class DualityRoll extends D20Roll {
|
export default class DualityRoll extends D20Roll {
|
||||||
_advantageFaces = 6;
|
_advantageFaces = 6;
|
||||||
|
|
@ -26,27 +24,31 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
get dHope() {
|
get dHope() {
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice();
|
||||||
return this.dice[0];
|
return this.dice[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
set dHope(faces) {
|
set dHope(faces) {
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
// TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dHope.faces
|
||||||
this.dice[0].faces = this.getFaces(faces);
|
this.dHope.faces = this.getFaces(faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
get dFear() {
|
get dFear() {
|
||||||
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice();
|
||||||
return this.dice[1];
|
return this.dice[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
set dFear(faces) {
|
set dFear(faces) {
|
||||||
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
// TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dFear.faces
|
||||||
this.dice[1].faces = this.getFaces(faces);
|
this.dFear.faces = this.getFaces(faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
get dAdvantage() {
|
get dAdvantage() {
|
||||||
return this.dice[2];
|
return this.dice[2] instanceof game.system.api.dice.diceTypes.AdvantageDie ? this.dice[2] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dDisadvantage() {
|
||||||
|
return this.dice[2] instanceof game.system.api.dice.diceTypes.DisadvantageDie ? this.dice[2] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get advantageFaces() {
|
get advantageFaces() {
|
||||||
|
|
@ -65,6 +67,11 @@ export default class DualityRoll extends D20Roll {
|
||||||
this._advantageNumber = Number(value);
|
this._advantageNumber = Number(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get extraDice() {
|
||||||
|
const { DualityDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes;
|
||||||
|
return this.dice.filter(x => ![DualityDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die));
|
||||||
|
}
|
||||||
|
|
||||||
setRallyChoices() {
|
setRallyChoices() {
|
||||||
return this.data?.parent?.appliedEffects.reduce((a, c) => {
|
return this.data?.parent?.appliedEffects.reduce((a, c) => {
|
||||||
const change = c.system.changes.find(ch => ch.key === 'system.bonuses.rally');
|
const change = c.system.changes.find(ch => ch.key === 'system.bonuses.rally');
|
||||||
|
|
@ -118,22 +125,28 @@ export default class DualityRoll extends D20Roll {
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
static fromData(data) {
|
static fromData(data) {
|
||||||
data.terms[0].class = foundry.dice.terms.Die.name;
|
data.terms[0].class = 'DualityDie';
|
||||||
data.terms[2].class = foundry.dice.terms.Die.name;
|
data.terms[2].class = 'DualityDie';
|
||||||
|
if (data.options.roll.advantage?.type && data.terms[4]?.faces) {
|
||||||
|
data.terms[4].class = data.options.roll.advantage.type === 1 ? 'AdvantageDie' : 'DisadvantageDie';
|
||||||
|
}
|
||||||
return super.fromData(data);
|
return super.fromData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
createBaseDice() {
|
createBaseDice() {
|
||||||
if (this.dice[0] instanceof foundry.dice.terms.Die && this.dice[1] instanceof foundry.dice.terms.Die) {
|
if (
|
||||||
|
this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie &&
|
||||||
|
this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie
|
||||||
|
) {
|
||||||
this.terms = [this.terms[0], this.terms[1], this.terms[2]];
|
this.terms = [this.terms[0], this.terms[1], this.terms[2]];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.terms[0] = new foundry.dice.terms.Die({
|
this.terms[0] = new game.system.api.dice.diceTypes.DualityDie({
|
||||||
faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12
|
faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12
|
||||||
});
|
});
|
||||||
this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' });
|
this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' });
|
||||||
this.terms[2] = new foundry.dice.terms.Die({
|
this.terms[2] = new game.system.api.dice.diceTypes.DualityDie({
|
||||||
faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12
|
faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -371,63 +384,4 @@ export default class DualityRoll extends D20Roll {
|
||||||
if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id);
|
if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async reroll(rollBase, dieIndex, diceType, updateResources = true) {
|
|
||||||
let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...rollBase, evaluated: false });
|
|
||||||
const term = parsedRoll.terms[dieIndex];
|
|
||||||
await term.reroll(`/r1=${term.total}`);
|
|
||||||
const result = await parsedRoll.evaluate();
|
|
||||||
|
|
||||||
if (game.modules.get('dice-so-nice')?.active) {
|
|
||||||
const diceSoNiceRoll = {
|
|
||||||
_evaluated: true,
|
|
||||||
dice: [
|
|
||||||
new foundry.dice.terms.Die({
|
|
||||||
...term,
|
|
||||||
faces: term._faces,
|
|
||||||
results: term.results.filter(x => !x.rerolled)
|
|
||||||
})
|
|
||||||
],
|
|
||||||
options: { appearance: {} }
|
|
||||||
};
|
|
||||||
|
|
||||||
const diceSoNicePresets = await getDiceSoNicePresets(`d${term._faces}`, `d${term._faces}`);
|
|
||||||
if (diceSoNicePresets[diceType]) {
|
|
||||||
diceSoNiceRoll.dice[0].options = diceSoNicePresets[diceType];
|
|
||||||
}
|
|
||||||
|
|
||||||
await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
|
|
||||||
} else {
|
|
||||||
foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
|
|
||||||
}
|
|
||||||
|
|
||||||
const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, {
|
|
||||||
targets: parsedRoll.options.targets ?? [],
|
|
||||||
roll: {
|
|
||||||
advantage: parsedRoll.options.roll.advantage?.type,
|
|
||||||
difficulty: parsedRoll.options.roll.difficulty ? Number(parsedRoll.options.roll.difficulty) : null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const extraIndex = newRoll.advantage ? 3 : 2;
|
|
||||||
newRoll.extra = newRoll.extra.slice(extraIndex);
|
|
||||||
|
|
||||||
const actor = parsedRoll.options.source.actor
|
|
||||||
? await foundry.utils.fromUuid(parsedRoll.options.source.actor)
|
|
||||||
: null;
|
|
||||||
const config = {
|
|
||||||
source: { actor: parsedRoll.options.source.actor ?? '' },
|
|
||||||
targets: parsedRoll.targets,
|
|
||||||
roll: newRoll,
|
|
||||||
rerolledRoll: parsedRoll.options.roll,
|
|
||||||
resourceUpdates: new ResourceUpdateMap(actor)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (updateResources) {
|
|
||||||
await DualityRoll.addDualityResourceUpdates(config);
|
|
||||||
await config.resourceUpdates.updateResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
return { newRoll, parsedRoll };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ export default class FateRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
set dHope(faces) {
|
set dHope(faces) {
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
// TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dHope.faces
|
||||||
this.dice[0].faces = this.getFaces(faces);
|
this.dHope.faces = this.getFaces(faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
get dFear() {
|
get dFear() {
|
||||||
|
|
@ -31,8 +31,8 @@ export default class FateRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
set dFear(faces) {
|
set dFear(faces) {
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
// TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dFear.faces
|
||||||
this.dice[0].faces = this.getFaces(faces);
|
this.dFear.faces = this.getFaces(faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isCritical() {
|
get isCritical() {
|
||||||
|
|
@ -43,6 +43,22 @@ export default class FateRoll extends D20Roll {
|
||||||
return this.data.fateType;
|
return this.data.fateType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get withHope() {
|
||||||
|
if (!this._evaluatedl) return;
|
||||||
|
return this.dHope.total >= this.dFear.total;
|
||||||
|
}
|
||||||
|
|
||||||
|
get withFear() {
|
||||||
|
if (!this._evaluated) return;
|
||||||
|
return this.dHope.total < this.dFear.total;
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalLabel() {
|
||||||
|
const label = this.withHope ? 'DAGGERHEART.GENERAL.hope' : 'DAGGERHEART.GENERAL.fear';
|
||||||
|
|
||||||
|
return game.i18n.localize(label);
|
||||||
|
}
|
||||||
|
|
||||||
static getHooks(hooks) {
|
static getHooks(hooks) {
|
||||||
return [...(hooks ?? []), 'Fate'];
|
return [...(hooks ?? []), 'Fate'];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../systemRegistration/socket.mjs';
|
import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs';
|
||||||
|
|
||||||
export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
targetHook = null;
|
targetHook = null;
|
||||||
|
|
@ -78,25 +78,14 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
if (this.isContentVisible) {
|
if (this.isContentVisible) {
|
||||||
if (this.type === 'dualityRoll') {
|
if (this.type === 'dualityRoll') {
|
||||||
html.classList.add('duality');
|
html.classList.add('duality');
|
||||||
switch (this.system.roll?.result?.duality) {
|
if (this.system.roll.withHope) html.classList.add('hope');
|
||||||
case 1:
|
else if (this.system.roll.withFear) html.classList.add('fear');
|
||||||
html.classList.add('hope');
|
else html.classList.add('critical');
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
html.classList.add('fear');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
html.classList.add('critical');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (this.type === 'fateRoll') {
|
if (this.type === 'fateRoll') {
|
||||||
html.classList.add('fate');
|
html.classList.add('fate');
|
||||||
if (this.system.roll?.fate.fateDie == 'Hope') {
|
if (this.system.roll?.fateDie) {
|
||||||
html.classList.add('hope');
|
html.classList.add(this.system.roll.fateDie.toLowerCase());
|
||||||
}
|
|
||||||
if (this.system.roll?.fate.fateDie == 'Fear') {
|
|
||||||
html.classList.add('fear');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,15 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 15px;
|
width: 15px;
|
||||||
}
|
}
|
||||||
|
&.has-minus:before {
|
||||||
|
content: '-';
|
||||||
|
font-size: var(--font-size-20);
|
||||||
|
grid-area: c;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,14 @@
|
||||||
{{#if @root.advantage}}
|
{{#if @root.advantage}}
|
||||||
{{#if (eq @root.advantage 1)}}
|
{{#if (eq @root.advantage 1)}}
|
||||||
<div class="dice-option">
|
<div class="dice-option">
|
||||||
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/adv/' @root.roll.dAdvantage.denomination '.svg'}}" alt="">
|
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/adv/d' @root.roll.advantageFaces '.svg'}}" alt="">
|
||||||
<div class="dice-select">
|
<div class="dice-select">
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.Advantage.full"}}</span>
|
<span class="label">{{localize "DAGGERHEART.GENERAL.Advantage.full"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else if (eq @root.advantage -1)}}
|
{{else if (eq @root.advantage -1)}}
|
||||||
<div class="dice-option">
|
<div class="dice-option">
|
||||||
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/disadv/' @root.roll.dAdvantage.denomination '.svg'}}" alt="">
|
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/disadv/d' @root.roll.advantageFaces '.svg'}}" alt="">
|
||||||
<div class="dice-select">
|
<div class="dice-select">
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -158,7 +158,7 @@
|
||||||
{{/times}}
|
{{/times}}
|
||||||
</select>
|
</select>
|
||||||
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
||||||
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
{{selectOptions diceOptions selected=(concat 'd' @root.roll.advantageFaces)}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{#if abilities}}
|
{{#if abilities}}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
{{#each damage.parts as |part|}}
|
{{#each damage.parts as |part|}}
|
||||||
<div class="roll-dice-container">
|
<div class="roll-dice-container">
|
||||||
{{#each part.dice as |dice index|}}
|
{{#each part.dice as |dice index|}}
|
||||||
<a class="roll-dice" data-action="rerollDamageDice" data-member-key="{{@../../../key}}" data-damage-key="{{@../../key}}" data-part="{{@../index}}" data-dice="{{index}}">
|
<a class="roll-dice" data-action="rerollDamageDice" data-member-key="{{../../../key}}" data-damage-key="{{@../../key}}" data-part="{{@../index}}" data-dice="{{index}}">
|
||||||
<span class="dice-label">{{dice.total}}</span>
|
<span class="dice-label">{{dice.total}}</span>
|
||||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" dice.dice ".svg"}}" />
|
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" dice.dice ".svg"}}" />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -62,32 +62,30 @@
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{#if rollData}}
|
{{#if roll}}
|
||||||
{{#with rollData.options.roll}}
|
<div class="roll-data {{#if roll.withHope}}hope{{else if roll.withFear}}fear{{else}}critical{{/if}}">
|
||||||
<div class="roll-data {{#if this.isCritical}}critical{{else}}{{#if (eq this.result.duality 1)}}hope{{else}}fear{{/if}}{{/if}}">
|
<div class="duality-label">{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}</div>
|
||||||
<div class="duality-label">{{this.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=this.result.label}}</div>
|
|
||||||
<div class="roll-dice-container">
|
<div class="roll-dice-container">
|
||||||
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="hope">
|
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="hope">
|
||||||
<span class="dice-label">{{this.hope.value}}</span>
|
<span class="dice-label">{{roll.dHope.total}}</span>
|
||||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" this.hope.dice ".svg"}}" />
|
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" roll.dHope.denomination ".svg"}}" />
|
||||||
</a>
|
</a>
|
||||||
<span class="roll-operator">+</span>
|
<span class="roll-operator">+</span>
|
||||||
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="fear">
|
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="fear">
|
||||||
<span class="dice-label">{{this.fear.value}}</span>
|
<span class="dice-label">{{roll.dFear.total}}</span>
|
||||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/fear/" this.fear.dice ".svg"}}" />
|
<img src="{{concat "systems/daggerheart/assets/icons/dice/fear/" roll.dFear.denomination ".svg"}}" />
|
||||||
</a>
|
</a>
|
||||||
{{#if this.advantage.type}}
|
{{#if roll.advantage.type}}
|
||||||
<span class="roll-operator">{{#if (eq this.advantage.type 1)}}+{{else}}-{{/if}}</span>
|
<span class="roll-operator">{{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}}</span>
|
||||||
<span class="roll-dice">
|
<span class="roll-dice">
|
||||||
<span class="dice-label">{{this.advantage.value}}</span>
|
<span class="dice-label">{{roll.advantage.value}}</span>
|
||||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/" (ifThen (eq this.advantage.type 1) "adv/" "disadv/") this.advantage.dice ".svg"}}" />
|
<img src="{{concat "systems/daggerheart/assets/icons/dice/" (ifThen (eq roll.advantage.type 1) "adv/" "disadv/") roll.advantage.dice ".svg"}}" />
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span class="roll-operator">{{#if (gte this.modifierTotal 0)}}+{{else}}-{{/if}}</span>
|
<span class="roll-operator">{{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}}</span>
|
||||||
<span class="roll-value">{{positive this.modifierTotal}}</span>
|
<span class="roll-value">{{positive roll.modifierTotal}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/with}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="hint">{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}}</span>
|
<span class="hint">{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@
|
||||||
{{#if hintText}}
|
{{#if hintText}}
|
||||||
<div class="hint">{{localize hintText}}</div>
|
<div class="hint">{{localize hintText}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if joinedRoll.rollData}}
|
{{#if joinedRoll.roll}}
|
||||||
<div class="result-container">
|
<div class="result-container">
|
||||||
<span class="result-section-label">{{localize "DAGGERHEART.GENERAL.dualityRoll"}}</span>
|
<span class="result-section-label">{{localize "DAGGERHEART.GENERAL.dualityRoll"}}</span>
|
||||||
<div class="result-info">
|
<div class="result-info">
|
||||||
<div class="damage-info">{{joinedRoll.rollData.options.roll.total}}</div>
|
<div class="damage-info">{{joinedRoll.roll.total}}</div>
|
||||||
<div>{{localize "DAGGERHEART.GENERAL.withThing" thing=joinedRoll.rollData.options.roll.result.label}}</div>
|
<div>{{localize "DAGGERHEART.GENERAL.withThing" thing=joinedRoll.roll.totalLabel}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if hasDamage}}
|
{{#if joinedRoll.rollData.options.hasDamage}}
|
||||||
<div class="result-container">
|
<div class="result-container">
|
||||||
<span class="result-section-label">{{localize "DAGGERHEART.GENERAL.damage"}}</span>
|
<span class="result-section-label">{{localize "DAGGERHEART.GENERAL.damage"}}</span>
|
||||||
{{#each joinedRoll.rollData.options.damage as |damage key|}}
|
{{#each joinedRoll.rollData.options.damage as |damage key|}}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.criticalShort"}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.criticalShort"}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if (and roll.result (not (eq roll.type "reaction")))}}
|
{{#if (and roll.result (not (eq roll.type "reaction")))}}
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.withThing" thing=roll.result.label}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -29,48 +29,48 @@
|
||||||
<div class="dice-tooltip">
|
<div class="dice-tooltip">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="roll-dice">
|
<div class="roll-dice">
|
||||||
{{#if roll.fate}}
|
{{#if roll.fateDie}}
|
||||||
{{#if (eq roll.fate.fateDie "Hope")}}
|
{{#if (eq roll.fateDie "Hope")}}
|
||||||
<div class="roll-die">
|
<div class="roll-die">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
||||||
<div class="dice {{roll.fate.dice}} color-hope" data-die-index="0" data-type="hope">
|
<div class="dice {{roll.dHope.denomination}} color-hope" data-die-index="0" data-type="hope">
|
||||||
{{roll.fate.value}}
|
{{roll.dHope.total}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq roll.fate.fateDie "Fear")}}
|
{{#if (eq roll.fateDie "Fear")}}
|
||||||
<div class="roll-die">
|
<div class="roll-die">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.fear"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.fear"}}</label>
|
||||||
<div class="dice {{roll.fate.dice}} color-fear" data-die-index="0" data-type="fear">
|
<div class="dice {{roll.dFear.denomination}} color-fear" data-die-index="0" data-type="fear">
|
||||||
{{roll.fate.value}}
|
{{roll.dFear.total}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if roll.hope}}
|
{{#if roll.dHope}}
|
||||||
<div class="roll-die">
|
<div class="roll-die">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
||||||
<div class="dice {{roll.hope.dice}} color-hope reroll-button" data-die-index="0" data-type="hope" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}">
|
<div class="dice {{roll.dHope.denomination}} color-hope reroll-button" data-die-index="0" data-type="hope" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}">
|
||||||
{{#if roll.hope.rerolled.any}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.UI.Tooltip.diceIsRerolled" times=roll.hope.rerolled.rerolls.length}}"></i>{{/if}}
|
{{#if roll.dHopehope.rerolled.any}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.UI.Tooltip.diceIsRerolled" times=roll.dHope.rerolled.rerolls.length}}"></i>{{/if}}
|
||||||
{{roll.hope.value}}
|
{{roll.dHope.total}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="roll-die has-plus">
|
<div class="roll-die has-plus">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.fear"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.fear"}}</label>
|
||||||
<div class="dice {{roll.fear.dice}} color-fear reroll-button" data-die-index="2" data-type="fear" style="--svg-folder: 'fear';" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}">
|
<div class="dice {{roll.dFear.denomination}} color-fear reroll-button" data-die-index="1" data-type="fear" style="--svg-folder: 'fear';" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}">
|
||||||
{{#if roll.fear.rerolled.any}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.UI.Tooltip.diceIsRerolled" times=roll.fear.rerolled.rerolls.length}}"></i>{{/if}}
|
{{#if roll.dFear.rerolled.any}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.UI.Tooltip.diceIsRerolled" times=roll.dFear.rerolled.rerolls.length}}"></i>{{/if}}
|
||||||
{{roll.fear.value}}
|
{{roll.dFear.total}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{#if roll.advantage.type}}
|
{{#if roll.dAdvantage}}
|
||||||
<div class="roll-die has-plus">
|
<div class="roll-die has-plus">
|
||||||
{{#if (eq roll.advantage.type 1)}}
|
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.Advantage.short"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.Advantage.short"}}</label>
|
||||||
<div class="dice {{roll.advantage.dice}} color-adv">{{roll.advantage.value}}</div>
|
<div class="dice {{roll.dAdvantage.denomination}} color-adv">{{roll.dAdvantage.total}}</div>
|
||||||
{{else}}
|
</div>
|
||||||
|
{{else if roll.dDisadvantage}}
|
||||||
|
<div class="roll-die has-minus">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.Disadvantage.short"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.Disadvantage.short"}}</label>
|
||||||
<div class="dice {{roll.advantage.dice}} color-dis">{{roll.advantage.value}}</div>
|
<div class="dice {{roll.dDisadvantage.denomination}} color-dis">{{roll.dDisadvantage.total}}</div>
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if roll.rally.dice}}
|
{{#if roll.rally.dice}}
|
||||||
|
|
@ -79,15 +79,11 @@
|
||||||
<div class="dice {{roll.rally.dice}}">{{roll.rally.value}}</div>
|
<div class="dice {{roll.rally.dice}}">{{roll.rally.value}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#each roll.extra}}
|
{{#each roll.extraDice}}
|
||||||
{{#each results}}
|
|
||||||
{{#unless discarded}}
|
|
||||||
<div class="roll-die has-plus">
|
<div class="roll-die has-plus">
|
||||||
<label></label>
|
<label></label>
|
||||||
<div class="dice {{../dice}}">{{result}}</div>
|
<div class="dice {{this.denomination}}">{{this.total}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
|
||||||
{{/each}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#each roll.dice}}
|
{{#each roll.dice}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue