@archivist-gg/dnd5e 0.3.0 → 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 (260) 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 +34 -0
  10. package/dist/background/background.schema.js +9 -6
  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-DPUJDOKV.js +365 -0
  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-VTYUBINW.js → chunk-HJ5EEZ47.js} +1 -1
  39. package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
  40. package/dist/{chunk-A4WENOUQ.js → chunk-I2NDWFDD.js} +52 -8
  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-TUIFSVLI.js → chunk-JRDPUDT5.js} +30 -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-DZXSWSBP.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-EMOORSQ7.js → chunk-OSQFPGLM.js} +45 -6
  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 +2120 -6923
  122. package/dist/item/item.ai-schema.d.ts +1 -1
  123. package/dist/item/item.codec.js +4 -3
  124. package/dist/item/item.enrichment.js +4 -4
  125. package/dist/item/item.parser.js +3 -2
  126. package/dist/item/item.schema.d.ts +69 -3
  127. package/dist/item/item.schema.js +2 -1
  128. package/dist/item/item.types.d.ts +69 -3
  129. package/dist/monster/monster.codec.d.ts +7 -6
  130. package/dist/monster/monster.enrichment.js +4 -4
  131. package/dist/monster/monster.format.d.ts +135 -0
  132. package/dist/monster/monster.format.js +78 -0
  133. package/dist/monster/monster.parser.d.ts +6 -1
  134. package/dist/monster/monster.parser.js +10 -1
  135. package/dist/monster/monster.schema.d.ts +369 -0
  136. package/dist/monster/monster.schema.js +34 -0
  137. package/dist/monster/monster.types.d.ts +200 -14
  138. package/dist/optional-feature/optional-feature.codec.js +6 -5
  139. package/dist/optional-feature/optional-feature.parser.js +5 -4
  140. package/dist/optional-feature/optional-feature.schema.d.ts +176 -0
  141. package/dist/optional-feature/optional-feature.schema.js +4 -3
  142. package/dist/pack.d.ts +1 -1
  143. package/dist/pc/conditions.constants.d.ts +0 -1
  144. package/dist/pc/conditions.constants.js +1 -3
  145. package/dist/pc/decision-recognizer.js +1 -1
  146. package/dist/pc/pc.additional-spells.d.ts +47 -0
  147. package/dist/pc/pc.additional-spells.js +23 -0
  148. package/dist/pc/pc.asi-flatten.d.ts +18 -0
  149. package/dist/pc/pc.decision-engine.d.ts +106 -5
  150. package/dist/pc/pc.decision-engine.js +28 -10
  151. package/dist/pc/pc.defense-normalize.d.ts +11 -0
  152. package/dist/pc/pc.defense-normalize.js +6 -0
  153. package/dist/pc/pc.equipment.d.ts +30 -1
  154. package/dist/pc/pc.equipment.js +12 -7
  155. package/dist/pc/pc.feature-effects.d.ts +225 -11
  156. package/dist/pc/pc.feature-effects.js +21 -5
  157. package/dist/pc/pc.parser.js +2 -2
  158. package/dist/pc/pc.pools.d.ts +11 -3
  159. package/dist/pc/pc.pools.js +9 -13
  160. package/dist/pc/pc.proficiencies.d.ts +60 -4
  161. package/dist/pc/pc.proficiencies.js +89 -37
  162. package/dist/pc/pc.proficiency-grants.d.ts +58 -0
  163. package/dist/pc/pc.proficiency-normalize.d.ts +29 -0
  164. package/dist/pc/pc.proficiency-normalize.js +12 -0
  165. package/dist/pc/pc.proficiency-query.d.ts +13 -0
  166. package/dist/pc/pc.proficiency-query.js +5 -1
  167. package/dist/pc/pc.recalc.d.ts +69 -14
  168. package/dist/pc/pc.recalc.js +291 -142
  169. package/dist/pc/pc.resolver.d.ts +34 -8
  170. package/dist/pc/pc.resolver.js +27 -12
  171. package/dist/pc/pc.resource-seed.d.ts +3 -2
  172. package/dist/pc/pc.resource-seed.js +19 -17
  173. package/dist/pc/pc.resources.d.ts +87 -0
  174. package/dist/pc/pc.resources.js +21 -0
  175. package/dist/pc/pc.rest.d.ts +10 -1
  176. package/dist/pc/pc.rest.js +66 -12
  177. package/dist/pc/pc.schema.d.ts +147 -7
  178. package/dist/pc/pc.schema.js +4 -2
  179. package/dist/pc/pc.slotting.js +3 -3
  180. package/dist/pc/pc.spellcasting.d.ts +80 -7
  181. package/dist/pc/pc.spellcasting.js +18 -6
  182. package/dist/pc/pc.table-column.d.ts +23 -0
  183. package/dist/pc/pc.table-column.js +13 -3
  184. package/dist/pc/pc.types.d.ts +253 -16
  185. package/dist/pc/pool-layout.d.ts +47 -0
  186. package/dist/pc/pool-layout.js +16 -0
  187. package/dist/pc/roll-scope.d.ts +2 -0
  188. package/dist/pc/roll-scope.js +8 -0
  189. package/dist/pc/roll-tag-labels.d.ts +40 -0
  190. package/dist/pc/roll-tag-labels.js +17 -0
  191. package/dist/pc/spell-source.d.ts +21 -0
  192. package/dist/pc/spell-source.js +13 -0
  193. package/dist/race/race.codec.js +9 -7
  194. package/dist/race/race.parser.js +8 -6
  195. package/dist/race/race.schema.d.ts +51 -1
  196. package/dist/race/race.schema.js +8 -5
  197. package/dist/race/race.structural.d.ts +7 -0
  198. package/dist/race/race.structural.js +6 -0
  199. package/dist/race/race.types.d.ts +20 -0
  200. package/dist/schemas/attack-schema.d.ts +5 -0
  201. package/dist/schemas/caster-type-schema.d.ts +14 -0
  202. package/dist/schemas/caster-type-schema.js +6 -0
  203. package/dist/schemas/choice-schema.js +2 -2
  204. package/dist/schemas/entity-extras-schema.d.ts +53 -0
  205. package/dist/schemas/entity-extras-schema.js +10 -0
  206. package/dist/schemas/equipment-grant-schema.d.ts +2 -0
  207. package/dist/schemas/equipment-grant-schema.js +1 -1
  208. package/dist/schemas/feature-alias.d.ts +34 -0
  209. package/dist/schemas/feature-effect-schema.d.ts +124 -0
  210. package/dist/schemas/feature-effect-schema.js +1 -1
  211. package/dist/schemas/feature-schema.d.ts +8 -0
  212. package/dist/schemas/feature-schema.js +6 -4
  213. package/dist/schemas/resource-schema.d.ts +43 -0
  214. package/dist/schemas/resource-schema.js +1 -1
  215. package/dist/schemas/selection-pool-schema.d.ts +2 -0
  216. package/dist/schemas/selection-pool-schema.js +1 -1
  217. package/dist/spell/spell.access.js +23 -3
  218. package/dist/spell/spell.codec.js +4 -3
  219. package/dist/spell/spell.enrichment.js +4 -4
  220. package/dist/spell/spell.parser.d.ts +30 -0
  221. package/dist/spell/spell.parser.js +9 -2
  222. package/dist/spell/spell.scaling.d.ts +27 -6
  223. package/dist/spell/spell.scaling.js +25 -6
  224. package/dist/spell/spell.schema.d.ts +44 -2
  225. package/dist/spell/spell.schema.js +2 -1
  226. package/dist/spell/spell.types.d.ts +14 -0
  227. package/dist/subclass/subclass.codec.d.ts +1 -1
  228. package/dist/subclass/subclass.codec.js +11 -8
  229. package/dist/subclass/subclass.parser.js +10 -7
  230. package/dist/subclass/subclass.schema.d.ts +54 -7
  231. package/dist/subclass/subclass.schema.js +8 -6
  232. package/dist/subclass/subclass.types.d.ts +20 -2
  233. package/dist/types/choice.d.ts +56 -0
  234. package/dist/types/choice.js +21 -3
  235. package/dist/types/equipment-grant.d.ts +8 -1
  236. package/dist/types/feature-effect.d.ts +78 -23
  237. package/dist/types/feature.d.ts +70 -1
  238. package/dist/types/optional-feature.types.d.ts +28 -0
  239. package/dist/types/resource.d.ts +21 -1
  240. package/dist/types/selection-pool.d.ts +17 -2
  241. package/dist/weapon/weapon.classify.js +2 -2
  242. package/dist/weapon/weapon.codec.js +4 -3
  243. package/dist/weapon/weapon.parser.js +3 -2
  244. package/dist/weapon/weapon.schema.d.ts +4 -0
  245. package/dist/weapon/weapon.schema.js +2 -1
  246. package/dist/weapon/weapon.types.d.ts +8 -0
  247. package/package.json +2 -2
  248. package/dist/chunk-5MZSB6OM.js +0 -1089
  249. package/dist/chunk-5XUXXAQJ.js +0 -30
  250. package/dist/chunk-7P65Q426.js +0 -158
  251. package/dist/chunk-AIRFC5NQ.js +0 -143
  252. package/dist/chunk-BH6AMZVY.js +0 -25
  253. package/dist/chunk-CZPMTQOY.js +0 -68
  254. package/dist/chunk-M2EMFD6S.js +0 -269
  255. package/dist/chunk-N2JE7BWL.js +0 -81
  256. package/dist/chunk-NXR3BD2V.js +0 -90
  257. package/dist/chunk-Q5K6LWBZ.js +0 -45
  258. package/dist/chunk-TZK36BU7.js +0 -38
  259. package/dist/chunk-W7HWMMBF.js +0 -46
  260. package/dist/chunk-Y4I74YEG.js +0 -33
