Skip to content

Commit e726ea3

Browse files
committed
Overhauled saves from chat card
1 parent 1b499b2 commit e726ea3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1207
-443
lines changed

CHANGELOG.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
- All testing efforts were done in v13's Dark mode. The sheet was never designed with v13's theming in mind and it turned out to be pretty difficult to attempt to add it this late in the game. Light mode will _probably_ work fine but don't be surprised if there are small visual issues here and there.
88

9+
### Known Issue
10+
11+
- Rerolling an individual rerolls all combatants.
12+
- If two groups ends up with the same initiative value, all combatants will display with decimals. This is a janky workaround to prevent groups with identical initiatives from ending up mixed in the tracker. Doing it the "right" way proved more trouble than it was worth.
13+
914
### Changes
1015

1116
- Added container items.
@@ -21,6 +26,7 @@
2126
- Combined Arts + Spells + Foci and Abilities into a single Abilities compendium.
2227
- Combined Adventuring Gear + Weapons + Armor into a single Gear compendium.
2328
- Fixed various errors and inconsistencies. If you spot any I missed, please report them.
29+
- Added SRD content, including Deluxe and Atlas classes. Shoutout to pandaniel and Zi-SH on the Discord for their help doing data entry on this one.
2430
- Added icons to most gear items.
2531
- A few bits of adventuring gear didn't have anything suitable in Foundry's icon collection.
2632
- The shields share a single icon, as do two pieces of mail armor, due to limited selection in said collection.
@@ -40,13 +46,16 @@
4046
- Fixed faction attacks forcing attacks to be against certain asset types.
4147
- Fixed an error with monster saves.
4248
- This was caused by an ill-advised "optimization" that had ramifications I didn't foresee. To ensure that all monsters in compendiums are fixed, this is a breaking change. Namely, if you had any characters or monsters that used the "Base Save" in Tweaks to modify their saving throws, you will have to redo the change using the "Universal Save Mod", also located in Tweaks.
49+
- Clicking a save button on a chat card has been vastly improved.
50+
- Now opens a dialog asking for a universal modifier and has individual modifier overrides for each selected token.
51+
- Rolls all saves at once and outputs a single chat card containing the results.
4352
- Fixed weapon charges not displaying on inventory tab.
4453
- Possible fix for an Item Piles interaction.
4554
- Moved party sheet button so it is no longer hidden by Foundry's search button in the actors tab.
46-
- Initiative updates.
47-
- Completely reworked initiative, fixing group initiative and a handful of other issues such as reroll and reset. Shoutout to wyrmisis who gave me permission to use their solution from the OSE project!
48-
- Fixed Alert 1 not providing a group bonus when Alert combatant's initiative is not the highest within the group.
49-
- Updating the initiative of one member of a group should update the initiative of all members.
55+
- Completely reworked initiative, fixing group initiative and a handful of other issues such as reroll and reset. Shoutout to wyrmisis who gave me permission to use their solution from the OSE project!
56+
- Fixed Alert 1 not providing a group bonus when Alert combatant's initiative is not the highest within the group.
57+
- Updating the initiative of one member of a group should update the initiative of all members.
58+
- Initiative rolls are now grouped into a single chat card instead of spamming the chat.
5059

5160
## New in 1.4.6
5261

api-utils.js

Lines changed: 0 additions & 62 deletions
This file was deleted.

lang/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@
384384
"WWN.spells.Time": "Time",
385385
"WWN.spells.TimeHint": "Length of time effort is committed",
386386
"WWN.spells.Effort": "Effort",
387+
"WWN.spells.Commit": "Commit",
387388
"WWN.spells.Committed": "Committed",
388389
"WWN.spells.Current": "Current",
389390
"WWN.spells.HighMage": "High Mage",

module/chat.js

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,103 @@
88
* @return {Array} The extended options Array including new context choices
99
*/
1010
export const addChatMessageContextOptions = function (html, options) {
11-
let canApply = (li) =>
12-
canvas.tokens.controlled.length && li.find(".dice-roll").length;
13-
options.push(
11+
/**
12+
* Determines if damage can be applied from this message
13+
* @param {HTMLElement} li The chat message element
14+
* @return {boolean} Whether damage can be applied
15+
*/
16+
const canApply = (li) => {
17+
const message = game.messages.get(li.dataset.messageId);
18+
if (!canvas.tokens.controlled.length) return false;
19+
20+
// Check for v13 style rolls
21+
if (message.rolls?.length) return true;
22+
23+
// Check for legacy style rolls in content
24+
if (message.content) {
25+
return message.content.includes("damage-roll") ||
26+
message.content.includes("dice-roll");
27+
}
28+
29+
return false;
30+
};
31+
32+
/**
33+
* Extracts the damage amount from a chat message
34+
* @param {ChatMessage} message The chat message to extract from
35+
* @return {number|null} The damage amount, or null if not found
36+
*/
37+
const getDamageAmount = (message) => {
38+
// Case 1: Message has rolls (v13)
39+
if (message.rolls?.length) {
40+
return message.rolls[0].total;
41+
}
42+
43+
// Case 2: Legacy damage roll in content
44+
if (message.content) {
45+
const tempDiv = document.createElement('div');
46+
tempDiv.innerHTML = message.content;
47+
48+
// Try both damage-roll and dice-roll elements
49+
const damageRoll = tempDiv.querySelector('.damage-roll .part-total, .dice-roll .dice-total');
50+
if (damageRoll) {
51+
return Number(damageRoll.textContent);
52+
}
53+
}
54+
55+
return null;
56+
};
57+
58+
// Define the damage application options
59+
const damageOptions = [
1460
{
1561
name: game.i18n.localize("WWN.messages.applyDamage"),
1662
icon: '<i class="fas fa-user-minus"></i>',
17-
condition: canApply,
18-
callback: (li) => applyChatCardDamage(li, 1, 1),
63+
multiplier: 1
1964
},
2065
{
2166
name: game.i18n.localize("WWN.messages.applyHealing"),
2267
icon: '<i class="fas fa-user-plus"></i>',
23-
condition: canApply,
24-
callback: (li) => applyChatCardDamage(li, -1, 1),
68+
multiplier: -1
2569
},
2670
{
2771
name: game.i18n.localize("WWN.messages.applyHalfDamage"),
2872
icon: '<i class="fas fa-user-minus"></i>',
29-
condition: canApply,
30-
callback: (li) => applyChatCardDamage(li, 0.5, 1),
73+
multiplier: 0.5
3174
},
3275
{
3376
name: game.i18n.localize("WWN.messages.applyHalfHealing"),
3477
icon: '<i class="fas fa-user-plus"></i>',
35-
condition: canApply,
36-
callback: (li) => applyChatCardDamage(li, -0.5, 1),
78+
multiplier: -0.5
3779
},
3880
{
3981
name: game.i18n.localize("WWN.messages.applyDoubleDamage"),
4082
icon: '<i class="fas fa-user-minus"></i>',
41-
condition: canApply,
42-
callback: (li) => applyChatCardDamage(li, 2, 1),
83+
multiplier: 2
4384
},
4485
{
4586
name: game.i18n.localize("WWN.messages.applyDoubleHealing"),
4687
icon: '<i class="fas fa-user-plus"></i>',
47-
condition: canApply,
48-
callback: (li) => applyChatCardDamage(li, -2, 1),
88+
multiplier: -2
4989
}
50-
);
90+
];
91+
92+
// Add each damage option to the context menu
93+
damageOptions.forEach(opt => {
94+
options.push({
95+
name: opt.name,
96+
icon: opt.icon,
97+
condition: canApply,
98+
callback: (li) => {
99+
const message = game.messages.get(li.dataset.messageId);
100+
const damage = getDamageAmount(message);
101+
if (damage !== null) {
102+
applyChatCardDamage(damage, opt.multiplier);
103+
}
104+
}
105+
});
106+
});
107+
51108
return options;
52109
};
53110

@@ -69,52 +126,38 @@ export const addChatMessageButtons = function (msg, html, data) {
69126
// Buttons
70127
let roll = html.find(".damage-roll");
71128
if (roll.length > 0) {
72-
let total = roll.find(".dice-total");
73-
let value = total.text();
74129
roll.append(
75130
$(
76131
`<div class="dice-damage"><button type="button" data-action="apply-damage" title="` +
77-
game.i18n.localize("WWN.messages.applyDamage") +
78-
`"><i class="fas fa-tint"></i></button></div>`
132+
game.i18n.localize("WWN.messages.applyDamage") +
133+
`"><i class="fas fa-tint"></i></button></div>`
79134
)
80135
);
81-
roll.find('button[data-action="apply-damage"]').click((ev) => {
82-
ev.preventDefault();
83-
applyChatCardDamage(roll, 1, 0);
84-
});
85136
}
86137

87138
const shockMessage = html.find(".shock-message");
88139
if (shockMessage.length > 0) {
89140
shockMessage.append(
90141
$(
91142
`<div class="dice-damage"><button type="button" data-action="apply-damage" title="` +
92-
game.i18n.localize("WWN.messages.applyShockDamage") +
93-
`"><i class="fas fa-tint"></i></button></div>`
143+
game.i18n.localize("WWN.messages.applyShockDamage") +
144+
`"><i class="fas fa-tint"></i></button></div>`
94145
)
95146
);
96-
shockMessage.find('button[data-action="apply-damage"]').click((ev) => {
97-
ev.preventDefault();
98-
applyChatCardDamage(shockMessage, 1, 0);
99-
});
100147
}
101148
};
102149

103150
/**
104151
* Apply rolled dice damage to the token or tokens which are currently controlled.
105152
* This allows for damage to be scaled by a multiplier to account for healing, critical hits, or resistance
106153
*
107-
* @param {HTMLElement} roll The chat entry which contains the roll data
108-
* @param {Number} multiplier A damage multiplier to apply to the rolled damage.
154+
* @param {Number} amount The base damage amount to apply
155+
* @param {Number} multiplier A damage multiplier to apply to the rolled damage.
109156
* @return {Promise}
110157
*/
111-
async function applyChatCardDamage(roll, multiplier, index) {
112-
const diceTotals = roll.find(".dice-total");
158+
export async function applyChatCardDamage(amount, multiplier) {
113159
const targets = canvas.tokens.controlled;
114-
const amount =
115-
diceTotals.length > 1
116-
? Number(diceTotals[index].textContent)
117-
: Number(diceTotals[0].textContent);
160+
118161
const title =
119162
multiplier > 0
120163
? `Applied ${Math.floor(amount * multiplier)} damage`
@@ -126,14 +169,14 @@ async function applyChatCardDamage(roll, multiplier, index) {
126169
body: `<ul><li>${targets
127170
.map((t) => t.name)
128171
.join("</li><li>")}</li></ul>`,
129-
image: image
172+
image: image
130173
};
131174

132175
const template = "systems/wwn/templates/chat/apply-damage.html";
133176
const html = await renderTemplate(template, templateData);
134177

135178
const chatData = {
136-
user: game.user_id,
179+
user: game.user.id,
137180
content: html
138181
};
139182

0 commit comments

Comments
 (0)