@archivist-gg/dnd5e 0.3.10 → 0.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/LICENSES/SRD.md +38 -3
  2. package/dist/armor/armor.codec.js +3 -3
  3. package/dist/armor/armor.parser.js +2 -2
  4. package/dist/armor/armor.schema.d.ts +1 -0
  5. package/dist/armor/armor.schema.js +1 -1
  6. package/dist/armor/armor.types.d.ts +2 -0
  7. package/dist/background/background.codec.js +5 -5
  8. package/dist/background/background.parser.js +4 -4
  9. package/dist/background/background.schema.js +3 -3
  10. package/dist/chunk-2LULMQTF.js +14 -0
  11. package/dist/{chunk-CBEKVAX4.js → chunk-4BZ47YJ4.js} +10 -3
  12. package/dist/{chunk-22MOUU2G.js → chunk-4SLOJXJ4.js} +1 -1
  13. package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
  14. package/dist/{chunk-J77CKYV3.js → chunk-5KGV6TF7.js} +1 -1
  15. package/dist/{chunk-3UNP3G4D.js → chunk-6ZY3U6BQ.js} +1 -1
  16. package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
  17. package/dist/{chunk-2M34FLAY.js → chunk-BRGLDWUP.js} +3 -1
  18. package/dist/chunk-CM5CWO4K.js +735 -0
  19. package/dist/{chunk-MI7P3NX3.js → chunk-DPM6V7YX.js} +2 -2
  20. package/dist/chunk-EJP263OP.js +186 -0
  21. package/dist/{chunk-G247QXWW.js → chunk-EL6QPF6I.js} +1 -1
  22. package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
  23. package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
  24. package/dist/{chunk-PI4LLJG4.js → chunk-FPGXFD2M.js} +2 -2
  25. package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
  26. package/dist/{chunk-NWDF5HG3.js → chunk-G7ED5H2G.js} +1 -1
  27. package/dist/chunk-H5PTKYXL.js +101 -0
  28. package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
  29. package/dist/{chunk-PP2UHLBA.js → chunk-HJQNK3J5.js} +8 -0
  30. package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
  31. package/dist/chunk-IHE6KVC3.js +13 -0
  32. package/dist/{chunk-BLRW2UU6.js → chunk-J53ERF6K.js} +2 -2
  33. package/dist/{chunk-MQ747UCR.js → chunk-JNNNBEUH.js} +65 -2
  34. package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
  35. package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
  36. package/dist/chunk-LBEXLN6I.js +91 -0
  37. package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
  38. package/dist/{chunk-OYUEUKKF.js → chunk-LVX6TQ3R.js} +12 -8
  39. package/dist/{chunk-R747YKS7.js → chunk-M2OWVAZG.js} +1 -1
  40. package/dist/{chunk-7YU4NPKR.js → chunk-MC5YJ4PB.js} +1 -1
  41. package/dist/{chunk-JCEV7KYN.js → chunk-MUIU7RZ3.js} +1 -1
  42. package/dist/{chunk-JSZ4H6AQ.js → chunk-MWCCGPG3.js} +1 -1
  43. package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
  44. package/dist/{chunk-S56D6B6C.js → chunk-PLOSP4XQ.js} +3 -3
  45. package/dist/{chunk-JANNRGJC.js → chunk-PX25R3DK.js} +1 -1
  46. package/dist/{chunk-V373TRJE.js → chunk-Q5XTEYHD.js} +191 -125
  47. package/dist/{chunk-MAH6DCRI.js → chunk-Q6UOHCCT.js} +1 -1
  48. package/dist/{chunk-HLQAFZKQ.js → chunk-QEO7LYTG.js} +216 -95
  49. package/dist/{chunk-PJMG5XV3.js → chunk-QSBJ6NEM.js} +1 -1
  50. package/dist/{chunk-BL3VELKP.js → chunk-R2V5LN3I.js} +1 -1
  51. package/dist/{chunk-4DOMDEBZ.js → chunk-RQNJXADQ.js} +1 -1
  52. package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
  53. package/dist/chunk-T5GZBKIQ.js +927 -0
  54. package/dist/{chunk-PZCE7DJM.js → chunk-UE6LKRXQ.js} +15 -1
  55. package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
  56. package/dist/{chunk-QHMWA3SZ.js → chunk-VDPRBUU5.js} +1 -1
  57. package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
  58. package/dist/{chunk-V6LJFP4R.js → chunk-X7VZY4ON.js} +2 -2
  59. package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
  60. package/dist/{chunk-BIA32MQ5.js → chunk-XJRNEQPD.js} +1 -1
  61. package/dist/{chunk-OZP6JFGT.js → chunk-XY6X2APM.js} +3 -1
  62. package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
  63. package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
  64. package/dist/{chunk-VQAXTIBW.js → chunk-ZDAEGJH4.js} +2 -0
  65. package/dist/{chunk-XTRDCSJB.js → chunk-ZMJQUZQH.js} +4 -1
  66. package/dist/chunk-ZUQW5VBZ.js +89 -0
  67. package/dist/class/class.codec.js +7 -7
  68. package/dist/class/class.parser.js +6 -6
  69. package/dist/class/class.schema.d.ts +10 -0
  70. package/dist/class/class.schema.js +5 -5
  71. package/dist/entities/base-item-resolver.js +2 -2
  72. package/dist/entities/slug.d.ts +18 -8
  73. package/dist/entities/slug.js +3 -1
  74. package/dist/feat/feat.codec.js +5 -5
  75. package/dist/feat/feat.parser.js +4 -4
  76. package/dist/feat/feat.schema.d.ts +16 -3
  77. package/dist/feat/feat.schema.js +3 -3
  78. package/dist/index.js +5277 -2017
  79. package/dist/item/item.actions-map.d.ts +40 -5
  80. package/dist/item/item.actions-map.js +5 -84
  81. package/dist/item/item.attunement.js +3 -9
  82. package/dist/item/item.bonuses.js +5 -2
  83. package/dist/item/item.codec.js +3 -3
  84. package/dist/item/item.conditions.js +4 -1
  85. package/dist/item/item.conditions.types.d.ts +4 -0
  86. package/dist/item/item.cost.d.ts +3 -0
  87. package/dist/item/item.cost.js +29 -0
  88. package/dist/item/item.icon.d.ts +15 -0
  89. package/dist/item/item.icon.js +211 -0
  90. package/dist/item/item.parser.js +2 -2
  91. package/dist/item/item.schema.d.ts +16 -1
  92. package/dist/item/item.schema.js +3 -1
  93. package/dist/item/item.types.d.ts +9 -2
  94. package/dist/monster/monster.parser.js +5 -5
  95. package/dist/monster/monster.schema.js +4 -4
  96. package/dist/optional-feature/optional-feature.codec.js +4 -4
  97. package/dist/optional-feature/optional-feature.parser.js +3 -3
  98. package/dist/optional-feature/optional-feature.schema.d.ts +229 -3
  99. package/dist/optional-feature/optional-feature.schema.js +6 -2
  100. package/dist/pc/pc.additional-spells.js +4 -4
  101. package/dist/pc/pc.asi-flatten.d.ts +62 -1
  102. package/dist/pc/pc.asi-flatten.js +16 -0
  103. package/dist/pc/pc.conditions.js +1 -1
  104. package/dist/pc/pc.containment.d.ts +45 -0
  105. package/dist/pc/pc.containment.js +24 -0
  106. package/dist/pc/pc.decision-engine.d.ts +21 -3
  107. package/dist/pc/pc.decision-engine.js +23 -14
  108. package/dist/pc/pc.entry-overrides.d.ts +79 -0
  109. package/dist/pc/pc.entry-overrides.js +40 -0
  110. package/dist/pc/pc.equipment.d.ts +2 -2
  111. package/dist/pc/pc.equipment.js +18 -7
  112. package/dist/pc/pc.feature-effects.js +2 -2
  113. package/dist/pc/pc.infusions.d.ts +220 -0
  114. package/dist/pc/pc.infusions.js +64 -0
  115. package/dist/pc/pc.parser.js +18 -1
  116. package/dist/pc/pc.pools.d.ts +1 -1
  117. package/dist/pc/pc.pools.js +11 -3
  118. package/dist/pc/pc.proficiencies.js +21 -14
  119. package/dist/pc/pc.recalc.d.ts +39 -36
  120. package/dist/pc/pc.recalc.js +60 -32
  121. package/dist/pc/pc.resolver.js +21 -14
  122. package/dist/pc/pc.resource-seed.js +1 -1
  123. package/dist/pc/pc.resources.d.ts +6 -1
  124. package/dist/pc/pc.resources.js +3 -1
  125. package/dist/pc/pc.rest.d.ts +21 -1
  126. package/dist/pc/pc.rest.js +52 -19
  127. package/dist/pc/pc.schema.d.ts +14 -0
  128. package/dist/pc/pc.schema.js +1 -1
  129. package/dist/pc/pc.slotting.d.ts +36 -3
  130. package/dist/pc/pc.slotting.js +13 -5
  131. package/dist/pc/pc.tool-picks.d.ts +51 -0
  132. package/dist/pc/pc.tool-picks.js +18 -0
  133. package/dist/pc/pc.types.d.ts +70 -12
  134. package/dist/pc/pool-layout.d.ts +14 -0
  135. package/dist/pc/pool-layout.js +7 -3
  136. package/dist/race/race.codec.js +6 -6
  137. package/dist/race/race.parser.js +5 -5
  138. package/dist/race/race.schema.js +4 -4
  139. package/dist/schemas/attack-schema.d.ts +1 -1
  140. package/dist/schemas/choice-schema.js +2 -2
  141. package/dist/schemas/feature-effect-schema.d.ts +16 -3
  142. package/dist/schemas/feature-effect-schema.js +1 -1
  143. package/dist/schemas/feature-schema.js +3 -3
  144. package/dist/schemas/selection-pool-schema.d.ts +10 -0
  145. package/dist/schemas/selection-pool-schema.js +1 -1
  146. package/dist/spell/spell.codec.js +3 -3
  147. package/dist/spell/spell.parser.js +2 -2
  148. package/dist/spell/spell.scaling.d.ts +34 -10
  149. package/dist/spell/spell.scaling.js +36 -4
  150. package/dist/spell/spell.schema.d.ts +1 -0
  151. package/dist/spell/spell.schema.js +1 -1
  152. package/dist/spell/spell.types.d.ts +4 -0
  153. package/dist/srd/retired-items.d.ts +14 -0
  154. package/dist/srd/retired-items.js +11 -0
  155. package/dist/subclass/subclass.codec.js +7 -7
  156. package/dist/subclass/subclass.parser.js +6 -6
  157. package/dist/subclass/subclass.schema.d.ts +10 -0
  158. package/dist/subclass/subclass.schema.js +5 -5
  159. package/dist/types/choice.d.ts +8 -0
  160. package/dist/types/equipment-grant.d.ts +18 -1
  161. package/dist/types/equipment-grant.js +12 -0
  162. package/dist/types/feature-effect.d.ts +6 -1
  163. package/dist/types/optional-feature.types.d.ts +79 -1
  164. package/dist/types/selection-pool.d.ts +16 -1
  165. package/dist/weapon/weapon.classify.d.ts +10 -8
  166. package/dist/weapon/weapon.classify.js +2 -2
  167. package/dist/weapon/weapon.codec.js +3 -3
  168. package/dist/weapon/weapon.parser.js +2 -2
  169. package/dist/weapon/weapon.schema.d.ts +1 -0
  170. package/dist/weapon/weapon.schema.js +1 -1
  171. package/dist/weapon/weapon.types.d.ts +2 -0
  172. package/package.json +1 -1
  173. package/dist/chunk-O4SRD3J5.js +0 -165
  174. package/dist/chunk-WXWPK3LI.js +0 -55