@@ -0,0 +1,365 @@
1
+ import {
2
+ readTableColumn
3
+ } from "./chunk-IUAAXXNO.js";
4
+ import {
5
+ bareSlug,
6
+ baseClassName
7
+ } from "./chunk-VTTA2ALZ.js";
8
+ import {
9
+ abilityModifier
10
+ } from "./chunk-PDJSUH24.js";
11
+
12
+ // src/pc/pc.spellcasting.ts
13
+ function hasPreparedColumn(table) {
14
+ return Object.values(table).some((row) => PREPARED_COLUMNS.some((k) => {
15
+ var _a;
16
+ return ((_a = row == null ? void 0 : row.columns) == null ? void 0 : _a[k]) !== void 0;
17
+ }));
18
+ }
19
+ function resolveSpellcasting(rc) {
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
21
+ const sub = (_b = (_a = rc.subclass) == null ? void 0 : _a.spellcasting) != null ? _b : null;
22
+ const cls = (_d = (_c = rc.entity) == null ? void 0 : _c.spellcasting) != null ? _d : null;
23
+ const casterType = (_f = (_e = sub == null ? void 0 : sub.caster_type) != null ? _e : cls == null ? void 0 : cls.caster_type) != null ? _f : null;
24
+ const ability = (_h = (_g = sub == null ? void 0 : sub.ability) != null ? _g : cls == null ? void 0 : cls.ability) != null ? _h : null;
25
+ if (!casterType || !ability) return null;
26
+ const table = (_l = (_k = (sub == null ? void 0 : sub.caster_type) ? (_i = rc.subclass) == null ? void 0 : _i.table : void 0) != null ? _k : (_j = rc.entity) == null ? void 0 : _j.table) != null ? _l : {};
27
+ const preparation = (_n = (_m = sub == null ? void 0 : sub.preparation) != null ? _m : cls == null ? void 0 : cls.preparation) != null ? _n : hasPreparedColumn(table) ? "prepared" : "known";
28
+ const spellList = (_p = (_o = sub == null ? void 0 : sub.spell_list) != null ? _o : cls == null ? void 0 : cls.spell_list) != null ? _p : null;
29
+ return { ability, casterType, preparation, spellList, table };
30
+ }
31
+ function effectiveSpellcastingAbility(classSlug, dataAbility, overrides) {
32
+ var _a, _b;
33
+ return (_b = (_a = overrides.spellcasting_ability_by_class) == null ? void 0 : _a[classSlug]) != null ? _b : dataAbility;
34
+ }
35
+ function normalizeKnownSpell(entry) {
36
+ var _a, _b;
37
+ if (typeof entry === "string") {
38
+ return { slug: bareSlug(entry), classSlug: null, source: "class", preparedFlag: void 0, alwaysPrepared: false };
39
+ }
40
+ return {
41
+ slug: bareSlug(entry.spell),
42
+ classSlug: entry.class ? bareSlug(entry.class) : null,
43
+ source: (_a = entry.source) != null ? _a : "class",
44
+ preparedFlag: entry.prepared,
45
+ alwaysPrepared: (_b = entry.always_prepared) != null ? _b : false
46
+ };
47
+ }
48
+ function firstListedCasterClass(spellClasses, casterClassSlugs) {
49
+ var _a;
50
+ if (!Array.isArray(spellClasses) || spellClasses.length === 0) return null;
51
+ const listed = new Set(spellClasses.map((c) => baseClassName(String(c))));
52
+ return (_a = casterClassSlugs.find((slug) => listed.has(baseClassName(slug)))) != null ? _a : null;
53
+ }
54
+ var LISTED_CLASS_NAMES = /* @__PURE__ */ new WeakMap();
55
+ var NO_NAMES = /* @__PURE__ */ new Set();
56
+ function listedSpellClassNames(registry, compendium) {
57
+ var _a;
58
+ const count = registry.count();
59
+ let cached = LISTED_CLASS_NAMES.get(registry);
60
+ if (!cached || cached.count !== count) {
61
+ const byCompendium = /* @__PURE__ */ new Map();
62
+ for (const e of registry.search("", "spell", Number.POSITIVE_INFINITY)) {
63
+ const classes = e.data.classes;
64
+ if (!Array.isArray(classes)) continue;
65
+ let names = byCompendium.get(e.compendium);
66
+ if (!names) byCompendium.set(e.compendium, names = /* @__PURE__ */ new Set());
67
+ for (const c of classes) names.add(baseClassName(String(c)));
68
+ }
69
+ cached = { count, byCompendium };
70
+ LISTED_CLASS_NAMES.set(registry, cached);
71
+ }
72
+ return (_a = cached.byCompendium.get(compendium)) != null ? _a : NO_NAMES;
73
+ }
74
+ function attributeUnclassedSpell(spellClasses, casters, registry) {
75
+ var _a;
76
+ const first = casters[0];
77
+ if (!first) return null;
78
+ const listed = firstListedCasterClass(spellClasses, casters.map((c) => c.classSlug));
79
+ if (listed == null || listed === first.classSlug) return first.classSlug;
80
+ if (first.spellList == null) return first.classSlug;
81
+ const compendium = (_a = registry.getByTypeAndSlug("class", first.classSlug)) == null ? void 0 : _a.compendium;
82
+ if (compendium == null || !listedSpellClassNames(registry, compendium).has(baseClassName(first.classSlug))) return first.classSlug;
83
+ return listed;
84
+ }
85
+ var FULL_CASTER_SLOTS = [
86
+ /* 1 */
87
+ [2, 0, 0, 0, 0, 0, 0, 0, 0],
88
+ /* 2 */
89
+ [3, 0, 0, 0, 0, 0, 0, 0, 0],
90
+ /* 3 */
91
+ [4, 2, 0, 0, 0, 0, 0, 0, 0],
92
+ /* 4 */
93
+ [4, 3, 0, 0, 0, 0, 0, 0, 0],
94
+ /* 5 */
95
+ [4, 3, 2, 0, 0, 0, 0, 0, 0],
96
+ /* 6 */
97
+ [4, 3, 3, 0, 0, 0, 0, 0, 0],
98
+ /* 7 */
99
+ [4, 3, 3, 1, 0, 0, 0, 0, 0],
100
+ /* 8 */
101
+ [4, 3, 3, 2, 0, 0, 0, 0, 0],
102
+ /* 9 */
103
+ [4, 3, 3, 3, 1, 0, 0, 0, 0],
104
+ /* 10 */
105
+ [4, 3, 3, 3, 2, 0, 0, 0, 0],
106
+ /* 11 */
107
+ [4, 3, 3, 3, 2, 1, 0, 0, 0],
108
+ /* 12 */
109
+ [4, 3, 3, 3, 2, 1, 0, 0, 0],
110
+ /* 13 */
111
+ [4, 3, 3, 3, 2, 1, 1, 0, 0],
112
+ /* 14 */
113
+ [4, 3, 3, 3, 2, 1, 1, 0, 0],
114
+ /* 15 */
115
+ [4, 3, 3, 3, 2, 1, 1, 1, 0],
116
+ /* 16 */
117
+ [4, 3, 3, 3, 2, 1, 1, 1, 0],
118
+ /* 17 */
119
+ [4, 3, 3, 3, 2, 1, 1, 1, 1],
120
+ /* 18 */
121
+ [4, 3, 3, 3, 3, 1, 1, 1, 1],
122
+ /* 19 */
123
+ [4, 3, 3, 3, 3, 2, 1, 1, 1],
124
+ /* 20 */
125
+ [4, 3, 3, 3, 3, 2, 2, 1, 1]
126
+ ];
127
+ var HALF_CASTER_SLOTS = [
128
+ /* 1 */
129
+ [0, 0, 0, 0, 0],
130
+ /* 2 */
131
+ [2, 0, 0, 0, 0],
132
+ /* 3 */
133
+ [3, 0, 0, 0, 0],
134
+ /* 4 */
135
+ [3, 0, 0, 0, 0],
136
+ /* 5 */
137
+ [4, 2, 0, 0, 0],
138
+ /* 6 */
139
+ [4, 2, 0, 0, 0],
140
+ /* 7 */
141
+ [4, 3, 0, 0, 0],
142
+ /* 8 */
143
+ [4, 3, 0, 0, 0],
144
+ /* 9 */
145
+ [4, 3, 2, 0, 0],
146
+ /* 10 */
147
+ [4, 3, 2, 0, 0],
148
+ /* 11 */
149
+ [4, 3, 3, 0, 0],
150
+ /* 12 */
151
+ [4, 3, 3, 0, 0],
152
+ /* 13 */
153
+ [4, 3, 3, 1, 0],
154
+ /* 14 */
155
+ [4, 3, 3, 1, 0],
156
+ /* 15 */
157
+ [4, 3, 3, 2, 0],
158
+ /* 16 */
159
+ [4, 3, 3, 2, 0],
160
+ /* 17 */
161
+ [4, 3, 3, 3, 1],
162
+ /* 18 */
163
+ [4, 3, 3, 3, 1],
164
+ /* 19 */
165
+ [4, 3, 3, 3, 2],
166
+ /* 20 */
167
+ [4, 3, 3, 3, 2]
168
+ ];
169
+ var THIRD_CASTER_SLOTS = [
170
+ /* 1 */
171
+ [0, 0, 0, 0],
172
+ /* 2 */
173
+ [0, 0, 0, 0],
174
+ /* 3 */
175
+ [2, 0, 0, 0],
176
+ /* 4 */
177
+ [3, 0, 0, 0],
178
+ /* 5 */
179
+ [3, 0, 0, 0],
180
+ /* 6 */
181
+ [3, 0, 0, 0],
182
+ /* 7 */
183
+ [4, 2, 0, 0],
184
+ /* 8 */
185
+ [4, 2, 0, 0],
186
+ /* 9 */
187
+ [4, 2, 0, 0],
188
+ /* 10 */
189
+ [4, 3, 0, 0],
190
+ /* 11 */
191
+ [4, 3, 0, 0],
192
+ /* 12 */
193
+ [4, 3, 0, 0],
194
+ /* 13 */
195
+ [4, 3, 2, 0],
196
+ /* 14 */
197
+ [4, 3, 2, 0],
198
+ /* 15 */
199
+ [4, 3, 2, 0],
200
+ /* 16 */
201
+ [4, 3, 3, 0],
202
+ /* 17 */
203
+ [4, 3, 3, 0],
204
+ /* 18 */
205
+ [4, 3, 3, 0],
206
+ /* 19 */
207
+ [4, 3, 3, 1],
208
+ /* 20 */
209
+ [4, 3, 3, 1]
210
+ ];
211
+ var PACT_MAGIC = [
212
+ /* 1 */
213
+ { level: 1, total: 1 },
214
+ /* 2 */
215
+ { level: 1, total: 2 },
216
+ /* 3 */
217
+ { level: 2, total: 2 },
218
+ /* 4 */
219
+ { level: 2, total: 2 },
220
+ /* 5 */
221
+ { level: 3, total: 2 },
222
+ /* 6 */
223
+ { level: 3, total: 2 },
224
+ /* 7 */
225
+ { level: 4, total: 2 },
226
+ /* 8 */
227
+ { level: 4, total: 2 },
228
+ /* 9 */
229
+ { level: 5, total: 2 },
230
+ /* 10 */
231
+ { level: 5, total: 2 },
232
+ /* 11 */
233
+ { level: 5, total: 3 },
234
+ /* 12 */
235
+ { level: 5, total: 3 },
236
+ /* 13 */
237
+ { level: 5, total: 3 },
238
+ /* 14 */
239
+ { level: 5, total: 3 },
240
+ /* 15 */
241
+ { level: 5, total: 3 },
242
+ /* 16 */
243
+ { level: 5, total: 3 },
244
+ /* 17 */
245
+ { level: 5, total: 4 },
246
+ /* 18 */
247
+ { level: 5, total: 4 },
248
+ /* 19 */
249
+ { level: 5, total: 4 },
250
+ /* 20 */
251
+ { level: 5, total: 4 }
252
+ ];
253
+ var ARTIFICER_CASTER_SLOTS = HALF_CASTER_SLOTS.map((row) => [...row]);
254
+ ARTIFICER_CASTER_SLOTS[0] = [2, 0, 0, 0, 0];
255
+ function slotTableFor(caster) {
256
+ switch (caster) {
257
+ case "full":
258
+ return FULL_CASTER_SLOTS;
259
+ case "half":
260
+ return HALF_CASTER_SLOTS;
261
+ case "third":
262
+ return THIRD_CASTER_SLOTS;
263
+ case "artificer":
264
+ return ARTIFICER_CASTER_SLOTS;
265
+ default: {
266
+ const _n = caster;
267
+ throw new Error(`unknown caster type ${String(_n)}`);
268
+ }
269
+ }
270
+ }
271
+ function rowToRecord(row) {
272
+ const out = {};
273
+ row.forEach((n, i) => {
274
+ if (n > 0) out[i + 1] = n;
275
+ });
276
+ return out;
277
+ }
278
+ function deriveSpellSlots(classes) {
279
+ let fullLevels = 0, halfLevels = 0, thirdLevels = 0, artificerLevels = 0, warlockLevel = 0;
280
+ const regular = [];
281
+ for (const c of classes) {
282
+ if (c.casterType === "pact") {
283
+ warlockLevel += c.level;
284
+ continue;
285
+ }
286
+ regular.push({ caster: c.casterType, level: c.level });
287
+ switch (c.casterType) {
288
+ case "full":
289
+ fullLevels += c.level;
290
+ break;
291
+ case "half":
292
+ halfLevels += c.level;
293
+ break;
294
+ case "third":
295
+ thirdLevels += c.level;
296
+ break;
297
+ case "artificer":
298
+ artificerLevels += c.level;
299
+ break;
300
+ default: {
301
+ const _n = c.casterType;
302
+ throw new Error(`unknown caster type ${String(_n)}`);
303
+ }
304
+ }
305
+ }
306
+ let standard = {};
307
+ if (regular.length === 1) {
308
+ const only = regular[0];
309
+ const table = slotTableFor(only.caster);
310
+ const idx = only.level - 1;
311
+ if (idx >= 0 && idx < table.length) standard = rowToRecord(table[idx]);
312
+ } else if (regular.length >= 2) {
313
+ const cl = fullLevels + Math.floor(halfLevels / 2) + Math.floor(thirdLevels / 3) + Math.ceil(artificerLevels / 2);
314
+ if (cl >= 1 && cl <= FULL_CASTER_SLOTS.length) standard = rowToRecord(FULL_CASTER_SLOTS[cl - 1]);
315
+ }
316
+ const pact = warlockLevel >= 1 && warlockLevel <= PACT_MAGIC.length ? PACT_MAGIC[warlockLevel - 1] : null;
317
+ return { standard, pact };
318
+ }
319
+ var PREPARED_COLUMNS = ["Prepared Spells", "Spells Prepared"];
320
+ function preparedLevelTerm(caster, level) {
321
+ switch (caster) {
322
+ case "full":
323
+ case "pact":
324
+ return level;
325
+ case "half":
326
+ case "artificer":
327
+ return Math.floor(level / 2);
328
+ case "third":
329
+ return Math.floor(level / 3);
330
+ default: {
331
+ const _n = caster;
332
+ throw new Error(`unknown caster type ${String(_n)}`);
333
+ }
334
+ }
335
+ }
336
+ function computeSpellLimits(inputs) {
337
+ const out = [];
338
+ for (const i of inputs) {
339
+ const p = i.profile;
340
+ const cantripsKnown = readTableColumn(p.table, i.level, ["Cantrips Known", "Cantrips"]);
341
+ const mod = abilityModifier(i.abilityScore);
342
+ let preparedOrKnown;
343
+ if (p.preparation === "prepared") {
344
+ const fromTable = readTableColumn(p.table, i.level, PREPARED_COLUMNS);
345
+ preparedOrKnown = fromTable !== null ? fromTable : Math.max(1, mod + preparedLevelTerm(p.casterType, i.level));
346
+ } else {
347
+ preparedOrKnown = readTableColumn(p.table, i.level, ["Spells Known", "Prepared Spells"]);
348
+ }
349
+ out.push({ classSlug: i.classSlug, kind: p.preparation, cantripsKnown, preparedOrKnown });
350
+ }
351
+ return out;
352
+ }
353
+
354
+ export {
355
+ resolveSpellcasting,
356
+ effectiveSpellcastingAbility,
357
+ normalizeKnownSpell,
358
+ listedSpellClassNames,
359
+ attributeUnclassedSpell,
360
+ slotTableFor,
361
+ deriveSpellSlots,
362
+ PREPARED_COLUMNS,
363
+ preparedLevelTerm,
364
+ computeSpellLimits
365
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseFeat
3
- } from "./chunk-XTIQWSFM.js";
3
+ } from "./chunk-D5U7GMPX.js";
4
4
 
