@archivist-gg/dnd5e 0.3.11 → 0.3.17

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 (192) 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-XTRDCSJB.js → chunk-2JSQE3DD.js} +15 -1
  11. package/dist/chunk-2LULMQTF.js +14 -0
  12. package/dist/{chunk-MAH6DCRI.js → chunk-2UDSN6VW.js} +1 -1
  13. package/dist/chunk-3LWMFYKS.js +57 -0
  14. package/dist/{chunk-JCEV7KYN.js → chunk-3MGQFFNE.js} +1 -1
  15. package/dist/chunk-3VZZDKRA.js +1014 -0
  16. package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
  17. package/dist/{chunk-2M34FLAY.js → chunk-5MXFW4O3.js} +9 -3
  18. package/dist/{chunk-4DOMDEBZ.js → chunk-6EI737IO.js} +1 -1
  19. package/dist/{chunk-G247QXWW.js → chunk-7ATNGKBS.js} +1 -1
  20. package/dist/{chunk-XY6X2APM.js → chunk-7Q2VPKCD.js} +17 -0
  21. package/dist/{chunk-T2SNEJOE.js → chunk-7QN7XSAK.js} +1 -1
  22. package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
  23. package/dist/{chunk-7YU4NPKR.js → chunk-AZRGFUSR.js} +1 -1
  24. package/dist/{chunk-PP2UHLBA.js → chunk-B3DP42OM.js} +5 -0
  25. package/dist/chunk-CM5CWO4K.js +735 -0
  26. package/dist/{chunk-MQ747UCR.js → chunk-DOXSFYLH.js} +70 -2
  27. package/dist/chunk-EJP263OP.js +186 -0
  28. package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
  29. package/dist/{chunk-V6LJFP4R.js → chunk-FANQVQ3D.js} +2 -2
  30. package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
  31. package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
  32. package/dist/{chunk-JANNRGJC.js → chunk-G6PBI2BU.js} +1 -1
  33. package/dist/chunk-H5PTKYXL.js +101 -0
  34. package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
  35. package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
  36. package/dist/chunk-HTYMW5CH.js +228 -0
  37. package/dist/chunk-IHE6KVC3.js +13 -0
  38. package/dist/{chunk-QHMWA3SZ.js → chunk-JCMUVZIK.js} +1 -1
  39. package/dist/{chunk-V373TRJE.js → chunk-JSM6JFZR.js} +198 -125
  40. package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
  41. package/dist/chunk-KR6JF3BF.js +14 -0
  42. package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
  43. package/dist/chunk-LBEXLN6I.js +91 -0
  44. package/dist/{chunk-BLRW2UU6.js → chunk-LF5AGJA4.js} +2 -2
  45. package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
  46. package/dist/{chunk-BIA32MQ5.js → chunk-MBX25B6D.js} +1 -1
  47. package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
  48. package/dist/{chunk-J77CKYV3.js → chunk-OFCSP6MT.js} +1 -1
  49. package/dist/{chunk-2INMRR3Q.js → chunk-ONTGZR5T.js} +326 -149
  50. package/dist/{chunk-MWCCGPG3.js → chunk-OOSRUJBI.js} +3 -2
  51. package/dist/{chunk-U3BABVJF.js → chunk-PKX6TGRE.js} +2 -2
  52. package/dist/{chunk-PJMG5XV3.js → chunk-PQZ4LM4Z.js} +1 -1
  53. package/dist/chunk-PXVNAY7T.js +84 -0
  54. package/dist/chunk-QH36K2PU.js +158 -0
  55. package/dist/{chunk-R747YKS7.js → chunk-QZSWN2KT.js} +1 -1
  56. package/dist/{chunk-CHUALUIX.js → chunk-RYLXAYIQ.js} +1 -1
  57. package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
  58. package/dist/{chunk-PZCE7DJM.js → chunk-T6QIF5XR.js} +31 -1
  59. package/dist/{chunk-CBEKVAX4.js → chunk-TULQ4FFX.js} +41 -13
  60. package/dist/{chunk-S56D6B6C.js → chunk-UUBJCNQU.js} +12 -3
  61. package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
  62. package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
  63. package/dist/{chunk-3HX5VLWP.js → chunk-VRV3NNTA.js} +2 -2
  64. package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
  65. package/dist/{chunk-BL3VELKP.js → chunk-Y5VVP73C.js} +1 -1
  66. package/dist/{chunk-PI4LLJG4.js → chunk-YD2VAHA6.js} +2 -2
  67. package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
  68. package/dist/{chunk-NWDF5HG3.js → chunk-YKL6SHRJ.js} +1 -1
  69. package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
  70. package/dist/chunk-ZUQW5VBZ.js +89 -0
  71. package/dist/class/class.codec.js +7 -7
  72. package/dist/class/class.parser.js +6 -6
  73. package/dist/class/class.schema.d.ts +18 -0
  74. package/dist/class/class.schema.js +5 -5
  75. package/dist/class/class.standard-array.d.ts +16 -0
  76. package/dist/class/class.standard-array.js +20 -0
  77. package/dist/class/class.types.d.ts +3 -0
  78. package/dist/dnd/amount-text.d.ts +38 -0
  79. package/dist/dnd/amount-text.js +13 -0
  80. package/dist/dnd/resource-words.d.ts +4 -0
  81. package/dist/dnd/resource-words.js +30 -0
  82. package/dist/entities/base-item-resolver.js +2 -2
  83. package/dist/entities/slug.d.ts +18 -8
  84. package/dist/entities/slug.js +3 -1
  85. package/dist/feat/feat.codec.js +5 -5
  86. package/dist/feat/feat.parser.js +4 -4
  87. package/dist/feat/feat.schema.d.ts +41 -3
  88. package/dist/feat/feat.schema.js +3 -3
  89. package/dist/index.js +7513 -4177
  90. package/dist/item/item.actions-map.d.ts +40 -5
  91. package/dist/item/item.actions-map.js +5 -84
  92. package/dist/item/item.attunement.js +3 -9
  93. package/dist/item/item.bonuses.js +5 -2
  94. package/dist/item/item.codec.js +3 -3
  95. package/dist/item/item.conditions.js +4 -1
  96. package/dist/item/item.conditions.types.d.ts +4 -0
  97. package/dist/item/item.cost.d.ts +3 -0
  98. package/dist/item/item.cost.js +29 -0
  99. package/dist/item/item.icon.d.ts +15 -0
  100. package/dist/item/item.icon.js +211 -0
  101. package/dist/item/item.parser.js +2 -2
  102. package/dist/item/item.schema.d.ts +16 -1
  103. package/dist/item/item.schema.js +3 -1
  104. package/dist/item/item.types.d.ts +9 -2
  105. package/dist/monster/monster.parser.js +5 -5
  106. package/dist/monster/monster.schema.js +4 -4
  107. package/dist/optional-feature/optional-feature.codec.js +5 -4
  108. package/dist/optional-feature/optional-feature.parser.js +4 -3
  109. package/dist/optional-feature/optional-feature.schema.d.ts +255 -3
  110. package/dist/optional-feature/optional-feature.schema.js +7 -2
  111. package/dist/pc/pc.additional-spells.js +3 -3
  112. package/dist/pc/pc.amount-bindings.d.ts +32 -0
  113. package/dist/pc/pc.amount-bindings.js +23 -0
  114. package/dist/pc/pc.asi-flatten.d.ts +62 -1
  115. package/dist/pc/pc.asi-flatten.js +16 -0
  116. package/dist/pc/pc.conditions.js +1 -1
  117. package/dist/pc/pc.containment.d.ts +45 -0
  118. package/dist/pc/pc.containment.js +24 -0
  119. package/dist/pc/pc.decision-engine.d.ts +24 -3
  120. package/dist/pc/pc.decision-engine.js +26 -16
  121. package/dist/pc/pc.entry-overrides.d.ts +79 -0
  122. package/dist/pc/pc.entry-overrides.js +40 -0
  123. package/dist/pc/pc.equipment.d.ts +2 -2
  124. package/dist/pc/pc.equipment.js +19 -7
  125. package/dist/pc/pc.feature-effects.d.ts +12 -0
  126. package/dist/pc/pc.feature-effects.js +2 -2
  127. package/dist/pc/pc.infusions.d.ts +228 -0
  128. package/dist/pc/pc.infusions.js +64 -0
  129. package/dist/pc/pc.member-choices.d.ts +90 -0
  130. package/dist/pc/pc.member-choices.js +32 -0
  131. package/dist/pc/pc.parser.js +18 -1
  132. package/dist/pc/pc.pools.d.ts +8 -1
  133. package/dist/pc/pc.pools.js +13 -3
  134. package/dist/pc/pc.proficiencies.js +23 -15
  135. package/dist/pc/pc.proficiency-query.js +6 -0
  136. package/dist/pc/pc.recalc.d.ts +39 -36
  137. package/dist/pc/pc.recalc.js +115 -70
  138. package/dist/pc/pc.resolver.d.ts +2 -1
  139. package/dist/pc/pc.resolver.js +22 -14
  140. package/dist/pc/pc.resource-seed.js +1 -1
  141. package/dist/pc/pc.resources.d.ts +6 -1
  142. package/dist/pc/pc.resources.js +3 -1
  143. package/dist/pc/pc.rest.d.ts +21 -1
  144. package/dist/pc/pc.rest.js +52 -19
  145. package/dist/pc/pc.schema.d.ts +43 -2
  146. package/dist/pc/pc.schema.js +1 -1
  147. package/dist/pc/pc.slotting.d.ts +36 -3
  148. package/dist/pc/pc.slotting.js +13 -5
  149. package/dist/pc/pc.tool-picks.d.ts +51 -0
  150. package/dist/pc/pc.tool-picks.js +18 -0
  151. package/dist/pc/pc.types.d.ts +115 -14
  152. package/dist/pc/pc.weapon-grant.d.ts +15 -0
  153. package/dist/pc/pool-layout.d.ts +8 -0
  154. package/dist/pc/pool-layout.js +5 -3
  155. package/dist/pc/resource-equivalents.d.ts +44 -0
  156. package/dist/pc/spell-source.js +4 -9
  157. package/dist/race/race.codec.js +6 -6
  158. package/dist/race/race.parser.js +5 -5
  159. package/dist/race/race.schema.js +4 -4
  160. package/dist/schemas/attack-schema.d.ts +1 -1
  161. package/dist/schemas/choice-schema.js +2 -2
  162. package/dist/schemas/feature-effect-schema.d.ts +41 -3
  163. package/dist/schemas/feature-effect-schema.js +1 -1
  164. package/dist/schemas/feature-schema.js +3 -3
  165. package/dist/schemas/selection-pool-schema.d.ts +10 -0
  166. package/dist/schemas/selection-pool-schema.js +1 -1
  167. package/dist/spell/spell.codec.js +2 -2
  168. package/dist/spell/spell.parser.d.ts +6 -1
  169. package/dist/spell/spell.parser.js +5 -3
  170. package/dist/spell/spell.types.d.ts +10 -0
  171. package/dist/srd/retired-items.d.ts +14 -0
  172. package/dist/srd/retired-items.js +11 -0
  173. package/dist/subclass/subclass.codec.js +7 -7
  174. package/dist/subclass/subclass.parser.js +6 -6
  175. package/dist/subclass/subclass.schema.d.ts +10 -0
  176. package/dist/subclass/subclass.schema.js +5 -5
  177. package/dist/types/choice.d.ts +13 -0
  178. package/dist/types/equipment-grant.d.ts +18 -1
  179. package/dist/types/equipment-grant.js +12 -0
  180. package/dist/types/feature-effect.d.ts +12 -1
  181. package/dist/types/optional-feature.types.d.ts +84 -1
  182. package/dist/types/selection-pool.d.ts +18 -3
  183. package/dist/weapon/weapon.classify.d.ts +10 -8
  184. package/dist/weapon/weapon.classify.js +2 -2
  185. package/dist/weapon/weapon.codec.js +3 -3
  186. package/dist/weapon/weapon.parser.js +2 -2
  187. package/dist/weapon/weapon.schema.d.ts +1 -0
  188. package/dist/weapon/weapon.schema.js +1 -1
  189. package/dist/weapon/weapon.types.d.ts +2 -0
  190. package/package.json +1 -1
  191. package/dist/chunk-O4SRD3J5.js +0 -165
  192. package/dist/chunk-WXWPK3LI.js +0 -55
