@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
@@ -0,0 +1,106 @@
1
+ // src/types/choice.ts
2
+ var ALL_SKILL_SLUGS = [
3
+ "acrobatics",
4
+ "animal-handling",
5
+ "arcana",
6
+ "athletics",
7
+ "deception",
8
+ "history",
9
+ "insight",
10
+ "intimidation",
11
+ "investigation",
12
+ "medicine",
13
+ "nature",
14
+ "perception",
15
+ "performance",
16
+ "persuasion",
17
+ "religion",
18
+ "sleight-of-hand",
19
+ "stealth",
20
+ "survival"
21
+ ];
22
+ var STANDARD_LANGUAGES = [
23
+ "common",
24
+ "dwarvish",
25
+ "elvish",
26
+ "giant",
27
+ "gnomish",
28
+ "goblin",
29
+ "halfling",
30
+ "orc"
31
+ ];
32
+ var EXOTIC_LANGUAGES = [
33
+ "abyssal",
34
+ "celestial",
35
+ "deep-speech",
36
+ "draconic",
37
+ "infernal",
38
+ "primordial",
39
+ "sylvan",
40
+ "undercommon"
41
+ ];
42
+ var SECRET_LANGUAGES = ["druidic", "thieves'-cant"];
43
+ var ALL_LANGUAGES = [
44
+ ...STANDARD_LANGUAGES,
45
+ ...EXOTIC_LANGUAGES,
46
+ ...SECRET_LANGUAGES
47
+ ];
48
+ var ARTISANS_TOOLS = [
49
+ "alchemist's-supplies",
50
+ "brewer's-supplies",
51
+ "calligrapher's-supplies",
52
+ "carpenter's-tools",
53
+ "cartographer's-tools",
54
+ "cobbler's-tools",
55
+ "cook's-utensils",
56
+ "glassblower's-tools",
57
+ "jeweler's-tools",
58
+ "leatherworker's-tools",
59
+ "mason's-tools",
60
+ "painter's-supplies",
61
+ "potter's-tools",
62
+ "smith's-tools",
63
+ "tinker's-tools",
64
+ "weaver's-tools",
65
+ "woodcarver's-tools"
66
+ ];
67
+ var MUSICAL_INSTRUMENTS = [
68
+ "bagpipes",
69
+ "drum",
70
+ "dulcimer",
71
+ "flute",
72
+ "horn",
73
+ "lute",
74
+ "lyre",
75
+ "pan-flute",
76
+ "shawm",
77
+ "viol"
78
+ ];
79
+ var GAMING_SETS = ["dice-set", "playing-cards"];
80
+ var OTHER_TOOLS = [
81
+ "disguise-kit",
82
+ "forgery-kit",
83
+ "herbalism-kit",
84
+ "navigator's-tools",
85
+ "poisoner's-kit",
86
+ "thieves'-tools"
87
+ ];
88
+ var ALL_TOOLS = [
89
+ ...ARTISANS_TOOLS,
90
+ ...MUSICAL_INSTRUMENTS,
91
+ ...GAMING_SETS,
92
+ ...OTHER_TOOLS
93
+ ];
94
+
95
+ export {
96
+ ALL_SKILL_SLUGS,
97
+ STANDARD_LANGUAGES,
98
+ EXOTIC_LANGUAGES,
99
+ SECRET_LANGUAGES,
100
+ ALL_LANGUAGES,
101
+ ARTISANS_TOOLS,
102
+ MUSICAL_INSTRUMENTS,
103
+ GAMING_SETS,
104
+ OTHER_TOOLS,
105
+ ALL_TOOLS
106
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseWeapon
3
- } from "./chunk-6NK2MUD3.js";
3
+ } from "./chunk-HZA7OE7N.js";
4
4
 
5
5
  // src/weapon/weapon.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  backgroundEntitySchema
3
- } from "./chunk-SE7AZDR3.js";
3
+ } from "./chunk-JRDPUDT5.js";
4
4
 
5
5
  // src/background/background.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -0,0 +1,15 @@
