@archivist-gg/dnd5e 0.1.1 → 0.3.0

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 (87) hide show
  1. package/dist/background/background.codec.js +4 -4
  2. package/dist/background/background.parser.js +3 -3
  3. package/dist/background/background.schema.js +2 -2
  4. package/dist/{chunk-FFULAF2P.js → chunk-2BWAID3Y.js} +2 -2
  5. package/dist/chunk-353WXS6S.js +25 -0
  6. package/dist/{chunk-FUK7QSN5.js → chunk-42Y5IJKT.js} +1 -1
  7. package/dist/{chunk-TPZSPU4L.js → chunk-4JHOHWBI.js} +1 -1
  8. package/dist/{chunk-DC74TZNA.js → chunk-4LZJXJJS.js} +7 -2
  9. package/dist/chunk-5MZSB6OM.js +1089 -0
  10. package/dist/{chunk-FEOB24KP.js → chunk-73HOFQQ5.js} +1 -1
  11. package/dist/{chunk-YDPWD2T7.js → chunk-7VJ6BOA5.js} +4 -1
  12. package/dist/{chunk-ZLG6FQFB.js → chunk-A4WENOUQ.js} +21 -2
  13. package/dist/{chunk-GEJSJP6E.js → chunk-AIRFC5NQ.js} +3 -1
  14. package/dist/{chunk-DABBCYTT.js → chunk-CZPMTQOY.js} +1 -1
  15. package/dist/{chunk-DRNZJNJP.js → chunk-DZXSWSBP.js} +1 -1
  16. package/dist/{chunk-ADLTSHOR.js → chunk-EMOORSQ7.js} +59 -30
  17. package/dist/{chunk-RVYYKYFL.js → chunk-GE4TLPWM.js} +1 -1
  18. package/dist/{chunk-VLKIB33F.js → chunk-K6Q5OUGK.js} +6 -0
  19. package/dist/{chunk-PMADYMUI.js → chunk-L7E2UT5A.js} +1 -1
  20. package/dist/{chunk-3TRGRSCH.js → chunk-LV4SNWZQ.js} +7 -1
  21. package/dist/{chunk-IXZXFFFW.js → chunk-M2EMFD6S.js} +1 -1
  22. package/dist/{chunk-UC4FE5X3.js → chunk-N6N74K6X.js} +1 -1
  23. package/dist/{chunk-CDW7R2QT.js → chunk-NXSWH3AE.js} +4 -1
  24. package/dist/{chunk-IDTDACM6.js → chunk-PHQRGDRQ.js} +1 -1
  25. package/dist/{chunk-BAXWWGFJ.js → chunk-Q5K6LWBZ.js} +1 -1
  26. package/dist/{chunk-Z6GXV2GO.js → chunk-TLYDBT5F.js} +1 -1
  27. package/dist/{chunk-A7T5L7SS.js → chunk-TUIFSVLI.js} +1 -1
  28. package/dist/{chunk-J2RYSZMQ.js → chunk-VTTA2ALZ.js} +2 -2
  29. package/dist/{chunk-Z4TL2V7S.js → chunk-VTYUBINW.js} +1 -1
  30. package/dist/{chunk-B7UXKNLD.js → chunk-W7HWMMBF.js} +1 -1
  31. package/dist/{chunk-SSXBYF3P.js → chunk-XLSVNUTK.js} +1 -1
  32. package/dist/{chunk-GIOH5JB5.js → chunk-XTIQWSFM.js} +1 -1
  33. package/dist/{chunk-PKC77VZP.js → chunk-ZZGEVJKX.js} +1 -1
  34. package/dist/class/class.codec.js +5 -5
  35. package/dist/class/class.parser.js +4 -4
  36. package/dist/class/class.schema.js +3 -3
  37. package/dist/class/class.slug.d.ts +7 -5
  38. package/dist/class/class.slug.js +1 -1
  39. package/dist/entities/base-item-resolver.d.ts +9 -0
  40. package/dist/entities/base-item-resolver.js +6 -4
  41. package/dist/entities/slug.d.ts +7 -0
  42. package/dist/entities/slug.js +3 -1
  43. package/dist/feat/feat.codec.js +4 -4
  44. package/dist/feat/feat.parser.js +3 -3
  45. package/dist/feat/feat.schema.js +2 -2
  46. package/dist/index.js +4116 -3662
  47. package/dist/item/item.actions-map.d.ts +18 -10
  48. package/dist/item/item.actions-map.js +16 -12
  49. package/dist/item/item.codec.js +3 -3
  50. package/dist/item/item.parser.js +2 -2
  51. package/dist/item/item.schema.d.ts +3 -0
  52. package/dist/item/item.schema.js +1 -1
  53. package/dist/item/item.types.d.ts +8 -0
  54. package/dist/pc/pc.decision-engine.d.ts +0 -3
  55. package/dist/pc/pc.decision-engine.js +8 -3
  56. package/dist/pc/pc.equipment.js +5 -8
  57. package/dist/pc/pc.feature-effects.d.ts +5 -0
  58. package/dist/pc/pc.feature-effects.js +2 -4
  59. package/dist/pc/pc.parser.js +1 -1
  60. package/dist/pc/pc.pools.js +8 -3
  61. package/dist/pc/pc.recalc.d.ts +7 -0
  62. package/dist/pc/pc.recalc.js +94 -40
  63. package/dist/pc/pc.resolver.d.ts +59 -1
  64. package/dist/pc/pc.resolver.js +21 -343
  65. package/dist/pc/pc.rest.d.ts +1 -1
  66. package/dist/pc/pc.rest.js +20 -11
  67. package/dist/pc/pc.schema.d.ts +23 -0
  68. package/dist/pc/pc.schema.js +1 -1
  69. package/dist/pc/pc.slotting.js +3 -3
  70. package/dist/pc/pc.spellcasting.js +2 -2
  71. package/dist/pc/pc.types.d.ts +65 -5
  72. package/dist/race/race.codec.js +5 -5
  73. package/dist/race/race.parser.js +4 -4
  74. package/dist/race/race.schema.js +3 -3
  75. package/dist/schemas/choice-schema.js +1 -1
  76. package/dist/schemas/feature-schema.js +2 -2
  77. package/dist/spell/spell.access.js +1 -1
  78. package/dist/subclass/subclass.codec.js +5 -5
  79. package/dist/subclass/subclass.parser.js +4 -4
  80. package/dist/subclass/subclass.schema.js +3 -3
  81. package/dist/types/choice.d.ts +5 -0
  82. package/dist/weapon/weapon-mastery.d.ts +3 -0
  83. package/dist/weapon/weapon.classify.d.ts +21 -0
  84. package/dist/weapon/weapon.classify.js +7 -0
  85. package/package.json +1 -1
  86. package/dist/chunk-6PXE7T7C.js +0 -79
  87. package/dist/chunk-TJCNX6UZ.js +0 -521
