@archivist-gg/dnd5e 0.3.19 → 0.3.26

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 (441) hide show
  1. package/LICENSE +48 -21
  2. package/README.md +26 -48
  3. package/dist/armor/armor.codec.d.ts +0 -7
  4. package/dist/armor/armor.codec.js +1 -9
  5. package/dist/armor/armor.parser.js +1 -8
  6. package/dist/armor/armor.schema.js +1 -7
  7. package/dist/armor/armor.types.d.ts +0 -3
  8. package/dist/background/background.codec.d.ts +0 -6
  9. package/dist/background/background.codec.js +1 -12
  10. package/dist/background/background.parser.js +1 -11
  11. package/dist/background/background.schema.js +1 -12
  12. package/dist/background/background.types.d.ts +0 -5
  13. package/dist/chunk-2EOGK6R6.js +1 -0
  14. package/dist/chunk-2HRRH3WL.js +1 -0
  15. package/dist/chunk-2NUDWOFG.js +1 -0
  16. package/dist/chunk-3LWOVRLA.js +1 -0
  17. package/dist/chunk-3QQOATV3.js +1 -0
  18. package/dist/chunk-4E2GIWJE.js +1 -0
  19. package/dist/chunk-4GN3GYMP.js +1 -0
  20. package/dist/chunk-4IAMSRHD.js +1 -0
  21. package/dist/chunk-4JEF3CET.js +1 -0
  22. package/dist/chunk-4KVVAENP.js +1 -0
  23. package/dist/chunk-4SYAKWY4.js +1 -0
  24. package/dist/chunk-56JK6VCL.js +1 -0
  25. package/dist/chunk-5XDCM6YK.js +1 -0
  26. package/dist/chunk-63YJPWTM.js +1 -0
  27. package/dist/chunk-6R46KYGU.js +1 -0
  28. package/dist/chunk-6W253VHH.js +1 -0
  29. package/dist/chunk-72PRMZRD.js +1 -0
  30. package/dist/chunk-757KM22B.js +1 -0
  31. package/dist/chunk-7EL3GWWJ.js +1 -0
  32. package/dist/chunk-7FPQJDFD.js +1 -0
  33. package/dist/chunk-AINRPPLH.js +1 -0
  34. package/dist/chunk-BC52J4LA.js +1 -0
  35. package/dist/chunk-BCXGB4HP.js +1 -0
  36. package/dist/chunk-BREHZNTL.js +1 -0
  37. package/dist/chunk-BZ6BGGZS.js +1 -0
  38. package/dist/chunk-CAPYNIGK.js +1 -0
  39. package/dist/chunk-CCAVZANF.js +1 -0
  40. package/dist/chunk-CCFIINBA.js +1 -0
  41. package/dist/chunk-CEHL7PPC.js +1 -0
  42. package/dist/chunk-CMIEZQL4.js +1 -0
  43. package/dist/chunk-CNMHADNV.js +1 -0
  44. package/dist/chunk-CSTAQQGX.js +1 -0
  45. package/dist/chunk-DTB7YBMZ.js +1 -0
  46. package/dist/chunk-DVUXUIPV.js +1 -0
  47. package/dist/chunk-DZITM5AG.js +1 -0
  48. package/dist/chunk-E3MS4M3N.js +1 -0
  49. package/dist/chunk-E7KFJLDR.js +1 -0
  50. package/dist/chunk-EAARMPCW.js +1 -0
  51. package/dist/chunk-EPA24PVZ.js +1 -0
  52. package/dist/chunk-ETDMOGFO.js +1 -0
  53. package/dist/chunk-EVT7MGAC.js +1 -0
  54. package/dist/chunk-FOLHTMSC.js +1 -0
  55. package/dist/chunk-GCYUCIDN.js +1 -0
  56. package/dist/chunk-GD7WRCNH.js +1 -0
  57. package/dist/chunk-GGQDQSIF.js +1 -0
  58. package/dist/chunk-GIQLIBC7.js +1 -0
  59. package/dist/chunk-HX7WBOKR.js +1 -0
  60. package/dist/chunk-I26FHSI6.js +1 -0
  61. package/dist/chunk-IHPLT2ZT.js +1 -0
  62. package/dist/chunk-J3RP5C7L.js +1 -0
  63. package/dist/chunk-J5GL6FLP.js +1 -0
  64. package/dist/chunk-JXDX2DKF.js +1 -0
  65. package/dist/chunk-KEXSF3CH.js +1 -0
  66. package/dist/chunk-KM75CC6Q.js +1 -0
  67. package/dist/chunk-L2DXF7YS.js +1 -0
  68. package/dist/chunk-LHH5XSEA.js +1 -0
  69. package/dist/chunk-LJNT3PJP.js +1 -0
  70. package/dist/chunk-LR6UMA5V.js +1 -0
  71. package/dist/chunk-M6RPOLKS.js +1 -0
  72. package/dist/chunk-MGGKZGLG.js +1 -0
  73. package/dist/chunk-NEMX7QGG.js +1 -0
  74. package/dist/chunk-NIWLD33X.js +1 -0
  75. package/dist/chunk-NU2Z7MTS.js +1 -0
  76. package/dist/chunk-NYPH7RQN.js +1 -0
  77. package/dist/chunk-NYTR6NJS.js +1 -0
  78. package/dist/chunk-O2QZ73GA.js +1 -0
  79. package/dist/chunk-O776WL7O.js +1 -0
  80. package/dist/chunk-ONCXJMJM.js +1 -0
  81. package/dist/chunk-OTRH62HY.js +1 -0
  82. package/dist/chunk-PFQPP77Q.js +1 -0
  83. package/dist/chunk-PKIMOVQG.js +1 -0
  84. package/dist/chunk-PZ3ZZ5H5.js +1 -0
  85. package/dist/chunk-PZ4L2EEG.js +1 -0
  86. package/dist/chunk-QMEKQTUT.js +1 -0
  87. package/dist/chunk-QVWT67WA.js +1 -0
  88. package/dist/chunk-RE5Z5RNK.js +1 -0
  89. package/dist/chunk-RHIEOYDX.js +1 -0
  90. package/dist/chunk-RQZCGXUZ.js +1 -0
  91. package/dist/chunk-S5UCI27C.js +1 -0
  92. package/dist/chunk-SEOASDO4.js +1 -0
  93. package/dist/chunk-SFK57JAA.js +1 -0
  94. package/dist/chunk-SU4MEZ5P.js +1 -0
  95. package/dist/chunk-T55DELVL.js +1 -0
  96. package/dist/chunk-TKIEPC6F.js +1 -0
  97. package/dist/chunk-UBUKCRZ3.js +1 -0
  98. package/dist/chunk-VA3ZWV7C.js +1 -0
  99. package/dist/chunk-VIP3FH2O.js +1 -0
  100. package/dist/chunk-VTQ4RWEG.js +1 -0
  101. package/dist/chunk-VVJXZZ4Z.js +1 -0
  102. package/dist/chunk-WAUNLUFQ.js +1 -0
  103. package/dist/chunk-X22SISGM.js +1 -0
  104. package/dist/chunk-XKJXT2PN.js +1 -0
  105. package/dist/chunk-XPF53K54.js +1 -0
  106. package/dist/chunk-YGH7S5ZF.js +1 -0
  107. package/dist/chunk-ZE46ADXS.js +1 -0
  108. package/dist/chunk-ZI3FEUX3.js +1 -0
  109. package/dist/chunk-ZS5BMNXC.js +1 -0
  110. package/dist/chunk-ZVL5FXXO.js +1 -0
  111. package/dist/class/class.codec.d.ts +0 -7
  112. package/dist/class/class.codec.js +1 -18
  113. package/dist/class/class.parser.js +1 -17
  114. package/dist/class/class.schema.d.ts +4 -3
  115. package/dist/class/class.schema.js +1 -15
  116. package/dist/class/class.slug.d.ts +0 -11
  117. package/dist/class/class.slug.js +1 -8
  118. package/dist/class/class.standard-array.d.ts +0 -7
  119. package/dist/class/class.standard-array.js +1 -20
  120. package/dist/class/class.types.d.ts +0 -20
  121. package/dist/condition/condition.codec.d.ts +0 -6
  122. package/dist/condition/condition.parser.d.ts +0 -10
  123. package/dist/condition/condition.parser.js +1 -7
  124. package/dist/condition/condition.schema.d.ts +0 -16
  125. package/dist/condition/condition.types.d.ts +0 -3
  126. package/dist/data-srd/index.generated.js +1 -146
  127. package/dist/dnd/amount-text.d.ts +3 -30
  128. package/dist/dnd/amount-text.js +1 -15
  129. package/dist/dnd/constants.d.ts +0 -18
  130. package/dist/dnd/constants.js +1 -42
  131. package/dist/dnd/formula-tags.d.ts +0 -2
  132. package/dist/dnd/formula-tags.js +1 -119
  133. package/dist/dnd/math.d.ts +0 -26
  134. package/dist/dnd/math.js +1 -45
  135. package/dist/dnd/prose-tags.d.ts +1 -15
  136. package/dist/dnd/prose-tags.js +1 -18
  137. package/dist/dnd/resource-die.d.ts +0 -4
  138. package/dist/dnd/resource-die.js +1 -17
  139. package/dist/dnd/resource-formula.d.ts +0 -43
  140. package/dist/dnd/resource-formula.js +1 -14
  141. package/dist/dnd/resource-words.d.ts +0 -2
  142. package/dist/dnd/resource-words.js +1 -30
  143. package/dist/dnd/srd-tag-converter.d.ts +0 -21
  144. package/dist/dnd/srd-tag-converter.js +1 -12
  145. package/dist/dnd/tag-grammar.js +1 -12
  146. package/dist/dnd/warn-once.js +1 -8
  147. package/dist/encounter/encounter.ai-schema.js +1 -8
  148. package/dist/entities/base-item-resolver.d.ts +0 -26
  149. package/dist/entities/base-item-resolver.js +1 -11
  150. package/dist/entities/registry-revision.d.ts +0 -15
  151. package/dist/entities/registry-revision.js +1 -10
  152. package/dist/entities/slug.d.ts +1 -31
  153. package/dist/entities/slug.js +1 -12
  154. package/dist/entities/wikilink-display.d.ts +0 -2
  155. package/dist/entities/wikilink-display.js +1 -10
  156. package/dist/feat/feat.category-codes.d.ts +1 -26
  157. package/dist/feat/feat.category-codes.js +1 -14
  158. package/dist/feat/feat.codec.d.ts +0 -6
  159. package/dist/feat/feat.codec.js +1 -12
  160. package/dist/feat/feat.parser.js +1 -11
  161. package/dist/feat/feat.schema.d.ts +46 -4
  162. package/dist/feat/feat.schema.js +1 -10
  163. package/dist/feat/feat.types.d.ts +0 -6
  164. package/dist/index.js +45 -141495
  165. package/dist/inline-tag-parser.js +1 -6
  166. package/dist/item/item.actions-map.d.ts +4 -63
  167. package/dist/item/item.actions-map.js +1 -10
  168. package/dist/item/item.ai-schema.js +1 -6
  169. package/dist/item/item.attunement.d.ts +0 -14
  170. package/dist/item/item.attunement.js +1 -6
  171. package/dist/item/item.bonuses.js +1 -10
  172. package/dist/item/item.codec.js +1 -9
  173. package/dist/item/item.conditions.d.ts +0 -7
  174. package/dist/item/item.conditions.js +1 -11
  175. package/dist/item/item.conditions.types.d.ts +0 -2
  176. package/dist/item/item.cost.js +1 -29
  177. package/dist/item/item.enrichment.js +1 -9
  178. package/dist/item/item.icon.d.ts +0 -8
  179. package/dist/item/item.icon.js +1 -211
  180. package/dist/item/item.parser.js +1 -8
  181. package/dist/item/item.schema.d.ts +5 -0
  182. package/dist/item/item.schema.js +1 -11
  183. package/dist/item/item.types.d.ts +5 -28
  184. package/dist/monster/monster.ai-schema.js +1 -6
  185. package/dist/monster/monster.codec.d.ts +0 -10
  186. package/dist/monster/monster.enrichment.js +1 -19
  187. package/dist/monster/monster.format.d.ts +0 -69
  188. package/dist/monster/monster.format.js +1 -78
  189. package/dist/monster/monster.parser.d.ts +0 -4
  190. package/dist/monster/monster.parser.js +1 -15
  191. package/dist/monster/monster.resolve.d.ts +0 -4
  192. package/dist/monster/monster.schema.d.ts +0 -9
  193. package/dist/monster/monster.schema.js +1 -34
  194. package/dist/monster/monster.types.d.ts +0 -3
  195. package/dist/monster/monster.types.js +1 -1
  196. package/dist/optional-feature/optional-feature.codec.d.ts +0 -11
  197. package/dist/optional-feature/optional-feature.codec.js +1 -13
  198. package/dist/optional-feature/optional-feature.parser.js +1 -12
  199. package/dist/optional-feature/optional-feature.schema.d.ts +44 -3
  200. package/dist/optional-feature/optional-feature.schema.js +1 -15
  201. package/dist/pack.d.ts +0 -9
  202. package/dist/pc/conditions.constants.js +1 -6
  203. package/dist/pc/decision-recognizer.js +1 -8
  204. package/dist/pc/pc.additional-spells.d.ts +0 -24
  205. package/dist/pc/pc.additional-spells.js +1 -26
  206. package/dist/pc/pc.amount-bindings.d.ts +3 -28
  207. package/dist/pc/pc.amount-bindings.js +1 -28
  208. package/dist/pc/pc.asi-flatten.d.ts +0 -59
  209. package/dist/pc/pc.asi-flatten.js +1 -16
  210. package/dist/pc/pc.conditions.d.ts +1 -0
  211. package/dist/pc/pc.conditions.js +1 -6
  212. package/dist/pc/pc.containment.d.ts +0 -5
  213. package/dist/pc/pc.containment.js +1 -24
  214. package/dist/pc/pc.decision-engine.d.ts +6 -145
  215. package/dist/pc/pc.decision-engine.js +1 -55
  216. package/dist/pc/pc.defense-normalize.d.ts +0 -10
  217. package/dist/pc/pc.defense-normalize.js +1 -6
  218. package/dist/pc/pc.entry-overrides.d.ts +19 -58
  219. package/dist/pc/pc.entry-overrides.js +1 -41
  220. package/dist/pc/pc.equipment.d.ts +2 -22
  221. package/dist/pc/pc.equipment.js +1 -34
  222. package/dist/pc/pc.feature-effects.d.ts +27 -281
  223. package/dist/pc/pc.feature-effects.js +1 -39
  224. package/dist/pc/pc.formula-context.js +1 -11
  225. package/dist/pc/pc.infusions.d.ts +0 -65
  226. package/dist/pc/pc.infusions.js +1 -65
  227. package/dist/pc/pc.item-effects.d.ts +19 -0
  228. package/dist/pc/pc.item-effects.js +1 -0
  229. package/dist/pc/pc.member-choices.d.ts +3 -66
  230. package/dist/pc/pc.member-choices.js +1 -39
  231. package/dist/pc/pc.parser.js +1 -58
  232. package/dist/pc/pc.pools.d.ts +7 -10
  233. package/dist/pc/pc.pools.js +1 -27
  234. package/dist/pc/pc.proficiencies.d.ts +0 -40
  235. package/dist/pc/pc.proficiencies.js +1 -156
  236. package/dist/pc/pc.proficiency-grants.d.ts +3 -27
  237. package/dist/pc/pc.proficiency-normalize.d.ts +0 -35
  238. package/dist/pc/pc.proficiency-normalize.js +1 -18
  239. package/dist/pc/pc.proficiency-query.d.ts +0 -13
  240. package/dist/pc/pc.proficiency-query.js +1 -27
  241. package/dist/pc/pc.recalc.d.ts +8 -131
  242. package/dist/pc/pc.recalc.js +1 -1042
  243. package/dist/pc/pc.resolver.d.ts +9 -107
  244. package/dist/pc/pc.resolver.js +1 -60
  245. package/dist/pc/pc.resource-seed.d.ts +0 -8
  246. package/dist/pc/pc.resource-seed.js +1 -42
  247. package/dist/pc/pc.resources.d.ts +1 -59
  248. package/dist/pc/pc.resources.js +1 -23
  249. package/dist/pc/pc.rest.d.ts +1 -20
  250. package/dist/pc/pc.rest.js +1 -231
  251. package/dist/pc/pc.schema.d.ts +20 -2
  252. package/dist/pc/pc.schema.js +1 -9
  253. package/dist/pc/pc.slotting.d.ts +0 -29
  254. package/dist/pc/pc.slotting.js +1 -28
  255. package/dist/pc/pc.speeds.d.ts +36 -0
  256. package/dist/pc/pc.spell-scope.d.ts +0 -16
  257. package/dist/pc/pc.spellcasting.d.ts +0 -70
  258. package/dist/pc/pc.spellcasting.js +1 -28
  259. package/dist/pc/pc.table-column.d.ts +3 -22
  260. package/dist/pc/pc.table-column.js +1 -18
  261. package/dist/pc/pc.tool-picks.d.ts +0 -27
  262. package/dist/pc/pc.tool-picks.js +1 -18
  263. package/dist/pc/pc.types.d.ts +59 -374
  264. package/dist/pc/pc.weapon-grant.d.ts +0 -6
  265. package/dist/pc/pool-layout.d.ts +0 -39
  266. package/dist/pc/pool-layout.js +1 -18
  267. package/dist/pc/resource-equivalents.d.ts +2 -40
  268. package/dist/pc/roll-scope.js +1 -8
  269. package/dist/pc/roll-tag-labels.d.ts +0 -32
  270. package/dist/pc/roll-tag-labels.js +1 -17
  271. package/dist/pc/spell-source.d.ts +0 -11
  272. package/dist/pc/spell-source.js +1 -8
  273. package/dist/race/race.codec.d.ts +0 -6
  274. package/dist/race/race.codec.js +1 -15
  275. package/dist/race/race.parser.js +1 -14
  276. package/dist/race/race.schema.d.ts +0 -8
  277. package/dist/race/race.schema.js +1 -14
  278. package/dist/race/race.structural.d.ts +0 -6
  279. package/dist/race/race.structural.js +1 -6
  280. package/dist/race/race.types.d.ts +0 -8
  281. package/dist/schemas/attack-schema.d.ts +5 -0
  282. package/dist/schemas/caster-type-schema.d.ts +1 -6
  283. package/dist/schemas/caster-type-schema.js +1 -6
  284. package/dist/schemas/choice-schema.js +1 -7
  285. package/dist/schemas/duration-schema.d.ts +0 -2
  286. package/dist/schemas/duration-schema.js +1 -6
  287. package/dist/schemas/entity-extras-schema.d.ts +0 -30
  288. package/dist/schemas/entity-extras-schema.js +1 -10
  289. package/dist/schemas/equipment-grant-schema.d.ts +0 -2
  290. package/dist/schemas/equipment-grant-schema.js +1 -12
  291. package/dist/schemas/feature-alias.d.ts +0 -27
  292. package/dist/schemas/feature-effect-schema.d.ts +44 -3
  293. package/dist/schemas/feature-effect-schema.js +1 -6
  294. package/dist/schemas/feature-schema.d.ts +0 -6
  295. package/dist/schemas/feature-schema.js +1 -12
  296. package/dist/schemas/resource-schema.d.ts +1 -34
  297. package/dist/schemas/resource-schema.js +1 -12
  298. package/dist/schemas/selection-pool-schema.js +1 -10
  299. package/dist/spell/casting-time.d.ts +0 -15
  300. package/dist/spell/casting-time.js +1 -6
  301. package/dist/spell/spell.access.d.ts +0 -6
  302. package/dist/spell/spell.access.js +1 -45
  303. package/dist/spell/spell.ai-schema.js +1 -6
  304. package/dist/spell/spell.codec.js +1 -9
  305. package/dist/spell/spell.enrichment.js +1 -9
  306. package/dist/spell/spell.filter.d.ts +0 -5
  307. package/dist/spell/spell.filter.js +1 -75
  308. package/dist/spell/spell.parser.d.ts +0 -31
  309. package/dist/spell/spell.parser.js +1 -16
  310. package/dist/spell/spell.scaling.d.ts +0 -46
  311. package/dist/spell/spell.scaling.js +1 -79
  312. package/dist/spell/spell.schema.js +1 -7
  313. package/dist/spell/spell.types.d.ts +0 -7
  314. package/dist/srd/retired-items.d.ts +0 -4
  315. package/dist/srd/retired-items.js +1 -11
  316. package/dist/srd-store.d.ts +0 -33
  317. package/dist/subclass/subclass.codec.d.ts +0 -8
  318. package/dist/subclass/subclass.codec.js +1 -17
  319. package/dist/subclass/subclass.parser.js +1 -16
  320. package/dist/subclass/subclass.schema.d.ts +2 -1
  321. package/dist/subclass/subclass.schema.js +1 -14
  322. package/dist/subclass/subclass.types.d.ts +0 -3
  323. package/dist/types/attack.d.ts +2 -0
  324. package/dist/types/casting-option.d.ts +0 -4
  325. package/dist/types/choice.d.ts +1 -72
  326. package/dist/types/choice.js +1 -24
  327. package/dist/types/edition.d.ts +0 -3
  328. package/dist/types/equipment-grant.d.ts +1 -27
  329. package/dist/types/equipment-grant.js +1 -12
  330. package/dist/types/feature-effect.d.ts +11 -23
  331. package/dist/types/feature.d.ts +0 -22
  332. package/dist/types/optional-feature.types.d.ts +1 -31
  333. package/dist/types/resource.d.ts +1 -21
  334. package/dist/types/selection-pool.d.ts +0 -24
  335. package/dist/weapon/weapon-mastery.d.ts +0 -1
  336. package/dist/weapon/weapon.classify.d.ts +0 -11
  337. package/dist/weapon/weapon.classify.js +1 -7
  338. package/dist/weapon/weapon.codec.d.ts +0 -9
  339. package/dist/weapon/weapon.codec.js +1 -9
  340. package/dist/weapon/weapon.parser.js +1 -8
  341. package/dist/weapon/weapon.schema.js +1 -7
  342. package/dist/weapon/weapon.types.d.ts +0 -3
  343. package/package.json +3 -3
  344. package/src/data-srd/ATTRIBUTION.md +1 -1
  345. package/dist/chunk-2FRUSVZS.js +0 -489
  346. package/dist/chunk-2LULMQTF.js +0 -14
  347. package/dist/chunk-3LWMFYKS.js +0 -57
  348. package/dist/chunk-3SFGWFVQ.js +0 -19
  349. package/dist/chunk-3SIUAFDQ.js +0 -18
  350. package/dist/chunk-3TM34RSJ.js +0 -23
  351. package/dist/chunk-4J6DS3EJ.js +0 -30
  352. package/dist/chunk-4U55VNC7.js +0 -22
  353. package/dist/chunk-5GKJAUMX.js +0 -59
  354. package/dist/chunk-5JXFJ5AU.js +0 -26
  355. package/dist/chunk-64VNLMSG.js +0 -375
  356. package/dist/chunk-656QCX4U.js +0 -22
  357. package/dist/chunk-6GNXYAYP.js +0 -25
  358. package/dist/chunk-6PXTNCBP.js +0 -133
  359. package/dist/chunk-6X2NV665.js +0 -33
  360. package/dist/chunk-7Q2VPKCD.js +0 -181
  361. package/dist/chunk-7XJHI5H5.js +0 -709
  362. package/dist/chunk-A54HHCWW.js +0 -67
  363. package/dist/chunk-B2QHP6UF.js +0 -159
  364. package/dist/chunk-B3DP42OM.js +0 -55
  365. package/dist/chunk-BJGOSM76.js +0 -18
  366. package/dist/chunk-BJWSOQUC.js +0 -133
  367. package/dist/chunk-CJYCVNW2.js +0 -7
  368. package/dist/chunk-CM5CWO4K.js +0 -735
  369. package/dist/chunk-DEEHHLAP.js +0 -271
  370. package/dist/chunk-DPUJDOKV.js +0 -365
  371. package/dist/chunk-EJD47JHL.js +0 -1838
  372. package/dist/chunk-EJP263OP.js +0 -186
  373. package/dist/chunk-EVMUJYUD.js +0 -195
  374. package/dist/chunk-EYX4JMAU.js +0 -101
  375. package/dist/chunk-FC4IGH5Y.js +0 -18
  376. package/dist/chunk-FJYBLXV7.js +0 -89
  377. package/dist/chunk-FMUD3LDV.js +0 -19
  378. package/dist/chunk-FMYWORTP.js +0 -93
  379. package/dist/chunk-FVXLP7P3.js +0 -18
  380. package/dist/chunk-G6MHJDVT.js +0 -41
  381. package/dist/chunk-GVWEFECG.js +0 -18
  382. package/dist/chunk-HHBD4SQ6.js +0 -24
  383. package/dist/chunk-HS6FIOLP.js +0 -52
  384. package/dist/chunk-HY2SRSVM.js +0 -23
  385. package/dist/chunk-IHE6KVC3.js +0 -13
  386. package/dist/chunk-IN4M4X7P.js +0 -34
  387. package/dist/chunk-IUAAXXNO.js +0 -58
  388. package/dist/chunk-JXWNXIIZ.js +0 -219
  389. package/dist/chunk-K5NJBTE2.js +0 -18
  390. package/dist/chunk-KR6JF3BF.js +0 -14
  391. package/dist/chunk-KSTV7J2U.js +0 -112
  392. package/dist/chunk-KU3YLF6D.js +0 -106
  393. package/dist/chunk-LBEXLN6I.js +0 -91
  394. package/dist/chunk-LHZXYFBU.js +0 -94
  395. package/dist/chunk-LICYHPI3.js +0 -237
  396. package/dist/chunk-LNT64X7C.js +0 -81
  397. package/dist/chunk-LSLSG67V.js +0 -31
  398. package/dist/chunk-LVQLWRCU.js +0 -15
  399. package/dist/chunk-MYY2C5MB.js +0 -233
  400. package/dist/chunk-NKZMQV2C.js +0 -19
  401. package/dist/chunk-NTU2DXNG.js +0 -355
  402. package/dist/chunk-NXUY5XQN.js +0 -1062
  403. package/dist/chunk-NZO7M5GV.js +0 -18
  404. package/dist/chunk-OOL4KMG2.js +0 -71
  405. package/dist/chunk-OOSRUJBI.js +0 -19
  406. package/dist/chunk-PDJSUH24.js +0 -110
  407. package/dist/chunk-PTXBIDG7.js +0 -63
  408. package/dist/chunk-PVCEA4HZ.js +0 -6
  409. package/dist/chunk-QA3YCOML.js +0 -101
  410. package/dist/chunk-QFWQKS3M.js +0 -110
  411. package/dist/chunk-QS5L5YTJ.js +0 -24
  412. package/dist/chunk-QYZV2MQA.js +0 -97
  413. package/dist/chunk-RD2MID3M.js +0 -292
  414. package/dist/chunk-S3YUXDSC.js +0 -278
  415. package/dist/chunk-S7REMWW4.js +0 -21
  416. package/dist/chunk-TOM66P2P.js +0 -38
  417. package/dist/chunk-TRBGC4ZG.js +0 -112
  418. package/dist/chunk-UA5KS2PL.js +0 -26
  419. package/dist/chunk-UJCK5IW4.js +0 -187
  420. package/dist/chunk-UNYR5GLI.js +0 -23
  421. package/dist/chunk-UZXG6QSY.js +0 -58
  422. package/dist/chunk-VN5DLURA.js +0 -158
  423. package/dist/chunk-VP5TIXDK.js +0 -178
  424. package/dist/chunk-VPYBK2MG.js +0 -18
  425. package/dist/chunk-VTTA2ALZ.js +0 -16
  426. package/dist/chunk-W6GC6OKK.js +0 -16
  427. package/dist/chunk-WELIKLZF.js +0 -256
  428. package/dist/chunk-WOHX7YTH.js +0 -165
  429. package/dist/chunk-WSVMLNTO.js +0 -31
  430. package/dist/chunk-WYGD2UGN.js +0 -14
  431. package/dist/chunk-XCFC7LGF.js +0 -122
  432. package/dist/chunk-XJ2F2WO6.js +0 -8
  433. package/dist/chunk-XTEFPUSN.js +0 -23
  434. package/dist/chunk-YBLDE5CG.js +0 -42
  435. package/dist/chunk-YDGMBMYI.js +0 -25
  436. package/dist/chunk-YHYTW5QA.js +0 -20
  437. package/dist/chunk-ZCTUYGNV.js +0 -26
  438. package/dist/chunk-ZDAEGJH4.js +0 -102
  439. package/dist/chunk-ZJXSXVFP.js +0 -58
  440. package/dist/chunk-ZOWKWMD2.js +0 -18
  441. package/dist/chunk-ZUQW5VBZ.js +0 -89
