@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.
- package/LICENSES/SRD.md +38 -3
- package/dist/armor/armor.codec.js +3 -3
- package/dist/armor/armor.parser.js +2 -2
- package/dist/armor/armor.schema.d.ts +1 -0
- package/dist/armor/armor.schema.js +1 -1
- package/dist/armor/armor.types.d.ts +2 -0
- package/dist/background/background.codec.js +5 -5
- package/dist/background/background.parser.js +4 -4
- package/dist/background/background.schema.js +3 -3
- package/dist/{chunk-XTRDCSJB.js → chunk-2JSQE3DD.js} +15 -1
- package/dist/chunk-2LULMQTF.js +14 -0
- package/dist/{chunk-MAH6DCRI.js → chunk-2UDSN6VW.js} +1 -1
- package/dist/chunk-3LWMFYKS.js +57 -0
- package/dist/{chunk-JCEV7KYN.js → chunk-3MGQFFNE.js} +1 -1
- package/dist/chunk-3VZZDKRA.js +1014 -0
- package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
- package/dist/{chunk-2M34FLAY.js → chunk-5MXFW4O3.js} +9 -3
- package/dist/{chunk-4DOMDEBZ.js → chunk-6EI737IO.js} +1 -1
- package/dist/{chunk-G247QXWW.js → chunk-7ATNGKBS.js} +1 -1
- package/dist/{chunk-XY6X2APM.js → chunk-7Q2VPKCD.js} +17 -0
- package/dist/{chunk-T2SNEJOE.js → chunk-7QN7XSAK.js} +1 -1
- package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
- package/dist/{chunk-7YU4NPKR.js → chunk-AZRGFUSR.js} +1 -1
- package/dist/{chunk-PP2UHLBA.js → chunk-B3DP42OM.js} +5 -0
- package/dist/chunk-CM5CWO4K.js +735 -0
- package/dist/{chunk-MQ747UCR.js → chunk-DOXSFYLH.js} +70 -2
- package/dist/chunk-EJP263OP.js +186 -0
- package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
- package/dist/{chunk-V6LJFP4R.js → chunk-FANQVQ3D.js} +2 -2
- package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
- package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
- package/dist/{chunk-JANNRGJC.js → chunk-G6PBI2BU.js} +1 -1
- package/dist/chunk-H5PTKYXL.js +101 -0
- package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
- package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
- package/dist/chunk-HTYMW5CH.js +228 -0
- package/dist/chunk-IHE6KVC3.js +13 -0
- package/dist/{chunk-QHMWA3SZ.js → chunk-JCMUVZIK.js} +1 -1
- package/dist/{chunk-V373TRJE.js → chunk-JSM6JFZR.js} +198 -125
- package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
- package/dist/chunk-KR6JF3BF.js +14 -0
- package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
- package/dist/chunk-LBEXLN6I.js +91 -0
- package/dist/{chunk-BLRW2UU6.js → chunk-LF5AGJA4.js} +2 -2
- package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
- package/dist/{chunk-BIA32MQ5.js → chunk-MBX25B6D.js} +1 -1
- package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
- package/dist/{chunk-J77CKYV3.js → chunk-OFCSP6MT.js} +1 -1
- package/dist/{chunk-2INMRR3Q.js → chunk-ONTGZR5T.js} +326 -149
- package/dist/{chunk-MWCCGPG3.js → chunk-OOSRUJBI.js} +3 -2
- package/dist/{chunk-U3BABVJF.js → chunk-PKX6TGRE.js} +2 -2
- package/dist/{chunk-PJMG5XV3.js → chunk-PQZ4LM4Z.js} +1 -1
- package/dist/chunk-PXVNAY7T.js +84 -0
- package/dist/chunk-QH36K2PU.js +158 -0
- package/dist/{chunk-R747YKS7.js → chunk-QZSWN2KT.js} +1 -1
- package/dist/{chunk-CHUALUIX.js → chunk-RYLXAYIQ.js} +1 -1
- package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
- package/dist/{chunk-PZCE7DJM.js → chunk-T6QIF5XR.js} +31 -1
- package/dist/{chunk-CBEKVAX4.js → chunk-TULQ4FFX.js} +41 -13
- package/dist/{chunk-S56D6B6C.js → chunk-UUBJCNQU.js} +12 -3
- package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
- package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
- package/dist/{chunk-3HX5VLWP.js → chunk-VRV3NNTA.js} +2 -2
- package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
- package/dist/{chunk-BL3VELKP.js → chunk-Y5VVP73C.js} +1 -1
- package/dist/{chunk-PI4LLJG4.js → chunk-YD2VAHA6.js} +2 -2
- package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
- package/dist/{chunk-NWDF5HG3.js → chunk-YKL6SHRJ.js} +1 -1
- package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
- package/dist/chunk-ZUQW5VBZ.js +89 -0
- package/dist/class/class.codec.js +7 -7
- package/dist/class/class.parser.js +6 -6
- package/dist/class/class.schema.d.ts +18 -0
- package/dist/class/class.schema.js +5 -5
- package/dist/class/class.standard-array.d.ts +16 -0
- package/dist/class/class.standard-array.js +20 -0
- package/dist/class/class.types.d.ts +3 -0
- package/dist/dnd/amount-text.d.ts +38 -0
- package/dist/dnd/amount-text.js +13 -0
- package/dist/dnd/resource-words.d.ts +4 -0
- package/dist/dnd/resource-words.js +30 -0
- package/dist/entities/base-item-resolver.js +2 -2
- package/dist/entities/slug.d.ts +18 -8
- package/dist/entities/slug.js +3 -1
- package/dist/feat/feat.codec.js +5 -5
- package/dist/feat/feat.parser.js +4 -4
- package/dist/feat/feat.schema.d.ts +41 -3
- package/dist/feat/feat.schema.js +3 -3
- package/dist/index.js +7513 -4177
- package/dist/item/item.actions-map.d.ts +40 -5
- package/dist/item/item.actions-map.js +5 -84
- package/dist/item/item.attunement.js +3 -9
- package/dist/item/item.bonuses.js +5 -2
- package/dist/item/item.codec.js +3 -3
- package/dist/item/item.conditions.js +4 -1
- package/dist/item/item.conditions.types.d.ts +4 -0
- package/dist/item/item.cost.d.ts +3 -0
- package/dist/item/item.cost.js +29 -0
- package/dist/item/item.icon.d.ts +15 -0
- package/dist/item/item.icon.js +211 -0
- package/dist/item/item.parser.js +2 -2
- package/dist/item/item.schema.d.ts +16 -1
- package/dist/item/item.schema.js +3 -1
- package/dist/item/item.types.d.ts +9 -2
- package/dist/monster/monster.parser.js +5 -5
- package/dist/monster/monster.schema.js +4 -4
- package/dist/optional-feature/optional-feature.codec.js +5 -4
- package/dist/optional-feature/optional-feature.parser.js +4 -3
- package/dist/optional-feature/optional-feature.schema.d.ts +255 -3
- package/dist/optional-feature/optional-feature.schema.js +7 -2
- package/dist/pc/pc.additional-spells.js +3 -3
- package/dist/pc/pc.amount-bindings.d.ts +32 -0
- package/dist/pc/pc.amount-bindings.js +23 -0
- package/dist/pc/pc.asi-flatten.d.ts +62 -1
- package/dist/pc/pc.asi-flatten.js +16 -0
- package/dist/pc/pc.conditions.js +1 -1
- package/dist/pc/pc.containment.d.ts +45 -0
- package/dist/pc/pc.containment.js +24 -0
- package/dist/pc/pc.decision-engine.d.ts +24 -3
- package/dist/pc/pc.decision-engine.js +26 -16
- package/dist/pc/pc.entry-overrides.d.ts +79 -0
- package/dist/pc/pc.entry-overrides.js +40 -0
- package/dist/pc/pc.equipment.d.ts +2 -2
- package/dist/pc/pc.equipment.js +19 -7
- package/dist/pc/pc.feature-effects.d.ts +12 -0
- package/dist/pc/pc.feature-effects.js +2 -2
- package/dist/pc/pc.infusions.d.ts +228 -0
- package/dist/pc/pc.infusions.js +64 -0
- package/dist/pc/pc.member-choices.d.ts +90 -0
- package/dist/pc/pc.member-choices.js +32 -0
- package/dist/pc/pc.parser.js +18 -1
- package/dist/pc/pc.pools.d.ts +8 -1
- package/dist/pc/pc.pools.js +13 -3
- package/dist/pc/pc.proficiencies.js +23 -15
- package/dist/pc/pc.proficiency-query.js +6 -0
- package/dist/pc/pc.recalc.d.ts +39 -36
- package/dist/pc/pc.recalc.js +115 -70
- package/dist/pc/pc.resolver.d.ts +2 -1
- package/dist/pc/pc.resolver.js +22 -14
- package/dist/pc/pc.resource-seed.js +1 -1
- package/dist/pc/pc.resources.d.ts +6 -1
- package/dist/pc/pc.resources.js +3 -1
- package/dist/pc/pc.rest.d.ts +21 -1
- package/dist/pc/pc.rest.js +52 -19
- package/dist/pc/pc.schema.d.ts +43 -2
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.slotting.d.ts +36 -3
- package/dist/pc/pc.slotting.js +13 -5
- package/dist/pc/pc.tool-picks.d.ts +51 -0
- package/dist/pc/pc.tool-picks.js +18 -0
- package/dist/pc/pc.types.d.ts +115 -14
- package/dist/pc/pc.weapon-grant.d.ts +15 -0
- package/dist/pc/pool-layout.d.ts +8 -0
- package/dist/pc/pool-layout.js +5 -3
- package/dist/pc/resource-equivalents.d.ts +44 -0
- package/dist/pc/spell-source.js +4 -9
- package/dist/race/race.codec.js +6 -6
- package/dist/race/race.parser.js +5 -5
- package/dist/race/race.schema.js +4 -4
- package/dist/schemas/attack-schema.d.ts +1 -1
- package/dist/schemas/choice-schema.js +2 -2
- package/dist/schemas/feature-effect-schema.d.ts +41 -3
- package/dist/schemas/feature-effect-schema.js +1 -1
- package/dist/schemas/feature-schema.js +3 -3
- package/dist/schemas/selection-pool-schema.d.ts +10 -0
- package/dist/schemas/selection-pool-schema.js +1 -1
- package/dist/spell/spell.codec.js +2 -2
- package/dist/spell/spell.parser.d.ts +6 -1
- package/dist/spell/spell.parser.js +5 -3
- package/dist/spell/spell.types.d.ts +10 -0
- package/dist/srd/retired-items.d.ts +14 -0
- package/dist/srd/retired-items.js +11 -0
- package/dist/subclass/subclass.codec.js +7 -7
- package/dist/subclass/subclass.parser.js +6 -6
- package/dist/subclass/subclass.schema.d.ts +10 -0
- package/dist/subclass/subclass.schema.js +5 -5
- package/dist/types/choice.d.ts +13 -0
- package/dist/types/equipment-grant.d.ts +18 -1
- package/dist/types/equipment-grant.js +12 -0
- package/dist/types/feature-effect.d.ts +12 -1
- package/dist/types/optional-feature.types.d.ts +84 -1
- package/dist/types/selection-pool.d.ts +18 -3
- package/dist/weapon/weapon.classify.d.ts +10 -8
- package/dist/weapon/weapon.classify.js +2 -2
- package/dist/weapon/weapon.codec.js +3 -3
- package/dist/weapon/weapon.parser.js +2 -2
- package/dist/weapon/weapon.schema.d.ts +1 -0
- package/dist/weapon/weapon.schema.js +1 -1
- package/dist/weapon/weapon.types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-O4SRD3J5.js +0 -165
- package/dist/chunk-WXWPK3LI.js +0 -55
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D2b-A · nested choices on pool members (design §2.2, user rulings 2026-09-27: GENERAL and RECURSIVE).
|
|
3
|
+
*
|
|
4
|
+
* A pool member (an invocation, a maneuver, a fighting-style option, ...) may carry its own choices: Lessons of the First
|
|
5
|
+
* Ones' Origin feat, Superior Technique's maneuver, Blessed and Druidic Warrior's cantrips, Pact of the Tome's cantrips
|
|
6
|
+
* and rituals, the three blasts' cantrip. A nested pick lives in the pool's ANCHOR block under
|
|
7
|
+
* `<poolId>:<pickKey>:<choiceId>` (a nested feat's own children under `<poolId>:<pickKey>:feat:<childId>`, the decision
|
|
8
|
+
* engine's prefix chaining), keyed by the stored pick string, so reordering or adding picks never moves it.
|
|
9
|
+
*
|
|
10
|
+
* The choices are the member's authored `choices`; absent (every note in the vault today), they are DERIVED at read time
|
|
11
|
+
* from the raw keys the notes already carry (`feat_progression`, `optionalfeature_progression`, `additional_spells`
|
|
12
|
+
* with `choose`, a `spell-choose` prerequisite), so existing notes work with no re-import. Authored `choices` win.
|
|
13
|
+
*/
|
|
14
|
+
import type { Character, ChoiceValue, FeatVia, ResolvedCharacter, ResolvedClass } from "./pc.types.js";
|
|
15
|
+
import type { Choice } from "@archivist-gg/dnd5e/types/choice";
|
|
16
|
+
import type { OptionalFeatureEntity } from "@archivist-gg/dnd5e/types/optional-feature.types";
|
|
17
|
+
import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
|
|
18
|
+
/** Whether `ch` names a target rather than granting what it picks (the data flag `target: true`, which the spell-choose
|
|
19
|
+
* derivation below writes and an authored note may carry). */
|
|
20
|
+
export declare function isTargetChoice(ch: Choice): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The member's choices: its authored `choices`, else the ones its raw keys ask for (see the module docblock). Pure; the
|
|
23
|
+
* derived rows carry the member's edition so a pick never offers the other edition's twin.
|
|
24
|
+
*/
|
|
25
|
+
export declare function memberChoices(entity: OptionalFeatureEntity | null | undefined): Choice[];
|
|
26
|
+
/** One stored pool pick whose member carries choices, with the block its nested picks live in. */
|
|
27
|
+
export interface PoolMemberSite {
|
|
28
|
+
classIndex: number;
|
|
29
|
+
/** The pool's anchor level (the block's key in `choices`). */
|
|
30
|
+
level: number;
|
|
31
|
+
poolId: string;
|
|
32
|
+
/** The stored pick string (a copy of a repeatable note keeps its `slug#param`). */
|
|
33
|
+
pickKey: string;
|
|
34
|
+
member: OptionalFeatureEntity;
|
|
35
|
+
memberSlug: string;
|
|
36
|
+
choices: Choice[];
|
|
37
|
+
/** `<poolId>:<pickKey>:` */
|
|
38
|
+
prefix: string;
|
|
39
|
+
/** The nested pick stored for a member choice id. */
|
|
40
|
+
read: (choiceId: string) => ChoiceValue | undefined;
|
|
41
|
+
/** The anchor block, as stored. */
|
|
42
|
+
block: Record<string, ChoiceValue>;
|
|
43
|
+
}
|
|
44
|
+
/** Structural subset of the registry the raw enumerator reads. */
|
|
45
|
+
export interface MemberRegistry {
|
|
46
|
+
getByTypeAndSlug(entityType: string, slug: string): {
|
|
47
|
+
slug: string;
|
|
48
|
+
data: Record<string, unknown>;
|
|
49
|
+
} | undefined;
|
|
50
|
+
search(query: string, entityType: string, limit: number): Array<{
|
|
51
|
+
slug: string;
|
|
52
|
+
data: Record<string, unknown>;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Every pool member site from the RAW character (the resolver's view, before pools resolve): each class's and subclass's
|
|
57
|
+
* declared pools, their anchor levels (`poolAnchorLevel`, the one derivation `resolvePool` uses), the picks stored there,
|
|
58
|
+
* each resolved to its note (full slug, else bare). A pick with no note, or a note with no choices, yields no site, so an
|
|
59
|
+
* orphan nested key is inert.
|
|
60
|
+
*/
|
|
61
|
+
export declare function poolMemberSites(classes: ResolvedClass[], registry: MemberRegistry): PoolMemberSite[];
|
|
62
|
+
/** The same sites read from a RESOLVED character's pools (the ledger's, the proficiency walk's and recalc's view). */
|
|
63
|
+
export declare function poolMemberSitesOf(resolved: Pick<ResolvedCharacter, "pools" | "classes">): PoolMemberSite[];
|
|
64
|
+
/** A feat the character picked, where it was picked, and how its own children are read. */
|
|
65
|
+
export interface FeatPickSite {
|
|
66
|
+
slug: string;
|
|
67
|
+
classIndex: number;
|
|
68
|
+
level: number | null;
|
|
69
|
+
via: FeatVia | null;
|
|
70
|
+
/** A child choice of THIS feat, as stored (`feat:<id>` in the slot's block, or `<prefix>feat:<id>` under a member). */
|
|
71
|
+
read: (childId: string) => ChoiceValue | undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Every feat pick with its own read (design §2.2 step 4): the class-slot picks (`choices[<level>].feat`, children under
|
|
75
|
+
* `feat:<id>`) and the pool-member picks (a member choice of `entity_type: feat`, children under `<prefix>feat:<id>`).
|
|
76
|
+
* The ONE list the four feat readers walk (the resolver's feats and feat spells, the proficiency walk, ability points).
|
|
77
|
+
* `classSlugOf` names a class for the provenance. NOT de-duplicated: a feat taken twice (Magic Initiate, one spell list
|
|
78
|
+
* each) is two sites with two reads; a reader that lists feats de-duplicates by slug itself (first wins).
|
|
79
|
+
*/
|
|
80
|
+
export declare function featPickSites(classEntries: ReadonlyArray<{
|
|
81
|
+
choices?: Character["class"][number]["choices"] | ResolvedClass["choices"];
|
|
82
|
+
}> | undefined, memberSites: PoolMemberSite[], classSlugOf: (classIndex: number) => string | null): FeatPickSite[];
|
|
83
|
+
/** Look a feat pick up in the resolved feats (by slug, then bare slug). */
|
|
84
|
+
export declare function featOfSite(site: FeatPickSite, feats: ReadonlyArray<FeatEntity>): FeatEntity | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* The nested keys an array write to `key` orphans (design §2.2 step 8): every `<key>:<k>:*` whose `k` was stored before
|
|
87
|
+
* and is not in `next`. Pure; the writer deletes them in the same write, so a re-pick never resurrects an old answer.
|
|
88
|
+
* A key that is not a pool (no array stored) orphans nothing.
|
|
89
|
+
*/
|
|
90
|
+
export declare function nestedPickKeysToPrune(block: Record<string, unknown> | undefined, key: string, next: readonly string[]): string[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
featOfSite,
|
|
3
|
+
featPickSites,
|
|
4
|
+
isTargetChoice,
|
|
5
|
+
memberChoices,
|
|
6
|
+
nestedPickKeysToPrune,
|
|
7
|
+
poolMemberSites,
|
|
8
|
+
poolMemberSitesOf
|
|
9
|
+
} from "../chunk-HTYMW5CH.js";
|
|
10
|
+
import "../chunk-3VZZDKRA.js";
|
|
11
|
+
import "../chunk-W6GC6OKK.js";
|
|
12
|
+
import "../chunk-B3DP42OM.js";
|
|
13
|
+
import "../chunk-IUAAXXNO.js";
|
|
14
|
+
import "../chunk-IHE6KVC3.js";
|
|
15
|
+
import "../chunk-LHZXYFBU.js";
|
|
16
|
+
import "../chunk-YBLDE5CG.js";
|
|
17
|
+
import "../chunk-ZUQW5VBZ.js";
|
|
18
|
+
import "../chunk-LVQLWRCU.js";
|
|
19
|
+
import "../chunk-CM5CWO4K.js";
|
|
20
|
+
import "../chunk-ZCTUYGNV.js";
|
|
21
|
+
import "../chunk-3TM34RSJ.js";
|
|
22
|
+
import "../chunk-PDJSUH24.js";
|
|
23
|
+
import "../chunk-WELIKLZF.js";
|
|
24
|
+
export {
|
|
25
|
+
featOfSite,
|
|
26
|
+
featPickSites,
|
|
27
|
+
isTargetChoice,
|
|
28
|
+
memberChoices,
|
|
29
|
+
nestedPickKeysToPrune,
|
|
30
|
+
poolMemberSites,
|
|
31
|
+
poolMemberSitesOf
|
|
32
|
+
};
|
package/dist/pc/pc.parser.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
characterSchema
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-T6QIF5XR.js";
|
|
4
4
|
import "../chunk-S7REMWW4.js";
|
|
5
|
+
import {
|
|
6
|
+
keptSlugForLink
|
|
7
|
+
} from "../chunk-CM5CWO4K.js";
|
|
8
|
+
import "../chunk-ZCTUYGNV.js";
|
|
5
9
|
|
|
6
10
|
// src/pc/pc.parser.ts
|
|
7
11
|
import * as yaml from "js-yaml";
|
|
8
12
|
function parsePC(source) {
|
|
13
|
+
var _a;
|
|
9
14
|
let raw;
|
|
10
15
|
try {
|
|
11
16
|
raw = yaml.load(source);
|
|
@@ -34,8 +39,20 @@ function parsePC(source) {
|
|
|
34
39
|
if (legacyState.attuned_items) {
|
|
35
40
|
delete legacyState.attuned_items;
|
|
36
41
|
}
|
|
42
|
+
for (const entry of (_a = data.equipment) != null ? _a : []) {
|
|
43
|
+
if (typeof entry.item !== "string") continue;
|
|
44
|
+
const next = migrateRetiredItemLink(entry.item);
|
|
45
|
+
if (next !== null) entry.item = next;
|
|
46
|
+
}
|
|
37
47
|
return { success: true, data };
|
|
38
48
|
}
|
|
49
|
+
function migrateRetiredItemLink(item) {
|
|
50
|
+
var _a;
|
|
51
|
+
const m = /^\[\[([^\]|]+)(\|[^\]]*)?\]\]$/.exec(item.trim());
|
|
52
|
+
const kept = keptSlugForLink(m ? m[1] : item);
|
|
53
|
+
if (kept === void 0) return null;
|
|
54
|
+
return m ? `[[${kept}${(_a = m[2]) != null ? _a : ""}]]` : kept;
|
|
55
|
+
}
|
|
39
56
|
export {
|
|
40
57
|
parsePC
|
|
41
58
|
};
|
package/dist/pc/pc.pools.d.ts
CHANGED
|
@@ -9,7 +9,14 @@ export interface PoolRegistry {
|
|
|
9
9
|
getByTypeAndSlug(entityType: string, slug: string): RegisteredEntity | undefined;
|
|
10
10
|
}
|
|
11
11
|
export declare function levelPrereqMax(d: OptionalFeatureEntity): number;
|
|
12
|
-
|
|
12
|
+
/** The pool's ANCHOR level (its picks live in `choices[anchorLevel][pool.id]`): the first level whose count column
|
|
13
|
+
* carries a value of at least 1, else 1; `columnSeen` says whether any level carried the column at all. ONE derivation
|
|
14
|
+
* shared by `resolvePool` and the nested-choice enumerator (D2b-A, `pc.member-choices.ts`), so the two always agree. */
|
|
15
|
+
export declare function poolAnchorLevel(entity: Pick<NonNullable<ResolvedClass["entity"]>, "table">, pool: Pick<SelectionPool, "count">): {
|
|
16
|
+
anchorLevel: number;
|
|
17
|
+
columnSeen: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function resolvePool(rc: ResolvedClass, classIndex: number, pool: SelectionPool, registry: PoolRegistry, index: ResourceIndex, edition?: string): ResolvedPool;
|
|
13
20
|
export declare function resolveAllPools(resolved: ResolvedCharacter, registry: PoolRegistry, index: ResourceIndex): ResolvedPool[];
|
|
14
21
|
/** The stored picks that survived resolution but are NOT in the collapsed `available` list, compared by FULL
|
|
15
22
|
* slug: exactly the rule the plugin's `strandedSelections` used before T3 retires it (R4-G5 §3.2.3). Because
|
package/dist/pc/pc.pools.js
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
levelPrereqMax,
|
|
3
|
+
poolAnchorLevel,
|
|
3
4
|
resolveAllPools,
|
|
4
5
|
resolvePool,
|
|
5
6
|
strandedPicks
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-3VZZDKRA.js";
|
|
8
|
+
import "../chunk-W6GC6OKK.js";
|
|
9
|
+
import "../chunk-B3DP42OM.js";
|
|
8
10
|
import "../chunk-IUAAXXNO.js";
|
|
11
|
+
import "../chunk-IHE6KVC3.js";
|
|
12
|
+
import "../chunk-LHZXYFBU.js";
|
|
13
|
+
import "../chunk-ZUQW5VBZ.js";
|
|
9
14
|
import "../chunk-LVQLWRCU.js";
|
|
10
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-CM5CWO4K.js";
|
|
16
|
+
import "../chunk-ZCTUYGNV.js";
|
|
17
|
+
import "../chunk-3TM34RSJ.js";
|
|
18
|
+
import "../chunk-PDJSUH24.js";
|
|
19
|
+
import "../chunk-WELIKLZF.js";
|
|
11
20
|
export {
|
|
12
21
|
levelPrereqMax,
|
|
22
|
+
poolAnchorLevel,
|
|
13
23
|
resolveAllPools,
|
|
14
24
|
resolvePool,
|
|
15
25
|
strandedPicks
|
|
@@ -2,31 +2,39 @@ import {
|
|
|
2
2
|
collectChosenProficiencies,
|
|
3
3
|
collectProficiencyGrants,
|
|
4
4
|
computeEffectiveProficiencies
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-PP2UHLBA.js";
|
|
10
|
-
import "../chunk-IUAAXXNO.js";
|
|
11
|
-
import "../chunk-YHYTW5QA.js";
|
|
12
|
-
import "../chunk-3HX5VLWP.js";
|
|
13
|
-
import "../chunk-PVCEA4HZ.js";
|
|
14
|
-
import "../chunk-UBBKSYBY.js";
|
|
15
|
-
import "../chunk-CBEKVAX4.js";
|
|
5
|
+
} from "../chunk-ONTGZR5T.js";
|
|
6
|
+
import "../chunk-2LULMQTF.js";
|
|
7
|
+
import "../chunk-H5PTKYXL.js";
|
|
8
|
+
import "../chunk-TULQ4FFX.js";
|
|
16
9
|
import "../chunk-TOM66P2P.js";
|
|
17
10
|
import "../chunk-KU3YLF6D.js";
|
|
11
|
+
import "../chunk-HTYMW5CH.js";
|
|
12
|
+
import "../chunk-KSTV7J2U.js";
|
|
13
|
+
import "../chunk-DPUJDOKV.js";
|
|
14
|
+
import "../chunk-LBEXLN6I.js";
|
|
18
15
|
import {
|
|
19
16
|
proficiencyLabel,
|
|
20
17
|
toProfSlug
|
|
21
18
|
} from "../chunk-RLGQ5PZZ.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
24
|
-
import "../chunk-
|
|
19
|
+
import "../chunk-3VZZDKRA.js";
|
|
20
|
+
import "../chunk-W6GC6OKK.js";
|
|
21
|
+
import "../chunk-B3DP42OM.js";
|
|
22
|
+
import "../chunk-IUAAXXNO.js";
|
|
23
|
+
import "../chunk-YHYTW5QA.js";
|
|
24
|
+
import "../chunk-VRV3NNTA.js";
|
|
25
|
+
import "../chunk-PVCEA4HZ.js";
|
|
26
|
+
import "../chunk-IHE6KVC3.js";
|
|
27
|
+
import "../chunk-LHZXYFBU.js";
|
|
25
28
|
import "../chunk-YBLDE5CG.js";
|
|
29
|
+
import "../chunk-ZUQW5VBZ.js";
|
|
30
|
+
import "../chunk-LVQLWRCU.js";
|
|
31
|
+
import "../chunk-CM5CWO4K.js";
|
|
26
32
|
import "../chunk-EVMUJYUD.js";
|
|
27
33
|
import "../chunk-VTTA2ALZ.js";
|
|
28
|
-
import "../chunk-
|
|
34
|
+
import "../chunk-ZCTUYGNV.js";
|
|
35
|
+
import "../chunk-7Q2VPKCD.js";
|
|
29
36
|
import "../chunk-ZDAEGJH4.js";
|
|
37
|
+
import "../chunk-3TM34RSJ.js";
|
|
30
38
|
import "../chunk-PDJSUH24.js";
|
|
31
39
|
import "../chunk-WELIKLZF.js";
|
|
32
40
|
import "../chunk-4U55VNC7.js";
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
qualifiedGrantCovers
|
|
3
|
+
} from "../chunk-3LWMFYKS.js";
|
|
4
|
+
import "../chunk-YDGMBMYI.js";
|
|
1
5
|
import {
|
|
2
6
|
normKey
|
|
3
7
|
} from "../chunk-RLGQ5PZZ.js";
|
|
8
|
+
import "../chunk-ZCTUYGNV.js";
|
|
4
9
|
|
|
5
10
|
// src/pc/pc.proficiency-query.ts
|
|
6
11
|
function isProficientWithWeapon(weapon, profs) {
|
|
7
12
|
if (profs.weapons.specific.some((e) => e === weapon.slug || normKey(e) === normKey(weapon.name))) return true;
|
|
13
|
+
if (profs.weapons.specific.some((e) => qualifiedGrantCovers(e, weapon))) return true;
|
|
8
14
|
const baseCategory = weapon.category.split("-")[0];
|
|
9
15
|
return profs.weapons.categories.includes(baseCategory);
|
|
10
16
|
}
|
package/dist/pc/pc.recalc.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
|
|
|
4
4
|
import type { EntityRegistry } from "@archivist-gg/core";
|
|
5
5
|
import { type UnarmedStrikeSpec } from "./pc.equipment.js";
|
|
6
6
|
import { type FeatureEffectTotals } from "./pc.feature-effects.js";
|
|
7
|
-
import type { ACTerm, DerivedStats, ProficiencySet, ResolvedCharacter, ResolvedClass, CharacterOverrides } from "./pc.types.js";
|
|
7
|
+
import type { ACTerm, AttackRow, DamageRider, DerivedStats, ProficiencySet, ResolvedCharacter, ResolvedClass, CharacterOverrides } from "./pc.types.js";
|
|
8
8
|
/**
|
|
9
9
|
* PHB "fixed average" value per hit die (per level beyond first). Called
|
|
10
10
|
* "average" in the PHB but actually ceil((die + 1) / 2); equivalent to
|
|
@@ -23,19 +23,14 @@ export declare function parseDieSize(die: string | number | undefined | null): n
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function flattenRaceAsi(race: RaceEntity | null): Partial<Record<Ability, number>>;
|
|
25
25
|
/**
|
|
26
|
-
* Sums the LEGACY class-level ASI-BRANCH allocations (`choices[lvl].asi`) per
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* rather than a feat. Shared by both `computeAbilityScores`' fold and
|
|
30
|
-
* `abilityBonusBreakdown`'s `class` bucket so the two reads can never drift.
|
|
26
|
+
* Sums the LEGACY class-level ASI-BRANCH allocations (`choices[lvl].asi`) per ability across every class: the path of an
|
|
27
|
+
* L4/L8-style "Ability Score Increase or Feat" decision saved on the plain +2 ASI branch rather than a feat. Shared by
|
|
28
|
+
* `computeAbilityScores`' fold and `abilityBonusBreakdown`'s `class` bucket so the two reads can never drift.
|
|
31
29
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* discarded as an orphan rather than folded: that level took the feat branch, and
|
|
37
|
-
* the `asi` beside it is residue the picker never cleared on a branch switch.
|
|
38
|
-
* Folding both paid the same slot twice (Volker.md drew FOUR points from one L4).
|
|
30
|
+
* The level gate is the ONE predicate `legacyAsiBranch` (pc.asi-flatten.ts, H234 H4(2)), shared with the Builder's ledger
|
|
31
|
+
* alias and write path: a level whose `feat` is a string took the feat branch, and its `asi` is an orphan discarded since
|
|
32
|
+
* R4-P4 Decision B (Volker.md drew FOUR points from one L4 when both folded). Disjoint from chosen-feat ability-points
|
|
33
|
+
* (`choices[lvl]["feat:<id>"]`, collectClassFeatAbilityPoints) and from origin ability-points: no source double-counts.
|
|
39
34
|
*/
|
|
40
35
|
export declare function collectClassAsiBranch(resolved: ResolvedCharacter): Partial<Record<Ability, number>>;
|
|
41
36
|
/** Per-ability bonus provenance for the builder's obelisk captions:
|
|
@@ -69,6 +64,10 @@ export declare function hpLevelCount(classes: ResolvedClass[]): number;
|
|
|
69
64
|
* so a later popup can render the two components separately.
|
|
70
65
|
*/
|
|
71
66
|
export declare function multiclassMaxHP(classes: ResolvedClass[], conMod: number): number;
|
|
67
|
+
/** Does a damage rider reach this attack row (ART-c1 Task 9b, controller ruling 8)? A rider with no `scope` reaches
|
|
68
|
+
* every row (today's reach); a scoped one reaches a row when ANY of its words matches it: `melee` / `ranged` the
|
|
69
|
+
* row's `weaponCategory`, `unarmed` the engine's Unarmed Strike row, `finesse` / `thrown` the row's properties. */
|
|
70
|
+
export declare function riderReachesRow(rider: DamageRider, row: AttackRow): boolean;
|
|
72
71
|
/**
|
|
73
72
|
* The BEST APPLICABLE unarmoured formula (R4-G7 T6a, spec §4): the plain 10 + DEX mod, against every
|
|
74
73
|
* `unarmored-ac` effect that folds right now (its `base ?? 10` plus the modifier of every ability its
|
|
@@ -121,29 +120,33 @@ export declare function speedFromRace(resolved: ResolvedCharacter): number;
|
|
|
121
120
|
* double-counts. The chosen feat entity is resolved from `resolved.feats`
|
|
122
121
|
* (already looked up by the resolver) — no registry needed here.
|
|
123
122
|
*
|
|
124
|
-
* The L19 Epic Boon folds through this SAME path, but only as of R4-P4's
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* the
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* (
|
|
137
|
-
* `
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
123
|
+
* The L19 Epic Boon folds through this SAME path, but only as of R4-P4's re-key
|
|
124
|
+
* (live in the SRD data from that phase's regeneration). This docblock earlier
|
|
125
|
+
* cited it as an existing example, which it was not. EVERY reader OF THE FEAT
|
|
126
|
+
* PICK keys on the LITERAL string `feat`, and there are FOUR of them, not the two
|
|
127
|
+
* the R4-P4 spec §2.3 and task brief enumerate: this function (`block.feat`,
|
|
128
|
+
* below), `collectFeatPicks` (pc.resolver.ts), `PCResolver.resolve`'s
|
|
129
|
+
* feat-to-spell application pass, the two `collectFeatGrantedSpells` calls
|
|
130
|
+
* (pc.resolver.ts), the one that makes a SPELL-granting boon work, and
|
|
131
|
+
* `visitProficiencyChoices`' arm (A) (pc.decision-engine.ts, R4-G3b §8), which
|
|
132
|
+
* reads `block.feat` to walk the chosen feat's own proficiency choices. Note the
|
|
133
|
+
* qualifier: this is NOT a claim that every reader of a saved class choice block
|
|
134
|
+
* keys on `feat`. Others read the very same block by OTHER keys ·
|
|
135
|
+
* `collectClassAsiBranch` (above) reads the legacy `.asi` through
|
|
136
|
+
* `legacyAsiBranch` (pc.asi-flatten.ts), while `resolvePool` (pc.pools.ts) and
|
|
137
|
+
* `resolveChosenInline` (pc.resolver.ts) read by a DYNAMIC pool/choice id.
|
|
138
|
+
* `legacyAsiBranch` also tests `block.feat`, but only to DETECT the feat branch
|
|
139
|
+
* (R4-P4 Decision B), not to consume the pick. pc.decision-engine.ts's LEDGER
|
|
140
|
+
* (`buildItem`) is NOT a reader: it reads generically by `choice.id`, which is
|
|
141
|
+
* exactly why re-keying works at all; since H234 its class walk also SYNTHESIZES
|
|
142
|
+
* a `feat` answer, the read-only alias for a level saved in the older ASI shape
|
|
143
|
+
* (`legacyAsiReader`), which consumes no persisted `feat` key. srd-2024.yaml
|
|
144
|
+
* authored the boon's pick `id: epic-boon`, so an L19 selection persisted under
|
|
145
|
+
* `choices[19]["epic-boon"]`, which no reader looks at: the boon resolved to no
|
|
146
|
+
* feat, granted no spells, and contributed no ability points at all. Re-keying
|
|
147
|
+
* the authored pick to `id: feat` is what makes it fold. No persisted GRANDCHILD
|
|
148
|
+
* key moved with it · pc.decision-engine.ts builds `feat:<childId>` off a
|
|
149
|
+
* hardcoded prefix, independent of the parent choice's own id.
|
|
147
150
|
*
|
|
148
151
|
* Clamps defensively (per-ability max_per, then stops at the points total in
|
|
149
152
|
* ABILITY_KEYS order), mirroring collectChosenAbilityPoints.
|