@@ -1,356 +1,34 @@
1
1
  import {
2
- resolveAllPools
3
- } from "../chunk-6PXE7T7C.js";
4
- import {
5
- normalizeKnownSpell,
6
- resolveSpellcasting
7
- } from "../chunk-IXZXFFFW.js";
8
- import "../chunk-5XUXXAQJ.js";
9
- import {
10
- bareEntitySlug
11
- } from "../chunk-TJCNX6UZ.js";
2
+ PCResolver,
3
+ collectChosenGrantedFeatures,
4
+ collectChosenWeaponMasteries,
5
+ collectFeatGrantedSpells,
6
+ collectFeatSlugs,
7
+ collectItemGrantedSpells,
8
+ collectResolvedFeatures,
9
+ dedupeResolvedSpells,
10
+ resolveOriginFeat,
11
+ stripSlug
12
+ } from "../chunk-5MZSB6OM.js";
12
13
  import "../chunk-BH6AMZVY.js";
14
+ import "../chunk-M2EMFD6S.js";
15
+ import "../chunk-5XUXXAQJ.js";
13
16
  import "../chunk-JEYQU3JT.js";
14
- import "../chunk-J2RYSZMQ.js";
17
+ import "../chunk-N6N74K6X.js";
18
+ import "../chunk-4LZJXJJS.js";
19
+ import "../chunk-LV4SNWZQ.js";
20
+ import "../chunk-VTTA2ALZ.js";
15
21
  import "../chunk-NAEPSZAM.js";
16
22
  import "../chunk-WP2CX2JO.js";
17
-
18
- // src/pc/pc.resolver.ts
19
- var SLUG_RE = /^\[\[(.+?)\]\]$/;
20
- function stripSlug(ref) {
21
- if (!ref) return null;
22
- const m = ref.match(SLUG_RE);
23
- return m ? m[1] : ref;
24
- }
25
- var PCResolver = class {
26
- constructor(entities) {
27
- this.entities = entities;
28
- }
29
- /** Exposed so recalc() can apply equipment bonuses (Pass A / Pass B). */
30
- get registry() {
31
- return this.entities;
32
- }
33
- resolve(character) {
34
- var _a, _b, _c, _d, _e;
35
- const warnings = [];
36
- const lookup = (rawRef, type) => {
37
- const slug = stripSlug(rawRef);
38
- if (!slug) return null;
39
- const reg = this.entities.getByTypeAndSlug(type, slug);
40
- if (!reg) {
41
- warnings.push(`Slug [[${slug}]] not found in compendium as ${type}.`);
42
- return null;
43
- }
44
- const data = reg.data;
45
- return data.slug == null ? { ...data, slug: reg.slug } : data;
46
- };
47
- const race = lookup(character.race, "race");
48
- const background = lookup(character.background, "background");
49
- const classes = character.class.map((c) => ({
50
- entity: lookup(c.name, "class"),
51
- level: c.level,
52
- subclass: lookup(c.subclass, "subclass"),
53
- choices: c.choices
54
- }));
55
- const featSlugs = collectFeatSlugs(character);
56
- const feats = [];
57
- for (const slug of featSlugs) {
58
- const f = lookup(`[[${slug}]]`, "feat");
59
- if (f) feats.push(f);
60
- }
61
- const totalLevel = classes.reduce((sum, c) => sum + c.level, 0);
62
- const features = collectResolvedFeatures(race, classes, background, feats);
63
- const extraFeatures = collectChosenGrantedFeatures(character, classes, this.entities, race, background);
64
- features.push(...extraFeatures);
65
- const primaryCasterSlug = (_a = classes.map((c, i) => c.entity && resolveSpellcasting(c) ? stripSlug(character.class[i].name) : null).find((slug) => slug != null)) != null ? _a : null;
66
- const spells = [];
67
- for (const raw of (_b = character.spells.known) != null ? _b : []) {
68
- const n = normalizeKnownSpell(raw);
69
- const reg = this.entities.getByTypeAndSlug("spell", n.slug);
70
- if (!reg) {
71
- warnings.push(`Spell [[${n.slug}]] not found in compendium.`);
72
- continue;
73
- }
74
- const entity = reg.data;
75
- const isCantrip = ((_c = entity.level) != null ? _c : 0) === 0;
76
- const classSlug = (_d = n.classSlug) != null ? _d : primaryCasterSlug;
77
- const prep = isCantrip || n.alwaysPrepared ? true : (_e = n.preparedFlag) != null ? _e : false;
78
- spells.push({ entity, slug: n.slug, classSlug, source: n.source, prepared: prep, alwaysPrepared: n.alwaysPrepared });
79
- }
80
- const chosenMasteries = collectChosenWeaponMasteries(character);
81
- if (chosenMasteries.full.length > 0) {
82
- const target = features.find(
83
- (rf) => {
84
- var _a2;
85
- return rf.feature.id === "weapon-mastery" || ((_a2 = rf.feature.choices) == null ? void 0 : _a2.some(
86
- (ch) => ch.kind === "select-entity" && ch.id === "weapon-mastery" && ch.entity_type === "weapon"
87
- ));
88
- }
89
- );
90
- if (target) {
91
- const names = chosenMasteries.full.map(
92
- (fullSlug) => {
93
- var _a2, _b2;
94
- return (_b2 = (_a2 = this.entities.getByTypeAndSlug("weapon", fullSlug)) == null ? void 0 : _a2.name) != null ? _b2 : fullSlug;
95
- }
96
- );
97
- const entry = { label: "Mastered weapons", description: names.join(", ") };
98
- target.chosenInline = target.chosenInline ? [...target.chosenInline, entry] : [entry];
99
- }
100
- }
101
- const resolvedCharacter = {
102
- definition: character,
103
- race,
104
- classes,
105
- background,
106
- feats,
107
- totalLevel,
108
- features,
109
- spells,
110
- pools: [],
111
- weaponMasteries: chosenMasteries.bare,
112
- state: character.state
113
- };
114
- resolvedCharacter.pools = resolveAllPools(resolvedCharacter, this.entities);
115
- return { character: resolvedCharacter, warnings };
116
- }
117
- };
118
- function collectChosenWeaponMasteries(character) {
119
- var _a, _b;
120
- const full = /* @__PURE__ */ new Set();
121
- for (const cls of (_a = character.class) != null ? _a : []) {
122
- for (const lvl of Object.values((_b = cls.choices) != null ? _b : {})) {
123
- const pick = lvl["weapon-mastery"];
124
- if (Array.isArray(pick)) {
125
- for (const s of pick) if (typeof s === "string") full.add(s);
126
- }
127
- }
128
- }
129
- return { full: [...full], bare: [...new Set([...full].map(bareEntitySlug))] };
130
- }
131
- function collectFeatSlugs(character) {
132
- const slugs = /* @__PURE__ */ new Set();
133
- for (const c of character.class) {
134
- for (const [, choiceBlock] of Object.entries(c.choices)) {
135
- const feat = choiceBlock == null ? void 0 : choiceBlock.feat;
136
- if (typeof feat === "string") {
137
- const s = stripSlug(feat);
138
- if (s) slugs.add(s);
139
- }
140
- }
141
- }
142
- return [...slugs];
143
- }
144
- function collectChosenGrantedFeatures(character, classes, registry, race = null, background = null) {
145
- var _a, _b;
146
- const out = [];
147
- classes.forEach((c, i) => {
148
- var _a2, _b2, _c, _d;
149
- if (!c.entity) return;
150
- const entity = c.entity;
151
- const entry = character.class[i];
152
- if (!entry) return;
153
- for (const [lvlStr, atLevel] of Object.entries(entry.choices)) {
154
- const lvl = Number(lvlStr);
155
- if (!Number.isFinite(lvl) || lvl > entry.level) continue;
156
- const features = (_b2 = ((_a2 = entity.features_by_level) != null ? _a2 : {})[lvl]) != null ? _b2 : [];
157
- const subFeatures = c.subclass ? (_d = ((_c = c.subclass.features_by_level) != null ? _c : {})[lvl]) != null ? _d : [] : [];
158
- for (const feature of [...features, ...subFeatures]) {
159
- walkChoiceGrants(feature.choices, atLevel, (granted, suppress) => {
160
- out.push({
161
- feature: granted,
162
- source: { kind: "class", slug: entity.slug, level: lvl },
163
- ...suppress ? { renderSuppressed: true } : {}
164
- });
165
- }, registry);
166
- }
167
- }
168
- });
169
- const oc = (_a = character.origin_choices) != null ? _a : {};
170
- const originAt = (ns) => {
171
- const at = {};
172
- for (const [key, val] of Object.entries(oc)) {
173
- if (key.startsWith(`${ns}:`)) at[key.slice(ns.length + 1)] = val;
174
- }
175
- return at;
176
- };
177
- if (race) {
178
- const atRace = originAt("race");
179
- const emitRace = (granted, suppress) => {
180
- out.push({
181
- feature: granted,
182
- source: { kind: "race", slug: race.slug },
183
- ...suppress ? { renderSuppressed: true } : {}
184
- });
185
- };
186
- walkChoiceGrants(race.choices, atRace, emitRace, registry);
187
- for (const trait of (_b = race.traits) != null ? _b : []) {
188
- walkChoiceGrants(trait.choices, atRace, emitRace, registry);
189
- }
190
- }
191
- if (background) {
192
- const atBg = originAt("background");
193
- const emitBg = (granted, suppress) => {
194
- out.push({
195
- feature: granted,
196
- source: { kind: "background", slug: background.slug },
197
- ...suppress ? { renderSuppressed: true } : {}
198
- });
199
- };
200
- walkChoiceGrants(background.choices, atBg, emitBg, registry);
201
- if (background.feature) {
202
- walkChoiceGrants(background.feature.choices, atBg, emitBg, registry);
203
- }
204
- }
205
- return out;
206
- }
207
- function walkChoiceGrants(choices, atLevel, emit, registry) {
208
- var _a, _b, _c, _d, _e;
209
- for (const ch of choices != null ? choices : []) {
210
- const sel = atLevel[ch.id];
211
- if (ch.kind === "select-entity" && ch.entity_type === "optional-feature") {
212
- const slugs = Array.isArray(sel) ? sel : typeof sel === "string" ? [sel] : [];
213
- for (const slug of slugs) {
214
- const reg = registry.getByTypeAndSlug("optional-feature", (_a = stripSlug(String(slug))) != null ? _a : String(slug));
215
- if (!reg) continue;
216
- const d = reg.data;
217
- emit({
218
- id: (_b = d.slug) != null ? _b : String(slug),
219
- name: (_c = d.name) != null ? _c : String(slug),
220
- description: d.description,
221
- effects: d.effects,
222
- ...d.action_cost ? { action: d.action_cost } : {}
223
- });
224
- }
225
- }
226
- if (ch.kind === "select-inline") {
227
- const branch = typeof sel === "string" ? ch.options.find((o) => o.value === sel) : void 0;
228
- if ((_d = branch == null ? void 0 : branch.effects) == null ? void 0 : _d.length) {
229
- const wc = (_e = branch.choices) == null ? void 0 : _e.find(
230
- (c) => c.kind === "select-entity" && c.entity_type === "weapon"
231
- );
232
- const picked = wc ? atLevel == null ? void 0 : atLevel[wc.id] : void 0;
233
- const effects = branch.effects.map(
234
- (e) => e.kind === "weapon-ability" && e.weapons === "chosen" && typeof picked === "string" ? { ...e, weapons: [bareEntitySlug(picked)] } : e
235
- );
236
- emit({ id: `${ch.id}-${branch.value}`, name: branch.label, description: branch.description, effects }, true);
237
- }
238
- if (branch == null ? void 0 : branch.choices) walkChoiceGrants(branch.choices, atLevel, emit, registry);
239
- }
240
- }
241
- }
242
- function resolveChosenInline(feature, atLevel) {
243
- var _a;
244
- if (!atLevel) return void 0;
245
- const picks = [];
246
- for (const ch of (_a = feature.choices) != null ? _a : []) {
247
- if (ch.kind !== "select-inline") continue;
248
- const sel = atLevel[ch.id];
249
- if (typeof sel !== "string") continue;
250
- const opt = ch.options.find((o) => o.value === sel);
251
- if (!opt) continue;
252
- picks.push({ label: opt.label, description: opt.description });
253
- }
254
- return picks.length ? picks : void 0;
255
- }
256
- function isAsiSlotFeature(feature) {
257
- var _a, _b, _c, _d;
258
- return feature.id === "ability-score-improvement" && !((_a = feature.effects) == null ? void 0 : _a.length) && !((_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);
259
- }
260
- function collectResolvedFeatures(race, classes, background, feats) {
261
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
262
- const out = [];
263
- for (const c of classes) {
264
- if (!c.entity) continue;
265
- const slug = c.entity.slug;
266
- const byLevel = (_a = c.entity.features_by_level) != null ? _a : {};
267
- for (const [lvlStr, feats0] of Object.entries(byLevel)) {
268
- const lvl = parseInt(lvlStr, 10);
269
- if (Number.isNaN(lvl) || lvl > c.level) continue;
270
- for (const feat of feats0) {
271
- const chosenInline = resolveChosenInline(feat, (_b = c.choices) == null ? void 0 : _b[lvl]);
272
- out.push({
273
- feature: feat,
274
- source: { kind: "class", slug, level: lvl },
275
- ...chosenInline ? { chosenInline } : {},
276
- ...isAsiSlotFeature(feat) ? { buildOnly: true } : {}
277
- });
278
- }
279
- }
280
- if ((_c = c.entity.resources) == null ? void 0 : _c.length) {
281
- out.push({
282
- feature: { name: c.entity.name, resources: c.entity.resources },
283
- source: { kind: "class", slug, level: 1 }
284
- });
285
- }
286
- if (c.subclass) {
287
- const sSlug = c.subclass.slug;
288
- const sByLevel = (_d = c.subclass.features_by_level) != null ? _d : {};
289
- for (const [lvlStr, feats0] of Object.entries(sByLevel)) {
290
- const lvl = parseInt(lvlStr, 10);
291
- if (Number.isNaN(lvl) || lvl > c.level) continue;
292
- for (const feat of feats0) {
293
- const chosenInline = resolveChosenInline(feat, (_e = c.choices) == null ? void 0 : _e[lvl]);
294
- out.push({
295
- feature: feat,
296
- source: { kind: "subclass", slug: sSlug, level: lvl },
297
- ...chosenInline ? { chosenInline } : {},
298
- ...isAsiSlotFeature(feat) ? { buildOnly: true } : {}
299
- });
300
- }
301
- }
302
- if ((_f = c.subclass.resources) == null ? void 0 : _f.length) {
303
- out.push({
304
- feature: { name: c.subclass.name, resources: c.subclass.resources },
305
- source: { kind: "subclass", slug: sSlug, level: 1 }
306
- });
307
- }
308
- }
309
- }
310
- if (race) {
311
- const traits = (_g = race.traits) != null ? _g : [];
312
- for (const feat of traits) {
313
- out.push({ feature: feat, source: { kind: "race", slug: race.slug } });
314
- }
315
- }
316
- if (background) {
317
- const bgFeature = background.feature;
318
- if (bgFeature) {
319
- out.push({ feature: bgFeature, source: { kind: "background", slug: background.slug } });
320
- }
321
- }
322
- for (const feat of feats) {
323
- const bundled = (_h = feat.features) != null ? _h : [];
324
- const entityEffects = (_i = feat.effects) != null ? _i : [];
325
- if (bundled.length > 0) {
326
- bundled.forEach((f, i) => {
327
- var _a2;
328
- const feature = i === 0 && entityEffects.length > 0 ? { ...f, effects: [...(_a2 = f.effects) != null ? _a2 : [], ...entityEffects] } : f;
329
- out.push({ feature, source: { kind: "feat", slug: feat.slug } });
330
- });
331
- } else {
332
- const name = (_j = feat.name) != null ? _j : feat.slug;
333
- const foldedDesc = [feat.description, ...(_k = feat.benefits) != null ? _k : []].filter(Boolean).join("\n\n") || void 0;
334
- const buildOnly = ((_l = feat.choices) != null ? _l : []).some((c) => c.kind === "ability-points" && c.points >= 2) && !((_m = feat.effects) == null ? void 0 : _m.length) && !((_n = feat.resources) == null ? void 0 : _n.length) && bundled.length === 0;
335
- out.push({
336
- feature: {
337
- name,
338
- ...foldedDesc ? { description: foldedDesc } : {},
339
- ...feat.resources ? { resources: feat.resources } : {},
340
- ...entityEffects.length > 0 ? { effects: entityEffects } : {}
341
- },
342
- source: { kind: "feat", slug: feat.slug },
343
- ...buildOnly ? { buildOnly: true } : {}
344
- });
345
- }
346
- }
347
- return out;
348
- }
349
23
  export {
350
24
  PCResolver,
351
25
  collectChosenGrantedFeatures,
352
26
  collectChosenWeaponMasteries,
27
+ collectFeatGrantedSpells,
353
28
  collectFeatSlugs,
29
+ collectItemGrantedSpells,
354
30
  collectResolvedFeatures,
31
+ dedupeResolvedSpells,
32
+ resolveOriginFeat,
355
33
  stripSlug
356
34
  };
@@ -1,7 +1,7 @@
1
1
  import type { EntityRegistry } from "@archivist-gg/core";
2
2
  import type { Character, DerivedStats, ResolvedCharacter } from "./pc.types.js";
3
3
  export type RestType = "short" | "long";
4
- export type RestCategoryId = "hp-to-max" | "hd-regain" | "spell-slots" | "pact-slots" | "exhaustion" | `feature:${string}` | `item:${number}`;
4
+ export type RestCategoryId = "hp-to-max" | "hd-regain" | "spell-slots" | "pact-slots" | "exhaustion" | "hp-modifier-reset" | `feature:${string}` | `item:${number}`;
5
5
  export interface RestCategory {
6
6
  id: RestCategoryId;
7
7
  label: string;
@@ -16,7 +16,7 @@ function findResourceById(resolved, id) {
16
16
  return void 0;
17
17
  }
18
18
  function computeRestPlan(character, resolved, derived, registry, type) {
19
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
19
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
20
20
  const cats = [];
21
21
  let hdRegainDist;
22
22
  const pact = character.state.spell_slots_pact;
@@ -38,16 +38,25 @@ function computeRestPlan(character, resolved, derived, registry, type) {
38
38
  preview: `${character.state.exhaustion} \u2192 ${character.state.exhaustion - 1}`
39
39
  });
40
40
  }
41
- const slotsUsed = Object.values((_a = character.state.spell_slots) != null ? _a : {}).reduce((s, slot) => {
41
+ const hpModifier = (_b = (_a = character.overrides) == null ? void 0 : _a.hp) == null ? void 0 : _b.modifier;
42
+ if (hpModifier !== void 0) {
43
+ const signed = hpModifier > 0 ? `+${hpModifier}` : `${hpModifier}`;
44
+ cats.push({
45
+ id: "hp-modifier-reset",
46
+ label: "Max HP Modifier",
47
+ preview: `${signed} \u2192 cleared`
48
+ });
49
+ }
50
+ const slotsUsed = Object.values((_c = character.state.spell_slots) != null ? _c : {}).reduce((s, slot) => {
42
51
  var _a2;
43
52
  return s + ((_a2 = slot.used) != null ? _a2 : 0);
44
53
  }, 0);
45
54
  if (slotsUsed > 0) {
46
55
  cats.push({ id: "spell-slots", label: "Spell Slots", preview: "all reset" });
47
56
  }
48
- const totalLevel = (_b = resolved.totalLevel) != null ? _b : 0;
57
+ const totalLevel = (_d = resolved.totalLevel) != null ? _d : 0;
49
58
  const regainBudget = Math.max(1, Math.floor(totalLevel / 2));
50
- const pools = Object.entries((_c = character.state.hit_dice) != null ? _c : {}).map(([die, hd]) => ({ die, used: hd.used, total: hd.total })).filter((p) => p.used > 0).sort((a, b) => b.used - a.used);
59
+ const pools = Object.entries((_e = character.state.hit_dice) != null ? _e : {}).map(([die, hd]) => ({ die, used: hd.used, total: hd.total })).filter((p) => p.used > 0).sort((a, b) => b.used - a.used);
51
60
  if (pools.length > 0) {
52
61
  let left = regainBudget;
53
62
  const dist = [];
@@ -68,14 +77,14 @@ function computeRestPlan(character, resolved, derived, registry, type) {
68
77
  hdRegainDist = dist.map((d) => ({ die: d.die, targetUsed: d.targetUsed }));
69
78
  }
70
79
  }
71
- for (const [key, fu] of Object.entries((_d = character.state.feature_uses) != null ? _d : {})) {
80
+ for (const [key, fu] of Object.entries((_f = character.state.feature_uses) != null ? _f : {})) {
72
81
  if (fu.used <= 0) continue;
73
82
  const res = findResourceById(resolved, key);
74
- const reset = (_e = res == null ? void 0 : res.reset) != null ? _e : "long-rest";
83
+ const reset = (_g = res == null ? void 0 : res.reset) != null ? _g : "long-rest";
75
84
  if (reset !== "short-rest" && reset !== "long-rest" && reset !== "dawn" && reset !== "dusk") continue;
76
85
  cats.push({
77
86
  id: `feature:${key}`,
78
- label: (_f = res == null ? void 0 : res.label) != null ? _f : key,
87
+ label: (_h = res == null ? void 0 : res.label) != null ? _h : key,
79
88
  preview: `${fu.used}/${fu.max} restored`
80
89
  });
81
90
  }
@@ -95,13 +104,13 @@ function computeRestPlan(character, resolved, derived, registry, type) {
95
104
  });
96
105
  }
97
106
  if (type === "short") {
98
- for (const [key, fu] of Object.entries((_g = character.state.feature_uses) != null ? _g : {})) {
107
+ for (const [key, fu] of Object.entries((_i = character.state.feature_uses) != null ? _i : {})) {
99
108
  if (fu.used <= 0) continue;
100
109
  const res = findResourceById(resolved, key);
101
- if (((_h = res == null ? void 0 : res.reset) != null ? _h : "long-rest") !== "short-rest") continue;
110
+ if (((_j = res == null ? void 0 : res.reset) != null ? _j : "long-rest") !== "short-rest") continue;
102
111
  cats.push({
103
112
  id: `feature:${key}`,
104
- label: (_i = res == null ? void 0 : res.label) != null ? _i : key,
113
+ label: (_k = res == null ? void 0 : res.label) != null ? _k : key,
105
114
  preview: `${fu.used}/${fu.max} restored`
106
115
  });
107
116
  }
@@ -120,7 +129,7 @@ function computeRestPlan(character, resolved, derived, registry, type) {
120
129
  });
121
130
  });
122
131
  }
