From fbbc5eecfa0db2ba1c87f63c5ee77293bb306181 Mon Sep 17 00:00:00 2001 From: Michal Tuszowski Date: Sat, 23 Aug 2025 20:41:27 +0000 Subject: [PATCH] Import gk-greyknight-0.6.4.5.zip do wg-greyknights (2025-08-23T20:41:27Z) --- wg-greyknights/module.json | 2 +- wg-greyknights/scripts/helpers.js | 66 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/wg-greyknights/module.json b/wg-greyknights/module.json index 45ecb93..4e042f3 100644 --- a/wg-greyknights/module.json +++ b/wg-greyknights/module.json @@ -1,7 +1,7 @@ { "id": "gk-greyknight", "title": "Grey Knights — Compendium (Wrath & Glory)", - "version": "0.6.4.4", + "version": "0.6.4.5", "compatibility": { "minimum": "11", "verified": "13" diff --git a/wg-greyknights/scripts/helpers.js b/wg-greyknights/scripts/helpers.js index 2407606..d6c96d6 100644 --- a/wg-greyknights/scripts/helpers.js +++ b/wg-greyknights/scripts/helpers.js @@ -168,3 +168,69 @@ Hooks.on("renderActorSheet", async (sheet, htmlEl, data) => { } catch (e) { console.error("gk-greyknight QoL summary:", e); } }); + +// gk-greyknight 0.6.4.5 — Reliable Brotherhood notification on psychic power use +Hooks.on("createChatMessage", async (doc, options, userId) => { + try { + // Heuristic detection of psychic power usage + const flavor = (doc.flavor || "").toLowerCase(); + const contentText = (ui?.chat && doc.content) ? TextEditor?.stripHTML(doc.content)?.toLowerCase?.() : (doc.content || "").toLowerCase(); + const keyWords = ["psychic", "psychic mastery", "power", "smite", "hammerhand", "sanctuary", "shrouding", "might of titan"]; + const looksPsychic = keyWords.some(k => flavor.includes(k) || contentText.includes(k)); + if (!looksPsychic) return; + + // Resolve actor + let actor = null; + const sp = doc.speaker || {}; + if (sp.actor) actor = game.actors?.get(sp.actor); + if (!actor && canvas?.tokens) { + const t = canvas.tokens.get(sp.token) || canvas.tokens.controlled?.[0]; + actor = t?.actor || actor; + } + if (!actor) return; + + // Check Brotherhood ability on actor + const hasBrotherhood = actor.items?.some(i => i.type === "ability" && i.name === "Brotherhood of Psykers"); + if (!hasBrotherhood) return; + + // Count allies with Brotherhood in the scene + const tokens = canvas?.tokens?.placeables || []; + const allied = new Set(); + for (const t of tokens) { + const a = t.actor; if (!a) continue; + const ok = a.items?.some(i => i.type === "ability" && i.name === "Brotherhood of Psykers"); + if (ok) allied.add(a.id); + } + const total = allied.size; + const bonus = allied.has(actor.id) ? Math.max(0, total - 1) : total; + + // Compose message + const msg = `
+ Brotherhood Focus: Allies with Brotherhood here: ${total} → bonus to Psychic Mastery: +${bonus} dice. +
House rule: only one linked Grey Knight should use a psychic power as their Action per round; subsequent powers add +1 Wrath die.
+
`; + + // Whisper to owners + GM + const ownerIds = Object.entries(actor.ownership || {}) + .filter(([uid, lvl]) => lvl >= (CONST.DOCUMENT_OWNERSHIP_LEVELS?.OWNER ?? 3)) + .map(([uid]) => uid); + const gmIds = game.users?.filter(u => u.isGM).map(u => u.id) ?? []; + const whisper = Array.from(new Set([...ownerIds, ...gmIds])); + await ChatMessage.create({content: msg, whisper, speaker: {actor: actor.id}}); + + // If in combat, enforce one-per-round reminder + const combat = game.combat; + if (combat) { + const key = `gk-greyknight.usedPsychicAction.r${combat.round}`; + const prev = combat.getFlag("gk-greyknight", key) || null; + if (prev && prev !== actor.id) { + ui.notifications?.warn("House rule (Brotherhood Focus): only one Grey Knight should use a psychic power as their Action this round."); + } else if (!prev) { + await combat.setFlag("gk-greyknight", key, actor.id); + } + } + } catch (e) { + console.error("gk-greyknight 0.6.4.5 notification error:", e); + } +}); +