5
5
  // src/feat/feat.codec.ts
6
6
  import yaml from "js-yaml";
@@ -0,0 +1,195 @@
1
+ // src/dnd/resource-formula.ts
2
+ var IDENTS = /* @__PURE__ */ new Set([
3
+ "level",
4
+ "class_level",
5
+ "prof",
6
+ "str_mod",
7
+ "dex_mod",
8
+ "con_mod",
9
+ "int_mod",
10
+ "wis_mod",
11
+ "cha_mod"
12
+ ]);
13
+ var AT_WILL_MAX = 999;
14
+ var FUNCS = /* @__PURE__ */ new Set(["ceil", "floor", "max", "min"]);
15
+ function tokenize(input) {
16
+ input = input.trim();
17
+ const tokens = [];
18
+ const re = /\s*('[^']*'|\{[a-z_]+\}|[a-z_]+|\d+|[+\-*/(),])/y;
19
+ let i = 0;
20
+ while (i < input.length) {
21
+ re.lastIndex = i;
22
+ const m = re.exec(input);
23
+ if (!m || m.index !== i) return null;
24
+ const raw = m[1];
25
+ i = re.lastIndex;
26
+ if (/^\d+$/.test(raw)) tokens.push({ kind: "num", value: parseInt(raw, 10) });
27
+ else if (raw.startsWith("'")) tokens.push({ kind: "str", value: raw.slice(1, -1) });
28
+ else if (raw === "(") tokens.push({ kind: "lparen" });
29
+ else if (raw === ")") tokens.push({ kind: "rparen" });
30
+ else if (raw === ",") tokens.push({ kind: "comma" });
31
+ else if (raw === "+" || raw === "-" || raw === "*" || raw === "/") tokens.push({ kind: "op", op: raw });
32
+ else {
33
+ const braced = raw.startsWith("{");
34
+ const name = braced ? raw.slice(1, -1) : raw;
35
+ if (!braced && FUNCS.has(name)) tokens.push({ kind: "fn", name });
36
+ else if (!braced && name === "column") tokens.push({ kind: "col" });
37
+ else if (IDENTS.has(name)) tokens.push({ kind: "id", name });
38
+ else return null;
39
+ }
40
+ }
41
+ return tokens.length > 0 ? tokens : null;
42
+ }
43
+ function evalTokens(tokens, b) {
44
+ let pos = 0;
45
+ const peek = () => tokens[pos];
46
+ const factor = () => {
47
+ var _a, _b, _c, _d, _e, _f, _g, _h;
48
+ const t = peek();
49
+ if (!t) return null;
50
+ if (t.kind === "num") {
51
+ pos++;
52
+ return t.value;
53
+ }
54
+ if (t.kind === "id") {
55
+ const val = b[t.name];
56
+ if (val === void 0) return null;
57
+ pos++;
58
+ return val;
59
+ }
60
+ if (t.kind === "fn") {
61
+ pos++;
62
+ if (((_a = peek()) == null ? void 0 : _a.kind) !== "lparen") return null;
63
+ pos++;
64
+ const args = [];
65
+ const first = expr();
66
+ if (first === null) return null;
67
+ args.push(first);
68
+ while (((_b = peek()) == null ? void 0 : _b.kind) === "comma") {
69
+ pos++;
70
+ const next = expr();
71
+ if (next === null) return null;
72
+ args.push(next);
73
+ }
74
+ if (((_c = peek()) == null ? void 0 : _c.kind) !== "rparen") return null;
75
+ pos++;
76
+ if (t.name === "ceil" || t.name === "floor") {
77
+ if (args.length !== 1) return null;
78
+ return t.name === "ceil" ? Math.ceil(args[0]) : Math.floor(args[0]);
79
+ }
80
+ if (args.length < 2) return null;
81
+ return t.name === "max" ? Math.max(...args) : Math.min(...args);
82
+ }
83
+ if (t.kind === "col") {
84
+ pos++;
85
+ if (((_d = peek()) == null ? void 0 : _d.kind) !== "lparen") return null;
86
+ pos++;
87
+ const s = peek();
88
+ if (!s || s.kind !== "str") return null;
89
+ pos++;
90
+ if (((_e = peek()) == null ? void 0 : _e.kind) !== "rparen") return null;
91
+ pos++;
92
+ return (_g = (_f = b.columns) == null ? void 0 : _f[s.value]) != null ? _g : 0;
93
+ }
94
+ if (t.kind === "lparen") {
95
+ pos++;
96
+ const inner = expr();
97
+ if (inner === null) return null;
98
+ if (((_h = peek()) == null ? void 0 : _h.kind) !== "rparen") return null;
99
+ pos++;
100
+ return inner;
101
+ }
102
+ return null;
103
+ };
104
+ const term = () => {
105
+ var _a;
106
+ let v = factor();
107
+ if (v === null) return null;
108
+ while (((_a = peek()) == null ? void 0 : _a.kind) === "op" && (peek().op === "*" || peek().op === "/")) {
109
+ const op = peek().op;
110
+ pos++;
111
+ const r = factor();
112
+ if (r === null) return null;
113
+ v = op === "*" ? v * r : v / r;
114
+ }
115
+ return v;
116
+ };
117
+ const expr = () => {
118
+ var _a;
119
+ let v = term();
120
+ if (v === null) return null;
121
+ while (((_a = peek()) == null ? void 0 : _a.kind) === "op" && (peek().op === "+" || peek().op === "-")) {
122
+ const op = peek().op;
123
+ pos++;
124
+ const r = term();
125
+ if (r === null) return null;
126
+ v = op === "+" ? v + r : v - r;
127
+ }
128
+ return v;
129
+ };
130
+ const result = expr();
131
+ if (result === null || pos !== tokens.length) return null;
132
+ return result;
133
+ }
134
+ var ZERO = {
135
+ level: 1,
136
+ class_level: 1,
137
+ prof: 2,
138
+ str_mod: 0,
139
+ dex_mod: 0,
140
+ con_mod: 0,
141
+ int_mod: 0,
142
+ wis_mod: 0,
143
+ cha_mod: 0,
144
+ columns: {}
145
+ };
146
+ function isValidMaxFormula(formula) {
147
+ const toks = tokenize(formula);
148
+ if (!toks) return false;
149
+ return evalTokens(toks, ZERO) !== null;
150
+ }
151
+ function evaluateMaxFormula(formula, bindings) {
152
+ const toks = tokenize(formula);
153
+ if (!toks) throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);
154
+ const v = evalTokens(toks, bindings);
155
+ if (v === null) throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);
156
+ return v;
157
+ }
158
+ function resolveMaxAt(totalLevel, resource) {
159
+ var _a;
160
+ let chosen = resource.max_formula;
161
+ let best = 0;
162
+ for (const step of (_a = resource.scales_at) != null ? _a : []) {
163
+ if (step.level <= totalLevel && step.level > best) {
164
+ best = step.level;
165
+ chosen = step.max;
166
+ }
167
+ }
168
+ return chosen;
169
+ }
170
+ function resolveMaxCountAt(level, resource, bindings) {
171
+ var _a;
172
+ const tryEval = (s) => {
173
+ const toks = tokenize(s);
174
+ return toks ? evalTokens(toks, bindings) : null;
175
+ };
176
+ let best = 0;
177
+ let chosen = null;
178
+ for (const step of (_a = resource.scales_at) != null ? _a : []) {
179
+ if (step.level > level || step.level <= best) continue;
180
+ const v = tryEval(step.max);
181
+ if (v === null) continue;
182
+ best = step.level;
183
+ chosen = v;
184
+ }
185
+ if (chosen !== null) return chosen;
186
+ return tryEval(resource.max_formula);
187
+ }
188
+
189
+ export {
190
+ AT_WILL_MAX,
191
+ isValidMaxFormula,
192
+ evaluateMaxFormula,
193
+ resolveMaxAt,
194
+ resolveMaxCountAt
195
+ };
@@ -1,9 +1,13 @@
1
1
  import {
2
2
  featureSchema
3
- } from "./chunk-CZPMTQOY.js";
3
+ } from "./chunk-4FWNK4FD.js";
4
4
  import {
5
5
  choiceSchema
6
- } from "./chunk-NXSWH3AE.js";
6
+ } from "./chunk-T26ZVCL5.js";
7
+ import {
8
+ additionalSpellsEntrySchema,
9
+ imageField
10
+ } from "./chunk-UA5KS2PL.js";
7
11
 
