From 91a517637445a90ca60d52b840b91ad01450ee52 Mon Sep 17 00:00:00 2001 From: "centron\\schwoerer" Date: Thu, 20 Nov 2025 14:36:40 +0100 Subject: [PATCH] feat(gowlers-tracking-ledger): improve damage source extraction with proper metadata resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implement resolveActorFromMetadata() to extract attacker from message metadata UUID - Implement resolveItemFromMetadata() to extract weapon/ability from attacker's inventory - Change label format from "Damage (Actor, Weapon)" to "Actor -> Weapon" (e.g., "Goblin -> Scimitar Slash") - Add support for identifiedInfo, metadata, flavor text, and speaker.alias in priority order - Add support for Critical and Nonlethal damage modifiers - Update version to 0.1.19 This properly resolves WHO did the damage (attacker name) and WHAT was used (weapon/ability name), addressing the missing damage details. Format matches reference macros (macro_activate-hp-tracking.js). 🤖 Generated with Claude Code Co-Authored-By: Claude --- .../scripts/gowlers-tracking-ledger.js | 109 ++++++++++-------- .../gowlers-tracking-ledger/module.json | 2 +- 2 files changed, 61 insertions(+), 50 deletions(-) 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 a43c7842..5a1a4973 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 @@ -1,6 +1,6 @@ const MODULE_ID = "gowlers-tracking-ledger"; -const MODULE_VERSION = "0.1.18"; +const MODULE_VERSION = "0.1.19"; const TRACK_SETTING = "actorSettings"; const FLAG_SCOPE = "world"; const MAX_HISTORY_ROWS = 100; @@ -283,10 +283,11 @@ async function initializeModule() { Hooks.on("updateCombat", (combat) => onCombatUpdate(combat)); // Helper: Build source label from damage/healing context - function buildSourceLabel(value, options) { - // Order of precedence (per Manual_dmgtracking.md): - // 1. identifiedInfo from chat message - // 2. Chat card metadata (actor/item) + // Format: "ActorName -> ActionName" (e.g., "Goblin -> Scimitar Slash") + function buildSourceLabel(value, options = {}) { + // Order of precedence (per reference macros and Manual_dmgtracking.md): + // 1. identifiedInfo from chat message (action name, item name) + // 2. Chat card metadata (actor/item UUIDs) - resolve to documents // 3. Chat card flavor text // 4. Fallbacks @@ -296,55 +297,65 @@ async function initializeModule() { return null; } - console.log("[GowlersTracking] buildSourceLabel: Processing damage value:", value); - console.log("[GowlersTracking] buildSourceLabel: Message flags:", message.flags); + const info = message.flags?.pf1?.identifiedInfo ?? {}; + const metadata = message.flags?.pf1?.metadata ?? {}; + const fromChatFlavor = message.flavor?.trim(); - // Check for identifiedInfo (action name, item name) - if (message.flags?.pf1?.identifiedInfo) { - const identified = message.flags.pf1.identifiedInfo; - const actionName = identified.action || identified.actionName || identified.itemName; - const actorName = identified.actorName || "Unknown"; - console.log("[GowlersTracking] Found identifiedInfo:", identified); - if (actionName) { - const label = value < 0 ? `Damage (${actorName}, ${actionName})` : `Healing (${actionName})`; - console.log("[GowlersTracking] Using identifiedInfo label:", label); - return label; + // Try to resolve the actor document from metadata + const actorDoc = resolveActorFromMetadata(metadata); + // Try to resolve the item document from the actor + const itemDoc = actorDoc ? resolveItemFromMetadata(actorDoc, metadata) : null; + + // Build actor name from multiple sources in order of preference + const actorName = actorDoc?.name ?? + info.actorName ?? + message.speaker?.alias ?? + null; + + // Build action/item name from multiple sources + const actionName = info.actionName ?? + info.name ?? + itemDoc?.name ?? + fromChatFlavor ?? + null; + + // Build final label with format "ActorName -> ActionName" + let label = null; + if (actorName && actionName) label = `${actorName} -> ${actionName}`; + else if (actionName) label = actionName; + else if (actorName) label = actorName; + else label = value < 0 ? "Damage" : "Healing"; + + // Add special modifiers + if (options.isCritical) label += " (Critical)"; + if (options.asNonlethal) label += " [Nonlethal]"; + + console.log("[GowlersTracking] buildSourceLabel resolved to:", label); + return label; + } + + // Helper: Resolve actor from metadata UUID + function resolveActorFromMetadata(metadata = {}) { + if (!metadata.actor) return null; + + try { + if (typeof fromUuidSync === "function") { + const doc = fromUuidSync(metadata.actor); + if (doc instanceof Actor) return doc; } + } catch (err) { + console.warn("[GowlersTracking] Failed to resolve actor UUID:", metadata.actor, err); } - // Check for chat card metadata (actor + item responsible) - if (message.flags?.pf1?.metadata) { - const meta = message.flags.pf1.metadata; - const actorName = meta.actor?.name || meta.actorName || "Unknown"; - const itemName = meta.item?.name || meta.itemName || "Attack"; - console.log("[GowlersTracking] Found metadata:", meta); - if (value < 0) { - const label = `Damage (${actorName}, ${itemName})`; - console.log("[GowlersTracking] Using metadata label:", label); - return label; - } else { - const label = `Healing (${itemName})`; - console.log("[GowlersTracking] Using metadata healing label:", label); - return label; - } - } + // Fallback: extract actor ID from UUID and look up + const id = String(metadata.actor).split(".").pop(); + return game.actors.get(id) ?? null; + } - // Check for flavor text (custom macros may only have flavor) - if (message.flavor) { - // Try to parse flavor for action names - const flavorMatch = message.flavor.match(/\*\*(.*?)\*\*|(.*?)<\/strong>/); - if (flavorMatch) { - const actionName = flavorMatch[1] || flavorMatch[2]; - const label = value < 0 ? `Damage (${actionName})` : `Healing (${actionName})`; - console.log("[GowlersTracking] Using flavor text label:", label); - return label; - } - } - - // Fallbacks - const fallback = value < 0 ? "Damage" : "Healing"; - console.log("[GowlersTracking] Using fallback label:", fallback); - return fallback; + // Helper: Resolve item from actor's inventory using metadata UUID + function resolveItemFromMetadata(actor, metadata = {}) { + if (!metadata.item || !(actor?.items instanceof Collection)) return null; + return actor.items.get(metadata.item) ?? null; } // Helper: Record damage source for later consumption diff --git a/src/macros_new/gowlers-tracking-ledger/module.json b/src/macros_new/gowlers-tracking-ledger/module.json index 0fb74ee8..a899c181 100644 --- a/src/macros_new/gowlers-tracking-ledger/module.json +++ b/src/macros_new/gowlers-tracking-ledger/module.json @@ -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.18", + "version": "0.1.19", "authors": [ { "name": "Gowler", "url": "https://foundryvtt.com" } ],