feat(gowlers-tracking-ledger): add detailed source info and damage breakdown tooltips
- Source column now shows attacker name and item: "Damage (Chyvvom, Binding Contracts)" - Add damage breakdown detection from pf1DamageData - Add hover tooltips to delta (Δ) column showing damage/healing breakdown - Extract damage types and values: "5 physical, 5 fire" etc. - Store damageBreakdown field in history entries - Support tooltips for HP and XP changes - Update version to 0.1.13 Now you can see detailed damage types and amounts by hovering over the delta column, and source column shows exactly who dealt the damage and with what ability. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
const MODULE_ID = "gowlers-tracking-ledger";
|
||||
const MODULE_VERSION = "0.1.12";
|
||||
const MODULE_VERSION = "0.1.13";
|
||||
const TRACK_SETTING = "actorSettings";
|
||||
const FLAG_SCOPE = "world";
|
||||
const MAX_HISTORY_ROWS = 100;
|
||||
@@ -430,7 +430,11 @@ function buildHistoryContent(actor, tabArg) {
|
||||
columns: [
|
||||
{ label: "Timestamp", render: (entry) => formatDate(entry.timestamp) },
|
||||
{ label: "HP", render: (entry) => entry.value },
|
||||
{ label: "Δ", render: (entry) => entry.diff },
|
||||
{
|
||||
label: "Δ",
|
||||
render: (entry) => entry.diff,
|
||||
getTitle: (entry) => entry.damageBreakdown ? `${entry.damageBreakdown}` : ""
|
||||
},
|
||||
{ label: "Source", render: (entry) => entry.source ?? "Manual" },
|
||||
{ label: "Encounter", render: (entry) => entry.encounterId ? entry.encounterId.slice(0, 8) : "N/A" },
|
||||
],
|
||||
@@ -442,7 +446,11 @@ function buildHistoryContent(actor, tabArg) {
|
||||
columns: [
|
||||
{ label: "Timestamp", render: (entry) => formatDate(entry.timestamp) },
|
||||
{ label: "XP", render: (entry) => entry.value },
|
||||
{ label: "Δ", render: (entry) => entry.diff },
|
||||
{
|
||||
label: "Δ",
|
||||
render: (entry) => entry.diff,
|
||||
getTitle: (entry) => entry.damageBreakdown ? `${entry.damageBreakdown}` : ""
|
||||
},
|
||||
{ label: "Source", render: (entry) => entry.source ?? "Manual" },
|
||||
{ label: "Encounter", render: (entry) => entry.encounterId ? entry.encounterId.slice(0, 8) : "N/A" },
|
||||
],
|
||||
@@ -526,7 +534,12 @@ function renderHistoryTable(entries, columns, id) {
|
||||
.map(
|
||||
(entry) => `
|
||||
<tr>
|
||||
${columns.map((col) => `<td>${col.render(entry) ?? ""}</td>`).join("")}
|
||||
${columns.map((col) => {
|
||||
const cellContent = col.render(entry) ?? "";
|
||||
const title = col.getTitle ? col.getTitle(entry) : "";
|
||||
const titleAttr = title ? ` title="${title}"` : "";
|
||||
return `<td${titleAttr}>${cellContent}</td>`;
|
||||
}).join("")}
|
||||
</tr>`
|
||||
)
|
||||
.join("");
|
||||
@@ -564,14 +577,42 @@ async function recordHistoryEntry(actor, statId, previous, nextValue, userId, op
|
||||
}
|
||||
}
|
||||
|
||||
// Detect source of the change
|
||||
// Detect source of the change with actor and item details
|
||||
let source = "Manual";
|
||||
let sourceDetails = "";
|
||||
let damageBreakdown = "";
|
||||
|
||||
if (options?.pf1DamageData) {
|
||||
source = "Attack";
|
||||
// Try to get attacker actor and item information
|
||||
const attackerName = options?.pf1?.attackerName || "Unknown";
|
||||
const itemName = options?.pf1?.itemName || "Attack";
|
||||
source = "Damage";
|
||||
sourceDetails = `${attackerName}, ${itemName}`;
|
||||
|
||||
// Extract damage breakdown if available
|
||||
if (options?.pf1DamageData?.rolls) {
|
||||
const damageRolls = options.pf1DamageData.rolls;
|
||||
const breakdown = [];
|
||||
let total = 0;
|
||||
for (const roll of damageRolls) {
|
||||
if (roll.damageType && roll.value) {
|
||||
breakdown.push(`${roll.value} ${roll.damageType}`);
|
||||
total += parseInt(roll.value) || 0;
|
||||
}
|
||||
}
|
||||
if (breakdown.length > 0) {
|
||||
damageBreakdown = breakdown.join(", ");
|
||||
}
|
||||
}
|
||||
} else if (options?.healing) {
|
||||
const healerName = options?.pf1?.healerName || "Unknown";
|
||||
const itemName = options?.pf1?.itemName || "Healing";
|
||||
source = "Healing";
|
||||
sourceDetails = `${healerName}, ${itemName}`;
|
||||
damageBreakdown = `Healed for ${Math.abs(diffValue)} HP`;
|
||||
} else if (options?.pf1?.actionType === "spell") {
|
||||
source = "Spell";
|
||||
sourceDetails = options?.pf1?.itemName || "Spell";
|
||||
} else if (statId === "xp" && diffValue > 0) {
|
||||
source = "XP Award";
|
||||
} else if (statId === "hp") {
|
||||
@@ -579,11 +620,18 @@ async function recordHistoryEntry(actor, statId, previous, nextValue, userId, op
|
||||
const hpDiff = parseInt(diffValue);
|
||||
if (hpDiff < 0) {
|
||||
source = "Damage";
|
||||
damageBreakdown = `${Math.abs(hpDiff)} damage`;
|
||||
} else if (hpDiff > 0) {
|
||||
source = "Healing";
|
||||
damageBreakdown = `${hpDiff} healing`;
|
||||
}
|
||||
}
|
||||
|
||||
// Format source with details if available
|
||||
if (sourceDetails) {
|
||||
source = `${source} (${sourceDetails})`;
|
||||
}
|
||||
|
||||
const entry = {
|
||||
timestamp: Date.now(),
|
||||
value: config.formatValue(nextValue),
|
||||
@@ -591,6 +639,7 @@ async function recordHistoryEntry(actor, statId, previous, nextValue, userId, op
|
||||
user: game.users.get(userId)?.name ?? "System",
|
||||
source: source,
|
||||
encounterId: encounterId,
|
||||
damageBreakdown: damageBreakdown,
|
||||
};
|
||||
|
||||
console.log(`[GowlersTracking] History entry created for ${statId}:`, entry);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "module",
|
||||
"title": "Gowler's Tracking Ledger",
|
||||
"description": "Adds HP/XP/Currency log buttons to PF1 sheets and opens the tracking dialog preloaded with the actor's logs.",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"authors": [
|
||||
{ "name": "Gowler", "url": "https://foundryvtt.com" }
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user