@archivist-gg/dnd5e 0.2.0 → 0.3.1
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 +3 -3
- package/dist/background/background.parser.js +2 -2
- package/dist/background/background.schema.d.ts +8 -0
- package/dist/background/background.schema.js +5 -3
- package/dist/chunk-353WXS6S.js +25 -0
- package/dist/{chunk-DC74TZNA.js → chunk-4LZJXJJS.js} +7 -2
- package/dist/{chunk-DZXSWSBP.js → chunk-5ZBE4CWV.js} +1 -1
- package/dist/{chunk-IXZXFFFW.js → chunk-6IRYTM5V.js} +6 -1
- package/dist/chunk-7TEK5KK7.js +49 -0
- package/dist/{chunk-V6SOFUJW.js → chunk-AIRFC5NQ.js} +3 -1
- package/dist/{chunk-VTYUBINW.js → chunk-BIK4DFWK.js} +1 -1
- package/dist/{chunk-TQZB4OCJ.js → chunk-D3CLOBE3.js} +49 -21
- package/dist/{chunk-3TRGRSCH.js → chunk-LV4SNWZQ.js} +7 -1
- package/dist/{chunk-UC4FE5X3.js → chunk-N6N74K6X.js} +1 -1
- package/dist/chunk-O5EYMKFH.js +6 -0
- package/dist/{chunk-TUIFSVLI.js → chunk-SE7AZDR3.js} +1 -0
- package/dist/{chunk-5WQD3WNZ.js → chunk-TN6ZLTNU.js} +6 -5
- package/dist/{chunk-R5SQHP2X.js → chunk-TNUFPIXI.js} +48 -30
- package/dist/{chunk-J2RYSZMQ.js → chunk-VTTA2ALZ.js} +2 -2
- 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/index.js +3902 -3623
- package/dist/item/item.actions-map.d.ts +8 -7
- package/dist/item/item.actions-map.js +3 -4
- package/dist/item/item.ai-schema.d.ts +1 -1
- package/dist/pc/pc.decision-engine.d.ts +13 -3
- package/dist/pc/pc.decision-engine.js +9 -9
- package/dist/pc/pc.equipment.js +6 -12
- package/dist/pc/pc.feature-effects.d.ts +5 -0
- package/dist/pc/pc.feature-effects.js +2 -11
- package/dist/pc/pc.parser.js +1 -1
- package/dist/pc/pc.pools.js +7 -7
- package/dist/pc/pc.proficiencies.d.ts +31 -0
- package/dist/pc/pc.proficiencies.js +96 -23
- package/dist/pc/pc.proficiency-normalize.d.ts +5 -0
- package/dist/pc/pc.proficiency-query.js +5 -1
- package/dist/pc/pc.recalc.d.ts +7 -0
- package/dist/pc/pc.recalc.js +112 -58
- package/dist/pc/pc.resolver.js +7 -7
- package/dist/pc/pc.rest.d.ts +1 -1
- package/dist/pc/pc.rest.js +20 -11
- package/dist/pc/pc.schema.d.ts +10 -4
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.slotting.js +3 -3
- package/dist/pc/pc.spellcasting.d.ts +5 -1
- package/dist/pc/pc.spellcasting.js +4 -2
- package/dist/pc/pc.types.d.ts +30 -4
- package/dist/spell/spell.access.js +1 -1
- package/dist/types/choice.d.ts +5 -0
- package/dist/types/choice.js +9 -3
- 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-BH6AMZVY.js +0 -25
|
@@ -21,14 +21,15 @@ export declare const ITEM_ACTIONS: Record<string, ItemAction>;
|
|
|
21
21
|
* (`srd-5e_wand-of-fireballs`, `srd-2024_wand-of-fireballs`,
|
|
22
22
|
* `homebrew_wand-of-fireballs`).
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* Type-namespaced slugs follow the shape `<prefix>_<entity_type>_<name-slug>`
|
|
25
|
+
* (all kebab-case; slugify never emits `_`), so a slug splits on `_` into
|
|
26
|
+
* exactly 3 parts and the bare name is `parts.slice(2).join("_")`. This is
|
|
27
|
+
* arity-robust: it also recovers the bare name from a legacy 2-part
|
|
28
|
+
* `<prefix>_<name>` slug and an already-bare name. `ITEM_ACTIONS` is keyed by
|
|
29
|
+
* bare name.
|
|
29
30
|
*
|
|
30
|
-
* Returns `undefined` if no map entry matches
|
|
31
|
-
*
|
|
31
|
+
* Returns `undefined` if no map entry matches. Does not crash on slugs
|
|
32
|
+
* without an underscore — those are treated as already-bare.
|
|
32
33
|
*/
|
|
33
34
|
export declare function findItemAction(slug: string): ItemAction | undefined;
|
|
34
35
|
/**
|
|
@@ -63,10 +63,9 @@ var ITEM_ACTIONS = {
|
|
|
63
63
|
};
|
|
64
64
|
function findItemAction(slug) {
|
|
65
65
|
if (slug in ITEM_ACTIONS) return ITEM_ACTIONS[slug];
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return ITEM_ACTIONS[bare];
|
|
66
|
+
const p = slug.split("_");
|
|
67
|
+
const bare = p.length >= 3 ? p.slice(2).join("_") : p[p.length - 1];
|
|
68
|
+
return bare === slug ? void 0 : ITEM_ACTIONS[bare];
|
|
70
69
|
}
|
|
71
70
|
function resolveItemAction(slug, entry, itemType) {
|
|
72
71
|
var _a, _b;
|
|
@@ -14,8 +14,8 @@ export declare const itemInputSchema: z.ZodObject<{
|
|
|
14
14
|
"wondrous item": "wondrous item";
|
|
15
15
|
}>;
|
|
16
16
|
rarity: z.ZodEnum<{
|
|
17
|
-
legendary: "legendary";
|
|
18
17
|
common: "common";
|
|
18
|
+
legendary: "legendary";
|
|
19
19
|
uncommon: "uncommon";
|
|
20
20
|
rare: "rare";
|
|
21
21
|
"very rare": "very rare";
|
|
@@ -68,9 +68,6 @@ export interface DecisionContext {
|
|
|
68
68
|
}
|
|
69
69
|
/** "[[SRD 2024/Classes/Fighter]]" → "fighter" (tail segment, slugified). */
|
|
70
70
|
export declare function wikilinkTailSlug(link: string): string;
|
|
71
|
-
/** "srd-2024_fighter" → "fighter". Tolerates a nullish slug (degrades to "") so a
|
|
72
|
-
* malformed entity can't hard-crash the builder; the resolver backfills real slugs. */
|
|
73
|
-
export declare function bareEntitySlug(slug: string | null | undefined): string;
|
|
74
71
|
declare function matchesFilter(e: RegisteredEntity, where: EntityFilter, ownerBare: string): boolean;
|
|
75
72
|
/** Test-only export of {@link matchesFilter} (Task B2). */
|
|
76
73
|
export declare const __matchesFilterForTest: typeof matchesFilter;
|
|
@@ -83,6 +80,19 @@ export declare function collectChosenProficiencies(resolved: ResolvedCharacter):
|
|
|
83
80
|
languages: string[];
|
|
84
81
|
tools: string[];
|
|
85
82
|
};
|
|
83
|
+
export interface ChoiceStatus {
|
|
84
|
+
id: string;
|
|
85
|
+
count: number;
|
|
86
|
+
selected: number;
|
|
87
|
+
}
|
|
88
|
+
/** Per-choice status for language/tool select-proficiency decisions, using the
|
|
89
|
+
* SAME walk as collectChosenProficiencies so required/selected counts cannot
|
|
90
|
+
* diverge from the picks. `selected` counts persisted picks validated against
|
|
91
|
+
* the choice's `from` pool (stale slugs ignored, mirroring the pick fold). */
|
|
92
|
+
export declare function collectLanguageToolChoiceStatus(resolved: ResolvedCharacter): {
|
|
93
|
+
languages: ChoiceStatus[];
|
|
94
|
+
tools: ChoiceStatus[];
|
|
95
|
+
};
|
|
86
96
|
export interface OriginAbilityPoints {
|
|
87
97
|
race: Partial<Record<Ability, number>>;
|
|
88
98
|
background: Partial<Record<Ability, number>>;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__matchesFilterForTest,
|
|
3
|
-
bareEntitySlug,
|
|
4
3
|
buildDecisionLedger,
|
|
5
4
|
collectChosenAbilityPoints,
|
|
6
5
|
collectChosenProficiencies,
|
|
6
|
+
collectLanguageToolChoiceStatus,
|
|
7
7
|
wikilinkTailSlug
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-IXZXFFFW.js";
|
|
8
|
+
} from "../chunk-TNUFPIXI.js";
|
|
9
|
+
import "../chunk-7TEK5KK7.js";
|
|
10
|
+
import "../chunk-6IRYTM5V.js";
|
|
12
11
|
import "../chunk-5XUXXAQJ.js";
|
|
13
12
|
import "../chunk-JEYQU3JT.js";
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-N6N74K6X.js";
|
|
14
|
+
import "../chunk-4LZJXJJS.js";
|
|
15
|
+
import "../chunk-LV4SNWZQ.js";
|
|
16
|
+
import "../chunk-VTTA2ALZ.js";
|
|
17
17
|
import "../chunk-NAEPSZAM.js";
|
|
18
18
|
import "../chunk-WP2CX2JO.js";
|
|
19
19
|
export {
|
|
20
20
|
__matchesFilterForTest,
|
|
21
|
-
bareEntitySlug,
|
|
22
21
|
buildDecisionLedger,
|
|
23
22
|
collectChosenAbilityPoints,
|
|
24
23
|
collectChosenProficiencies,
|
|
24
|
+
collectLanguageToolChoiceStatus,
|
|
25
25
|
wikilinkTailSlug
|
|
26
26
|
};
|
package/dist/pc/pc.equipment.js
CHANGED
|
@@ -2,20 +2,14 @@ import {
|
|
|
2
2
|
computeAppliedBonuses,
|
|
3
3
|
computeSlotsAndAttacks,
|
|
4
4
|
emptyAppliedBonuses
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-IXZXFFFW.js";
|
|
10
|
-
import "../chunk-5XUXXAQJ.js";
|
|
11
|
-
import "../chunk-JEYQU3JT.js";
|
|
5
|
+
} from "../chunk-D3CLOBE3.js";
|
|
6
|
+
import "../chunk-353WXS6S.js";
|
|
7
|
+
import "../chunk-O5EYMKFH.js";
|
|
8
|
+
import "../chunk-N6N74K6X.js";
|
|
12
9
|
import "../chunk-LWFTHJIE.js";
|
|
13
10
|
import "../chunk-DNAJRMNN.js";
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-J2RYSZMQ.js";
|
|
17
|
-
import "../chunk-NAEPSZAM.js";
|
|
18
|
-
import "../chunk-WP2CX2JO.js";
|
|
11
|
+
import "../chunk-4LZJXJJS.js";
|
|
12
|
+
import "../chunk-LV4SNWZQ.js";
|
|
19
13
|
export {
|
|
20
14
|
computeAppliedBonuses,
|
|
21
15
|
computeSlotsAndAttacks,
|
|
@@ -24,6 +24,11 @@ export interface WeaponAbilityOverride {
|
|
|
24
24
|
export interface FeatureEffectTotals {
|
|
25
25
|
initiative_bonus: number;
|
|
26
26
|
hp_per_level_bonus: number;
|
|
27
|
+
/** One term per hp-per-level-bonus effect, labeled with the owning feature's name. */
|
|
28
|
+
hp_per_level_terms: {
|
|
29
|
+
label: string;
|
|
30
|
+
value: number;
|
|
31
|
+
}[];
|
|
27
32
|
speed_walk_bonus: number;
|
|
28
33
|
/**
|
|
29
34
|
* Absolute walk-speed FLOOR from `speed-bonus` effects with `set:true` (e.g.
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeFeatureEffects,
|
|
3
3
|
emptyFeatureEffectTotals
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-BH6AMZVY.js";
|
|
7
|
-
import "../chunk-UC4FE5X3.js";
|
|
8
|
-
import "../chunk-IXZXFFFW.js";
|
|
9
|
-
import "../chunk-5XUXXAQJ.js";
|
|
10
|
-
import "../chunk-JEYQU3JT.js";
|
|
11
|
-
import "../chunk-DC74TZNA.js";
|
|
12
|
-
import "../chunk-3TRGRSCH.js";
|
|
13
|
-
import "../chunk-J2RYSZMQ.js";
|
|
14
|
-
import "../chunk-NAEPSZAM.js";
|
|
4
|
+
} from "../chunk-AIRFC5NQ.js";
|
|
5
|
+
import "../chunk-LV4SNWZQ.js";
|
|
15
6
|
import "../chunk-WP2CX2JO.js";
|
|
16
7
|
export {
|
|
17
8
|
computeFeatureEffects,
|
package/dist/pc/pc.parser.js
CHANGED
package/dist/pc/pc.pools.js
CHANGED
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
levelPrereqMax,
|
|
3
3
|
resolveAllPools,
|
|
4
4
|
resolvePool
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-IXZXFFFW.js";
|
|
5
|
+
} from "../chunk-TNUFPIXI.js";
|
|
6
|
+
import "../chunk-7TEK5KK7.js";
|
|
7
|
+
import "../chunk-6IRYTM5V.js";
|
|
9
8
|
import "../chunk-5XUXXAQJ.js";
|
|
10
9
|
import "../chunk-JEYQU3JT.js";
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-N6N74K6X.js";
|
|
11
|
+
import "../chunk-4LZJXJJS.js";
|
|
12
|
+
import "../chunk-LV4SNWZQ.js";
|
|
13
|
+
import "../chunk-VTTA2ALZ.js";
|
|
14
14
|
import "../chunk-NAEPSZAM.js";
|
|
15
15
|
import "../chunk-WP2CX2JO.js";
|
|
16
16
|
export {
|
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
import type { ResolvedCharacter } from "./pc.types.js";
|
|
2
|
+
import { type ChoiceStatus } from "./pc.decision-engine.js";
|
|
2
3
|
export interface ProficiencyAggregate {
|
|
3
4
|
armor: string[];
|
|
4
5
|
weapons: string[];
|
|
5
6
|
tools: string[];
|
|
6
7
|
languages: string[];
|
|
8
|
+
/** Unresolved language/tool decisions as "choose N" placeholders (N = count -
|
|
9
|
+
* selected, only when > 0). Additive; consumed by the plugin proficiency panel. */
|
|
10
|
+
choices: {
|
|
11
|
+
languages: string[];
|
|
12
|
+
tools: string[];
|
|
13
|
+
};
|
|
7
14
|
}
|
|
15
|
+
/** Normalized intermediate of every proficiency/language source the DISPLAY path
|
|
16
|
+
* reads, in one place. Only the class branch is a live proficiency source today
|
|
17
|
+
* (race/bg/feat `.proficiencies` object fields do not exist on those entities);
|
|
18
|
+
* race languages, bg tool/lang, and feat grants read their real fields. Chosen
|
|
19
|
+
* picks + per-choice status come from the single decision walk in
|
|
20
|
+
* pc.decision-engine so display can never diverge from the persisted picks. */
|
|
21
|
+
export interface ProficiencySources {
|
|
22
|
+
classArmor: string[];
|
|
23
|
+
classWeaponFixed: string[];
|
|
24
|
+
classWeaponCategories: string[];
|
|
25
|
+
classToolFixed: string[];
|
|
26
|
+
raceLangFixed: string[];
|
|
27
|
+
bgToolFixed: string[];
|
|
28
|
+
bgLangFixed: string[];
|
|
29
|
+
featArmor: string[];
|
|
30
|
+
featWeapons: string[];
|
|
31
|
+
featTools: string[];
|
|
32
|
+
featLanguages: string[];
|
|
33
|
+
chosenLanguages: string[];
|
|
34
|
+
chosenTools: string[];
|
|
35
|
+
languageChoices: ChoiceStatus[];
|
|
36
|
+
toolChoices: ChoiceStatus[];
|
|
37
|
+
}
|
|
38
|
+
export declare function collectProficiencySources(resolved: ResolvedCharacter): ProficiencySources;
|
|
8
39
|
export declare function aggregateProficiencies(resolved: ResolvedCharacter): ProficiencyAggregate;
|
|
@@ -1,47 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectChosenProficiencies,
|
|
3
|
+
collectLanguageToolChoiceStatus
|
|
4
|
+
} from "../chunk-TNUFPIXI.js";
|
|
5
|
+
import "../chunk-7TEK5KK7.js";
|
|
6
|
+
import "../chunk-6IRYTM5V.js";
|
|
7
|
+
import "../chunk-5XUXXAQJ.js";
|
|
8
|
+
import "../chunk-JEYQU3JT.js";
|
|
9
|
+
import "../chunk-N6N74K6X.js";
|
|
10
|
+
import "../chunk-4LZJXJJS.js";
|
|
11
|
+
import "../chunk-LV4SNWZQ.js";
|
|
12
|
+
import "../chunk-VTTA2ALZ.js";
|
|
13
|
+
import "../chunk-NAEPSZAM.js";
|
|
14
|
+
import "../chunk-WP2CX2JO.js";
|
|
15
|
+
|
|
1
16
|
// src/pc/pc.proficiencies.ts
|
|
2
|
-
function
|
|
3
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
17
|
+
function collectProficiencySources(resolved) {
|
|
18
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
19
|
+
const classArmor = [];
|
|
20
|
+
const classWeaponFixed = [];
|
|
21
|
+
const classWeaponCategories = [];
|
|
22
|
+
const classToolFixed = [];
|
|
8
23
|
for (const c of resolved.classes) {
|
|
9
24
|
const prof = (_a = c.entity) == null ? void 0 : _a.proficiencies;
|
|
10
25
|
if (!prof) continue;
|
|
11
|
-
for (const a of (_b = prof.armor) != null ? _b : [])
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
for (const a of (_b = prof.armor) != null ? _b : []) classArmor.push(a);
|
|
27
|
+
for (const w of (_d = (_c = prof.weapons) == null ? void 0 : _c.fixed) != null ? _d : []) classWeaponFixed.push(w);
|
|
28
|
+
for (const w of (_f = (_e = prof.weapons) == null ? void 0 : _e.categories) != null ? _f : []) classWeaponCategories.push(w);
|
|
29
|
+
for (const t of (_h = (_g = prof.tools) == null ? void 0 : _g.fixed) != null ? _h : []) classToolFixed.push(t);
|
|
15
30
|
}
|
|
16
|
-
const
|
|
17
|
-
|
|
31
|
+
const raceLangFixed = [...(_k = (_j = (_i = resolved.race) == null ? void 0 : _i.languages) == null ? void 0 : _j.fixed) != null ? _k : []];
|
|
32
|
+
const bgToolFixed = [];
|
|
33
|
+
const bgLangFixed = [];
|
|
18
34
|
const bg = resolved.background;
|
|
19
35
|
if (bg) {
|
|
20
|
-
for (const entry of (
|
|
21
|
-
if (entry.kind === "fixed")
|
|
36
|
+
for (const entry of (_l = bg.tool_proficiencies) != null ? _l : []) {
|
|
37
|
+
if (entry.kind === "fixed") bgToolFixed.push(...entry.items);
|
|
22
38
|
}
|
|
23
|
-
for (const entry of (
|
|
24
|
-
if (entry.kind === "fixed")
|
|
39
|
+
for (const entry of (_m = bg.language_proficiencies) != null ? _m : []) {
|
|
40
|
+
if (entry.kind === "fixed") bgLangFixed.push(...entry.languages);
|
|
25
41
|
}
|
|
26
42
|
}
|
|
43
|
+
const featArmor = [];
|
|
44
|
+
const featWeapons = [];
|
|
45
|
+
const featTools = [];
|
|
46
|
+
const featLanguages = [];
|
|
27
47
|
for (const f of resolved.feats) {
|
|
28
|
-
const
|
|
48
|
+
const featView = f;
|
|
49
|
+
const grants = featView.proficiencies;
|
|
29
50
|
if (!grants) continue;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
featArmor.push(...(_n = grants.armor) != null ? _n : []);
|
|
52
|
+
featWeapons.push(...(_o = grants.weapons) != null ? _o : []);
|
|
53
|
+
featTools.push(...(_p = grants.tools) != null ? _p : []);
|
|
54
|
+
featLanguages.push(...(_q = grants.languages) != null ? _q : []);
|
|
34
55
|
}
|
|
56
|
+
const chosen = collectChosenProficiencies(resolved);
|
|
57
|
+
const status = collectLanguageToolChoiceStatus(resolved);
|
|
58
|
+
return {
|
|
59
|
+
classArmor,
|
|
60
|
+
classWeaponFixed,
|
|
61
|
+
classWeaponCategories,
|
|
62
|
+
classToolFixed,
|
|
63
|
+
raceLangFixed,
|
|
64
|
+
bgToolFixed,
|
|
65
|
+
bgLangFixed,
|
|
66
|
+
featArmor,
|
|
67
|
+
featWeapons,
|
|
68
|
+
featTools,
|
|
69
|
+
featLanguages,
|
|
70
|
+
chosenLanguages: chosen.languages,
|
|
71
|
+
chosenTools: chosen.tools,
|
|
72
|
+
languageChoices: status.languages,
|
|
73
|
+
toolChoices: status.tools
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function aggregateProficiencies(resolved) {
|
|
77
|
+
const src = collectProficiencySources(resolved);
|
|
78
|
+
const armor = /* @__PURE__ */ new Set();
|
|
79
|
+
const weapons = /* @__PURE__ */ new Set();
|
|
80
|
+
const tools = /* @__PURE__ */ new Set();
|
|
81
|
+
const languages = /* @__PURE__ */ new Set();
|
|
82
|
+
for (const a of src.classArmor) armor.add(prettyName(a));
|
|
83
|
+
for (const w of src.classWeaponFixed) weapons.add(prettyName(w));
|
|
84
|
+
for (const w of src.classWeaponCategories) weapons.add(prettyName(w));
|
|
85
|
+
for (const t of src.classToolFixed) tools.add(prettyName(t));
|
|
86
|
+
for (const l of src.raceLangFixed) languages.add(prettyName(l));
|
|
87
|
+
for (const t of src.bgToolFixed) tools.add(prettyName(t));
|
|
88
|
+
for (const l of src.bgLangFixed) languages.add(prettyName(l));
|
|
89
|
+
for (const a of src.featArmor) armor.add(prettyName(a));
|
|
90
|
+
for (const w of src.featWeapons) weapons.add(prettyName(w));
|
|
91
|
+
for (const t of src.featTools) tools.add(prettyName(t));
|
|
92
|
+
for (const l of src.featLanguages) languages.add(prettyName(l));
|
|
93
|
+
for (const l of src.chosenLanguages) languages.add(prettyName(l));
|
|
94
|
+
for (const t of src.chosenTools) tools.add(prettyName(t));
|
|
35
95
|
return {
|
|
36
96
|
armor: [...armor].sort(),
|
|
37
97
|
weapons: [...weapons].sort(),
|
|
38
98
|
tools: [...tools].sort(),
|
|
39
|
-
languages: [...languages].sort()
|
|
99
|
+
languages: [...languages].sort(),
|
|
100
|
+
choices: {
|
|
101
|
+
languages: placeholders(src.languageChoices),
|
|
102
|
+
tools: placeholders(src.toolChoices)
|
|
103
|
+
}
|
|
40
104
|
};
|
|
41
105
|
}
|
|
106
|
+
function placeholders(choices) {
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const c of choices) {
|
|
109
|
+
const remaining = c.count - c.selected;
|
|
110
|
+
if (remaining > 0) out.push("choose " + remaining);
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
42
114
|
function prettyName(slug) {
|
|
43
115
|
return slug.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
44
116
|
}
|
|
45
117
|
export {
|
|
46
|
-
aggregateProficiencies
|
|
118
|
+
aggregateProficiencies,
|
|
119
|
+
collectProficiencySources
|
|
47
120
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Normalized token-set key for matching class weapon DISPLAY names ("hand crossbows")
|
|
2
|
+
* against weapon-entity names ("Crossbow, hand"). EXACT equality on the key; verified
|
|
3
|
+
* collision-free across the SRD weapon set. Strip-"s" singularizer does not handle
|
|
4
|
+
* irregular plurals; no SRD weapon triggers that. */
|
|
5
|
+
export declare const normKey: (s: string) => string;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normKey
|
|
3
|
+
} from "../chunk-O5EYMKFH.js";
|
|
4
|
+
|
|
1
5
|
// src/pc/pc.proficiency-query.ts
|
|
2
6
|
function isProficientWithWeapon(weapon, profs) {
|
|
3
|
-
if (profs.weapons.specific.
|
|
7
|
+
if (profs.weapons.specific.some((e) => e === weapon.slug || normKey(e) === normKey(weapon.name))) return true;
|
|
4
8
|
const baseCategory = weapon.category.split("-")[0];
|
|
5
9
|
return profs.weapons.categories.includes(baseCategory);
|
|
6
10
|
}
|
package/dist/pc/pc.recalc.d.ts
CHANGED
|
@@ -45,11 +45,18 @@ export declare function abilityBonusBreakdown(resolved: ResolvedCharacter): Reco
|
|
|
45
45
|
class: number;
|
|
46
46
|
feat: number;
|
|
47
47
|
}>;
|
|
48
|
+
/** Dice-only portion of PC max HP: first VALID level anywhere = max(die),
|
|
49
|
+
* every later valid level = PHB average. Skip rule identical to hpLevelCount. */
|
|
50
|
+
export declare function hitDiceAverageSum(classes: ResolvedClass[]): number;
|
|
51
|
+
/** Count of levels that contribute to HP (valid class entries only). */
|
|
52
|
+
export declare function hpLevelCount(classes: ResolvedClass[]): number;
|
|
48
53
|
/**
|
|
49
54
|
* PC-oriented multiclass HP.
|
|
50
55
|
* - First class's first level: max(hit_die) + conMod.
|
|
51
56
|
* - Every subsequent level (in any class): phbAverageForDie(thatLevel'sClass) + conMod.
|
|
52
57
|
* CON mod contributes once per total level.
|
|
58
|
+
* Decomposed (P5 T2) into hitDiceAverageSum (dice-only) + hpLevelCount (level count),
|
|
59
|
+
* so a later popup can render the two components separately.
|
|
53
60
|
*/
|
|
54
61
|
export declare function multiclassMaxHP(classes: ResolvedClass[], conMod: number): number;
|
|
55
62
|
/**
|