package/LICENSES/SRD.md CHANGED
@@ -27,8 +27,9 @@ Coast. This project is unofficial and not affiliated with or endorsed by Wizards
27
27
 
28
28
  ## Provenance and changes made (CC-BY "indicate if changes were made")
29
29
 
30
- The shipped SRD data is MODIFIED, and it is a MERGE. It was not taken from the SRD PDFs. It is
31
- assembled by `tools/srd-canonical/` from:
30
+ The shipped SRD data is MODIFIED, and it is a MERGE. Apart from the few SRD 5.2 equipment
31
+ descriptions transcribed from the document itself (below), it was not taken from the SRD PDFs. It
32
+ is assembled by `tools/srd-canonical/` from:
32
33
 
33
34
  - the **Open5e** v2 API, queried with the official-SRD document filter
34
35
  `document__key__in=srd-2014` / `srd-2024`, the immediate redistribution source of the SRD
@@ -36,8 +37,13 @@ assembled by `tools/srd-canonical/` from:
36
37
  - a structured-rules JSON dump, used to enrich mechanical fields, to expand the SRD's generic
37
38
  magic-item variants into one entity per base item, and, for the 15 conditions per edition, as
38
39
  the text source (Open5e exposes no condition endpoint for these documents);
40
+ - the **SRD 5.2** document itself (`SRD_CC_v5.2.pdf`,
41
+ https://media.dndbeyond.com/compendium-images/srd/5.2/SRD_CC_v5.2.pdf, CC-BY-4.0), for the
42
+ 2024 equipment descriptions Open5e does not carry, transcribed verbatim into the overlay (see
43
+ the equipment paragraph below);
39
44
  - virtual-tabletop activation data, used to derive typed item effects;
40
- - a hand-curated overlay (`tools/srd-canonical/overlays/`), authored for this project.
45
+ - a hand-curated overlay (`tools/srd-canonical/overlays/`), authored for this project apart from
46
+ the SRD 5.2 transcriptions it carries.
41
47
 
42
48
  Content is reformatted to this project's schema and to Markdown, cross-references become vault
43
49
  wikilinks, and dice and save expressions become this project's inline roll tags; narrative prose
@@ -53,4 +59,33 @@ the ENTITY and not about every byte of its text, the emit path additionally runs
53
59
  markup (reference tags, source-book abbreviation suffixes, template pointers, third-party
54
60
  database identifiers) and the editorial commentary its contributors wrote about the SRD.
55
61
 
62
+ The mundane equipment (adventuring gear including the packs and poisons, ammunition, spellcasting
63
+ foci, artisan's tools, tools, musical instruments and gaming sets; the gear pass,
64
+ `tools/srd-canonical/merger-rules/gear-merge.ts`) follows the same rules. A record is selected by
65
+ the structured-rules dump's own per-entry SRD flags or, for the members listed in
66
+ `tools/srd-canonical/data/gear-open5e-join.json` (Map, String, Firearm Bullets (10), Dragonchess
67
+ Set and Three-Dragon Ante Set, which Open5e's `srd-2024` document carries but the dump leaves
68
+ unflagged), by Open5e's document filter. Firearm Bullet, also listed, ships as the single piece of
69
+ the SRD's Firearm Bullets (10), as the flagged single pieces (Arrow, Bolt, Needle, Sling Bullet)
70
+ do for their bundles. Names, structure (type, weight, cost, focus kind, container capacity) and
71
+ the `pack_contents` strings, including the seven SRD pack phrases that name no item of their own
72
+ ("10 feet of string", "alms box", "block of incense", "censer", "vestments", "little bag of
73
+ sand", "small knife"), come from the structured-rules data, a name being the SRD name the dump
74
+ records where it records one; two SRD 5.2 poisons carry their SRD 5.2 names, Spider's Sting and
75
+ Crawler Mucus. The container data of the following records comes instead from the hand-curated
76
+ overlay: the Portable Hole (a magic item, in both editions), marked as a container whose
77
+ contents weigh nothing, where the dump carries no container capacity; the 2014 Scholar's Pack,
78
+ whose `pack_contents` carry the ten sheets of parchment its SRD 5.1 description names
79
+ (`Parchment (one sheet) (x10)`), where the dump lists one; and the 2024 Chest and Vial, whose
80
+ `holds_items` says the Chest holds items (the dump gives it a volume only) and the Vial (which
81
+ holds up to 4 ounces of liquid) holds no items. The text comes from Open5e (its items and item
82
+ sets under the same document filter), never from the structured-rules dump. The 2024 records
83
+ without usable Open5e text
84
+ (fourteen poisons, the five arcane foci and the Glass Bottle, each listed with its page in
85
+ `tools/srd-canonical/overlays/srd-2024.yaml`) are transcribed verbatim from the SRD 5.2 document
86
+ and checked against it by `tools/srd-canonical/verify-srd52-transcriptions.ts`. The 2024 Belt of
87
+ Giant Strength (Frost or Stone) takes its Strength score, 23, from the hand-curated overlay,
88
+ transcribed from the SRD 5.2 table, because the structured-rules data names the frost and stone
89
+ giants' belts separately.
90
+
56
91
  Credit to **Open5e** (https://open5e.com) as the immediate SRD-redistribution source.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  armorCodec
3
- } from "../chunk-AW3EHF3L.js";
4
- import "../chunk-5N2GW72F.js";
5
- import "../chunk-JC5UNIVM.js";
3
+ } from "../chunk-FC4IGH5Y.js";
4
+ import "../chunk-UZXG6QSY.js";
5
+ import "../chunk-HS6FIOLP.js";
6
6
  import "../chunk-UA5KS2PL.js";
7
7
  export {
8
8
  armorCodec
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parseArmor
3
- } from "../chunk-5N2GW72F.js";
4
- import "../chunk-JC5UNIVM.js";
3
+ } from "../chunk-UZXG6QSY.js";
4
+ import "../chunk-HS6FIOLP.js";
5
5
  import "../chunk-UA5KS2PL.js";
