mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
Merge fae7efd023 into 0b343c9f52
This commit is contained in:
commit
54b0cda45a
20 changed files with 647 additions and 155 deletions
|
|
@ -8,8 +8,9 @@ import * as fields from './module/data/fields/_module.mjs';
|
||||||
import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
|
import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
|
||||||
import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs';
|
import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs';
|
||||||
import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs';
|
import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs';
|
||||||
import { BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll } from './module/dice/_module.mjs';
|
import { BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll } from './module/dice/_module.mjs';
|
||||||
import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs';
|
import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs';
|
||||||
|
import { enrichedFateRoll, getFateType } from './module/enrichers/FateRollEnricher.mjs';
|
||||||
import {
|
import {
|
||||||
handlebarsRegistration,
|
handlebarsRegistration,
|
||||||
runMigrations,
|
runMigrations,
|
||||||
|
|
@ -23,12 +24,13 @@ import TemplateManager from './module/documents/templateManager.mjs';
|
||||||
CONFIG.DH = SYSTEM;
|
CONFIG.DH = SYSTEM;
|
||||||
CONFIG.TextEditor.enrichers.push(...enricherConfig);
|
CONFIG.TextEditor.enrichers.push(...enricherConfig);
|
||||||
|
|
||||||
CONFIG.Dice.rolls = [BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll];
|
CONFIG.Dice.rolls = [BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll];
|
||||||
CONFIG.Dice.daggerheart = {
|
CONFIG.Dice.daggerheart = {
|
||||||
DHRoll: DHRoll,
|
DHRoll: DHRoll,
|
||||||
DualityRoll: DualityRoll,
|
DualityRoll: DualityRoll,
|
||||||
D20Roll: D20Roll,
|
D20Roll: D20Roll,
|
||||||
DamageRoll: DamageRoll
|
DamageRoll: DamageRoll,
|
||||||
|
FateRoll: FateRoll
|
||||||
};
|
};
|
||||||
|
|
||||||
CONFIG.Actor.documentClass = documents.DhpActor;
|
CONFIG.Actor.documentClass = documents.DhpActor;
|
||||||
|
|
@ -308,6 +310,38 @@ Hooks.on('chatMessage', (_, message) => {
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.startsWith('/fr')) {
|
||||||
|
const result =
|
||||||
|
message.trim().toLowerCase() === '/fr' ? { result: {} } : rollCommandToJSON(message.replace(/\/fr\s?/, ''));
|
||||||
|
if (!result) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateParsing'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result: rollCommand, flavor } = result;
|
||||||
|
|
||||||
|
const fateTypeFromRollCommand = getFateType(rollCommand?.type);
|
||||||
|
|
||||||
|
if (fateTypeFromRollCommand == "BAD") {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fateType = fateTypeFromRollCommand;
|
||||||
|
|
||||||
|
const target = getCommandTarget({ allowNull: true });
|
||||||
|
const title = fateType + ' Fate Roll';
|
||||||
|
|
||||||
|
enrichedFateRoll({
|
||||||
|
target,
|
||||||
|
title,
|
||||||
|
label: 'test',
|
||||||
|
fateType
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateActorsRangeDependentEffects = async token => {
|
const updateActorsRangeDependentEffects = async token => {
|
||||||
|
|
|
||||||
14
lang/en.json
14
lang/en.json
|
|
@ -1001,15 +1001,15 @@
|
||||||
"DeathMoves": {
|
"DeathMoves": {
|
||||||
"avoidDeath": {
|
"avoidDeath": {
|
||||||
"name": "Avoid Death",
|
"name": "Avoid Death",
|
||||||
"description": "You drop unconscious temporarily and work with the GM to describe how the situation gets much worse because of it. Then roll your Fear die; if its value is equal to or under your Level, take a Scar."
|
"description": "Your character avoids death and faces the consequences. They temporarily drop unconscious, and then you work with the GM to describe how the situation worsens. While unconscious, your character can't move or act, and they can't be targeted by an attack. They return to consciousness when an ally clears 1 or more of their marked Hit Points or when the party finishes a long rest. After your character falls unconscious, roll your Hope Die. If its value is equal to or less than your character's level, they gain a scar: permanently cross out a Hope slot and work with the GM to determine its lasting narrative impact and how, if possible, it can be restored. If you ever cross out your last Hope slot, your character's journey ends."
|
||||||
},
|
},
|
||||||
"riskItAll": {
|
"riskItAll": {
|
||||||
"name": "Risk It All",
|
"name": "Risk It All",
|
||||||
"description": "Roll your Duality Dice. If Hope is higher, you stay on your feet and clear an amount of Hit Points and/or Stress equal to the value of the Hope die (divide the Hope die value up between these however you’d prefer). If your Fear die is higher, you cross through the veil of death. If the Duality Dice are tied, you stay on your feet and clear all Hit Points and Stress."
|
"description": "Roll your Duality Dice. If the Hope Die is higher, your character stays on their feet and clears a number of Hit Points or Stress equal to the value of the Hope Die (you can divide the Hope Die value between Hit Points and Stress however you'd prefer). If the Fear Die is higher, your character crosses through the veil of death. If the Duality Dice show matching results, your character stays up and clears all Hit Points and Stress."
|
||||||
},
|
},
|
||||||
"blazeOfGlory": {
|
"blazeOfGlory": {
|
||||||
"name": "Blaze Of Glory",
|
"name": "Blaze Of Glory",
|
||||||
"description": "With Blaze of Glory, the player is accepting death for the character. Take one action (at GM discretion), which becomes an automatic critical success, then cross through the veil of death."
|
"description": " Your character embraces death and goes out in a blaze of glory. Take one final action. It automatically critically succeeds (with GM approval), and then you cross through the veil of death. NOTE: A Blaze of Glory effect has been added to your character. Any Duality Roll will automatically be a critical."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DomainCardTypes": {
|
"DomainCardTypes": {
|
||||||
|
|
@ -2109,11 +2109,14 @@
|
||||||
"plural": "Experiences"
|
"plural": "Experiences"
|
||||||
},
|
},
|
||||||
"failure": "Failure",
|
"failure": "Failure",
|
||||||
|
"fate": "Fate",
|
||||||
|
"fateRoll": "Fate Roll",
|
||||||
"fear": "Fear",
|
"fear": "Fear",
|
||||||
"features": "Features",
|
"features": "Features",
|
||||||
"formula": "Formula",
|
"formula": "Formula",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
"gm": "GM",
|
"gm": "GM",
|
||||||
|
"guaranteedCriticalSuccess": "Guaranteed Critical Success",
|
||||||
"healing": "Healing",
|
"healing": "Healing",
|
||||||
"healingRoll": "Healing Roll",
|
"healingRoll": "Healing Roll",
|
||||||
"hit": {
|
"hit": {
|
||||||
|
|
@ -2173,6 +2176,7 @@
|
||||||
"rollWith": "{roll} Roll",
|
"rollWith": "{roll} Roll",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"scalable": "Scalable",
|
"scalable": "Scalable",
|
||||||
|
"scars": "Scars",
|
||||||
"situationalBonus": "Situational Bonus",
|
"situationalBonus": "Situational Bonus",
|
||||||
"spent": "Spent",
|
"spent": "Spent",
|
||||||
"step": "Step",
|
"step": "Step",
|
||||||
|
|
@ -2720,7 +2724,9 @@
|
||||||
"noAssignedPlayerCharacter": "You have no assigned character.",
|
"noAssignedPlayerCharacter": "You have no assigned character.",
|
||||||
"noSelectedToken": "You have no selected token",
|
"noSelectedToken": "You have no selected token",
|
||||||
"onlyUseableByPC": "This can only be used with a PC token",
|
"onlyUseableByPC": "This can only be used with a PC token",
|
||||||
"dualityParsing": "Duality roll not properly formated",
|
"dualityParsing": "Duality roll not properly formatted",
|
||||||
|
"fateParsing": "Fate roll not properly formatted",
|
||||||
|
"fateTypeParsing": "Fate roll not properly formatted, bad fate type. Valid types are 'Hope' and 'Fear'",
|
||||||
"attributeFaulty": "The supplied Attribute doesn't exist",
|
"attributeFaulty": "The supplied Attribute doesn't exist",
|
||||||
"domainCardWrongDomain": "You don't have access to that Domain",
|
"domainCardWrongDomain": "You don't have access to that Domain",
|
||||||
"domainCardToHighLevel": "The Domain Card is too high level to be selected",
|
"domainCardToHighLevel": "The Domain Card is too high level to be selected",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
import { enrichedFateRoll } from '../../enrichers/FateRollEnricher.mjs';
|
||||||
|
import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs';
|
||||||
|
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
export default class DhpDeathMove extends HandlebarsApplicationMixin(ApplicationV2) {
|
export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
constructor(actor) {
|
constructor(actor) {
|
||||||
super({});
|
super({});
|
||||||
|
|
||||||
|
|
@ -38,6 +42,99 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleAvoidDeath() {
|
||||||
|
const target = this.actor.uuid;
|
||||||
|
const config = await enrichedFateRoll({
|
||||||
|
target,
|
||||||
|
title: "Avoid Death Hope Fate Roll",
|
||||||
|
label: 'test',
|
||||||
|
fateType: "Hope"
|
||||||
|
});
|
||||||
|
if (config.roll.fate.value <= this.actor.system.levelData.level.current) {
|
||||||
|
// apply scarring - for now directly apply - later add a button.
|
||||||
|
const newScarAmount = this.actor.system.scars + 1;
|
||||||
|
|
||||||
|
await this.actor.update(
|
||||||
|
{
|
||||||
|
system: {
|
||||||
|
scars: newScarAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearAllStressAndHitpoints() {
|
||||||
|
await this.actor.update(
|
||||||
|
{
|
||||||
|
system: {
|
||||||
|
resources: {
|
||||||
|
hitPoints: {
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
stress: {
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleRiskItAll() {
|
||||||
|
const config = await enrichedDualityRoll({
|
||||||
|
reaction: true,
|
||||||
|
traitValue: null,
|
||||||
|
target: null,
|
||||||
|
difficulty: null,
|
||||||
|
title: "Risk It All",
|
||||||
|
label: 'test',
|
||||||
|
actionType: null,
|
||||||
|
advantage: null
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.roll.isCritical) {
|
||||||
|
console.log("Clear all stress and HP");
|
||||||
|
this.clearAllStressAndHitpoints();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hope
|
||||||
|
if (config.roll.result.duality == 1) {
|
||||||
|
console.log("Need to clear up Stress and HP up to hope value");
|
||||||
|
console.log("Hope rolled", config.roll.hope.value);
|
||||||
|
if (config.roll.hope.value >= (this.actor.system.resources.hitPoints.value + this.actor.system.resources.stress.value)) {
|
||||||
|
console.log("Hope roll value is more than the HP + Stress, auto- remove");
|
||||||
|
this.clearAllStressAndHitpoints();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fear
|
||||||
|
if (config.roll.result.duality == -1) {
|
||||||
|
console.log("You have died...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleBlazeOfGlory() {
|
||||||
|
this.actor.createEmbeddedDocuments('ActiveEffect', [
|
||||||
|
{
|
||||||
|
name: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'),
|
||||||
|
description: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.description'),
|
||||||
|
img: CONFIG.DH.GENERAL.deathMoves.blazeOfGlory.img,
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
key: 'system.rules.roll.guaranteedCritical',
|
||||||
|
mode: 2,
|
||||||
|
value: "true"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
static selectMove(_, button) {
|
static selectMove(_, button) {
|
||||||
const move = button.dataset.move;
|
const move = button.dataset.move;
|
||||||
this.selectedMove = CONFIG.DH.GENERAL.deathMoves[move];
|
this.selectedMove = CONFIG.DH.GENERAL.deathMoves[move];
|
||||||
|
|
@ -46,6 +143,10 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
|
||||||
}
|
}
|
||||||
|
|
||||||
static async takeMove() {
|
static async takeMove() {
|
||||||
|
const autoExpandDescription = game.settings.get(
|
||||||
|
CONFIG.DH.id,
|
||||||
|
CONFIG.DH.SETTINGS.gameSettings.appearance
|
||||||
|
).expandRollMessage?.desc;
|
||||||
const cls = getDocumentClass('ChatMessage');
|
const cls = getDocumentClass('ChatMessage');
|
||||||
const msg = {
|
const msg = {
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
|
|
@ -57,7 +158,9 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
|
||||||
author: game.users.get(game.user.id),
|
author: game.users.get(game.user.id),
|
||||||
title: game.i18n.localize(this.selectedMove.name),
|
title: game.i18n.localize(this.selectedMove.name),
|
||||||
img: this.selectedMove.img,
|
img: this.selectedMove.img,
|
||||||
description: game.i18n.localize(this.selectedMove.description)
|
description: game.i18n.localize(this.selectedMove.description),
|
||||||
|
open: autoExpandDescription ? 'open' : '',
|
||||||
|
chevron: autoExpandDescription ? 'fa-chevron-up' : 'fa-chevron-down'
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
title: game.i18n.localize(
|
title: game.i18n.localize(
|
||||||
|
|
@ -74,5 +177,21 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
|
||||||
cls.create(msg);
|
cls.create(msg);
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
|
|
||||||
|
if (CONFIG.DH.GENERAL.deathMoves.avoidDeath === this.selectedMove) {
|
||||||
|
this.handleAvoidDeath();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG.DH.GENERAL.deathMoves.riskItAll === this.selectedMove) {
|
||||||
|
this.handleRiskItAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG.DH.GENERAL.deathMoves.blazeOfGlory === this.selectedMove) {
|
||||||
|
this.handleBlazeOfGlory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import DHBaseActorSheet from '../api/base-actor.mjs';
|
import DHBaseActorSheet from '../api/base-actor.mjs';
|
||||||
import DhpDeathMove from '../../dialogs/deathMove.mjs';
|
import DhDeathMove from '../../dialogs/deathMove.mjs';
|
||||||
import { abilities } from '../../../config/actorConfig.mjs';
|
import { abilities } from '../../../config/actorConfig.mjs';
|
||||||
import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs';
|
import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs';
|
||||||
import DhCharacterCreation from '../../characterCreation/characterCreation.mjs';
|
import DhCharacterCreation from '../../characterCreation/characterCreation.mjs';
|
||||||
|
|
@ -666,7 +666,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
* @type {ApplicationClickAction}
|
* @type {ApplicationClickAction}
|
||||||
*/
|
*/
|
||||||
static async #makeDeathMove() {
|
static async #makeDeathMove() {
|
||||||
await new DhpDeathMove(this.document).render({ force: true });
|
await new DhDeathMove(this.document).render({ force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -78,12 +78,7 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
bags: new fields.NumberField({ initial: 0, integer: true }),
|
bags: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
chests: new fields.NumberField({ initial: 0, integer: true })
|
chests: new fields.NumberField({ initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
scars: new fields.TypedObjectField(
|
scars: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.scars' }),
|
||||||
new fields.SchemaField({
|
|
||||||
name: new fields.StringField({}),
|
|
||||||
description: new fields.StringField()
|
|
||||||
})
|
|
||||||
),
|
|
||||||
biography: new fields.SchemaField({
|
biography: new fields.SchemaField({
|
||||||
background: new fields.HTMLField(),
|
background: new fields.HTMLField(),
|
||||||
connections: new fields.HTMLField(),
|
connections: new fields.HTMLField(),
|
||||||
|
|
@ -283,6 +278,9 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
runeWard: new fields.BooleanField({ initial: false }),
|
runeWard: new fields.BooleanField({ initial: false }),
|
||||||
burden: new fields.SchemaField({
|
burden: new fields.SchemaField({
|
||||||
ignore: new fields.BooleanField()
|
ignore: new fields.BooleanField()
|
||||||
|
}),
|
||||||
|
roll: new fields.SchemaField({
|
||||||
|
guaranteedCritical: new fields.BooleanField()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
@ -624,7 +622,7 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
? armor.system.baseThresholds.severe + this.levelData.level.current
|
? armor.system.baseThresholds.severe + this.levelData.level.current
|
||||||
: this.levelData.level.current * 2
|
: this.levelData.level.current * 2
|
||||||
};
|
};
|
||||||
this.resources.hope.max -= Object.keys(this.scars).length;
|
this.resources.hope.max -= this.scars;
|
||||||
this.resources.hitPoints.max += this.class.value?.system?.hitPoints ?? 0;
|
this.resources.hitPoints.max += this.class.value?.system?.hitPoints ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -696,4 +694,9 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
t => !!t
|
t => !!t
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static migrateData(source) {
|
||||||
|
if (typeof (source.scars) === 'object') source.scars = 0;
|
||||||
|
return super.migrateData(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export const config = {
|
||||||
adversaryRoll: DHActorRoll,
|
adversaryRoll: DHActorRoll,
|
||||||
damageRoll: DHActorRoll,
|
damageRoll: DHActorRoll,
|
||||||
dualityRoll: DHActorRoll,
|
dualityRoll: DHActorRoll,
|
||||||
|
fateRoll: DHActorRoll,
|
||||||
groupRoll: DHGroupRoll,
|
groupRoll: DHGroupRoll,
|
||||||
systemMessage: DHSystemMessage
|
systemMessage: DHSystemMessage
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ export { default as D20Roll } from './d20Roll.mjs';
|
||||||
export { default as DamageRoll } from './damageRoll.mjs';
|
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';
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
constructor(formula, data = {}, options = {}) {
|
constructor(formula, data = {}, options = {}) {
|
||||||
super(formula, data, options);
|
super(formula, data, options);
|
||||||
this.rallyChoices = this.setRallyChoices();
|
this.rallyChoices = this.setRallyChoices();
|
||||||
|
this.guaranteedCritical = options.guaranteedCritical;
|
||||||
}
|
}
|
||||||
|
|
||||||
static messageType = 'dualityRoll';
|
static messageType = 'dualityRoll';
|
||||||
|
|
@ -25,29 +26,23 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
get dHope() {
|
get dHope() {
|
||||||
// if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return;
|
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
return this.dice[0];
|
return this.dice[0];
|
||||||
// return this.#hopeDice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set dHope(faces) {
|
set dHope(faces) {
|
||||||
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
this.terms[0].faces = this.getFaces(faces);
|
this.dice[0].faces = this.getFaces(faces);
|
||||||
// this.#hopeDice = `d${face}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get dFear() {
|
get dFear() {
|
||||||
// if ( !(this.terms[1] instanceof foundry.dice.terms.Die) ) return;
|
|
||||||
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
return this.dice[1];
|
return this.dice[1];
|
||||||
// return this.#fearDice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set dFear(faces) {
|
set dFear(faces) {
|
||||||
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
this.dice[1].faces = this.getFaces(faces);
|
this.dice[1].faces = this.getFaces(faces);
|
||||||
// this.#fearDice = `d${face}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get dAdvantage() {
|
get dAdvantage() {
|
||||||
|
|
@ -90,26 +85,27 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
get isCritical() {
|
get isCritical() {
|
||||||
|
if (this.guaranteedCritical) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!this.dHope._evaluated || !this.dFear._evaluated) return;
|
if (!this.dHope._evaluated || !this.dFear._evaluated) return;
|
||||||
return this.dHope.total === this.dFear.total;
|
return this.dHope.total === this.dFear.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
get withHope() {
|
get withHope() {
|
||||||
if (!this._evaluated) return;
|
if (!this._evaluated || this.guaranteedCritical) return;
|
||||||
return this.dHope.total > this.dFear.total;
|
return this.dHope.total > this.dFear.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
get withFear() {
|
get withFear() {
|
||||||
if (!this._evaluated) return;
|
if (!this._evaluated || this.guaranteedCritical) return;
|
||||||
return this.dHope.total < this.dFear.total;
|
return this.dHope.total < this.dFear.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalLabel() {
|
get totalLabel() {
|
||||||
const label = this.withHope
|
const label = this.guaranteedCritical ? 'DAGGERHEART.GENERAL.guaranteedCriticalSuccess' :
|
||||||
? 'DAGGERHEART.GENERAL.hope'
|
this.isCritical ? 'DAGGERHEART.GENERAL.criticalSuccess' :
|
||||||
: this.withFear
|
this.withHope ? 'DAGGERHEART.GENERAL.hope' : 'DAGGERHEART.GENERAL.fear';
|
||||||
? 'DAGGERHEART.GENERAL.fear'
|
|
||||||
: 'DAGGERHEART.GENERAL.criticalSuccess';
|
|
||||||
|
|
||||||
return game.i18n.localize(label);
|
return game.i18n.localize(label);
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +116,9 @@ export default class DualityRoll extends D20Roll {
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
static fromData(data) {
|
static fromData(data) {
|
||||||
|
if (data.options.guaranteedCritical) {
|
||||||
|
console.log("TODO: set the max values for Hope and Fear here?");
|
||||||
|
}
|
||||||
data.terms[0].class = foundry.dice.terms.Die.name;
|
data.terms[0].class = foundry.dice.terms.Die.name;
|
||||||
data.terms[2].class = foundry.dice.terms.Die.name;
|
data.terms[2].class = foundry.dice.terms.Die.name;
|
||||||
return super.fromData(data);
|
return super.fromData(data);
|
||||||
|
|
@ -173,6 +172,23 @@ export default class DualityRoll extends D20Roll {
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async buildConfigure(config = {}, message = {}) {
|
||||||
|
console.log("buildConfigure, config", config);
|
||||||
|
config.dialog ??= {};
|
||||||
|
config.guaranteedCritical = config.data?.parent?.appliedEffects.reduce((a, c) => {
|
||||||
|
const change = c.changes.find(ch => ch.key === 'system.rules.roll.guaranteedCritical');
|
||||||
|
if (change) a = true;
|
||||||
|
return a;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if (config.guaranteedCritical) {
|
||||||
|
config.dialog.configure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.buildConfigure(config, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static async buildEvaluate(roll, config = {}, message = {}) {
|
static async buildEvaluate(roll, config = {}, message = {}) {
|
||||||
await super.buildEvaluate(roll, config, message);
|
await super.buildEvaluate(roll, config, message);
|
||||||
|
|
||||||
|
|
@ -190,7 +206,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
|
|
||||||
data.hope = {
|
data.hope = {
|
||||||
dice: roll.dHope.denomination,
|
dice: roll.dHope.denomination,
|
||||||
value: roll.dHope.total,
|
value: this.guaranteedCritical ? 0 : roll.dHope.total,
|
||||||
rerolled: {
|
rerolled: {
|
||||||
any: roll.dHope.results.some(x => x.rerolled),
|
any: roll.dHope.results.some(x => x.rerolled),
|
||||||
rerolls: roll.dHope.results.filter(x => x.rerolled)
|
rerolls: roll.dHope.results.filter(x => x.rerolled)
|
||||||
|
|
@ -198,7 +214,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
};
|
};
|
||||||
data.fear = {
|
data.fear = {
|
||||||
dice: roll.dFear.denomination,
|
dice: roll.dFear.denomination,
|
||||||
value: roll.dFear.total,
|
value: this.guaranteedCritical ? 0 : roll.dFear.total,
|
||||||
rerolled: {
|
rerolled: {
|
||||||
any: roll.dFear.results.some(x => x.rerolled),
|
any: roll.dFear.results.some(x => x.rerolled),
|
||||||
rerolls: roll.dFear.results.filter(x => x.rerolled)
|
rerolls: roll.dFear.results.filter(x => x.rerolled)
|
||||||
|
|
@ -210,7 +226,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
};
|
};
|
||||||
data.result = {
|
data.result = {
|
||||||
duality: roll.withHope ? 1 : roll.withFear ? -1 : 0,
|
duality: roll.withHope ? 1 : roll.withFear ? -1 : 0,
|
||||||
total: roll.dHope.total + roll.dFear.total,
|
total: this.guaranteedCritical ? 0 : roll.dHope.total + roll.dFear.total,
|
||||||
label: roll.totalLabel
|
label: roll.totalLabel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
101
module/dice/fateRoll.mjs
Normal file
101
module/dice/fateRoll.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
|
||||||
|
import D20Roll from './d20Roll.mjs';
|
||||||
|
import { setDiceSoNiceForHopeFateRoll, setDiceSoNiceForFearFateRoll } from '../helpers/utils.mjs';
|
||||||
|
|
||||||
|
export default class FateRoll extends D20Roll {
|
||||||
|
constructor(formula, data = {}, options = {}) {
|
||||||
|
super(formula, data, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static messageType = 'fateRoll';
|
||||||
|
|
||||||
|
static DefaultDialog = D20RollDialog;
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
return game.i18n.localize(
|
||||||
|
`DAGGERHEART.GENERAL.fateRoll`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get dHope() {
|
||||||
|
// if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return;
|
||||||
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
|
return this.dice[0];
|
||||||
|
// return this.#hopeDice;
|
||||||
|
}
|
||||||
|
|
||||||
|
set dHope(faces) {
|
||||||
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
|
this.dice[0].faces = this.getFaces(faces);
|
||||||
|
// this.#hopeDice = `d${face}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dFear() {
|
||||||
|
// if ( !(this.terms[1] instanceof foundry.dice.terms.Die) ) return;
|
||||||
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
|
return this.dice[0];
|
||||||
|
// return this.#fearDice;
|
||||||
|
}
|
||||||
|
|
||||||
|
set dFear(faces) {
|
||||||
|
if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||||
|
this.dice[0].faces = this.getFaces(faces);
|
||||||
|
// this.#fearDice = `d${face}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isCritical() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get fateDie() {
|
||||||
|
return this.data.fateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getHooks(hooks) {
|
||||||
|
return [...(hooks ?? []), 'Fate'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
static fromData(data) {
|
||||||
|
data.terms[0].class = foundry.dice.terms.Die.name;
|
||||||
|
return super.fromData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
createBaseDice() {
|
||||||
|
if (this.dice[0] instanceof foundry.dice.terms.Die) {
|
||||||
|
this.terms = [this.terms[0]];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.terms[0] = new foundry.dice.terms.Die({ faces: 12 });
|
||||||
|
}
|
||||||
|
|
||||||
|
static async buildEvaluate(roll, config = {}, message = {}) {
|
||||||
|
await super.buildEvaluate(roll, config, message);
|
||||||
|
|
||||||
|
if (roll.fateDie === "Hope") {
|
||||||
|
await setDiceSoNiceForHopeFateRoll(
|
||||||
|
roll,
|
||||||
|
config.roll.fate.dice
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await setDiceSoNiceForFearFateRoll(
|
||||||
|
roll,
|
||||||
|
config.roll.fate.dice
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static postEvaluate(roll, config = {}) {
|
||||||
|
const data = super.postEvaluate(roll, config);
|
||||||
|
|
||||||
|
data.fate = {
|
||||||
|
dice: roll.fateDie === "Hope" ? roll.dHope.denomination : roll.dFear.denomination,
|
||||||
|
value: roll.fateDie === "Hope" ? roll.dHope.total : roll.dFear.total,
|
||||||
|
fateDie: roll.fateDie
|
||||||
|
};
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -87,6 +87,15 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.type === 'fateRoll') {
|
||||||
|
html.classList.add('fate');
|
||||||
|
if (this.system.roll?.fate.fateDie == 'Hope') {
|
||||||
|
html.classList.add('hope');
|
||||||
|
}
|
||||||
|
if (this.system.roll?.fate.fateDie == 'Fear') {
|
||||||
|
html.classList.add('fear');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const autoExpandRoll = game.settings.get(
|
const autoExpandRoll = game.settings.get(
|
||||||
CONFIG.DH.id,
|
CONFIG.DH.id,
|
||||||
|
|
|
||||||
|
|
@ -105,4 +105,5 @@ export const enrichedDualityRoll = async (
|
||||||
config.source = { actor: null };
|
config.source = { actor: null };
|
||||||
await CONFIG.Dice.daggerheart.DualityRoll.build(config);
|
await CONFIG.Dice.daggerheart.DualityRoll.build(config);
|
||||||
}
|
}
|
||||||
|
return config;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
97
module/enrichers/FateRollEnricher.mjs
Normal file
97
module/enrichers/FateRollEnricher.mjs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { getCommandTarget, rollCommandToJSON } from '../helpers/utils.mjs';
|
||||||
|
|
||||||
|
export default function DhFateRollEnricher(match, _options) {
|
||||||
|
const roll = rollCommandToJSON(match[1], match[0]);
|
||||||
|
if (!roll) return match[0];
|
||||||
|
|
||||||
|
const fateTypeFromRoll = getFateType(roll?.type);
|
||||||
|
|
||||||
|
if (fateTypeFromRoll == "BAD") {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFateMessage(roll.result, roll?.flavor);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFateType(fateTypeValue) {
|
||||||
|
const fateTypeFromValue = fateTypeValue ?
|
||||||
|
(fateTypeValue.toLowerCase() == "fear" ? "Fear" :
|
||||||
|
(fateTypeValue.toLowerCase() == "hope" ? "Hope" : "BAD")) : "Hope";
|
||||||
|
|
||||||
|
|
||||||
|
return fateTypeFromValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFateMessage(roll, flavor) {
|
||||||
|
const fateType = getFateType(roll?.type);
|
||||||
|
|
||||||
|
if (fateType == "BAD") {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing'));
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const fateTypeLocalized = fateType === "Hope" ? game.i18n.localize("DAGGERHEART.GENERAL.hope") : game.i18n.localize("DAGGERHEART.GENERAL.fear");
|
||||||
|
|
||||||
|
const title = flavor ?? fateTypeLocalized + ' ' +
|
||||||
|
game.i18n.localize('DAGGERHEART.GENERAL.fate') + ' ' +
|
||||||
|
game.i18n.localize('DAGGERHEART.GENERAL.roll');
|
||||||
|
|
||||||
|
const dataLabel = game.i18n.localize('DAGGERHEART.GENERAL.fate');
|
||||||
|
|
||||||
|
const fateElement = document.createElement('span');
|
||||||
|
fateElement.innerHTML = `
|
||||||
|
<button type="button" class="fate-roll-button${roll?.inline ? ' inline' : ''}"
|
||||||
|
data-title="${title}"
|
||||||
|
data-label="${dataLabel}"
|
||||||
|
data-fateType="${fateType}"
|
||||||
|
>
|
||||||
|
${title}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return fateElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const renderFateButton = async event => {
|
||||||
|
const button = event.currentTarget,
|
||||||
|
target = getCommandTarget({ allowNull: true });
|
||||||
|
console.log("button", button);
|
||||||
|
|
||||||
|
const fateTypeFromButton = getFateType(button.dataset?.fatetype);
|
||||||
|
|
||||||
|
if (fateTypeFromButton == "BAD") {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await enrichedFateRoll(
|
||||||
|
{
|
||||||
|
target,
|
||||||
|
title: button.dataset.title,
|
||||||
|
label: button.dataset.label,
|
||||||
|
fateType: fateTypeFromButton
|
||||||
|
},
|
||||||
|
event
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const enrichedFateRoll = async (
|
||||||
|
{ target, title, label, fateType },
|
||||||
|
event
|
||||||
|
) => {
|
||||||
|
const config = {
|
||||||
|
event: event ?? {},
|
||||||
|
title: title,
|
||||||
|
roll: {
|
||||||
|
label: label,
|
||||||
|
},
|
||||||
|
hasRoll: true,
|
||||||
|
fateType: fateType
|
||||||
|
};
|
||||||
|
|
||||||
|
config.data = { experiences: {}, traits: {}, fateType: fateType };
|
||||||
|
config.source = { actor: target?.uuid };
|
||||||
|
await CONFIG.Dice.daggerheart.FateRoll.build(config);
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { default as DhDamageEnricher, renderDamageButton } from './DamageEnricher.mjs';
|
import { default as DhDamageEnricher, renderDamageButton } from './DamageEnricher.mjs';
|
||||||
import { default as DhDualityRollEnricher, renderDualityButton } from './DualityRollEnricher.mjs';
|
import { default as DhDualityRollEnricher, renderDualityButton } from './DualityRollEnricher.mjs';
|
||||||
|
import { default as DhFateRollEnricher, renderFateButton } from './FateRollEnricher.mjs';
|
||||||
import { default as DhEffectEnricher } from './EffectEnricher.mjs';
|
import { default as DhEffectEnricher } from './EffectEnricher.mjs';
|
||||||
import { default as DhTemplateEnricher, renderMeasuredTemplate } from './TemplateEnricher.mjs';
|
import { default as DhTemplateEnricher, renderMeasuredTemplate } from './TemplateEnricher.mjs';
|
||||||
import { default as DhLookupEnricher } from './LookupEnricher.mjs';
|
import { default as DhLookupEnricher } from './LookupEnricher.mjs';
|
||||||
|
|
||||||
export { DhDamageEnricher, DhDualityRollEnricher, DhEffectEnricher, DhTemplateEnricher };
|
export { DhDamageEnricher, DhDualityRollEnricher, DhEffectEnricher, DhTemplateEnricher, DhFateRollEnricher };
|
||||||
|
|
||||||
export const enricherConfig = [
|
export const enricherConfig = [
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +16,10 @@ export const enricherConfig = [
|
||||||
pattern: /\[\[\/dr\s?(.*?)\]\]({[^}]*})?/g,
|
pattern: /\[\[\/dr\s?(.*?)\]\]({[^}]*})?/g,
|
||||||
enricher: DhDualityRollEnricher
|
enricher: DhDualityRollEnricher
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
pattern: /\[\[\/fr\s?(.*?)\]\]({[^}]*})?/g,
|
||||||
|
enricher: DhFateRollEnricher
|
||||||
|
},
|
||||||
{
|
{
|
||||||
pattern: /@Effect\[([^\[\]]*)\]({[^}]*})?/g,
|
pattern: /@Effect\[([^\[\]]*)\]({[^}]*})?/g,
|
||||||
enricher: DhEffectEnricher
|
enricher: DhEffectEnricher
|
||||||
|
|
@ -38,6 +43,10 @@ export const enricherRenderSetup = element => {
|
||||||
.querySelectorAll('.duality-roll-button')
|
.querySelectorAll('.duality-roll-button')
|
||||||
.forEach(element => element.addEventListener('click', renderDualityButton));
|
.forEach(element => element.addEventListener('click', renderDualityButton));
|
||||||
|
|
||||||
|
element
|
||||||
|
.querySelectorAll('.fate-roll-button')
|
||||||
|
.forEach(element => element.addEventListener('click', renderFateButton));
|
||||||
|
|
||||||
element
|
element
|
||||||
.querySelectorAll('.measured-template-button')
|
.querySelectorAll('.measured-template-button')
|
||||||
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
|
.forEach(element => element.addEventListener('click', renderMeasuredTemplate));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { diceTypes, getDiceSoNicePresets, range } from '../config/generalConfig.mjs';
|
import { diceTypes, getDiceSoNicePresets, getDiceSoNicePreset, range } from '../config/generalConfig.mjs';
|
||||||
import Tagify from '@yaireo/tagify';
|
import Tagify from '@yaireo/tagify';
|
||||||
|
|
||||||
export const capitalize = string => {
|
export const capitalize = string => {
|
||||||
|
|
@ -69,6 +69,20 @@ export const setDiceSoNiceForDualityRoll = async (rollResult, advantageState, ho
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setDiceSoNiceForHopeFateRoll = async (rollResult, hopeFaces) => {
|
||||||
|
if (!game.modules.get('dice-so-nice')?.active) return;
|
||||||
|
const { diceSoNice } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance);
|
||||||
|
const diceSoNicePresets = await getDiceSoNicePreset(diceSoNice.hope, hopeFaces);
|
||||||
|
rollResult.dice[0].options = diceSoNicePresets;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setDiceSoNiceForFearFateRoll = async (rollResult, fearFaces) => {
|
||||||
|
if (!game.modules.get('dice-so-nice')?.active) return;
|
||||||
|
const { diceSoNice } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance);
|
||||||
|
const diceSoNicePresets = await getDiceSoNicePreset(diceSoNice.fear, fearFaces);
|
||||||
|
rollResult.dice[0].options = diceSoNicePresets;
|
||||||
|
};
|
||||||
|
|
||||||
export const chunkify = (array, chunkSize, mappingFunc) => {
|
export const chunkify = (array, chunkSize, mappingFunc) => {
|
||||||
var chunkifiedArray = [];
|
var chunkifiedArray = [];
|
||||||
for (let i = 0; i < array.length; i += chunkSize) {
|
for (let i = 0; i < array.length; i += chunkSize) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
.measured-template-button,
|
.measured-template-button,
|
||||||
.enriched-damage-button,
|
.enriched-damage-button,
|
||||||
|
.fate-roll-button,
|
||||||
.duality-roll-button {
|
.duality-roll-button {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
color: @dark;
|
color: @dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.fate,
|
||||||
&.duality {
|
&.duality {
|
||||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||||
|
|
||||||
|
|
@ -66,6 +67,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.fate,
|
||||||
&.critical {
|
&.critical {
|
||||||
--text-color: @chat-purple;
|
--text-color: @chat-purple;
|
||||||
--bg-color: @chat-purple-40;
|
--bg-color: @chat-purple-40;
|
||||||
|
|
@ -80,7 +82,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.duality) {
|
&:not(.duality .fate) {
|
||||||
.font-20 {
|
.font-20 {
|
||||||
color: @dark;
|
color: @dark;
|
||||||
}
|
}
|
||||||
|
|
@ -173,6 +175,28 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.fate {
|
||||||
|
|
||||||
|
&.hope {
|
||||||
|
--text-color: @golden;
|
||||||
|
--bg-color: @golden-40;
|
||||||
|
.message-header,
|
||||||
|
.message-content {
|
||||||
|
background-color: @golden-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fear {
|
||||||
|
--text-color: @chat-blue;
|
||||||
|
--bg-color: @chat-blue-40;
|
||||||
|
.message-header,
|
||||||
|
.message-content {
|
||||||
|
background-color: @chat-blue-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
&.duality {
|
&.duality {
|
||||||
&.hope {
|
&.hope {
|
||||||
--text-color: @golden;
|
--text-color: @golden;
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@
|
||||||
},
|
},
|
||||||
"ChatMessage": {
|
"ChatMessage": {
|
||||||
"dualityRoll": {},
|
"dualityRoll": {},
|
||||||
|
"fateRoll": {},
|
||||||
"adversaryRoll": {},
|
"adversaryRoll": {},
|
||||||
"damageRoll": {},
|
"damageRoll": {},
|
||||||
"abilityUse": {},
|
"abilityUse": {},
|
||||||
|
|
|
||||||
|
|
@ -68,82 +68,115 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if (eq @root.rollType 'FateRoll')}}
|
||||||
|
{{#if (eq @root.roll.fateDie 'Hope')}}
|
||||||
|
|
||||||
|
<div class="dice-option">
|
||||||
|
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/hope/' @root.roll.dHope.denomination '.svg'}}" alt="">
|
||||||
|
<div class="dice-select">
|
||||||
|
<span class="label">{{localize "DAGGERHEART.GENERAL.hope"}}</span>
|
||||||
|
<select name="roll.dice.dHope">
|
||||||
|
{{selectOptions diceOptions selected=@root.roll.dHope.denomination}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (eq @root.roll.fateDie 'Fear')}}
|
||||||
|
<div class="dice-option">
|
||||||
|
<img class="dice-icon" src="{{concat 'systems/daggerheart/assets/icons/dice/fear/' @root.roll.dFear.denomination '.svg'}}" alt="">
|
||||||
|
<div class="dice-select">
|
||||||
|
<span class="label">{{localize "DAGGERHEART.GENERAL.fear"}}</span>
|
||||||
|
<select name="roll.dice.dFear">
|
||||||
|
{{selectOptions diceOptions selected=@root.roll.dFear.denomination}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if experiences.length}}
|
{{#if (ne @root.rollType 'FateRoll')}}
|
||||||
<fieldset class="experience-container">
|
|
||||||
<legend>{{localize "DAGGERHEART.GENERAL.experience.plural"}}</legend>
|
|
||||||
{{#each experiences}}
|
|
||||||
{{#if name}}
|
|
||||||
<div class="experience-chip {{#if (includes ../selectedExperiences id)}}selected{{/if}}" data-action="selectExperience" data-key="{{id}}" data-tooltip="{{this.description}}">
|
|
||||||
<span><i class="{{ifThen (includes ../selectedExperiences id) "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
|
||||||
<span class="label">{{name}} +{{value}}</span>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
</fieldset>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<fieldset class="modifier-container {{#if (eq @root.rollType 'DualityRoll')}}two-columns{{else}}one-column{{/if}}">
|
{{#if experiences.length}}
|
||||||
<legend>{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}</legend>
|
<fieldset class="experience-container">
|
||||||
<div class="nest-inputs">
|
<legend>{{localize "DAGGERHEART.GENERAL.experience.plural"}}</legend>
|
||||||
<button class="advantage-chip flex1 {{#if (eq advantage 1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="1">
|
{{#each experiences}}
|
||||||
{{#if (eq advantage 1)}}
|
{{#if name}}
|
||||||
<span><i class="fa-solid fa-circle"></i></span>
|
<div class="experience-chip {{#if (includes ../selectedExperiences id)}}selected{{/if}}" data-action="selectExperience" data-key="{{id}}" data-tooltip="{{this.description}}">
|
||||||
{{else}}
|
<span><i class="{{ifThen (includes ../selectedExperiences id) "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
||||||
<span><i class="fa-regular fa-circle"></i></span>
|
<span class="label">{{name}} +{{value}}</span>
|
||||||
{{/if}}
|
</div>
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.Advantage.full"}}</span>
|
{{/if}}
|
||||||
{{#if @root.rollConfig.data.advantageSources.length}}
|
{{/each}}
|
||||||
<span class="advantage-chip-tooltip" data-tooltip="{{concat "#advantage#" @root.rollConfig.source.actor}}"><i class="fa-solid fa-circle-info"></i></span>
|
</fieldset>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</button>
|
<fieldset class="modifier-container {{#if (eq @root.rollType 'DualityRoll')}}two-columns{{else}}one-column{{/if}}">
|
||||||
<button class="disadvantage-chip flex1 {{#if (eq advantage -1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="-1">
|
{{#if @root.advantage}}
|
||||||
{{#if (eq advantage -1)}}
|
<legend>{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}</legend>
|
||||||
<span><i class="fa-solid fa-circle"></i></span>
|
|
||||||
{{else}}
|
|
||||||
<span><i class="fa-regular fa-circle"></i></span>
|
|
||||||
{{/if}}
|
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
|
||||||
{{#if @root.rollConfig.data.disadvantageSources.length}}
|
|
||||||
<span class="advantage-chip-tooltip" data-tooltip="{{concat "#disadvantage#" @root.rollConfig.source.actor}}"><i class="fa-solid fa-circle-info"></i></span>
|
|
||||||
{{/if}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{{#unless (eq @root.rollType 'D20Roll')}}
|
|
||||||
<div class="nest-inputs">
|
<div class="nest-inputs">
|
||||||
<select name="roll.dice.advantageNumber"{{#unless advantage}} disabled{{/unless}}>
|
<button class="advantage-chip flex1 {{#if (eq advantage 1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="1">
|
||||||
{{#times 10}}
|
{{#if (eq advantage 1)}}
|
||||||
<option value="{{add this 1}}" {{#if (eq @root.roll.advantageNumber (add this 1))}} selected{{/if}}>{{add this 1}}</option>
|
<span><i class="fa-solid fa-circle"></i></span>
|
||||||
{{/times}}
|
{{else}}
|
||||||
</select>
|
<span><i class="fa-regular fa-circle"></i></span>
|
||||||
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
{{/if}}
|
||||||
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
<span class="label">{{localize "DAGGERHEART.GENERAL.Advantage.full"}}</span>
|
||||||
</select>
|
{{#if @root.rollConfig.data.advantageSources.length}}
|
||||||
|
<span class="advantage-chip-tooltip" data-tooltip="{{concat "#advantage#" @root.rollConfig.source.actor}}"><i class="fa-solid fa-circle-info"></i></span>
|
||||||
|
{{/if}}
|
||||||
|
</button>
|
||||||
|
<button class="disadvantage-chip flex1 {{#if (eq advantage -1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="-1">
|
||||||
|
{{#if (eq advantage -1)}}
|
||||||
|
<span><i class="fa-solid fa-circle"></i></span>
|
||||||
|
{{else}}
|
||||||
|
<span><i class="fa-regular fa-circle"></i></span>
|
||||||
|
{{/if}}
|
||||||
|
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
||||||
|
{{#if @root.rollConfig.data.disadvantageSources.length}}
|
||||||
|
<span class="advantage-chip-tooltip" data-tooltip="{{concat "#disadvantage#" @root.rollConfig.source.actor}}"><i class="fa-solid fa-circle-info"></i></span>
|
||||||
|
{{/if}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{{#if abilities}}
|
{{#unless (eq @root.rollType 'D20Roll')}}
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.traitModifier"}}</span>
|
<div class="nest-inputs">
|
||||||
<select name="trait">
|
<select name="roll.dice.advantageNumber"{{#unless advantage}} disabled{{/unless}}>
|
||||||
{{selectOptions abilities selected=@root.rollConfig.roll.trait valueAttr="id" labelAttr="label" blank="" localize=true}}
|
{{#times 10}}
|
||||||
|
<option value="{{add this 1}}" {{#if (eq @root.roll.advantageNumber (add this 1))}} selected{{/if}}>{{add this 1}}</option>
|
||||||
|
{{/times}}
|
||||||
|
</select>
|
||||||
|
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
||||||
|
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{#if abilities}}
|
||||||
|
<span>{{localize "DAGGERHEART.GENERAL.traitModifier"}}</span>
|
||||||
|
<select name="trait">
|
||||||
|
{{selectOptions abilities selected=@root.rollConfig.roll.trait valueAttr="id" labelAttr="label" blank="" localize=true}}
|
||||||
|
</select>
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if @root.rallyDie.length}}
|
||||||
|
<span class="formula-label">{{localize "DAGGERHEART.CLASS.Feature.rallyDice"}}</span>
|
||||||
|
<select name="roll.dice._rallyIndex">
|
||||||
|
{{selectOptions @root.rallyDie blank="" selected=@root.roll._rallyIndex}}
|
||||||
</select>
|
</select>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/unless}}
|
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}}
|
||||||
{{#if @root.rallyDie.length}}
|
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
||||||
<span class="formula-label">{{localize "DAGGERHEART.CLASS.Feature.rallyDice"}}</span>
|
</fieldset>
|
||||||
<select name="roll.dice._rallyIndex">
|
{{/if}}
|
||||||
{{selectOptions @root.rallyDie blank="" selected=@root.roll._rallyIndex}}
|
|
||||||
</select>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}}
|
|
||||||
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
|
||||||
</fieldset>
|
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
{{#if (or costs uses)}}
|
{{#if (or costs uses)}}
|
||||||
{{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}}
|
{{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span>
|
{{#if (ne @root.rollType 'FateRoll')}}
|
||||||
|
<span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="roll-dialog-controls">
|
<div class="roll-dialog-controls">
|
||||||
<select class="roll-mode-select" name="selectedRollMode">
|
<select class="roll-mode-select" name="selectedRollMode">
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<div class="daggerheart chat downtime">
|
<div class="daggerheart chat downtime">
|
||||||
<ul class="downtime-moves-list">
|
<ul class="downtime-moves-list">
|
||||||
<details class="downtime-move">
|
<details class="downtime-move" {{this.open}}>
|
||||||
<summary class="downtime-label">
|
<summary class="downtime-label">
|
||||||
<img class="downtime-image" src="{{this.img}}" />
|
<img class="downtime-image" src="{{this.img}}" />
|
||||||
<div class="header-label">
|
<div class="header-label">
|
||||||
<h2 class="title">{{this.title}}</h2>
|
<h2 class="title">{{this.title}}</h2>
|
||||||
<span class="label">{{localize 'DAGGERHEART.UI.Chat.deathMove.title'}}</span>
|
<span class="label">{{localize 'DAGGERHEART.UI.Chat.deathMove.title'}}</span>
|
||||||
</div>
|
</div>
|
||||||
<i class="fa-solid fa-chevron-down"></i>
|
<i class="fa-solid {{this.chevron}}"></i>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
{{{this.description}}}
|
{{{this.description}}}
|
||||||
|
|
|
||||||
|
|
@ -29,64 +29,86 @@
|
||||||
<div class="dice-tooltip">
|
<div class="dice-tooltip">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="roll-dice">
|
<div class="roll-dice">
|
||||||
{{#if roll.hope}}
|
{{#if roll.fate}}
|
||||||
<div class="roll-die">
|
{{#if (eq roll.fate.fateDie "Hope")}}
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
<div class="roll-die">
|
||||||
<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")}}">
|
<label>{{localize "DAGGERHEART.GENERAL.hope"}}</label>
|
||||||
{{#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}}
|
<div class="dice {{roll.fate.dice}} color-hope" data-die-index="0" data-type="hope">
|
||||||
{{roll.hope.value}}
|
{{roll.fate.value}}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="roll-die has-plus">
|
|
||||||
<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")}}">
|
|
||||||
{{#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}}
|
|
||||||
{{roll.fear.value}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{#if roll.advantage.type}}
|
|
||||||
<div class="roll-die has-plus">
|
|
||||||
{{#if (eq roll.advantage.type 1)}}
|
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.Advantage.short"}}</label>
|
|
||||||
<div class="dice {{roll.advantage.dice}} color-adv">{{roll.advantage.value}}</div>
|
|
||||||
{{else}}
|
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.Disadvantage.short"}}</label>
|
|
||||||
<div class="dice {{roll.advantage.dice}} color-dis">{{roll.advantage.value}}</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{#if roll.rally.dice}}
|
|
||||||
<div class="roll-die has-plus">
|
|
||||||
<label>{{localize "DAGGERHEART.CLASS.Feature.short"}}</label>
|
|
||||||
<div class="dice {{roll.rally.dice}}">{{roll.rally.value}}</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{#each roll.extra}}
|
|
||||||
{{#each results}}
|
|
||||||
{{#unless discarded}}
|
|
||||||
<div class="roll-die has-plus">
|
|
||||||
<label></label>
|
|
||||||
<div class="dice {{../dice}}">{{result}}</div>
|
|
||||||
</div>
|
|
||||||
{{/unless}}
|
|
||||||
{{/each}}
|
|
||||||
{{/each}}
|
|
||||||
{{else}}
|
|
||||||
{{#each roll.dice}}
|
|
||||||
{{#each results}}
|
|
||||||
<div class="roll-die {{#unless (or @../first discarded)}} has-plus{{/unless}}">
|
|
||||||
<div class="dice {{../dice}}{{#if discarded}} discarded{{else}}{{#if (and @../first ../../roll.advantage.type)}}{{#if (eq ../../roll.advantage.type 1)}} color-adv{{else}} color-dis{{/if}}{{/if}}{{#if success}} color-adv{{/if}}{{/if}}">
|
|
||||||
{{result}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq roll.fate.fateDie "Fear")}}
|
||||||
|
<div class="roll-die">
|
||||||
|
<label>{{localize "DAGGERHEART.GENERAL.fear"}}</label>
|
||||||
|
<div class="dice {{roll.fate.dice}} color-fear" data-die-index="0" data-type="fear">
|
||||||
|
{{roll.fate.value}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if roll.hope}}
|
||||||
|
<div class="roll-die">
|
||||||
|
<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")}}">
|
||||||
|
{{#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}}
|
||||||
|
{{roll.hope.value}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="roll-die has-plus">
|
||||||
|
<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")}}">
|
||||||
|
{{#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}}
|
||||||
|
{{roll.fear.value}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#if roll.advantage.type}}
|
||||||
|
<div class="roll-die has-plus">
|
||||||
|
{{#if (eq roll.advantage.type 1)}}
|
||||||
|
<label>{{localize "DAGGERHEART.GENERAL.Advantage.short"}}</label>
|
||||||
|
<div class="dice {{roll.advantage.dice}} color-adv">{{roll.advantage.value}}</div>
|
||||||
|
{{else}}
|
||||||
|
<label>{{localize "DAGGERHEART.GENERAL.Disadvantage.short"}}</label>
|
||||||
|
<div class="dice {{roll.advantage.dice}} color-dis">{{roll.advantage.value}}</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#if roll.rally.dice}}
|
||||||
|
<div class="roll-die has-plus">
|
||||||
|
<label>{{localize "DAGGERHEART.CLASS.Feature.short"}}</label>
|
||||||
|
<div class="dice {{roll.rally.dice}}">{{roll.rally.value}}</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#each roll.extra}}
|
||||||
|
{{#each results}}
|
||||||
|
{{#unless discarded}}
|
||||||
|
<div class="roll-die has-plus">
|
||||||
|
<label></label>
|
||||||
|
<div class="dice {{../dice}}">{{result}}</div>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{/each}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/each}}
|
{{else}}
|
||||||
|
{{#each roll.dice}}
|
||||||
|
{{#each results}}
|
||||||
|
<div class="roll-die {{#unless (or @../first discarded)}} has-plus{{/unless}}">
|
||||||
|
<div class="dice {{../dice}}{{#if discarded}} discarded{{else}}{{#if (and @../first ../../roll.advantage.type)}}{{#if (eq ../../roll.advantage.type 1)}} color-adv{{else}} color-dis{{/if}}{{/if}}{{#if success}} color-adv{{/if}}{{/if}}">
|
||||||
|
{{result}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="roll-formula">{{roll.formula}}</div>
|
{{#if roll.fate}}
|
||||||
|
{{else}}
|
||||||
|
<div class="roll-formula">{{roll.formula}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue