@archivist-gg/dnd5e 0.3.11 → 0.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSES/SRD.md +38 -3
  2. package/dist/armor/armor.codec.js +3 -3
  3. package/dist/armor/armor.parser.js +2 -2
  4. package/dist/armor/armor.schema.d.ts +1 -0
  5. package/dist/armor/armor.schema.js +1 -1
  6. package/dist/armor/armor.types.d.ts +2 -0
  7. package/dist/background/background.codec.js +5 -5
  8. package/dist/background/background.parser.js +4 -4
  9. package/dist/background/background.schema.js +3 -3
  10. package/dist/{chunk-XTRDCSJB.js → chunk-2JSQE3DD.js} +15 -1
  11. package/dist/chunk-2LULMQTF.js +14 -0
  12. package/dist/{chunk-MAH6DCRI.js → chunk-2UDSN6VW.js} +1 -1
  13. package/dist/chunk-3LWMFYKS.js +57 -0
  14. package/dist/{chunk-JCEV7KYN.js → chunk-3MGQFFNE.js} +1 -1
  15. package/dist/chunk-3VZZDKRA.js +1014 -0
  16. package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
  17. package/dist/{chunk-2M34FLAY.js → chunk-5MXFW4O3.js} +9 -3
  18. package/dist/{chunk-4DOMDEBZ.js → chunk-6EI737IO.js} +1 -1
  19. package/dist/{chunk-G247QXWW.js → chunk-7ATNGKBS.js} +1 -1
  20. package/dist/{chunk-XY6X2APM.js → chunk-7Q2VPKCD.js} +17 -0
  21. package/dist/{chunk-T2SNEJOE.js → chunk-7QN7XSAK.js} +1 -1
  22. package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
  23. package/dist/{chunk-7YU4NPKR.js → chunk-AZRGFUSR.js} +1 -1
  24. package/dist/{chunk-PP2UHLBA.js → chunk-B3DP42OM.js} +5 -0
  25. package/dist/chunk-CM5CWO4K.js +735 -0
  26. package/dist/{chunk-MQ747UCR.js → chunk-DOXSFYLH.js} +70 -2
  27. package/dist/chunk-EJP263OP.js +186 -0
  28. package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
  29. package/dist/{chunk-V6LJFP4R.js → chunk-FANQVQ3D.js} +2 -2
  30. package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
  31. package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
  32. package/dist/{chunk-JANNRGJC.js → chunk-G6PBI2BU.js} +1 -1
  33. package/dist/chunk-H5PTKYXL.js +101 -0
  34. package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
  35. package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
  36. package/dist/chunk-HTYMW5CH.js +228 -0
  37. package/dist/chunk-IHE6KVC3.js +13 -0
  38. package/dist/{chunk-QHMWA3SZ.js → chunk-JCMUVZIK.js} +1 -1
  39. package/dist/{chunk-V373TRJE.js → chunk-JSM6JFZR.js} +198 -125
  40. package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
  41. package/dist/chunk-KR6JF3BF.js +14 -0
  42. package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
  43. package/dist/chunk-LBEXLN6I.js +91 -0
  44. package/dist/{chunk-BLRW2UU6.js → chunk-LF5AGJA4.js} +2 -2
  45. package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
  46. package/dist/{chunk-BIA32MQ5.js → chunk-MBX25B6D.js} +1 -1
  47. package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
  48. package/dist/{chunk-J77CKYV3.js → chunk-OFCSP6MT.js} +1 -1
  49. package/dist/{chunk-2INMRR3Q.js → chunk-ONTGZR5T.js} +326 -149
  50. package/dist/{chunk-MWCCGPG3.js → chunk-OOSRUJBI.js} +3 -2
  51. package/dist/{chunk-U3BABVJF.js → chunk-PKX6TGRE.js} +2 -2
  52. package/dist/{chunk-PJMG5XV3.js → chunk-PQZ4LM4Z.js} +1 -1
  53. package/dist/chunk-PXVNAY7T.js +84 -0
  54. package/dist/chunk-QH36K2PU.js +158 -0
  55. package/dist/{chunk-R747YKS7.js → chunk-QZSWN2KT.js} +1 -1
  56. package/dist/{chunk-CHUALUIX.js → chunk-RYLXAYIQ.js} +1 -1
  57. package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
  58. package/dist/{chunk-PZCE7DJM.js → chunk-T6QIF5XR.js} +31 -1
  59. package/dist/{chunk-CBEKVAX4.js → chunk-TULQ4FFX.js} +41 -13
  60. package/dist/{chunk-S56D6B6C.js → chunk-UUBJCNQU.js} +12 -3
  61. package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
  62. package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
  63. package/dist/{chunk-3HX5VLWP.js → chunk-VRV3NNTA.js} +2 -2
  64. package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
  65. package/dist/{chunk-BL3VELKP.js → chunk-Y5VVP73C.js} +1 -1
  66. package/dist/{chunk-PI4LLJG4.js → chunk-YD2VAHA6.js} +2 -2
  67. package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
  68. package/dist/{chunk-NWDF5HG3.js → chunk-YKL6SHRJ.js} +1 -1
  69. package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
  70. package/dist/chunk-ZUQW5VBZ.js +89 -0
  71. package/dist/class/class.codec.js +7 -7
  72. package/dist/class/class.parser.js +6 -6
  73. package/dist/class/class.schema.d.ts +18 -0
  74. package/dist/class/class.schema.js +5 -5
  75. package/dist/class/class.standard-array.d.ts +16 -0
  76. package/dist/class/class.standard-array.js +20 -0
  77. package/dist/class/class.types.d.ts +3 -0
  78. package/dist/dnd/amount-text.d.ts +38 -0
  79. package/dist/dnd/amount-text.js +13 -0
  80. package/dist/dnd/resource-words.d.ts +4 -0
  81. package/dist/dnd/resource-words.js +30 -0
  82. package/dist/entities/base-item-resolver.js +2 -2
  83. package/dist/entities/slug.d.ts +18 -8
  84. package/dist/entities/slug.js +3 -1
  85. package/dist/feat/feat.codec.js +5 -5
  86. package/dist/feat/feat.parser.js +4 -4
  87. package/dist/feat/feat.schema.d.ts +41 -3
  88. package/dist/feat/feat.schema.js +3 -3
  89. package/dist/index.js +7513 -4177
  90. package/dist/item/item.actions-map.d.ts +40 -5
  91. package/dist/item/item.actions-map.js +5 -84
  92. package/dist/item/item.attunement.js +3 -9
  93. package/dist/item/item.bonuses.js +5 -2
  94. package/dist/item/item.codec.js +3 -3
  95. package/dist/item/item.conditions.js +4 -1
  96. package/dist/item/item.conditions.types.d.ts +4 -0
  97. package/dist/item/item.cost.d.ts +3 -0
  98. package/dist/item/item.cost.js +29 -0
  99. package/dist/item/item.icon.d.ts +15 -0
  100. package/dist/item/item.icon.js +211 -0
  101. package/dist/item/item.parser.js +2 -2
  102. package/dist/item/item.schema.d.ts +16 -1
  103. package/dist/item/item.schema.js +3 -1
  104. package/dist/item/item.types.d.ts +9 -2
  105. package/dist/monster/monster.parser.js +5 -5
  106. package/dist/monster/monster.schema.js +4 -4
  107. package/dist/optional-feature/optional-feature.codec.js +5 -4
  108. package/dist/optional-feature/optional-feature.parser.js +4 -3
  109. package/dist/optional-feature/optional-feature.schema.d.ts +255 -3
  110. package/dist/optional-feature/optional-feature.schema.js +7 -2
  111. package/dist/pc/pc.additional-spells.js +3 -3
  112. package/dist/pc/pc.amount-bindings.d.ts +32 -0
  113. package/dist/pc/pc.amount-bindings.js +23 -0
  114. package/dist/pc/pc.asi-flatten.d.ts +62 -1
  115. package/dist/pc/pc.asi-flatten.js +16 -0
  116. package/dist/pc/pc.conditions.js +1 -1
  117. package/dist/pc/pc.containment.d.ts +45 -0
  118. package/dist/pc/pc.containment.js +24 -0
  119. package/dist/pc/pc.decision-engine.d.ts +24 -3
  120. package/dist/pc/pc.decision-engine.js +26 -16
  121. package/dist/pc/pc.entry-overrides.d.ts +79 -0
  122. package/dist/pc/pc.entry-overrides.js +40 -0
  123. package/dist/pc/pc.equipment.d.ts +2 -2
  124. package/dist/pc/pc.equipment.js +19 -7
  125. package/dist/pc/pc.feature-effects.d.ts +12 -0
  126. package/dist/pc/pc.feature-effects.js +2 -2
  127. package/dist/pc/pc.infusions.d.ts +228 -0
  128. package/dist/pc/pc.infusions.js +64 -0
  129. package/dist/pc/pc.member-choices.d.ts +90 -0
  130. package/dist/pc/pc.member-choices.js +32 -0
  131. package/dist/pc/pc.parser.js +18 -1
  132. package/dist/pc/pc.pools.d.ts +8 -1
  133. package/dist/pc/pc.pools.js +13 -3
  134. package/dist/pc/pc.proficiencies.js +23 -15
  135. package/dist/pc/pc.proficiency-query.js +6 -0
  136. package/dist/pc/pc.recalc.d.ts +39 -36
  137. package/dist/pc/pc.recalc.js +115 -70
  138. package/dist/pc/pc.resolver.d.ts +2 -1
  139. package/dist/pc/pc.resolver.js +22 -14
  140. package/dist/pc/pc.resource-seed.js +1 -1
  141. package/dist/pc/pc.resources.d.ts +6 -1
  142. package/dist/pc/pc.resources.js +3 -1
  143. package/dist/pc/pc.rest.d.ts +21 -1
  144. package/dist/pc/pc.rest.js +52 -19
  145. package/dist/pc/pc.schema.d.ts +43 -2
  146. package/dist/pc/pc.schema.js +1 -1
  147. package/dist/pc/pc.slotting.d.ts +36 -3
  148. package/dist/pc/pc.slotting.js +13 -5
  149. package/dist/pc/pc.tool-picks.d.ts +51 -0
  150. package/dist/pc/pc.tool-picks.js +18 -0
  151. package/dist/pc/pc.types.d.ts +115 -14
  152. package/dist/pc/pc.weapon-grant.d.ts +15 -0
  153. package/dist/pc/pool-layout.d.ts +8 -0
  154. package/dist/pc/pool-layout.js +5 -3
  155. package/dist/pc/resource-equivalents.d.ts +44 -0
  156. package/dist/pc/spell-source.js +4 -9
  157. package/dist/race/race.codec.js +6 -6
  158. package/dist/race/race.parser.js +5 -5
  159. package/dist/race/race.schema.js +4 -4
  160. package/dist/schemas/attack-schema.d.ts +1 -1
  161. package/dist/schemas/choice-schema.js +2 -2
  162. package/dist/schemas/feature-effect-schema.d.ts +41 -3
  163. package/dist/schemas/feature-effect-schema.js +1 -1
  164. package/dist/schemas/feature-schema.js +3 -3
  165. package/dist/schemas/selection-pool-schema.d.ts +10 -0
  166. package/dist/schemas/selection-pool-schema.js +1 -1
  167. package/dist/spell/spell.codec.js +2 -2
  168. package/dist/spell/spell.parser.d.ts +6 -1
  169. package/dist/spell/spell.parser.js +5 -3
  170. package/dist/spell/spell.types.d.ts +10 -0
  171. package/dist/srd/retired-items.d.ts +14 -0
  172. package/dist/srd/retired-items.js +11 -0
  173. package/dist/subclass/subclass.codec.js +7 -7
  174. package/dist/subclass/subclass.parser.js +6 -6
  175. package/dist/subclass/subclass.schema.d.ts +10 -0
  176. package/dist/subclass/subclass.schema.js +5 -5
  177. package/dist/types/choice.d.ts +13 -0
  178. package/dist/types/equipment-grant.d.ts +18 -1
  179. package/dist/types/equipment-grant.js +12 -0
  180. package/dist/types/feature-effect.d.ts +12 -1
  181. package/dist/types/optional-feature.types.d.ts +84 -1
  182. package/dist/types/selection-pool.d.ts +18 -3
  183. package/dist/weapon/weapon.classify.d.ts +10 -8
  184. package/dist/weapon/weapon.classify.js +2 -2
  185. package/dist/weapon/weapon.codec.js +3 -3
  186. package/dist/weapon/weapon.parser.js +2 -2
  187. package/dist/weapon/weapon.schema.d.ts +1 -0
  188. package/dist/weapon/weapon.schema.js +1 -1
  189. package/dist/weapon/weapon.types.d.ts +2 -0
  190. package/package.json +1 -1
  191. package/dist/chunk-O4SRD3J5.js +0 -165
  192. package/dist/chunk-WXWPK3LI.js +0 -55