6
6
  export {
7
7
  parseArmor
@@ -22,6 +22,7 @@ export declare const armorEntitySchema: z.ZodObject<{
22
22
  edition: z.ZodOptional<z.ZodString>;
23
23
  entries: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
24
24
  rendering_hint: z.ZodOptional<z.ZodString>;
25
+ icon: z.ZodOptional<z.ZodString>;
25
26
  has_fluff: z.ZodOptional<z.ZodBoolean>;
26
27
  has_fluff_images: z.ZodOptional<z.ZodBoolean>;
27
28
  image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  armorEntitySchema
3
- } from "../chunk-JC5UNIVM.js";
3
+ } from "../chunk-HS6FIOLP.js";
4
4
  import "../chunk-UA5KS2PL.js";
5
5
  export {
6
6
  armorEntitySchema
@@ -26,6 +26,8 @@ export interface ArmorEntity {
26
26
  entries?: unknown[];
27
27
  /** Carried as the empty string on every converter armor carrier today (27). */
28
28
  rendering_hint?: string;
29
+ /** The icon key (I3): a key of the renderer's icon set or a Lucide name. */
30
+ icon?: string;
29
31
  has_fluff?: boolean;
30
32
  has_fluff_images?: boolean;
31
33
  /** One wikilink, or an array for >= 2 fluff images (images-ON emit). */
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  backgroundCodec
3
- } from "../chunk-MAH6DCRI.js";
4
- import "../chunk-4DOMDEBZ.js";
5
- import "../chunk-JCEV7KYN.js";
3
+ } from "../chunk-2UDSN6VW.js";
4
+ import "../chunk-6EI737IO.js";
5
+ import "../chunk-3MGQFFNE.js";
6
6
  import "../chunk-IN4M4X7P.js";