@@ -65,6 +65,17 @@ var equipmentEntryStateSchema = z.object({
65
65
  effect: z.string()
66
66
  }).optional()
67
67
  }).strict();
68
+ var entryRefField = z.preprocess(
69
+ (v) => typeof v === "number" ? String(v) : typeof v === "string" && v.length > 0 ? v : void 0,
70
+ z.string().optional()
71
+ );
72
+ var infusionMarkerSchema = z.object({
73
+ kind: z.enum(["infused", "created"]),
74
+ by: z.string().min(1),
75
+ seq: z.number().int().min(1),
76
+ choice: z.string().min(1).optional(),
77
+ charges: z.object({ current: z.number().int().nonnegative() }).optional()
78
+ });
68
79
  var equipmentEntrySchema = z.object({
69
80
  item: z.string().min(1),
70
81
  equipped: z.boolean().optional(),
@@ -77,7 +88,10 @@ var equipmentEntrySchema = z.object({
77
88
  // Build-only provenance for Equipment-step-seeded gear (e.g. "builder:starting",
78
89
  // "builder:gold-buy"). Permissive plain string; stripped by finishBuild so a
79
90
  // finished file never carries it.
80
- granted_by: z.string().optional()
91
+ granted_by: z.string().optional(),
92
+ id: entryRefField,
93
+ in: entryRefField,
94
+ infusion: infusionMarkerSchema.optional()
81
95
  });
82
96
  var characterOverridesShape = z.object({
83
97
  scores: z.partialRecord(abilityEnum, z.number().int()).optional(),
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  armorEntitySchema
3
- } from "./chunk-JC5UNIVM.js";
3
+ } from "./chunk-HS6FIOLP.js";
4
4
 
5
5
  // src/armor/armor.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -23,6 +23,7 @@ var KNOWN_KEYS = /* @__PURE__ */ new Set([
23
23
  // enough: this set is the second, independent gate — a key missing here is copied into
24
24
  // `raw` as well, so the two lists must move together.
25
25
  "rendering_hint",
26
+ "icon",
26
27
  "has_fluff",
27
28
  "has_fluff_images",
28
29
  "image",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MONSTER_KNOWN_KEYS,
3
3
  monsterSchema
4
- } from "./chunk-G247QXWW.js";
4
+ } from "./chunk-EL6QPF6I.js";
5
5
 
