@archivist-gg/dnd5e 0.3.1 → 0.3.4

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 (259) hide show
  1. package/LICENSES/SRD.md +25 -6
  2. package/dist/armor/armor.codec.js +4 -3
  3. package/dist/armor/armor.parser.js +3 -2
  4. package/dist/armor/armor.schema.d.ts +4 -0
  5. package/dist/armor/armor.schema.js +2 -1
  6. package/dist/armor/armor.types.d.ts +8 -0
  7. package/dist/background/background.codec.js +7 -6
  8. package/dist/background/background.parser.js +6 -5
  9. package/dist/background/background.schema.d.ts +26 -0
  10. package/dist/background/background.schema.js +5 -4
  11. package/dist/background/background.types.d.ts +22 -0
  12. package/dist/{chunk-4TIJKN6O.js → chunk-23LZLBJK.js} +1 -1
  13. package/dist/{chunk-AFKTJXRA.js → chunk-2DFENQIJ.js} +18 -0
  14. package/dist/chunk-2FRUSVZS.js +489 -0
  15. package/dist/chunk-4FWNK4FD.js +159 -0
  16. package/dist/chunk-4U55VNC7.js +22 -0
  17. package/dist/{chunk-4JHOHWBI.js → chunk-4XTNPNQB.js} +1 -1
  18. package/dist/{chunk-HCP3GMHS.js → chunk-5N2GW72F.js} +15 -2
  19. package/dist/{chunk-42Y5IJKT.js → chunk-5U5FFFA3.js} +5 -1
  20. package/dist/{chunk-4F6AIZ36.js → chunk-5XMQPTHD.js} +1 -1
  21. package/dist/{chunk-GJOI2GHP.js → chunk-6GNXYAYP.js} +1 -1
  22. package/dist/chunk-6PKV5V2H.js +178 -0
  23. package/dist/{chunk-66XXW2Z2.js → chunk-6PXTNCBP.js} +2 -2
  24. package/dist/chunk-6X2NV665.js +33 -0
  25. package/dist/{chunk-LV4SNWZQ.js → chunk-6X4KUDMU.js} +8 -1
  26. package/dist/{chunk-ZMR77DDL.js → chunk-AW3EHF3L.js} +1 -1
  27. package/dist/chunk-CJYCVNW2.js +7 -0
  28. package/dist/chunk-COEOOQX2.js +133 -0
  29. package/dist/{chunk-XTIQWSFM.js → chunk-D5U7GMPX.js} +1 -1
  30. package/dist/{chunk-RAWJTA45.js → chunk-DEEHHLAP.js} +1 -1
  31. package/dist/{chunk-6IRYTM5V.js → chunk-DPUJDOKV.js} +119 -28
  32. package/dist/{chunk-73HOFQQ5.js → chunk-ESS46GR4.js} +1 -1
  33. package/dist/chunk-EVMUJYUD.js +195 -0
  34. package/dist/{chunk-2BWAID3Y.js → chunk-FDBWYMZK.js} +29 -3
  35. package/dist/{chunk-K6Q5OUGK.js → chunk-GFZ7PITJ.js} +86 -10
  36. package/dist/chunk-H7KBLR4X.js +81 -0
  37. package/dist/{chunk-L7E2UT5A.js → chunk-HB7XZXDK.js} +5 -1
  38. package/dist/{chunk-BIK4DFWK.js → chunk-HJ5EEZ47.js} +1 -1
  39. package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
  40. package/dist/{chunk-TN6ZLTNU.js → chunk-I2NDWFDD.js} +51 -4
  41. package/dist/{chunk-RSDRMH54.js → chunk-IMZFOOVL.js} +1 -1
  42. package/dist/{chunk-3DZ74AKK.js → chunk-IN4M4X7P.js} +8 -2
  43. package/dist/chunk-IUAAXXNO.js +58 -0
  44. package/dist/{chunk-XJNECUPT.js → chunk-JC5UNIVM.js} +19 -0
  45. package/dist/chunk-JJ46T5XX.js +297 -0
  46. package/dist/{chunk-SE7AZDR3.js → chunk-JRDPUDT5.js} +29 -3
  47. package/dist/{chunk-24GFQU7T.js → chunk-JSZ4H6AQ.js} +1 -1
  48. package/dist/chunk-KU3YLF6D.js +106 -0
  49. package/dist/{chunk-5INR4NSL.js → chunk-LDDCNPHD.js} +1 -1
  50. package/dist/{chunk-5ZBE4CWV.js → chunk-LMBAEIP6.js} +1 -1
  51. package/dist/chunk-LVQLWRCU.js +15 -0
  52. package/dist/chunk-MI7P3NX3.js +161 -0
  53. package/dist/chunk-O4SRD3J5.js +165 -0
  54. package/dist/{chunk-D3CLOBE3.js → chunk-OSQFPGLM.js} +44 -8
  55. package/dist/chunk-OZP6JFGT.js +162 -0
  56. package/dist/{chunk-NAEPSZAM.js → chunk-PDJSUH24.js} +24 -2
  57. package/dist/chunk-PP2UHLBA.js +50 -0
  58. package/dist/chunk-PVCEA4HZ.js +6 -0
  59. package/dist/{chunk-XLSVNUTK.js → chunk-R3VAKWKW.js} +1 -1
  60. package/dist/chunk-RIXI5D3R.js +89 -0
  61. package/dist/chunk-RLGQ5PZZ.js +16 -0
  62. package/dist/chunk-S7REMWW4.js +21 -0
  63. package/dist/{chunk-7VJ6BOA5.js → chunk-SMLXZUBH.js} +9 -1
  64. package/dist/{chunk-NXSWH3AE.js → chunk-T26ZVCL5.js} +1 -1
  65. package/dist/chunk-TOM66P2P.js +38 -0
  66. package/dist/chunk-UA5KS2PL.js +26 -0
  67. package/dist/{chunk-N6N74K6X.js → chunk-UBBKSYBY.js} +1 -1
  68. package/dist/{chunk-353WXS6S.js → chunk-UIRMA5KM.js} +1 -1
  69. package/dist/{chunk-GE4TLPWM.js → chunk-US5IKYCW.js} +1 -1
  70. package/dist/chunk-UXPGW4TI.js +101 -0
  71. package/dist/chunk-VQAXTIBW.js +100 -0
  72. package/dist/{chunk-WP2CX2JO.js → chunk-WELIKLZF.js} +22 -1
  73. package/dist/chunk-WPWOHGPI.js +172 -0
  74. package/dist/{chunk-GZ46OVGZ.js → chunk-WSVMLNTO.js} +1 -1
  75. package/dist/{chunk-4LZJXJJS.js → chunk-WXWPK3LI.js} +6 -2
  76. package/dist/{chunk-ZZGEVJKX.js → chunk-XBQMCEI2.js} +1 -1
  77. package/dist/{chunk-PHQRGDRQ.js → chunk-XGOFP7AQ.js} +5 -1
  78. package/dist/chunk-XJ2F2WO6.js +8 -0
  79. package/dist/chunk-XQCSGNXE.js +1580 -0
  80. package/dist/chunk-YBLDE5CG.js +42 -0
  81. package/dist/{chunk-JEYQU3JT.js → chunk-YHYTW5QA.js} +2 -18
  82. package/dist/{chunk-TLYDBT5F.js → chunk-YJJTISBN.js} +64 -7
  83. package/dist/{chunk-PZOWBI3B.js → chunk-YLL2QXY2.js} +7 -2
  84. package/dist/{chunk-MDEJHMKK.js → chunk-ZONJ66NE.js} +26 -5
  85. package/dist/class/class.codec.js +12 -9
  86. package/dist/class/class.parser.js +11 -8
  87. package/dist/class/class.schema.d.ts +55 -3
  88. package/dist/class/class.schema.js +9 -7
  89. package/dist/class/class.types.d.ts +48 -3
  90. package/dist/condition/condition.codec.d.ts +9 -0
  91. package/dist/condition/condition.entity-type.d.ts +2 -0
  92. package/dist/condition/condition.parser.d.ts +13 -0
  93. package/dist/condition/condition.parser.js +7 -0
  94. package/dist/condition/condition.schema.d.ts +29 -0
  95. package/dist/condition/condition.types.d.ts +15 -0
  96. package/dist/condition/condition.types.js +0 -0
  97. package/dist/dnd/constants.d.ts +22 -0
  98. package/dist/dnd/constants.js +9 -3
  99. package/dist/dnd/formula-tags.js +2 -2
  100. package/dist/dnd/math.d.ts +26 -0
  101. package/dist/dnd/math.js +12 -2
  102. package/dist/dnd/prose-tags.js +1 -1
  103. package/dist/dnd/resource-formula.d.ts +36 -10
  104. package/dist/dnd/resource-formula.js +10 -155
  105. package/dist/dnd/srd-tag-converter.js +3 -3
  106. package/dist/dnd/tag-grammar.js +1 -1
  107. package/dist/dnd/warn-once.d.ts +2 -0
  108. package/dist/dnd/warn-once.js +8 -0
  109. package/dist/entities/base-item-resolver.js +2 -2
  110. package/dist/entities/slug.d.ts +13 -0
  111. package/dist/entities/slug.js +5 -3
  112. package/dist/entities/wikilink-display.d.ts +3 -0
  113. package/dist/entities/wikilink-display.js +10 -0
  114. package/dist/feat/feat.category-codes.d.ts +32 -0
  115. package/dist/feat/feat.category-codes.js +14 -0
  116. package/dist/feat/feat.codec.js +7 -5
  117. package/dist/feat/feat.parser.js +6 -4
  118. package/dist/feat/feat.schema.d.ts +230 -0
  119. package/dist/feat/feat.schema.js +5 -3
  120. package/dist/feat/feat.types.d.ts +37 -1
  121. package/dist/index.js +2033 -6907
  122. package/dist/item/item.codec.js +4 -3
  123. package/dist/item/item.enrichment.js +4 -4
  124. package/dist/item/item.parser.js +3 -2
  125. package/dist/item/item.schema.d.ts +69 -3
  126. package/dist/item/item.schema.js +2 -1
  127. package/dist/item/item.types.d.ts +69 -3
  128. package/dist/monster/monster.codec.d.ts +7 -6
  129. package/dist/monster/monster.enrichment.js +4 -4
  130. package/dist/monster/monster.format.d.ts +135 -0
  131. package/dist/monster/monster.format.js +78 -0
  132. package/dist/monster/monster.parser.d.ts +6 -1
  133. package/dist/monster/monster.parser.js +10 -1
  134. package/dist/monster/monster.schema.d.ts +369 -0
  135. package/dist/monster/monster.schema.js +34 -0
  136. package/dist/monster/monster.types.d.ts +200 -14
  137. package/dist/optional-feature/optional-feature.codec.js +6 -5
  138. package/dist/optional-feature/optional-feature.parser.js +5 -4
  139. package/dist/optional-feature/optional-feature.schema.d.ts +176 -0
  140. package/dist/optional-feature/optional-feature.schema.js +4 -3
  141. package/dist/pack.d.ts +1 -1
  142. package/dist/pc/conditions.constants.d.ts +0 -1
  143. package/dist/pc/conditions.constants.js +1 -3
  144. package/dist/pc/decision-recognizer.js +1 -1
  145. package/dist/pc/pc.additional-spells.d.ts +47 -0
  146. package/dist/pc/pc.additional-spells.js +23 -0
  147. package/dist/pc/pc.asi-flatten.d.ts +18 -0
  148. package/dist/pc/pc.decision-engine.d.ts +105 -17
  149. package/dist/pc/pc.decision-engine.js +28 -12
  150. package/dist/pc/pc.defense-normalize.d.ts +11 -0
  151. package/dist/pc/pc.defense-normalize.js +6 -0
  152. package/dist/pc/pc.equipment.d.ts +30 -1
  153. package/dist/pc/pc.equipment.js +12 -8
  154. package/dist/pc/pc.feature-effects.d.ts +225 -11
  155. package/dist/pc/pc.feature-effects.js +21 -5
  156. package/dist/pc/pc.parser.js +2 -2
  157. package/dist/pc/pc.pools.d.ts +11 -3
  158. package/dist/pc/pc.pools.js +9 -13
  159. package/dist/pc/pc.proficiencies.d.ts +54 -29
  160. package/dist/pc/pc.proficiencies.js +74 -95
  161. package/dist/pc/pc.proficiency-grants.d.ts +58 -0
  162. package/dist/pc/pc.proficiency-normalize.d.ts +24 -0
  163. package/dist/pc/pc.proficiency-normalize.js +12 -0
  164. package/dist/pc/pc.proficiency-query.d.ts +13 -0
  165. package/dist/pc/pc.proficiency-query.js +1 -1
  166. package/dist/pc/pc.recalc.d.ts +69 -14
  167. package/dist/pc/pc.recalc.js +261 -122
  168. package/dist/pc/pc.resolver.d.ts +34 -8
  169. package/dist/pc/pc.resolver.js +27 -12
  170. package/dist/pc/pc.resource-seed.d.ts +3 -2
  171. package/dist/pc/pc.resource-seed.js +19 -17
  172. package/dist/pc/pc.resources.d.ts +87 -0
  173. package/dist/pc/pc.resources.js +21 -0
  174. package/dist/pc/pc.rest.d.ts +10 -1
  175. package/dist/pc/pc.rest.js +66 -12
  176. package/dist/pc/pc.schema.d.ts +139 -3
  177. package/dist/pc/pc.schema.js +4 -2
  178. package/dist/pc/pc.slotting.js +3 -3
  179. package/dist/pc/pc.spellcasting.d.ts +75 -6
  180. package/dist/pc/pc.spellcasting.js +16 -6
  181. package/dist/pc/pc.table-column.d.ts +23 -0
  182. package/dist/pc/pc.table-column.js +13 -3
  183. package/dist/pc/pc.types.d.ts +251 -12
  184. package/dist/pc/pool-layout.d.ts +47 -0
  185. package/dist/pc/pool-layout.js +16 -0
  186. package/dist/pc/roll-scope.d.ts +2 -0
  187. package/dist/pc/roll-scope.js +8 -0
  188. package/dist/pc/roll-tag-labels.d.ts +40 -0
  189. package/dist/pc/roll-tag-labels.js +17 -0
  190. package/dist/pc/spell-source.d.ts +21 -0
  191. package/dist/pc/spell-source.js +13 -0
  192. package/dist/race/race.codec.js +9 -7
  193. package/dist/race/race.parser.js +8 -6
  194. package/dist/race/race.schema.d.ts +51 -1
  195. package/dist/race/race.schema.js +8 -5
  196. package/dist/race/race.structural.d.ts +7 -0
  197. package/dist/race/race.structural.js +6 -0
  198. package/dist/race/race.types.d.ts +20 -0
  199. package/dist/schemas/attack-schema.d.ts +5 -0
  200. package/dist/schemas/caster-type-schema.d.ts +14 -0
  201. package/dist/schemas/caster-type-schema.js +6 -0
  202. package/dist/schemas/choice-schema.js +2 -2
  203. package/dist/schemas/entity-extras-schema.d.ts +53 -0
  204. package/dist/schemas/entity-extras-schema.js +10 -0
  205. package/dist/schemas/equipment-grant-schema.d.ts +2 -0
  206. package/dist/schemas/equipment-grant-schema.js +1 -1
  207. package/dist/schemas/feature-alias.d.ts +34 -0
  208. package/dist/schemas/feature-effect-schema.d.ts +124 -0
  209. package/dist/schemas/feature-effect-schema.js +1 -1
  210. package/dist/schemas/feature-schema.d.ts +8 -0
  211. package/dist/schemas/feature-schema.js +6 -4
  212. package/dist/schemas/resource-schema.d.ts +43 -0
  213. package/dist/schemas/resource-schema.js +1 -1
  214. package/dist/schemas/selection-pool-schema.d.ts +2 -0
  215. package/dist/schemas/selection-pool-schema.js +1 -1
  216. package/dist/spell/spell.access.js +23 -3
  217. package/dist/spell/spell.codec.js +4 -3
  218. package/dist/spell/spell.enrichment.js +4 -4
  219. package/dist/spell/spell.parser.d.ts +30 -0
  220. package/dist/spell/spell.parser.js +9 -2
  221. package/dist/spell/spell.scaling.d.ts +27 -6
  222. package/dist/spell/spell.scaling.js +25 -6
  223. package/dist/spell/spell.schema.d.ts +44 -2
  224. package/dist/spell/spell.schema.js +2 -1
  225. package/dist/spell/spell.types.d.ts +14 -0
  226. package/dist/subclass/subclass.codec.d.ts +1 -1
  227. package/dist/subclass/subclass.codec.js +11 -8
  228. package/dist/subclass/subclass.parser.js +10 -7
  229. package/dist/subclass/subclass.schema.d.ts +54 -7
  230. package/dist/subclass/subclass.schema.js +8 -6
  231. package/dist/subclass/subclass.types.d.ts +20 -2
  232. package/dist/types/choice.d.ts +53 -2
  233. package/dist/types/choice.js +13 -1
  234. package/dist/types/equipment-grant.d.ts +8 -1
  235. package/dist/types/feature-effect.d.ts +78 -23
  236. package/dist/types/feature.d.ts +70 -1
  237. package/dist/types/optional-feature.types.d.ts +28 -0
  238. package/dist/types/resource.d.ts +21 -1
  239. package/dist/types/selection-pool.d.ts +17 -2
  240. package/dist/weapon/weapon.classify.js +2 -2
  241. package/dist/weapon/weapon.codec.js +4 -3
  242. package/dist/weapon/weapon.parser.js +3 -2
  243. package/dist/weapon/weapon.schema.d.ts +4 -0
  244. package/dist/weapon/weapon.schema.js +2 -1
  245. package/dist/weapon/weapon.types.d.ts +8 -0
  246. package/package.json +2 -2
  247. package/dist/chunk-5XUXXAQJ.js +0 -30
  248. package/dist/chunk-7P65Q426.js +0 -158
  249. package/dist/chunk-7TEK5KK7.js +0 -49
  250. package/dist/chunk-AIRFC5NQ.js +0 -143
  251. package/dist/chunk-CZPMTQOY.js +0 -68
  252. package/dist/chunk-N2JE7BWL.js +0 -81
  253. package/dist/chunk-NXR3BD2V.js +0 -90
  254. package/dist/chunk-O5EYMKFH.js +0 -6
  255. package/dist/chunk-Q5K6LWBZ.js +0 -45
  256. package/dist/chunk-TNUFPIXI.js +0 -1110
  257. package/dist/chunk-TZK36BU7.js +0 -38
  258. package/dist/chunk-W7HWMMBF.js +0 -46
  259. package/dist/chunk-Y4I74YEG.js +0 -33