8
12
  // src/race/race.schema.ts
9
13
  import { z } from "zod";
@@ -55,9 +59,31 @@ var raceEntitySchema = z.object({
55
59
  variant_label: z.string().min(1),
56
60
  traits: z.array(featureSchema),
57
61
  choices: z.array(choiceSchema).optional(),
58
- subspecies_of: z.string().regex(wikilinkRegex).optional()
62
+ subspecies_of: z.string().regex(wikilinkRegex).optional(),
63
+ rendering_hint: z.string().optional(),
64
+ has_fluff: z.boolean().optional(),
65
+ has_fluff_images: z.boolean().optional(),
66
+ creature_type: z.array(z.string().min(1)).optional(),
67
+ // guarded non-empty at the emitter (finding 24)
68
+ creature_type_tags: z.array(z.string().min(1)).optional(),
69
+ additional_spells: z.union([
70
+ z.array(additionalSpellsEntrySchema),
71
+ // converter form, 109 docs
72
+ additionalSpellsEntrySchema
73
+ // SHIPPED-BUNDLE bare-object form, 3 docs (§2.8)
74
+ ]).optional(),
75
+ // The four RAW 5etools PASSTHROUGHS (race-mapper.ts D13 block copies them VERBATIM, no shape
76
+ // guard — finding 24): today's variant set is a snapshot, not a contract (lineage is already
77
+ // string|null|boolean), and NO G row ever reads them. Maximally loose by ruling; the guard
78
+ // test §9.5 pins today's variant classes since the census goes blind under z.unknown().
79
+ trait_tags: z.unknown().optional(),
80
+ lineage: z.unknown().optional(),
81
+ height_and_weight: z.unknown().optional(),
82
+ sound_clip: z.unknown().optional(),
83
+ image: imageField
59
84
  });
60
85
 
61
86
  export {
87
+ fixedAsiSchema,
62
88
  raceEntitySchema
63
89
  };