6
6
  // src/monster/monster.parser.ts
7
7
  import { parseYaml } from "@archivist-gg/core";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseItem
3
- } from "./chunk-SMLXZUBH.js";
3
+ } from "./chunk-EYX4JMAU.js";
4
4
 
5
5
  // src/item/item.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  featureSchema
3
- } from "./chunk-PI4LLJG4.js";
3
+ } from "./chunk-FPGXFD2M.js";
4
4
  import {
5
5
  choiceSchema
6
- } from "./chunk-2M34FLAY.js";
6
+ } from "./chunk-BRGLDWUP.js";
7
7
  import {
8
8
  additionalSpellsEntrySchema,
9
9
  imageField
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  weaponEntitySchema
3
- } from "./chunk-2DFENQIJ.js";
3
+ } from "./chunk-5GKJAUMX.js";
4
4
 
5
5
  // src/weapon/weapon.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -26,6 +26,7 @@ var KNOWN_KEYS = /* @__PURE__ */ new Set([
26
26
  // enough: this set is the second, independent gate — a key missing here is copied into
27
27
  // `raw` as well, so the two lists must move together.
28
28
  "rendering_hint",
29
+ "icon",
29
30
  "has_fluff",
30
31
  "has_fluff_images",
31
32
  "image"
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseClass
3
- } from "./chunk-NWDF5HG3.js";
3
+ } from "./chunk-G7ED5H2G.js";
4
4
 