@@ -1,28 +1,40 @@
1
+ import {
2
+ amountBindingsFor
3
+ } from "../chunk-PXVNAY7T.js";
4
+ import "../chunk-KR6JF3BF.js";
1
5
  import {
2
6
  computeConditionEffects
3
- } from "../chunk-R2ZV233X.js";
7
+ } from "../chunk-MYY2C5MB.js";
4
8
  import {
5
9
  collectChosenAbilityPoints,
6
10
  collectChosenProficiencies
7
- } from "../chunk-2INMRR3Q.js";
11
+ } from "../chunk-ONTGZR5T.js";
12
+ import "../chunk-2LULMQTF.js";
13
+ import "../chunk-H5PTKYXL.js";
14
+ import {
15
+ assembleEffectFeatures,
16
+ computeFeatureEffects,
17
+ foldsNow,
18
+ selfEffectsOf
19
+ } from "../chunk-TULQ4FFX.js";
20
+ import "../chunk-TOM66P2P.js";
21
+ import "../chunk-KU3YLF6D.js";
22
+ import {
23
+ featPickSites,
24
+ poolMemberSitesOf
25
+ } from "../chunk-HTYMW5CH.js";
8
26
  import {
9
27
  resourceLevelFor
10
- } from "../chunk-4ISR76DH.js";
28
+ } from "../chunk-KSTV7J2U.js";
11
29
  import {
12
30
  computeSpellLimits,
13
31
  deriveSpellSlots,
14
32
  effectiveSpellcastingAbility,
15
33
  resolveSpellcasting
16
34
  } from "../chunk-DPUJDOKV.js";