1
+ // src/dnd/warn-once.ts
2
+ var seen = /* @__PURE__ */ new Set();
3
+ function warnOnce(key, msg) {
4
+ if (seen.has(key)) return;
5
+ seen.add(key);
6
+ console.warn(msg);
7
+ }
8
+ function __resetWarnOnceForTests() {
9
+ seen.clear();
10
+ }
11
+
12
+ export {
13
+ warnOnce,
14
+ __resetWarnOnceForTests
15
+ };
@@ -0,0 +1,161 @@
1
+ import {
2
+ RACE_STRUCTURAL_PSEUDO
3
+ } from "./chunk-PVCEA4HZ.js";
4
+ import {
5
+ warnOnce
6
+ } from "./chunk-LVQLWRCU.js";
7
+ import {
8
+ slugify
9
+ } from "./chunk-6X4KUDMU.js";
10
+ import {
11
+ mirrorSpellShapes
12
+ } from "./chunk-OZP6JFGT.js";
13
+ import {
14
+ ABILITY_KEYS
15
+ } from "./chunk-WELIKLZF.js";
16
+
17
+ // src/pc/pc.additional-spells.ts
18
+ var entriesOf = (a) => Array.isArray(a) ? a : a && typeof a === "object" ? [a] : [];
19
+ var editionOf = (x) => {
20
+ const e = x == null ? void 0 : x.edition;
21
+ return typeof e === "string" ? e : void 0;
22
+ };
23
+ var prefixOf = (slug) => {
24
+ var _a;
25
+ return (_a = slug.split("_")[0]) != null ? _a : slug;
26
+ };
27
+ function normalizeSpellRef(ref) {
28
+ var _a, _b, _c;
29
+ if (typeof ref !== "string") return null;
30
+ let s = ref.trim();
31
+ const wl = /^\[\[(.+)\]\]$/.exec(s);
32
+ if (wl) {
33
+ const target = (_a = wl[1].split("|")[0]) != null ? _a : "";
34
+ const tail = (_b = target.split("/").pop()) != null ? _b : target;
35
+ const w = slugify(tail.replace(/#.*$/, "").trim());
36
+ return w.length > 0 ? w : null;
37
+ }
38
+ s = s.replace(/#.*$/, "");
39
+ s = (_c = s.split("|")[0]) != null ? _c : "";
40
+ const out = slugify(s.trim());
41
+ return out.length > 0 ? out : null;
42
+ }
43
+ function buildSpellNameIndex(entities) {
44
+ var _a;
45
+ const byName = /* @__PURE__ */ new Map();
46
+ for (const e of entities.search("", "spell", Number.POSITIVE_INFINITY)) {
47
+ const raw = e.data.name;
48
+ const key = slugify(typeof raw === "string" ? raw : e.name);
49
+ const list = (_a = byName.get(key)) != null ? _a : [];
50
+ list.push(e);
51
+ byName.set(key, list);
52
+ }
53
+ return { byName };
54
+ }
55
+ function resolveSpellByName(opts) {
56
+ var _a;
57
+ const { entities, index, nameSlug, carrierSlug, carrierEdition, alreadyCollected } = opts;
58
+ const own = alreadyCollected.find((s) => {
59
+ var _a2;
60
+ return slugify(String((_a2 = s.entity.name) != null ? _a2 : "")) === nameSlug;
61
+ });
62
+ if (own) return { entity: own.entity, slug: own.slug };
63
+ const exact = entities.getByTypeAndSlug("spell", `${prefixOf(carrierSlug)}_spell_${nameSlug}`);
64
+ if (exact) return { entity: mirrorSpellShapes(exact.data), slug: exact.slug };
65
+ const cands = (_a = index.byName.get(nameSlug)) != null ? _a : [];
66
+ if (cands.length === 0) {
67
+ warnOnce(`addspells:miss:${nameSlug}`, `archivist: additional_spells ref "${nameSlug}" matches no spell in the compendium`);
68
+ return null;
69
+ }
70
+ const prefix = prefixOf(carrierSlug);
71
+ let pool = cands.filter((e) => prefixOf(e.slug) === prefix);
72
+ if (pool.length === 0) pool = cands;
73
+ if (carrierEdition !== void 0) {
74
+ const same = pool.filter((e) => editionOf(e.data) === carrierEdition);
75
+ if (same.length > 0) pool = same;
76
+ }
77
+ pool = [...pool].sort((a, b) => a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0);
78
+ if (pool.length > 1) warnOnce(`addspells:multi:${nameSlug}`, `archivist: additional_spells ref "${nameSlug}" matches ${cands.length} spells; using "${pool[0].slug}"`);
79
+ return { entity: mirrorSpellShapes(pool[0].data), slug: pool[0].slug };
80
+ }
81
+ var hasContentSelectInline = (choices) => Array.isArray(choices) && choices.some((c) => (c == null ? void 0 : c.kind) === "select-inline" && typeof c.id === "string" && !RACE_STRUCTURAL_PSEUDO.has(c.id) || Array.isArray(c == null ? void 0 : c.options) && c.options.some((o) => hasContentSelectInline(o == null ? void 0 : o.choices)));
82
+ function raceIsUngated(race) {
83
+ var _a;
84
+ const r = race;
85
+ if (hasContentSelectInline(r.choices)) return false;
86
+ return !((_a = r.traits) != null ? _a : []).some((t) => hasContentSelectInline(t == null ? void 0 : t.choices));
87
+ }
88
+ var readAbility = (v, own) => {
89
+ if (v && typeof v === "object" && "choose" in v) return "choose";
90
+ if (typeof v !== "string") return void 0;
91
+ if (v === "inherit") return own != null ? own : void 0;
92
+ return ABILITY_KEYS.includes(v) ? v : void 0;
93
+ };
94
+ var entryHasInSliceLeaf = (e, comparand, own) => readAbility(e.ability, own) !== "choose" && ["known", "prepared"].some((b) => {
95
+ const lv = e[b];
96
+ return !!lv && typeof lv === "object" && !Array.isArray(lv) && Object.entries(lv).some(([k, v]) => (k === "_" || Number(k) <= comparand) && Array.isArray(v) && v.some((x) => typeof x === "string"));
97
+ });
98
+ function collectAdditionalSpells(args) {
99
+ const { race, feats, classes, totalLevel, ownAbility, alreadyCollected, entities, warnings } = args;
100
+ let index = null;
101
+ const indexOf = () => index != null ? index : index = buildSpellNameIndex(entities);
102
+ const out = [];
103
+ const carriers = [];
104
+ const asRaw = (x) => x == null ? void 0 : x.additional_spells;
105
+ if (race && raceIsUngated(race)) carriers.push({ root: "race", slug: race.slug, edition: editionOf(race), entries: entriesOf(asRaw(race)), comparand: totalLevel, classSlug: null });
106
+ for (const f of feats) carriers.push({ root: "feat", slug: f.slug, edition: editionOf(f), entries: entriesOf(asRaw(f)), comparand: totalLevel, classSlug: null });
107
+ for (const c of classes) {
108
+ if (!c.entity) continue;
109
+ carriers.push({ root: "class", slug: c.entity.slug, edition: editionOf(c.entity), entries: entriesOf(asRaw(c.entity)), comparand: c.level, classSlug: c.entity.slug });
110
+ if (c.subclass) carriers.push({ root: "subclass", slug: c.subclass.slug, edition: editionOf(c.subclass), entries: entriesOf(asRaw(c.subclass)), comparand: c.level, classSlug: c.entity.slug });
111
+ }
112
+ for (const car of carriers) {
113
+ if (car.entries.length === 0) continue;
114
+ if (car.entries.length > 1) {
115
+ if (car.entries.some((e) => entryHasInSliceLeaf(e, car.comparand, ownAbility))) warnOnce(`addspells:siblings:${car.slug}`, `archivist: additional_spells on "${car.slug}" has ${car.entries.length} sibling entries (a choose-one grant); skipped`);
116
+ continue;
117
+ }
118
+ const entry = car.entries[0];
119
+ const ability = readAbility(entry.ability, ownAbility);
120
+ if (ability === "choose") continue;
121
+ for (const bucket of ["known", "prepared"]) {
122
+ const levels = entry[bucket];
123
+ if (!levels || typeof levels !== "object" || Array.isArray(levels)) continue;
124
+ for (const [k, v] of Object.entries(levels)) {
125
+ if (!(k === "_" || Number(k) <= car.comparand)) continue;
126
+ if (!Array.isArray(v)) {
127
+ warnOnce(`addspells:usage:${car.slug}:${bucket}:${k}`, `archivist: additional_spells on "${car.slug}" ${bucket}.${k} is a usage economy (skipped; G8)`);
128
+ continue;
129
+ }
130
+ for (const leaf of v) {
131
+ const nameSlug = normalizeSpellRef(leaf);
132
+ if (!nameSlug) continue;
133
+ const hit = resolveSpellByName({ entities, index: indexOf(), nameSlug, carrierSlug: car.slug, carrierEdition: car.edition, alreadyCollected: [...alreadyCollected, ...out] });
134
+ if (!hit) {
135
+ warnings.push(`additional_spells ref "${String(leaf)}" on ${car.slug} not found in compendium.`);
136
+ continue;
137
+ }
138
+ out.push({
139
+ entity: hit.entity,
140
+ slug: hit.slug,
141
+ classSlug: car.classSlug,
142
+ source: car.root === "race" ? "race" : car.root === "feat" ? "feat" : "class",
143
+ prepared: true,
144
+ alwaysPrepared: true,
145
+ ...ability ? { ability } : {}
146
+ });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return out;
152
+ }
153
+
154
+ export {
155
+ prefixOf,
156
+ normalizeSpellRef,
157
+ buildSpellNameIndex,
158
+ resolveSpellByName,
159
+ raceIsUngated,
160
+ collectAdditionalSpells
161
+ };
@@ -0,0 +1,165 @@
1
+ import {
2
+ derivePoolLayout
3
+ } from "./chunk-PP2UHLBA.js";
4
+ import {
5
+ readTableColumn
6
+ } from "./chunk-IUAAXXNO.js";
7
+ import {
8
+ warnOnce
9
+ } from "./chunk-LVQLWRCU.js";
10
+ import {
11
+ bareEntitySlug,
12
+ wikilinkTailSlug
13
+ } from "./chunk-6X4KUDMU.js";
14
+
15
+ // src/pc/pc.pools.ts
16
+ function levelPrereqMax(d) {
17
+ var _a;
18
+ return ((_a = d.prerequisites) != null ? _a : []).filter((p) => p.kind === "level").reduce((m, p) => Math.max(m, p.min), 0);
19
+ }
20
+ function resolvePool(rc, classIndex, pool, registry, index) {
21
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
22
+ const entity = rc.entity;
23
+ const level = rc.level;
24
+ const ownerBare = bareEntitySlug(entity.slug);
25
+ const ownerPrefix = entity.slug.split("_")[0];
26
+ const col = pool.count.column;
27
+ const count = (_a = readTableColumn(entity.table, level, [col])) != null ? _a : 0;
28
+ let anchorLevel = 1;
29
+ let columnSeen = false;
30
+ for (let l = 1; l <= 20; l++) {
31
+ const c = readTableColumn(entity.table, l, [col]);
32
+ if (c != null) columnSeen = true;
33
+ if (c != null && c >= 1) {
34
+ anchorLevel = l;
35
+ break;
36
+ }
37
+ }
38
+ if (!columnSeen) {
39
+ warnOnce(
40
+ `pool-column:${pool.id}`,
41
+ `Archivist: pool "${pool.id}" declares count column "${col}", which "${entity.slug}"'s class table carries at no level; the pool resolves count 0 at anchor level 1`
42
+ );
43
+ }
44
+ const ft = pool.source.where.feature_type;
45
+ const all = registry.search("", "optional-feature", Number.POSITIVE_INFINITY).slice().sort((a, b) => a.name.localeCompare(b.name) || a.slug.localeCompare(b.slug));
46
+ const byBare = /* @__PURE__ */ new Map();
47
+ const candidates = /* @__PURE__ */ new Map();
48
+ for (const e of all) {
49
+ const d = e.data;
50
+ const entry = { slug: e.slug, entity: d, ...e.compendium ? { compendium: e.compendium } : {} };
51
+ const bare = bareEntitySlug(e.slug);
52
+ byBare.set(bare, entry);
53
+ if (d.feature_type !== ft) continue;
54
+ if (!((_b = d.available_to) != null ? _b : []).some((l) => wikilinkTailSlug(l) === ownerBare)) continue;
55
+ if (levelPrereqMax(d) > level) continue;
56
+ const group = candidates.get(bare);
57
+ if (group) group.push(entry);
58
+ else candidates.set(bare, [entry]);
59
+ }
60
+ const available = [];
61
+ for (const [bare, group] of candidates) {
62
+ if (group.length === 1) {
63
+ available.push(group[0]);
64
+ continue;
65
+ }
66
+ const owned = group.find((e) => e.slug.split("_")[0] === ownerPrefix);
67
+ if (!owned) {
68
+ warnOnce(
69
+ `pool-collapse:${bare}`,
70
+ `Archivist: pool "${pool.id}" holds ${group.length} cross-edition entries for "${bare}" and none shares the owner's compendium prefix "${ownerPrefix}"; keeping "${group[0].slug}"`
71
+ );
72
+ }
73
+ available.push(owned != null ? owned : group[0]);
74
+ }
75
+ const grantDecls = [
76
+ ...(_d = (_c = rc.entity) == null ? void 0 : _c.pool_grants) != null ? _d : [],
77
+ ...(_f = (_e = rc.subclass) == null ? void 0 : _e.pool_grants) != null ? _f : []
78
+ ];
79
+ const grantsRaw = grantDecls.filter((g) => g.pool === pool.id).flatMap((g) => g.grants).filter((g) => g.at_level <= level).map((g) => byBare.get(wikilinkTailSlug(g.feature))).filter((e) => e != null);
80
+ const grantedBare = /* @__PURE__ */ new Set();
81
+ const grants = grantsRaw.filter((e) => {
82
+ const key = bareEntitySlug(e.slug);
83
+ if (grantedBare.has(key)) return false;
84
+ grantedBare.add(key);
85
+ return true;
86
+ });
87
+ const bySlugAvailable = new Map(available.map((e) => [e.slug, e]));
88
+ const byBareAvailable = new Map(available.map((e) => [bareEntitySlug(e.slug), e]));
89
+ const resolveStored = (s) => {
90
+ const exact = bySlugAvailable.get(s);
91
+ if (exact) return exact;
92
+ const survivor = byBareAvailable.get(bareEntitySlug(s));
93
+ if (survivor) return survivor;
94
+ const full = registry.getByTypeAndSlug("optional-feature", s);
95
+ if (full) {
96
+ const d = full.data;
97
+ return { slug: full.slug, entity: d, ...full.compendium ? { compendium: full.compendium } : {} };
98
+ }
99
+ return byBare.get(bareEntitySlug(s));
100
+ };
101
+ const raw = (_g = rc.choices[anchorLevel]) == null ? void 0 : _g[pool.id];
102
+ const selectedSlugs = Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
103
+ const selected = [];
104
+ const seenBare = /* @__PURE__ */ new Set();
105
+ for (const s of selectedSlugs) {
106
+ const entry = resolveStored(s);
107
+ if (!entry) continue;
108
+ const bare = bareEntitySlug(entry.slug);
109
+ if (grantedBare.has(bare) || seenBare.has(bare)) continue;
110
+ seenBare.add(bare);
111
+ selected.push(entry);
112
+ }
113
+ const members = [...available, ...grants];
114
+ const layout = derivePoolLayout(members);
115
+ const votes = /* @__PURE__ */ new Map();
116
+ for (const e of members) {
117
+ const id = (_h = e.entity.consumes) == null ? void 0 : _h.resource;
118
+ if (!id || !index.has(id)) continue;
119
+ votes.set(id, ((_i = votes.get(id)) != null ? _i : 0) + 1);
120
+ }
121
+ let resource;
122
+ let bestN = 0;
123
+ for (const [id, n] of votes) if (n > bestN) {
124
+ resource = id;
125
+ bestN = n;
126
+ }
127
+ return {
128
+ id: pool.id,
129
+ label: pool.label,
130
+ classIndex,
131
+ count,
132
+ anchorLevel,
133
+ selected,
134
+ available,
135
+ grants,
136
+ ...layout ? { layout } : {},
137
+ ...resource ? { resource } : {}
138
+ };
139
+ }
140
+ function resolveAllPools(resolved, registry, index) {
141
+ const out = [];
142
+ resolved.classes.forEach((rc, classIndex) => {
143
+ var _a, _b, _c;
144
+ if (!rc.entity) return;
145
+ const decls = [...(_a = rc.entity.selection_pools) != null ? _a : [], ...(_c = (_b = rc.subclass) == null ? void 0 : _b.selection_pools) != null ? _c : []];
146
+ const seen = /* @__PURE__ */ new Set();
147
+ for (const pool of decls) {
148
+ if (seen.has(pool.id)) continue;
149
+ seen.add(pool.id);
150
+ out.push(resolvePool(rc, classIndex, pool, registry, index));
151
+ }
152
+ });
153
+ return out;
154
+ }
155
+ function strandedPicks(pool) {
156
+ const inAvailable = new Set(pool.available.map((e) => e.slug));
157
+ return pool.selected.filter((e) => !inAvailable.has(e.slug));
158
+ }
159
+
160
+ export {
161
+ levelPrereqMax,
162
+ resolvePool,
163
+ resolveAllPools,
164
+ strandedPicks
165
+ };
@@ -1,25 +1,25 @@
1
1
  import {
2
2
  classifyWeaponRange
3
- } from "./chunk-353WXS6S.js";
4
- import {
5
- normKey
6
- } from "./chunk-O5EYMKFH.js";
3
+ } from "./chunk-UIRMA5KM.js";
7
4
  import {
8
5
  defaultSlotForType,
9
6
  effectiveArmor,
10
7
  isItemEntity,
11
8
  isWeaponEntity,
12
9
  resolveEntityForEntry
13
- } from "./chunk-N6N74K6X.js";
10
+ } from "./chunk-UBBKSYBY.js";
11
+ import {
12
+ normKey
13
+ } from "./chunk-RLGQ5PZZ.js";
14
14
  import {
15
15
  readNumericBonus
16
16
  } from "./chunk-LWFTHJIE.js";
17
17
  import {
18
18
  resolveBaseItem
19
- } from "./chunk-4LZJXJJS.js";
19
+ } from "./chunk-WXWPK3LI.js";
20
20
  import {
21
21
  bareEntitySlug
22
- } from "./chunk-LV4SNWZQ.js";
22
+ } from "./chunk-6X4KUDMU.js";
23
23
 
24
24
  // src/weapon/weapon-mastery.ts
25
25
  var MASTERY = {
@@ -405,7 +405,7 @@ function magicBonusesForWeaponEntry(entry, registry, ctx) {
405
405
  itemRiders = Array.isArray(entity.damage_riders) ? entity.damage_riders.filter((r) => {
406
406
  var _a2;
407
407
  return ((_a2 = r.applies_to) != null ? _a2 : "weapon") !== "spell";
408
- }).map((r) => ({ amount: r.amount, damage_type: r.damage_type, source: entity.name })) : [];
408
+ }).map((r) => ({ amount: r.amount, damage_type: r.damage_type, source: entity.name, ...r.condition ? { condition: r.condition } : {} })) : [];
409
409
  }
410
410
  return {
411
411
  atk: itemAttack + entryAttack,
@@ -482,6 +482,40 @@ function buildAttackRow(args) {
482
482
  }
483
483
  return row;
484
484
  }
485
+ function buildUnarmedRow(mods, proficiencyBonus, spec) {
486
+ var _a;
487
+ const candidates = ["str", ...(_a = spec == null ? void 0 : spec.abilities) != null ? _a : []];
488
+ let ability = "str";
489
+ for (const ab of candidates) if (mods[ab] >= mods[ability]) ability = ab;
490
+ const abilityMod = mods[ability];
491
+ const toHit = abilityMod + proficiencyBonus;
492
+ const flat = `${abilityMod >= 0 ? "+" : ""}${abilityMod}`.replace(/^\+0$/, "");
493
+ const damageDice = (spec == null ? void 0 : spec.dice) ? `${spec.dice}${flat}` : String(Math.max(0, 1 + abilityMod));
494
+ const label = `${ability.toUpperCase()} modifier`;
495
+ return {
496
+ id: "unarmed-strike",
497
+ name: "Unarmed Strike",
498
+ unarmed: true,
499
+ range: "5 ft",
500
+ toHit,
501
+ damageDice,
502
+ damageType: "bludgeoning",
503
+ properties: [],
504
+ proficient: true,
505
+ breakdown: {
506
+ toHit: [
507
+ { source: label, amount: abilityMod, kind: "ability" },
508
+ { source: "Proficiency bonus", amount: proficiencyBonus, kind: "ability" }
509
+ ],
510
+ damage: [
511
+ { source: "Base damage", amount: 0, kind: "ability" },
512
+ { source: label, amount: abilityMod, kind: "ability" }
513
+ ]
514
+ },
515
+ subLabel: "Unarmed",
516
+ actionCost: "action"
517
+ };
518
+ }
485
519
  function humanizeWeaponToken(s) {
486
520
  return s.replace(/[-_]/g, " ").replace(/(^|[\s(])\w/g, (c) => c.toUpperCase());
487
521
  }
@@ -594,5 +628,7 @@ function computeSlotsAndAttacks(resolved, mods, profs, registry, warnings, profi
594
628
  export {
595
629
  emptyAppliedBonuses,
596
630
  computeAppliedBonuses,
631
+ isWeaponSlugProficient,
632
+ buildUnarmedRow,
597
633
  computeSlotsAndAttacks
598
634
  };