mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
Basic rework to the roll data in messages
This commit is contained in:
parent
e2b13d6717
commit
2664979823
15 changed files with 199 additions and 226 deletions
|
|
@ -35,6 +35,8 @@ CONFIG.Dice.daggerheart = {
|
||||||
FateRoll: FateRoll
|
FateRoll: FateRoll
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CONFIG.Dice.termTypes.DualityDie = dice.diceTypes.DualityDie;
|
||||||
|
|
||||||
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,15 @@ 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}`, { liveRoll: true });
|
||||||
dieIndex,
|
await newRoll._evaluate();
|
||||||
diceType,
|
const rollData = newRoll.toJSON();
|
||||||
false
|
|
||||||
);
|
|
||||||
const rollData = parsedRoll.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 +692,8 @@ 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 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 +704,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 } }
|
||||||
};
|
};
|
||||||
|
|
@ -719,34 +712,34 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
await cls.create(msgData);
|
await cls.create(msgData);
|
||||||
|
|
||||||
/* Handle resource updates from the finished TagTeamRoll */
|
/* Handle resource updates from the finished TagTeamRoll */
|
||||||
const tagTeamData = this.party.system.tagTeam;
|
// const tagTeamData = this.party.system.tagTeam;
|
||||||
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 = mainRoll.options.roll.isCritical || mainRoll.options.roll.result.duality === 1;
|
||||||
if (memberId === tagTeamData.initiator.memberId) {
|
// if (memberId === tagTeamData.initiator.memberId) {
|
||||||
const value = tagTeamData.initiator.cost
|
// const value = tagTeamData.initiator.cost
|
||||||
? rollGivesHope
|
// ? rollGivesHope
|
||||||
? 1 - tagTeamData.initiator.cost
|
// ? 1 - tagTeamData.initiator.cost
|
||||||
: -tagTeamData.initiator.cost
|
// : -tagTeamData.initiator.cost
|
||||||
: 1;
|
// : 1;
|
||||||
resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true });
|
// resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true });
|
||||||
} 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 (mainRoll.options.roll.isCritical)
|
||||||
resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
// resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
||||||
if (mainRoll.options.roll.result.duality === -1) {
|
// 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;
|
||||||
}
|
// }
|
||||||
|
|
||||||
game.actors.get(memberId).modifyResource(resourceUpdates);
|
// game.actors.get(memberId).modifyResource(resourceUpdates);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (fearUpdate.value) {
|
// if (fearUpdate.value) {
|
||||||
mainActor.modifyResource([fearUpdate]);
|
// mainActor.modifyResource([fearUpdate]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/* Fin */
|
/* Fin */
|
||||||
this.cancelRoll({ confirm: false });
|
this.cancelRoll({ confirm: false });
|
||||||
|
|
|
||||||
|
|
@ -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,17 @@ 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.system.roll._evaluate();
|
||||||
|
await message.update({
|
||||||
if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
|
rolls: [message.system.roll.toJSON()]
|
||||||
|
|
||||||
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 { Dice, diceTypes } from './die/_module.mjs';
|
||||||
|
|
|
||||||
|
|
@ -224,42 +224,4 @@ export default class D20Roll extends DHRoll {
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,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
|
||||||
|
|
|
||||||
7
module/dice/die/_module.mjs
Normal file
7
module/dice/die/_module.mjs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import DualityDie from './dualityDie.mjs';
|
||||||
|
|
||||||
|
export const Dice = [DualityDie];
|
||||||
|
|
||||||
|
export const diceTypes = {
|
||||||
|
DualityDie
|
||||||
|
};
|
||||||
51
module/dice/die/dualityDie.mjs
Normal file
51
module/dice/die/dualityDie.mjs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
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) {
|
||||||
|
if (game.modules.get('dice-so-nice')?.active) {
|
||||||
|
/* Dice Customization for the roll */
|
||||||
|
} 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;
|
||||||
|
|
@ -19,6 +17,22 @@ export default class DualityRoll extends D20Roll {
|
||||||
|
|
||||||
static DefaultDialog = D20RollDialog;
|
static DefaultDialog = D20RollDialog;
|
||||||
|
|
||||||
|
/**@inheritdoc */
|
||||||
|
static instantiateAST(ast) {
|
||||||
|
/* First two dice are always the DualityDice */
|
||||||
|
const nodes = CONFIG.Dice.parser.flattenTree(ast);
|
||||||
|
const dieNodes = nodes.filter(x => x.class === 'DiceTerm');
|
||||||
|
if (dieNodes.length > 1) {
|
||||||
|
dieNodes[0].class = 'DualityDie';
|
||||||
|
dieNodes[1].class = 'DualityDie';
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes.map(node => {
|
||||||
|
const cls = foundry.dice.terms[node.class] ?? foundry.dice.terms.RollTerm;
|
||||||
|
return cls.fromParseNode(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get title() {
|
get title() {
|
||||||
return game.i18n.localize(
|
return game.i18n.localize(
|
||||||
`DAGGERHEART.GENERAL.${this.options?.actionType === 'reaction' ? 'reactionRoll' : 'dualityRoll'}`
|
`DAGGERHEART.GENERAL.${this.options?.actionType === 'reaction' ? 'reactionRoll' : 'dualityRoll'}`
|
||||||
|
|
@ -65,6 +79,21 @@ export default class DualityRoll extends D20Roll {
|
||||||
this._advantageNumber = Number(value);
|
this._advantageNumber = Number(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This isn't fullproof, but trying to cover parathetical situations is ridiculously complex */
|
||||||
|
get modifierTotal() {
|
||||||
|
let modifierTotal = 0;
|
||||||
|
for (let i = 0; i < this.terms.length; i++) {
|
||||||
|
if (
|
||||||
|
this.terms[i] instanceof foundry.dice.terms.NumericTerm &&
|
||||||
|
!!this.terms[i - 1] &&
|
||||||
|
this.terms[i - 1] instanceof foundry.dice.terms.OperatorTerm
|
||||||
|
)
|
||||||
|
modifierTotal += Number(`${this.terms[i - 1].operator}${this.terms[i].total}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifierTotal;
|
||||||
|
}
|
||||||
|
|
||||||
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');
|
||||||
|
|
@ -116,24 +145,20 @@ export default class DualityRoll extends D20Roll {
|
||||||
return [...(hooks ?? []), 'Duality'];
|
return [...(hooks ?? []), 'Duality'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
|
||||||
static fromData(data) {
|
|
||||||
data.terms[0].class = foundry.dice.terms.Die.name;
|
|
||||||
data.terms[2].class = foundry.dice.terms.Die.name;
|
|
||||||
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 +396,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 };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,17 +78,9 @@ 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');
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -47,19 +47,19 @@
|
||||||
</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.advantage.type}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue