From 7ac5432788da1fafa517e49b0eb9e1d747818330 Mon Sep 17 00:00:00 2001 From: "centron\\schwoerer" Date: Fri, 21 Nov 2025 20:17:10 +0100 Subject: [PATCH] Add damage dealt tab and tracking --- .../scripts/gowlers-tracking-ledger.js | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js b/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js index 1ad6f155..bc388d94 100644 --- a/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js +++ b/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js @@ -14,6 +14,7 @@ const DEFAULT_CHAT = Object.freeze({ hp: false, xp: false, currency: false }); const SETTINGS_VERSION = 2; const COIN_ORDER = ["pp", "gp", "sp", "cp"]; const ENCOUNTER_FLAG = "pf1EncounterHistory"; +const DAMAGE_DEALT_FLAG = "pf1DamageDealtHistory"; const STAT_CONFIGS = { hp: { @@ -972,6 +973,22 @@ function buildHistoryContent(actor, tabArg) { }, ], }, + { + id: "damage", + label: "Damage", + flag: DAMAGE_DEALT_FLAG, + columns: [ + { label: "Timestamp", render: (entry) => formatDate(entry.timestamp) }, + { label: "Dmg", render: (entry) => entry.amount != null ? `${entry.amount}` : "" }, + { + label: "?", + render: (entry) => entry.source ?? "", + getTitle: (entry) => entry.breakdown ?? "", + }, + { label: "Target", render: (entry) => entry.target ?? "Unknown" }, + { label: "Encounter", render: (entry) => entry.encounterId ? entry.encounterId.slice(0, 8) : "N/A" }, + ], + }, ]; const tabs = configs @@ -1191,6 +1208,25 @@ async function recordHistoryEntry(actor, statId, previous, nextValue, userId, op matchedMessage.damageDetails?.breakdown || `${damageAmount} damage`; console.log(`[GowlersTracking] Using matched damage source:`, source); + + // Also record outgoing damage for the attacker (damage dealt history) + try { + const metadata = matchedMessage.message?.flags?.pf1?.metadata ?? {}; + const attacker = resolveActorFromMetadata(metadata); + if (attacker) { + const dealtEntry = { + timestamp: Date.now(), + amount: damageAmount, + target: actor.name, + source: source, + breakdown: damageBreakdown, + encounterId: encounterId, + }; + recordDamageDealt(attacker, dealtEntry); + } + } catch (err) { + console.warn("[GowlersTracking] Failed to record outgoing damage for attacker:", err); + } } } @@ -1458,6 +1494,22 @@ function computeEncounterXp(encounter) { return { monsters, monsterTotalXp, players, playerCount, perActorMonsterXp }; } +async function recordDamageDealt(attacker, entry) { + if (!attacker?.id) return; + try { + const existing = (await attacker.getFlag(FLAG_SCOPE, DAMAGE_DEALT_FLAG)) ?? []; + existing.unshift(entry); + if (existing.length > MAX_HISTORY_ROWS) existing.splice(MAX_HISTORY_ROWS); + await attacker.update( + { [`flags.${FLAG_SCOPE}.${DAMAGE_DEALT_FLAG}`]: existing }, + { [MODULE_ID]: true } + ); + refreshOpenDialogs(attacker.id); + } catch (err) { + console.error("[GowlersTracking] Failed to record damage dealt:", err); + } +} + function buildEncounterXpTooltip(encounter) { try { const { monsters, monsterTotalXp, players, playerCount } = computeEncounterXp(encounter);