7
- import "../chunk-2M34FLAY.js";
8
- import "../chunk-XTRDCSJB.js";
7
+ import "../chunk-5MXFW4O3.js";
8
+ import "../chunk-2JSQE3DD.js";
9
9
  import "../chunk-UA5KS2PL.js";
10
10
  export {
11
11
  backgroundCodec
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  parseBackground
3
- } from "../chunk-4DOMDEBZ.js";
4
- import "../chunk-JCEV7KYN.js";
3
+ } from "../chunk-6EI737IO.js";
4
+ import "../chunk-3MGQFFNE.js";
5
5
  import "../chunk-IN4M4X7P.js";
6
- import "../chunk-2M34FLAY.js";
7
- import "../chunk-XTRDCSJB.js";
6
+ import "../chunk-5MXFW4O3.js";
7
+ import "../chunk-2JSQE3DD.js";
8
8
  import "../chunk-UA5KS2PL.js";
9
9
  export {
10
10
  parseBackground
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  backgroundEntitySchema,
3
3
  langProfSchema
4
- } from "../chunk-JCEV7KYN.js";
4
+ } from "../chunk-3MGQFFNE.js";
5
5
  import "../chunk-IN4M4X7P.js";
6
- import "../chunk-2M34FLAY.js";
7
- import "../chunk-XTRDCSJB.js";
6
+ import "../chunk-5MXFW4O3.js";
7
+ import "../chunk-2JSQE3DD.js";
8
8
  import "../chunk-UA5KS2PL.js";
