@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.
- package/dist/background/background.codec.js +4 -4
- package/dist/background/background.parser.js +3 -3
- package/dist/background/background.schema.js +2 -2
- package/dist/{chunk-FFULAF2P.js → chunk-2BWAID3Y.js} +2 -2
- package/dist/chunk-353WXS6S.js +25 -0
- package/dist/{chunk-FUK7QSN5.js → chunk-42Y5IJKT.js} +1 -1
- package/dist/{chunk-TPZSPU4L.js → chunk-4JHOHWBI.js} +1 -1
- package/dist/{chunk-DC74TZNA.js → chunk-4LZJXJJS.js} +7 -2
- package/dist/chunk-5MZSB6OM.js +1089 -0
- package/dist/{chunk-FEOB24KP.js → chunk-73HOFQQ5.js} +1 -1
- package/dist/{chunk-YDPWD2T7.js → chunk-7VJ6BOA5.js} +4 -1
- package/dist/{chunk-ZLG6FQFB.js → chunk-A4WENOUQ.js} +21 -2
- package/dist/{chunk-GEJSJP6E.js → chunk-AIRFC5NQ.js} +3 -1
- package/dist/{chunk-DABBCYTT.js → chunk-CZPMTQOY.js} +1 -1
- package/dist/{chunk-DRNZJNJP.js → chunk-DZXSWSBP.js} +1 -1
- package/dist/{chunk-ADLTSHOR.js → chunk-EMOORSQ7.js} +59 -30
- package/dist/{chunk-RVYYKYFL.js → chunk-GE4TLPWM.js} +1 -1
- package/dist/{chunk-VLKIB33F.js → chunk-K6Q5OUGK.js} +6 -0
- package/dist/{chunk-PMADYMUI.js → chunk-L7E2UT5A.js} +1 -1
- package/dist/{chunk-3TRGRSCH.js → chunk-LV4SNWZQ.js} +7 -1
- package/dist/{chunk-IXZXFFFW.js → chunk-M2EMFD6S.js} +1 -1
- package/dist/{chunk-UC4FE5X3.js → chunk-N6N74K6X.js} +1 -1
- package/dist/{chunk-CDW7R2QT.js → chunk-NXSWH3AE.js} +4 -1
- package/dist/{chunk-IDTDACM6.js → chunk-PHQRGDRQ.js} +1 -1
- package/dist/{chunk-BAXWWGFJ.js → chunk-Q5K6LWBZ.js} +1 -1
- package/dist/{chunk-Z6GXV2GO.js → chunk-TLYDBT5F.js} +1 -1
- package/dist/{chunk-A7T5L7SS.js → chunk-TUIFSVLI.js} +1 -1
- package/dist/{chunk-J2RYSZMQ.js → chunk-VTTA2ALZ.js} +2 -2
- package/dist/{chunk-Z4TL2V7S.js → chunk-VTYUBINW.js} +1 -1
- package/dist/{chunk-B7UXKNLD.js → chunk-W7HWMMBF.js} +1 -1
- package/dist/{chunk-SSXBYF3P.js → chunk-XLSVNUTK.js} +1 -1
- package/dist/{chunk-GIOH5JB5.js → chunk-XTIQWSFM.js} +1 -1
- package/dist/{chunk-PKC77VZP.js → chunk-ZZGEVJKX.js} +1 -1
- package/dist/class/class.codec.js +5 -5
- package/dist/class/class.parser.js +4 -4
- package/dist/class/class.schema.js +3 -3
- package/dist/class/class.slug.d.ts +7 -5
- package/dist/class/class.slug.js +1 -1
- package/dist/entities/base-item-resolver.d.ts +9 -0
- package/dist/entities/base-item-resolver.js +6 -4
- package/dist/entities/slug.d.ts +7 -0
- package/dist/entities/slug.js +3 -1
- package/dist/feat/feat.codec.js +4 -4
- package/dist/feat/feat.parser.js +3 -3
- package/dist/feat/feat.schema.js +2 -2
- package/dist/index.js +4116 -3662
- package/dist/item/item.actions-map.d.ts +18 -10
- package/dist/item/item.actions-map.js +16 -12
- package/dist/item/item.codec.js +3 -3
- package/dist/item/item.parser.js +2 -2
- package/dist/item/item.schema.d.ts +3 -0
- package/dist/item/item.schema.js +1 -1
- package/dist/item/item.types.d.ts +8 -0
- package/dist/pc/pc.decision-engine.d.ts +0 -3
- package/dist/pc/pc.decision-engine.js +8 -3
- package/dist/pc/pc.equipment.js +5 -8
- package/dist/pc/pc.feature-effects.d.ts +5 -0
- package/dist/pc/pc.feature-effects.js +2 -4
- package/dist/pc/pc.parser.js +1 -1
- package/dist/pc/pc.pools.js +8 -3
- package/dist/pc/pc.recalc.d.ts +7 -0
- package/dist/pc/pc.recalc.js +94 -40
- package/dist/pc/pc.resolver.d.ts +59 -1
- package/dist/pc/pc.resolver.js +21 -343
- package/dist/pc/pc.rest.d.ts +1 -1
- package/dist/pc/pc.rest.js +20 -11
- package/dist/pc/pc.schema.d.ts +23 -0
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.slotting.js +3 -3
- package/dist/pc/pc.spellcasting.js +2 -2
- package/dist/pc/pc.types.d.ts +65 -5
- package/dist/race/race.codec.js +5 -5
- package/dist/race/race.parser.js +4 -4
- package/dist/race/race.schema.js +3 -3
- package/dist/schemas/choice-schema.js +1 -1
- package/dist/schemas/feature-schema.js +2 -2
- package/dist/spell/spell.access.js +1 -1
- package/dist/subclass/subclass.codec.js +5 -5
- package/dist/subclass/subclass.parser.js +4 -4
- package/dist/subclass/subclass.schema.js +3 -3
- package/dist/types/choice.d.ts +5 -0
- package/dist/weapon/weapon-mastery.d.ts +3 -0
- package/dist/weapon/weapon.classify.d.ts +21 -0
- package/dist/weapon/weapon.classify.js +7 -0
- package/package.json +1 -1
- package/dist/chunk-6PXE7T7C.js +0 -79
- package/dist/chunk-TJCNX6UZ.js +0 -521
package/dist/pc/pc.resolver.js
CHANGED
|
@@ -1,356 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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-
|
|
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
|
};
|
package/dist/pc/pc.rest.d.ts
CHANGED
|
@@ -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;
|
package/dist/pc/pc.rest.js
CHANGED
|
@@ -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
|
|
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 = (
|
|
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((
|
|
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((
|
|
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 = (
|
|
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: (
|
|
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((
|
|
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 (((
|
|
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: (
|
|
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((
|
|
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 {
|
package/dist/pc/pc.schema.d.ts
CHANGED
|
@@ -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>>;
|
package/dist/pc/pc.schema.js
CHANGED
package/dist/pc/pc.slotting.js
CHANGED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
isShieldArmor,
|
|
7
7
|
isWeaponEntity,
|
|
8
8
|
resolveEntityForEntry
|
|
9
|
-
} from "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
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-
|
|
6
|
+
} from "../chunk-M2EMFD6S.js";
|
|
7
7
|
import "../chunk-5XUXXAQJ.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-VTTA2ALZ.js";
|
|
9
9
|
import "../chunk-NAEPSZAM.js";
|
|
10
10
|
import "../chunk-WP2CX2JO.js";
|
|
11
11
|
export {
|