Smallest amongst the Ordos, duty bound to battle daemons and the corrupting influence of Chaos. Every encounter with their foe, every scrap of arcane lore learnt, degrades body and soul. The Chamber Militant of the Ordo Malleus are the Grey Knights, making rare and terrible crusades together.
You gain either: +3 Corruption and +1 Conviction. Or: +2 bonus dice on any Scholar (Int) and Investigation (Int) Tests related to daemons and the Warp.
Brotherhood of Psykers. The Grey Knights fight as one mind, their souls warded by hexagrammic rites and the tutelage of Titan. This Ability is the Grey Knights counterpart to Chapter Cult.
Discipline: When you gain this Ability, choose Librarius or Sanctic. You know one power from the chosen Discipline and may learn further powers from it as normal.
Brotherhood Focus (house rule, narrative): While two or more allied characters with this Ability are present in the same scene, each such character gains +1 bonus die to Psychic Mastery tests per other allied character with this Ability (cumulative). Each subsequent power cast in the same round using this shared focus adds one additional Wrath die to the test (GM adjudication). Only one character linked by this Ability may use a psychic power as their Action in a given round.
Your melee attacks gain +1ED until the start of your next Turn (while Sustained, the bonus persists). Optionally spend 3 Shock on activation to gain +1 DN to resist Disarm/Shove manoeuvres against you.
You ward allies with hexagrammic litanies. Allies in the aura gain +1 to Resolve tests vs. Fear/Corruption and count as having Sanctified attacks against DAEMON for the purpose of overcoming Resistances (GM adjudication). The aura ends if you become Incapacitated.
Warp-wrought mist blurs the target. Attacks against the target suffer +1 DN (ranged) while Sustained; moving more than normal speed ends the effect at end of Turn. Potency: also impose +1 DN on melee attacks.
Infuse an ally with the adamant strength of Titan. The target gains +1 to Strength-based Tests and +1ED on melee attacks until the start of your next Turn; while Sustained, the bonuses persist. Potency: also +1 to Toughness Tests.
","value":10,"keywords":"POWERED, IMPERIUM, ADEPTUS ASTARTES, GREY KNIGHTS, INQUISITION, DAEMONHUNTERS","equipped":false,"rating":7,"base":0,"traits":{"list":[{"name":"cumbersome"},{"name":"powered","rating":"4"}]},"invulnerable":false},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755859195679,"modifiedTime":1755859221056,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.9XTvCiJElW4LJij9","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":"K59Lb8PvaCmIrviu","_id":"9XTvCiJElW4LJij9"}
+{"name":"Nemesis Falchions (Pair)","type":"weapon","img":"modules/wng-core/assets/icons/weapons/force-sword.webp","system":{"quantity":1,"rarity":"unique","description":"A matched pair of sanctified force blades. When wielding both, each attack may gain either +1 bonus die to WS or +1ED. Vs DAEMON/PSYKER: +1ED. Requires PSYKER to benefit from Force.","value":9,"keywords":"IMPERIUM, ADEPTUS ASTARTES, GREY KNIGHTS, SANCTIFIED","equipped":false,"attack":{"base":0,"bonus":0,"rank":"none"},"damage":{"base":12,"bonus":0,"rank":0,"ed":{"base":2,"bonus":0,"rank":0,"dice":""},"ap":{"base":-3,"bonus":0,"rank":0,"dice":""},"enabled":false,"otherDamage":{"mortal":"0","wounds":"0","shock":"0"},"dice":""},"ed":{"base":0,"bonus":0,"rank":0},"ap":{"base":0,"bonus":0,"rank":0},"category":"melee","range":{"short":0,"medium":0,"long":0,"melee":1,"thrown":null},"ammo":{"id":""},"salvo":0,"traits":{"list":[{"name":"force"},{"name":"parry"}]},"upgrades":[],"otherDamage":{},"combi":{},"twinned":false},"effects":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755858904217,"modifiedTime":1755859370010,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.AUwZwmYWGCSH04m2","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":null,"flags":{},"_id":"AUwZwmYWGCSH04m2"}
+{"name":"Aegis of Titan (Ability)","type":"ability","img":"modules/wng-core/assets/icons/abilities/the-inquisition.webp","_id":"DaEMUDPe8wmrWz70","effects":[{"_id":"WD4ApIMZ3pnaPDtl","name":"Aegis of Titan — Innate Purity","icon":"icons/svg/aura.svg","origin":"","disabled":false,"duration":{"startTime":null},"changes":[{"key":"system.combat.resolve.bonus","mode":2,"value":1,"priority":20}],"transfer":true,"flags":{}},{"_id":"OybEJ8Tl1hRkI5zJ","name":"Aegis of Titan — Aegis Synergy","icon":"icons/svg/upgrade.svg","origin":"","disabled":true,"duration":{"startTime":null},"changes":[{"key":"system.combat.resolve.bonus","mode":2,"value":1,"priority":20}],"transfer":true,"flags":{}},{"name":"Aegis: +1 Deny the Witch","img":"modules/wng-core/assets/icons/abilities/the-inquisition.webp","_id":"ded0d4166d594fd2","type":"base","system":{"transferData":{"type":"document","originalType":"document","documentType":"Actor","avoidTest":{"value":"none","opposed":false,"prevention":true,"reversed":false},"testIndependent":false,"equipTransfer":true,"selfOnly":false,"prompt":false,"area":{"templateData":{"borderColor":null,"fillColor":null,"texture":null},"keep":false,"aura":{"transferred":false,"render":false},"duration":"sustained"},"zone":{"type":"zone","transferred":false,"traits":{},"skipImmediateOnPlacement":false,"keep":false}},"itemTargetData":{"ids":[],"allItems":false},"scriptData":[],"zone":{"type":"zone","traits":{},"skipImmediateOnPlacement":false},"sourceData":{"test":{}}},"changes":[{"key":"flags.gk-greyknight.denyBonus","mode":2,"value":"1","priority":10}],"disabled":false,"transfer":true,"statuses":[]}],"flags":{"core":{}},"folder":null,"system":{"description":"Innate purity (+1 vs Corruption). While equipped with Aegis armour, enable Synergy for an additional +1 vs Corruption. In addition, you gain +1 die to Deny the Witch.","keywords":"IMPERIUM, ADEPTUS ASTARTES, GREY KNIGHTS, INQUISITION, DAEMONHUNTERS, ORDO MALLEUS"},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}}
+{"name":"Nemesis Force Halberd","type":"weapon","img":"modules/wng-core/assets/icons/powers/mental-force.webp","effects":[],"flags":{"wng-core":{"initialization-folder":"Weapons","sort":0},"core":{}},"system":{"quantity":1,"rarity":"uncommon","description":"Force Staves are laced with a complex psy-matrix that allows them to act as a psychic battery, storing psychic energy that can be released with brutal efficiency.
Nemesis: vs DAEMON/PSYKER: +1 ED (homebrew). Two‑Handed.
","value":2,"keywords":"IMPERIUM, ADEPTUS ASTARTES, GREY KNIGHTS, INQUISITION, DAEMONHUNTERS, ORDO MALLEUS, MELEE, FORCE, 2-HANDED","equipped":false,"attack":{"base":0,"bonus":0,"rank":"none"},"damage":{"base":4,"bonus":0,"rank":0,"ap":{"base":-1,"bonus":0,"rank":0},"ed":{"base":2,"bonus":0,"rank":0},"enabled":false,"otherDamage":{"mortal":"0","wounds":"0","shock":"0"}},"ed":{"base":0,"bonus":0,"rank":0},"ap":{"base":0,"bonus":0,"rank":0},"category":"melee","range":{"short":0,"medium":0,"long":0,"melee":2,"thrown":null},"ammo":{"id":""},"salvo":0,"traits":{"list":[{"name":"brutal"},{"name":"force"}]},"upgrades":[],"otherDamage":{},"combi":{},"twinned":false},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755779931196,"modifiedTime":1755779931196,"lastModifiedBy":"8fThFXcxV83JCCcX","exportSource":{"worldId":"gilead-wandg","uuid":"Item.9vfkaU0vc61t7hKO","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":"85dkcvhBYli5TJrZ","_id":"NX6bWADcIa03iGCK"}
+{"name":"Grey Knight Armour Integrated Storm Bolter","type":"weapon","img":"modules/wng-core/assets/icons/weapons/storm-bolter.webp","effects":[],"flags":{"wng-core":{"initialization-folder":"Weapons","sort":0},"core":{}},"system":{"quantity":1,"rarity":"unique","description":"
Integrated forearm storm bolter. Integrated: does not occupy hands; may fire while wielding two‑handed melee. Treat as Pistol for firing in melee.
Your melee attacks gain +1ED until the start of your next Turn (while Sustained, the bonus persists). Optionally spend 3 Shock on activation to gain +1 DN to resist Disarm/Shove manoeuvres against you.
You ward allies with hexagrammic litanies. Allies in the aura gain +1 to Resolve tests vs. Fear/Corruption and count as having Sanctified attacks against DAEMON for the purpose of overcoming Resistances (GM adjudication). The aura ends if you become Incapacitated.
"},"_id":"a0b1c2d3e4f50618"}
+{"name":"The Shrouding (Sanctic)","type":"psychicPower","img":"modules/wng-core/assets/icons/powers/power.webp","effects":[],"flags":{"core":{}},"system":{"dn":"7","cost":10,"activation":"action","duration":"Sustained","range":"Self or Ally within 15 m","multiTarget":false,"keywords":"PSYCHIC, SANCTIC","prerequisites":"PSYKER Keyword","description":"
Warp-wrought mist blurs the target. Attacks against the target suffer +1 DN (ranged) while Sustained; moving more than normal speed ends the effect at end of Turn. Potency: also impose +1 DN on melee attacks.
"},"_id":"a0b1c2d3e4f50619"}
+{"name":"Might of Titan (Sanctic)","type":"psychicPower","img":"modules/wng-core/assets/icons/powers/power.webp","effects":[],"flags":{"core":{}},"system":{"dn":"7","cost":15,"activation":"action","duration":"Sustained","range":"15 m","multiTarget":false,"keywords":"PSYCHIC, SANCTIC","prerequisites":"PSYKER Keyword","description":"
Infuse an ally with the adamant strength of Titan. The target gains +1 to Strength-based Tests and +1ED on melee attacks until the start of your next Turn; while Sustained, the bonuses persist. Potency: also +1 to Toughness Tests.
"},"_id":"a0b1c2d3e4f5061a"}
+{"name":"Brotherhood of Psykers","type":"ability","img":"modules/wng-core/assets/icons/abilities/adeptus-astartes.webp","effects":[],"flags":{"core":{}},"system":{"description":"
Brotherhood of Psykers. The Grey Knights fight as one mind, their souls warded by hexagrammic rites and the tutelage of Titan. This Ability is the Grey Knights counterpart to Chapter Cult.
Discipline: When you gain this Ability, choose Librarius or Sanctic. You know one power from the chosen Discipline and may learn further powers from it as normal.
Brotherhood Focus (house rule, narrative): While two or more allied characters with this Ability are present in the same scene, each such character gains +1 bonus die to Psychic Mastery tests per other allied character with this Ability (cumulative). Each subsequent power cast in the same round using this shared focus adds one additional Wrath die to the test (GM adjudication). Only one character linked by this Ability may use a psychic power as their Action in a given round.
","cost":0,"requirements":"GREY KNIGHTS"},"_id":"b1a2c3d4e5f60718"}
+{"name":"Psycannon","type":"weapon","img":"modules/wng-core/assets/icons/weapons/autocannon.webp","system":{"quantity":1,"rarity":"unique","description":"Anti-daemonicboltweapon.VsDAEMON/PSYKER:+1ED.OnCritical:gainsRending(1)fortheresult.","value":9,"keywords":"BOLT,IMPERIUM,ADEPTUSASTARTES,GREYKNIGHTS,SANCTIFIED","equipped":false,"attack":{"base":0,"bonus":0,"rank":"none"},"damage":{"base":14,"bonus":0,"rank":0,"ed":{"base":3,"bonus":0,"rank":0,"dice":""},"ap":{"base":-2,"bonus":0,"rank":0,"dice":""},"enabled":false,"otherDamage":{"mortal":"0","wounds":"0","shock":"0"},"dice":""},"ed":{"base":0,"bonus":0,"rank":0},"ap":{"base":0,"bonus":0,"rank":0},"category":"ranged","range":{"short":20,"medium":40,"long":60,"melee":1,"thrown":null},"ammo":{"id":""},"salvo":2,"traits":{"list":[{"name":"heavy","rating":"7"},{"name":"rapidFire","rating":"2"}]},"upgrades":[],"otherDamage":{},"combi":{},"twinned":false},"effects":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755858910417,"modifiedTime":1756051080757,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.luQa0ffP6nroOeN8","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":null,"flags":{},"_id":"luQa0ffP6nroOeN8"}
+{"name":"ORDO MALLEUS","type":"keyword","img":"modules/wng-core/assets/factions/the-inquisition.svg","effects":[{"_id":"xs6DzM62O4RjebzK","changes":[{"key":"system.combat.conviction.bonus","mode":2,"value":"1","priority":null},{"key":"system.corruption.current","mode":2,"value":"3","priority":null}],"disabled":false,"duration":{"startTime":null,"seconds":null,"combat":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"transfer":true,"flags":{"wrath-and-glory":{"description":"","migrated":true,"manualEffectKeys":true}},"tint":"#ffffff","origin":null,"name":"ORDO MALLEUS (Choice 1)","description":"","statuses":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","lastModifiedBy":null},"img":"modules/wng-core/assets/factions/the-inquisition.svg","type":"base","system":{"transferData":{"type":"other","originalType":"document","documentType":"Actor","avoidTest":{"value":"none","opposed":false,"prevention":true,"reversed":false},"testIndependent":false,"equipTransfer":false,"selfOnly":false,"prompt":false,"area":{"templateData":{"borderColor":null,"fillColor":null,"texture":null},"keep":false,"aura":{"transferred":false,"render":false},"duration":"sustained"},"zone":{"type":"zone","transferred":false,"traits":{},"skipImmediateOnPlacement":false,"keep":false}},"itemTargetData":{"ids":[],"allItems":false},"scriptData":[],"zone":{"type":"zone","traits":{},"skipImmediateOnPlacement":false},"sourceData":{"test":{}}},"sort":0},{"_id":"Q0aNWykjDCqeTtQL","changes":[],"disabled":false,"duration":{"startTime":null,"seconds":null,"combat":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"transfer":true,"flags":{"wrath-and-glory":{"description":"Scholar/Investigation related to Daemons/The Warp","changeCondition":{"0":{"description":"Scholar/Investigation related to Daemons/The Warp","script":""}},"manualEffectKeys":true}},"tint":"#ffffff","origin":null,"name":"ORDO MALLEUS (Choice 2)","description":"","statuses":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","lastModifiedBy":null},"img":"modules/wng-core/assets/factions/the-inquisition.svg","type":"base","system":{"scriptData":[{"script":"return args.fields.pool += 2;","label":"Bonus dice on any Scholar (Int) and Investigation (Int) Tests related to daemons and the Warp.","trigger":"dialog","options":{"targeter":false,"hideScript":"return ![\"scholar\", \"investigation\"].includes(args.skill);","activateScript":"","submissionScript":"","deleteEffect":false,"defending":false},"async":false}],"transferData":{"type":"other","originalType":"document","documentType":"Actor","avoidTest":{"value":"none","opposed":false,"prevention":true,"reversed":false},"testIndependent":false,"equipTransfer":false,"selfOnly":false,"prompt":false,"area":{"templateData":{"borderColor":null,"fillColor":null,"texture":null},"keep":false,"aura":{"transferred":false,"render":false},"duration":"sustained"},"zone":{"type":"zone","transferred":false,"traits":{},"skipImmediateOnPlacement":false,"keep":false}},"itemTargetData":{"ids":[],"allItems":false},"zone":{"type":"zone","traits":{},"skipImmediateOnPlacement":false},"sourceData":{"test":{}}},"sort":0},{"name":"Choice","img":"modules/wng-core/assets/factions/the-inquisition.svg","_id":"tk4CpA9MHTJ47VAe","type":"base","system":{"transferData":{"type":"document","originalType":"document","documentType":"Actor","avoidTest":{"value":"none","opposed":false,"prevention":true,"reversed":false},"testIndependent":false,"equipTransfer":false,"selfOnly":false,"prompt":false,"area":{"templateData":{"borderColor":null,"fillColor":null,"texture":null},"keep":false,"aura":{"transferred":false,"render":false},"duration":"sustained"},"zone":{"type":"zone","transferred":false,"traits":{},"skipImmediateOnPlacement":false,"keep":false}},"itemTargetData":{"ids":[],"allItems":false},"scriptData":[{"script":"let effects = this.item.effects.contents.filter(i => i.id != this.effect.id);\n\nlet choice = await ItemDialog.create(effects, 1, {title : this.item.name, text: this.effect.name});\nchoice[0].updateSource({name : choice[0].baseName, \"system.transferData.type\" : \"document\"})","label":"Choice","trigger":"immediate","options":{"targeter":false,"deleteEffect":true,"defending":false},"async":false}],"zone":{"type":"zone","traits":{},"skipImmediateOnPlacement":false},"sourceData":{"test":{}}},"changes":[],"disabled":false,"duration":{"startTime":null,"seconds":null,"combat":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"description":"","origin":null,"tint":"#ffffff","transfer":true,"statuses":[],"sort":0,"flags":{"wrath-and-glory":{"manualEffectKeys":false}},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","lastModifiedBy":null}}],"flags":{"wng-core":{"initialization-folder":"Ordos","sort":0},"core":{}},"system":{"description":"
The Daemon Hunters
Smallest amongst the Ordos, duty bound to battle daemons and the corrupting influence of Chaos. Every encounter with their foe, every scrap of arcane lore learnt, degrades body and soul. The Chamber Militant of the Ordo Malleus are the Grey Knights, making rare and terrible crusades together.
You gain either: +3 Corruption and +1 Conviction. Or: +2 bonus dice on any Scholar (Int) and Investigation (Int) Tests related to daemons and the Warp.
"},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755816946335,"modifiedTime":1755816946335,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.mpcvHYlffwcBy9gP","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":"SXjZUgQ1pROPVE9j","_id":"mpcvHYlffwcBy9gP"}
+{"name":"PsyboltAmmunition","type":"ammo","img":"modules/wng-core/assets/icons/ammo/ammo.webp","system":{"quantity":1,"rarity":"unique","description":"UpgradeforBOLT/StormBolterweapons.Grants+1ED.AgainstDAEMON/PSYKER,attacksgainRending(1).Applymanuallytoattackresolvingrules;conditionaleffectsarenotautomated.","value":5,"keywords":"BOLT,SANCTIFIED","effect":"","traits":{"list":[{"name":"force","type":"add"},{"name":"blessed","type":"add","rating":"2"}]}},"effects":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1756061909914,"modifiedTime":1756061909914,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.iMlwOxHqV9PWIEz5","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":null,"flags":{},"_id":"iMlwOxHqV9PWIEz5"}
+{"name":"Grey Knight (Archetype)","type":"archetype","img":"modules/wng-core/assets/icons/abilities/the-inquisition.webp","effects":[{"_id":"uMkkBfS2rRXluXA6","name":"Aegis of Titan — Innate Purity","icon":"icons/svg/aura.svg","origin":"","disabled":false,"duration":{"startTime":null},"changes":[{"key":"system.combat.resolve.bonus","mode":2,"value":1,"priority":20}],"transfer":true,"flags":{}}],"flags":{"wng-forsaken":{"initialization-folder":"Archetypes","sort":0},"core":{}},"system":{"tier":4,"journal":"DMmW708Q5AQvQfuy","species":{"name":"Adeptus Astartes","id":"KpwHo0A92bR7iVMB"},"faction":{"name":"Adeptus Astartes","id":"CN5E9Z5GqfiR1MDn"},"influence":2,"cost":359,"keywords":["IMPERIUM","ADEPTUS ASTARTES","GREY KNIGHTS","INQUISITION","DAEMONHUNTERS","ORDO MALLEUS"],"attributes":{"strength":5,"toughness":5,"agility":5,"initiative":5,"willpower":6,"intellect":3,"fellowship":null},"skills":{"athletics":3,"awareness":3,"ballisticSkill":5,"cunning":null,"deception":null,"insight":null,"intimidation":null,"investigation":null,"leadership":null,"medicae":null,"persuasion":null,"pilot":null,"psychicMastery":4,"scholar":2,"stealth":3,"survival":1,"tech":null,"weaponSkill":5},"ability":{"id":"DaEMUDPe8wmrWz70","name":"Aegis of Titan","description":"Innate Purity: +1 vs Corruption. Aegis Synergy: +1 vs Corruption while equipped with Aegis armour. Re-roll 1 die on Deny the Witch each round."},"wargear":{"freeItems":[]},"suggested":{"attributes":{"strength":null,"toughness":null,"agility":null,"initiative":null,"willpower":null,"intellect":null,"fellowship":null},"skills":{"athletics":null,"awareness":null,"ballisticSkill":null,"cunning":null,"deception":null,"insight":null,"intimidation":null,"investigation":null,"leadership":null,"medicae":null,"persuasion":null,"pilot":null,"psychicMastery":null,"scholar":null,"stealth":null,"survival":null,"tech":null,"weaponSkill":null},"talents":{"list":[]}}},"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755771384639,"modifiedTime":1755771384639,"lastModifiedBy":"8fThFXcxV83JCCcX","exportSource":{"worldId":"gilead-wandg","uuid":"Item.TCmE7YmUDUVQ3xoz","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":"DEb55m6iVZ0NUOxA","_id":"qSv5JzFRjTYdw1zI"}
+{"name":"Psilencer","type":"weapon","img":"modules/wng-core/assets/icons/weapons/assault-cannon.webp","system":{"quantity":1,"rarity":"unique","description":"High-ratepsykicdisruptor.VsPSYKER:+1ED;hitPSYKERcannotAiminthesameround.","value":9,"keywords":"IMPERIUM,ADEPTUSASTARTES,GREYKNIGHTS,SANCTIFIED","equipped":false,"attack":{"base":0,"bonus":0,"rank":"none"},"damage":{"base":11,"bonus":0,"rank":0,"ed":{"base":2,"bonus":0,"rank":0,"dice":""},"ap":{"base":0,"bonus":0,"rank":0,"dice":""},"enabled":false,"otherDamage":{"mortal":"0","wounds":"0","shock":"0"},"dice":""},"ed":{"base":0,"bonus":0,"rank":0},"ap":{"base":0,"bonus":0,"rank":0},"category":"ranged","range":{"short":12,"medium":24,"long":36,"melee":1,"thrown":null},"ammo":{"id":""},"salvo":3,"traits":{"list":[{"name":"rapidFire","rating":"3"},{"name":"reliable"}]},"upgrades":[],"otherDamage":{},"combi":{},"twinned":false},"effects":[],"_stats":{"coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1","createdTime":1755859392521,"modifiedTime":1756051080757,"lastModifiedBy":"ETeghv7x8fjtIEKK","exportSource":{"worldId":"gilead2","uuid":"Item.qvk9TxIezbO2C5OK","coreVersion":"13.347","systemId":"wrath-and-glory","systemVersion":"7.1.1"}},"folder":null,"flags":{},"_id":"qvk9TxIezbO2C5OK"}
diff --git a/wg-greyknights/scripts/helpers.js b/wg-greyknights/scripts/helpers.js
index d6c96d6..a386a51 100644
--- a/wg-greyknights/scripts/helpers.js
+++ b/wg-greyknights/scripts/helpers.js
@@ -1,133 +1,103 @@
-// gk-greyknight — helpers v0.6.4 (Brotherhood discipline prompt)
-Hooks.once("ready", () => {
- const PACK_KEY = "gk-greyknight.gk-items";
- const PACK_SRC_PREFIX = `Compendium.${PACK_KEY}.`;
- const FLAG_SCOPE = "gk-greyknight";
+// gk-greyknight helpers.js — consolidated 0.6.4.6
+// Zawiera: Brotherhood prompt + starter, powiadomienie (także poza walką), sheet summary,
+// mini-widżet, oraz patcher traitów (Psycannon/Psilencer -> force).
- async function promptDiscipline(actor) {
- const existing = await actor.getFlag(FLAG_SCOPE, "discipline");
- if (existing) return existing;
- return await new Promise(resolve => {
- new Dialog({
- title: "Brotherhood of Psykers — Discipline",
- content: `
Choose a psychic discipline for this character:
-
-
-
-
-
(You can change this later in Actor → Flags → gk-greyknight → discipline.)
`,
- buttons: {
- ok: { label: "Confirm", icon: "", callback: html => resolve(html.find('input[name=\"disc\"]:checked').val() || "librarius") },
- cancel: { label: "Cancel", callback: () => resolve(null) }
- },
- default: "ok"
- }).render(true);
- });
+/* ---------------- Utilities ---------------- */
+const GK_DEBUG = false;
+const FLAG_SCOPE = "gk-greyknight";
+
+async function findItemInAllPacksByName(name, type=null) {
+ for (const pack of game.packs) {
+ if (pack.documentName !== "Item") continue;
+ const idx = await pack.getIndex();
+ const hit = idx.find(e => e.name === name && (!type || e.type === type));
+ if (hit) return await pack.getDocument(hit._id);
}
-
- if (window._gkBroHookId) { Hooks.off("createItem", window._gkBroHookId); window._gkBroHookId = null; }
-
- window._gkBroHookId = Hooks.on("createItem", async (item, opts, userId) => {
- try {
- if (game.userId !== userId) return;
- if (item?.type !== "ability") return;
- const name = item?.name || "";
- if (name !== "Brotherhood of Psykers") return;
- const src = item?.flags?.core?.sourceId || "";
- const isFromOurPack = src.startsWith(PACK_SRC_PREFIX);
- if (!isFromOurPack && name !== "Brotherhood of Psykers") return;
- const actor = item.parent; if (!actor) return;
-
- const chosen = await promptDiscipline(actor);
- if (!chosen) return;
- await actor.setFlag(FLAG_SCOPE, "discipline", chosen);
-
- if (chosen === "sanctic") {
- ui.notifications.info("Discipline set to SANCTIC. Open the GK compendium and pick one Sanctic power as your starter.");
- } else {
- ui.notifications.info("Discipline set to LIBRARIUS. Use core Librarius powers from wng-core.");
- }
- } catch (e) { console.error("gk-greyknight brotherhood helper:", e); }
+ return null;
+}
+async function ensureHasItemByName(actor, name, type=null) {
+ const existing = actor.items?.find(i => i.name === name && (!type || i.type === type));
+ if (existing) return existing;
+ const doc = await findItemInAllPacksByName(name, type);
+ if (!doc) return null;
+ const data = doc.toObject(); delete data._id;
+ const [created] = await actor.createEmbeddedDocuments("Item", [data]);
+ return created;
+}
+async function promptDiscipline(actor) {
+ const existing = await actor.getFlag(FLAG_SCOPE, "discipline");
+ if (existing) return existing;
+ return await new Promise(resolve => {
+ new Dialog({
+ title: "Brotherhood of Psykers — Choose Discipline",
+ content: `
Select a discipline for this character:
+
+ `,
+ buttons: {
+ ok: { label: "Confirm", icon: "", callback: html => resolve(html.find('input[name="disc"]:checked').val() || "sanctic") },
+ cancel: { label: "Cancel", callback: () => resolve(null) }
+ },
+ default: "ok"
+ }).render(true);
});
-
- console.log("gk-greyknight helpers active (v0.6.4): Brotherhood discipline prompt enabled.");
-});
-
-/* gk-greyknight 0.6.4.1 — house-rule reminder (non-blocking) */
-Hooks.on("preCreateChatMessage", (doc, data, options, userId) => {
+}
+async function gkResolveActorFromMessage(doc) {
+ const sp = doc.speaker || {};
+ let actor = sp.actor ? game.actors?.get(sp.actor) : null;
+ if (!actor && canvas?.tokens) {
+ const t = (sp.token && canvas.tokens.get(sp.token)) || canvas.tokens.controlled?.[0] || null;
+ actor = t?.actor || actor;
+ }
+ return actor;
+}
+async function gkIsPsychicMessage(doc) {
try {
- const flavor = (data.flavor || "").toLowerCase();
- const isPsychic = flavor.includes("psychic") || flavor.includes("power");
- if (!isPsychic) return;
- const speaker = data.speaker || {}; const actor = game.actors?.get(speaker.actor);
- if (!actor) return;
- const hasBrotherhood = actor.items?.some(i => i.type === "ability" && i.name === "Brotherhood of Psykers");
- if (!hasBrotherhood) return;
- const combat = game.combat; if (!combat) return;
- 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) combat.setFlag("gk-greyknight", key, actor.id);
- } catch (e) { console.error("gk-greyknight helpers (house-rule reminder):", e); }
-});
-
-// === gk-greyknight 0.6.4.3 — Brotherhood discipline prompt + starter grants ===
-Hooks.once("ready", () => {
- const FLAG_SCOPE = "gk-greyknight";
- // Prevent duplicate hook registration on hot-reload
- if (window._gkBroHookId) { Hooks.off("createItem", window._gkBroHookId); window._gkBroHookId = null; }
-
- async function findItemInAllPacksByName(name, type=null) {
- for (const pack of game.packs) {
- if (pack.documentName !== "Item") continue;
- const index = await pack.getIndex();
- const hit = index.find(e => e.name === name && (!type || e.type === type));
- if (hit) return await pack.getDocument(hit._id);
+ const raw = `${doc.flavor || ""} ${TextEditor?.stripHTML(doc.content || "") || ""}`.toLowerCase();
+ const keys = ["psychic","psychic mastery","psychic power","moc psioniczna","smite","hammerhand","sanctuary","shrouding","might of titan"];
+ if (keys.some(k=>raw.includes(k))) return true;
+ const flagsStr = JSON.stringify(doc.flags || {}).toLowerCase();
+ if (flagsStr.includes("psychic")) return true;
+ if (flagsStr.includes("psychicpower")) return true;
+ if (flagsStr.includes("\"power\"")) return true;
+ const tryUuids = [
+ doc.getFlag?.("core","sourceId"),
+ doc.getFlag?.("wng-core","itemUuid"),
+ doc.flags?.document?.uuid,
+ doc.flags?.uuid
+ ].filter(Boolean);
+ for (const u of tryUuids) {
+ try { const it = await fromUuid(u); if (it?.type === "psychicPower") return true; } catch(e){}
}
- return null;
- }
- async function ensureHasItemByName(actor, name, type=null) {
- const existing = actor.items?.find(i => i.name === name && (!type || i.type === type));
- if (existing) return existing;
- const doc = await findItemInAllPacksByName(name, type);
- if (!doc) return null;
- const data = doc.toObject(); delete data._id;
- const [created] = await actor.createEmbeddedDocuments("Item", [data]);
- return created;
- }
- async function promptDiscipline(actor) {
- const existing = await actor.getFlag(FLAG_SCOPE, "discipline");
- if (existing) return existing;
- return await new Promise(resolve => {
- new Dialog({
- title: "Brotherhood of Psykers — Choose Discipline",
- content: `
Select a discipline for this character:
-
- `,
- buttons: {
- ok: { label: "Confirm", icon: "", callback: html => resolve(html.find('input[name="disc"]:checked').val() || "sanctic") },
- cancel: { label: "Cancel", callback: () => resolve(null) }
- },
- default: "ok"
- }).render(true);
- });
+ } catch(e) { if (GK_DEBUG) console.warn("gk IsPsychicMessage error:", e); }
+ return false;
+}
+function gkBrotherhoodAlliesAndBonus(actor) {
+ const tokens = canvas?.tokens?.placeables || [];
+ const ids = 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) ids.add(a.id);
}
+ const total = ids.size;
+ const bonus = ids.has(actor?.id) ? Math.max(0, total - 1) : total;
+ return { total, bonus };
+}
- window._gkBroHookId = Hooks.on("createItem", async (item, opts, userId) => {
+/* ---------------- 1) Brotherhood: prompt + starter ---------------- */
+Hooks.once("ready", () => {
+ // Avoid duplicate hook if hot-reloaded
+ if (window._gkBroCreateHookId) { Hooks.off("createItem", window._gkBroCreateHookId); window._gkBroCreateHookId = null; }
+ window._gkBroCreateHookId = Hooks.on("createItem", async (item, opts, userId) => {
try {
if (game.userId !== userId) return;
if (item?.type !== "ability" || item?.name !== "Brotherhood of Psykers") return;
const actor = item.parent; if (!actor) return;
-
const chosen = await promptDiscipline(actor);
if (!chosen) return;
await actor.setFlag(FLAG_SCOPE, "discipline", chosen);
-
- // Ensure PSYKER keyword so powers are available
const psyker = await ensureHasItemByName(actor, "PSYKER", "keyword");
if (!psyker) ui.notifications?.warn("PSYKER keyword not found in loaded packs. Add it manually from wng-core.");
-
- // Starter power by discipline
if (chosen === "sanctic") {
const ok = await ensureHasItemByName(actor, "Hammerhand (Sanctic)", "psychicPower");
if (!ok) ui.notifications?.warn("Couldn't auto-add Hammerhand (Sanctic). Drag a Sanctic power from the GK pack.");
@@ -141,96 +111,3 @@ Hooks.once("ready", () => {
} catch (e) { console.error("gk-greyknight — Brotherhood prompt:", e); }
});
});
-
-
-// gk-greyknight 0.6.4.4 — QoL: Brotherhood Focus summary on sheet open
-Hooks.on("renderActorSheet", async (sheet, htmlEl, data) => {
- try {
- const actor = sheet.actor; if (!actor) return;
- const hasBro = actor.items?.some(i => i.type === "ability" && i.name === "Brotherhood of Psykers");
- if (!hasBro) return;
- 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;
- const owners = Object.keys(actor.ownership || {}).filter(uid => actor.ownership[uid] >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER);
- const content = `
-
Brotherhood Focus — Summary
-
Allies with Brotherhood in scene: ${total} (excluding self: ${bonus} bonus die to Psychic Mastery).
-
Reminder: each subsequent power cast this round using the shared focus adds one extra Wrath die. Only one linked character should use a psychic power as their Action per round.
-
`;
- ChatMessage.create({content, whisper: owners, speaker: {actor: actor.id}});
- } 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);
- }
-});
-