9
9
  export {
10
10
  backgroundEntitySchema,
@@ -3,9 +3,21 @@ 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 }),
10
+ // SL (2026-09-27): the `skill-bonus` twin for saving throws (Aura of Protection). `saves` absent = every save; `inactive_while` turns
11
+ // the bonus off while the character is incapacitated (any condition that disables actions) or unconscious.
12
+ z.object({
13
+ kind: z.literal("save-bonus"),
14
+ ability: abilityEnum,
15
+ minimum: z.number().int().optional(),
16
+ saves: z.array(abilityEnum).nonempty().optional(),
17
+ inactive_while: z.enum(["incapacitated", "unconscious"]).optional(),
18
+ condition: conditionField,
19
+ subject: subjectField
20
+ }),
9
21
  // Jack of All Trades / Remarkable Athlete: half the proficiency bonus, and ONLY on a skill the character is
10
22
  // not already proficient in — the "doesn't otherwise use your Proficiency Bonus" clause is the whole mechanic,
11
23
  // so it is the kind's semantics, not a field. `skills` omitted = every skill (Jack of All Trades); a list
@@ -68,7 +80,9 @@ var featureEffectSchema = z.discriminatedUnion("kind", [
68
80
  // canonical damage types. Do not tighten to an enum.
69
81
  damage_type: z.string().min(1),
70
82
  amount: z.string().min(1),
71
- applies_to: z.enum(["weapon", "spell", "all"]).optional(),
83
+ // ART-c1 Task 9b: `spell` and `all` as before, or a weapon scope, one word or an any-of list, which the engine
84
+ // evaluates per attack row (pc.recalc.ts `riderReachesRow`). `weapon`, like an absent value, reaches every row.
85
+ applies_to: z.union([z.enum(["spell", "all"]), weaponScopeEnum, z.array(weaponScopeEnum).min(1)]).optional(),
72
86
  condition: conditionField,
73
87
  subject: subjectField
74
88
  }),