17
- import "../chunk-O4SRD3J5.js";
18
- import "../chunk-PP2UHLBA.js";
19
35
  import {
20
- diceColumnAt,
21
- unarmedDieColumnFor
22
- } from "../chunk-IUAAXXNO.js";
23
- import "../chunk-YHYTW5QA.js";
24
- import "../chunk-3HX5VLWP.js";
25
- import "../chunk-PVCEA4HZ.js";
36
+ legacyAsiBranch
37
+ } from "../chunk-LBEXLN6I.js";
26
38
  import {
27
39
  toDefenseSlug
28
40
  } from "../chunk-XJ2F2WO6.js";
@@ -31,31 +43,38 @@ import {
31
43
  computeAppliedBonuses,
32
44
  computeSlotsAndAttacks,
33
45
  emptyAppliedBonuses
34
- } from "../chunk-V373TRJE.js";
35
- import "../chunk-UIRMA5KM.js";
36
- import "../chunk-UBBKSYBY.js";
37
- import {
38
- assembleEffectFeatures,
39
- computeFeatureEffects,
40
- foldsNow,
41
- selfEffectsOf
42
- } from "../chunk-CBEKVAX4.js";
43
- import "../chunk-TOM66P2P.js";
44
- import "../chunk-KU3YLF6D.js";
46
+ } from "../chunk-JSM6JFZR.js";
47
+ import "../chunk-3LWMFYKS.js";
48
+ import "../chunk-YDGMBMYI.js";
49
+ import "../chunk-EJP263OP.js";
45
50
  import "../chunk-RLGQ5PZZ.js";
46
- import "../chunk-LWFTHJIE.js";
47
- import "../chunk-DNAJRMNN.js";
48
- import "../chunk-LVQLWRCU.js";
49
- import "../chunk-WXWPK3LI.js";
50
- import "../chunk-6X4KUDMU.js";
51
+ import "../chunk-3VZZDKRA.js";
52
+ import "../chunk-W6GC6OKK.js";
53
+ import "../chunk-B3DP42OM.js";
54
+ import {
55
+ diceColumnAt,
56
+ unarmedDieColumnFor
57
+ } from "../chunk-IUAAXXNO.js";
58
+ import "../chunk-YHYTW5QA.js";
59
+ import "../chunk-VRV3NNTA.js";
60
+ import "../chunk-PVCEA4HZ.js";
61
+ import "../chunk-IHE6KVC3.js";
62
+ import "../chunk-HHBD4SQ6.js";
63
+ import "../chunk-A54HHCWW.js";
64
+ import "../chunk-LHZXYFBU.js";
51
65
  import "../chunk-YBLDE5CG.js";
66
+ import "../chunk-ZUQW5VBZ.js";
67
+ import "../chunk-LVQLWRCU.js";
68
+ import "../chunk-CM5CWO4K.js";
52
69
  import {
53
- evaluateMaxFormula,
54
- isValidMaxFormula
55
- } from "../chunk-EVMUJYUD.js";
70
+ resolveAmountText
71
+ } from "../chunk-QH36K2PU.js";
72
+ import "../chunk-EVMUJYUD.js";
56
73
  import "../chunk-VTTA2ALZ.js";
57
- import "../chunk-XY6X2APM.js";
74
+ import "../chunk-ZCTUYGNV.js";
75
+ import "../chunk-7Q2VPKCD.js";
58
76
  import "../chunk-ZDAEGJH4.js";