5
5
  // src/class/class.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  spellEntitySchema
3
- } from "./chunk-VQAXTIBW.js";
3
+ } from "./chunk-ZDAEGJH4.js";
4
4
 
5
5
  // src/spell/spell.parser.ts
6
6
  import { parseYaml, toStringSafe } from "@archivist-gg/core";
@@ -18,6 +18,7 @@ var KNOWN_KEYS = /* @__PURE__ */ new Set([
18
18
  "description",
19
19
  "at_higher_levels",
20
20
  "damage",
21
+ "damage_roll",
21
22
  "saving_throw",
22
23
  "casting_options",
23
24
  // §2 · the fourteen converter keys. This gate and `spellEntitySchema` are independent: a key
@@ -121,6 +122,7 @@ function parseSpell(source) {
121
122
  if (raw.description) spell.description = raw.description;
122
123
  if (raw.at_higher_levels) spell.at_higher_levels = raw.at_higher_levels.map(String);
123
124
  if (raw.damage) spell.damage = { types: raw.damage.types.map(String) };
125
+ if (raw.damage_roll != null) spell.damage_roll = raw.damage_roll;
124
126
  if (raw.saving_throw) spell.saving_throw = { ability: raw.saving_throw.ability };
125
127
  if (raw.casting_options) {
126
128
  spell.casting_options = raw.casting_options.map((opt) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bareEntitySlug
3
- } from "./chunk-6X4KUDMU.js";
3
+ } from "./chunk-ZCTUYGNV.js";
4
4
 
5
5
  // src/weapon/weapon.classify.ts
6
6
  var PURE_RANGED_THROWN_SLUGS = /* @__PURE__ */ new Set(["dart", "net"]);
@@ -7,15 +7,20 @@ function bareEntitySlug(slug) {
7
7
  const p = slug.split("_");
8
8
  return p.length >= 3 ? p.slice(2).join("_") : p[p.length - 1];
9
9
  }
10
+ var STORED_SLUG = /^[a-z0-9-]+(?:_[a-z0-9-]+)+$/;
11
+ function isStoredSlug(tail) {
12
+ return STORED_SLUG.test(tail);
13
+ }
10
14
  function wikilinkTailSlug(link) {
11
15
  var _a;
12
16
  const inner = link.replace(/^\[\[/, "").replace(/\]\]$/, "");
13
- const tail = (_a = inner.split("/").pop()) != null ? _a : inner;
14
- return slugify(tail);
17
+ const tail = ((_a = inner.split("/").pop()) != null ? _a : inner).trim();
18
+ return isStoredSlug(tail) ? bareEntitySlug(tail) : slugify(tail);
15
19
  }
16
20
 
17
21
  export {
18
22
  slugify,
19
23
  bareEntitySlug,
24
+ isStoredSlug,
20
25
  wikilinkTailSlug
21
26
  };
@@ -59,6 +59,8 @@ var spellEntitySchema = z.object({
59
59
  description: z.string().optional(),
60
60
  at_higher_levels: z.array(z.string()).optional(),
61
61
  damage: z.object({ types: z.array(z.string()) }).optional(),
62
+ // The base roll at the spell's own level (a cantrip's tier-1 roll); see `Spell.damage_roll`.
63
+ damage_roll: z.string().optional(),
62
64
  saving_throw: z.object({ ability: z.string() }).optional(),
63
65
  casting_options: z.array(castingOptionSchema).optional(),
64
66
  // §2 · the fourteen converter keys this root refused before R4-G2. Doc counts are MEASURED over
@@ -3,6 +3,7 @@ import { z } from "zod";
3
3
  var abilityEnum = z.enum(["str", "dex", "con", "int", "wis", "cha"]);
4
4
  var subjectField = z.string().min(1).optional();
5
5
  var conditionField = z.string().optional();
6
+ var weaponScopeEnum = z.enum(["weapon", "melee", "ranged", "unarmed", "finesse", "thrown"]);
6
7
  var featureEffectSchema = z.discriminatedUnion("kind", [
7
8
  z.object({ kind: z.literal("initiative-bonus"), value: z.number().int(), condition: conditionField, subject: subjectField }),
8
9
  z.object({ kind: z.literal("skill-bonus"), skills: z.array(z.string().min(1)).nonempty(), ability: abilityEnum, minimum: z.number().int().optional(), condition: conditionField, subject: subjectField }),
@@ -68,7 +69,9 @@ var featureEffectSchema = z.discriminatedUnion("kind", [
68
69
  // canonical damage types. Do not tighten to an enum.
69
70
  damage_type: z.string().min(1),
70
71
  amount: z.string().min(1),
71
- applies_to: z.enum(["weapon", "spell", "all"]).optional(),
72
+ // ART-c1 Task 9b: `spell` and `all` as before, or a weapon scope, one word or an any-of list, which the engine
73
+ // evaluates per attack row (pc.recalc.ts `riderReachesRow`). `weapon`, like an absent value, reaches every row.
74
+ applies_to: z.union([z.enum(["spell", "all"]), weaponScopeEnum, z.array(weaponScopeEnum).min(1)]).optional(),
72
75
  condition: conditionField,
73
76
  subject: subjectField
74
77
  }),
@@ -0,0 +1,89 @@
1
+ // src/item/item.actions-map.ts
2
+ var ITEM_ACTIONS = {
3
+ // Wands and rods
4
+ "wand-of-fireballs": { cost: "action", range: "150 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
5
+ "wand-of-magic-missiles": { cost: "action", range: "120 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
6
+ "wand-of-lightning-bolts": { cost: "action", range: "100 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
7
+ "wand-of-paralysis": { cost: "action", range: "60 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
8
+ "wand-of-fear": { cost: "action", range: "Self", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
9
+ "wand-of-binding": { cost: "action", range: "Self", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
10
+ "wand-of-secrets": { cost: "action", range: "30 ft.", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
11
+ "wand-of-web": { cost: "action", range: "60 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
12
+ "wand-of-wonder": { cost: "action", range: "120 ft.", max_charges: 7, recovery: { amount: "1d6+1", reset: "dawn" } },
13
+ // Activatable wondrous items
14
+ "boots-of-speed": { cost: "bonus-action", range: "Self", max_charges: 1, recovery: { amount: "1", reset: "long" } },
15
+ "boots-of-levitation": { cost: "action", range: "Self" },
16
+ "boots-of-striding-and-springing": { cost: "free", range: "Self" },
17
+ "broom-of-flying": { cost: "action", range: "Touch" },
18
+ "cloak-of-displacement": { cost: "free", range: "Self" },
19
+ "cloak-of-the-bat": { cost: "action", range: "Self", max_charges: 1, recovery: { amount: "1", reset: "long" } },
20
+ "decanter-of-endless-water": { cost: "action", range: "Touch" },
21
+ "drum-of-panic": { cost: "action", range: "120 ft.", max_charges: 1, recovery: { amount: "1", reset: "long" } },
22
+ "eyes-of-charming": { cost: "action", range: "30 ft.", max_charges: 3, recovery: { amount: "3", reset: "dawn" } },
23
+ // Rings
24
+ "ring-of-three-wishes": { cost: "action", range: "Self", max_charges: 3, recovery: { amount: "0", reset: "special" } },
25
+ "ring-of-shooting-stars": { cost: "action", range: "60 ft.", max_charges: 6, recovery: { amount: "1d6", reset: "dawn" } },
26
+ "ring-of-the-ram": { cost: "action", range: "60 ft.", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
27
+ "ring-of-spell-storing": { cost: "action", range: "Self", max_charges: 5 },
28
+ "ring-of-animal-influence": { cost: "action", range: "Self", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
29
+ "ring-of-elemental-command": { cost: "action", range: "Self", max_charges: 5, recovery: { amount: "1d4+1", reset: "dawn" } },
30
+ "ring-of-evasion": { cost: "reaction", range: "Self", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
31
+ // Necklaces
32
+ "necklace-of-fireballs": { cost: "action", range: "60 ft.", max_charges: 9 },
33
+ // Gems
34
+ "gem-of-brightness": { cost: "action", range: "60 ft.", max_charges: 50 },
35
+ "gem-of-seeing": { cost: "action", range: "Self", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
36
+ // Helms
37
+ "helm-of-teleportation": { cost: "action", range: "Self", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
38
+ // Medallions
39
+ "medallion-of-thoughts": { cost: "action", range: "30 ft.", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
40
+ // Pipes
41
+ "pipes-of-haunting": { cost: "action", range: "30 ft.", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
42
+ "pipes-of-the-sewers": { cost: "action", range: "Self", max_charges: 3, recovery: { amount: "1d3", reset: "dawn" } },
43
+ // Cubes / chimes
44
+ "cube-of-force": { cost: "action", range: "Self", max_charges: 36, recovery: { amount: "1d20", reset: "dawn" } },
45
+ "chime-of-opening": { cost: "action", range: "120 ft.", max_charges: 10 },
46
+ // Magic weapons with activation actions (surface in items table only via override; weapons table is primary)
47
+ "sun-blade": { cost: "free", range: "Self" },
48
+ // Potions / consumables · consumed on use (user ruling 2026-09-24): using one spends the entry's quantity, so they
49
+ // carry no charges or recovery. 2024 healing potions are a Bonus Action to drink/administer (the type=potion
50
+ // default covers uncurated ones).
51
+ "potion-of-healing": { cost: "bonus-action", range: "Self", consumed: true },
52
+ "potion-of-greater-healing": { cost: "bonus-action", range: "Self", consumed: true },
53
+ "potion-of-superior-healing": { cost: "bonus-action", range: "Self", consumed: true },
54
+ "potion-of-supreme-healing": { cost: "bonus-action", range: "Self", consumed: true },
55
+ "alchemists-fire": { cost: "action", range: "20 ft.", consumed: true },
56
+ "holy-water": { cost: "action", range: "20 ft.", consumed: true },
57
+ // Oils are APPLIED (minutes), not drunk: curated to "action" so the blanket
58
+ // type=potion → bonus-action default never mislabels these mis-typed items.
59
+ "oil-of-sharpness": { cost: "action", range: "Self", consumed: true },
60
+ "oil-of-etherealness": { cost: "action", range: "Self", consumed: true },
61
+ "oil-of-slipperiness": { cost: "action", range: "Self", consumed: true },
62
+ "dust-of-disappearance": { cost: "action", range: "Self", consumed: true }
63
+ };
64
+ function findItemAction(slug) {
65
+ if (slug in ITEM_ACTIONS) return ITEM_ACTIONS[slug];
66
+ const p = slug.split("_");
67
+ const bare = p.length >= 3 ? p.slice(2).join("_") : p[p.length - 1];
68
+ return bare === slug ? void 0 : ITEM_ACTIONS[bare];
69
+ }
70
+ function resolveItemAction(slug, entry, itemType, opts) {
71
+ var _a, _b, _c, _d, _e, _f;
72
+ const curated = (_a = findItemAction(slug)) != null ? _a : null;
73
+ const override = (opts == null ? void 0 : opts.weaponLike) ? void 0 : entry.overrides;
74
+ const overrideCost = override == null ? void 0 : override.action;
75
+ const overrideRange = override == null ? void 0 : override.range;
76
+ const viewEntity = (_b = opts == null ? void 0 : opts.view) == null ? void 0 : _b.entity;
77
+ const viewAction = viewEntity == null ? void 0 : viewEntity.action;
78
+ const viewRange = viewEntity == null ? void 0 : viewEntity.range;
79
+ const typeDefault = itemType === "potion" ? "bonus-action" : itemType === "scroll" ? (_c = opts == null ? void 0 : opts.spellCost) != null ? _c : "action" : void 0;
80
+ const cost = (_e = (_d = overrideCost != null ? overrideCost : viewAction) != null ? _d : curated == null ? void 0 : curated.cost) != null ? _e : typeDefault;
81
+ if (!cost) return null;
82
+ return { cost, range: (_f = overrideRange != null ? overrideRange : viewRange) != null ? _f : curated == null ? void 0 : curated.range };
83
+ }
84
+
85
+ export {
86
+ ITEM_ACTIONS,
87
+ findItemAction,
88
+ resolveItemAction
89
+ };
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  classCodec
3
- } from "../chunk-BIA32MQ5.js";
4
- import "../chunk-NWDF5HG3.js";
3
+ } from "../chunk-XJRNEQPD.js";
4
+ import "../chunk-G7ED5H2G.js";
5
5
  import "../chunk-4U55VNC7.js";
6
- import "../chunk-S56D6B6C.js";
7
- import "../chunk-23LZLBJK.js";
6
+ import "../chunk-PLOSP4XQ.js";
7
+ import "../chunk-G6MHJDVT.js";
8
8
  import "../chunk-CJYCVNW2.js";
9
- import "../chunk-PI4LLJG4.js";
9
+ import "../chunk-FPGXFD2M.js";
10
10
  import "../chunk-WYGD2UGN.js";
11
11
  import "../chunk-ZJXSXVFP.js";
12
12
  import "../chunk-IN4M4X7P.js";
13
- import "../chunk-2M34FLAY.js";
14
- import "../chunk-XTRDCSJB.js";
13
+ import "../chunk-BRGLDWUP.js";
14
+ import "../chunk-ZMJQUZQH.js";
15
15
  import "../chunk-UA5KS2PL.js";
16
16
  export {
17
17
  classCodec
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  parseClass
3
- } from "../chunk-NWDF5HG3.js";
3
+ } from "../chunk-G7ED5H2G.js";
4
4
  import "../chunk-4U55VNC7.js";
5
- import "../chunk-S56D6B6C.js";
6
- import "../chunk-23LZLBJK.js";
5
+ import "../chunk-PLOSP4XQ.js";
6
+ import "../chunk-G6MHJDVT.js";
7
7
  import "../chunk-CJYCVNW2.js";
8
- import "../chunk-PI4LLJG4.js";
8
+ import "../chunk-FPGXFD2M.js";
9
9
  import "../chunk-WYGD2UGN.js";
10
10
  import "../chunk-ZJXSXVFP.js";
11
11
  import "../chunk-IN4M4X7P.js";
12
- import "../chunk-2M34FLAY.js";
13
- import "../chunk-XTRDCSJB.js";
12
+ import "../chunk-BRGLDWUP.js";
13
+ import "../chunk-ZMJQUZQH.js";
14
14
  import "../chunk-UA5KS2PL.js";
15
15
  export {
16
16
  parseClass
@@ -191,8 +191,18 @@ export declare const classEntitySchema: z.ZodObject<{
191
191
  }, z.core.$strip>;
192
192
  count: z.ZodObject<{
193
193
  column: z.ZodString;
194
+ label: z.ZodOptional<z.ZodString>;
194
195
  }, z.core.$strip>;
195
196
  replaceable: z.ZodOptional<z.ZodBoolean>;
197
+ active: z.ZodOptional<z.ZodObject<{
198
+ column: z.ZodString;
199
+ label: z.ZodString;
200
+ verb: z.ZodString;
201
+ counter_label: z.ZodOptional<z.ZodString>;
202
+ create_label: z.ZodOptional<z.ZodString>;
203
+ create_verb: z.ZodOptional<z.ZodString>;
204
+ }, z.core.$strip>>;
205
+ head_resource: z.ZodOptional<z.ZodString>;
196
206
  }, z.core.$strip>>>;
197
207
  pool_grants: z.ZodOptional<z.ZodArray<z.ZodObject<{
198
208
  pool: z.ZodString;
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  classEntitySchema
3
- } from "../chunk-S56D6B6C.js";
4
- import "../chunk-23LZLBJK.js";
3
+ } from "../chunk-PLOSP4XQ.js";
4
+ import "../chunk-G6MHJDVT.js";
5
5
  import "../chunk-CJYCVNW2.js";
6
- import "../chunk-PI4LLJG4.js";
6
+ import "../chunk-FPGXFD2M.js";
7
7
  import "../chunk-WYGD2UGN.js";
8
8
  import "../chunk-ZJXSXVFP.js";
9
9
  import "../chunk-IN4M4X7P.js";
10
- import "../chunk-2M34FLAY.js";
11
- import "../chunk-XTRDCSJB.js";
10
+ import "../chunk-BRGLDWUP.js";
11
+ import "../chunk-ZMJQUZQH.js";
12
12
  import "../chunk-UA5KS2PL.js";
13
13
  export {
14
14
  classEntitySchema
@@ -2,8 +2,8 @@ import {
2
2
  resolveBaseItem,
3
3
  resolveBaseItemOfType,
4
4
  vaultPathToSlug
5
- } from "../chunk-WXWPK3LI.js";
6
- import "../chunk-6X4KUDMU.js";
5
+ } from "../chunk-CM5CWO4K.js";
6
+ import "../chunk-ZCTUYGNV.js";
7
7
  export {
8
8
  resolveBaseItem,
9
9
  resolveBaseItemOfType,
@@ -10,16 +10,26 @@ export declare function slugify(name: string): string;
10
10
  * `parts.slice(2).join("_")`. Tolerates a nullish slug (degrades to "") so a
11
11
  * malformed entity can't hard-crash the builder; the resolver backfills real slugs. */
12
12
  export declare function bareEntitySlug(slug: string | null | undefined): string;
13
- /** "[[SRD 2024/Classes/Fighter]]" to "fighter" (tail segment, slugified).
13
+ /** Whether a link tail is a stored registry slug (`me_feat_wish-magic`) rather than a human name
14
+ * ("Wish Magic", "Magic Initiate (Cleric)"). The ONE slug-form rule: `wikilinkTailSlug` reads a tail by it,
15
+ * and a registry-free display surface uses it to name a slug-form link instead of printing the raw slug. */
16
+ export declare function isStoredSlug(tail: string): boolean;
17
+ /** A link's BARE name slug, the key `bareEntitySlug` gives an owner: "[[SRD 2024/Classes/Fighter]]" and
18
+ * "[[srd-2024_class_fighter]]" both give "fighter".
14
19
  *
15
- * The tail goes through the SAME `slugify` that mints registry slugs, so an apostrophe is DELETED rather than
16
- * hyphenated ("Mage's Bane" to "mages-bane", where the old hand-rolled regex minted "mage-s-bane" and missed
17
- * every time). Only ever call this on a human NAME tail, never on a full `<prefix>_<name>` slug, which slugify
18
- * would destroy: `pc.decision-engine.ts`'s `resolveEntityRef` is the function that strips a `[[wikilink]]`
19
- * WITHOUT slugifying, and it is the one to use for a STORED slug.
20
+ * A link names an entity one of two ways, and the tail is read by its shape:
21
+ * - a human NAME tail (a path's file name, or a bare `[[fighter]]`) goes through the SAME `slugify` that mints
22
+ * registry slugs, so an apostrophe is DELETED rather than hyphenated ("Mage's Bane" to "mages-bane", where
23
+ * the old hand-rolled regex minted "mage-s-bane" and missed every time);
24
+ * - a STORED slug tail (`[[me_class_bard-captain-lugen-compatibility]]`, the form every PC note and the Me
25
+ * homebrew notes write) goes through `bareEntitySlug`. slugify DELETES the `_`, so it used to mint
26
+ * "meclassbard-captain-lugen-compatibility", no owner's bare slug: a Me subclass linking its class that way
27
+ * was never offered under it and the Builder's Class step called it an orphan (2026-09-25, Captain Lugen).
28
+ * The answer is the BARE slug, never the full one, so a lookup that needs the exact entity must not route a
29
+ * stored slug through here: `pc.decision-engine.ts`'s `resolveEntityRef` strips a `[[wikilink]]` WITHOUT this
30
+ * helper and looks the full slug up directly.
20
31
  *
21
32
  * MOVED here from `pc.decision-engine.ts` in R4-G5 T1, beside `bareEntitySlug`, so `pc.pools.ts` can use it
22
33
  * without importing the decision engine: the engine imports `pc.pools` for `strandedPicks`, and the old
23
- * direction would be a cycle. The engine keeps a re-export, so its three plugin importers and its own test
24
- * are untouched. */
34
+ * direction would be a cycle. The engine keeps a re-export for its plugin importer and its own test. */
25
35
  export declare function wikilinkTailSlug(link: string): string;
@@ -1,10 +1,12 @@
1
1
  import {
2
2
  bareEntitySlug,
3
+ isStoredSlug,
3
4
  slugify,
4
5
  wikilinkTailSlug
5
- } from "../chunk-6X4KUDMU.js";
6
+ } from "../chunk-ZCTUYGNV.js";
6
7
  export {
7
8
  bareEntitySlug,
9
+ isStoredSlug,
8
10
  slugify,
9
11
  wikilinkTailSlug
10
12
  };
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  featCodec
3
- } from "../chunk-3UNP3G4D.js";
4
- import "../chunk-22MOUU2G.js";
5
- import "../chunk-OYUEUKKF.js";
3
+ } from "../chunk-6ZY3U6BQ.js";
4
+ import "../chunk-4SLOJXJ4.js";
5
+ import "../chunk-LVX6TQ3R.js";
6
6
  import "../chunk-ZJXSXVFP.js";
7
- import "../chunk-2M34FLAY.js";
8
- import "../chunk-XTRDCSJB.js";
7
+ import "../chunk-BRGLDWUP.js";
8
+ import "../chunk-ZMJQUZQH.js";
9
9
  import "../chunk-UA5KS2PL.js";
10
10
  export {
11
11
  featCodec
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  parseFeat
3
- } from "../chunk-22MOUU2G.js";
4
- import "../chunk-OYUEUKKF.js";
3
+ } from "../chunk-4SLOJXJ4.js";
4
+ import "../chunk-LVX6TQ3R.js";
5
5
  import "../chunk-ZJXSXVFP.js";
6
- import "../chunk-2M34FLAY.js";
7
- import "../chunk-XTRDCSJB.js";
6
+ import "../chunk-BRGLDWUP.js";
7
+ import "../chunk-ZMJQUZQH.js";
8
8
  import "../chunk-UA5KS2PL.js";
9
9
  export {
10
10
  parseFeat
@@ -163,11 +163,24 @@ export declare const featEntitySchema: z.ZodObject<{
163
163
  kind: z.ZodLiteral<"damage-bonus">;
164
164
  damage_type: z.ZodString;
165
165
  amount: z.ZodString;
166
- applies_to: z.ZodOptional<z.ZodEnum<{
167
- weapon: "weapon";
166
+ applies_to: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
168
167
  spell: "spell";
169
168
  all: "all";
170
- }>>;
169
+ }>, z.ZodEnum<{
170
+ weapon: "weapon";
171
+ melee: "melee";
172
+ ranged: "ranged";
173
+ unarmed: "unarmed";
174
+ finesse: "finesse";
175
+ thrown: "thrown";
176
+ }>, z.ZodArray<z.ZodEnum<{
177
+ weapon: "weapon";
178
+ melee: "melee";
179
+ ranged: "ranged";
180
+ unarmed: "unarmed";
181
+ finesse: "finesse";
182
+ thrown: "thrown";
183
+ }>>]>>;
171
184
  condition: z.ZodOptional<z.ZodString>;
172
185
  subject: z.ZodOptional<z.ZodString>;
173
186
  }, z.core.$strip>, z.ZodObject<{
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  featEntitySchema
3
- } from "../chunk-OYUEUKKF.js";
3
+ } from "../chunk-LVX6TQ3R.js";
4
4
  import "../chunk-ZJXSXVFP.js";
5
- import "../chunk-2M34FLAY.js";
6
- import "../chunk-XTRDCSJB.js";
5
+ import "../chunk-BRGLDWUP.js";
6
+ import "../chunk-ZMJQUZQH.js";
7
7
  import "../chunk-UA5KS2PL.js";
8
8
  export {
9
9
  featEntitySchema