@@ -0,0 +1,14 @@
1
+ // src/types/equipment-grant.ts
2
+ function isCategoryGrant(g) {
3
+ return !!g && typeof g === "object" && typeof g.category === "string" && g.category.length > 0;
4
+ }
5
+ var equipmentCategoryKey = (i, j, k) => `equipment-${i}-opt-${j}-cat-${k}`;
6
+ var equipmentCategoryKeys = (grants, i, j) => grants.flatMap((g, k) => isCategoryGrant(g) ? [equipmentCategoryKey(i, j, k)] : []);
7
+ var isStartingEquipmentKey = (key) => key.startsWith("equipment-");
8
+
9
+ export {
10
+ isCategoryGrant,
11
+ equipmentCategoryKey,
12
+ equipmentCategoryKeys,
13
+ isStartingEquipmentKey
14
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseBackground
3
- } from "./chunk-4DOMDEBZ.js";
3
+ } from "./chunk-6EI737IO.js";
4
4
 
5
5
  // src/background/background.codec.ts
6
6
  import yaml from "js-yaml";
@@ -0,0 +1,57 @@
1
+ import {
2
+ classifyWeaponRange
3
+ } from "./chunk-YDGMBMYI.js";
4
+
5
+ // src/pc/pc.weapon-grant.ts
6
+ var PROPERTY_KEY = {
7
+ "2h": "two_handed",
8
+ "two-handed": "two_handed",
9
+ "two handed": "two_handed",
10
+ h: "heavy",
11
+ l: "light",
12
+ f: "finesse",
13
+ t: "thrown",
14
+ v: "versatile",
15
+ r: "reach",
16
+ a: "ammunition",
17
+ ld: "loading",
18
+ s: "special"
19
+ };
20
+ var propertyKey = (word) => {
21
+ var _a;
22
+ const w = word.trim().toLowerCase();
23
+ return (_a = PROPERTY_KEY[w]) != null ? _a : w.replace(/[\s-]+/g, "_");
24
+ };
25
+ var GRANT_RE = new RegExp(
26
+ "^(?:all\\s+)?(?:(melee|ranged)\\s+)?(simple|martial)(?:\\s+(melee|ranged))?\\s+weapons?\\s+(?:that|which)\\s+(have|has|don'?t\\s+have|do\\s+not\\s+have|doesn'?t\\s+have|does\\s+not\\s+have)\\s+the\\s+(.+?)\\s+propert(?:y|ies)\\.?$",
27
+ "i"
28
+ );
29
+ function parseQualifiedWeaponGrant(text) {
30
+ var _a, _b;
31
+ const m = GRANT_RE.exec(text.replace(/’/g, "'").trim().replace(/\s+/g, " "));
32
+ if (!m) return null;
33
+ const range = (_b = (_a = m[1]) != null ? _a : m[3]) == null ? void 0 : _b.toLowerCase();
34
+ const properties = m[5].split(/\s*,\s*|\s+or\s+|\s+and\s+/i).map((w) => w.trim()).filter(Boolean).map(propertyKey);
35
+ if (properties.length === 0) return null;
36
+ return {
37
+ category: m[2].toLowerCase(),
38
+ ...range ? { range } : {},
39
+ properties,
40
+ without: /n'?t|not/i.test(m[4])
41
+ };
42
+ }
43
+ function qualifiedGrantCovers(text, weapon) {
44
+ const g = parseQualifiedWeaponGrant(text);
45
+ if (!g || typeof weapon.category !== "string") return false;
46
+ if (!new RegExp(`^${g.category}\\b`).test(weapon.category)) return false;
47
+ if (g.range) {
48
+ const melee = classifyWeaponRange(weapon).melee !== null;
49
+ if (g.range === "melee" !== melee) return false;
50
+ }
51
+ const has = g.properties.some((p) => weapon.properties.some((x) => x === p));
52
+ return g.without ? !has : has;
53
+ }
54
+
55
+ export {
56
+ qualifiedGrantCovers
57
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-IN4M4X7P.js";
4
4
  import {
5
5
  choiceSchema
6
- } from "./chunk-2M34FLAY.js";
6
+ } from "./chunk-5MXFW4O3.js";
7
7
  import {
8
8
  additionalSpellsEntrySchema,
9
9
  imageField