123
- const hdAvailable = type === "short" ? Object.entries((_j = character.state.hit_dice) != null ? _j : {}).filter(([, hd]) => hd.used < hd.total).map(([die, hd]) => ({ die, remaining: hd.total - hd.used })) : [];
132
+ const hdAvailable = type === "short" ? Object.entries((_l = character.state.hit_dice) != null ? _l : {}).filter(([, hd]) => hd.used < hd.total).map(([die, hd]) => ({ die, remaining: hd.total - hd.used })) : [];
124
133
  return { type, categories: cats, hdAvailable, hdRegainDist };
125
134
  }
126
135
  export {
@@ -130,6 +130,19 @@ export declare const characterSchema: z.ZodObject<{
130
130
  special: "special";
131
131
  }>>;
132
132
  range: z.ZodOptional<z.ZodString>;
133
+ resist: z.ZodOptional<z.ZodArray<z.ZodString>>;
134
+ immune: z.ZodOptional<z.ZodArray<z.ZodString>>;
135
+ vulnerable: z.ZodOptional<z.ZodArray<z.ZodString>>;
136
+ condition_immune: z.ZodOptional<z.ZodArray<z.ZodString>>;
137
+ spell: z.ZodOptional<z.ZodString>;
138
+ spell_ability: z.ZodOptional<z.ZodEnum<{
139
+ str: "str";
140
+ dex: "dex";
141
+ con: "con";
142
+ int: "int";
143
+ wis: "wis";
144
+ cha: "cha";
145
+ }>>;
133
146
  }, z.core.$strict>>;
134
147
  state: z.ZodOptional<z.ZodObject<{
135
148
  charges: z.ZodOptional<z.ZodObject<{
@@ -208,6 +221,8 @@ export declare const characterSchema: z.ZodObject<{
208
221
  }, z.core.$strip>>;
209
222
  hp: z.ZodOptional<z.ZodObject<{
210
223
  max: z.ZodOptional<z.ZodNumber>;
224
+ rolled: z.ZodOptional<z.ZodNumber>;
225
+ modifier: z.ZodOptional<z.ZodNumber>;
211
226
  }, z.core.$strip>>;
212
227
  ac: z.ZodOptional<z.ZodNumber>;
213
228
  speed: z.ZodOptional<z.ZodNumber>;
@@ -216,6 +231,14 @@ export declare const characterSchema: z.ZodObject<{
216
231
  saveDC: z.ZodOptional<z.ZodNumber>;
217
232
  attackBonus: z.ZodOptional<z.ZodNumber>;
218
233
  }, z.core.$strip>>;
234
+ spellcasting_ability: z.ZodOptional<z.ZodEnum<{
235
+ str: "str";
236
+ dex: "dex";
237
+ con: "con";
238
+ int: "int";
239
+ wis: "wis";
240
+ cha: "cha";
241
+ }>>;
219
242
  spell_slots: z.ZodOptional<z.ZodRecord<z.ZodCoercedNumber<unknown>, z.ZodNumber>>;
220
243
  attunement_limit: z.ZodOptional<z.ZodNumber>;
221
244
  }, z.core.$strip>>;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  characterSchema
3
- } from "../chunk-ZLG6FQFB.js";
3
+ } from "../chunk-A4WENOUQ.js";
4
4
  import "../chunk-TZK36BU7.js";
5
5
  export {
6
6
  characterSchema
@@ -6,9 +6,9 @@ import {
6
6
  isShieldArmor,
7
7
  isWeaponEntity,
8
8
  resolveEntityForEntry
9
- } from "../chunk-UC4FE5X3.js";
10
- import "../chunk-DC74TZNA.js";
11
- import "../chunk-3TRGRSCH.js";
9
+ } from "../chunk-N6N74K6X.js";
10
+ import "../chunk-4LZJXJJS.js";
11
+ import "../chunk-LV4SNWZQ.js";
12
12
  export {
13
13
  defaultSlotForType,
14
14
  effectiveArmor,
@@ -3,9 +3,9 @@ import {
3
3
  deriveSpellSlots,
4
4
  normalizeKnownSpell,
5
5
  resolveSpellcasting
6
- } from "../chunk-IXZXFFFW.js";
6
+ } from "../chunk-M2EMFD6S.js";
7
7
  import "../chunk-5XUXXAQJ.js";
8
- import "../chunk-J2RYSZMQ.js";
8
+ import "../chunk-VTTA2ALZ.js";
9
9
  import "../chunk-NAEPSZAM.js";
10
10
  import "../chunk-WP2CX2JO.js";
11
11
  export {