@@ -3,7 +3,7 @@ import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
3
3
  import type { BackgroundEntity } from "@archivist-gg/dnd5e/background/background.types";
4
4
  import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
5
5
  import type { Ability } from "@archivist-gg/dnd5e";
6
- import type { Character, ChoiceValue, ResolvedCharacter, ResolvedClass, ResolvedFeature, ResolvedSpell } from "./pc.types.js";
6
+ import type { Character, ChoiceValue, ResolvedCharacter, ResolvedClass, ResolvedFeature, ResolvedSpell, FeatVia } from "./pc.types.js";
7
7
  export interface ResolveResult {
8
8
  character: ResolvedCharacter;
9
9
  warnings: string[];
@@ -19,8 +19,19 @@ export declare function stripSlug(ref: string | null): string | null;
19
19
  * resolve to the BASE feat ("magic-initiate") while keeping the full variant
20
20
  * string as the display name. Returns null when the ref is empty or resolves to no
21
21
  * feat (an unresolvable ref folds nothing into the pipeline).
22
+ *
23
+ * R4-G4 §8: this is a SEVEN-TIER cascade, first hit wins, and the granting
24
+ * BACKGROUND's slug arrives as `ownerSlug` so the compendium-scoped tiers can read
25
+ * its prefix. It replaces the old two-tier "exact slug, else FIRST tail match"
26
+ * lookup, whose two defects were measured on the shipped corpora: a tail match on a
27
+ * DIFFERENT real feat pre-empted the parenthetical strip (PHB 2024
28
+ * "Magic Initiate; Cleric", tail `magic-initiate-cleric`, beat SRD 2024
29
+ * "Magic Initiate" for every 2024 Acolyte / Sage, order-independently), and where
30
+ * several same-NAMED feats exist the registry order decided which one won
31
+ * (`EntityRegistry.search` sorts by lowercased name, so equal names fall through to
32
+ * insertion order).
22
33
  */
23
- export declare function resolveOriginFeat(entities: EntityRegistry, originFeatRef: string | null): {
34
+ export declare function resolveOriginFeat(entities: EntityRegistry, originFeatRef: string | null | undefined, ownerSlug?: string | null): {
24
35
  feat: FeatEntity;
25
36
  display: string;
26
37
  } | null;
@@ -44,10 +55,17 @@ export declare function collectChosenWeaponMasteries(character: Character): {
44
55
  full: string[];
45
56
  };
46
57
  /**
47
- * Walks class.choices for `feat` entries and adds background feat slugs.
48
- * Returns bare slugs (no `[[ ]]`).
58
+ * R4-G7 T8 RIDER-23 · every `choices[<level>].feat` pick with the slot it was taken at: the index of its class entry and
59
+ * the level key as a number (`null` when the key is not an integer). De-duplicated by slug in first-seen order (class
60
+ * entries in order, level keys ascending as `Object.entries` yields integer keys), so a feat picked twice keeps its FIRST
61
+ * slot. Slugs are bare (no `[[ ]]`). The resolver's one walk of class.choices for `feat` entries: the slug-only wrapper that
62
+ * mapped it had no production caller after RIDER-23 and was retired in wave D fix round 1.
49
63
  */
50
- export declare function collectFeatSlugs(character: Character): string[];
64
+ export declare function collectFeatPicks(character: Character): {
65
+ slug: string;
66
+ classIndex: number;
67
+ level: number | null;
68
+ }[];
51
69
  /**
52
70
  * Feat→spell application (3d). Walks a feat's OWN `choices` to find its spell
53
71
  * picks and turns each into a ResolvedSpell. A feat's spells sit behind a
@@ -80,8 +98,16 @@ export declare function collectItemGrantedSpells(character: Character, ownAbilit
80
98
  * Collapses duplicate resolved spells (3d Minor #2 carry-forward + P4-T3 segmented
81
99
  * dedupe). A spell can be emitted more than once: it may be BOTH in
82
100
  * `character.spells.known` AND a feat pick, or a feat may be taken as both origin +
83
- * class-slot. A class-sourced copy owns a real DC via its `classSlug`, so it always
84
- * wins over a feat copy of the same slug; otherwise first-seen wins. Insertion order
101
+ * class-slot, or an `additional_spells` grant (R4-G3b §5) may name a spell the character
102
+ * already knows. A class-sourced copy owns a real DC via its `classSlug`, so it always
103
+ * wins over a feat copy of the same slug; otherwise the FIRST-SEEN copy holds the slot.
104
+ * Which copy holds the slot is not the whole answer, though: `alwaysPrepared` is OR-merged
105
+ * onto the winner in BOTH collision orders (R4-G3b §5.2.8), so a hand-added Bless that a
106
+ * subclass later grants stops counting against the prepared limit instead of counting
107
+ * forever. `persisted` crosses the merge as well, in both orders (fix 1b): removability is
108
+ * MEMBERSHIP in `character.spells.known`, so the flag belongs to the SLUG, not to whichever
109
+ * copy won. Nothing else crosses: the winner keeps its own `source` / `classSlug` /
110
+ * `entryIndex`. Insertion order
85
111
  * is preserved (a later class copy replaces an earlier feat copy in place), so the
86
112
  * Spells section never renders duplicate rows while a legitimately class-known copy is
87
113
  * never lost. Item-source spells carry INSTANCE identity: they key by
@@ -101,4 +127,4 @@ export declare function collectChosenGrantedFeatures(character: Character, class
101
127
  data: Record<string, unknown>;
102
128
  } | undefined;
103
129
  }, race?: RaceEntity | null, background?: BackgroundEntity | null): ResolvedFeature[];
104
- export declare function collectResolvedFeatures(race: RaceEntity | null, classes: ResolvedClass[], background: BackgroundEntity | null, feats: FeatEntity[]): ResolvedFeature[];
130
+ export declare function collectResolvedFeatures(race: RaceEntity | null, classes: ResolvedClass[], background: BackgroundEntity | null, feats: FeatEntity[], featVia?: ReadonlyMap<string, FeatVia>): ResolvedFeature[];
@@ -3,29 +3,44 @@ import {
3
3
  collectChosenGrantedFeatures,
4
4
  collectChosenWeaponMasteries,
5
5
  collectFeatGrantedSpells,
6
- collectFeatSlugs,
6
+ collectFeatPicks,
7
7
  collectItemGrantedSpells,
8
8
  collectResolvedFeatures,
9
9
  dedupeResolvedSpells,
10
10
  resolveOriginFeat,
11
11
  stripSlug
12
- } from "../chunk-TNUFPIXI.js";
13
- import "../chunk-7TEK5KK7.js";
14
- import "../chunk-6IRYTM5V.js";
15
- import "../chunk-5XUXXAQJ.js";
16
- import "../chunk-JEYQU3JT.js";
17
- import "../chunk-N6N74K6X.js";
18
- import "../chunk-4LZJXJJS.js";
19
- import "../chunk-LV4SNWZQ.js";
12
+ } from "../chunk-XQCSGNXE.js";
13
+ import "../chunk-UXPGW4TI.js";
14
+ import "../chunk-DPUJDOKV.js";
15
+ import "../chunk-O4SRD3J5.js";
16
+ import "../chunk-PP2UHLBA.js";
17
+ import "../chunk-IUAAXXNO.js";
18
+ import "../chunk-YHYTW5QA.js";
19
+ import "../chunk-MI7P3NX3.js";
20
+ import "../chunk-PVCEA4HZ.js";
21
+ import "../chunk-UBBKSYBY.js";
22
+ import "../chunk-JJ46T5XX.js";
23
+ import "../chunk-TOM66P2P.js";
24
+ import "../chunk-KU3YLF6D.js";
25
+ import "../chunk-RLGQ5PZZ.js";
26
+ import "../chunk-LVQLWRCU.js";
27
+ import "../chunk-WXWPK3LI.js";
28
+ import "../chunk-6X4KUDMU.js";
29
+ import "../chunk-YBLDE5CG.js";
30
+ import "../chunk-EVMUJYUD.js";
20
31
  import "../chunk-VTTA2ALZ.js";
21
- import "../chunk-NAEPSZAM.js";
22
- import "../chunk-WP2CX2JO.js";
32
+ import "../chunk-OZP6JFGT.js";
33
+ import "../chunk-VQAXTIBW.js";
34
+ import "../chunk-PDJSUH24.js";
35
+ import "../chunk-WELIKLZF.js";
36
+ import "../chunk-4U55VNC7.js";
37
+ import "../chunk-UA5KS2PL.js";
23
38
  export {
24
39
  PCResolver,
25
40
  collectChosenGrantedFeatures,
26
41
  collectChosenWeaponMasteries,
27
42
  collectFeatGrantedSpells,
28
- collectFeatSlugs,
43
+ collectFeatPicks,
29
44
  collectItemGrantedSpells,
30
45
  collectResolvedFeatures,
31
46
  dedupeResolvedSpells,
@@ -4,7 +4,8 @@ import type { FormulaBindings } from "@archivist-gg/dnd5e/dnd/resource-formula";
4
4
  * is the character's level in the granting class; for a `subclass` source it
5
5
  * is the level in the class that OWNS that subclass, and it falls back to the
6
6
  * total level for race/background/feat sources (or when the class isn't found).
7
- * Also binds `columns` — the numeric values of that (sub)class's table row at
7
+ * Also binds `columns` · the numeric values of that (sub)class's table row at
8
8
  * `class_level` (empty when there is no table/row), backing the `column('Name')`
9
- * accessor in the DSL. Ability mods come from the final (post-bonus) derived mods. */
9
+ * accessor in the DSL. Ability mods come from the final (post-bonus) derived mods.
10
+ * `class_level` comes from `resourceLevelFor` (pc.resources.ts), the one derivation. */
10
11
  export declare function resourceBindings(resolved: ResolvedCharacter, derived: DerivedStats, source: FeatureSource): FormulaBindings;
@@ -1,27 +1,29 @@
1
+ import {
2
+ resourceLevelFor
3
+ } from "../chunk-UXPGW4TI.js";
4
+ import "../chunk-DPUJDOKV.js";
1
5
  import {
2
6
  numericColumnsAt
3
- } from "../chunk-5XUXXAQJ.js";
7
+ } from "../chunk-IUAAXXNO.js";
8
+ import "../chunk-LVQLWRCU.js";
9
+ import "../chunk-EVMUJYUD.js";
10
+ import "../chunk-VTTA2ALZ.js";
11
+ import "../chunk-PDJSUH24.js";
12
+ import "../chunk-WELIKLZF.js";
4
13
 
5
14
  // src/pc/pc.resource-seed.ts
6
15
  function resourceBindings(resolved, derived, source) {
7
16
  var _a, _b, _c, _d;
8
- let classLevel = resolved.totalLevel;
17
+ const classLevel = resourceLevelFor(source, resolved);
9
18
  let table;
10
- if (source.kind === "class") {
11
- const c = resolved.classes.find((c2) => {
12
- var _a2;
13
- return ((_a2 = c2.entity) == null ? void 0 : _a2.slug) === source.slug;
14
- });
15
- classLevel = (_a = c == null ? void 0 : c.level) != null ? _a : resolved.totalLevel;
16
- table = (_b = c == null ? void 0 : c.entity) == null ? void 0 : _b.table;
17
- } else if (source.kind === "subclass") {
18
- const c = resolved.classes.find((c2) => {
19
- var _a2;
20
- return ((_a2 = c2.subclass) == null ? void 0 : _a2.slug) === source.slug;
21
- });
22
- classLevel = (_c = c == null ? void 0 : c.level) != null ? _c : resolved.totalLevel;
23
- table = (_d = c == null ? void 0 : c.subclass) == null ? void 0 : _d.table;
24
- }
19
+ if (source.kind === "class") table = (_b = (_a = resolved.classes.find((c) => {
20
+ var _a2;
21
+ return ((_a2 = c.entity) == null ? void 0 : _a2.slug) === source.slug;
22
+ })) == null ? void 0 : _a.entity) == null ? void 0 : _b.table;
23
+ else if (source.kind === "subclass") table = (_d = (_c = resolved.classes.find((c) => {
24
+ var _a2;
25
+ return ((_a2 = c.subclass) == null ? void 0 : _a2.slug) === source.slug;
26
+ })) == null ? void 0 : _c.subclass) == null ? void 0 : _d.table;
25
27
  return {
26
28
  level: resolved.totalLevel,
27
29
  class_level: classLevel,
@@ -0,0 +1,87 @@
1
+ import type { FeatureSource, ResolvedCharacter, ResolvedFeature, ResolvedPool, DerivedStats } from "./pc.types.js";
2
+ import type { ResourceRecovery, ResourceDie, ResourceScaleStep, ResetTrigger } from "../types/resource.js";
3
+ /** The level a resource granted via `source` scales against (R4-G4 §6.2.4, ONE derivation): the
4
+ * character's level in the granting class; for a `subclass` source the level in the class that OWNS
5
+ * that subclass; the total level for race / background / feat sources, or when the class is not found.
6
+ * `resourceBindings` (pc.resource-seed.ts) binds `class_level` through this function, and R4-G4 T3
7
+ * (§6.2.4 / §6.2.5) routed the plugin's three former TOTAL-level reads through it too, so
8
+ * `class_level`, `scales_at` and the die can no longer disagree. T4 added a fourth read, the die label
9
+ * of `renderSpendControl`, and T5 a fifth, the die label of the pool tab's dice head.
10
+ *
11
+ * The units, re-measured 2026-09-06 on the SHIPPED plugin tree with
12
+ * `grep -rn "resourceLevelFor(" packages/obsidian/src`, which returns FOUR lines: FIVE READS reach
13
+ * this function through FOUR call EXPRESSIONS living in FOUR functions across FOUR files. The
14
+ * expressions are the plugin SEED (`seedFeatureUses` in `pc.resource-seed.ts`, for the level it hands
15
+ * `resolveMaxCountAt`), the module-private `resourceLevel(id, ctx)` helper of
16
+ * `components/actions/feature-rows.ts` (which resolves the owner from `resolved.resources` and falls
17
+ * back to the total level when there is none), `renderSpendControl`
18
+ * (`components/actions/spend-control.ts`) and `renderPoolHead` (`components/pool-tab.ts`). The count
19
+ * of READS is one higher than the count of expressions because `resourceLevel` serves TWO
20
+ * `resolveScalingDie` die labels, one in `renderCardResource` and one in `formatFeatureAttackNote`:
21
+ * so THREE of the five reads call this function directly (the seed, the spend control, the pool head)
22
+ * and TWO reach it through `resourceLevel`. Each render-time reader passes the owner its index entry
23
+ * already carries, so a die label and the tracker beside it read the same level. So a
24
+ * Barbarian 5 / Fighter 5 reads the level-5 Rage count, not the level-10 one. */
25
+ export declare function resourceLevelFor(source: FeatureSource, resolved: ResolvedCharacter): number;
26
+ export type ResourceOwner = {
27
+ kind: "feature";
28
+ featureId: string;
29
+ featureName: string;
30
+ source: FeatureSource;
31
+ } | {
32
+ kind: "pool";
33
+ poolId: string;
34
+ poolLabel: string;
35
+ source: FeatureSource;
36
+ };
37
+ export type RecoveryKind = "uses" | "spell-slots";
38
+ export type RecoveryFlavour = "rest" | "manual";
39
+ export interface ResolvedRecovery {
40
+ entry: ResourceRecovery;
41
+ kind: RecoveryKind;
42
+ flavour: RecoveryFlavour;
43
+ }
44
+ export interface ResolvedResource {
45
+ id: string;
46
+ name: string;
47
+ reset: ResetTrigger;
48
+ maxFormula: string;
49
+ die?: ResourceDie;
50
+ scalesAt?: ResourceScaleStep[];
51
+ recovery?: ResolvedRecovery[];
52
+ owner: ResourceOwner;
53
+ }
54
+ export type ResourceIndex = ReadonlyMap<string, ResolvedResource>;
55
+ /** KIND first (the schema key; absent = `uses`, UR2), FLAVOUR second (`action` / `reset`): a
56
+ * `spell-slots` entry is ALWAYS manual (the slot picker), whatever its action / reset say; a `uses`
57
+ * entry is a rest restore when its `reset` is `short-rest` or `long-rest` AND it carries no `action`,
58
+ * else manual (R4-G4 §7.2, invariant 12). The other rest-shaped triggers (`either`, `dawn`, `dusk`)
59
+ * read manual here: §7.1's partition of the 33 shipped entries has no carrier among them, and §15
60
+ * keeps the reset VOCABULARY of the rest arm deferred to G8.
61
+ *
62
+ * BOTH arms it routes are LANDED as of R4-G4 T7, and its CALLERS are counted here rather than its
63
+ * grep hits, because a docblock that names the function moves its own grep count. Measured
64
+ * 2026-09-05 on both trees: dnd5e has exactly ONE caller, `toResolvedResource` below, which STAMPS
65
+ * the kind and the flavour onto every entry of every indexed resource, so `pushPartialRecoveries`
66
+ * (pc.rest.ts) reads that stamp to emit the rest arm's partial category and never calls this
67
+ * function itself; the plugin has exactly ONE, `renderRecoveryAction` (blocks/feature-card.ts),
68
+ * which calls it directly and picks the card's arm from the KIND, then the FLAVOUR
69
+ * (`grep -rn "resolveRecovery" packages/obsidian/src` returns THREE lines there: the import, that
70
+ * call and one docblock mention). */
71
+ export declare function resolveRecovery(entry: ResourceRecovery): ResolvedRecovery;
72
+ /** ONE walk over `features[].feature.resources` (the walk `findResourceById` used to do per call). The
73
+ * owner is the DECLARING feature; a duplicate id keeps the FIRST declaration (seeding keeps its own
74
+ * max-of-maxes merge). Reads the features array ONLY. `name` falls back to the owning feature's name,
75
+ * the rule `findResourceById` carried, for resources synthesised from older fixtures that omit it. */
76
+ export declare function resolveFeatureResources(features: ReadonlyArray<ResolvedFeature>): ResourceIndex;
77
+ /** The full index: the feature resources (`resolveFeatureResources`) plus the pool picks' own
78
+ * `uses` (R4-G4 §12, LANDED at T7b). A pure function of `resolved.features` and `resolved.pools`,
79
+ * each guarded `?? []` because the cast fixtures behind the rest suites in both repos carry
80
+ * neither; `computeRestPlan` derives it per call and never reads `resolved.resources`, the
81
+ * resolver stores it on `resolved.resources` after pools resolve, and the resolver suite pins the
82
+ * stored index equal to a fresh derivation. */
83
+ export declare function resolveResourceIndex(resolved: ResolvedCharacter): ResourceIndex;
84
+ /** 8 + prof + mod(ability) when the pool's owning class's subclass carries `spellcasting.ability` AND
85
+ * `resolveSpellcasting` returns null for that class (no caster profile: the Four Elements shape); null
86
+ * otherwise. Reads `subclass.spellcasting.ability` and NEVER `dc_formula` (R4-G4 §11.2). */
87
+ export declare function poolSaveDC(resolved: ResolvedCharacter, derived: DerivedStats, pool: ResolvedPool): number | null;
@@ -0,0 +1,21 @@
1
+ import {
2
+ poolSaveDC,
3
+ resolveFeatureResources,
4
+ resolveRecovery,
5
+ resolveResourceIndex,
6
+ resourceLevelFor
7
+ } from "../chunk-UXPGW4TI.js";
8
+ import "../chunk-DPUJDOKV.js";
9
+ import "../chunk-IUAAXXNO.js";
10
+ import "../chunk-LVQLWRCU.js";
11
+ import "../chunk-EVMUJYUD.js";
12
+ import "../chunk-VTTA2ALZ.js";
13
+ import "../chunk-PDJSUH24.js";
14
+ import "../chunk-WELIKLZF.js";
15
+ export {
16
+ poolSaveDC,
17
+ resolveFeatureResources,
18
+ resolveRecovery,
19
+ resolveResourceIndex,
20
+ resourceLevelFor
21
+ };
@@ -1,11 +1,20 @@
1
1
  import type { EntityRegistry } from "@archivist-gg/core";
2
2
  import type { Character, DerivedStats, ResolvedCharacter } from "./pc.types.js";
3
3
  export type RestType = "short" | "long";
4
- export type RestCategoryId = "hp-to-max" | "hd-regain" | "spell-slots" | "pact-slots" | "exhaustion" | "hp-modifier-reset" | `feature:${string}` | `item:${number}`;
4
+ export type RestCategoryId = "hp-to-max" | "hd-regain" | "spell-slots" | "pact-slots" | "exhaustion" | "hp-modifier-reset" | `feature:${string}` | `item:${number}`
5
+ /** R4-G5 §4.4.2: END an active buff whose carrier declares a structured `duration`. The tail is the STORED
6
+ * `state.active_buffs` key (a class feature's `id` or a pool entry's resolved `slug`). Emitted by
7
+ * `pushBuffEnds` below and read by the plugin's `applyRestResets`, whose `buff:` arm removes that key
8
+ * from `state.active_buffs`. That arm is the plugin half of R4-G5 Task 6: this type is the task's
9
+ * dnd5e hard edge and is committed first. */
10
+ | `buff:${string}`;
5
11
  export interface RestCategory {
6
12
  id: RestCategoryId;
7
13
  label: string;
8
14
  preview: string;
15
+ /** R4-G4 §7.2.2: a PARTIAL restore from a `recovery[]` entry of kind `uses` and flavour `rest` (N uses, or "all"),
16
+ * emitted only when the resource's own `reset` does not already fire at this rest. Absent = the own reset (to 0). */
17
+ restore?: number | "all";
9
18
  }
10
19
  export interface RestPlan {
11
20
  type: RestType;
@@ -1,3 +1,14 @@
1
+ import {
2
+ resolveResourceIndex
3
+ } from "../chunk-UXPGW4TI.js";
4
+ import "../chunk-DPUJDOKV.js";
5
+ import "../chunk-IUAAXXNO.js";
6
+ import "../chunk-LVQLWRCU.js";
7
+ import "../chunk-EVMUJYUD.js";
8
+ import "../chunk-VTTA2ALZ.js";
9
+ import "../chunk-PDJSUH24.js";
10
+ import "../chunk-WELIKLZF.js";
11
+
1
12
  // src/pc/pc.rest.ts
2
13
  function resolveItemName(entry, registry) {
3
14
  var _a;
@@ -6,19 +17,58 @@ function resolveItemName(entry, registry) {
6
17
  const slug = ref ? ref[1] : entry.item;
7
18
  return (_a = registry.getBySlug(slug)) == null ? void 0 : _a.name;
8
19
  }
9
- function findResourceById(resolved, id) {
10
- var _a, _b, _c;
11
- for (const rf of (_a = resolved.features) != null ? _a : []) {
12
- for (const r of (_b = rf.feature.resources) != null ? _b : []) {
13
- if (r.id === id) return { label: (_c = r.name) != null ? _c : rf.feature.name, reset: r.reset };
20
+ var FIRES_AT = {
21
+ long: /* @__PURE__ */ new Set(["short-rest", "long-rest", "either", "dawn", "dusk"]),
22
+ short: /* @__PURE__ */ new Set(["short-rest", "either"])
23
+ };
24
+ function pushPartialRecoveries(cats, character, index, type) {
25
+ var _a, _b;
26
+ for (const [key, fu] of Object.entries((_a = character.state.feature_uses) != null ? _a : {})) {
27
+ if (fu.used <= 0) continue;
28
+ const res = index.get(key);
29
+ if (!((_b = res == null ? void 0 : res.recovery) == null ? void 0 : _b.length)) continue;
30
+ if (FIRES_AT[type].has(res.reset)) continue;
31
+ const entry = res.recovery.find((r) => r.kind === "uses" && r.flavour === "rest" && FIRES_AT[type].has(r.entry.reset));
32
+ if (!entry) continue;
33
+ const amount = entry.entry.amount;
34
+ const restore = amount === "all" ? "all" : typeof amount === "number" ? amount : Number(amount);
35
+ if (restore !== "all" && !Number.isFinite(restore)) continue;
36
+ const n = restore === "all" ? fu.used : Math.min(fu.used, restore);
37
+ cats.push({ id: `feature:${key}`, label: res.name, preview: `${n} of ${fu.used} used restored`, restore });
38
+ }
39
+ }
40
+ function pushBuffEnds(cats, character, resolved) {
41
+ var _a, _b, _c, _d, _e, _f, _g;
42
+ const structured = (d) => !!d && typeof d === "object";
43
+ for (const key of (_a = character.state.active_buffs) != null ? _a : []) {
44
+ let found = false;
45
+ let name = key;
46
+ for (const rf of (_b = resolved.features) != null ? _b : []) {
47
+ if (rf.feature.id === key && structured(rf.feature.duration)) {
48
+ found = true;
49
+ name = (_c = rf.feature.name) != null ? _c : key;
50
+ break;
51
+ }
52
+ }
53
+ if (!found) {
54
+ for (const pool of (_d = resolved.pools) != null ? _d : []) {
55
+ const entry = [...(_e = pool.selected) != null ? _e : [], ...(_f = pool.grants) != null ? _f : []].find((e) => e.slug === key);
56
+ if (entry && structured(entry.entity.duration)) {
57
+ found = true;
58
+ name = (_g = entry.entity.name) != null ? _g : key;
59
+ break;
60
+ }
61
+ }
14
62
  }
63
+ if (!found) continue;
64
+ cats.push({ id: `buff:${key}`, label: `End ${name}`, preview: "active \u2192 ended" });
15
65
  }
16
- return void 0;
17
66
  }
18
67
  function computeRestPlan(character, resolved, derived, registry, type) {
19
68
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
20
69
  const cats = [];
21
70
  let hdRegainDist;
71
+ const index = resolveResourceIndex(resolved);
22
72
  const pact = character.state.spell_slots_pact;
23
73
  if (pact && pact.used > 0) {
24
74
  cats.push({ id: "pact-slots", label: "Pact Magic Slots", preview: "all reset" });
@@ -79,15 +129,16 @@ function computeRestPlan(character, resolved, derived, registry, type) {
79
129
  }
80
130
  for (const [key, fu] of Object.entries((_f = character.state.feature_uses) != null ? _f : {})) {
81
131
  if (fu.used <= 0) continue;
82
- const res = findResourceById(resolved, key);
132
+ const res = index.get(key);
83
133
  const reset = (_g = res == null ? void 0 : res.reset) != null ? _g : "long-rest";
84
- if (reset !== "short-rest" && reset !== "long-rest" && reset !== "dawn" && reset !== "dusk") continue;
134
+ if (reset !== "short-rest" && reset !== "long-rest" && reset !== "either" && reset !== "dawn" && reset !== "dusk") continue;
85
135
  cats.push({
86
136
  id: `feature:${key}`,
87
- label: (_h = res == null ? void 0 : res.label) != null ? _h : key,
137
+ label: (_h = res == null ? void 0 : res.name) != null ? _h : key,
88
138
  preview: `${fu.used}/${fu.max} restored`
89
139
  });
90
140
  }
141
+ pushPartialRecoveries(cats, character, index, "long");
91
142
  character.equipment.forEach((entry, idx) => {
92
143
  var _a2, _b2, _c2, _d2, _e2;
93
144
  const rec = (_a2 = entry.state) == null ? void 0 : _a2.recovery;
@@ -106,14 +157,16 @@ function computeRestPlan(character, resolved, derived, registry, type) {
106
157
  if (type === "short") {
107
158
  for (const [key, fu] of Object.entries((_i = character.state.feature_uses) != null ? _i : {})) {
108
159
  if (fu.used <= 0) continue;
109
- const res = findResourceById(resolved, key);
110
- if (((_j = res == null ? void 0 : res.reset) != null ? _j : "long-rest") !== "short-rest") continue;
160
+ const res = index.get(key);
161
+ const r = (_j = res == null ? void 0 : res.reset) != null ? _j : "long-rest";
162
+ if (r !== "short-rest" && r !== "either") continue;
111
163
  cats.push({
112
164
  id: `feature:${key}`,
113
- label: (_k = res == null ? void 0 : res.label) != null ? _k : key,
165
+ label: (_k = res == null ? void 0 : res.name) != null ? _k : key,
114
166
  preview: `${fu.used}/${fu.max} restored`
115
167
  });
116
168
  }
169
+ pushPartialRecoveries(cats, character, index, "short");
117
170
  character.equipment.forEach((entry, idx) => {
118
171
  var _a2, _b2, _c2, _d2, _e2;
119
172
  const rec = (_a2 = entry.state) == null ? void 0 : _a2.recovery;
@@ -129,6 +182,7 @@ function computeRestPlan(character, resolved, derived, registry, type) {
129
182
  });
130
183
  });
131
184
  }
185
+ pushBuffEnds(cats, character, resolved);
132
186
  const hdAvailable = type === "short" ? Object.entries((_l = character.state.hit_dice) != null ? _l : {}).filter(([, hd]) => hd.used < hd.total).map(([die, hd]) => ({ die, remaining: hd.total - hd.used })) : [];
133
187
  return { type, categories: cats, hdAvailable, hdRegainDist };
134
188
  }
@@ -1,4 +1,113 @@
1
1
  import { z } from "zod";
2
+ export declare const characterOverridesShape: z.ZodObject<{
3
+ scores: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
4
+ str: "str";
5
+ dex: "dex";
6
+ con: "con";
7
+ int: "int";
8
+ wis: "wis";
9
+ cha: "cha";
10
+ }> & z.core.$partial, z.ZodNumber>>;
11
+ saves: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
12
+ str: "str";
13
+ dex: "dex";
14
+ con: "con";
15
+ int: "int";
16
+ wis: "wis";
17
+ cha: "cha";
18
+ }> & z.core.$partial, z.ZodObject<{
19
+ bonus: z.ZodOptional<z.ZodNumber>;
20
+ proficient: z.ZodOptional<z.ZodBoolean>;
21
+ }, z.core.$strip>>>;
22
+ skills: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
23
+ acrobatics: "acrobatics";
24
+ "animal-handling": "animal-handling";
25
+ arcana: "arcana";
26
+ athletics: "athletics";
27
+ deception: "deception";
28
+ history: "history";
29
+ insight: "insight";
30
+ intimidation: "intimidation";
31
+ investigation: "investigation";
32
+ medicine: "medicine";
33
+ nature: "nature";
34
+ perception: "perception";
35
+ performance: "performance";
36
+ persuasion: "persuasion";
37
+ religion: "religion";
38
+ "sleight-of-hand": "sleight-of-hand";
39
+ stealth: "stealth";
40
+ survival: "survival";
41
+ }> & z.core.$partial, z.ZodObject<{
42
+ bonus: z.ZodNumber;
43
+ proficiency: z.ZodOptional<z.ZodEnum<{
44
+ none: "none";
45
+ expertise: "expertise";
46
+ proficient: "proficient";
47
+ }>>;
48
+ }, z.core.$strip>>>;
49
+ passives: z.ZodOptional<z.ZodObject<{
50
+ perception: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
51
+ investigation: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
52
+ insight: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
53
+ }, z.core.$strip>>;
54
+ hp: z.ZodOptional<z.ZodObject<{
55
+ max: z.ZodOptional<z.ZodNumber>;
56
+ rolled: z.ZodOptional<z.ZodNumber>;
57
+ modifier: z.ZodOptional<z.ZodNumber>;
58
+ }, z.core.$strip>>;
59
+ ac: z.ZodOptional<z.ZodNumber>;
60
+ speed: z.ZodOptional<z.ZodNumber>;
61
+ initiative: z.ZodOptional<z.ZodNumber>;
62
+ spellcasting_ability_by_class: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
63
+ str: "str";
64
+ dex: "dex";
65
+ con: "con";
66
+ int: "int";
67
+ wis: "wis";
68
+ cha: "cha";
69
+ }>>>;
70
+ spellcasting_ability: z.ZodOptional<z.ZodEnum<{
71
+ str: "str";
72
+ dex: "dex";
73
+ con: "con";
74
+ int: "int";
75
+ wis: "wis";
76
+ cha: "cha";
77
+ }>>;
78
+ spell_slots: z.ZodOptional<z.ZodRecord<z.ZodCoercedNumber<unknown>, z.ZodNumber>>;
79
+ attunement_limit: z.ZodOptional<z.ZodNumber>;
80
+ languages: z.ZodOptional<z.ZodObject<{
81
+ add: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
83
+ }, z.core.$strip>>;
84
+ tools: z.ZodOptional<z.ZodObject<{
85
+ add: z.ZodOptional<z.ZodArray<z.ZodString>>;
86
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
+ proficiency: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
88
+ none: "none";
89
+ expertise: "expertise";
90
+ proficient: "proficient";
91
+ }>>>;
92
+ }, z.core.$strip>>;
93
+ defenses: z.ZodOptional<z.ZodObject<{
94
+ resistances: z.ZodOptional<z.ZodObject<{
95
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
+ }, z.core.$strip>>;
97
+ immunities: z.ZodOptional<z.ZodObject<{
98
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
99
+ }, z.core.$strip>>;
100
+ vulnerabilities: z.ZodOptional<z.ZodObject<{
101
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
102
+ }, z.core.$strip>>;
103
+ condition_immunities: z.ZodOptional<z.ZodObject<{
104
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
105
+ }, z.core.$strip>>;
106
+ }, z.core.$strip>>;
107
+ }, z.core.$strip>;
108
+ /** The overrides key set as a type. Paired with `keyof CharacterOverrides` by the compile-time parity
109
+ * assertion in pc.types.ts, which is what actually stops a one-sided addition. */
110
+ export type CharacterOverridesSchemaKeys = keyof z.infer<typeof characterOverridesShape>;
2
111
  export declare const characterSchema: z.ZodObject<{
3
112
  name: z.ZodString;
4
113
  edition: z.ZodEnum<{
@@ -27,10 +136,10 @@ export declare const characterSchema: z.ZodObject<{
27
136
  cha: z.ZodNumber;
28
137
  }, z.core.$strip>;
29
138
  ability_method: z.ZodEnum<{
139
+ rolled: "rolled";
30
140
  "standard-array": "standard-array";
31
141
  "point-buy": "point-buy";
32
142
  "archivist-point-buy": "archivist-point-buy";
33
- rolled: "rolled";
34
143
  manual: "manual";
35
144
  }>;
36
145
  builder_rolls: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
@@ -87,8 +196,8 @@ export declare const characterSchema: z.ZodObject<{
87
196
  class: z.ZodOptional<z.ZodString>;
88
197
  source: z.ZodOptional<z.ZodEnum<{
89
198
  domain: "domain";
90
- race: "race";
91
199
  item: "item";
200
+ race: "race";
92
201
  class: "class";
93
202
  feat: "feat";
94
203
  }>>;
@@ -210,8 +319,8 @@ export declare const characterSchema: z.ZodObject<{
210
319
  bonus: z.ZodNumber;
211
320
  proficiency: z.ZodOptional<z.ZodEnum<{
212
321
  none: "none";
213
- proficient: "proficient";
214
322
  expertise: "expertise";
323
+ proficient: "proficient";
215
324
  }>>;
216
325
  }, z.core.$strip>>>;
217
326
  passives: z.ZodOptional<z.ZodObject<{
@@ -245,6 +354,33 @@ export declare const characterSchema: z.ZodObject<{
245
354
  }>>;
246
355
  spell_slots: z.ZodOptional<z.ZodRecord<z.ZodCoercedNumber<unknown>, z.ZodNumber>>;
247
356
  attunement_limit: z.ZodOptional<z.ZodNumber>;
357
+ languages: z.ZodOptional<z.ZodObject<{
358
+ add: z.ZodOptional<z.ZodArray<z.ZodString>>;
359
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
360
+ }, z.core.$strip>>;
361
+ tools: z.ZodOptional<z.ZodObject<{
362
+ add: z.ZodOptional<z.ZodArray<z.ZodString>>;
363
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
364
+ proficiency: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
365
+ none: "none";
366
+ expertise: "expertise";
367
+ proficient: "proficient";
368
+ }>>>;
369
+ }, z.core.$strip>>;
370
+ defenses: z.ZodOptional<z.ZodObject<{
371
+ resistances: z.ZodOptional<z.ZodObject<{
372
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
373
+ }, z.core.$strip>>;
374
+ immunities: z.ZodOptional<z.ZodObject<{
375
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
376
+ }, z.core.$strip>>;
377
+ vulnerabilities: z.ZodOptional<z.ZodObject<{
378
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
379
+ }, z.core.$strip>>;
380
+ condition_immunities: z.ZodOptional<z.ZodObject<{
381
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
382
+ }, z.core.$strip>>;
383
+ }, z.core.$strip>>;
248
384
  }, z.core.$strip>>;
249
385
  currency: z.ZodOptional<z.ZodObject<{
250
386
  cp: z.ZodNumber;
@@ -1,7 +1,9 @@
1
1
  import {
2
+ characterOverridesShape,
2
3
  characterSchema
3
- } from "../chunk-TN6ZLTNU.js";
4
- import "../chunk-TZK36BU7.js";
4
+ } from "../chunk-I2NDWFDD.js";
5
+ import "../chunk-S7REMWW4.js";
5
6
  export {
7
+ characterOverridesShape,
6
8
  characterSchema
7
9
  };