@@ -0,0 +1 @@
1
+ function readTableColumn(table,level,keys){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return null;for(const k of keys){const raw=cols[k];if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))return n}return null}function numericColumnsAt(table,level){var _a;const out={};const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return out;for(const[k,raw]of Object.entries(cols)){if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))out[k]=n}return out}var COUNT_COLUMNS={"weapon-mastery":["Weapon Mastery"]};function countColumnsFor(choiceId){if(!Object.prototype.hasOwnProperty.call(COUNT_COLUMNS,choiceId))return void 0;return COUNT_COLUMNS[choiceId]}function diceColumnAt(table,level,key){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols||!Object.prototype.hasOwnProperty.call(cols,key))return null;const raw=cols[key];if(typeof raw!=="string")return null;const cell=raw.trim();return/^\d+d\d+$/i.test(cell)?cell:null}function tableCellAt(table,level,key){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols||!Object.prototype.hasOwnProperty.call(cols,key))return null;const raw=cols[key];const cell=typeof raw==="number"?String(raw):typeof raw==="string"?raw.trim():"";if(/^\d+d\d+$/i.test(cell))return cell;if(!/^[+-]?\d+$/.test(cell))return null;const n=parseInt(cell,10);return n===0?null:String(n)}var UNARMED_DIE_COLUMNS={"martial-arts":"Martial Arts"};function unarmedDieColumnFor(featureSlug){if(!Object.prototype.hasOwnProperty.call(UNARMED_DIE_COLUMNS,featureSlug))return void 0;return UNARMED_DIE_COLUMNS[featureSlug]}export{readTableColumn,numericColumnsAt,COUNT_COLUMNS,countColumnsFor,diceColumnAt,tableCellAt,UNARMED_DIE_COLUMNS,unarmedDieColumnFor};
@@ -0,0 +1 @@
1
+ import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-NIWLD33X.js";import{resourceSchema}from"./chunk-CCFIINBA.js";import{startingEquipmentEntrySchema,startingGoldSchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var armorCategoryEnum=z.enum(["light","medium","heavy","shield"]);var weaponCategoryEnum=z.enum(["simple","martial"]);var hitDieEnum=z.enum(["d6","d8","d10","d12"]);var editionEnum=z.enum(["2014","2024"]);var weaponProficiencySchema=z.object({fixed:z.array(z.string()).optional(),categories:z.array(weaponCategoryEnum).optional(),conditional:z.array(z.object({category:weaponCategoryEnum,where_property:z.array(z.string()).nonempty()})).optional()}).refine(w=>{var _a,_b,_c,_d,_e,_f;return((_b=(_a=w.fixed)==null?void 0:_a.length)!=null?_b:0)+((_d=(_c=w.categories)==null?void 0:_c.length)!=null?_d:0)+((_f=(_e=w.conditional)==null?void 0:_e.length)!=null?_f:0)>0},{message:"weapon proficiency must declare at least one of fixed/categories/conditional"});var toolProficiencySchema=z.object({fixed:z.array(z.string()).optional(),choice:z.object({count:z.number().int().positive(),from:z.array(z.string()).nonempty()}).optional()}).refine(t=>{var _a,_b;return((_b=(_a=t.fixed)==null?void 0:_a.length)!=null?_b:0)>0||t.choice!==void 0},{message:"tool proficiency must declare fixed or choice"});var spellcastingSchema=z.object({caster_type:casterTypeEnum,ability:abilityEnum,preparation:z.enum(["known","prepared"]),spell_list:z.string().min(1)});var weaponMasterySchema=z.object({starting_count:z.number().int().nonnegative().optional(),scaling:z.record(z.string(),z.number().int().nonnegative()).optional()});var classTableRowSchema=z.object({prof_bonus:z.number().int().positive(),columns:z.record(z.string(),z.union([z.string(),z.number()])).optional(),feature_ids:z.array(z.string())});var classEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),hit_die:hitDieEnum,primary_abilities:z.array(abilityEnum).nonempty(),standard_array:z.strictObject({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}).optional(),saving_throws:z.array(abilityEnum).length(2),proficiencies:z.object({armor:z.array(armorCategoryEnum),weapons:weaponProficiencySchema,tools:toolProficiencySchema.optional()}),skill_choices:z.object({count:z.number().int().positive(),from:z.array(skillEnum).nonempty()}),choices:z.array(choiceSchema).optional(),starting_equipment:z.array(startingEquipmentEntrySchema),starting_gold:startingGoldSchema.optional(),spellcasting:spellcastingSchema.nullable(),subclass_level:z.number().int().positive(),subclass_feature_name:z.string().min(1),weapon_mastery:weaponMasterySchema.nullable(),epic_boon_level:z.number().int().positive().nullable(),table:z.record(z.string(),classTableRowSchema),features_by_level:z.record(z.string(),z.array(featureSchema)),resources:z.array(resourceSchema),selection_pools:z.array(selectionPoolSchema).optional(),pool_grants:z.array(poolGrantSchema).optional(),tabs:z.array(tabDeclSchema).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),table_col_labels:z.array(z.string().min(1)).optional(),starting_equipment_additional_from_background:z.boolean().optional(),multiclassing:z.unknown().optional(),cantrip_progression:z.array(z.number()).optional(),prepared_spells:z.string().min(1).optional(),prepared_spells_change:z.string().min(1).optional(),prepared_spells_progression:z.array(z.number()).optional(),spells_known_progression:z.array(z.number()).optional(),spells_known_progression_fixed:z.array(z.number()).optional(),spells_known_progression_fixed_allow_lower_level:z.boolean().optional(),spells_known_progression_fixed_by_level:z.record(z.string(),z.record(z.string(),z.number())).optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),image:imageField});export{classEntitySchema};
@@ -0,0 +1 @@
1
+ var ITEM_ACTIONS={"wand-of-fireballs":{cost:"action",range:"150 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-magic-missiles":{cost:"action",range:"120 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-lightning-bolts":{cost:"action",range:"100 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-paralysis":{cost:"action",range:"60 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-fear":{cost:"action",range:"Self",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-binding":{cost:"action",range:"Self",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-secrets":{cost:"action",range:"30 ft.",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"wand-of-web":{cost:"action",range:"60 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"wand-of-wonder":{cost:"action",range:"120 ft.",max_charges:7,recovery:{amount:"1d6+1",reset:"dawn"}},"boots-of-speed":{cost:"bonus-action",range:"Self",max_charges:1,recovery:{amount:"1",reset:"long"}},"boots-of-levitation":{cost:"action",range:"Self"},"boots-of-striding-and-springing":{cost:"free",range:"Self"},"broom-of-flying":{cost:"action",range:"Touch"},"cloak-of-displacement":{cost:"free",range:"Self"},"cloak-of-the-bat":{cost:"action",range:"Self",max_charges:1,recovery:{amount:"1",reset:"long"}},"decanter-of-endless-water":{cost:"action",range:"Touch"},"drum-of-panic":{cost:"action",range:"120 ft.",max_charges:1,recovery:{amount:"1",reset:"long"}},"eyes-of-charming":{cost:"action",range:"30 ft.",max_charges:3,recovery:{amount:"3",reset:"dawn"}},"ring-of-three-wishes":{cost:"action",range:"Self",max_charges:3,recovery:{amount:"0",reset:"special"}},"ring-of-shooting-stars":{cost:"action",range:"60 ft.",max_charges:6,recovery:{amount:"1d6",reset:"dawn"}},"ring-of-the-ram":{cost:"action",range:"60 ft.",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"ring-of-spell-storing":{cost:"action",range:"Self",max_charges:5},"ring-of-animal-influence":{cost:"action",range:"Self",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"ring-of-elemental-command":{cost:"action",range:"Self",max_charges:5,recovery:{amount:"1d4+1",reset:"dawn"}},"ring-of-evasion":{cost:"reaction",range:"Self",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"necklace-of-fireballs":{cost:"action",range:"60 ft.",max_charges:9},"gem-of-brightness":{cost:"action",range:"60 ft.",max_charges:50},"gem-of-seeing":{cost:"action",range:"Self",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"helm-of-teleportation":{cost:"action",range:"Self",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"medallion-of-thoughts":{cost:"action",range:"30 ft.",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"pipes-of-haunting":{cost:"action",range:"30 ft.",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"pipes-of-the-sewers":{cost:"action",range:"Self",max_charges:3,recovery:{amount:"1d3",reset:"dawn"}},"cube-of-force":{cost:"action",range:"Self",max_charges:36,recovery:{amount:"1d20",reset:"dawn"}},"chime-of-opening":{cost:"action",range:"120 ft.",max_charges:10},"sun-blade":{cost:"free",range:"Self"},"potion-of-healing":{cost:"bonus-action",range:"Self",consumed:true},"potion-of-greater-healing":{cost:"bonus-action",range:"Self",consumed:true},"potion-of-superior-healing":{cost:"bonus-action",range:"Self",consumed:true},"potion-of-supreme-healing":{cost:"bonus-action",range:"Self",consumed:true},"alchemists-fire":{cost:"action",range:"20 ft.",consumed:true},"holy-water":{cost:"action",range:"20 ft.",consumed:true},"oil-of-sharpness":{cost:"action",range:"Self",consumed:true},"oil-of-etherealness":{cost:"action",range:"Self",consumed:true},"oil-of-slipperiness":{cost:"action",range:"Self",consumed:true},"dust-of-disappearance":{cost:"action",range:"Self",consumed:true}};function findItemAction(slug){if(slug in ITEM_ACTIONS)return ITEM_ACTIONS[slug];const bare=bareActionKey(slug);return bare===slug?void 0:ITEM_ACTIONS[bare]}function bareActionKey(slug){const p=slug.split("_");return p.length>=3?p.slice(2).join("_"):p[p.length-1]}var READ_ONCE_ITEMS=new Set(["manual-of-bodily-health","manual-of-gainful-exercise","manual-of-quickness-of-action","tome-of-clear-thought","tome-of-leadership-and-influence","tome-of-understanding"]);function isReadOnceItem(slug){return READ_ONCE_ITEMS.has(slug)||READ_ONCE_ITEMS.has(bareActionKey(slug))}var ACTIVATED_SPEED_ITEMS=new Set(["winged-boots","wings-of-flying","boots-of-speed"]);function isActivatedSpeedItem(slug,item){if((item==null?void 0:item.speed_on_use)===true)return true;return ACTIVATED_SPEED_ITEMS.has(slug)||ACTIVATED_SPEED_ITEMS.has(bareActionKey(slug))}function resolveItemAction(slug,entry,itemType,opts){var _a,_b,_c,_d,_e,_f;const curated=(_a=findItemAction(slug))!=null?_a:null;const override=(opts==null?void 0:opts.weaponLike)?void 0:entry.overrides;const overrideCost=override==null?void 0:override.action;const overrideRange=override==null?void 0:override.range;const viewEntity=(_b=opts==null?void 0:opts.view)==null?void 0:_b.entity;const viewAction=viewEntity==null?void 0:viewEntity.action;const viewRange=viewEntity==null?void 0:viewEntity.range;const typeDefault=itemType==="potion"?"bonus-action":itemType==="scroll"?(_c=opts==null?void 0:opts.spellCost)!=null?_c:"action":void 0;const cost=(_e=(_d=overrideCost!=null?overrideCost:viewAction)!=null?_d:curated==null?void 0:curated.cost)!=null?_e:typeDefault;if(!cost)return null;return{cost,range:(_f=overrideRange!=null?overrideRange:viewRange)!=null?_f:curated==null?void 0:curated.range}}export{ITEM_ACTIONS,findItemAction,isReadOnceItem,isActivatedSpeedItem,resolveItemAction};
@@ -0,0 +1 @@
1
+ var seen=new Set;function warnOnce(key,msg){if(seen.has(key))return;seen.add(key);console.warn(msg)}function __resetWarnOnceForTests(){seen.clear()}export{warnOnce,__resetWarnOnceForTests};
@@ -0,0 +1 @@
1
+ import{qualifiedGrantCovers}from"./chunk-T55DELVL.js";import{classifyWeaponRange}from"./chunk-SEOASDO4.js";import{resolveContainment}from"./chunk-4E2GIWJE.js";import{pushDefenseGrant}from"./chunk-GD7WRCNH.js";import{normKey}from"./chunk-VTQ4RWEG.js";import{itemBenefitsActive,itemLabel,itemRowEffects}from"./chunk-J3RP5C7L.js";import{WEAPON_DEFAULT_ACTION_COST,resolveEntryEntity}from"./chunk-PKIMOVQG.js";import{isActivatedSpeedItem}from"./chunk-DVUXUIPV.js";import{readNumericBonus}from"./chunk-NEMX7QGG.js";import{defaultSlotForType,effectiveArmor,effectiveWeapon,isItemEntity,isShieldArmor,isTwoHandedWeapon,slotAcTerms}from"./chunk-4IAMSRHD.js";import{resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bareEntitySlug}from"./chunk-63YJPWTM.js";var MASTERY={cleave:{label:"Cleave",description:"If you hit a creature with a melee attack roll using this weapon, you can make an attack roll with the weapon against a second creature within 5 feet of the first that is also within your reach. On a hit, the second creature takes the weapon's damage, but don't add your ability modifier to that damage unless it is negative. You can make this extra attack only once per turn.",gist:"hit a 2nd creature in reach"},graze:{label:"Graze",description:"If your attack roll with this weapon misses a creature, you can deal damage to that creature equal to the ability modifier you used to make the attack roll. This damage is the same type dealt by the weapon, and the damage can be increased only by increasing the ability modifier.",gist:"on miss: ability-mod damage"},nick:{label:"Nick",description:"When you make the extra attack of the Light property, you can make it as part of the Attack action instead of as a Bonus Action. You can make this extra attack only once per turn.",gist:"extra Light attack (no Bonus Action)"},push:{label:"Push",description:"If you hit a creature with this weapon, you can push the creature up to 10 feet straight away from yourself if it is Large or smaller.",gist:"on hit: pushed 10 ft."},sap:{label:"Sap",description:"If you hit a creature with this weapon, that creature has Disadvantage on its next attack roll before the start of your next turn.",gist:"on hit: target Disadvantage"},slow:{label:"Slow",description:"If you hit a creature with this weapon and deal damage, you can reduce its Speed by 10 feet until the start of your next turn. If the creature is hit more than once by weapons that have this property, the Speed reduction doesn't exceed 10 feet.",gist:"on hit: -10 ft. Speed"},topple:{label:"Topple",description:"If you hit a creature with this weapon, you can force the creature to make a Constitution saving throw (DC 8 plus the ability modifier used to make the attack roll and your Proficiency Bonus). On a failed save, the creature has the Prone condition.",gist:"on fail: Prone"},vex:{label:"Vex",description:"If you hit a creature with this weapon and deal damage, you have Advantage on your next attack roll against that creature before the end of your next turn.",gist:"on hit: you gain Advantage next"}};function masteryGist(slug){var _a;return(_a=MASTERY[slug])==null?void 0:_a.gist}function masteryDerived(slug,abilityMod,proficiencyBonus){if(slug==="topple")return{label:"Save DC",value:8+proficiencyBonus+abilityMod};if(slug==="graze")return{label:"On miss",value:abilityMod};return void 0}var ABILITY_KEYS=["str","dex","con","int","wis","cha"];function isAbilityKey(k){return ABILITY_KEYS.includes(k)}function emptyAppliedBonuses(){return{ability_bonuses:{},ability_statics:{},save_bonus:0,save_terms:[],speed_bonuses:{walk:0,fly:null,swim:0,climb:0},speed_walk_set:0,speed_walk_set_terms:[],speed_terms:[],spell_attack:0,spell_save_dc:0,defenses:{resistances:[],immunities:[],vulnerabilities:[],condition_immunities:[]},informational:[],senses:{darkvision:0,blindsight:0,tremorsense:0,truesight:0}}}function unwrapSlug(item){const m=item.match(/^\[\[(.+)\]\]$/);return m?m[1]:null}function unwrapClassSlug(maybeWiki){if(!maybeWiki)return"";const m=/^\[\[([^\]]+)\]\]$/.exec(maybeWiki);return(m?m[1]:maybeWiki).toLowerCase()}function buildConditionContext(resolved,equippedSlots,registry){var _a,_b;return{derived:{equippedSlots},classList:(_a=resolved.definition.class)!=null?_a:[],race:resolved.definition.race,subclasses:((_b=resolved.definition.class)!=null?_b:[]).map(c=>c.subclass).filter(s=>typeof s==="string"&&s.length>0).map(unwrapClassSlug),registry}}function pushApply(outcome,field,source,pool,onApply){if(!outcome)return;if(outcome.kind==="applied")onApply(outcome.value);else if(outcome.kind==="informational"){pool.push({field,source,value:outcome.value,conditions:outcome.conditions})}}function isOtherSpeedMode(mode){return mode==="fly"||mode==="swim"||mode==="climb"||mode==="burrow"}function computeAppliedBonuses(resolved,_profs,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t;const out=emptyAppliedBonuses();const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const ctx=buildConditionContext(resolved,{},registry);for(let index=0;index<equipment.length;index++){const entry=equipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity){const slug=unwrapSlug(entry.item);if(slug&&entry.equipped&&!((_b=resolved.infusions)==null?void 0:_b.views.has(index)))warnings.push(`Equipped item [[${slug}]] not found in compendium.`);continue}if(!itemBenefitsActive(entry,entity,registry,(_c=resolved.infusions)==null?void 0:_c.views.get(index)))continue;if(entityType!=="item")continue;const item=entity;const label=itemLabel(entry,item);const grant=(bucket,values)=>{for(const v of values!=null?values:[])if(typeof v==="string")pushDefenseGrant(out.defenses[bucket],v,label,void 0,{index,name:label})};grant("resistances",item.resist);grant("immunities",item.immune);grant("vulnerabilities",item.vulnerable);grant("condition_immunities",item.condition_immune);grant("resistances",(_d=entry.overrides)==null?void 0:_d.resist);grant("immunities",(_e=entry.overrides)==null?void 0:_e.immune);grant("vulnerabilities",(_f=entry.overrides)==null?void 0:_f.vulnerable);grant("condition_immunities",(_g=entry.overrides)==null?void 0:_g.condition_immune);const gs=(_h=item.grants)==null?void 0:_h.senses;if(gs){if(typeof gs.darkvision==="number")out.senses.darkvision=Math.max(out.senses.darkvision,gs.darkvision);if(typeof gs.blindsight==="number")out.senses.blindsight=Math.max(out.senses.blindsight,gs.blindsight);if(typeof gs.tremorsense==="number")out.senses.tremorsense=Math.max(out.senses.tremorsense,gs.tremorsense);if(typeof gs.truesight==="number")out.senses.truesight=Math.max(out.senses.truesight,gs.truesight)}const floor=(_j=(_i=item.modify_speed)==null?void 0:_i.static)==null?void 0:_j.walk;if(typeof floor==="number"&&floor>0){out.speed_walk_set=Math.max(out.speed_walk_set,floor);out.speed_walk_set_terms.push({source:label,amount:floor})}const activatedSpeed=isActivatedSpeedItem(String((_k=item.slug)!=null?_k:"")||((_l=unwrapSlug(entry.item))!=null?_l:entry.item),item);const itemSpeed=(mode,kind,amount)=>{if(!activatedSpeed&&isOtherSpeedMode(mode))out.speed_terms.push({mode,kind,source:label,amount})};for(const[mode,n]of Object.entries((_n=(_m=item.modify_speed)==null?void 0:_m.static)!=null?_n:{}))if(typeof n==="number"&&n>0)itemSpeed(mode,"grant",n);for(const[mode,to]of Object.entries((_p=(_o=item.modify_speed)==null?void 0:_o.equal)!=null?_p:{}))if(to==="walk")itemSpeed(mode,"walk",0);const b=item.bonuses;if(!b)continue;const saveSource=(_r=(_q=entry.overrides)==null?void 0:_q.name)!=null?_r:item.name;pushApply(readNumericBonus(b.saving_throws,ctx),"saving_throws",saveSource,out.informational,v=>{out.save_bonus+=v;out.save_terms.push({source:saveSource,amount:v})});pushApply(readNumericBonus(b.spell_attack,ctx),"spell_attack",item.name,out.informational,v=>{out.spell_attack+=v});pushApply(readNumericBonus(b.spell_save_dc,ctx),"spell_save_dc",item.name,out.informational,v=>{out.spell_save_dc+=v});if((_s=b.ability_scores)==null?void 0:_s.bonus){for(const[k,v]of Object.entries(b.ability_scores.bonus)){if(!isAbilityKey(k))continue;pushApply(readNumericBonus(v,ctx),`ability_scores.bonus.${k}`,item.name,out.informational,val=>{var _a2;out.ability_bonuses[k]=((_a2=out.ability_bonuses[k])!=null?_a2:0)+val})}}if((_t=b.ability_scores)==null?void 0:_t.static){for(const[k,n]of Object.entries(b.ability_scores.static)){if(!isAbilityKey(k)||typeof n!=="number")continue;const prev=out.ability_statics[k];if(prev===void 0){out.ability_statics[k]=n}else{if(n!==prev){warnings.push(`Multiple static ${k.toUpperCase()} bonuses on equipped+attuned items; using highest (${Math.max(prev,n)}).`)}out.ability_statics[k]=Math.max(prev,n)}}}if(b.speed){pushApply(readNumericBonus(b.speed.walk,ctx),"speed.walk",item.name,out.informational,v=>{out.speed_bonuses.walk+=v;out.speed_terms.push({mode:"walk",kind:"bonus",source:label,amount:v})});if(b.speed.fly==="walk"){out.speed_bonuses.fly="walk";itemSpeed("fly","walk",0)}else{pushApply(readNumericBonus(b.speed.fly,ctx),"speed.fly",item.name,out.informational,v=>{const cur=out.speed_bonuses.fly;out.speed_bonuses.fly=(typeof cur==="number"?cur:0)+v;itemSpeed("fly","grant",v)})}pushApply(readNumericBonus(b.speed.swim,ctx),"speed.swim",item.name,out.informational,v=>{out.speed_bonuses.swim+=v;itemSpeed("swim","grant",v)});pushApply(readNumericBonus(b.speed.climb,ctx),"speed.climb",item.name,out.informational,v=>{out.speed_bonuses.climb+=v;itemSpeed("climb","grant",v)})}}return out}function assignSlots(resolved,registry,warnings){var _a;const slots={};const eq=(_a=resolved.definition.equipment)!=null?_a:[];for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||!entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(slots[entry.slot])continue;const placed={index:i,entity,entityType,entry};slots[entry.slot]=placed}for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(!entity||!entityType)continue;const defaultSlot=defaultSlotForType(entityType,entity,registry);if(!defaultSlot){if(isItemEntity(entity)&&typeof entity.base_item==="string"&&entity.base_item.length>0){warnings.push(`Magic item "${entity.name}" base_item ${entity.base_item} did not resolve to a base weapon or armor; not slotted (AC/attack not applied).`)}continue}const placed={index:i,entity,entityType,entry};if(defaultSlot==="mainhand"){if(!slots.mainhand)slots.mainhand=placed;else if(!slots.offhand)slots.offhand=placed}else if(!slots[defaultSlot]){slots[defaultSlot]=placed}}return slots}function pickShield(equippedSlots,equipment,registry,infusions){const slotted=equippedSlots.shield;const slottedArmor=effectiveArmor(slotted==null?void 0:slotted.entity,registry);if(slotted&&slottedArmor&&isShieldArmor(slottedArmor)){return{index:slotted.index,shield:slottedArmor,entity:slotted.entity,entry:slotted.entry}}for(let i=0;i<equipment.length;i++){const entry=equipment[i];if(!entry.equipped)continue;const{entity}=resolveEntryEntity(entry,i,registry,infusions);const armor=effectiveArmor(entity,registry);if(armor&&isShieldArmor(armor))return{index:i,shield:armor,entity,entry}}return null}function twoHandedShieldWarnings(equipment,registry,warnings,infusions){const equipped=equipment.flatMap((entry,i)=>{if(!entry.equipped)return[];const{entity}=resolveEntryEntity(entry,i,registry,infusions);return[{entry,entity}]});const isShield=e=>{const armor=effectiveArmor(e.entity,registry);return!!armor&&isShieldArmor(armor)};for(const e of equipped){if(!e.entity||!isTwoHandedWeapon(e.entity,registry))continue;if(!equipped.some(other=>other!==e&&isShield(other)))continue;warnings.push(`${e.entity.name} is two-handed and a Shield is also equipped.`)}}function computeAC(equippedSlots,resolved,mods,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const breakdown=[];const armorSlot=equippedSlots.armor;const armorEntity=(_a=armorSlot==null?void 0:armorSlot.entity)!=null?_a:null;const armor=effectiveArmor(armorEntity,registry);if(isItemEntity(armorEntity)&&typeof armorEntity.base_item==="string"&&!armor){warnings.push(`Magic armor "${armorEntity.name}" base_item ${armorEntity.base_item} did not resolve to a base armor; AC not applied.`)}const acCtx=buildConditionContext(resolved,equippedSlots,registry);const skip=new Set;const slotBonus=slot=>{var _a2,_b2;const view=slot?(_a2=resolved.infusions)==null?void 0:_a2.views.get(slot.index):void 0;if(!slot||!(view==null?void 0:view.entity)||!isItemEntity(view.entity)||!itemBenefitsActive(slot.entry,view.entity,registry,view))return 0;const out=readNumericBonus((_b2=view.entity.bonuses)==null?void 0:_b2.ac,acCtx);if((out==null?void 0:out.kind)!=="applied")return 0;skip.add(slot.index);return out.value};const armorTerms=slotAcTerms(armor,armorSlot==null?void 0:armorSlot.entry);let ac=10;if(armor&&armorTerms.armor!==null){const armorBase=armorTerms.armor+slotBonus(armorSlot);ac=armorBase;breakdown.push({source:(_b=armorEntity==null?void 0:armorEntity.name)!=null?_b:armor.name,amount:armorBase,kind:"armor"});if(armor.ac.add_dex){const dexCap=(_c=armor.ac.dex_max)!=null?_c:Number.POSITIVE_INFINITY;const dexAdd=Math.min(mods.dex,dexCap);ac+=dexAdd;const capped=mods.dex>dexCap;breakdown.push({source:`DEX modifier${capped?" (capped)":""}`,amount:dexAdd,kind:"dex"})}}else{ac=10+mods.dex;breakdown.push({source:"Base",amount:10,kind:"unarmored"});breakdown.push({source:"DEX modifier",amount:mods.dex,kind:"dex"})}const acBonus=armorTerms.override;if(acBonus!==0){ac+=acBonus;breakdown.push({source:`${(_d=armorEntity==null?void 0:armorEntity.name)!=null?_d:"Armor"} (override)`,amount:acBonus,kind:"override"})}const picked=pickShield(equippedSlots,(_e=resolved.definition.equipment)!=null?_e:[],registry,resolved.infusions);if(picked){const{shield,entity:shieldEntity}=picked;const shieldTerms=slotAcTerms(shield,picked.entry);const n=shieldTerms.armor+slotBonus(picked);ac+=n;breakdown.push({source:(_f=shieldEntity==null?void 0:shieldEntity.name)!=null?_f:shield.name,amount:n,kind:"shield"});const shieldAcBonus=shieldTerms.override;if(shieldAcBonus!==0){ac+=shieldAcBonus;breakdown.push({source:`${(_g=shieldEntity==null?void 0:shieldEntity.name)!=null?_g:shield.name} (override)`,amount:shieldAcBonus,kind:"shield"})}}const acInformational=[];const acEquipment=(_h=resolved.definition.equipment)!=null?_h:[];for(let index=0;index<acEquipment.length;index++){if(skip.has(index))continue;const entry=acEquipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity||entityType!=="item")continue;if(!itemBenefitsActive(entry,entity,registry,(_i=resolved.infusions)==null?void 0:_i.views.get(index)))continue;const item=entity;const out=readNumericBonus((_j=item.bonuses)==null?void 0:_j.ac,acCtx);if(!out)continue;if(out.kind==="applied"){ac+=out.value;breakdown.push({source:item.name,amount:out.value,kind:"item"})}else if(out.kind==="informational"){acInformational.push({field:"ac",source:item.name,value:out.value,conditions:out.conditions})}}return{ac,breakdown,informational:acInformational}}function hasProperty(weapon,prop){return weapon.properties.some(p=>p===prop)}function attackAbility(weapon,mods,weaponAbilities){const modes=classifyWeaponRange(weapon);const finesse=hasProperty(weapon,"finesse");if(modes.melee){const scoped=weaponAbilities.find(o2=>{var _a;return(_a=o2.weaponSlugs)==null?void 0:_a.includes(bareEntitySlug(weapon.slug))});const glob=weaponAbilities.find(o2=>!o2.weaponSlugs);const o=scoped!=null?scoped:glob;if(o)return o.ability;if(finesse)return mods.dex>=mods.str?"dex":"str";return"str"}return finesse&&mods.str>mods.dex?"str":"dex"}function pactScopedAbilities(overrides,pactPicked,isPact){if(!overrides.some(o=>o.pactWeapon))return overrides;return overrides.flatMap(o=>{if(!o.pactWeapon)return[o];return!pactPicked||isPact?[{ability:o.ability}]:[]})}function pactWeaponIndexes(resolved,registry){var _a;const pick=resolved.pactWeapon;if(!pick)return null;const out=new Set;const bare=bareEntitySlug(pick);((_a=resolved.definition.equipment)!=null?_a:[]).forEach((entry,i)=>{var _a2;if(typeof entry.item!=="string")return;const slugs=[unwrapSlug(entry.item),registry?(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.slug:void 0];if(slugs.some(s=>!!s&&(s===pick||bareEntitySlug(s)===bare)))out.add(i)});return out.size?out:null}function isWeaponSlugProficient(weapon,weaponSlug,profs){const wp=profs.weapons;if(wp.specific.some(e=>e===weaponSlug||normKey(e)===normKey(weapon.name)))return true;if(wp.specific.some(e=>qualifiedGrantCovers(e,weapon)))return true;const cat=weapon.category;if(typeof cat==="string"){if(/^simple\b/.test(cat)&&wp.categories.includes("simple"))return true;if(/^martial\b/.test(cat)&&wp.categories.includes("martial"))return true;if(wp.categories.includes(cat))return true}return false}function magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions){var _a,_b,_c,_d;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const ovr=(_a=entry.overrides)!=null?_a:{};const entryAttack=typeof ovr.bonus==="number"?ovr.bonus:0;const entryDamage=typeof ovr.damage_bonus==="number"?ovr.damage_bonus:0;const extra=typeof ovr.extra_damage==="string"?ovr.extra_damage:void 0;let itemAttack=0;let itemDamage=0;let sourceName;let itemName;let damageTypeOverride;let propertiesOverride;const informational=[];let itemRiders=[];let critRange;const conditionalCrits=[];if(entity&&isItemEntity(entity)){sourceName=entity.name;itemName=entity.name;damageTypeOverride=typeof entity.damage_type==="string"&&entity.damage_type.length>0?entity.damage_type:void 0;propertiesOverride=Array.isArray(entity.properties)&&entity.properties.length>0?entity.properties:void 0}if(entity&&isItemEntity(entity)&&itemBenefitsActive(entry,entity,registry,infusions==null?void 0:infusions.views.get(index))){const b=entity.bonuses;const atkOut=readNumericBonus(b==null?void 0:b.weapon_attack,ctx);const dmgOut=readNumericBonus(b==null?void 0:b.weapon_damage,ctx);if((atkOut==null?void 0:atkOut.kind)==="applied")itemAttack=atkOut.value;else if((atkOut==null?void 0:atkOut.kind)==="informational")informational.push({field:"weapon_attack",source:entity.name,value:atkOut.value,conditions:atkOut.conditions});if((dmgOut==null?void 0:dmgOut.kind)==="applied")itemDamage=dmgOut.value;else if((dmgOut==null?void 0:dmgOut.kind)==="informational")informational.push({field:"weapon_damage",source:entity.name,value:dmgOut.value,conditions:dmgOut.conditions});itemRiders=Array.isArray(entity.damage_riders)?entity.damage_riders.filter(r=>{var _a2;return((_a2=r.applies_to)!=null?_a2:"weapon")!=="spell"}).map(r=>({amount:r.amount,damage_type:r.damage_type,source:entity.name,...r.condition?{condition:r.condition}:{}})):[];for(const eff of itemRowEffects(entity)){if(eff.kind==="damage-bonus"&&((_b=eff.applies_to)!=null?_b:"weapon")!=="spell"){itemRiders.push({amount:eff.amount,damage_type:eff.damage_type,source:entity.name,...eff.condition?{condition:eff.condition}:{}})}else if(eff.kind==="crit-range"&&((_c=eff.applies_to)!=null?_c:"weapon")!=="spell"){if((_d=eff.condition)==null?void 0:_d.trim())conditionalCrits.push({minRoll:eff.min_roll,condition:eff.condition.trim(),source:entity.name});else critRange=Math.min(critRange!=null?critRange:20,eff.min_roll)}}}return{...critRange!==void 0&&critRange<20?{critRange}:{},...conditionalCrits.length?{conditionalCrits}:{},atk:itemAttack+entryAttack,dmg:itemDamage+entryDamage,extra,sourceName,itemName,damageTypeOverride,propertiesOverride,informational,riders:itemRiders}}function buildAttackRow(args){var _a,_b,_c,_d;const{id,name,weapon,baseDice,ability,mods,proficient,proficiencyBonus,magic,weaponMasteries}=args;const abilityMod=mods[ability];const pb=proficient?proficiencyBonus:0;const toHit=abilityMod+pb+magic.atk;const dmgFlat=abilityMod+magic.dmg;const formatDice=dice=>`${dice}${dmgFlat>=0?"+":""}${dmgFlat}`.replace(/\+0$/,"");const damageDice=formatDice(baseDice);const magicSource=magic.sourceName?`${magic.sourceName} bonus`:"Magic weapon";const toHitBreakdown=[{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficient?proficiencyBonus:0,kind:"ability"},{source:magicSource,amount:magic.atk,kind:"item"}];const damageBreakdown=[{source:"Base damage",amount:0,kind:"ability"},{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:magicSource,amount:magic.dmg,kind:"item"}];const modes=classifyWeaponRange(weapon);const fmtRanged=r=>r.long>r.normal?`${r.normal}/${r.long} ft.`:`${r.normal} ft.`;const range=modes.melee?`${modes.melee.reach} ft.`:modes.ranged?fmtRanged(modes.ranged):void 0;const thrownRange=modes.melee&&modes.ranged?fmtRanged(modes.ranged):void 0;const stringProps=weapon.properties.filter(p=>typeof p==="string");const finalProps=(_a=magic.propertiesOverride)!=null?_a:stringProps;const row={id,name,...range!==void 0?{range}:{},...thrownRange!==void 0?{thrownRange}:{},toHit,damageDice,damageType:(_b=magic.damageTypeOverride)!=null?_b:weapon.damage.type,...(()=>{const riders=[...magic.riders,...magic.extra?[{amount:magic.extra}]:[]];return riders.length?{damageRiders:riders}:{}})(),weaponCategory:modes.melee?"melee":"ranged",properties:finalProps,proficient,breakdown:{toHit:toHitBreakdown,damage:damageBreakdown},informational:args.magic.informational.length>0?args.magic.informational:void 0,slotKey:args.slotKey,subLabel:formatWeaponSubLabel(weapon,finalProps,modes),actionCost:args.actionCost,versatile:args.versatileDice?{damageDice:formatDice(args.versatileDice)}:void 0,...magic.critRange!==void 0?{critRange:magic.critRange}:{},...((_c=magic.conditionalCrits)==null?void 0:_c.length)?{conditionalCrits:magic.conditionalCrits}:{}};const mSlug=(_d=weapon.mastery)==null?void 0:_d[0];if(mSlug&&proficient&&weaponMasteries.includes(bareEntitySlug(weapon.slug))){const g=MASTERY[mSlug];if(g){const derived=masteryDerived(mSlug,mods[ability],proficiencyBonus);row.mastery={slug:mSlug,label:g.label,description:g.description,gist:masteryGist(mSlug),...derived?{derived}:{}}}}return row}function buildUnarmedRow(mods,proficiencyBonus,spec){var _a;const candidates=["str",...(_a=spec==null?void 0:spec.abilities)!=null?_a:[]];let ability="str";for(const ab of candidates)if(mods[ab]>=mods[ability])ability=ab;const abilityMod=mods[ability];const toHit=abilityMod+proficiencyBonus;const flat=`${abilityMod>=0?"+":""}${abilityMod}`.replace(/^\+0$/,"");const damageDice=(spec==null?void 0:spec.dice)?`${spec.dice}${flat}`:String(Math.max(0,1+abilityMod));const label=`${ability.toUpperCase()} modifier`;return{id:"unarmed-strike",name:"Unarmed Strike",unarmed:true,range:"5 ft.",toHit,damageDice,damageType:"bludgeoning",properties:[],proficient:true,breakdown:{toHit:[{source:label,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficiencyBonus,kind:"ability"}],damage:[{source:"Base damage",amount:(spec==null?void 0:spec.dice)?0:1,kind:"ability"},{source:label,amount:abilityMod,kind:"ability"}]},subLabel:"Unarmed",actionCost:"action"}}function buildFeatureAttackRows(resolved,mods,profs,proficiencyBonus,weaponAbilities=[]){var _a,_b,_c;const rows=[];const abilities=weaponAbilities.filter(o=>!o.pactWeapon);for(const rf of(_a=resolved.features)!=null?_a:[]){if(rf.renderSuppressed||rf.buildOnly)continue;const featureId=(_b=rf.feature.id)!=null?_b:rf.feature.name;((_c=rf.feature.attacks)!=null?_c:[]).forEach((a,n)=>{var _a2,_b2,_c2,_d,_e,_f,_g;if(!a.weapon_category||a.type!=="melee"&&a.type!=="ranged"||typeof a.damage!=="string"||!a.damage.trim())return;const long=(_c2=(_a2=a.range)==null?void 0:_a2.long)!=null?_c2:(_b2=a.range)==null?void 0:_b2.normal;const weapon={name:a.name,slug:`feature-attack_${featureId}_${n}`,category:`${a.weapon_category}-${a.type}`,damage:{dice:a.damage.trim(),type:(_d=a.damage_type)!=null?_d:""},properties:((_e=a.properties)!=null?_e:[]).map(p=>p.trim().toLowerCase()),...((_f=a.range)==null?void 0:_f.normal)!==void 0&&long!==void 0?{range:{normal:a.range.normal,long}}:{},...a.mastery?{mastery:[a.mastery.trim().toLowerCase()]}:{}};const proficient=isWeaponSlugProficient(weapon,weapon.slug,profs);const row=buildAttackRow({id:`feature-attack:${rf.source.kind}:${rf.source.slug}:${featureId}:${n}`,name:a.name,weapon,baseDice:weapon.damage.dice,ability:attackAbility(weapon,mods,abilities),mods,proficient,proficiencyBonus,magic:{atk:0,dmg:0,informational:[],riders:[]},actionCost:(_g=a.action)!=null?_g:WEAPON_DEFAULT_ACTION_COST,weaponMasteries:a.mastery?[bareEntitySlug(weapon.slug)]:[]});row.grantedBy=rf.feature.name;rows.push(row)})}return rows}function humanizeWeaponToken(s){return s.replace(/[-_]/g," ").replace(/(^|[\s(])\w/g,c=>c.toUpperCase())}function formatWeaponSubLabel(weapon,properties,modes){const parts=[];if(weapon.category){const cat=modes.melee&&/ranged/.test(weapon.category)?weapon.category.replace("ranged","melee"):weapon.category;parts.push(humanizeWeaponToken(cat))}if(properties.length>0)parts.push(properties.map(humanizeWeaponToken).join(", "));return parts.join(" \xB7 ")}function computeAttacks(equippedSlots,equipment,mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities=[],infusions,pactIndexes=null){var _a,_b;const rows=[];const rowFor=(index,entry,weapon,slotKey,versatileDice)=>{var _a2,_b2,_c,_d,_e;const slugFromEntry=(_a2=unwrapSlug(entry.item))!=null?_a2:weapon.slug;const proficient=isWeaponSlugProficient(weapon,slugFromEntry,profs)||isWeaponSlugProficient(weapon,weapon.slug,profs);if(!proficient){warnings.push(`Character not proficient with ${weapon.name}; proficiency bonus excluded.`)}const isPact=(pactIndexes==null?void 0:pactIndexes.has(index))===true;const ability=attackAbility(weapon,mods,pactScopedAbilities(weaponAbilities,pactIndexes!==null,isPact));const magic=magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions);const ovr=(_b2=entry.overrides)!=null?_b2:{};const row=buildAttackRow({id:`${index}:standard`,name:(_d=(_c=ovr.name)!=null?_c:magic.itemName)!=null?_d:weapon.name,weapon,baseDice:weapon.damage.dice,ability,mods,proficient,proficiencyBonus,magic,slotKey,actionCost:(_e=ovr.action)!=null?_e:WEAPON_DEFAULT_ACTION_COST,versatileDice,weaponMasteries});if(isPact)row.pactWeapon=true;return row};const handedSlots=[{key:"mainhand",placed:equippedSlots.mainhand},{key:"offhand",placed:equippedSlots.offhand}];for(const{key,placed}of handedSlots){if(!placed)continue;const{entity,entry}=placed;if(!entity)continue;const weapon=effectiveWeapon(entity,registry);if(!weapon){if(isItemEntity(entity)&&typeof entity.base_item==="string"&&!resolveBaseItem(entity.base_item,registry)){warnings.push(`Magic weapon ${entity.name} references missing base_item ${entity.base_item}.`)}continue}const versatileDice=key==="mainhand"&&hasProperty(weapon,"versatile")&&typeof weapon.damage.versatile_dice==="string"&&!equippedSlots.offhand?weapon.damage.versatile_dice:void 0;rows.push(rowFor(placed.index,entry,weapon,key,versatileDice))}const handIndex=new Set([(_a=equippedSlots.mainhand)==null?void 0:_a.index,(_b=equippedSlots.offhand)==null?void 0:_b.index]);equipment.forEach((entry,index)=>{if(!entry.equipped||handIndex.has(index))return;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const weapon=effectiveWeapon(entity,registry);if(!weapon)return;rows.push(rowFor(index,entry,weapon))});return rows}function coerceWeight(raw){if(typeof raw==="number"&&Number.isFinite(raw)&&raw>=0)return raw;if(typeof raw==="string"){const n=Number.parseFloat(raw);if(Number.isFinite(n)&&n>=0)return n}return 0}function computeCarriedWeight(resolved,registry){var _a;const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const view=resolveContainment(equipment,registry);const weightlessContainer=equipment.map(entry=>{var _a2,_b,_c;const data=(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.data;return((_c=(_b=data==null?void 0:data.container)==null?void 0:_b.capacity)==null?void 0:_c.weightless)===true});const exempt=i=>{for(let p=view.parentOf[i];p!==null;p=view.parentOf[p])if(weightlessContainer[p])return true;return false};let total=0;equipment.forEach((entry,i)=>{if(exempt(i))return;const found=resolveBaseItem(entry.item,registry);if(!found)return;const entity=found.data;const w=coerceWeight(entity.weight);if(w===0)return;const qty=typeof entry.qty==="number"&&entry.qty>=0?entry.qty:1;total+=w*qty});return total}function computeSlotsAndAttacks(resolved,mods,profs,registry,warnings,proficiencyBonus,weaponAbilities=[],weaponMasteries=[],attunementFloor=0){var _a,_b,_c,_d,_e;const equippedSlots=assignSlots(resolved,registry,warnings);twoHandedShieldWarnings((_a=resolved.definition.equipment)!=null?_a:[],registry,warnings,resolved.infusions);const overrides=(_b=resolved.definition.overrides)!=null?_b:{};const acOut=computeAC(equippedSlots,resolved,mods,registry,warnings);const ctx=buildConditionContext(resolved,equippedSlots,registry);const attacks=computeAttacks(equippedSlots,(_c=resolved.definition.equipment)!=null?_c:[],mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities,resolved.infusions,pactWeaponIndexes(resolved,registry));return{ac:acOut.ac,acBreakdown:acOut.breakdown,acInformational:acOut.informational,attacks,equippedSlots,carriedWeight:computeCarriedWeight(resolved,registry),attunementUsed:((_d=resolved.definition.equipment)!=null?_d:[]).filter(e=>e.attuned).length,attunementLimit:(_e=overrides.attunement_limit)!=null?_e:Math.max(3,attunementFloor)}}export{emptyAppliedBonuses,computeAppliedBonuses,pactWeaponIndexes,isWeaponSlugProficient,buildUnarmedRow,buildFeatureAttackRows,computeSlotsAndAttacks};
@@ -0,0 +1 @@
1
+ import{CONDITION_SLUGS}from"./chunk-KM75CC6Q.js";import{z}from"zod";var conditionSlugEnum=z.enum(CONDITION_SLUGS);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var proficiencyTri=z.enum(["none","proficient","expertise"]);var slotEnum=z.enum(["mainhand","offhand","armor","shield"]);var equipmentEntryOverridesSchema=z.object({name:z.string().optional(),bonus:z.number().int().optional(),damage_bonus:z.number().int().optional(),extra_damage:z.string().optional(),ac_bonus:z.number().int().optional(),action:z.enum(["action","bonus-action","reaction","free","special"]).optional(),range:z.string().optional(),resist:z.array(z.string()).optional(),immune:z.array(z.string()).optional(),vulnerable:z.array(z.string()).optional(),condition_immune:z.array(z.string()).optional(),spell:z.string().optional(),spell_ability:abilityEnum.optional()}).strict();var equipmentEntryStateSchema=z.object({charges:z.object({current:z.number().int().nonnegative(),max:z.number().int().nonnegative()}).optional(),recovery:z.object({amount:z.string(),reset:z.enum(["dawn","short","long","special"])}).optional(),depletion_risk:z.object({trigger:z.string(),roll:z.string(),threshold:z.number().int(),effect:z.string()}).optional()}).strict();var entryRefField=z.preprocess(v=>typeof v==="number"?String(v):typeof v==="string"&&v.length>0?v:void 0,z.string().optional());var infusionMarkerSchema=z.object({kind:z.enum(["infused","created"]),by:z.string().min(1),seq:z.number().int().min(1),choice:z.string().min(1).optional(),charges:z.object({current:z.number().int().nonnegative()}).optional()});var equipmentEntrySchema=z.object({item:z.string().min(1),equipped:z.boolean().optional(),attuned:z.boolean().optional(),qty:z.number().int().positive().optional(),notes:z.string().optional(),slot:slotEnum.nullable().optional(),overrides:equipmentEntryOverridesSchema.optional(),state:equipmentEntryStateSchema.optional(),granted_by:z.string().optional(),id:entryRefField,in:entryRefField,infusion:infusionMarkerSchema.optional()});var characterOverridesShape=z.object({scores:z.partialRecord(abilityEnum,z.number().int()).optional(),saves:z.partialRecord(abilityEnum,z.object({bonus:z.number().int().optional(),proficient:z.boolean().optional()})).optional(),skills:z.partialRecord(skillEnum,z.object({bonus:z.number().int(),proficiency:proficiencyTri.optional()})).optional(),passives:z.object({perception:z.number().int().optional(),investigation:z.number().int().optional(),insight:z.number().int().optional()}).partial().optional(),hp:z.object({max:z.number().int().positive().optional(),rolled:z.number().int().positive().optional(),modifier:z.number().int().optional()}).optional(),ac:z.number().int().optional(),speed:z.number().int().optional(),initiative:z.number().int().optional(),spellcasting_ability_by_class:z.record(z.string(),abilityEnum).optional(),spellcasting_ability:abilityEnum.optional(),spell_slots:z.record(z.coerce.number().int(),z.number().int().nonnegative()).optional(),attunement_limit:z.number().int().nonnegative().optional(),languages:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),tools:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional(),proficiency:z.record(z.string(),proficiencyTri).optional()}).optional(),weapons:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),armor:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),defenses:z.object({resistances:z.object({remove:z.array(z.string()).optional()}).optional(),immunities:z.object({remove:z.array(z.string()).optional()}).optional(),vulnerabilities:z.object({remove:z.array(z.string()).optional()}).optional(),condition_immunities:z.object({remove:z.array(z.string()).optional()}).optional()}).optional()});var characterOverridesSchema=characterOverridesShape.default({});var characterStateSchema=z.object({hp:z.object({current:z.number().int(),max:z.number().int(),temp:z.number().int().nonnegative()}),hit_dice:z.record(z.string(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots:z.record(z.coerce.number().int(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots_pact:z.object({level:z.number().int().nonnegative(),used:z.number().int().nonnegative(),total:z.number().int().nonnegative()}).optional(),concentration:z.string().nullable().default(null),conditions:z.array(conditionSlugEnum).default([]),exhaustion:z.number().int().min(0).max(6).default(0),death_saves:z.object({successes:z.number().int().min(0).max(3),failures:z.number().int().min(0).max(3)}).optional(),inspiration:z.number().int().nonnegative().default(0),currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),feature_uses:z.record(z.string(),z.object({used:z.number().int().nonnegative(),max:z.number().int().nonnegative()})).default({}),feature_rolls:z.record(z.string(),z.array(z.number().int().refine(n=>n!==0&&Math.abs(n)<=999,"banked rolls are nonzero, |value| 1..999"))).default({}),active_buffs:z.array(z.string()).optional(),attuned_items:z.array(z.string()).optional()});var choiceValueSchema=z.union([z.string(),z.array(z.string()),z.record(z.string(),z.unknown())]).catch(ctx=>ctx.value);var classEntrySchema=z.object({name:z.string().min(1),level:z.number().int().min(1).max(20),subclass:z.string().nullable().default(null),choices:z.record(z.coerce.number().int(),z.record(z.string(),choiceValueSchema).catch(ctx=>ctx.value)).default({})});var spellOverrideSchema=z.object({slug:z.string().min(1),overrides:z.record(z.string(),z.unknown()).default({})});var knownSpellObjectSchema=z.object({spell:z.string().min(1),class:z.string().optional(),source:z.enum(["class","feat","item","race","domain"]).optional(),prepared:z.boolean().optional(),always_prepared:z.boolean().optional()}).strict();var knownSpellEntrySchema=z.union([z.string().min(1),knownSpellObjectSchema]);var sheetViewFilterSchema=z.object({show:z.array(z.string().min(1)).optional(),hide:z.array(z.string().min(1)).optional()});var sheetPoolViewSchema=z.object({show:z.enum(["known","granted","not-known"]).optional().catch(void 0),off:z.record(z.string(),z.array(z.string())).optional(),folded:z.array(z.string().min(1)).optional()});var sheetStateSchema=z.object({layout:z.object({saves:z.enum(["section"]).optional().catch(void 0),body:z.enum(["wide"]).optional().catch(void 0)}).optional(),favorites:z.array(z.string().min(1)).optional(),filters:z.object({actions:sheetViewFilterSchema.optional(),passive:sheetViewFilterSchema.optional()}).optional(),pools:z.record(z.string(),sheetPoolViewSchema).optional()});var characterSchema=z.object({name:z.string().min(1),edition:z.enum(["2014","2024"]),builder:z.boolean().optional(),alignment:z.string().optional(),age:z.string().optional(),race:z.string().nullable().default(null),subrace:z.string().nullable().default(null),background:z.string().nullable().default(null),class:z.array(classEntrySchema).default([]),origin_choices:z.record(z.string(),choiceValueSchema).default({}),abilities:z.object({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}),ability_method:z.enum(["standard-array","point-buy","archivist-point-buy","rolled","manual"]),builder_rolls:z.array(z.number().int()).optional(),builder_equipment_mode:z.enum(["starting","gold","empty"]).optional(),skills:z.object({proficient:z.array(skillEnum).default([]),expertise:z.array(skillEnum).default([]),half:z.array(skillEnum).optional()}).default({proficient:[],expertise:[]}),spells:z.object({known:z.array(knownSpellEntrySchema).default([]),overrides:z.array(spellOverrideSchema).default([]),view:z.enum(["by-level","table"]).optional()}).default({known:[],overrides:[]}),equipment:z.array(equipmentEntrySchema).default([]),overrides:characterOverridesSchema,currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),additional_features:z.array(z.string().min(1)).default([]),notes:z.string().optional(),defenses:z.object({resistances:z.array(z.string()).default([]),immunities:z.array(z.string()).default([]),vulnerabilities:z.array(z.string()).default([]),condition_immunities:z.array(z.string()).default([])}).partial().optional(),sheet:sheetStateSchema.optional(),state:characterStateSchema});export{characterOverridesShape,characterSchema};
@@ -0,0 +1 @@
1
+ var IDENTS=new Set(["level","class_level","prof","str_mod","dex_mod","con_mod","int_mod","wis_mod","cha_mod"]);var AT_WILL_MAX=999;var FUNCS=new Set(["ceil","floor","max","min"]);function tokenize(input){input=input.trim();const tokens=[];const re=/\s*('[^']*'|\{[a-z_]+\}|[a-z_]+|\d+|[+\-*/(),])/y;let i=0;while(i<input.length){re.lastIndex=i;const m=re.exec(input);if(!m||m.index!==i)return null;const raw=m[1];i=re.lastIndex;if(/^\d+$/.test(raw))tokens.push({kind:"num",value:parseInt(raw,10)});else if(raw.startsWith("'"))tokens.push({kind:"str",value:raw.slice(1,-1)});else if(raw==="(")tokens.push({kind:"lparen"});else if(raw===")")tokens.push({kind:"rparen"});else if(raw===",")tokens.push({kind:"comma"});else if(raw==="+"||raw==="-"||raw==="*"||raw==="/")tokens.push({kind:"op",op:raw});else{const braced=raw.startsWith("{");const name=braced?raw.slice(1,-1):raw;if(!braced&&FUNCS.has(name))tokens.push({kind:"fn",name});else if(!braced&&name==="column")tokens.push({kind:"col"});else if(IDENTS.has(name))tokens.push({kind:"id",name});else return null}}return tokens.length>0?tokens:null}function evalTokens(tokens,b){let pos=0;const peek=()=>tokens[pos];const factor=()=>{var _a,_b,_c,_d,_e,_f,_g,_h;const t=peek();if(!t)return null;if(t.kind==="num"){pos++;return t.value}if(t.kind==="id"){const val=b[t.name];if(val===void 0)return null;pos++;return val}if(t.kind==="fn"){pos++;if(((_a=peek())==null?void 0:_a.kind)!=="lparen")return null;pos++;const args=[];const first=expr();if(first===null)return null;args.push(first);while(((_b=peek())==null?void 0:_b.kind)==="comma"){pos++;const next=expr();if(next===null)return null;args.push(next)}if(((_c=peek())==null?void 0:_c.kind)!=="rparen")return null;pos++;if(t.name==="ceil"||t.name==="floor"){if(args.length!==1)return null;return t.name==="ceil"?Math.ceil(args[0]):Math.floor(args[0])}if(args.length<2)return null;return t.name==="max"?Math.max(...args):Math.min(...args)}if(t.kind==="col"){pos++;if(((_d=peek())==null?void 0:_d.kind)!=="lparen")return null;pos++;const s=peek();if(!s||s.kind!=="str")return null;pos++;if(((_e=peek())==null?void 0:_e.kind)!=="rparen")return null;pos++;return(_g=(_f=b.columns)==null?void 0:_f[s.value])!=null?_g:0}if(t.kind==="lparen"){pos++;const inner=expr();if(inner===null)return null;if(((_h=peek())==null?void 0:_h.kind)!=="rparen")return null;pos++;return inner}return null};const term=()=>{var _a;let v=factor();if(v===null)return null;while(((_a=peek())==null?void 0:_a.kind)==="op"&&(peek().op==="*"||peek().op==="/")){const op=peek().op;pos++;const r=factor();if(r===null)return null;v=op==="*"?v*r:v/r}return v};const expr=()=>{var _a;let v=term();if(v===null)return null;while(((_a=peek())==null?void 0:_a.kind)==="op"&&(peek().op==="+"||peek().op==="-")){const op=peek().op;pos++;const r=term();if(r===null)return null;v=op==="+"?v+r:v-r}return v};const result=expr();if(result===null||pos!==tokens.length)return null;return result}var ZERO={level:1,class_level:1,prof:2,str_mod:0,dex_mod:0,con_mod:0,int_mod:0,wis_mod:0,cha_mod:0,columns:{}};function isValidMaxFormula(formula){const toks=tokenize(formula);if(!toks)return false;return evalTokens(toks,ZERO)!==null}function evaluateMaxFormula(formula,bindings){const toks=tokenize(formula);if(!toks)throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);const v=evalTokens(toks,bindings);if(v===null)throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);return v}function resolveMaxAt(totalLevel,resource){var _a;let chosen=resource.max_formula;let best=0;for(const step of(_a=resource.scales_at)!=null?_a:[]){if(step.level<=totalLevel&&step.level>best){best=step.level;chosen=step.max}}return chosen}function resolveMaxCountAt(level,resource,bindings){var _a;const tryEval=s=>{const toks=tokenize(s);return toks?evalTokens(toks,bindings):null};let best=0;let chosen=null;for(const step of(_a=resource.scales_at)!=null?_a:[]){if(step.level>level||step.level<=best)continue;const v=tryEval(step.max);if(v===null)continue;best=step.level;chosen=v}if(chosen!==null)return chosen;return tryEval(resource.max_formula)}export{AT_WILL_MAX,isValidMaxFormula,evaluateMaxFormula,resolveMaxAt,resolveMaxCountAt};
@@ -0,0 +1 @@
1
+ import{parseClass}from"./chunk-XPF53K54.js";import yaml from"js-yaml";var classCodec={parse(doc){return parseClass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{classCodec};
@@ -0,0 +1 @@
1
+ import{subclassEntitySchema}from"./chunk-ONCXJMJM.js";import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseSubclass(source){const raw=parseYaml(source,["name","slug","parent_class"]);if(!raw.success)return raw;aliasFeaturesByLevelActionCost(raw.data.features_by_level);const result=subclassEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`subclass schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseSubclass};
@@ -0,0 +1 @@
1
+ var CR_PROFICIENCY={"0":2,"1/8":2,"1/4":2,"1/2":2,"1":2,"2":2,"3":2,"4":2,"5":3,"6":3,"7":3,"8":3,"9":4,"10":4,"11":4,"12":4,"13":5,"14":5,"15":5,"16":5,"17":6,"18":6,"19":6,"20":6,"21":7,"22":7,"23":7,"24":7,"25":8,"26":8,"27":8,"28":8,"29":9,"30":9};var CR_XP={"0":10,"1/8":25,"1/4":50,"1/2":100,"1":200,"2":450,"3":700,"4":1100,"5":1800,"6":2300,"7":2900,"8":3900,"9":5e3,"10":5900,"11":7200,"12":8400,"13":1e4,"14":11500,"15":13e3,"16":15e3,"17":18e3,"18":2e4,"19":22e3,"20":25e3,"21":33e3,"22":41e3,"23":5e4,"24":62e3,"25":75e3,"26":9e4,"27":105e3,"28":12e4,"29":135e3,"30":155e3};var ALL_CR_VALUES=["0","1/8","1/4","1/2","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30"];var SIZE_HIT_DICE={tiny:4,small:6,medium:8,large:10,huge:12,gargantuan:20};var ALL_SIZES=["Tiny","Small","Medium","Large","Huge","Gargantuan"];var SKILL_ABILITY={"acrobatics":"dex","animal handling":"wis","arcana":"int","athletics":"str","deception":"cha","history":"int","insight":"wis","intimidation":"cha","investigation":"int","medicine":"wis","nature":"int","perception":"wis","performance":"cha","persuasion":"cha","religion":"int","sleight of hand":"dex","stealth":"dex","survival":"wis"};var ALL_SKILLS=["Acrobatics","Animal Handling","Arcana","Athletics","Deception","History","Insight","Intimidation","Investigation","Medicine","Nature","Perception","Performance","Persuasion","Religion","Sleight of Hand","Stealth","Survival"];var ABILITY_KEYS=["str","dex","con","int","wis","cha"];var ABILITY_NAMES={str:"STR",dex:"DEX",con:"CON",int:"INT",wis:"WIS",cha:"CHA"};var DAMAGE_TYPES=["Acid","Bludgeoning","Cold","Fire","Force","Lightning","Necrotic","Piercing","Poison","Psychic","Radiant","Slashing","Thunder"];var DAMAGE_NONMAGICAL_VARIANTS=["Bludgeoning, Piercing, and Slashing from Nonmagical Attacks","Bludgeoning, Piercing, and Slashing from Nonmagical Attacks not made with Silvered Weapons","Bludgeoning, Piercing, and Slashing from Nonmagical Attacks not made with Adamantine Weapons"];var CONDITIONS=["Blinded","Charmed","Deafened","Exhaustion","Frightened","Grappled","Incapacitated","Invisible","Paralyzed","Petrified","Poisoned","Prone","Restrained","Stunned","Unconscious"];var STANDARD_SENSES=["Blindsight","Darkvision","Tremorsense","Truesight"];var STANDARD_ACTIONS={"2014":["Attack","Cast a Spell","Dash","Disengage","Dodge","Help","Hide","Ready","Search","Use an Object"],"2024":["Attack","Dash","Disengage","Dodge","Help","Hide","Influence","Magic","Ready","Search","Study","Utilize"]};var ALIGNMENT_ETHICAL=["Lawful","Neutral","Chaotic","Unaligned","Any"];var ALIGNMENT_MORAL=["Good","Neutral","Evil"];var ALL_SECTIONS=["Traits","Actions","Reactions","Bonus Actions","Legendary Actions","Lair Actions","Mythic Actions"];var ABILITY_NAME_TO_KEY={strength:"str",dexterity:"dex",constitution:"con",intelligence:"int",wisdom:"wis",charisma:"cha"};function normalizeAbility(value){var _a;const k=value.trim().toLowerCase();if(ABILITY_KEYS.includes(k))return k;return(_a=ABILITY_NAME_TO_KEY[k])!=null?_a:null}export{CR_PROFICIENCY,CR_XP,ALL_CR_VALUES,SIZE_HIT_DICE,ALL_SIZES,SKILL_ABILITY,ALL_SKILLS,ABILITY_KEYS,ABILITY_NAMES,DAMAGE_TYPES,DAMAGE_NONMAGICAL_VARIANTS,CONDITIONS,STANDARD_SENSES,STANDARD_ACTIONS,ALIGNMENT_ETHICAL,ALIGNMENT_MORAL,ALL_SECTIONS,ABILITY_NAME_TO_KEY,normalizeAbility};
@@ -0,0 +1 @@
1
+ import{ALL_SKILL_SLUGS}from"./chunk-4JEF3CET.js";import{normalizeAbility}from"./chunk-EVT7MGAC.js";var NOUNS=/\b(saving throws?|saves?|ability checks?|checks?|attack rolls?)\b/gi;var QUANTIFIERS=/\b(all|any|other|the next|you make|that you make)\b/gi;var slug=s=>s.toLowerCase().trim().replace(/[^a-z]+/g,"-").replace(/(^-|-$)/g,"");function normalizeRollScope(raw,_roll){if(raw==null)return void 0;const cleaned=raw.replace(NOUNS," ").replace(QUANTIFIERS," ").replace(/\s+/g," ").trim();const parts=cleaned.split(/\s*(?:,|\/|\band\b|\bor\b)\s*/i).map(p=>p.trim()).filter(Boolean);if(parts.length===0||parts.length>3)return void 0;const out=[];for(let p of parts){const m=p.match(/^(?:[a-z]+\s*)?\(\s*([a-z -]+)\s*\)$/i);if(m)p=m[1];const s=slug(p);if(ALL_SKILL_SLUGS.includes(s)){out.push(s);continue}const ab=normalizeAbility(p);if(ab){out.push(ab);continue}return void 0}return out}export{normalizeRollScope};
@@ -0,0 +1 @@
1
+ import{z}from"zod";var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var selectionPoolSchema=z.object({id:z.string().min(1),label:z.string().min(1),source:z.object({entity_type:z.literal("optional-feature"),where:z.object({feature_type:z.string().min(1),available_to:z.literal("self")})}),count:z.object({column:z.string().min(1),label:z.string().min(1).optional()}),replaceable:z.boolean().optional(),active:z.object({column:z.string().min(1),label:z.string().min(1),verb:z.string().min(1),counter_label:z.string().min(1).optional(),create_label:z.string().min(1).optional(),create_verb:z.string().min(1).optional()}).optional(),head_resource:z.string().min(1).optional()});var poolGrantSchema=z.object({pool:z.string().min(1),grants:z.array(z.object({feature:z.string().regex(wikilinkRegex),at_level:z.number().int().positive()}))});var tabDeclSchema=z.object({id:z.string().min(1),label:z.string().min(1),renders:z.object({pool:z.string().min(1),layout:z.enum(["spell-like","blocks","dice-pool","point-pool"]).optional()})});export{selectionPoolSchema,poolGrantSchema,tabDeclSchema};
@@ -0,0 +1 @@
1
+ import{normalizeRollScope}from"./chunk-FOLHTMSC.js";import{toProfSlug}from"./chunk-VTQ4RWEG.js";import{memberSpellTargets}from"./chunk-WAUNLUFQ.js";import{heldPicks}from"./chunk-PKIMOVQG.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{bareEntitySlug}from"./chunk-63YJPWTM.js";import{normalizeAbility}from"./chunk-EVT7MGAC.js";function emptyFeatureEffectTotals(){return{initiative_bonus:0,initiative_terms:[],initiative_amount_terms:[],skill_bonus_terms:[],save_bonus_terms:[],half_proficiency_terms:[],hp_per_level_bonus:0,hp_per_level_terms:[],speed_walk_bonus:0,speed_walk_terms:[],speed_terms:[],ignore_armor_strength:[],speed_walk_set:0,attunement_set:0,ability_bonus:{},senses:{darkvision:0,blindsight:0,tremorsense:0,truesight:0},ac_terms:[],resistances:[],immunities:[],vulnerabilities:[],condition_immunities:[],proficiencies:{skills:[],skillExpertise:[],tools:[],languages:[],saves:[],armor:[],weapons:[]},weaponAbilities:[],rollModifiers:[],saveOutcomes:[],critRange:20,conditionalCrits:[],extraAttack:0,scopedExtraAttacks:[],attackNotes:[],damageBonuses:[],spellDamageBonuses:[]}}function pushUnique(list,value){const key=value.trim().toLowerCase();if(!key)return;if(!list.some(v=>v.trim().toLowerCase()===key))list.push(value.trim())}function pushDefenseGrant(list,value,source,condition,item){var _a;const key=value.trim().toLowerCase();if(!key)return;const existing=list.find(g=>g.value.trim().toLowerCase()===key);if(existing){if(!existing.sources.includes(source))existing.sources.push(source);if(!existing.condition&&condition)existing.condition=condition;if(item)mergeDefenseItems((_a=existing.items)!=null?_a:existing.items=[],[item]);return}list.push({value:value.trim(),sources:[source],...condition?{condition}:{},...item?{items:[item]}:{}})}function mergeDefenseItems(into,from){for(const it of from)if(!into.some(x=>x.index===it.index))into.push({...it})}function ownerItem(owner,label){return(owner==null?void 0:owner.kind)==="item"?{index:owner.index,name:label}:void 0}var NAMED_COLUMN=/^column\(\s*'([^']+)'\s*\)$/;function foldsNow(rf,activeBuffs){if(rf.feature.activatable!==true)return true;const id=rf.feature.id;return!!id&&activeBuffs.has(id)}function assembleEffectFeatures(resolved){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const activeBuffs=new Set((_b=(_a=resolved.state)==null?void 0:_a.active_buffs)!=null?_b:[]);const featureIds=new Set(((_c=resolved.features)!=null?_c:[]).map(f=>f.feature.id).filter(id=>!!id));const aliases=[];for(const pool of(_d=resolved.pools)!=null?_d:[]){for(const entry of[...(_e=pool.selected)!=null?_e:[],...(_f=pool.grants)!=null?_f:[]]){if(activeBuffs.has(entry.slug))continue;const bare=bareEntitySlug(entry.slug);for(const stored of activeBuffs){if(featureIds.has(stored))continue;if(bareEntitySlug(stored)===bare){aliases.push(entry.slug);break}}}}for(const a of aliases)activeBuffs.add(a);const buffFeatures=[];const pushBoon=(item,pool)=>{var _a2,_b2,_c2,_d2,_e2,_f2,_g2,_h2,_i2,_j2,_k;const e=item.entity;if(!e||item.itemBound===true||((_b2=(_a2=e.effects)==null?void 0:_a2.length)!=null?_b2:0)===0)return;const block=(_f2=(_e2=(_d2=(_c2=resolved.classes)==null?void 0:_c2[pool.classIndex])==null?void 0:_d2.choices)==null?void 0:_e2[pool.anchorLevel])!=null?_f2:{};const spellTargets=memberSpellTargets(e,id=>{var _a3;return block[`${pool.id}:${(_a3=item.key)!=null?_a3:item.slug}:${id}`]});buffFeatures.push({feature:{id:item.slug,name:e.name,activatable:(_g2=e.activatable)!=null?_g2:false,effects:e.effects},source:{kind:"class",slug:(_k=(_j2=(_i2=(_h2=resolved.classes)==null?void 0:_h2[pool.classIndex])==null?void 0:_i2.entity)==null?void 0:_j2.slug)!=null?_k:pool.id,level:pool.anchorLevel},...spellTargets?{spellTargets}:{}})};for(const pool of(_g=resolved.pools)!=null?_g:[]){for(const sel of heldPicks(pool))pushBoon(sel,pool);for(const g of(_h=pool.grants)!=null?_h:[])pushBoon(g,pool)}return{features:[...(_i=resolved.features)!=null?_i:[],...buffFeatures,...(_j=resolved.itemFeatures)!=null?_j:[]],activeBuffs}}function foldsOnSelf(eff){if(eff.subject===void 0||eff.subject==="self")return true;warnOnce(eff.subject,`archivist: unrecognised effect subject "${eff.subject}" (only "self" folds)`);return false}function selfEffectsOf(f){var _a;return((_a=f.effects)!=null?_a:[]).filter(foldsOnSelf)}function computeFeatureEffects(features,opts){var _a,_b,_c;const out=emptyFeatureEffectTotals();for(const rf of features){if(!foldsNow(rf,(_a=opts==null?void 0:opts.activeBuffs)!=null?_a:new Set))continue;const level=(_b=opts==null?void 0:opts.levelFor)==null?void 0:_b.call(opts,rf.source);for(const eff of selfEffectsOf(rf.feature)){const effect=columnScaledRider(eff,rf,level,opts==null?void 0:opts.tableDiceFor,opts==null?void 0:opts.tableCellFor);if(effect)applyEffect(out,effect,(_c=rf.feature.name)!=null?_c:"Feature",level,rf.source,rf.spellTargets)}}return out}function classifyProficiencyEffect(eff){if(eff.kind!=="proficiency")return null;const raw=eff.value;const expertise=eff.expertise===true;switch(eff.proficiency_type){case"skill":return{bucket:"skills",value:toProfSlug(raw),raw,expertise};case"tool":return{bucket:"tools",value:toProfSlug(raw),raw,expertise};case"language":return{bucket:"languages",value:toProfSlug(raw),raw,expertise};case"armor":return{bucket:"armor",value:raw.toLowerCase(),raw,expertise};case"weapon":return{bucket:"weapons",value:raw.toLowerCase(),raw,expertise};default:{const ab=normalizeAbility(raw);return ab?{bucket:"saves",value:ab,raw,expertise}:null}}}function collectProficiencyEffectGrants(features,activeBuffs){const out={skills:[],tools:[],languages:[],saves:[],armor:[],weapons:[]};for(const rf of features){if(!foldsNow(rf,activeBuffs))continue;for(const eff of selfEffectsOf(rf.feature)){const c=classifyProficiencyEffect(eff);if(!c)continue;out[c.bucket].push({value:c.value,raw:c.raw,sourceKind:rf.source.kind,sourceSlug:rf.source.slug,...c.expertise?{expertise:true}:{}})}}return out}function scaled(base,key,scalesAt,level){if(level===void 0||!(scalesAt==null?void 0:scalesAt.length))return base;let best=base;let bestLevel=-1;for(const step of scalesAt){if(step.level>level||step.level<=bestLevel)continue;const v=step[key];if(typeof v!=="number")continue;best=v;bestLevel=step.level}return best}function columnScaledRider(eff,rf,level,tableDiceFor,tableCellFor){var _a;if(eff.kind!=="damage-bonus")return eff;const named=NAMED_COLUMN.exec(eff.amount.trim());if(named){const cell=(_a=tableCellFor==null?void 0:tableCellFor(rf.source,named[1]))!=null?_a:null;return cell?{...eff,amount:cell}:null}if(level===void 0||!tableDiceFor)return eff;const src=rf.source;const column=rf.feature.name;if(src.kind!=="class"&&src.kind!=="subclass"||!column)return eff;const atGain=tableDiceFor(src,column,src.level);if(!atGain||atGain.toLowerCase()!==eff.amount.trim().toLowerCase())return eff;const now=tableDiceFor(src,column,level);return now?{...eff,amount:now}:eff}function riderScope(appliesTo){if(appliesTo===void 0||appliesTo==="all"||appliesTo==="spell")return void 0;return Array.isArray(appliesTo)?[...appliesTo]:[appliesTo]}function applyEffect(out,eff,label,level,owner,targets){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o;switch(eff.kind){case"initiative-bonus":if(typeof eff.value==="number"){out.initiative_bonus+=eff.value;out.initiative_terms.push({label,value:eff.value})}else if(typeof eff.amount==="string"){out.initiative_amount_terms.push({label,amount:eff.amount,...owner?{owner}:{}})}break;case"skill-bonus":out.skill_bonus_terms.push({skills:eff.skills.map(toProfSlug),ability:eff.ability,minimum:(_a=eff.minimum)!=null?_a:0,label});break;case"save-bonus":out.save_bonus_terms.push({saves:[...(_b=eff.saves)!=null?_b:[]],ability:eff.ability,minimum:(_c=eff.minimum)!=null?_c:0,...eff.inactive_while?{inactiveWhile:eff.inactive_while}:{},label});break;case"half-proficiency":out.half_proficiency_terms.push({skills:((_d=eff.skills)!=null?_d:[]).map(toProfSlug),round:(_e=eff.round)!=null?_e:"down",label});break;case"hp-per-level-bonus":out.hp_per_level_bonus+=eff.value;out.hp_per_level_terms.push({label,value:eff.value});break;case"speed-bonus":{const gate=eff.inactive_while===void 0?void 0:[].concat(eff.inactive_while);const qualifiers={...eff.condition?{condition:eff.condition}:{},...gate?{inactiveWhile:gate}:{}};if(eff.equal_to==="walk"){out.speed_terms.push({mode:eff.mode,label,value:0,set:false,equalsWalk:true,...qualifiers});break}const value=scaled((_f=eff.value)!=null?_f:0,"value",eff.scales_at,level);out.speed_terms.push({mode:eff.mode,label,value,set:eff.set===true,...qualifiers});if(eff.mode==="walk"&&!gate){if(eff.set)out.speed_walk_set=Math.max(out.speed_walk_set,value);else{out.speed_walk_bonus+=value;out.speed_walk_terms.push({label,value})}}break}case"speed-rule":if(eff.flag==="ignore-armor-strength")out.ignore_armor_strength.push(label);break;case"attunement-limit":{out.attunement_set=Math.max(out.attunement_set,scaled(eff.value,"value",eff.scales_at,level));break}case"sense":out.senses[eff.type]=Math.max(out.senses[eff.type],eff.range);break;case"resistance":pushDefenseGrant(out.resistances,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"immunity":pushDefenseGrant(out.immunities,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"vulnerability":pushDefenseGrant(out.vulnerabilities,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"immune-condition":if(!eff.while)pushDefenseGrant(out.condition_immunities,eff.condition,label,void 0,ownerItem(owner,label));else if((owner==null?void 0:owner.kind)==="item")pushDefenseGrant(out.condition_immunities,eff.condition,label,eff.while,ownerItem(owner,label));break;case"proficiency":{const c=classifyProficiencyEffect(eff);if(!c)break;if(c.bucket==="saves"){pushUnique(out.proficiencies.saves,c.value)}else{pushUnique(out.proficiencies[c.bucket],c.value)}if(c.expertise&&c.bucket==="skills")pushUnique(out.proficiencies.skillExpertise,c.value);break}case"ac-bonus":out.ac_terms.push({value:eff.value,requires_armor:eff.requires_armor===true,label,condition:eff.condition});break;case"weapon-ability":{if(eff.ability!=="spellcasting"){const w=eff.weapons;if(w==="pact-weapon"){out.weaponAbilities.push({ability:eff.ability,pactWeapon:true});break}const weaponSlugs=!w||w==="chosen"?void 0:Array.isArray(w)?w.map(bareEntitySlug):[bareEntitySlug(w)];out.weaponAbilities.push({ability:eff.ability,weaponSlugs})}break}case"roll-modifier":{const rolls=eff.roll==="any"?["ability-check","saving-throw","attack"]:[eff.roll];const scopes=(_g=normalizeRollScope(eff.scope,rolls[0]))!=null?_g:[eff.scope];for(const roll of rolls)for(const scope of scopes)out.rollModifiers.push({mode:eff.mode,roll,scope,condition:eff.condition,label});break}case"save-outcome":out.saveOutcomes.push({ability:eff.ability==="any"?void 0:eff.ability,on_success:eff.on_success,on_failure:eff.on_failure,appliesTo:(_h=eff.applies_to)!=null?_h:void 0,condition:eff.condition,label});break;case"crit-range":if(((_i=eff.applies_to)!=null?_i:"weapon")==="spell")break;if((_j=eff.condition)==null?void 0:_j.trim())out.conditionalCrits.push({minRoll:eff.min_roll,condition:eff.condition.trim(),source:label});else out.critRange=Math.min(out.critRange,eff.min_roll);break;case"extra-attack":{const count=scaled(eff.count,"count",eff.scales_at,level);const scope=riderScope(eff.applies_to);if(scope)out.scopedExtraAttacks.push({count,scope});else out.extraAttack=Math.max(out.extraAttack,count)}break;case"reroll-damage":{const qualifiers=[eff.once_per_die?"once/die":"",(_l=(_k=eff.condition)==null?void 0:_k.trim())!=null?_l:""].filter(q=>q!=="");out.attackNotes.push(`Reroll ${eff.max_reroll}s${qualifiers.length?` (${qualifiers.join(", ")})`:""}`)}break;case"attack-rule":if(eff.flag==="no-ranged-in-melee-disadvantage")out.attackNotes.push("No disadvantage firing in melee");break;case"damage-bonus":if(((_m=eff.applies_to)!=null?_m:"weapon")!=="spell"){const scope=riderScope(eff.applies_to);out.damageBonuses.push({amount:eff.amount,damage_type:eff.damage_type,source:label,...eff.condition?{condition:eff.condition}:{},...scope?{scope}:{},...owner?{owner}:{}})}if(eff.applies_to==="spell"||eff.applies_to==="all"){const spellScope=(_n=eff.spell_scope)!=null?_n:eff.applies_to==="all"?{}:void 0;out.spellDamageBonuses.push({amount:eff.amount,damage_type:eff.damage_type,source:label,...eff.condition?{condition:eff.condition}:{},...owner?{owner}:{},...targets?{targets}:{},...spellScope?{scope:spellScope}:{}})}break;case"ability-score-increase":if(eff.abilities==="chosen")break;for(const ab of eff.abilities)out.ability_bonus[ab]=((_o=out.ability_bonus[ab])!=null?_o:0)+eff.amount;break;default:break}}export{emptyFeatureEffectTotals,pushDefenseGrant,mergeDefenseItems,foldsNow,assembleEffectFeatures,foldsOnSelf,selfEffectsOf,computeFeatureEffects,classifyProficiencyEffect,collectProficiencyEffectGrants};
@@ -0,0 +1 @@
1
+ import{parseOptionalFeature}from"./chunk-SFK57JAA.js";import yaml from"js-yaml";var optionalFeatureCodec={parse(doc){return parseOptionalFeature(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{optionalFeatureCodec};
@@ -0,0 +1 @@
1
+ import{actionCostEnum,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var categoryEnum=z.enum(["origin","general","fighting-style","epic-boon"]);var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("level"),min:z.number().int().positive()}),z.object({kind:z.literal("spellcaster")}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["armor","weapon","tool","skill","saving-throw"]),value:z.string().min(1)}),z.object({kind:z.literal("race"),slug:z.string().min(1)}),z.object({kind:z.literal("class"),slug:z.string().min(1)}),z.object({kind:z.literal("feat"),slug:z.string().min(1)}),z.object({kind:z.literal("campaign"),slug:z.string().min(1)}),z.object({kind:z.literal("exclusive-feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("feature"),slug:z.string().min(1)}),z.object({kind:z.literal("other"),detail:z.string().min(1)}),z.object({kind:z.literal("feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("background"),slug:z.string().min(1)})]);var featEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),category:categoryEnum,description:z.string(),prerequisites:z.array(prerequisiteSchema),benefits:z.array(z.string()),effects:z.array(featureEffectSchema),grants_asi:z.object({amount:z.number().int().positive(),pool:z.array(abilityEnum).optional()}).nullable(),repeatable:z.boolean(),choices:z.array(choiceSchema),rendering_hint:z.string().optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),trait_tags:z.unknown().optional(),optionalfeature_progression:z.array(progressionSchema).optional(),resources:z.array(resourceSchema).optional(),action_cost:actionCostEnum.optional(),image:imageField});export{featEntitySchema};
@@ -0,0 +1 @@
1
+ import{featureObjectSchema}from"./chunk-NIWLD33X.js";import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var str=z.string();var num=z.number();var bool=z.boolean();var strArr=z.array(z.string());var damageQualifierSchema=z.object({get types(){return z.array(z.union([str,damageQualifierSchema])).optional()},note:str.optional(),pre_note:str.optional(),cond:bool.optional(),special:str.optional()});var qualifierList=z.array(z.union([str,damageQualifierSchema])).optional();var speedValue=z.union([num,z.object({number:num,condition:str.optional()})]);var monsterSpeedSchema=z.object({walk:speedValue.optional(),fly:speedValue.optional(),swim:speedValue.optional(),climb:speedValue.optional(),burrow:speedValue.optional(),hover:bool.optional(),can_hover:bool.optional(),alternate:z.record(str,z.array(z.object({number:num,condition:str.optional()}))).optional(),choose:z.object({from:strArr,amount:num,note:str.optional()}).optional()});var monsterTypeSchema=z.object({type:z.union([str,z.object({choose:strArr})]),tags:z.array(z.union([str,z.object({tag:str,prefix:str,prefix_hidden:bool.optional()})])).optional(),sidekick_type:str.optional(),sidekick_tags:strArr.optional(),swarm_size:str.optional(),sidekick_hidden:bool.optional()});var monsterCRSchema=z.object({cr:str,lair:str.optional(),coven:str.optional(),xp:num.optional(),xp_lair:num.optional()});var monsterACSchema=z.object({ac:num.optional(),from:strArr.optional(),condition:str.optional(),braces:bool.optional(),special:str.optional()});var monsterHPSchema=z.object({average:num.optional(),formula:str.optional(),special:str.optional()});var alignmentEntrySchema=z.object({alignment:strArr.optional(),chance:num.optional(),note:str.optional(),special:str.optional()});var spellEntry=z.union([str,z.object({entry:str,hidden:bool.optional()})]);var spellList=z.array(spellEntry);var spellLevel=z.object({slots:num.optional(),lower:num.optional(),spells:strArr});var monsterSpellcastingSchema=z.object({name:str.optional(),type:str.optional(),headerEntries:strArr.optional(),footerEntries:strArr.optional(),ability:str.optional(),displayAs:str.optional(),hidden:strArr.optional(),spells:z.record(str,spellLevel).optional(),will:spellList.optional(),ritual:spellList.optional(),daily:z.record(str,spellList).optional(),rest:z.record(str,spellList).optional(),restLong:z.record(str,spellList).optional(),recharge:z.record(str,spellList).optional(),legendary:z.record(str,spellList).optional(),charges:z.record(str,spellList).optional(),chargesItem:str.optional()});var initiativeSchema=z.union([num,z.object({proficiency:num.optional(),advantage_mode:str.optional()})]);var gearEntrySchema=z.union([str,z.object({item:str,quantity:num.optional(),displayName:str.optional()})]);var featureArr=z.array(featureObjectSchema).optional();var monsterSchema=z.object({name:str.min(1),size:z.union([str,strArr]).optional(),size_note:str.optional(),type:z.union([str,monsterTypeSchema]).optional(),subtype:str.optional(),alignment:z.union([str,z.array(z.union([str,alignmentEntrySchema]))]).optional(),alignment_prefix:str.optional(),cr:z.union([str,monsterCRSchema]).optional(),pb_note:str.optional(),ac:z.array(monsterACSchema).optional(),hp:monsterHPSchema.optional(),speed:monsterSpeedSchema.optional(),abilities:z.object({str:num,dex:num,con:num,int:num,wis:num,cha:num}).optional(),saves:z.record(str,num).optional(),skills:z.record(str,num).optional(),skills_other:z.array(z.unknown()).optional(),senses:strArr.nullable().optional(),passive_perception:num.optional(),languages:strArr.nullable().optional(),damage_vulnerabilities:qualifierList,damage_resistances:qualifierList,damage_immunities:qualifierList,condition_immunities:qualifierList,traits:featureArr,actions:featureArr,bonus_actions:featureArr,reactions:featureArr,legendary_actions:featureArr,mythic:featureArr,mythic_header:strArr.optional(),legendary_action_uses:num.optional(),legendary_resistance:num.optional(),legendary_actions_lair_count:num.optional(),section_headers:z.array(z.object({section:str,header:strArr})).optional(),action_note:str.optional(),reaction_note:str.optional(),spellcasting:z.array(monsterSpellcastingSchema).optional(),legendary_group:z.object({name:str,source:str}).optional(),lair_actions:z.array(z.unknown()).optional(),regional_actions:z.array(z.unknown()).optional(),variant:z.array(z.unknown()).optional(),initiative:initiativeSchema.optional(),gear:z.array(gearEntrySchema).optional(),is_named_creature:bool.optional(),is_npc:bool.optional(),familiar:bool.optional(),short_name:z.union([str,bool]).optional(),level:num.optional(),dragon_age:str.optional(),dragon_casting_color:str.optional(),environment:strArr.optional(),treasure:strArr.optional(),attached_items:strArr.optional(),group:strArr.nullable().optional(),summoned_by_spell:str.optional(),summoned_by_spell_level:num.optional(),summoned_by_class:str.optional(),trait_tags:strArr.optional(),action_tags:strArr.optional(),sense_tags:strArr.optional(),language_tags:strArr.optional(),spellcasting_tags:strArr.optional(),misc_tags:strArr.optional(),damage_tags:strArr.optional(),damage_tags_spell:strArr.optional(),damage_tags_legendary:strArr.optional(),condition_inflict:strArr.optional(),condition_inflict_spell:strArr.optional(),condition_inflict_legendary:strArr.optional(),saving_throw_forced:strArr.optional(),saving_throw_forced_spell:strArr.optional(),saving_throw_forced_legendary:strArr.optional(),has_fluff:bool.optional(),has_fluff_images:bool.optional(),has_token:bool.optional(),token_credit:str.optional(),token_custom:bool.optional(),sound_clip:z.object({type:str,path:str}).optional(),alt_art:z.array(z.object({name:str,source:str.optional(),page:num.optional()})).optional(),image:imageField,thumbnail:imageField,rendering_hint:str.optional(),columns:num.optional(),slug:str.optional(),edition:str.optional(),source:str.optional(),raw:z.record(str,z.unknown()).optional()});var MONSTER_KNOWN_KEYS=new Set(Object.keys(monsterSchema.shape));export{damageQualifierSchema,monsterSpeedSchema,monsterTypeSchema,monsterCRSchema,monsterACSchema,monsterHPSchema,alignmentEntrySchema,monsterSpellcastingSchema,initiativeSchema,gearEntrySchema,monsterSchema,MONSTER_KNOWN_KEYS};
@@ -0,0 +1 @@
1
+ import{z}from"zod";var imageField=z.union([z.string().min(1),z.array(z.string().min(1))]).optional();var additionalSpellsEntrySchema=z.object({name:z.string().min(1).optional(),ability:z.union([z.string().min(1),z.object({choose:z.array(z.string().min(1))})]).optional(),known:z.unknown().optional(),innate:z.unknown().optional(),prepared:z.unknown().optional(),expanded:z.unknown().optional(),resourceName:z.string().min(1).optional()});var progressionSchema=z.object({name:z.string().min(1),progression:z.union([z.record(z.string(),z.number()),z.array(z.number())]),feature_type:z.array(z.string().min(1)).optional(),featureType:z.array(z.string().min(1)).optional(),category:z.array(z.string().min(1)).optional(),required:z.record(z.string(),z.array(z.string())).optional()});export{imageField,additionalSpellsEntrySchema,progressionSchema};
@@ -0,0 +1 @@
1
+ import{z}from"zod";var spellInputSchema=z.object({name:z.string().describe("Spell name"),level:z.number().min(0).max(9).describe("Spell level (0 for cantrips)"),school:z.enum(["abjuration","conjuration","divination","enchantment","evocation","illusion","necromancy","transmutation"]),casting_time:z.string().describe('e.g., "1 action", "1 bonus action"'),range:z.string().describe('e.g., "Touch", "120 feet", "Self"'),components:z.string().describe('e.g., "V, S", "V, S, M (diamond worth 100 gp)"'),duration:z.string().describe('e.g., "Instantaneous", "Concentration, up to 1 minute"'),description:z.array(z.string()).describe("Spell description paragraphs. Use inline formula tags for damage and save DCs: `damage:DICE` for damage rolls (e.g. `damage:8d6`), `dc:ABILITY` for save DCs (e.g. `dc:WIS`). Valid abilities: STR, DEX, CON, INT, WIS, CHA."),at_higher_levels:z.array(z.string()).optional(),classes:z.array(z.string()).optional(),ritual:z.boolean().optional(),concentration:z.boolean().optional()});export{spellInputSchema};
@@ -0,0 +1 @@
1
+ import{isConsumedOnUse,itemSpellUse,resolveEntryEntity}from"./chunk-PKIMOVQG.js";import{isReadOnceItem}from"./chunk-DVUXUIPV.js";import{requiresAttunement}from"./chunk-YGH7S5ZF.js";import{resolveEntityForEntry}from"./chunk-4IAMSRHD.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";var linkSlug=item=>{var _a,_b;return(_b=(_a=/^\[\[(.+?)(\|.*)?\]\]$/.exec(item.trim()))==null?void 0:_a[1])!=null?_b:null};function itemBenefitsActive(entry,entity,registry,view){var _a;if(!entry.equipped)return false;if(requiresAttunement(entity)&&entry.attuned!==true)return false;if(isConsumedOnUse(entry,registry,view))return false;const slug=entity==null?void 0:entity.slug;if(isReadOnceItem(typeof slug==="string"&&slug?slug:(_a=linkSlug(entry.item))!=null?_a:entry.item))return false;return true}function itemSpellCastable(entry,registry,view){const use=itemSpellUse(entry,registry,view);if(!use||!registry)return false;if(use.kind==="consume")return true;const entity=view?view.entity:resolveEntityForEntry(entry.item,registry).entity;return itemBenefitsActive(entry,entity,registry,view)}function itemLabel(entry,entity){var _a,_b,_c,_d;return(_d=(_a=entry.overrides)==null?void 0:_a.name)!=null?_d:String((_c=(_b=entity==null?void 0:entity.name)!=null?_b:linkSlug(entry.item))!=null?_c:entry.item)}var ITEM_ROW_KINDS=new Set(["damage-bonus","crit-range","reroll-damage","extra-attack","weapon-ability","attack-rule"]);function readItemEffects(entity){const raw=entity==null?void 0:entity.effects;const effects=[];const invalid=[];if(!Array.isArray(raw))return{effects,invalid};for(const e of raw){const parsed=featureEffectSchema.safeParse(e);if(parsed.success)effects.push(parsed.data);else invalid.push(typeof(e==null?void 0:e.kind)==="string"?String(e.kind):"unknown")}return{effects,invalid}}function itemRowEffects(entity){return readItemEffects(entity).effects.filter(e=>ITEM_ROW_KINDS.has(e.kind))}function buildItemFeatures(equipment,registry,infusions,warnings){const out=[];if(typeof registry.getBySlug!=="function")return out;equipment.forEach((entry,index)=>{var _a,_b;if(!entry.equipped)return;const{entity,entityType}=resolveEntryEntity(entry,index,registry,infusions);if(!entity||entityType!=="item")return;if(!itemBenefitsActive(entry,entity,registry,infusions==null?void 0:infusions.views.get(index)))return;const{effects,invalid}=readItemEffects(entity);const name=itemLabel(entry,entity);if(invalid.length){warnings.push(`${name}: the sheet cannot read ${invalid.length===1?"this effect":"these effects"} (${invalid.join(", ")}); ignored.`)}const own=effects.filter(e=>!ITEM_ROW_KINDS.has(e.kind));if(own.length===0)return;const slug=String((_b=(_a=entity.slug)!=null?_a:linkSlug(entry.item))!=null?_b:entry.item);out.push({feature:{id:`item:${index}:${slug}`,name,activatable:false,effects:own},source:{kind:"item",slug,index}})});return out}export{itemBenefitsActive,itemSpellCastable,itemLabel,ITEM_ROW_KINDS,readItemEffects,itemRowEffects,buildItemFeatures};
@@ -0,0 +1 @@
1
+ import{equipmentCategoryKey,isCategoryGrant}from"./chunk-2EOGK6R6.js";import{TOOL_CATEGORIES,backgroundToolPicks,categoryWords,classToolPicks,expandToolPool,toolCategoriesOf}from"./chunk-RQZCGXUZ.js";import{assembleEffectFeatures,classifyProficiencyEffect,collectProficiencyEffectGrants,foldsNow,selfEffectsOf}from"./chunk-GD7WRCNH.js";import{ALL_LANGUAGES,ALL_SKILL_SLUGS,ALL_TOOLS}from"./chunk-4JEF3CET.js";import{humanizeProficiency,proficiencyLabel,toProfSlug}from"./chunk-VTQ4RWEG.js";import{buildItemFeatures}from"./chunk-J3RP5C7L.js";import{classPactWeaponPick,featOfSite,featPickSites,isTargetChoice,memberChoices,pactWeaponPick,poolMemberSites,poolMemberSitesOf,raceFeatSites}from"./chunk-WAUNLUFQ.js";import{collectAdditionalSpells}from"./chunk-CEHL7PPC.js";import{resolveFeatureResources,resolveResourceIndex}from"./chunk-KEXSF3CH.js";import{attributeUnclassedSpell,effectiveSpellcastingAbility,normalizeKnownSpell,resolveSpellcasting}from"./chunk-PFQPP77Q.js";import{convertibleLegacyAsi,flattenAsiOrFeat,resolveLegacyAsiFeat}from"./chunk-QVWT67WA.js";import{bindFeatureConsumers,buildInfusionContext,resolveAllPools,resolveOptionRows,storedSpellNumbers,strandedPicks,withoutStrandedSites}from"./chunk-PKIMOVQG.js";import{countColumnsFor,readTableColumn}from"./chunk-CSTAQQGX.js";import{recognizeDecision}from"./chunk-3LWOVRLA.js";import{isItemEntity,resolveEntityForEntry}from"./chunk-4IAMSRHD.js";import{FEATURE_TYPE_FOR_CATEGORY,featCategoryOf,featProgressionCategory}from"./chunk-3QQOATV3.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bucketOf}from"./chunk-QMEKQTUT.js";import{isValidMaxFormula}from"./chunk-EAARMPCW.js";import{bareEntitySlug,wikilinkTailSlug}from"./chunk-63YJPWTM.js";import{mirrorSpellShapes}from"./chunk-4KVVAENP.js";import{ABILITY_KEYS}from"./chunk-EVT7MGAC.js";import{withResolvedActionCost}from"./chunk-S5UCI27C.js";var UNKNOWN_SOURCE="Unknown";var UNKNOWN_GRANT_SOURCE=UNKNOWN_SOURCE;function grantSourceName(resolved,kind,slug){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r;switch(kind){case"class":return(_d=(_c=(_b=(_a=resolved.classes)==null?void 0:_a.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===slug}))==null?void 0:_b.entity)==null?void 0:_c.name)!=null?_d:UNKNOWN_SOURCE;case"subclass":return(_h=(_g=(_f=(_e=resolved.classes)==null?void 0:_e.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===slug}))==null?void 0:_f.subclass)==null?void 0:_g.name)!=null?_h:UNKNOWN_SOURCE;case"race":return(_j=(_i=resolved.race)==null?void 0:_i.name)!=null?_j:UNKNOWN_SOURCE;case"background":return(_l=(_k=resolved.background)==null?void 0:_k.name)!=null?_l:UNKNOWN_SOURCE;case"feat":return(_o=(_n=(_m=resolved.feats)==null?void 0:_m.find(f=>f.slug===slug))==null?void 0:_n.name)!=null?_o:UNKNOWN_SOURCE;case"item":return(_r=(_q=(_p=resolved.itemFeatures)==null?void 0:_p.find(f=>f.source.slug===slug))==null?void 0:_q.feature.name)!=null?_r:UNKNOWN_SOURCE;default:return UNKNOWN_SOURCE}}function collectProficiencyGrants(resolved){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t,_u,_v,_w,_x;const classArmor=[];const classWeaponFixed=[];const classWeaponCategories=[];const classToolFixed=[];for(const c of resolved.classes){const prof=(_a=c.entity)==null?void 0:_a.proficiencies;if(!prof)continue;const source=(_c=(_b=c.entity)==null?void 0:_b.name)!=null?_c:UNKNOWN_SOURCE;for(const a of(_d=prof.armor)!=null?_d:[])classArmor.push({value:a,source});for(const w of(_f=(_e=prof.weapons)==null?void 0:_e.fixed)!=null?_f:[])classWeaponFixed.push({value:w,source});for(const w of(_h=(_g=prof.weapons)==null?void 0:_g.categories)!=null?_h:[])classWeaponCategories.push({value:w,source});for(const t of(_j=(_i=prof.tools)==null?void 0:_i.fixed)!=null?_j:[])classToolFixed.push({value:t,source});for(const t of classToolPicks(c.entity).grants)classToolFixed.push({value:t,source})}const raceSource=(_l=(_k=resolved.race)==null?void 0:_k.name)!=null?_l:UNKNOWN_SOURCE;const raceLangFixed=((_o=(_n=(_m=resolved.race)==null?void 0:_m.languages)==null?void 0:_n.fixed)!=null?_o:[]).map(l=>({value:l,source:raceSource}));const bgToolFixed=[];const bgLangFixed=[];const bg=resolved.background;if(bg){const source=(_p=bg.name)!=null?_p:UNKNOWN_SOURCE;for(const entry of(_q=bg.tool_proficiencies)!=null?_q:[]){if(entry.kind==="fixed"){for(const t of entry.items)bgToolFixed.push({value:t,source})}}for(const t of backgroundToolPicks(bg).grants)bgToolFixed.push({value:t,source});for(const entry of(_r=bg.language_proficiencies)!=null?_r:[]){if(entry.kind==="fixed"){for(const l of entry.languages)bgLangFixed.push({value:l,source})}}}const featArmor=[];const featWeapons=[];const featTools=[];const featLanguages=[];for(const f of(_s=resolved.feats)!=null?_s:[]){const featView=f;const grants=featView.proficiencies;if(!grants)continue;const source=(_t=f.name)!=null?_t:UNKNOWN_SOURCE;for(const a of(_u=grants.armor)!=null?_u:[])featArmor.push({value:a,source});for(const w of(_v=grants.weapons)!=null?_v:[])featWeapons.push({value:w,source});for(const t of(_w=grants.tools)!=null?_w:[])featTools.push({value:t,source});for(const l of(_x=grants.languages)!=null?_x:[])featLanguages.push({value:l,source})}const{features:effectFeatures,activeBuffs}=assembleEffectFeatures(resolved);const fx=collectProficiencyEffectGrants(effectFeatures,activeBuffs);const nameFor=(kind,slug)=>grantSourceName(resolved,kind,slug);const toGrants=(list,useRaw)=>list.map(g=>({value:useRaw?g.raw:g.value,source:nameFor(g.sourceKind,g.sourceSlug),...g.expertise?{expertise:true}:{}}));const effectArmor=toGrants(fx.armor,true);const effectWeapons=toGrants(fx.weapons,true);const effectTools=toGrants(fx.tools,false);const effectLanguages=toGrants(fx.languages,false);return{classArmor,classWeaponFixed,classWeaponCategories,classToolFixed,raceLangFixed,bgToolFixed,bgLangFixed,featArmor,featWeapons,featTools,featLanguages,effectArmor,effectWeapons,effectTools,effectLanguages}}function inventoryOptions(resolved,registry,entityType){var _a,_b,_c,_d;const out=[];const seen=new Set;const find=ref=>{var _a2,_b2;const withSlug=registry;if(typeof withSlug.getBySlug==="function")return resolveBaseItem(ref,withSlug);const bare=ref.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].trim();return(_b2=(_a2=registry.getByTypeAndSlug(entityType,bare))!=null?_a2:registry.getByTypeAndSlug("item",bare))!=null?_b2:null};for(const entry of(_b=(_a=resolved.definition)==null?void 0:_a.equipment)!=null?_b:[]){if(typeof entry.item!=="string")continue;const e=find(entry.item);if(!e||seen.has(e.slug))continue;const value=e.slug;const base=e.entityType===entityType?e:typeof e.data.base_item==="string"?find(e.data.base_item):null;if(!base||base.entityType!==entityType)continue;seen.add(value);const name=(_d=(_c=entry.overrides)==null?void 0:_c.name)!=null?_d:e.name;out.push({value,label:name,entity:e})}return out}var warnedDegradedEquipment=new Set;var warnedAmbiguousBare=new Set;var foldedTypeMemo=new Map;function foldedType(s){let v=foldedTypeMemo.get(s);if(v===void 0){v=categoryWords(s).join(" ");foldedTypeMemo.set(s,v)}return v}function matchesFilter(e,where,ownerBare){var _a,_b,_c,_d,_e,_f;const d=e.data;if(where.feature_type&&d.feature_type!==where.feature_type)return false;if(where.category&&featCategoryOf((_a=d.category)!=null?_a:"")!==featCategoryOf(where.category))return false;if(where.list&&!((_b=d.classes)!=null?_b:[]).includes(where.list))return false;if(where.level!==void 0&&((_c=d.level)!=null?_c:0)!==where.level)return false;if(where.edition&&d.edition!==where.edition)return false;if(where.ritual&&d.ritual!==true)return false;if(where.weapon_category){const cat=((_d=d.category)!=null?_d:"").toLowerCase();if(!cat.startsWith(`${where.weapon_category}-`)&&cat!==where.weapon_category)return false}if(where.armor_category){if(((_e=d.category)!=null?_e:"").toLowerCase()!==where.armor_category)return false}if(where.item_type){const t=foldedType(typeof d.type==="string"?d.type:"");if(!t||!where.item_type.some(x=>foldedType(x)===t))return false}if(where.mundane){const r=typeof d.rarity==="string"?d.rarity.trim().toLowerCase():"";if(r&&r!=="none"&&r!=="mundane")return false}if(where.parent_class==="self"){if(!d.parent_class||wikilinkTailSlug(d.parent_class)!==ownerBare)return false}if(where.available_to==="self"){const list=(_f=d.available_to)!=null?_f:[];if(!list.some(l=>wikilinkTailSlug(l)===ownerBare))return false}return true}var __matchesFilterForTest=matchesFilter;function parseEquipmentCategory(category){const tools=toolCategoriesOf(category);if(tools)return{kind:"tool",tools};const words=categoryWords(category).filter(w=>w!=="any");const has=w=>words.includes(w);const only=allowed=>words.every(w=>allowed.includes(w));if(words.length===1&&has("shield"))return{kind:"shield"};if(has("armor")&&only(["armor","light","medium","heavy"])&&words.length<=2){const armor=["light","medium","heavy"].find(k=>has(k));return{kind:"armor",armor}}if(has("weapon")&&only(["weapon","simple","martial","melee","ranged"])){const klass=["simple","martial"].filter(k=>has(k));const range=["melee","ranged"].filter(k=>has(k));if(klass.length===1&&range.length<=1&&words.length===2+range.length){return{kind:"weapon",weapon:klass[0],range:range[0]}}}return void 0}function categoryToEntitySelect(category,id){const spec=parseEquipmentCategory(category);const pick={kind:"select-entity",id,count:1};switch(spec==null?void 0:spec.kind){case"shield":return{...pick,label:"Choose a shield",entity_type:"armor",where:{armor_category:"shield"}};case"armor":return spec.armor?{...pick,label:`Choose ${spec.armor} armor`,entity_type:"armor",where:{armor_category:spec.armor}}:{...pick,label:"Choose armor",entity_type:"armor"};case"weapon":return{...pick,label:`Choose a ${spec.weapon}${spec.range?` ${spec.range}`:""} weapon`,entity_type:"weapon",where:{weapon_category:spec.weapon}};case"tool":return{...pick,label:`Choose ${spec.tools.map(t=>TOOL_CATEGORIES[t].label).join(" or ")}`,entity_type:"item",where:{item_type:spec.tools.map(t=>TOOL_CATEGORIES[t].itemType),mundane:true}};default:warnOnce(`equipment-category:${category}`,`Archivist: starting-equipment category "${category}" is not a known item category; its pick offers no options.`);return{...pick,label:`Choose a ${category.replace(/[-_]+/g," ")}`,entity_type:"item",from:[]}}}var __categoryToEntitySelectForTest=categoryToEntitySelect;function equipmentDecisions(entries,ownerSlug){const out=[];let degraded=false;(entries!=null?entries:[]).forEach((eq,i)=>{var _a;if((eq==null?void 0:eq.kind)!=="choice")return;const options=(_a=eq.options)!=null?_a:[];out.push({kind:"select-inline",id:`equipment-${i}`,label:"Starting Equipment",count:1,options:options.map((opt,j)=>{var _a2;const label=typeof opt==="string"?opt:(_a2=opt==null?void 0:opt.label)!=null?_a2:"";const wellFormed=!!opt&&typeof opt==="object"&&Array.isArray(opt.grants);if(!wellFormed)degraded=true;const grants=wellFormed?opt.grants:[];return{value:`option-${j}`,label,choices:grants.flatMap((g,k)=>isCategoryGrant(g)?[categoryToEntitySelect(g.category,equipmentCategoryKey(i,j,k))]:[])}})})});if(degraded&&!warnedDegradedEquipment.has(ownerSlug)){warnedDegradedEquipment.add(ownerSlug);console.warn(`[archivist] Starting equipment for "${ownerSlug}" is in an outdated/unstructured format; its nested picks and seeding are skipped. Re-sync the compendium (delete _compendium.md and reload) to fix.`)}return out}function authoredProficiencyPool(choice){if(!choice.from)return void 0;return choice.domain==="tool"?expandToolPool(choice.from):choice.from}function enumerateOptions(choice,ctx,ownerBare){var _a,_b;switch(choice.kind){case"select-inline":return choice.options.map(o=>({value:o.value,label:o.label,description:o.description}));case"select-entity":{if(choice.from){let byBare;const bareIndex=()=>{var _a2,_b2,_c,_d;if(byBare)return byBare;const built=new Map;const pool=ctx.registry.search("",choice.entity_type,Number.POSITIVE_INFINITY).slice().sort((a,b)=>a.name.localeCompare(b.name)||a.slug.localeCompare(b.slug));const seed=e=>{const bare=bareEntitySlug(e.slug);if(built.has(bare)){if(!warnedAmbiguousBare.has(bare)){warnedAmbiguousBare.add(bare);console.warn(`Archivist: bare slug "${bare}" matches multiple ${choice.entity_type} entities; using "${built.get(bare).slug}"`)}return}built.set(bare,e)};for(const e of pool)if((_b2=(_a2=ctx.isEntityVisible)==null?void 0:_a2.call(ctx,e))!=null?_b2:true)seed(e);for(const e of pool)if(!((_d=(_c=ctx.isEntityVisible)==null?void 0:_c.call(ctx,e))!=null?_d:true))seed(e);byBare=built;return built};return choice.from.map(slug=>{var _a2;const e=(_a2=ctx.registry.getByTypeAndSlug(choice.entity_type,slug))!=null?_a2:bareIndex().get(slug);return e?{value:e.slug,label:e.name,entity:e}:{value:slug,label:slug,missing:true}})}const all=ctx.registry.search("",choice.entity_type,Number.POSITIVE_INFINITY);const filtered=choice.where?all.filter(e=>matchesFilter(e,choice.where,ownerBare)):all;return filtered.map(e=>({value:e.slug,label:e.name,entity:e}))}case"select-proficiency":{const pool=(_a=authoredProficiencyPool(choice))!=null?_a:choice.domain==="skill"?[...ALL_SKILL_SLUGS]:choice.domain==="language"?[...ALL_LANGUAGES]:choice.domain==="tool"?[...ALL_TOOLS]:[];return pool.map(v=>({value:v,label:humanizeProficiency(v)}))}case"ability-points":{const pool=(_b=choice.pool)!=null?_b:["str","dex","con","int","wis","cha"];return pool.map(a=>({value:a,label:a.toUpperCase()}))}}}function selectionCount(choice,selected){if(selected===void 0)return 0;if(choice.kind==="ability-points"){if(typeof selected!=="object"||Array.isArray(selected))return 0;return Object.values(selected).reduce((s,v)=>s+(typeof v==="number"?v:0),0)}if(Array.isArray(selected))return selected.length;return typeof selected==="string"&&selected.length>0?1:0}function requiredCount(choice){var _a;if(choice.kind==="ability-points")return choice.points;if(choice.kind==="select-proficiency")return choice.count;return(_a=choice.count)!=null?_a:1}function capAtCount(choice,value){const folds=choice.kind==="select-proficiency"||choice.kind==="select-entity"&&choice.entity_type==="weapon"&&choice.id!=="weapon-mastery"&&!isTargetChoice(choice);if(!folds||!Array.isArray(value))return value;const n=requiredCount(choice);return value.length>n?value.slice(0,n):value}function statusOf(choice,selected,satisfied){const n=selectionCount(choice,selected);const need=requiredCount(choice);if(satisfied)return"resolved";if(n===0)return"unresolved";return n>=need?"resolved":"partial"}var matchPool=(v,pool)=>pool.find(p=>toProfSlug(p)===toProfSlug(v));var canonicalizeSelection=(value,pool)=>{var _a;if(typeof value==="string")return(_a=matchPool(value,pool))!=null?_a:value;if(Array.isArray(value))return value.map(v=>{var _a2;return(_a2=matchPool(v,pool))!=null?_a2:v});return value};function resolveEntityRef(ctx,entityType,value){if(typeof value!=="string"||value.length===0)return void 0;const raw=value.replace(/^\[\[/,"").replace(/\]\]$/,"");const direct=ctx.registry.getByTypeAndSlug(entityType,raw);if(direct)return direct;for(const e of ctx.registry.search("",entityType,Number.POSITIVE_INFINITY)){if(e.slug===raw||bareEntitySlug(e.slug)===raw)return e}return void 0}function buildItem(inputChoice,source,level,featureName,readValue,ctx,ownerBare,effective,opts){var _a,_b,_c,_d,_e;const choice=flattenAsiOrFeat(inputChoice);const keyPrefix=(_a=opts==null?void 0:opts.keyPrefix)!=null?_a:"";const expandFeatChildren=(_b=opts==null?void 0:opts.expandFeatChildren)!=null?_b:true;const key=keyPrefix+choice.id;const raw=capAtCount(choice,readValue(key));const preExclusionOptions=choice.kind==="select-entity"&&((_c=choice.where)==null?void 0:_c.inventory)===true?effective.inventory(choice.entity_type):enumerateOptions(choice,ctx,ownerBare);let options=preExclusionOptions;const mine=new Set((Array.isArray(raw)?raw:raw===void 0?[]:[raw]).map(v=>toProfSlug(String(v))));if(choice.kind==="select-proficiency"&&choice.domain==="skill"&&choice.from_proficient){options=options.filter(o=>effective.skill.has(toProfSlug(o.value))||mine.has(toProfSlug(o.value)))}const postInclusionOptions=options;const excludes=choice.kind==="select-proficiency"&&(choice.domain==="language"||choice.domain==="tool"||choice.domain==="skill"&&choice.expertise===true);if(excludes&&choice.kind==="select-proficiency"){const known=choice.domain==="skill"?effective.skillExpertise:effective[choice.domain];options=options.filter(o=>!known.has(toProfSlug(o.value))||mine.has(toProfSlug(o.value)))}const satisfied=excludes&&postInclusionOptions.length>0&&options.length===0;const selected=choice.kind==="select-proficiency"?canonicalizeSelection(raw,options.map(o=>o.value)):raw;const item={key,source,level,featureName,choice,description:opts==null?void 0:opts.description,options,selected,status:statusOf(choice,selected,satisfied),satisfied};if(choice.kind==="select-inline"&&typeof selected==="string"){const branch=choice.options.find(o=>o.value===selected);if((_d=branch==null?void 0:branch.choices)==null?void 0:_d.length){item.children=branch.choices.map(c=>buildItem(c,source,level,featureName,readValue,ctx,ownerBare,effective,{keyPrefix,expandFeatChildren}));if(item.status==="resolved"&&item.children.some(c=>c.status!=="resolved")){item.status="partial"}}}if(choice.kind==="select-entity"&&choice.entity_type==="feat"&&expandFeatChildren&&typeof selected==="string"){const entity=resolveEntityRef(ctx,"feat",selected);const rawChoices=(_e=entity==null?void 0:entity.data)==null?void 0:_e.choices;const featChoices=Array.isArray(rawChoices)?rawChoices:[];if(featChoices.length){const childPrefix=`${keyPrefix}feat:`;item.children=featChoices.map(c=>buildItem(c,source,level,featureName,readValue,ctx,ownerBare,effective,{keyPrefix:childPrefix,expandFeatChildren:false}));if(item.status==="resolved"&&item.children.some(c=>c.status!=="resolved")){item.status="partial"}}}return item}function buildSubclassItem(choice,source,level,featureName,c,ctx,ownerBare,description){const selected=c.subclass?c.subclass.slug:void 0;return{key:"subclass",source,level,featureName,description,choice,options:enumerateOptions(choice,ctx,ownerBare),selected,status:selected?"resolved":"unresolved",satisfied:false}}function visitProficiencyChoices(resolved,visit){var _a,_b,_c,_d,_e;const walk=(choices,read,owner)=>{for(const ch of choices!=null?choices:[]){visit(ch,read(ch.id),owner);if(ch.kind==="select-inline"){const sel=read(ch.id);const branch=typeof sel==="string"?ch.options.find(o=>o.value===sel):void 0;if(branch==null?void 0:branch.choices)walk(branch.choices,read,owner)}}};const oc=(_a=resolved.definition.origin_choices)!=null?_a:{};const originRead=ns=>id=>oc[`${ns}:${id}`];const stripRef=ref=>ref.replace(/^\[\[/,"").replace(/\]\]$/,"");const featBySlug=new Map(((_b=resolved.feats)!=null?_b:[]).map(f=>[f.slug,f]));const memberSites=poolMemberSitesOf(resolved);const featSites=featPickSites(resolved.classes,memberSites,ci=>{var _a2,_b2,_c2,_d2;return(_d2=(_c2=(_b2=(_a2=resolved.classes)==null?void 0:_a2[ci])==null?void 0:_b2.entity)==null?void 0:_c2.slug)!=null?_d2:null});resolved.classes.forEach((c,i)=>{var _a2,_b2,_c2,_d2,_e2,_f,_g,_h;if(!c.entity)return;const entity=c.entity;const readAt=lvl=>id=>{var _a3;return(_a3=c.choices[lvl])==null?void 0:_a3[id]};const className=entity.name;if(i===0&&((_b2=(_a2=entity.skill_choices)==null?void 0:_a2.from)==null?void 0:_b2.length)){visit({kind:"select-proficiency",id:"skills",count:entity.skill_choices.count,domain:"skill",from:entity.skill_choices.from},readAt(1)("skills"),className)}if(i===0)walk(entity.choices,readAt(1),className);if(i===0)walk(classToolPicks(entity).decisions,readAt(1),className);for(const rf of resolved.features){if(rf.source.kind!=="class"&&rf.source.kind!=="subclass")continue;const belongs=rf.source.kind==="class"?rf.source.slug===entity.slug:c.subclass!=null&&rf.source.slug===c.subclass.slug;if(!belongs)continue;const featureOwner=rf.source.kind==="subclass"?(_d2=(_c2=c.subclass)==null?void 0:_c2.name)!=null?_d2:className:className;for(const copy of(_e2=rf.foldedFrom)!=null?_e2:[])walk(copy.choices,readAt(copy.level),featureOwner);walk(rf.feature.choices,readAt(rf.source.level),featureOwner)}for(const site of featSites){if(site.classIndex!==i)continue;const feat=(_g=featBySlug.get(stripRef(site.slug)))!=null?_g:featOfSite(site,(_f=resolved.feats)!=null?_f:[]);if(!feat)continue;walk(feat.choices,site.read,feat.name)}for(const site of memberSites)if(site.classIndex===i)walk(site.choices,site.read,(_h=site.member.name)!=null?_h:className)});if(resolved.race){const raceName=resolved.race.name;walk(resolved.race.choices,originRead("race"),raceName);for(const t of(_c=resolved.race.traits)!=null?_c:[])walk(t.choices,originRead("race"),raceName)}if(resolved.background){const bgName=resolved.background.name;walk(resolved.background.choices,originRead("background"),bgName);walk(backgroundToolPicks(resolved.background).decisions,originRead("background"),bgName);if(resolved.background.feature){const feature=resolved.background.feature;walk(feature.choices,originRead("background"),bgName)}}if(resolved.originFeatSlug){const of=featBySlug.get(resolved.originFeatSlug);if(of)walk(of.choices,id=>oc[`background:feat:${id}`],of.name)}for(const site of raceFeatSites(resolved.race,oc)){const rf=(_e=featBySlug.get(stripRef(site.slug)))!=null?_e:((_d=resolved.feats)!=null?_d:[]).find(f=>bareEntitySlug(f.slug)===bareEntitySlug(site.slug));if(rf)walk(rf.choices,site.read,rf.name)}}var filterToPool=(vals,pool)=>pool?vals.map(v=>matchPool(v,pool)).filter(v=>!!v):vals;function collectChosenProficiencies(resolved){const out={skills:[],expertise:[],languages:[],tools:[],weapons:[],saves:[]};forEachChosenProficiency(resolved,(bucket,value)=>{const list=out[bucket];if(!list.includes(value))list.push(value)});return out}function forEachChosenProficiency(resolved,on){const isAbility=v=>ABILITY_KEYS.includes(v);visitProficiencyChoices(resolved,(choice,stored,owner)=>{const selected=capAtCount(choice,stored);const vals=Array.isArray(selected)?selected:typeof selected==="string"?[selected]:[];if(choice.kind==="select-entity"&&choice.entity_type==="weapon"){if(choice.id==="weapon-mastery"||isTargetChoice(choice))return;for(const v of vals){const bare=bareEntitySlug(String(v));if(bare)on("weapons",bare,owner)}return}if(choice.kind!=="select-proficiency")return;const valid=filterToPool(vals,authoredProficiencyPool(choice));if(choice.domain==="save"){for(const v of valid)if(isAbility(v))on("saves",v,owner);return}const bucket=choice.domain==="skill"?choice.expertise?"expertise":"skills":choice.domain==="language"?"languages":choice.domain==="tool"?"tools":null;if(bucket)for(const v of valid)on(bucket,v,owner)})}function collectRuleProficiencySources(resolved){var _a,_b,_c,_d;const out={skills:{},expertise:{},saves:{}};const add=(rec,key,source)=>{var _a2;const list=(_a2=rec[key])!=null?_a2:rec[key]=[];if(!list.includes(source))list.push(source)};const firstClass=(_b=(_a=resolved.classes)==null?void 0:_a[0])==null?void 0:_b.entity;if(firstClass)for(const ab of(_c=firstClass.saving_throws)!=null?_c:[])add(out.saves,ab,firstClass.name);const bg=resolved.background;if(bg)for(const sk of(_d=bg.skill_proficiencies)!=null?_d:[])add(out.skills,sk,bg.name);forEachChosenProficiency(resolved,(bucket,value,owner)=>{if(bucket==="skills"||bucket==="expertise"||bucket==="saves")add(out[bucket],value,owner)});const{features,activeBuffs}=assembleEffectFeatures(resolved);for(const rf of features){if(!foldsNow(rf,activeBuffs))continue;for(const eff of selfEffectsOf(rf.feature)){const c=classifyProficiencyEffect(eff);if(!c||c.bucket!=="skills"&&c.bucket!=="saves")continue;const named=grantSourceName(resolved,rf.source.kind,rf.source.slug);const source=named===UNKNOWN_GRANT_SOURCE?rf.feature.name:named;if(c.bucket==="saves")add(out.saves,c.value,source);else add(c.expertise?out.expertise:out.skills,c.value,source)}}return out}function proficiencyEntryFor(raw,vocab,origin,sources,expertise){const hit=matchPool(raw,vocab);const value=hit?toProfSlug(hit):raw;const label=hit?humanizeProficiency(value):origin==="custom"?raw:proficiencyLabel(raw);return{value,label,sources,origin,...expertise?{expertise:true}:{}}}function computeEffectiveProficiencies(resolved){const c=composeLanguageToolProficiencies(resolved);return{languages:c.languages.kept,tools:c.tools.kept}}function computeSuppressedProficiencies(resolved){const c=composeLanguageToolProficiencies(resolved);return{languages:c.languages.suppressed,tools:c.tools.suppressed}}function composeLanguageToolProficiencies(resolved){const grants=collectProficiencyGrants(resolved);const chosen=collectChosenProficiencies(resolved);const build=domain=>{var _a,_b,_c,_d,_e,_f,_g,_h;const vocab=domain==="languages"?ALL_LANGUAGES:ALL_TOOLS;const ov=(_b=(_a=resolved.definition)==null?void 0:_a.overrides)==null?void 0:_b[domain];const adds=(_c=ov==null?void 0:ov.add)!=null?_c:[];const removes=(_d=ov==null?void 0:ov.remove)!=null?_d:[];const byValue=new Map;const push=(raw,origin,source,expertise)=>{const probe=proficiencyEntryFor(raw,vocab,origin,source?[source]:[],expertise);const existing=byValue.get(probe.value);if(!existing){byValue.set(probe.value,probe);return}if(source&&!existing.sources.includes(source))existing.sources.push(source);if(expertise)existing.expertise=true;const rank={grant:0,pick:1,manual:2,custom:3};if(rank[origin]<rank[existing.origin])existing.origin=origin};const grantBuckets=domain==="languages"?[grants.raceLangFixed,grants.bgLangFixed,grants.featLanguages,grants.effectLanguages]:[grants.classToolFixed,grants.bgToolFixed,grants.featTools,grants.effectTools];for(const b of grantBuckets)for(const g of b)push(g.value,"grant",g.source,g.expertise);for(const v of domain==="languages"?chosen.languages:chosen.tools)push(v,"pick");for(const v of adds)push(v,matchPool(v,vocab)?"manual":"custom");const triSuppressed=new Set;if(domain==="tools"){const tri=(_h=(_g=(_f=(_e=resolved.definition)==null?void 0:_e.overrides)==null?void 0:_f.tools)==null?void 0:_g.proficiency)!=null?_h:{};for(const[tool,state]of Object.entries(tri)){const key=toProfSlug(tool);if(state==="none"){triSuppressed.add(key);continue}let entry=[...byValue.values()].find(e=>toProfSlug(e.value)===key);if(!entry){push(tool,matchPool(tool,vocab)?"manual":"custom");entry=[...byValue.values()].find(e=>toProfSlug(e.value)===key)}if(!entry)continue;if(state==="expertise")entry.expertise=true;else delete entry.expertise}}const suppressed=new Set([...removes.map(r=>toProfSlug(r)),...triSuppressed]);const byLabel=(a,b)=>a.label<b.label?-1:a.label>b.label?1:0;const kept=[...byValue.values()].filter(e=>!suppressed.has(toProfSlug(e.value))).sort(byLabel);return{kept,suppressed:[...byValue.values()].filter(e=>suppressed.has(toProfSlug(e.value))).sort(byLabel)}};return{languages:build("languages"),tools:build("tools")}}function collectChosenAbilityPoints(resolved){var _a,_b,_c;const oc=(_a=resolved.definition.origin_choices)!=null?_a:{};const out={race:{},background:{}};const fold=(ns,choices)=>{var _a2;for(const ch of choices!=null?choices:[]){if(ch.kind!=="ability-points")continue;const raw=oc[`${ns}:${ch.id}`];if(!raw||typeof raw!=="object"||Array.isArray(raw))continue;let left=ch.points;for(const ab of ABILITY_KEYS){if(ch.pool&&!ch.pool.includes(ab))continue;const v=raw[ab];if(typeof v!=="number"||v<=0||left<=0)continue;const take=Math.min(v,ch.max_per,left);out[ns][ab]=((_a2=out[ns][ab])!=null?_a2:0)+take;left-=take}}};const race=resolved.race;if(race){fold("race",race.choices);for(const t of(_b=race.traits)!=null?_b:[])fold("race",t.choices)}const bg=resolved.background;if(bg){fold("background",bg.choices);fold("background",(_c=bg.feature)==null?void 0:_c.choices)}return out}function buildDecisionLedger(resolved,ctx){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n;const eff=computeEffectiveProficiencies(resolved);const chosen=collectChosenProficiencies(resolved);const{features,activeBuffs}=assembleEffectFeatures(resolved);const effectGrants=collectProficiencyEffectGrants(features,activeBuffs);const effective={language:new Set(eff.languages.map(e=>toProfSlug(e.value))),tool:new Set(eff.tools.map(e=>toProfSlug(e.value))),skill:new Set([...(_c=(_b=(_a=resolved.definition)==null?void 0:_a.skills)==null?void 0:_b.proficient)!=null?_c:[],...(_e=(_d=resolved.background)==null?void 0:_d.skill_proficiencies)!=null?_e:[],...chosen.skills,...effectGrants.skills.map(g=>g.value)].map(toProfSlug)),skillExpertise:new Set([...(_h=(_g=(_f=resolved.definition)==null?void 0:_f.skills)==null?void 0:_g.expertise)!=null?_h:[],...chosen.expertise,...effectGrants.skills.filter(g=>g.expertise).map(g=>g.value)].map(toProfSlug)),inventory:entityType=>inventoryOptions(resolved,ctx.registry,entityType)};const classes=[];resolved.classes.forEach((c,classIndex)=>{var _a2,_b2,_c2,_d2,_e2,_f2,_g2,_h2,_i2,_j2,_k2,_l2,_m2,_n2,_o;if(!c.entity)return;const entity=c.entity;const ownerBare=bareEntitySlug(entity.slug);const byLevel=new Map;const push=(lvl,item)=>{var _a3;const arr=(_a3=byLevel.get(lvl))!=null?_a3:[];arr.push(item);byLevel.set(lvl,arr)};const readAt=lvl=>id=>{var _a3;return(_a3=c.choices[lvl])==null?void 0:_a3[id]};let legacyAsiFeat;const legacyAsiReader=(choice,lvl)=>{const alloc=convertibleLegacyAsi(c.choices[lvl]);if(!alloc)return null;const flat=flattenAsiOrFeat(choice);if(flat.kind!=="select-entity"||flat.entity_type!=="feat"||flat.from||flat.where)return null;if(legacyAsiFeat===void 0)legacyAsiFeat=resolveLegacyAsiFeat(ctx.registry,entity);const asi=legacyAsiFeat;if(!asi)return null;const raw=readAt(lvl);const childKey=`feat:${asi.childId}`;return id=>id==="feat"?asi.slug:id===childKey?alloc:raw(id)};const featProgressions=[...(_a2=entity.feat_progression)!=null?_a2:[],...(_c2=(_b2=c.subclass)==null?void 0:_b2.feat_progression)!=null?_c2:[]];const suppressedFeatureTypes=new Set;for(const decl of[...(_d2=entity.selection_pools)!=null?_d2:[],...(_f2=(_e2=c.subclass)==null?void 0:_e2.selection_pools)!=null?_f2:[]]){const rp=resolved.pools.find(p=>p.classIndex===classIndex&&p.id===decl.id);if(rp&&rp.count>=1)suppressedFeatureTypes.add(decl.source.where.feature_type)}for(const entry of featProgressions){const category=featProgressionCategory(entry.category);const ft=category?FEATURE_TYPE_FOR_CATEGORY[category]:void 0;if(ft)suppressedFeatureTypes.add(ft)}if(classIndex===0&&((_h2=(_g2=entity.skill_choices)==null?void 0:_g2.from)==null?void 0:_h2.length)){const skillChoice={kind:"select-proficiency",id:"skills",label:"Skill Proficiencies",count:entity.skill_choices.count,domain:"skill",from:entity.skill_choices.from};push(1,buildItem(skillChoice,{kind:"class",slug:entity.slug,level:1},1,"Proficiencies",readAt(1),ctx,ownerBare,effective))}if(classIndex===0){for(const ch of[...(_i2=entity.choices)!=null?_i2:[],...classToolPicks(entity).decisions]){push(1,buildItem(ch,{kind:"class",slug:entity.slug,level:1},1,"Proficiencies",readAt(1),ctx,ownerBare,effective))}}if(classIndex===0){for(const ch of equipmentDecisions(entity.starting_equipment,entity.slug)){push(1,buildItem(ch,{kind:"class",slug:entity.slug,level:1},1,"Starting Equipment",readAt(1),ctx,ownerBare,effective))}}let sawAuthoredSubclass=false;const staged=[];const authoredRank=(kind,level,feature)=>{var _a3,_b3,_c3;const at=(_c3=(_b3=(_a3=kind==="class"?entity:c.subclass)==null?void 0:_a3.features_by_level)==null?void 0:_b3[level])!=null?_c3:[];const index=at.findIndex(f=>feature.id?f.id===feature.id:f.name===feature.name);return(kind==="class"?0:1)*1e6+(index<0?999999:index)};for(const rf of resolved.features){const src=rf.source;if(src.kind!=="class"&&src.kind!=="subclass")continue;const belongs=src.kind==="class"?src.slug===entity.slug:c.subclass!=null&&src.slug===c.subclass.slug;if(!belongs)continue;const lvl=src.level;const stage=(atLvl,item)=>{staged.push({level:atLvl,item,rank:authoredRank(src.kind,atLvl,rf.feature),seq:staged.length})};const emitChoices=(list,atLvl,name,description)=>{var _a3,_b3;for(const ch of list){if(ch.kind==="select-entity"&&ch.entity_type==="subclass"){sawAuthoredSubclass=true;stage(atLvl,buildSubclassItem(ch,src,atLvl,name,c,ctx,ownerBare,description));continue}let emitted=ch;if(ch.kind==="select-entity"){const columns=countColumnsFor(ch.id);const fromTable=columns?readTableColumn(entity.table,c.level,columns):null;if(fromTable!=null)emitted={...ch,count:Math.max((_a3=ch.count)!=null?_a3:1,fromTable)}}stage(atLvl,buildItem(emitted,src,atLvl,name,(_b3=legacyAsiReader(emitted,atLvl))!=null?_b3:readAt(atLvl),ctx,ownerBare,effective,{description}))}};const informationalItem=(atLvl,name,description)=>{var _a3,_b3;return{key:(_a3=rf.feature.id)!=null?_a3:name,source:src,level:atLvl,featureName:name,description,choice:{kind:"select-inline",id:(_b3=rf.feature.id)!=null?_b3:name,options:[{value:"_",label:"_"}]},options:[],selected:void 0,status:"informational",satisfied:false}};const emitCopy=copy=>{let list=copy.choices;if(!(list==null?void 0:list.length)){const recognized=recognizeDecision({id:rf.feature.id,name:copy.name,description:copy.description});if(recognized==="informational"){stage(copy.level,informationalItem(copy.level,copy.name,copy.prose));return}list=recognized!=null?recognized:void 0;if(list==null?void 0:list.length){list=list.filter(ch=>{var _a3;if(ch.kind!=="select-entity")return true;const ft=(_a3=ch.where)==null?void 0:_a3.feature_type;return!(ft!==void 0&&suppressedFeatureTypes.has(ft))})}}if(!(list==null?void 0:list.length)){if(copy.prose)stage(copy.level,informationalItem(copy.level,copy.name,copy.prose));return}emitChoices(list,copy.level,copy.name,copy.description)};for(const copy of(_j2=rf.foldedFrom)!=null?_j2:[])emitCopy({...copy,prose:copy.description});emitCopy({level:lvl,name:rf.feature.name,description:rf.feature.description,prose:rf.feature.description||(((_k2=rf.feature.entries)==null?void 0:_k2.length)?rf.feature.entries.join("\n\n"):void 0),choices:rf.feature.choices})}staged.sort((a,b)=>a.rank-b.rank||a.seq-b.seq);for(const s of staged)push(s.level,s.item);const subclassLevel=(_l2=entity.subclass_level)!=null?_l2:null;if(subclassLevel!=null&&subclassLevel<=c.level&&!sawAuthoredSubclass){const featureName=(_m2=entity.subclass_feature_name)!=null?_m2:"Subclass";const synthChoice={kind:"select-entity",id:"subclass",label:featureName,count:1,entity_type:"subclass",where:{parent_class:"self"}};push(subclassLevel,buildSubclassItem(synthChoice,{kind:"class",slug:entity.slug,level:subclassLevel},subclassLevel,featureName,c,ctx,ownerBare))}for(const pool of resolved.pools){if(pool.classIndex!==classIndex||pool.count<1)continue;const stranded=strandedPicks(pool);const strandedSlugs=new Set(stranded.map(e=>e.slug));const synth={kind:"select-entity",id:pool.id,label:pool.label,count:pool.count,entity_type:"optional-feature",from:[...pool.available.map(e=>e.slug),...stranded.map(e=>e.slug)]};const item=buildItem(synth,{kind:"class",slug:entity.slug,level:pool.anchorLevel},pool.anchorLevel,pool.label,()=>pool.selected.map(e=>e.key),ctx,ownerBare,effective);item.pool={id:pool.id,anchorLevel:pool.anchorLevel};const repeatables=pool.available.filter(e=>e.entity.repeatable===true);if(repeatables.length>0){item.repeatable=repeatables.map(e=>{var _a3,_b3;return{noteSlug:e.slug,itemChoice:(_a3=e.entity.item_choice)!=null?_a3:"learn",rows:resolveOptionRows(e.entity,ctx.registry,{edition:resolved.definition.edition,isEntityVisible:(_b3=ctx.isEntityVisible)==null?void 0:_b3.bind(ctx)})}})}for(const o of item.options)if(strandedSlugs.has(o.value))o.stranded=true;const memberChildren=[];for(const entry of pool.selected){for(const ch of memberChoices(entry.entity)){const child=buildItem(ch,{kind:"class",slug:entity.slug,level:pool.anchorLevel},pool.anchorLevel,entry.entity.name,readAt(pool.anchorLevel),ctx,ownerBare,effective,{keyPrefix:`${pool.id}:${entry.key}:`});child.parentLabel=entry.entity.name;memberChildren.push(child)}}if(memberChildren.length){item.children=memberChildren;if(item.status==="resolved"&&memberChildren.some(c2=>c2.status!=="resolved"))item.status="partial"}push(pool.anchorLevel,item)}for(const entry of featProgressions){const category=featProgressionCategory(entry.category);if(!category){warnOnce(`feat-progression-category:${entity.slug}:${entry.name}`,`Archivist: feat_progression "${entry.name}" on "${entity.slug}" carries no category this engine maps (${((_n2=entry.category)!=null?_n2:[]).join(", ")}); no decision is offered`);continue}const progression=entry.progression;if(Array.isArray(progression))continue;for(const key of Object.keys(progression)){const lvl=Number.parseInt(key,10);if(!Number.isInteger(lvl)||String(lvl)!==key)continue;if(lvl>c.level)continue;if(((_o=byLevel.get(lvl))!=null?_o:[]).some(i=>i.key==="feat")){warnOnce(`feat-progression-collision:${entity.slug}:${lvl}`,`Archivist: "${entry.name}" on "${entity.slug}" would add a second feat pick at level ${lvl}, where one already exists; skipping`);continue}const progressionChoice={kind:"select-entity",id:"feat",label:entry.name,count:1,entity_type:"feat",where:{category}};push(lvl,buildItem(progressionChoice,{kind:"class",slug:entity.slug,level:lvl},lvl,entry.name,readAt(lvl),ctx,ownerBare,effective))}}const levels=[...byLevel.entries()].sort(([a],[b])=>a-b).map(([level,items])=>({level,items}));classes.push({classIndex,levels})});const origin=[];const oc=(_i=resolved.definition.origin_choices)!=null?_i:{};const originRead=ns=>id=>oc[`${ns}:${id}`];const pushOrigin=(choices,ns,source,featureName,ownerBare,description)=>{for(const ch of choices!=null?choices:[]){origin.push(buildItem(ch,source,0,featureName,originRead(ns),ctx,ownerBare,effective,{description}))}};if(resolved.race){const bare=bareEntitySlug(resolved.race.slug);pushOrigin(resolved.race.choices,"race",{kind:"race",slug:resolved.race.slug},(_j=resolved.race.name)!=null?_j:"Race",bare);for(const t of(_k=resolved.race.traits)!=null?_k:[]){pushOrigin(t.choices,"race",{kind:"race",slug:resolved.race.slug},t.name,bare,t.description)}}if(resolved.background){const bare=bareEntitySlug(resolved.background.slug);pushOrigin([...(_l=resolved.background.choices)!=null?_l:[],...backgroundToolPicks(resolved.background).decisions],"background",{kind:"background",slug:resolved.background.slug},(_m=resolved.background.name)!=null?_m:"Background",bare);if(resolved.background.feature){pushOrigin(resolved.background.feature.choices,"background",{kind:"background",slug:resolved.background.slug},resolved.background.feature.name,bare,resolved.background.feature.description)}if(resolved.background.origin_feat){const originFeat=resolveOriginFeat(ctx.registry,resolved.background.origin_feat,resolved.background.slug);if(originFeat){const featSource={kind:"feat",slug:originFeat.feat.slug};const featBare=bareEntitySlug(originFeat.feat.slug);for(const ch of(_n=originFeat.feat.choices)!=null?_n:[]){origin.push(buildItem(ch,featSource,0,originFeat.display,originRead("background"),ctx,featBare,effective,{keyPrefix:"feat:"}))}}}for(const ch of equipmentDecisions(resolved.background.equipment,resolved.background.slug)){origin.push(buildItem(ch,{kind:"background",slug:resolved.background.slug},0,"Starting Equipment",originRead("background"),ctx,bare,effective))}}return{classes,origin}}var SLUG_RE=/^\[\[(.+?)\]\]$/;function stripSlug(ref){if(!ref)return null;const m=ref.match(SLUG_RE);return m?m[1]:ref}function resolveOriginFeat(entities,originFeatRef,ownerSlug){var _a,_b,_c;if(!originFeatRef)return null;const slug=wikilinkTailSlug(originFeatRef);const inner=originFeatRef.replace(/^\[\[/,"").replace(/\]\]$/,"").trim();const rawTail=(_b=(_a=inner.split("/").pop())==null?void 0:_a.trim())!=null?_b:"";const base=rawTail.replace(/\s*\([^()]*\)\s*$/,"").trim();const baseSlug=base&&base!==rawTail?wikilinkTailSlug(`[[${base}]]`):null;const baseInner=baseSlug?inner.slice(0,inner.length-rawTail.length)+base:null;const prefix=(ownerSlug==null?void 0:ownerSlug.includes("_"))?ownerSlug.slice(0,ownerSlug.indexOf("_")):null;const feats=bucketOf(entities,"feat");const byPath=p=>feats.find(f=>f.filePath===`${p}.md`||f.filePath.endsWith(`/${p}.md`));const sameCompendiumTail=s=>prefix?feats.find(f=>f.slug.startsWith(`${prefix}_feat_`)&&f.slug.endsWith(`_${s}`)):void 0;const anyTail=s=>feats.find(f=>f.slug.endsWith(`_${s}`));const tiers=[()=>{var _a2;return(_a2=feats.find(f=>f.slug===inner))!=null?_a2:feats.find(f=>f.slug===slug)},()=>byPath(inner),()=>baseInner?byPath(baseInner):void 0,()=>sameCompendiumTail(slug),()=>baseSlug?sameCompendiumTail(baseSlug):void 0,()=>anyTail(slug),()=>baseSlug?anyTail(baseSlug):void 0];let reg;let hitTier=0;for(let i=0;i<tiers.length&&!reg;i++){reg=tiers[i]();hitTier=i+1}if(!reg)return null;const variantName=baseSlug&&(hitTier===3||hitTier===5||hitTier===7)?rawTail:void 0;const data=reg.data;const feat=data.slug==null?{...data,slug:reg.slug}:data;return{feat,display:(_c=variantName!=null?variantName:feat.name)!=null?_c:slug}}var PCResolver=class{constructor(entities){this.entities=entities}get registry(){return this.entities}resolve(character){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const warnings=[];const lookup=(rawRef,type)=>{const slug=stripSlug(rawRef);if(!slug)return null;const reg=this.entities.getByTypeAndSlug(type,slug);if(!reg){warnings.push(`Slug [[${slug}]] not found in compendium as ${type}.`);return null}const data=reg.data;return data.slug==null?{...data,slug:reg.slug}:data};const race=lookup(character.race,"race");const background=lookup(character.background,"background");const classes=character.class.map(c=>({entity:lookup(c.name,"class"),level:c.level,subclass:lookup(c.subclass,"subclass"),choices:c.choices}));const memberSites=withoutStrandedSites(poolMemberSites(classes,this.entities),classes,this.entities,character.edition);const classSlugOf=i=>{var _a2,_b2,_c2,_d2,_e2;return(_e2=(_b2=(_a2=classes[i])==null?void 0:_a2.entity)==null?void 0:_b2.slug)!=null?_e2:stripSlug((_d2=(_c2=character.class[i])==null?void 0:_c2.name)!=null?_d2:null)};const featSites=featPickSites(character.class,memberSites,classSlugOf);const feats=[];const featVia=new Map;for(const site of featSites){const f=lookup(`[[${site.slug}]]`,"feat");if(!f)continue;if(!feats.some(x=>x.slug===f.slug))feats.push(f);if(site.via&&!featVia.has(f.slug))featVia.set(f.slug,site.via)}const originFeat=(background==null?void 0:background.origin_feat)?resolveOriginFeat(this.entities,background.origin_feat,background.slug):null;const originFeatSlug=originFeat==null?void 0:originFeat.feat.slug;if(originFeat&&!feats.some(f=>f.slug===originFeat.feat.slug)){feats.push(originFeat.feat)}if(originFeat&&background&&!featVia.has(originFeat.feat.slug)){featVia.set(originFeat.feat.slug,{kind:"background",slug:background.slug})}const raceFeats=[];for(const site of raceFeatSites(race,character.origin_choices)){const f=lookup(`[[${site.slug}]]`,"feat");if(!f)continue;raceFeats.push({feat:f,read:site.read});if(!feats.some(x=>x.slug===f.slug))feats.push(f);if(!featVia.has(f.slug))featVia.set(f.slug,site.via)}const totalLevel=classes.reduce((sum,c)=>sum+c.level,0);const features=collectResolvedFeatures(race,classes,background,feats,featVia);const extraFeatures=collectChosenGrantedFeatures(character,classes,this.entities,race,background,memberSites);features.push(...extraFeatures);const originChoices=(_a=character.origin_choices)!=null?_a:{};const featChoiceSites=[];for(const site of featSites){const f=lookup(`[[${site.slug}]]`,"feat");if(f)featChoiceSites.push({feat:f,via:site.via,read:site.read})}if(originFeat&&background){featChoiceSites.push({feat:originFeat.feat,via:{kind:"background",slug:background.slug},read:id=>originChoices[`background:feat:${id}`]})}for(const rf of raceFeats)featChoiceSites.push({feat:rf.feat,via:race?{kind:"race",slug:race.slug}:null,read:rf.read});features.push(...collectFeatChoiceGrants(featChoiceSites,this.entities));features.push(...collectAdditionalFeatures(character,this.entities,warnings));const casters=[];classes.forEach((c,i)=>{const profile=c.entity?resolveSpellcasting(c):null;const classSlug=profile?stripSlug(character.class[i].name):null;if(profile&&classSlug!=null)casters.push({classSlug,spellList:profile.spellList})});const spells=[];for(const raw of(_b=character.spells.known)!=null?_b:[]){const n=normalizeKnownSpell(raw);const reg=this.entities.getByTypeAndSlug("spell",n.slug);if(!reg){warnings.push(`Spell [[${n.slug}]] not found in compendium.`);continue}const entity=mirrorSpellShapes(reg.data);const isCantrip=((_c=entity.level)!=null?_c:0)===0;const classSlug=(_d=n.classSlug)!=null?_d:attributeUnclassedSpell(entity.classes,casters,this.entities);const prep=isCantrip||n.alwaysPrepared?true:(_e=n.preparedFlag)!=null?_e:false;spells.push({entity,slug:n.slug,classSlug,source:n.source,prepared:prep,alwaysPrepared:n.alwaysPrepared,persisted:true})}const oc=(_f=character.origin_choices)!=null?_f:{};if(originFeat){const read=childId=>oc[`background:feat:${childId}`];spells.push(...collectFeatGrantedSpells(originFeat.feat,read,this.entities,warnings))}for(const rf of raceFeats)spells.push(...collectFeatGrantedSpells(rf.feat,rf.read,this.entities,warnings));for(const site of featSites){const reg=this.entities.getByTypeAndSlug("feat",site.slug);if(!reg)continue;const feat=reg.data;spells.push(...collectFeatGrantedSpells(feat,site.read,this.entities,warnings))}for(const site of memberSites){const classSlug=stripSlug((_h=(_g=character.class[site.classIndex])==null?void 0:_g.name)!=null?_h:null);for(const ch of site.choices){if(ch.kind!=="select-entity"||ch.entity_type!=="spell"||isTargetChoice(ch))continue;const v=site.read(ch.id);for(const ref of Array.isArray(v)?v:typeof v==="string"?[v]:[]){const slug=typeof ref==="string"?stripSlug(ref):null;if(!slug)continue;const reg=this.entities.getByTypeAndSlug("spell",slug);if(!reg){warnings.push(`Spell [[${slug}]] not found in compendium.`);continue}const entity=mirrorSpellShapes(reg.data);spells.push({entity,slug,classSlug,source:"class",prepared:true,alwaysPrepared:true})}}}const ownSpellcastingAbility=(_i=classes.map(c=>{if(!c.entity)return null;const p=resolveSpellcasting(c);return p?effectiveSpellcastingAbility(c.entity.slug,p.ability,character.overrides):null}).find(a=>a!=null))!=null?_i:null;spells.push(...collectItemGrantedSpells(character,ownSpellcastingAbility,this.entities,warnings));const chosenMasteries=collectChosenWeaponMasteries(character);if(chosenMasteries.full.length>0){const target=features.find(rf=>{var _a2;return rf.feature.id==="weapon-mastery"||((_a2=rf.feature.choices)==null?void 0:_a2.some(ch=>ch.kind==="select-entity"&&ch.id==="weapon-mastery"&&ch.entity_type==="weapon"))});if(target){const names=chosenMasteries.full.map(fullSlug=>{var _a2,_b2;return(_b2=(_a2=this.entities.getByTypeAndSlug("weapon",fullSlug))==null?void 0:_a2.name)!=null?_b2:fullSlug});const entry={label:"Mastered weapons",description:names.join(", ")};target.chosenInline=target.chosenInline?[...target.chosenInline,entry]:[entry]}}const featureResources=resolveFeatureResources(features);const resolvedCharacter={definition:character,race,classes,background,feats,...originFeatSlug?{originFeatSlug}:{},totalLevel,features,spells:[],pools:[],resources:featureResources,weaponMasteries:chosenMasteries.bare,...(()=>{var _a2;const p=(_a2=pactWeaponPick(memberSites))!=null?_a2:classPactWeaponPick(character,classes);return p?{pactWeapon:p}:{}})(),state:character.state};resolvedCharacter.pools=resolveAllPools(resolvedCharacter,this.entities,featureResources);spells.push(...collectAdditionalSpells({race,feats,classes,totalLevel,ownAbility:ownSpellcastingAbility,alreadyCollected:spells,entities:this.entities,warnings,raceChoice:id=>oc[`race:${id}`],pools:resolvedCharacter.pools}));resolvedCharacter.spells=dedupeResolvedSpells(spells);resolvedCharacter.resources=resolveResourceIndex(resolvedCharacter);resolvedCharacter.features=bindFeatureConsumers(resolvedCharacter.features,resolvedCharacter.resources,classes);const infusions=buildInfusionContext(character,resolvedCharacter,this.entities);if(infusions)resolvedCharacter.infusions=infusions;const itemFeatures=buildItemFeatures((_j=character.equipment)!=null?_j:[],this.entities,infusions,warnings);if(itemFeatures.length)resolvedCharacter.itemFeatures=itemFeatures;return{character:resolvedCharacter,warnings}}};function collectChosenWeaponMasteries(character){var _a,_b;const full=new Set;for(const cls of(_a=character.class)!=null?_a:[]){for(const lvl of Object.values((_b=cls.choices)!=null?_b:{})){const pick=lvl["weapon-mastery"];if(Array.isArray(pick)){for(const s of pick)if(typeof s==="string")full.add(s)}}}return{full:[...full],bare:[...new Set([...full].map(bareEntitySlug))]}}function collectFeatPicks(character){const picks=new Map;for(const site of featPickSites(character.class,[],()=>null)){if(!picks.has(site.slug))picks.set(site.slug,{slug:site.slug,classIndex:site.classIndex,level:site.level})}return[...picks.values()]}function collectFeatGrantedSpells(feat,read,entities,warnings){var _a;const ability=readChosenSpellAbility(read);const slugs=[];collectSpellPickSlugs(feat.choices,read,slugs);const out=[];for(const rawSlug of slugs){const slug=(_a=stripSlug(rawSlug))!=null?_a:rawSlug;const reg=entities.getByTypeAndSlug("spell",slug);if(!reg){warnings.push(`Feat spell [[${slug}]] not found in compendium.`);continue}const entity=mirrorSpellShapes(reg.data);out.push({entity,slug,classSlug:null,source:"feat",prepared:true,alwaysPrepared:true,ability})}return out}function collectItemGrantedSpells(character,ownAbility,entities,warnings){var _a;const out=[];((_a=character.equipment)!=null?_a:[]).forEach((entry,entryIndex)=>{var _a2,_b,_c,_d,_e,_f;const spellRef=(_a2=entry.overrides)==null?void 0:_a2.spell;if(!spellRef)return;const{entity:itemEntity}=resolveEntityForEntry(entry.item,entities);const scrollLevel=isItemEntity(itemEntity)?itemEntity.scroll_level:void 0;if(scrollLevel==null)return;const slug=(_b=stripSlug(spellRef))!=null?_b:spellRef;const reg=entities.getByTypeAndSlug("spell",slug);if(!reg){warnings.push(`Scroll spell [[${slug}]] not found in compendium.`);return}const entity=mirrorSpellShapes(reg.data);const ability=(_f=(_d=(_c=entry.overrides)==null?void 0:_c.spell_ability)!=null?_d:ownAbility)!=null?_f:(_e=character.overrides)==null?void 0:_e.spellcasting_ability;const itemCasting=storedSpellNumbers(itemEntity);out.push({entity,slug,classSlug:null,source:"item",prepared:true,alwaysPrepared:true,ability,entryIndex,...itemCasting?{itemCasting}:{}})});return out}function dedupeResolvedSpells(spells){const byKey=new Map;for(const s of spells){const key=s.source==="item"?`${s.slug}#${s.entryIndex}`:s.atWill?`${s.slug}#atwill`:s.slug;const existing=byKey.get(key);if(!existing){byKey.set(key,s);continue}if(existing.source==="feat"&&s.source!=="feat"){byKey.set(key,{...s,alwaysPrepared:s.alwaysPrepared||existing.alwaysPrepared,prepared:s.prepared||existing.alwaysPrepared,...existing.persisted||s.persisted?{persisted:true}:{}})}else if(s.alwaysPrepared&&!existing.alwaysPrepared){byKey.set(key,{...existing,alwaysPrepared:true,prepared:true})}}return[...byKey.values()]}function readChosenSpellAbility(read){const pick=read("spellcasting-ability");return typeof pick==="string"&&ABILITY_KEYS.includes(pick)?pick:null}function collectSpellPickSlugs(choices,read,out){for(const ch of choices!=null?choices:[]){if(ch.kind==="select-entity"&&ch.entity_type==="spell"){const sel=read(ch.id);const picks=Array.isArray(sel)?sel:typeof sel==="string"?[sel]:[];for(const p of picks)if(typeof p==="string"&&p.length>0)out.push(p)}else if(ch.kind==="select-inline"){const sel=read(ch.id);const branch=typeof sel==="string"?ch.options.find(o=>o.value===sel):void 0;if(branch==null?void 0:branch.choices)collectSpellPickSlugs(branch.choices,read,out)}}}function collectChosenGrantedFeatures(character,classes,registry,race=null,background=null,memberSites=[]){var _a,_b,_c,_d;const out=[];for(const site of memberSites){const classSlug=(_b=(_a=classes[site.classIndex])==null?void 0:_a.entity)==null?void 0:_b.slug;if(!classSlug)continue;const at={};const grants=site.choices.filter(ch=>!isTargetChoice(ch));for(const ch of grants)at[ch.id]=site.read(ch.id);walkChoiceGrants(grants,at,(granted,suppress)=>{out.push({feature:granted,source:{kind:"class",slug:classSlug,level:site.level},...suppress?{renderSuppressed:true}:{}})},registry)}classes.forEach((c,i)=>{var _a2,_b2,_c2,_d2;if(!c.entity)return;const entity=c.entity;const entry=character.class[i];if(!entry)return;for(const[lvlStr,atLevel]of Object.entries(entry.choices)){const lvl=Number(lvlStr);if(!Number.isFinite(lvl)||lvl>entry.level)continue;const features=(_b2=((_a2=entity.features_by_level)!=null?_a2:{})[lvl])!=null?_b2:[];const subFeatures=c.subclass?(_d2=((_c2=c.subclass.features_by_level)!=null?_c2:{})[lvl])!=null?_d2:[]:[];for(const feature of[...features,...subFeatures]){walkChoiceGrants(feature.choices,atLevel,(granted,suppress)=>{out.push({feature:granted,source:{kind:"class",slug:entity.slug,level:lvl},...suppress?{renderSuppressed:true}:{}})},registry)}}});const oc=(_c=character.origin_choices)!=null?_c:{};const originAt=ns=>{const at={};for(const[key,val]of Object.entries(oc)){if(key.startsWith(`${ns}:`))at[key.slice(ns.length+1)]=val}return at};if(race){const atRace=originAt("race");const emitRace=(granted,suppress)=>{out.push({feature:granted,source:{kind:"race",slug:race.slug},...suppress?{renderSuppressed:true}:{}})};walkChoiceGrants(race.choices,atRace,emitRace,registry);for(const trait of(_d=race.traits)!=null?_d:[]){walkChoiceGrants(trait.choices,atRace,emitRace,registry)}}if(background){const atBg=originAt("background");const emitBg=(granted,suppress)=>{out.push({feature:granted,source:{kind:"background",slug:background.slug},...suppress?{renderSuppressed:true}:{}})};walkChoiceGrants(background.choices,atBg,emitBg,registry);if(background.feature){walkChoiceGrants(background.feature.choices,atBg,emitBg,registry)}}return out}function choiceIdsOf(choices,out=[]){for(const ch of choices!=null?choices:[]){out.push(ch.id);if(ch.kind==="select-inline")for(const o of ch.options)choiceIdsOf(o.choices,out)}return out}function collectFeatChoiceGrants(sites,registry){var _a;const out=[];for(const site of sites){const choices=(_a=site.feat.choices)!=null?_a:[];if(!choices.length)continue;const at={};for(const id of choiceIdsOf(choices))at[id]=site.read(id);const source={kind:"feat",slug:site.feat.slug,...site.via?{via:site.via}:{}};walkChoiceGrants(choices,at,granted=>{var _a2;out.push({feature:{...granted,name:(_a2=site.feat.name)!=null?_a2:granted.name},source,renderSuppressed:true})},registry,{inlineOnly:true})}return out}function collectAdditionalFeatures(character,entities,warnings){var _a,_b,_c,_d,_e,_f,_g,_h;const out=[];for(const entry of(_a=character.additional_features)!=null?_a:[]){const slug=(_b=stripSlug(entry))!=null?_b:entry;const reg=entities.getByTypeAndSlug("optional-feature",slug);if(!reg){warnings.push(`Granted feature [[${slug}]] not found in compendium as optional-feature.`);continue}const d=reg.data;const feature={id:(_c=d.slug)!=null?_c:slug,name:(_d=d.name)!=null?_d:slug,description:d.description,...((_e=d.effects)==null?void 0:_e.length)?{effects:d.effects}:{},...d.action_cost?{action:d.action_cost}:{},...d.passive!==void 0?{passive:d.passive}:{},...d.activatable!==void 0?{activatable:d.activatable}:{},...d.duration?{duration:d.duration}:{},...d.consumes?{consumes:d.consumes}:{}};const uses=d.uses;if(uses){const maxFormula=String(uses.max);if(isValidMaxFormula(maxFormula)){feature.resources=[{id:(_f=d.slug)!=null?_f:slug,name:(_g=d.name)!=null?_g:slug,max_formula:maxFormula,reset:uses.recharge,...((_h=uses.recovery)==null?void 0:_h.length)?{recovery:uses.recovery}:{},...d.rendering_hint?{rendering_hint:d.rendering_hint}:{},...d.surface?{surface:d.surface}:{}}]}else{warnings.push(`Granted feature "${slug}" has a prose uses.max (${JSON.stringify(uses.max)}); no tracker.`)}}out.push({feature,source:{kind:"campaign",slug}})}return out}function walkChoiceGrants(choices,atLevel,emit,registry,opts={}){var _a,_b,_c,_d,_e;for(const ch of choices!=null?choices:[]){const sel=atLevel[ch.id];if(!opts.inlineOnly&&ch.kind==="select-entity"&&ch.entity_type==="optional-feature"){const slugs=Array.isArray(sel)?sel:typeof sel==="string"?[sel]:[];for(const slug of slugs){const reg=registry.getByTypeAndSlug("optional-feature",(_a=stripSlug(String(slug)))!=null?_a:String(slug));if(!reg)continue;const d=reg.data;emit({id:(_b=d.slug)!=null?_b:String(slug),name:(_c=d.name)!=null?_c:String(slug),description:d.description,effects:d.effects,...d.action_cost?{action:d.action_cost}:{}})}}if(ch.kind==="select-inline"){const picks=Array.isArray(sel)?sel.filter(v=>typeof v==="string"):typeof sel==="string"?[sel]:[];for(const value of picks){const branch=ch.options.find(o=>o.value===value);if((_d=branch==null?void 0:branch.effects)==null?void 0:_d.length){const wc=(_e=branch.choices)==null?void 0:_e.find(c=>c.kind==="select-entity"&&c.entity_type==="weapon");const picked=wc?atLevel==null?void 0:atLevel[wc.id]:void 0;const effects=branch.effects.map(e=>e.kind==="weapon-ability"&&e.weapons==="chosen"&&typeof picked==="string"?{...e,weapons:[bareEntitySlug(picked)]}:e);emit({id:`${ch.id}-${branch.value}`,name:branch.label,description:branch.description,effects},true)}if(branch==null?void 0:branch.choices)walkChoiceGrants(branch.choices,atLevel,emit,registry,opts)}}}}function resolveChosenInline(feature,atLevel){var _a;if(!atLevel)return void 0;const picks=[];for(const ch of(_a=feature.choices)!=null?_a:[]){if(ch.kind!=="select-inline")continue;const sel=atLevel[ch.id];if(typeof sel!=="string")continue;const opt=ch.options.find(o=>o.value===sel);if(!opt)continue;picks.push({label:opt.label,description:opt.description})}return picks.length?picks:void 0}function isAsiSlotFeature(feature){var _a,_b,_c,_d;return feature.id==="ability-score-improvement"&&!((_a=feature.effects)!=null?_a:[]).some(e=>!(e.kind==="ability-score-increase"&&e.abilities==="chosen"))&&!((_b=feature.resources)==null?void 0:_b.length)&&!feature.action&&!((_c=feature.sub_features)==null?void 0:_c.length)&&!((_d=feature.attacks)==null?void 0:_d.length)}function foldRepeated(list){const byId=new Map;for(const rf of list){const id=rf.feature.id;if(!id||rf.buildOnly)continue;const arr=byId.get(id);if(arr)arr.push(rf);else byId.set(id,[rf])}const out=[];for(const rf of list){if(!rf.feature.id||rf.buildOnly){out.push(rf);continue}const arr=byId.get(rf.feature.id);if(!arr||arr.length===1){out.push(rf);continue}const sorted=[...arr].sort((a,b)=>a.source.level-b.source.level);const top=sorted[sorted.length-1];if(rf!==top)continue;const effects=sorted.flatMap(c=>{var _a;return(_a=c.feature.effects)!=null?_a:[]});const seen=new Set;const resources=sorted.flatMap(c=>{var _a;return((_a=c.feature.resources)!=null?_a:[]).filter(r=>!seen.has(r.id)&&seen.add(r.id))});const chosenInline=sorted.flatMap(c=>c.chosenInline?[c.chosenInline]:[]);const cardProse=f=>{var _a,_b;return(_b=f.description)!=null?_b:((_a=f.entries)==null?void 0:_a.length)?f.entries.join("\n\n"):void 0};const foldedFrom=sorted.slice(0,-1).map(c=>{var _a;return{level:c.source.level,name:c.feature.name,...cardProse(c.feature)?{description:cardProse(c.feature)}:{},...((_a=c.feature.choices)==null?void 0:_a.length)?{choices:c.feature.choices}:{}}});out.push({...top,feature:{...top.feature,...effects.length?{effects}:{},...resources.length?{resources}:{}},...chosenInline.length?{chosenInline:chosenInline.flat()}:{},...foldedFrom.length?{foldedFrom}:{}})}return out}function collectResolvedFeatures(race,classes,background,feats,featVia=new Map){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o;const out=[];for(const c of classes){if(!c.entity)continue;const slug=c.entity.slug;const byLevel=(_a=c.entity.features_by_level)!=null?_a:{};const classFeatures=[];const subclassFeatures=[];for(const[lvlStr,feats0]of Object.entries(byLevel)){const lvl=parseInt(lvlStr,10);if(Number.isNaN(lvl)||lvl>c.level)continue;for(const feat of feats0){const chosenInline=resolveChosenInline(feat,(_b=c.choices)==null?void 0:_b[lvl]);const feature=withResolvedActionCost(feat);classFeatures.push({feature,source:{kind:"class",slug,level:lvl},...chosenInline?{chosenInline}:{},...isAsiSlotFeature(feature)?{buildOnly:true}:{}})}}if(c.subclass){const sSlug=c.subclass.slug;const sByLevel=(_c=c.subclass.features_by_level)!=null?_c:{};for(const[lvlStr,feats0]of Object.entries(sByLevel)){const lvl=parseInt(lvlStr,10);if(Number.isNaN(lvl)||lvl>c.level)continue;for(const feat of feats0){const chosenInline=resolveChosenInline(feat,(_d=c.choices)==null?void 0:_d[lvl]);const feature=withResolvedActionCost(feat);subclassFeatures.push({feature,source:{kind:"subclass",slug:sSlug,level:lvl},...chosenInline?{chosenInline}:{},...isAsiSlotFeature(feature)?{buildOnly:true}:{}})}}}const foldedClass=foldRepeated(classFeatures);const foldedSubclass=foldRepeated(subclassFeatures);out.push(...foldedClass);if((_e=c.entity.resources)==null?void 0:_e.length){out.push({feature:{name:c.entity.name,resources:c.entity.resources},source:{kind:"class",slug,level:1}})}out.push(...foldedSubclass);if((_g=(_f=c.subclass)==null?void 0:_f.resources)==null?void 0:_g.length){out.push({feature:{name:c.subclass.name,resources:c.subclass.resources},source:{kind:"subclass",slug:c.subclass.slug,level:1}})}}if(race){const traits=(_h=race.traits)!=null?_h:[];for(const feat of traits){out.push({feature:withResolvedActionCost(feat),source:{kind:"race",slug:race.slug}})}}if(background){const bgFeature=background.feature;if(bgFeature){out.push({feature:withResolvedActionCost(bgFeature),source:{kind:"background",slug:background.slug}})}}for(const feat of feats){const via=featVia.get(feat.slug);const featSource={kind:"feat",slug:feat.slug,...via?{via}:{}};const bundled=(_i=feat.features)!=null?_i:[];const entityEffects=(_j=feat.effects)!=null?_j:[];if(bundled.length>0){bundled.forEach((f,i)=>{var _a2,_b2;const feature=i===0?{...f,action:(_a2=f.action)!=null?_a2:feat.action_cost,...entityEffects.length>0?{effects:[...(_b2=f.effects)!=null?_b2:[],...entityEffects]}:{}}:f;out.push({feature,source:featSource})})}else{const name=(_k=feat.name)!=null?_k:feat.slug;const foldedDesc=[feat.description,...(_l=feat.benefits)!=null?_l:[]].filter(Boolean).join("\n\n")||void 0;const buildOnly=((_m=feat.choices)!=null?_m:[]).some(c=>c.kind==="ability-points"&&c.points>=2)&&!((_n=feat.effects)==null?void 0:_n.length)&&!((_o=feat.resources)==null?void 0:_o.length)&&bundled.length===0;out.push({feature:{name,...foldedDesc?{description:foldedDesc}:{},...feat.resources?{resources:feat.resources}:{},...feat.action_cost?{action:feat.action_cost}:{},...entityEffects.length>0?{effects:entityEffects}:{}},source:featSource,...buildOnly?{buildOnly:true}:{}})}}return out}export{stripSlug,resolveOriginFeat,PCResolver,collectChosenWeaponMasteries,collectFeatPicks,collectFeatGrantedSpells,collectItemGrantedSpells,dedupeResolvedSpells,collectChosenGrantedFeatures,collectFeatChoiceGrants,collectAdditionalFeatures,collectResolvedFeatures,collectProficiencyGrants,__matchesFilterForTest,__categoryToEntitySelectForTest,collectChosenProficiencies,collectRuleProficiencySources,computeEffectiveProficiencies,computeSuppressedProficiencies,collectChosenAbilityPoints,buildDecisionLedger};
@@ -0,0 +1 @@
1
+ import{convertDescToTags,detectSpellcastingAbility}from"./chunk-MGGKZGLG.js";import{abilityModifier}from"./chunk-7FPQJDFD.js";import{toStringSafe}from"@archivist-gg/core";var CR_TO_XP={"0":10,"1/8":25,"1/4":50,"1/2":100,"1":200,"2":450,"3":700,"4":1100,"5":1800,"6":2300,"7":2900,"8":3900,"9":5e3,"10":5900,"11":7200,"12":8400,"13":1e4,"14":11500,"15":13e3,"16":15e3,"17":18e3,"18":2e4,"19":22e3,"20":25e3,"21":33e3,"22":41e3,"23":5e4,"24":62e3,"25":75e3,"26":9e4,"27":105e3,"28":12e4,"29":135e3,"30":155e3};function parseCR(cr){if(!cr)return 0;if(cr.includes("/")){const[num,denom]=cr.split("/").map(Number);return num/denom}return Number(cr)||0}function getChallengeRatingXP(cr){var _a;return(_a=CR_TO_XP[cr])!=null?_a:0}function getProficiencyBonus(cr){const v=parseCR(cr);if(v<5)return 2;if(v<9)return 3;if(v<13)return 4;if(v<17)return 5;if(v<21)return 6;if(v<25)return 7;if(v<29)return 8;return 9}function enrichMonster(raw){var _a,_b,_c;const cr=toStringSafe((_a=raw.cr)!=null?_a:"0");const abilities=raw.abilities;const wisdomMod=abilities?abilityModifier(abilities.wis):0;const passivePerception=(_b=raw.passive_perception)!=null?_b:10+wisdomMod;const languages=((_c=raw.languages)==null?void 0:_c.length)?raw.languages:["---"];const enriched={...raw,cr,xp:getChallengeRatingXP(cr),proficiency_bonus:getProficiencyBonus(cr),passive_perception:passivePerception,languages};convertMonsterEntries(enriched,cr);return enriched}var MONSTER_SECTIONS=[["traits","trait"],["actions","action"],["reactions","reaction"],["legendary_actions","legendary"]];function convertMonsterEntries(monster,cr){var _a;const abilities=monster.abilities;if(!abilities)return;const profBonus=getProficiencyBonus(cr);const spellAbility=detectSpellcastingAbility(((_a=monster.traits)!=null?_a:[]).map(f=>{var _a2;return{name:f.name,entries:(_a2=f.entries)!=null?_a2:[]}}));for(const[key,category]of MONSTER_SECTIONS){const features=monster[key];if(!Array.isArray(features))continue;for(const feature of features){const f=feature;if(!Array.isArray(f.entries))continue;f.entries=f.entries.map(desc=>{var _a2;if(/\{@\w+/.test(desc))return desc;return convertDescToTags(desc,{abilities,profBonus,actionName:(_a2=f.name)!=null?_a2:"",actionCategory:category,spellAbility})})}}}export{CR_TO_XP,parseCR,getChallengeRatingXP,getProficiencyBonus,enrichMonster,convertMonsterEntries};
@@ -0,0 +1 @@
1
+ import{resolveSpellcasting}from"./chunk-PFQPP77Q.js";import{heldPicks}from"./chunk-PKIMOVQG.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{isValidMaxFormula}from"./chunk-EAARMPCW.js";function resourceLevelFor(source,resolved){var _a,_b,_c,_d;if(source.kind==="class"){return(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_a.level)!=null?_b:resolved.totalLevel}if(source.kind==="subclass"){return(_d=(_c=resolved.classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_c.level)!=null?_d:resolved.totalLevel}return resolved.totalLevel}function resolveRecovery(entry){var _a;const kind=(_a=entry.restores)!=null?_a:"uses";const restTriggered=(entry.reset==="short-rest"||entry.reset==="long-rest")&&!entry.action;const flavour=kind==="spell-slots"?"manual":restTriggered?"rest":"manual";return{entry,kind,flavour}}function toResolvedResource(r,fallbackName,owner){var _a,_b,_c;return{id:r.id,name:(_a=r.name)!=null?_a:fallbackName,reset:r.reset,maxFormula:r.max_formula,...r.die?{die:r.die}:{},...r.scales_at?{scalesAt:r.scales_at}:{},...((_b=r.recovery)==null?void 0:_b.length)?{recovery:r.recovery.map(resolveRecovery)}:{},...r.rendering_hint?{renderingHint:r.rendering_hint}:{},...r.surface?{surface:r.surface}:{},...((_c=r.equivalent_ids)==null?void 0:_c.length)?{equivalentIds:r.equivalent_ids}:{},owner}}function resolveFeatureResources(features){var _a,_b;const out=new Map;for(const rf of features){for(const r of(_a=rf.feature.resources)!=null?_a:[]){if(out.has(r.id))continue;const owner={kind:"feature",featureId:(_b=rf.feature.id)!=null?_b:rf.feature.name,featureName:rf.feature.name,source:rf.source};out.set(r.id,toResolvedResource(r,rf.feature.name,owner))}}return out}function pickResourceId(entry){return entry.param!=null?entry.key:entry.slug}function resolveResourceIndex(resolved){var _a,_b,_c,_d;const out=new Map(resolveFeatureResources((_a=resolved.features)!=null?_a:[]));for(const pool of(_b=resolved.pools)!=null?_b:[]){const rc=resolved.classes[pool.classIndex];const classSlug=(_c=rc==null?void 0:rc.entity)==null?void 0:_c.slug;if(!classSlug)continue;for(const entry of[...heldPicks(pool),...(_d=pool.grants)!=null?_d:[]]){if(entry.itemBound===true)continue;const uses=entry.entity.uses;const id=pickResourceId(entry);if(!uses||out.has(id))continue;const maxFormula=String(uses.max);if(!isValidMaxFormula(maxFormula)){warnOnce(`pool-uses:${entry.slug}`,`optional feature "${entry.slug}" has a prose uses.max (${JSON.stringify(uses.max)}); no tracker`);continue}const pres=entry.entity;out.set(id,{id,name:entry.entity.name,reset:uses.recharge,maxFormula,...pres.rendering_hint?{renderingHint:pres.rendering_hint}:{},...pres.surface?{surface:pres.surface}:{},owner:{kind:"pool",poolId:pool.id,poolLabel:pool.label,source:{kind:"class",slug:classSlug,level:pool.anchorLevel}}})}}return out}function poolSaveDC(resolved,derived,pool){var _a,_b;const rc=resolved.classes[pool.classIndex];const ability=(_b=(_a=rc==null?void 0:rc.subclass)==null?void 0:_a.spellcasting)==null?void 0:_b.ability;if(!rc||!ability)return null;if(resolveSpellcasting(rc)!==null)return null;return 8+derived.proficiencyBonus+derived.mods[ability]}export{resourceLevelFor,resolveRecovery,resolveFeatureResources,pickResourceId,resolveResourceIndex,poolSaveDC};
@@ -0,0 +1 @@
1
+ var CONDITION_SLUGS=["blinded","charmed","deafened","frightened","grappled","incapacitated","invisible","paralyzed","petrified","poisoned","prone","restrained","stunned","unconscious"];export{CONDITION_SLUGS};
@@ -0,0 +1 @@
1
+ import{startingEquipmentEntrySchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{additionalSpellsEntrySchema,imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var toolProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),items:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.array(z.string()).nonempty()})]);var langProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),languages:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])})]);var suggestedCharSchema=z.object({personality_traits:z.record(z.string(),z.string()).optional(),ideals:z.record(z.string(),z.object({name:z.string().optional(),desc:z.string(),alignment:z.string().optional()})).optional(),bonds:z.record(z.string(),z.string()).optional(),flaws:z.record(z.string(),z.string()).optional()});var backgroundEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),skill_proficiencies:z.array(skillEnum),tool_proficiencies:z.array(toolProfSchema),language_proficiencies:z.array(langProfSchema),equipment:z.array(startingEquipmentEntrySchema),feature:z.object({name:z.string().min(1),description:z.string().min(1)}),ability_score_increases:z.object({pool:z.array(abilityEnum).length(3)}).nullable(),origin_feat:z.string().regex(wikilinkRegex).nullable(),suggested_characteristics:suggestedCharSchema.nullable(),choices:z.array(choiceSchema).optional(),rendering_hint:z.string().optional(),has_fluff_images:z.boolean().optional(),tables:z.array(z.object({name:z.string().min(1),dice:z.string().min(1),rows:z.array(z.object({roll:z.string(),text:z.string()}))})).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),prerequisites:z.array(z.object({kind:z.literal("campaign"),slug:z.string().min(1)})).optional(),image:imageField});export{langProfSchema,backgroundEntitySchema};
@@ -0,0 +1 @@
1
+ import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var entityFilterSchema=z.object({feature_type:z.string().min(1).optional(),category:z.string().min(1).optional(),parent_class:z.literal("self").optional(),available_to:z.literal("self").optional(),weapon_category:z.enum(["simple","martial"]).optional(),armor_category:z.enum(["light","medium","heavy","shield"]).optional(),item_type:z.array(z.string().min(1)).nonempty().optional(),mundane:z.boolean().optional(),list:z.string().min(1).optional(),level:z.number().int().min(0).max(9).optional(),edition:z.string().min(1).optional(),ritual:z.boolean().optional(),inventory:z.boolean().optional()}).strict();var inlineOptionSchema=z.lazy(()=>z.object({value:z.string().min(1),label:z.string().min(1),description:z.string().optional(),effects:z.array(featureEffectSchema).optional(),choices:z.array(choiceSchema).optional()}).strict());var choiceSchema=z.lazy(()=>z.discriminatedUnion("kind",[z.object({kind:z.literal("select-inline"),id:z.string().min(1),label:z.string().optional(),count:z.number().int().positive().optional(),options:z.array(inlineOptionSchema).nonempty()}).strict(),z.object({kind:z.literal("select-entity"),id:z.string().min(1),label:z.string().optional(),count:z.number().int().positive().optional(),entity_type:z.string().min(1),from:z.array(z.string().min(1)).nonempty().optional(),where:entityFilterSchema.optional(),target:z.literal(true).optional()}).strict(),z.object({kind:z.literal("select-proficiency"),id:z.string().min(1),label:z.string().optional(),count:z.number().int().positive(),domain:z.enum(["skill","tool","language","save"]),from:z.array(z.string().min(1)).nonempty().optional(),from_proficient:z.boolean().optional(),expertise:z.boolean().optional()}).strict(),z.object({kind:z.literal("ability-points"),id:z.string().min(1),label:z.string().optional(),points:z.number().int().positive(),max_per:z.number().int().positive(),pool:z.array(abilityEnum).nonempty().optional()}).strict()]));export{choiceSchema};
@@ -0,0 +1 @@
1
+ import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var conditionalPropertySchema=z.object({kind:z.literal("conditional"),uid:z.string(),note:z.string()});var propertySchema=z.union([z.string(),conditionalPropertySchema]);var editionEnum=z.enum(["2014","2024"]);var weaponEntitySchema=z.object({name:z.string().min(1),slug:z.string().min(1),category:z.string(),damage:z.object({dice:z.string(),type:z.string(),versatile_dice:z.string().optional()}),properties:z.array(propertySchema).default([]),range:z.object({normal:z.number().int().nonnegative(),long:z.number().int().nonnegative()}).optional(),reload:z.number().int().nonnegative().optional(),mastery:z.array(z.string()).optional(),type_tags:z.array(z.string()).optional(),ammo_type:z.string().optional(),weight:z.union([z.number(),z.string()]).optional(),cost:z.string().optional(),source:z.string().optional(),page:z.number().int().optional(),edition:editionEnum,entries:z.array(z.unknown()).optional(),rendering_hint:z.string().optional(),icon:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),image:imageField,raw:z.record(z.string(),z.unknown()).optional()}).loose();export{weaponEntitySchema};
@@ -0,0 +1 @@
1
+ function toDefenseSlug(s){return s.trim().toLowerCase().replace(/\s+/g," ")}export{toDefenseSlug};
@@ -0,0 +1 @@
1
+ import{z}from"zod";var encounterInputSchema=z.object({party_size:z.number().min(1).max(10).describe("Number of players"),party_level:z.number().min(1).max(20).describe("Average party level"),difficulty:z.enum(["easy","medium","hard","deadly"]),environment:z.string().optional().describe('e.g., "swamp", "dungeon", "forest"'),theme:z.string().optional().describe('e.g., "undead horde", "dragon lair"')});var encounterMonsterSchema=z.object({name:z.string(),cr:z.string(),count:z.number(),role:z.string()});var encounterOutputSchema=z.object({monsters:z.array(encounterMonsterSchema),tactics:z.string(),terrain:z.string(),notes:z.string(),xp_budget:z.object({target:z.number(),actual:z.number(),difficulty_rating:z.string()})});export{encounterInputSchema,encounterOutputSchema};
@@ -0,0 +1 @@
1
+ import{abilityModifier}from"./chunk-7FPQJDFD.js";var ABILITY_KEYS=["str","dex","con","int","wis","cha"];var STATIC_FALLBACK_CONTEXT={abilities:{str:0,dex:0,con:0,int:0,wis:0,cha:0},profBonus:0,actionName:"",actionCategory:"trait"};var NATURAL_MELEE_NAMES=/\b(bite|claws?|slam|gore|tail|hooves|tusks?|talons?|fist|horns?)\b/i;var FINESSE_WEAPON_NAMES=/\b(shortsword|rapier|dagger|whip|scimitar)\b/i;var RANGED_WEAPON_NAMES=/\b(bow|crossbow|sling|dart|blowgun|javelin)\b/i;var SPELL_ATTACK_PHRASES=/\bspell\s+attack\b/i;function preferredAbilitiesForAttack(actionName,desc,spellAbility){const combined=`${actionName} ${desc}`;if(SPELL_ATTACK_PHRASES.test(combined)&&spellAbility)return[spellAbility];if(RANGED_WEAPON_NAMES.test(actionName))return["dex"];if(FINESSE_WEAPON_NAMES.test(actionName))return["str","dex"];if(NATURAL_MELEE_NAMES.test(actionName))return["str","dex"];return["str","dex"]}function identifyAbility(damageBonus,preferred,mods){if(damageBonus===null)return null;const candidates=ABILITY_KEYS.filter(k=>mods[k]===damageBonus);if(candidates.length===0)return null;if(candidates.length===1)return candidates[0];for(const p of preferred){if(candidates.includes(p))return p}return[...candidates].sort()[0]}function parseDamageBonusFromHitText(desc,attackPos){const window=desc.slice(attackPos,attackPos+250);const damageRe=/Hit:\s*(?:\d+\s*\()?\d+d\d+(?:\s*([+-])\s*(\d+))?\s*\)?\s*\w*\s+damage/i;const m=window.match(damageRe);if(!m)return null;if(m[1]===void 0||m[2]===void 0)return 0;return m[1]==="-"?-Number(m[2]):Number(m[2])}function parseDamageBonusFor2024(desc,attackPos){const window=desc.slice(attackPos,attackPos+250);const damageRe=/(?:\d+\s*\()?\d+d\d+(?:\s*([+-])\s*(\d+))?\s*\)?\s*\w*\s+damage/i;const m=window.match(damageRe);if(!m)return null;if(m[1]===void 0||m[2]===void 0)return 0;return m[1]==="-"?-Number(m[2]):Number(m[2])}function convertDescToTags(desc,ctx){try{if(!ctx.abilities)return desc;const mods=computeMods(ctx.abilities);const dcTargets=computeDcTargets(mods,ctx.profBonus);let result=desc;result=result.replace(/(Strength|Dexterity|Constitution|Intelligence|Wisdom|Charisma)\s+Saving\s+Throw:\s+DC\s+(\d+)/gi,(_match,abilityWord,n)=>{const dc=Number(n);const abil=abilityWordToKey(abilityWord);if(abil&&dcTargets[abil]===dc){return`${abilityWord} Saving Throw: \`dc:${abil.toUpperCase()}\``}return`${abilityWord} Saving Throw: \`dc:${dc}\``});result=result.replace(/DC (\d+)\s+(Strength|Dexterity|Constitution|Intelligence|Wisdom|Charisma)/gi,(_match,n,abilityWord)=>{const dc=Number(n);const abil=abilityWordToKey(abilityWord);if(abil&&dcTargets[abil]===dc){return`\`dc:${abil.toUpperCase()}\` ${abilityWord}`}return`\`dc:${dc}\` ${abilityWord}`});result=result.replace(/(Melee|Ranged|Spell)\s+Attack\s+Roll:\s+([+-])(\d+),/g,(match,kind,sign,n,offset)=>{const attackBonus=sign==="-"?-Number(n):Number(n);const before=desc.slice(Math.max(0,offset-200),offset);const actionMatch=before.match(/(?:^|\.\s+)([A-Z][\w\s,'-]{1,40})\./);const actionName=actionMatch?actionMatch[1]:ctx.actionName;const damageBonus=parseDamageBonusFor2024(desc,offset+match.length);const preferred=kind.toLowerCase()==="spell"&&ctx.spellAbility?[ctx.spellAbility]:preferredAbilitiesForAttack(actionName,desc,ctx.spellAbility);const ability=identifyAbility(damageBonus,preferred,mods);const literal=attackBonus>=0?`+${attackBonus}`:`${attackBonus}`;if(ability===null){return`${kind} Attack Roll: \`atk:${literal}\`,`}if(attackBonus===mods[ability]+ctx.profBonus){return`${kind} Attack Roll: \`atk:${ability.toUpperCase()}+PB\`,`}if(attackBonus===mods[ability]){return`${kind} Attack Roll: \`atk:${ability.toUpperCase()}\`,`}return`${kind} Attack Roll: \`atk:${literal}\`,`});result=result.replace(/([+-])(\d+)\s+to\s+hit/g,(_match,sign,n,attackPos)=>{const attackBonus=sign==="-"?-Number(n):Number(n);const before=desc.slice(Math.max(0,attackPos-200),attackPos);const actionMatch=before.match(/(?:^|\.\s+)([A-Z][\w\s,'-]{1,40})\./);const actionName=actionMatch?actionMatch[1]:ctx.actionName;const damageBonus=parseDamageBonusFromHitText(desc,attackPos);const preferred=preferredAbilitiesForAttack(actionName,desc,ctx.spellAbility);const ability=identifyAbility(damageBonus,preferred,mods);if(ability===null){const literal2=attackBonus>=0?`+${attackBonus}`:`${attackBonus}`;return`\`atk:${literal2}\``}if(attackBonus===mods[ability]+ctx.profBonus){return`\`atk:${ability.toUpperCase()}+PB\``}if(attackBonus===mods[ability]){return`\`atk:${ability.toUpperCase()}\``}const literal=attackBonus>=0?`+${attackBonus}`:`${attackBonus}`;return`\`atk:${literal}\``});result=result.replace(/(?:(\d+)\s*\()?(\d+d\d+)(?:\s*([+-])\s*(\d+))?\s*\)?(?:\s+(\w+))?\s+damage/gi,(_match,_average,dice,sign,bonusStr,typeWord)=>{var _a;let inner=dice;if(bonusStr!=null){const bonus=sign==="-"?-Number(bonusStr):Number(bonusStr);const matchingAbilities=ABILITY_KEYS.filter(k=>mods[k]===bonus);if(matchingAbilities.length>0){const preferred=preferredAbilitiesForAttack(ctx.actionName,"",ctx.spellAbility);const pick=(_a=preferred.find(p=>matchingAbilities.includes(p)))!=null?_a:[...matchingAbilities].sort()[0];inner=`${dice}+${pick.toUpperCase()}`}else{inner=`${dice}${bonus>=0?"+":""}${bonus}`}}const typeSuffix=typeWord?` ${typeWord} damage`:" damage";return`\`dmg:${inner}\`${typeSuffix}`});result=result.replace(/Hit:\s*(\d+)\s+(\w+)?\s*damage/gi,(_match,n,typeWord)=>{const tt=typeWord?` ${typeWord} damage`:" damage";return`Hit: \`dmg:${n}\`${tt}`});result=result.replace(/(?<!`)DC (\d+)(?!\s*(?:Strength|Dexterity|Constitution|Intelligence|Wisdom|Charisma))/gi,(_match,n)=>{const dc=Number(n);const candidates=ABILITY_KEYS.filter(k=>dcTargets[k]===dc);if(ctx.spellAbility&&candidates.includes(ctx.spellAbility)){return`\`dc:${ctx.spellAbility.toUpperCase()}\``}if(candidates.length===1){return`\`dc:${candidates[0].toUpperCase()}\``}if(candidates.length>1){const abil=disambiguateAbility(candidates,ctx,desc);return`\`dc:${abil.toUpperCase()}\``}return`\`dc:${dc}\``});result=result.replace(/`[^`]*`|(?<!\w)(\d+d\d+(?:\s*[+-]\s*\d+)?)(?!\w)/g,(match,dice)=>{if(dice)return`\`dice:${dice.replace(/\s+/g,"")}\``;return match});return result}catch(e){return desc}}function computeMods(abilities){return{str:abilityModifier(abilities.str),dex:abilityModifier(abilities.dex),con:abilityModifier(abilities.con),int:abilityModifier(abilities.int),wis:abilityModifier(abilities.wis),cha:abilityModifier(abilities.cha)}}function computeDcTargets(mods,profBonus){return{str:8+profBonus+mods.str,dex:8+profBonus+mods.dex,con:8+profBonus+mods.con,int:8+profBonus+mods.int,wis:8+profBonus+mods.wis,cha:8+profBonus+mods.cha}}function disambiguateAbility(candidates,ctx,desc){var _a,_b,_c,_d,_e,_f,_g,_h;if(candidates.length===1)return candidates[0];const combined=`${desc} ${ctx.actionName}`.toLowerCase();const prefers=abil=>candidates.includes(abil)?abil:void 0;if(/melee\s+or\s+ranged\s+weapon\s+attack/.test(combined)){return(_b=(_a=prefers("str"))!=null?_a:prefers("dex"))!=null?_b:candidates[0]}if(/melee\s+weapon\s+attack/.test(combined)){return(_d=(_c=prefers("str"))!=null?_c:prefers("dex"))!=null?_d:candidates[0]}if(/ranged\s+weapon\s+attack/.test(combined)){return(_e=prefers("dex"))!=null?_e:candidates[0]}if(/spell\s+attack/.test(combined)){if(ctx.spellAbility&&candidates.includes(ctx.spellAbility)){return ctx.spellAbility}return(_f=prefers("wis"))!=null?_f:candidates[0]}const rangedWords=/\b(bow|crossbow|dart|sling)\b/;const meleeWords=/\b(bite|claw|slam|tail|gore|horns?|fist|hoof|talons?)\b/;if(rangedWords.test(ctx.actionName.toLowerCase())){return(_g=prefers("dex"))!=null?_g:candidates[0]}if(meleeWords.test(ctx.actionName.toLowerCase())){return(_h=prefers("str"))!=null?_h:candidates[0]}return[...candidates].sort()[0]}function abilityWordToKey(word){const lower=word.toLowerCase();switch(lower){case"strength":return"str";case"dexterity":return"dex";case"constitution":return"con";case"intelligence":return"int";case"wisdom":return"wis";case"charisma":return"cha"}return void 0}function detectSpellcastingAbility(traits){if(!traits)return void 0;for(const trait of traits){for(const entry of trait.entries){const match=entry.match(/spellcasting ability is (intelligence|wisdom|charisma)/i);if(match){const name=match[1].toLowerCase();if(name==="intelligence")return"int";if(name==="wisdom")return"wis";if(name==="charisma")return"cha"}}}return void 0}export{STATIC_FALLBACK_CONTEXT,convertDescToTags,detectSpellcastingAbility};
@@ -0,0 +1 @@
1
+ import{evaluateConditions}from"./chunk-56JK6VCL.js";function isConditionalBonus(x){return!!x&&typeof x==="object"&&typeof x.value==="number"&&Array.isArray(x.when)}function readNumericBonus(raw,ctx){if(raw===void 0||raw===null)return null;if(typeof raw==="number"){return raw===0?null:{kind:"applied",value:raw}}if(!isConditionalBonus(raw))return null;if(raw.value===0)return null;const outcome=evaluateConditions(raw.when,ctx);if(outcome==="true")return{kind:"applied",value:raw.value};if(outcome==="false")return{kind:"skipped"};return{kind:"informational",value:raw.value,conditions:raw.when}}export{readNumericBonus};
@@ -0,0 +1 @@
1
+ import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resourceConsumptionSchema,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";import{z as z2}from"zod";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var attackSchema=z.object({name:z.string().min(1),type:z.enum(["melee","ranged","spell"]),ability:z.union([abilityEnum,z.array(abilityEnum).nonempty()]).optional(),damage:z.string().optional(),damage_type:z.string().optional(),action:z.enum(["action","bonus-action","reaction"]).optional(),properties:z.array(z.string()).optional(),range:z.object({normal:z.number().int().nonnegative().optional(),long:z.number().int().nonnegative().optional(),reach:z.number().int().nonnegative().optional()}).optional(),condition:z.string().optional(),bonus:z.number().optional(),extra_damage:z.object({dice:z.string(),type:z.string()}).optional(),weapon_category:z.enum(["simple","martial"]).optional(),mastery:z.string().min(1).optional()});var companionSchema=z2.object({statblock:z2.string().optional(),statblock_wikilink:z2.string().nullable().optional(),count:z2.string().optional(),count_scaling:z2.array(z2.object({level:z2.number().optional(),count:z2.string().optional(),source_quote:z2.string().optional()})).optional(),shares_action_economy:z2.boolean().optional(),turn_order:z2.string().optional(),turn_order_source_quote:z2.string().nullable().optional(),proficiency_bonus_scaled:z2.array(z2.object({stat:z2.string().optional(),formula:z2.string().optional(),source_quote:z2.string().optional()})).optional(),lifecycle:z2.object({created_by:z2.string().optional(),recreate_on:z2.string().nullable().optional(),previous_instance_perishes:z2.boolean().nullable().optional(),vanishes_if_owner_dies:z2.boolean().nullable().optional(),vanishes_after:z2.string().nullable().optional(),source_quote:z2.string().optional()}).nullable().optional(),autonomy:z2.object({when:z2.string().optional(),behaviour:z2.string().optional(),source_quote:z2.string().optional()}).nullable().optional(),variants:z2.array(z2.object({axis:z2.string().optional(),choices:z2.array(z2.string()).optional(),chosen_at:z2.string().optional(),source_quote:z2.string().optional()})).optional(),base_statblock:z2.string().nullable().optional(),overrides:z2.array(z2.object({field:z2.string().optional(),value:z2.string().optional(),source_quote:z2.string().optional()})).optional(),source_quote:z2.string().optional()});var featureObjectSchema=z2.lazy(()=>z2.object({id:z2.string().min(1).optional(),name:z2.string().min(1),description:z2.string().optional(),entries:z2.array(z2.string()).optional(),choices:z2.array(choiceSchema).optional(),grants_resource:z2.string().optional(),consumes:resourceConsumptionSchema.optional(),attacks:z2.array(attackSchema).optional(),action:z2.enum(["action","bonus-action","reaction","free","special"]).optional(),trigger:z2.string().optional(),dc_formula:z2.string().optional(),effects:z2.array(featureEffectSchema).optional(),sub_features:z2.array(featureSchemaTyped).optional(),resources:z2.array(resourceSchema).optional(),activatable:z2.boolean().optional(),passive:z2.boolean().optional(),duration:durationSchema.optional(),class_source:z2.string().min(1).optional(),rendering_hint:z2.string().optional(),subclass_short_name:z2.string().min(1).optional(),subclass_source:z2.string().min(1).optional(),header:z2.number().optional(),is_class_feature_variant:z2.boolean().optional(),gain_subclass_feature:z2.boolean().optional(),gain_subclass_feature_has_content:z2.boolean().optional(),type:z2.string().min(1).optional(),recharge:z2.object({type:z2.enum(["recharge_on_roll","per_day","per_short_rest","per_long_rest"]),param:z2.number()}).optional(),action_cost:actionCostEnum.optional(),save:z2.object({ability:z2.string().min(1),dc_formula:z2.string().min(1)}).optional(),companion:companionSchema.optional()}));var featureSchemaTyped=featureObjectSchema.refine(f=>f.description!==void 0||f.entries!==void 0&&f.entries.length>0,{message:"feature requires either description or non-empty entries"});var featureSchema=featureSchemaTyped;export{featureObjectSchema,featureSchema};
@@ -0,0 +1 @@
1
+ import{parseFeat}from"./chunk-OTRH62HY.js";import yaml from"js-yaml";var featCodec={parse(doc){return parseFeat(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{featCodec};
@@ -0,0 +1 @@
1
+ import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resetTriggerEnum,resourceConsumptionSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var editionEnum=z.enum(["2014","2024"]);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var namedRefSchema=z.object({name:z.string().min(1),source:z.string().min(1).optional(),visible_stats:z.boolean().optional()});var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("level"),min:z.number().int().positive(),class:namedRefSchema.optional(),subclass:namedRefSchema.optional()}),z.object({kind:z.literal("spell-known"),spell:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("pact"),pact:z.enum(["tome","blade","chain","talisman"])}),z.object({kind:z.literal("class"),class:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("other"),detail:z.string()}),z.object({kind:z.literal("optionalfeature"),optionalfeature:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("spell-choose"),choose:z.string().min(1),entry:z.string().optional(),entry_summary:z.string().optional()})]);var usesSchema=z.object({max:z.union([z.number(),z.string()]),recharge:resetTriggerEnum,recovery:z.array(z.object({id:z.string().min(1),name:z.string().min(1),amount:z.union([z.number(),z.string()]),reset:resetTriggerEnum,restores:z.enum(["uses","spell-slots"]).optional()})).optional()});var filterSpecSchema=z.object({rarity:z.array(z.string().min(1)).min(1),types:z.array(z.string().min(1)).optional(),exclude_types:z.array(z.string().min(1)).optional(),cursed:z.literal(false).optional()}).strict();var optionCreatesSchema=z.object({item:z.string().regex(wikilinkRegex).optional(),variant:z.object({candidates:z.array(z.string().regex(wikilinkRegex)).min(1)}).strict().optional(),filter:filterSpecSchema.optional()}).strict().refine(c=>[c.item,c.variant,c.filter].filter(a=>a!==void 0).length===1,{message:"creates needs exactly one of item, variant, filter"});var optionRowSchema=z.object({key:z.string().regex(/^[a-z0-9][a-z0-9._-]*$/,"an option key is lower-case, with no '#' and no whitespace"),name:z.string().min(1),min_level:z.number().int().min(1).max(20),attunement:z.boolean().optional(),creates:optionCreatesSchema}).strict();var infuseItemSchema=z.object({bonuses:z.object({ac:z.number().int().optional(),weapon_attack:z.number().int().optional(),weapon_damage:z.number().int().optional(),spell_attack:z.number().int().optional(),saving_throws:z.number().int().optional(),speed:z.object({walk:z.number().int().optional(),fly:z.number().int().optional(),swim:z.number().int().optional(),climb:z.number().int().optional()}).strict().optional()}).strict().optional(),resist:z.array(z.string().min(1)).optional(),charges:z.object({max:z.number().int().min(1),dice:z.string().optional(),recharge:z.string().optional(),recharge_amount:z.string().optional()}).strict().optional(),action:actionCostEnum.optional(),range:z.string().min(1).optional()}).strict();var infuseBlockSchema=z.object({targets:z.array(z.object({kind:z.enum(["armor","shield","weapon","gear"]),category:z.array(z.string().min(1)).min(1).optional(),property:z.string().min(1).optional(),name_any:z.array(z.string().min(1)).min(1).optional()}).strict()).min(1),targets_label:z.string().min(1).optional(),new_object:z.string().min(1).optional(),rarity:z.string().min(1).optional(),attunement:z.object({required:z.literal(true)}).strict().optional(),choice:z.object({kind:z.literal("damage-type"),options:z.array(z.string().min(1)).min(1).optional()}).strict().optional(),item:infuseItemSchema.optional(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),item:infuseItemSchema}).strict()).optional()}).strict().refine(b=>{var _a;return((_a=b.scales_at)!=null?_a:[]).every((r,i,a)=>i===0||a[i-1].level<r.level)},{message:"scales_at levels ascend"});var optionalFeatureEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),feature_type:z.string().min(1),description:z.string(),prerequisites:z.array(prerequisiteSchema),available_to:z.array(z.string().regex(wikilinkRegex)),effects:z.array(featureEffectSchema),action_cost:actionCostEnum.nullable().optional(),uses:usesSchema.nullable().optional(),consumes:resourceConsumptionSchema.nullable().optional(),duration:durationSchema.nullable().optional(),passive:z.boolean().optional(),activatable:z.boolean().optional(),rendering_hint:z.string().optional(),surface:z.enum(["band","tab"]).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),is_class_feature_variant:z.boolean().optional(),has_fluff_images:z.boolean().optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),image:imageField,repeatable:z.literal(true).optional(),item_choice:z.enum(["learn","create"]).optional(),options:z.array(optionRowSchema).optional(),infuse:infuseBlockSchema.optional(),choices:z.array(choiceSchema).optional()}).superRefine((d,ctx)=>{var _a;if(d.repeatable&&(!d.options||!d.item_choice))ctx.addIssue({code:"custom",message:"a repeatable note needs options and item_choice"});const keys=((_a=d.options)!=null?_a:[]).map(o=>o.key);if(new Set(keys).size!==keys.length)ctx.addIssue({code:"custom",message:"option keys are unique"})});export{optionRowSchema,infuseBlockSchema,optionalFeatureEntitySchema};
@@ -0,0 +1 @@
1
+ import{parseBackground}from"./chunk-VVJXZZ4Z.js";import yaml from"js-yaml";var backgroundCodec={parse(doc){return parseBackground(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{backgroundCodec};
@@ -0,0 +1 @@
1
+ import{armorEntitySchema}from"./chunk-RE5Z5RNK.js";import{parseYaml}from"@archivist-gg/core";var KNOWN_KEYS=new Set(["name","slug","category","ac","strength_requirement","stealth_disadvantage","weight","cost","rarity","source","page","edition","entries","raw","rendering_hint","icon","has_fluff","has_fluff_images","image","strength_required"]);function parseArmor(source){var _a;const raw=parseYaml(source,["name","slug","category","ac"]);if(!raw.success)return raw;if(raw.data.strength_requirement===void 0&&typeof raw.data.strength_required==="number"){raw.data.strength_requirement=raw.data.strength_required}const result=armorEntitySchema.safeParse(raw.data);if(!result.success){return{success:false,error:`armor schema validation failed: ${result.error.message}`}}const entity=result.data;const extras={};for(const[k,v]of Object.entries(raw.data)){if(!KNOWN_KEYS.has(k))extras[k]=v}if(Object.keys(extras).length>0){entity.raw={...(_a=entity.raw)!=null?_a:{},...extras}}return{success:true,data:entity}}export{parseArmor};
@@ -0,0 +1 @@
1
+ var RENDERING_HINT_LAYOUT={"dice-pool":"dice-pool","point-pool":"point-pool"};function derivePoolLayout(entries){var _a,_b;const votes=new Map;for(const e of entries){const hint=(_a=e.entity.rendering_hint)!=null?_a:"";if(!Object.prototype.hasOwnProperty.call(RENDERING_HINT_LAYOUT,hint))continue;const layout=RENDERING_HINT_LAYOUT[hint];votes.set(layout,((_b=votes.get(layout))!=null?_b:0)+1)}let best;let bestN=0;let tied=false;for(const[layout,n]of votes){if(n>bestN){best=layout;bestN=n;tied=false}else if(n===bestN)tied=true}return tied?void 0:best}function poolPresentation(authored,derived){const head=authored==="point-pool"?"points":authored==="dice-pool"?"dice":derived==="point-pool"?"points":"dice";return{head}}var RENDERING_HINT_AFFORDANCE={"granted-die-to-ally":"granted-die"};function deriveEntryAffordance(entity){var _a;const hint=(_a=entity.rendering_hint)!=null?_a:"";if(!Object.prototype.hasOwnProperty.call(RENDERING_HINT_AFFORDANCE,hint))return void 0;return RENDERING_HINT_AFFORDANCE[hint]}var AFFORDANCE_CAPTIONS={"granted-die":"{amount}{die} to an ally"};function formatAffordanceCaption(affordance,values){return AFFORDANCE_CAPTIONS[affordance].replace(/\{(\w+)\}/g,(whole,key)=>Object.prototype.hasOwnProperty.call(values,key)?String(values[key]):whole)}export{RENDERING_HINT_LAYOUT,derivePoolLayout,poolPresentation,RENDERING_HINT_AFFORDANCE,deriveEntryAffordance,AFFORDANCE_CAPTIONS,formatAffordanceCaption};