diff --git a/lang/en.json b/lang/en.json
index ef1e4936..8424336a 100755
--- a/lang/en.json
+++ b/lang/en.json
@@ -747,7 +747,8 @@
},
"GroupRollSelect": {
"title": "Group Roll",
- "mainCharacter": "Main Character",
+ "leader": "Leader",
+ "leaderRoll": "Leader Roll",
"openDialogForAll": "Open Dialog For All",
"startGroupRoll": "Start Group Roll",
"cancelGroupRoll": "Cancel",
diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs
index b5169443..dc24654e 100644
--- a/module/applications/dialogs/groupRollDialog.mjs
+++ b/module/applications/dialogs/groupRollDialog.mjs
@@ -1,3 +1,4 @@
+import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
import Party from '../sheets/actors/party.mjs';
@@ -109,15 +110,19 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
await super._onRender(context, options);
if (this.element.querySelector('.team-container')) return;
- const initializationPart = this.element.querySelector('.initialization-container');
- initializationPart.insertAdjacentHTML('afterend', '
');
- initializationPart.insertAdjacentHTML(
- 'afterend',
- `${game.i18n.localize('Aiding Characters')}
`
- );
- const teamContainer = this.element.querySelector('.team-container');
- for (const memberContainer of this.element.querySelectorAll('.team-member-container'))
- teamContainer.appendChild(memberContainer);
+
+ if (this.tabGroups.application !== this.constructor.PARTS.initialization.id) {
+ const initializationPart = this.element.querySelector('.initialization-container');
+ initializationPart.insertAdjacentHTML('afterend', '');
+ initializationPart.insertAdjacentHTML(
+ 'afterend',
+ `${game.i18n.localize('Aiding Characters')}
`
+ );
+
+ const teamContainer = this.element.querySelector('.team-container');
+ for (const memberContainer of this.element.querySelectorAll('.team-member-container'))
+ teamContainer.appendChild(memberContainer);
+ }
}
async _prepareContext(_options) {
@@ -161,6 +166,12 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
partContext.mainCharacter = this.getRollCharacterData(this.party.system.groupRoll.mainCharacter);
break;
case 'groupRoll':
+ const leader = this.party.system.groupRoll.mainCharacter;
+ partContext.hasRolled =
+ leader?.rollData ||
+ Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some(
+ x => x.successfull !== null
+ );
const { modifierTotal, modifiers } = Object.values(this.party.system.groupRoll.aidingCharacters).reduce(
(acc, curr) => {
const modifier = curr.successfull === true ? 1 : curr.successfull === false ? -1 : null;
@@ -173,15 +184,14 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
},
{ modifierTotal: 0, modifiers: [] }
);
- const mainCharacterTotal = this.party.system.groupRoll.mainCharacter?.rollData
- ? this.party.system.groupRoll.mainCharacter.roll.total
- : null;
+ const mainCharacterTotal = leader?.rollData ? leader.roll.total : null;
partContext.groupRoll = {
- totalLabel: this.party.system.groupRoll.mainCharacter?.rollData
+ totalLabel: leader?.rollData
? game.i18n.format('DAGGERHEART.GENERAL.withThing', {
- thing: this.party.system.groupRoll.mainCharacter.roll.totalLabel
+ thing: leader.roll.totalLabel
})
: null,
+ totalDualityClass: leader?.roll?.isCritical ? 'critical' : leader?.roll?.withHope ? 'hope' : 'fear',
total: mainCharacterTotal + modifierTotal,
mainCharacterTotal,
modifiers
@@ -333,13 +343,10 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
}
//#endregion
- static async #makeRoll(_event, button) {
- const { member } = button.dataset;
-
- const actor = game.actors.find(x => x.id === member);
+ async makeRoll(button, characterData, path) {
+ const actor = game.actors.find(x => x.id === characterData.id);
if (!actor) return;
- const characterData = this.party.system.groupRoll.aidingCharacters[member];
const result = await actor.rollTrait(characterData.rollChoice, {
skips: {
createMessage: true,
@@ -354,36 +361,43 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
delete rollData.options.messageRoll;
this.updatePartyData(
{
- [`system.groupRoll.aidingCharacters.${member}.rollData`]: rollData
+ [path]: rollData
},
this.getUpdatingParts(button)
);
}
- static async #removeRoll(_, button) {
+ static async #makeRoll(_event, button) {
+ const { member } = button.dataset;
+ const character = this.party.system.groupRoll.aidingCharacters[member];
+ this.makeRoll(button, character, `system.groupRoll.aidingCharacters.${member}.rollData`);
+ }
+
+ static async #makeMainCharacterRoll(_event, button) {
+ const character = this.party.system.groupRoll.mainCharacter;
+ this.makeRoll(button, character, 'system.groupRoll.mainCharacter.rollData');
+ }
+
+ async removeRoll(button, path) {
this.updatePartyData(
{
- [`system.groupRoll.aidingCharacters.${button.dataset.member}`]: {
+ [path]: {
rollData: null,
rollChoice: null,
- selected: false
+ selected: false,
+ successfull: null
}
},
this.getUpdatingParts(button)
);
}
- static async #rerollDice(_, button) {
- const { member } = button.dataset;
- this.rerollDice(
- button,
- this.party.system.groupRoll.aidingCharacters[member],
- `system.groupRoll.aidingCharacters.${member}.rollData`
- );
+ static async #removeRoll(_event, button) {
+ this.removeRoll(button, `system.groupRoll.aidingCharacters.${button.dataset.member}`);
}
- static async #rerollMainCharacterDice(_, button) {
- this.rerollDice(button, this.party.system.groupRoll.mainCharacter, `system.groupRoll.mainCharacter.rollData`);
+ static async #removeMainCharacterRoll(_event, button) {
+ this.removeRoll(button, 'system.groupRoll.mainCharacter');
}
async rerollDice(button, data, path) {
@@ -407,42 +421,17 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
);
}
- static async #makeMainCharacterRoll(_event, button) {
- const actor = game.actors.find(x => x.id === this.party.system.groupRoll.mainCharacter.id);
- if (!actor) return;
-
- const characterData = this.party.system.groupRoll.mainCharacter;
- const result = await actor.rollTrait(characterData.rollChoice, {
- skips: {
- createMessage: true,
- resources: true,
- triggers: true
- }
- });
-
- if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
-
- const rollData = result.messageRoll.toJSON();
- delete rollData.options.messageRoll;
- this.updatePartyData(
- {
- [`system.groupRoll.mainCharacter.rollData`]: rollData
- },
- this.getUpdatingParts(button)
+ static async #rerollDice(_, button) {
+ const { member } = button.dataset;
+ this.rerollDice(
+ button,
+ this.party.system.groupRoll.aidingCharacters[member],
+ `system.groupRoll.aidingCharacters.${member}.rollData`
);
}
- static async #removeMainCharacterRoll(_event, button) {
- this.updatePartyData(
- {
- [`system.groupRoll.mainCharacter`]: {
- rollData: null,
- rollChoice: null,
- selected: false
- }
- },
- this.getUpdatingParts(button)
- );
+ static async #rerollMainCharacterDice(_, button) {
+ this.rerollDice(button, this.party.system.groupRoll.mainCharacter, `system.groupRoll.mainCharacter.rollData`);
}
static #markSuccessfull(_event, button) {
@@ -517,6 +506,20 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
await cls.create(msgData);
+ const resourceMap = new ResourceUpdateMap(actor);
+ if (totalRoll.isCritical) {
+ resourceMap.addResources([
+ { key: 'stress', value: -1, total: 1 },
+ { key: 'hope', value: 1, total: 1 }
+ ]);
+ } else if (totalRoll.withHope) {
+ resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]);
+ } else {
+ resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]);
+ }
+
+ resourceMap.updateResources();
+
/* Fin */
this.cancelRoll({ confirm: false });
}
diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs
index 86f57ae5..b7ea9b9f 100644
--- a/module/applications/sheets/actors/party.mjs
+++ b/module/applications/sheets/actors/party.mjs
@@ -116,6 +116,7 @@ export default class Party extends DHBaseActorSheet {
relativeTo: this.document
});
context.tagTeamActive = Boolean(this.document.system.tagTeam.initiator);
+ context.groupRollActive = Boolean(this.document.system.groupRoll.mainCharacter);
}
async _prepareMembersContext(context, _options) {
diff --git a/styles/less/dialog/group-roll-dialog/initialization.less b/styles/less/dialog/group-roll-dialog/initialization.less
index 211495ee..96990339 100644
--- a/styles/less/dialog/group-roll-dialog/initialization.less
+++ b/styles/less/dialog/group-roll-dialog/initialization.less
@@ -1,3 +1,11 @@
+.theme-light .daggerheart.dialog.dh-style.views.group-roll-dialog {
+ .initialization-container .members-container .member-container {
+ .member-name {
+ background-image: url('../assets/parchments/dh-parchment-light.png');
+ }
+ }
+}
+
.daggerheart.dialog.dh-style.views.group-roll-dialog {
.initialization-container {
h2 {
@@ -20,6 +28,17 @@
.member-name {
position: absolute;
+ padding: 0 2px;
+ border: 1px solid;
+ border-radius: 6px;
+ margin-top: 4px;
+ color: light-dark(@dark, @beige);
+ background-image: url('../assets/parchments/dh-parchment-dark.png');
+ }
+
+ img {
+ border-radius: 6px;
+ border: 1px solid light-dark(@dark-blue, @golden);
}
}
}
diff --git a/styles/less/dialog/group-roll-dialog/sheet.less b/styles/less/dialog/group-roll-dialog/sheet.less
index 571d0d38..823f6cbf 100644
--- a/styles/less/dialog/group-roll-dialog/sheet.less
+++ b/styles/less/dialog/group-roll-dialog/sheet.less
@@ -12,6 +12,11 @@
gap: 8px;
flex: 1;
+ &.inactive {
+ opacity: 0.3;
+ pointer-events: none;
+ }
+
.data-container {
display: flex;
flex-direction: column;
@@ -59,9 +64,27 @@
align-items: center;
gap: 8px;
+ &.hope,
+ &.fear,
+ &.critical {
+ color: var(--text-color);
+ }
+
+ &.hope {
+ --text-color: @golden;
+ }
+
+ &.fear {
+ --text-color: @chat-blue;
+ }
+
+ &.critical {
+ --text-color: @chat-purple;
+ }
+
&::before,
&::after {
- color: light-dark(@dark-blue, @golden);
+ color: var(--text-color);
content: '';
flex: 1;
height: 2px;
diff --git a/styles/less/dialog/tag-team-dialog/initialization.less b/styles/less/dialog/tag-team-dialog/initialization.less
index 30676f82..0d16aa3b 100644
--- a/styles/less/dialog/tag-team-dialog/initialization.less
+++ b/styles/less/dialog/tag-team-dialog/initialization.less
@@ -20,6 +20,17 @@
.member-name {
position: absolute;
+ padding: 0 2px;
+ border: 1px solid;
+ border-radius: 6px;
+ margin-top: 4px;
+ color: light-dark(@dark, @beige);
+ background-image: url('../assets/parchments/dh-parchment-dark.png');
+ }
+
+ img {
+ border-radius: 6px;
+ border: 1px solid light-dark(@dark-blue, @golden);
}
}
}
diff --git a/templates/dialogs/groupRollDialog/groupRoll.hbs b/templates/dialogs/groupRollDialog/groupRoll.hbs
index 24f317a2..4b28bc30 100644
--- a/templates/dialogs/groupRollDialog/groupRoll.hbs
+++ b/templates/dialogs/groupRollDialog/groupRoll.hbs
@@ -3,13 +3,17 @@
-
{{groupRoll.total}} {{groupRoll.totalLabel}}
+ {{#if hasRolled}}
{{groupRoll.total}} {{groupRoll.totalLabel}}{{/if}}
- {{#if groupRoll.mainCharacterTotal includeZero=true}}{{groupRoll.mainCharacterTotal}}{{else}}{{localize ""}}{{/if}}
+ {{#if groupRoll.mainCharacterTotal includeZero=true}}{{groupRoll.mainCharacterTotal}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}}{{/if}}
{{#each groupRoll.modifiers as |modifier|}}
{{#if (gte modifier 0)}}+{{else}}-{{/if}}
{{positive modifier}}
{{/each}}
+ {{#unless groupRoll.modifiers.length}}
+ +
+ {{localize "DAGGERHEART.GENERAL.Modifier.plural"}}
+ {{/unless}}
diff --git a/templates/dialogs/groupRollDialog/groupRollMainCharacter.hbs b/templates/dialogs/groupRollDialog/groupRollMainCharacter.hbs
index 0a090acf..bf804aa6 100644
--- a/templates/dialogs/groupRollDialog/groupRollMainCharacter.hbs
+++ b/templates/dialogs/groupRollDialog/groupRollMainCharacter.hbs
@@ -1,71 +1,73 @@
-{{#with mainCharacter}}
-
-
{{localize "Main Character"}}
-