77
+ import "../chunk-3TM34RSJ.js";
59
78
  import {
60
79
  abilityModifier,
61
80
  attackBonus,
@@ -124,13 +143,11 @@ function collectClassAsiBranch(resolved) {
124
143
  var _a;
125
144
  const out = {};
126
145
  for (const c of resolved.classes) {
127
- for (const [, choice] of Object.entries(c.choices)) {
128
- const block = choice;
129
- if (typeof (block == null ? void 0 : block.feat) === "string") continue;
130
- const asi = block == null ? void 0 : block.asi;
131
- if (!asi) continue;
146
+ for (const choice of Object.values(c.choices)) {
147
+ const alloc = legacyAsiBranch(choice);
148
+ if (!alloc) continue;
132
149
  for (const ab of ABILITY_KEYS) {
133
- const v = asi[ab];
150
+ const v = alloc[ab];
134
151
  if (typeof v === "number") out[ab] = ((_a = out[ab]) != null ? _a : 0) + v;
135
152
  }
136
153
  }
@@ -190,14 +207,9 @@ function hpLevelCount(classes) {
190
207
  function multiclassMaxHP(classes, conMod) {
191
208
  return Math.max(1, hitDiceAverageSum(classes) + conMod * hpLevelCount(classes));
192
209
  }
193
- function resolveRiderAmount(amount, bindings) {
194
- if (!amount.includes("{")) return amount;
195
- const formula = amount.replace(/\{prof_bonus\}/g, "{prof}");
196
- if (!isValidMaxFormula(formula)) return amount;
197
- return String(evaluateMaxFormula(formula, bindings));
198
- }
199
210
  function resolveDamageRider(rider, rowDamageType, bindings) {
200
- const out = { ...rider, amount: resolveRiderAmount(rider.amount, bindings) };
211
+ const { owner, ...rest } = rider;
212
+ const out = { ...rest, amount: resolveAmountText(rider.amount, bindings(owner)) };
201
213
  if (rider.damage_type !== void 0 && !isChosenDamageType(rider.damage_type)) {
202
214
  const resolved = isCanonicalDamageType(rider.damage_type) ? rider.damage_type : rowDamageType;
203
215
  if (resolved) out.damage_type = resolved;
@@ -205,6 +217,24 @@ function resolveDamageRider(rider, rowDamageType, bindings) {
205
217
  }
206
218
  return out;
207
219
  }
220
+ function riderReachesRow(rider, row) {
221
+ var _a;
222
+ if (!((_a = rider.scope) == null ? void 0 : _a.length)) return true;
223
+ return rider.scope.some((word) => {
224
+ switch (word) {
225
+ case "weapon":
226
+ return true;
227
+ case "unarmed":
228
+ return row.unarmed === true;
229
+ case "melee":
230
+ case "ranged":
231
+ return row.weaponCategory === word;
232
+ case "finesse":
233
+ case "thrown":
234
+ return row.properties.includes(word);
235
+ }
236
+ });
237
+ }
208
238
  function unarmoredAC(resolved, mods, warnings) {
209
239
  return unarmoredACBreakdown(resolved, mods, warnings).total;
210
240
  }
@@ -333,17 +363,17 @@ function collectClassFeatAbilityPoints(resolved) {
333
363
  const stripRef = (ref) => ref.replace(/^\[\[/, "").replace(/\]\]$/, "");
334
364
  const featBySlug = /* @__PURE__ */ new Map();
335
365
  for (const f of resolved.feats) featBySlug.set(f.slug, f);
336
- for (const c of resolved.classes) {
337
- for (const atLevel of Object.values(c.choices)) {
338
- const block = atLevel;
339
- if (!block) continue;
340
- const featRef = block.feat;
341
- if (typeof featRef !== "string") continue;
342
- const feat = featBySlug.get(stripRef(featRef));
366
+ const sites = featPickSites(resolved.classes, poolMemberSitesOf(resolved), (ci) => {
367
+ var _a2, _b2, _c, _d;
368
+ return (_d = (_c = (_b2 = (_a2 = resolved.classes) == null ? void 0 : _a2[ci]) == null ? void 0 : _b2.entity) == null ? void 0 : _c.slug) != null ? _d : null;
369
+ });
370
+ for (const site of sites) {
371
+ {
372
+ const feat = featBySlug.get(stripRef(site.slug));
343
373
  if (!feat) continue;
344
374
  for (const ch of (_a = feat.choices) != null ? _a : []) {
345
375
  if (ch.kind !== "ability-points") continue;
346
- const raw = block[`feat:${ch.id}`];
376
+ const raw = site.read(ch.id);
347
377
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
348
378
  let left = ch.points;
349
379
  for (const ab of ABILITY_KEYS) {
@@ -519,7 +549,18 @@ function recalc(resolved, registry) {
519
549
  const overrides = (_a = resolved.definition.overrides) != null ? _a : {};
520
550
  const chosenProfs = collectChosenProficiencies(resolved);
521
551
  const { features: effectFeatures, activeBuffs } = assembleEffectFeatures(resolved);
522
- const featureEffects = computeFeatureEffects(effectFeatures, { activeBuffs, levelFor: (src) => resourceLevelFor(src, resolved) });
552
+ const tableDiceFor = (src, column, level) => {
553
+ var _a2;
554
+ const cls = src.kind === "class" ? resolved.classes.find((c) => {
555
+ var _a3;
556
+ return ((_a3 = c.entity) == null ? void 0 : _a3.slug) === src.slug;
557
+ }) : src.kind === "subclass" ? resolved.classes.find((c) => {
558
+ var _a3;
559
+ return ((_a3 = c.subclass) == null ? void 0 : _a3.slug) === src.slug;
560
+ }) : void 0;
561
+ return cls ? diceColumnAt((_a2 = cls.entity) == null ? void 0 : _a2.table, level, column) : null;
562
+ };
563
+ const featureEffects = computeFeatureEffects(effectFeatures, { activeBuffs, levelFor: (src) => resourceLevelFor(src, resolved), tableDiceFor });
523
564
  const profsForApply = computeProficiencies(resolved);
524
565
  for (const t of chosenProfs.tools) {
525
566
  if (!profsForApply.tools.specific.includes(t)) profsForApply.tools.specific.push(t);
@@ -593,17 +634,30 @@ function recalc(resolved, registry) {
593
634
  for (const ab of chosenProfs.saves) saveProfs.add(ab);
594
635
  const saves = {};
595
636
  const saveBreakdowns = {};
637
+ const activeSaveBonusTerms = featureEffects.save_bonus_terms.filter((t) => {
638
+ var _a2;
639
+ return t.inactiveWhile === "incapacitated" ? !conditionEffects.actions_disabled : t.inactiveWhile === "unconscious" ? !((_a2 = resolved.state.conditions) != null ? _a2 : []).includes("unconscious") : true;
640
+ });
596
641
  for (const ab of ABILITY_KEYS) {
597
642
  const override = (_f = overrides.saves) == null ? void 0 : _f[ab];
598
643
  const prof = (_g = override == null ? void 0 : override.proficient) != null ? _g : saveProfs.has(ab);
599
- const derivedBonus = savingThrow(scores[ab], prof, proficiencyBonus) + applied.save_bonus + conditionEffects.d20_test_penalty;
644
+ const featureTerms = [];
645
+ for (const t of activeSaveBonusTerms) {
646
+ if (t.saves.length > 0 && !t.saves.includes(ab)) continue;
647
+ const amount = Math.max(t.minimum, mods[t.ability]);
648
+ const prior = featureTerms.find((x) => x.source === t.label);
649
+ if (prior === void 0) featureTerms.push({ source: t.label, amount });
650
+ else if (amount > prior.amount) prior.amount = amount;
651
+ }
652
+ const derivedBonus = savingThrow(scores[ab], prof, proficiencyBonus) + applied.save_bonus + featureTerms.reduce((sum, t) => sum + t.amount, 0) + conditionEffects.d20_test_penalty;
600
653
  const bonus = (_h = override == null ? void 0 : override.bonus) != null ? _h : derivedBonus;
601
654
  saves[ab] = { bonus, proficient: prof };
602
655
  saveBreakdowns[ab] = [
603
656
  { source: ab.toUpperCase(), amount: mods[ab] },
604
657
  ...prof ? [{ source: "Proficiency", amount: proficiencyBonus }] : [],
605
- ...applied.save_bonus ? [{ source: "Equipment", amount: applied.save_bonus }] : [],
606
- ...conditionEffects.d20_test_penalty ? [{ source: "Conditions", amount: conditionEffects.d20_test_penalty }] : []
658
+ ...applied.save_terms.map((t) => ({ ...t })),
659
+ ...featureTerms,
660
+ ...conditionEffects.d20_test_penalty ? [{ source: `Exhaustion ${conditionEffects.exhaustion_level}`, amount: conditionEffects.d20_test_penalty }] : []
607
661
  ];
608
662
  }
609
663
  const profSet = /* @__PURE__ */ new Set([
@@ -634,7 +688,8 @@ function recalc(resolved, registry) {
634
688
  skills[skillKey] = {
635
689
  bonus,
636
690
  proficiency: tri,
637
- ability: ab
691
+ ability: ab,
692
+ ...halfProfBest ? { halfProficiency: { source: halfProfBest.source, amount: halfProfBest.amount } } : {}
638
693
  };
639
694
  }
640
695
  const passives = {
@@ -808,18 +863,7 @@ function recalc(resolved, registry) {
808
863
  ))
809
864
  };
810
865
  const attackRows = [...(_U = derivedEquipment == null ? void 0 : derivedEquipment.attacks) != null ? _U : [], buildUnarmedRow(mods, proficiencyBonus, resolveUnarmedStrike(resolved))];
811
- const riderBindings = {
812
- level: totalLevel,
813
- class_level: totalLevel,
814
- prof: proficiencyBonus,
815
- str_mod: mods.str,
816
- dex_mod: mods.dex,
817
- con_mod: mods.con,
818
- int_mod: mods.int,
819
- wis_mod: mods.wis,
820
- cha_mod: mods.cha,
821
- columns: {}
822
- };
866
+ const riderBindings = (owner) => amountBindingsFor(owner, resolved, { proficiencyBonus, mods, spellcastingClasses });
823
867
  return {
824
868
  totalLevel,
825
869
  proficiencyBonus,
@@ -862,7 +906,7 @@ function recalc(resolved, registry) {
862
906
  // attackNotes: reroll-damage / attack-rule captions, only when non-empty.
863
907
  attacks: attackRows.map((a) => {
864
908
  var _a2;
865
- const riders = [...(_a2 = a.damageRiders) != null ? _a2 : [], ...featureEffects.damageBonuses].map((r) => resolveDamageRider(r, a.damageType, riderBindings));
909
+ const riders = [...(_a2 = a.damageRiders) != null ? _a2 : [], ...featureEffects.damageBonuses.filter((r) => riderReachesRow(r, a))].map((r) => resolveDamageRider(r, a.damageType, riderBindings));
866
910
  return {
867
911
  ...a,
868
912
  toHit: a.toHit + conditionEffects.d20_test_penalty,
@@ -895,6 +939,7 @@ export {
895
939
  phbAverageForDie,
896
940
  recalc,
897
941
  resolveUnarmedStrike,
942
+ riderReachesRow,
898
943
  speedFromRace,
899
944
  unarmoredAC,
900
945
  unarmoredACBreakdown
@@ -4,6 +4,7 @@ import type { BackgroundEntity } from "@archivist-gg/dnd5e/background/background
4
4
  import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
5
5
  import type { Ability } from "@archivist-gg/dnd5e";
6
6
  import type { Character, ChoiceValue, ResolvedCharacter, ResolvedClass, ResolvedFeature, ResolvedSpell, FeatVia } from "./pc.types.js";
7
+ import { type PoolMemberSite } from "./pc.member-choices.js";
7
8
  export interface ResolveResult {
8
9
  character: ResolvedCharacter;
9
10
  warnings: string[];
@@ -126,7 +127,7 @@ export declare function collectChosenGrantedFeatures(character: Character, class
126
127
  getByTypeAndSlug(type: string, slug: string): {
127
128
  data: Record<string, unknown>;
128
129
  } | undefined;
129
- }, race?: RaceEntity | null, background?: BackgroundEntity | null): ResolvedFeature[];
130
+ }, race?: RaceEntity | null, background?: BackgroundEntity | null, memberSites?: PoolMemberSite[]): ResolvedFeature[];
130
131
  /**
131
132
  * `character.additional_features` → ResolvedFeatures (the DM-grant path).
132
133
  *
@@ -10,28 +10,36 @@ import {
10
10
  dedupeResolvedSpells,
11
11
  resolveOriginFeat,
12
12
  stripSlug
13
- } from "../chunk-2INMRR3Q.js";
14
- import "../chunk-4ISR76DH.js";
13
+ } from "../chunk-ONTGZR5T.js";
14
+ import "../chunk-2LULMQTF.js";
15
+ import "../chunk-H5PTKYXL.js";
16
+ import "../chunk-TULQ4FFX.js";
17
+ import "../chunk-TOM66P2P.js";
18
+ import "../chunk-KU3YLF6D.js";
19
+ import "../chunk-HTYMW5CH.js";
20
+ import "../chunk-KSTV7J2U.js";
15
21
  import "../chunk-DPUJDOKV.js";
16
- import "../chunk-O4SRD3J5.js";
17
- import "../chunk-PP2UHLBA.js";
22
+ import "../chunk-LBEXLN6I.js";
23
+ import "../chunk-RLGQ5PZZ.js";
24
+ import "../chunk-3VZZDKRA.js";
25
+ import "../chunk-W6GC6OKK.js";
26
+ import "../chunk-B3DP42OM.js";
18
27
  import "../chunk-IUAAXXNO.js";
19
28
  import "../chunk-YHYTW5QA.js";
20
- import "../chunk-3HX5VLWP.js";
29
+ import "../chunk-VRV3NNTA.js";
21
30
  import "../chunk-PVCEA4HZ.js";
22
- import "../chunk-UBBKSYBY.js";
23
- import "../chunk-CBEKVAX4.js";
24
- import "../chunk-TOM66P2P.js";
25
- import "../chunk-KU3YLF6D.js";
26
- import "../chunk-RLGQ5PZZ.js";
27
- import "../chunk-LVQLWRCU.js";
28
- import "../chunk-WXWPK3LI.js";
29
- import "../chunk-6X4KUDMU.js";
31
+ import "../chunk-IHE6KVC3.js";
32
+ import "../chunk-LHZXYFBU.js";
30
33
  import "../chunk-YBLDE5CG.js";
34
+ import "../chunk-ZUQW5VBZ.js";
35
+ import "../chunk-LVQLWRCU.js";
36
+ import "../chunk-CM5CWO4K.js";
31
37
  import "../chunk-EVMUJYUD.js";
32
38
  import "../chunk-VTTA2ALZ.js";
33
- import "../chunk-XY6X2APM.js";
39
+ import "../chunk-ZCTUYGNV.js";
40
+ import "../chunk-7Q2VPKCD.js";
34
41
  import "../chunk-ZDAEGJH4.js";
42
+ import "../chunk-3TM34RSJ.js";
35
43
  import "../chunk-PDJSUH24.js";
36
44
  import "../chunk-WELIKLZF.js";
37
45
  import "../chunk-4U55VNC7.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resourceLevelFor
3
- } from "../chunk-4ISR76DH.js";
3
+ } from "../chunk-KSTV7J2U.js";
4
4
  import "../chunk-DPUJDOKV.js";
5
5
  import {
6
6
  numericColumnsAt
@@ -1,4 +1,4 @@
1
- import type { FeatureSource, ResolvedCharacter, ResolvedFeature, ResolvedPool, DerivedStats } from "./pc.types.js";
1
+ import type { FeatureSource, ResolvedCharacter, ResolvedFeature, ResolvedPool, ResolvedPoolEntry, DerivedStats } from "./pc.types.js";
2
2
  import type { ResourceRecovery, ResourceDie, ResourceScaleStep, ResetTrigger } from "../types/resource.js";
3
3
  /** The level a resource granted via `source` scales against (R4-G4 §6.2.4, ONE derivation): the
4
4
  * character's level in the granting class; for a `subclass` source the level in the class that OWNS
@@ -80,6 +80,11 @@ export declare function resolveRecovery(entry: ResourceRecovery): ResolvedRecove
80
80
  * max-of-maxes merge). Reads the features array ONLY. `name` falls back to the owning feature's name,
81
81
  * the rule `findResourceById` carried, for resources synthesised from older fixtures that omit it. */
82
82
  export declare function resolveFeatureResources(features: ReadonlyArray<ResolvedFeature>): ResourceIndex;
83
+ /** The resource id a pool pick's own tracker uses (spec §5.2): a repeatable copy keys by its pick key, every other pick by its slug.
84
+ * A repeatable (non-item-bound) copy keys its tracker by its KEY, so two copies are two trackers; `param != null` keeps a cast
85
+ * fixture without the field on the slug. ONE rule for both sides: dnd5e seeds by it and the plugin's pick tracker reads by it
86
+ * (ART-c1, R-3 c). */
87
+ export declare function pickResourceId(entry: Pick<ResolvedPoolEntry, "slug" | "key" | "param">): string;
83
88
  /** The full index: the feature resources (`resolveFeatureResources`) plus the pool picks' own
84
89
  * `uses` (R4-G4 §12, LANDED at T7b). A pure function of `resolved.features` and `resolved.pools`,
85
90
  * each guarded `?? []` because the cast fixtures behind the rest suites in both repos carry
@@ -1,10 +1,11 @@
1
1
  import {
2
+ pickResourceId,
2
3
  poolSaveDC,
3
4
  resolveFeatureResources,
4
5
  resolveRecovery,
5
6
  resolveResourceIndex,
6
7
  resourceLevelFor
7
- } from "../chunk-4ISR76DH.js";
8
+ } from "../chunk-KSTV7J2U.js";
8
9
  import "../chunk-DPUJDOKV.js";
9
10
  import "../chunk-IUAAXXNO.js";
10
11
  import "../chunk-LVQLWRCU.js";
@@ -13,6 +14,7 @@ import "../chunk-VTTA2ALZ.js";
13
14
  import "../chunk-PDJSUH24.js";
14
15
  import "../chunk-WELIKLZF.js";
15
16
  export {
17
+ pickResourceId,
16
18
  poolSaveDC,
17
19
  resolveFeatureResources,
18
20
  resolveRecovery,
@@ -1,5 +1,6 @@
1
1
  import type { EntityRegistry } from "@archivist-gg/core";
2
- import type { Character, DerivedStats, ResolvedCharacter } from "./pc.types.js";
2
+ import type { ResetTrigger } from "../types/resource.js";
3
+ import type { Character, DerivedStats, EquipmentEntryState, ResolvedCharacter } from "./pc.types.js";
3
4
  export type RestType = "short" | "long";
4
5
  export type RestCategoryId = "hp-to-max" | "hd-regain" | "spell-slots" | "pact-slots" | "exhaustion" | "hp-modifier-reset" | `feature:${string}` | `item:${number}`
5
6
  /** R4-G5 §4.4.2: END an active buff whose carrier declares a structured `duration`. The tail is the STORED
@@ -15,6 +16,14 @@ export interface RestCategory {
15
16
  /** R4-G4 §7.2.2: a PARTIAL restore from a `recovery[]` entry of kind `uses` and flavour `rest` (N uses, or "all"),
16
17
  * emitted only when the resource's own `reset` does not already fire at this rest. Absent = the own reset (to 0). */
17
18
  restore?: number | "all";
19
+ /** ART-c1 Task 9c (S-4, controller ruling 10): an `item:` category's recharge, the amount its rule restores ("1d6+1",
20
+ * "3", "all") and the charges before the rest. The sheet's rest dialog rolls a DICE amount once when it opens and the
21
+ * rest applies `min(max, current + n)`; this plan stays pure and rolls nothing. */
22
+ recharge?: {
23
+ amount: string;
24
+ current: number;
25
+ max: number;
26
+ };
18
27
  }
19
28
  export interface RestPlan {
20
29
  type: RestType;
@@ -29,4 +38,15 @@ export interface RestPlan {
29
38
  targetUsed: number;
30
39
  }>;
31
40
  }
41
+ /** The persisted item-charge recovery vocabulary (`pc.schema.ts` `equipmentEntryStateSchema.recovery.reset`). */
42
+ export type ItemRecoveryReset = NonNullable<EquipmentEntryState["recovery"]>["reset"];
43
+ /** Every reset a counter can carry: a feature resource's `ResetTrigger` or an item's recovery reset. The two
44
+ * vocabularies share only `dawn`, which means the same thing in both. */
45
+ export type AnyReset = ResetTrigger | ItemRecoveryReset;
46
+ /** The earliest rest that restores `reset` in full, or `null` when none does. A value outside both vocabularies (raw
47
+ * note data reaches here unvalidated) is restored by no rest: an OWN-property lookup, so a prototype key such as
48
+ * `constructor` is not a reset either. */
49
+ export declare function earliestRestoringRest(reset: AnyReset): RestType | null;
50
+ /** Whether a rest of `type` restores `reset` in full: the earliest rest that restores it is no longer than `type`. */
51
+ export declare function restRestores(type: RestType, reset: AnyReset): boolean;
32
52
  export declare function computeRestPlan(character: Character, resolved: ResolvedCharacter, derived: DerivedStats, registry: EntityRegistry | null, type: RestType): RestPlan;
@@ -1,11 +1,23 @@
1
1
  import {
2
2
  resolveResourceIndex
3
- } from "../chunk-4ISR76DH.js";
3
+ } from "../chunk-KSTV7J2U.js";
4
4
  import "../chunk-DPUJDOKV.js";
5
+ import {
6
+ effectiveItemCharges,
7
+ effectiveItemRecovery
8
+ } from "../chunk-3VZZDKRA.js";
9
+ import "../chunk-W6GC6OKK.js";
10
+ import "../chunk-B3DP42OM.js";
5
11
  import "../chunk-IUAAXXNO.js";
12
+ import "../chunk-IHE6KVC3.js";
13
+ import "../chunk-LHZXYFBU.js";
14
+ import "../chunk-ZUQW5VBZ.js";
6
15
  import "../chunk-LVQLWRCU.js";
16
+ import "../chunk-CM5CWO4K.js";
7
17
  import "../chunk-EVMUJYUD.js";
8
18
  import "../chunk-VTTA2ALZ.js";
19
+ import "../chunk-ZCTUYGNV.js";
20
+ import "../chunk-3TM34RSJ.js";
9
21
  import "../chunk-PDJSUH24.js";
10
22
  import "../chunk-WELIKLZF.js";
11
23
 
@@ -17,18 +29,35 @@ function resolveItemName(entry, registry) {
17
29
  const slug = ref ? ref[1] : entry.item;
18
30
  return (_a = registry.getBySlug(slug)) == null ? void 0 : _a.name;
19
31
  }
20
- var FIRES_AT = {
21
- long: /* @__PURE__ */ new Set(["short-rest", "long-rest", "either", "dawn", "dusk"]),
22
- short: /* @__PURE__ */ new Set(["short-rest", "either"])
32
+ var RESTORED_BY = {
33
+ "short-rest": "short",
34
+ either: "short",
35
+ short: "short",
36
+ "long-rest": "long",
37
+ long: "long",
38
+ dawn: "long",
39
+ dusk: "long",
40
+ turn: null,
41
+ round: null,
42
+ custom: null,
43
+ special: null
23
44
  };
45
+ var REST_SPAN = { short: 1, long: 2 };
46
+ function earliestRestoringRest(reset) {
47
+ return Object.prototype.hasOwnProperty.call(RESTORED_BY, reset) ? RESTORED_BY[reset] : null;
48
+ }
49
+ function restRestores(type, reset) {
50
+ const earliest = earliestRestoringRest(reset);
51
+ return earliest !== null && REST_SPAN[earliest] <= REST_SPAN[type];
52
+ }
24
53
  function pushPartialRecoveries(cats, character, index, type) {
25
54
  var _a, _b;
26
55
  for (const [key, fu] of Object.entries((_a = character.state.feature_uses) != null ? _a : {})) {
27
56
  if (fu.used <= 0) continue;
28
57
  const res = index.get(key);
29
58
  if (!((_b = res == null ? void 0 : res.recovery) == null ? void 0 : _b.length)) continue;
30
- if (FIRES_AT[type].has(res.reset)) continue;
31
- const entry = res.recovery.find((r) => r.kind === "uses" && r.flavour === "rest" && FIRES_AT[type].has(r.entry.reset));
59
+ if (restRestores(type, res.reset)) continue;
60
+ const entry = res.recovery.find((r) => r.kind === "uses" && r.flavour === "rest" && restRestores(type, r.entry.reset));
32
61
  if (!entry) continue;
33
62
  const amount = entry.entry.amount;
34
63
  const restore = amount === "all" ? "all" : typeof amount === "number" ? amount : Number(amount);
@@ -132,8 +161,7 @@ function computeRestPlan(character, resolved, derived, registry, type) {
132
161
  const bankedRolls = banked ? banked.filter((v) => v > 0).length : 0;
133
162
  if (fu.used <= 0 && bankedRolls <= 0) continue;
134
163
  const res = index.get(key);
135
- const reset = (_h = res == null ? void 0 : res.reset) != null ? _h : "long-rest";
136
- if (reset !== "short-rest" && reset !== "long-rest" && reset !== "either" && reset !== "dawn" && reset !== "dusk") continue;
164
+ if (!restRestores("long", (_h = res == null ? void 0 : res.reset) != null ? _h : "long-rest")) continue;
137
165
  const rollsNote = bankedRolls > 0 ? ` \xB7 ${bankedRolls} roll${bankedRolls === 1 ? "" : "s"} cleared` : "";
138
166
  cats.push({
139
167
  id: `feature:${key}`,
@@ -144,16 +172,18 @@ function computeRestPlan(character, resolved, derived, registry, type) {
144
172
  pushPartialRecoveries(cats, character, index, "long");
145
173
  character.equipment.forEach((entry, idx) => {
146
174
  var _a2, _b2, _c2, _d2, _e2;
147
- const rec = (_a2 = entry.state) == null ? void 0 : _a2.recovery;
148
- const charges = (_b2 = entry.state) == null ? void 0 : _b2.charges;
175
+ const view = (_b2 = (_a2 = resolved.infusions) == null ? void 0 : _a2.views.get(idx)) != null ? _b2 : null;
176
+ const rec = effectiveItemRecovery(entry, registry, view);
177
+ const charges = effectiveItemCharges(entry, registry, view);
149
178
  if (!rec || !charges) return;
150
179
  if (charges.current >= charges.max) return;
151
- if (rec.reset !== "short" && rec.reset !== "long" && rec.reset !== "dawn") return;
180
+ if (!restRestores("long", rec.reset)) return;
152
181
  const label = (_e2 = (_d2 = (_c2 = entry.overrides) == null ? void 0 : _c2.name) != null ? _d2 : resolveItemName(entry, registry)) != null ? _e2 : entry.item;
153
182
  cats.push({
154
183
  id: `item:${idx}`,
155
184
  label,
156
- preview: `${charges.current} \u2192 ${charges.max}`
185
+ preview: `${charges.current} \u2192 ${charges.max}`,
186
+ recharge: { amount: rec.amount, current: charges.current, max: charges.max }
157
187
  });
158
188
  });
159
189
  }
@@ -163,8 +193,7 @@ function computeRestPlan(character, resolved, derived, registry, type) {
163
193
  const bankedRolls = banked ? banked.filter((v) => v > 0).length : 0;
164
194
  if (fu.used <= 0 && bankedRolls <= 0) continue;
165
195
  const res = index.get(key);
166
- const r = (_l = res == null ? void 0 : res.reset) != null ? _l : "long-rest";
167
- if (r !== "short-rest" && r !== "either") continue;
196
+ if (!restRestores("short", (_l = res == null ? void 0 : res.reset) != null ? _l : "long-rest")) continue;
168
197
  const rollsNote = bankedRolls > 0 ? ` \xB7 ${bankedRolls} roll${bankedRolls === 1 ? "" : "s"} cleared` : "";
169
198
  cats.push({
170
199
  id: `feature:${key}`,
@@ -175,16 +204,18 @@ function computeRestPlan(character, resolved, derived, registry, type) {
175
204
  pushPartialRecoveries(cats, character, index, "short");
176
205
  character.equipment.forEach((entry, idx) => {
177
206
  var _a2, _b2, _c2, _d2, _e2;
178
- const rec = (_a2 = entry.state) == null ? void 0 : _a2.recovery;
179
- const charges = (_b2 = entry.state) == null ? void 0 : _b2.charges;
207
+ const view = (_b2 = (_a2 = resolved.infusions) == null ? void 0 : _a2.views.get(idx)) != null ? _b2 : null;
208
+ const rec = effectiveItemRecovery(entry, registry, view);
209
+ const charges = effectiveItemCharges(entry, registry, view);
180
210
  if (!rec || !charges) return;
181
211
  if (charges.current >= charges.max) return;
182
- if (rec.reset !== "short") return;
212
+ if (!restRestores("short", rec.reset)) return;
183
213
  const label = (_e2 = (_d2 = (_c2 = entry.overrides) == null ? void 0 : _c2.name) != null ? _d2 : resolveItemName(entry, registry)) != null ? _e2 : entry.item;
184
214
  cats.push({
185
215
  id: `item:${idx}`,
186
216
  label,
187
- preview: `${charges.current} \u2192 ${charges.max}`
217
+ preview: `${charges.current} \u2192 ${charges.max}`,
218
+ recharge: { amount: rec.amount, current: charges.current, max: charges.max }
188
219
  });
189
220
  });
190
221
  }
@@ -193,5 +224,7 @@ function computeRestPlan(character, resolved, derived, registry, type) {
193
224
  return { type, categories: cats, hdAvailable, hdRegainDist };
194
225
  }
195
226
  export {
196
- computeRestPlan
227
+ computeRestPlan,
228
+ earliestRestoringRest,
229
+ restRestores
197
230
  };