@archivist-gg/dnd5e 0.1.1 → 0.2.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-FUK7QSN5.js → chunk-42Y5IJKT.js} +1 -1
- package/dist/{chunk-TPZSPU4L.js → chunk-4JHOHWBI.js} +1 -1
- package/dist/{chunk-ZLG6FQFB.js → chunk-5WQD3WNZ.js} +16 -1
- package/dist/{chunk-FEOB24KP.js → chunk-73HOFQQ5.js} +1 -1
- package/dist/{chunk-YDPWD2T7.js → chunk-7VJ6BOA5.js} +4 -1
- package/dist/{chunk-DABBCYTT.js → chunk-CZPMTQOY.js} +1 -1
- package/dist/{chunk-DRNZJNJP.js → chunk-DZXSWSBP.js} +1 -1
- 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-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-R5SQHP2X.js +1092 -0
- package/dist/{chunk-Z6GXV2GO.js → chunk-TLYDBT5F.js} +1 -1
- package/dist/{chunk-ADLTSHOR.js → chunk-TQZB4OCJ.js} +16 -12
- package/dist/{chunk-A7T5L7SS.js → chunk-TUIFSVLI.js} +1 -1
- package/dist/{chunk-GEJSJP6E.js → chunk-V6SOFUJW.js} +1 -1
- 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/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 +321 -75
- package/dist/item/item.actions-map.d.ts +10 -3
- package/dist/item/item.actions-map.js +13 -8
- 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.js +8 -1
- package/dist/pc/pc.equipment.js +7 -3
- package/dist/pc/pc.feature-effects.js +9 -2
- package/dist/pc/pc.parser.js +1 -1
- package/dist/pc/pc.pools.js +8 -3
- package/dist/pc/pc.recalc.js +20 -10
- package/dist/pc/pc.resolver.d.ts +59 -1
- package/dist/pc/pc.resolver.js +20 -342
- package/dist/pc/pc.schema.d.ts +21 -0
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.types.d.ts +37 -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/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/package.json +1 -1
- package/dist/chunk-6PXE7T7C.js +0 -79
- package/dist/chunk-TJCNX6UZ.js +0 -521
|
@@ -33,9 +33,16 @@ export declare const ITEM_ACTIONS: Record<string, ItemAction>;
|
|
|
33
33
|
export declare function findItemAction(slug: string): ItemAction | undefined;
|
|
34
34
|
/**
|
|
35
35
|
* Resolve the ItemAction for an equipped entry.
|
|
36
|
-
* Priority:
|
|
37
|
-
*
|
|
36
|
+
* Priority: per-instance override > curated map > `itemType==="potion"`
|
|
37
|
+
* bonus-action default > null.
|
|
38
|
+
*
|
|
39
|
+
* `itemType` is the entity's `data.type` (from the registry, statically
|
|
40
|
+
* `unknown`); per the 2024 SRD, drinking/administering a potion is a Bonus
|
|
41
|
+
* Action, so an uncurated `type==="potion"` item still surfaces (curated oils
|
|
42
|
+
* mis-typed `"potion"` are pinned to "action" so this default cannot mislabel
|
|
43
|
+
* them). Returns null when no source supplies a cost (non-potion uncurated with
|
|
44
|
+
* no override).
|
|
38
45
|
*
|
|
39
46
|
* Accepts both bare and compendium-prefixed slugs (see `findItemAction`).
|
|
40
47
|
*/
|
|
41
|
-
export declare function resolveItemAction(slug: string, entry: EquipmentEntry): ItemAction | null;
|
|
48
|
+
export declare function resolveItemAction(slug: string, entry: EquipmentEntry, itemType?: unknown): ItemAction | null;
|
|
@@ -46,13 +46,19 @@ var ITEM_ACTIONS = {
|
|
|
46
46
|
// Magic weapons with activation actions (surface in items table only via override; weapons table is primary)
|
|
47
47
|
"sun-blade": { cost: "free", range: "self" },
|
|
48
48
|
// Potions / consumables
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"potion-of-
|
|
52
|
-
"potion-of-
|
|
49
|
+
// 2024 healing potions are a Bonus Action to drink/administer (curation still
|
|
50
|
+
// carries range/max_charges/recovery; the type=potion default covers uncurated ones).
|
|
51
|
+
"potion-of-healing": { cost: "bonus-action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
52
|
+
"potion-of-greater-healing": { cost: "bonus-action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
53
|
+
"potion-of-superior-healing": { cost: "bonus-action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
54
|
+
"potion-of-supreme-healing": { cost: "bonus-action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
53
55
|
"alchemists-fire": { cost: "action", range: "20 ft.", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
54
56
|
"holy-water": { cost: "action", range: "20 ft.", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
57
|
+
// Oils are APPLIED (minutes), not drunk: curated to "action" so the blanket
|
|
58
|
+
// type=potion → bonus-action default never mislabels these mis-typed items.
|
|
55
59
|
"oil-of-sharpness": { cost: "action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
60
|
+
"oil-of-etherealness": { cost: "action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
61
|
+
"oil-of-slipperiness": { cost: "action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } },
|
|
56
62
|
"dust-of-disappearance": { cost: "action", range: "self", max_charges: 1, recovery: { amount: "0", reset: "special" } }
|
|
57
63
|
};
|
|
58
64
|
function findItemAction(slug) {
|
|
@@ -62,14 +68,13 @@ function findItemAction(slug) {
|
|
|
62
68
|
const bare = slug.slice(underscore + 1);
|
|
63
69
|
return ITEM_ACTIONS[bare];
|
|
64
70
|
}
|
|
65
|
-
function resolveItemAction(slug, entry) {
|
|
66
|
-
var _a;
|
|
71
|
+
function resolveItemAction(slug, entry, itemType) {
|
|
72
|
+
var _a, _b;
|
|
67
73
|
const curated = (_a = findItemAction(slug)) != null ? _a : null;
|
|
68
74
|
const override = entry.overrides;
|
|
69
75
|
const overrideCost = override == null ? void 0 : override.action;
|
|
70
76
|
const overrideRange = override == null ? void 0 : override.range;
|
|
71
|
-
|
|
72
|
-
const cost = overrideCost != null ? overrideCost : curated == null ? void 0 : curated.cost;
|
|
77
|
+
const cost = (_b = overrideCost != null ? overrideCost : curated == null ? void 0 : curated.cost) != null ? _b : itemType === "potion" ? "bonus-action" : void 0;
|
|
73
78
|
if (!cost) return null;
|
|
74
79
|
return {
|
|
75
80
|
cost,
|
package/dist/item/item.codec.js
CHANGED
package/dist/item/item.parser.js
CHANGED
|
@@ -175,6 +175,9 @@ export declare const itemEntitySchema: z.ZodObject<{
|
|
|
175
175
|
}>>;
|
|
176
176
|
condition: z.ZodOptional<z.ZodString>;
|
|
177
177
|
}, z.core.$strip>>>;
|
|
178
|
+
scroll_level: z.ZodOptional<z.ZodNumber>;
|
|
179
|
+
unidentified: z.ZodOptional<z.ZodBoolean>;
|
|
180
|
+
masked_category: z.ZodOptional<z.ZodString>;
|
|
178
181
|
raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
179
182
|
damage_dice: z.ZodOptional<z.ZodString>;
|
|
180
183
|
damage_type: z.ZodOptional<z.ZodString>;
|
package/dist/item/item.schema.js
CHANGED
|
@@ -106,6 +106,14 @@ export interface ItemEntity {
|
|
|
106
106
|
applies_to?: "weapon" | "spell" | "all";
|
|
107
107
|
condition?: string;
|
|
108
108
|
}>;
|
|
109
|
+
/** Spell-scroll casting level (e.g. 3 for a "Spell Scroll (3rd Level)"). */
|
|
110
|
+
scroll_level?: number;
|
|
111
|
+
/** Marks an item the player has not yet identified: the sheet shows the
|
|
112
|
+
* masked_category label instead of the item's true identity. */
|
|
113
|
+
unidentified?: boolean;
|
|
114
|
+
/** Generic category label shown for an unidentified item (e.g. "potion",
|
|
115
|
+
* "scroll", "wand") in place of its real name. */
|
|
116
|
+
masked_category?: string;
|
|
109
117
|
raw?: Record<string, unknown>;
|
|
110
118
|
damage_dice?: string;
|
|
111
119
|
damage_type?: string;
|
|
@@ -5,9 +5,16 @@ import {
|
|
|
5
5
|
collectChosenAbilityPoints,
|
|
6
6
|
collectChosenProficiencies,
|
|
7
7
|
wikilinkTailSlug
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-R5SQHP2X.js";
|
|
9
9
|
import "../chunk-BH6AMZVY.js";
|
|
10
|
+
import "../chunk-UC4FE5X3.js";
|
|
11
|
+
import "../chunk-IXZXFFFW.js";
|
|
12
|
+
import "../chunk-5XUXXAQJ.js";
|
|
10
13
|
import "../chunk-JEYQU3JT.js";
|
|
14
|
+
import "../chunk-DC74TZNA.js";
|
|
15
|
+
import "../chunk-3TRGRSCH.js";
|
|
16
|
+
import "../chunk-J2RYSZMQ.js";
|
|
17
|
+
import "../chunk-NAEPSZAM.js";
|
|
11
18
|
import "../chunk-WP2CX2JO.js";
|
|
12
19
|
export {
|
|
13
20
|
__matchesFilterForTest,
|
package/dist/pc/pc.equipment.js
CHANGED
|
@@ -2,15 +2,19 @@ import {
|
|
|
2
2
|
computeAppliedBonuses,
|
|
3
3
|
computeSlotsAndAttacks,
|
|
4
4
|
emptyAppliedBonuses
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-TJCNX6UZ.js";
|
|
5
|
+
} from "../chunk-TQZB4OCJ.js";
|
|
6
|
+
import "../chunk-R5SQHP2X.js";
|
|
8
7
|
import "../chunk-BH6AMZVY.js";
|
|
8
|
+
import "../chunk-UC4FE5X3.js";
|
|
9
|
+
import "../chunk-IXZXFFFW.js";
|
|
10
|
+
import "../chunk-5XUXXAQJ.js";
|
|
9
11
|
import "../chunk-JEYQU3JT.js";
|
|
10
12
|
import "../chunk-LWFTHJIE.js";
|
|
11
13
|
import "../chunk-DNAJRMNN.js";
|
|
12
14
|
import "../chunk-DC74TZNA.js";
|
|
13
15
|
import "../chunk-3TRGRSCH.js";
|
|
16
|
+
import "../chunk-J2RYSZMQ.js";
|
|
17
|
+
import "../chunk-NAEPSZAM.js";
|
|
14
18
|
import "../chunk-WP2CX2JO.js";
|
|
15
19
|
export {
|
|
16
20
|
computeAppliedBonuses,
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeFeatureEffects,
|
|
3
3
|
emptyFeatureEffectTotals
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-V6SOFUJW.js";
|
|
5
|
+
import "../chunk-R5SQHP2X.js";
|
|
6
6
|
import "../chunk-BH6AMZVY.js";
|
|
7
|
+
import "../chunk-UC4FE5X3.js";
|
|
8
|
+
import "../chunk-IXZXFFFW.js";
|
|
9
|
+
import "../chunk-5XUXXAQJ.js";
|
|
7
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";
|
|
8
15
|
import "../chunk-WP2CX2JO.js";
|
|
9
16
|
export {
|
|
10
17
|
computeFeatureEffects,
|
package/dist/pc/pc.parser.js
CHANGED
package/dist/pc/pc.pools.js
CHANGED
|
@@ -2,11 +2,16 @@ import {
|
|
|
2
2
|
levelPrereqMax,
|
|
3
3
|
resolveAllPools,
|
|
4
4
|
resolvePool
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-5XUXXAQJ.js";
|
|
7
|
-
import "../chunk-TJCNX6UZ.js";
|
|
5
|
+
} from "../chunk-R5SQHP2X.js";
|
|
8
6
|
import "../chunk-BH6AMZVY.js";
|
|
7
|
+
import "../chunk-UC4FE5X3.js";
|
|
8
|
+
import "../chunk-IXZXFFFW.js";
|
|
9
|
+
import "../chunk-5XUXXAQJ.js";
|
|
9
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";
|
|
10
15
|
import "../chunk-WP2CX2JO.js";
|
|
11
16
|
export {
|
|
12
17
|
levelPrereqMax,
|
package/dist/pc/pc.recalc.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computeSpellLimits,
|
|
3
|
-
deriveSpellSlots,
|
|
4
|
-
resolveSpellcasting
|
|
5
|
-
} from "../chunk-IXZXFFFW.js";
|
|
6
|
-
import "../chunk-5XUXXAQJ.js";
|
|
7
1
|
import {
|
|
8
2
|
computeConditionEffects
|
|
9
3
|
} from "../chunk-R2ZV233X.js";
|
|
@@ -11,16 +5,22 @@ import {
|
|
|
11
5
|
computeAppliedBonuses,
|
|
12
6
|
computeSlotsAndAttacks,
|
|
13
7
|
emptyAppliedBonuses
|
|
14
|
-
} from "../chunk-
|
|
15
|
-
import "../chunk-UC4FE5X3.js";
|
|
8
|
+
} from "../chunk-TQZB4OCJ.js";
|
|
16
9
|
import {
|
|
17
10
|
computeFeatureEffects
|
|
18
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-V6SOFUJW.js";
|
|
19
12
|
import {
|
|
20
13
|
collectChosenAbilityPoints,
|
|
21
14
|
collectChosenProficiencies
|
|
22
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-R5SQHP2X.js";
|
|
23
16
|
import "../chunk-BH6AMZVY.js";
|
|
17
|
+
import "../chunk-UC4FE5X3.js";
|
|
18
|
+
import {
|
|
19
|
+
computeSpellLimits,
|
|
20
|
+
deriveSpellSlots,
|
|
21
|
+
resolveSpellcasting
|
|
22
|
+
} from "../chunk-IXZXFFFW.js";
|
|
23
|
+
import "../chunk-5XUXXAQJ.js";
|
|
24
24
|
import "../chunk-JEYQU3JT.js";
|
|
25
25
|
import "../chunk-LWFTHJIE.js";
|
|
26
26
|
import "../chunk-DNAJRMNN.js";
|
|
@@ -574,6 +574,15 @@ function recalc(resolved, registry) {
|
|
|
574
574
|
saveDC: spellcastingClasses[0].saveDC,
|
|
575
575
|
attackBonus: spellcastingClasses[0].attackBonus
|
|
576
576
|
} : null;
|
|
577
|
+
const abilitySpellcasting = {};
|
|
578
|
+
for (const s of resolved.spells) {
|
|
579
|
+
const ab = s.ability;
|
|
580
|
+
if (!ab || abilitySpellcasting[ab]) continue;
|
|
581
|
+
abilitySpellcasting[ab] = {
|
|
582
|
+
saveDC: saveDC(scores[ab], proficiencyBonus) + applied.spell_save_dc,
|
|
583
|
+
attackBonus: attackBonus(scores[ab], proficiencyBonus) + applied.spell_attack
|
|
584
|
+
};
|
|
585
|
+
}
|
|
577
586
|
const derivedSlots = deriveSpellSlots(slotInputs);
|
|
578
587
|
const spellLimits = computeSpellLimits(limitInputs);
|
|
579
588
|
const defenses = {
|
|
@@ -616,6 +625,7 @@ function recalc(resolved, registry) {
|
|
|
616
625
|
initiative: init,
|
|
617
626
|
spellcasting,
|
|
618
627
|
spellcastingClasses,
|
|
628
|
+
abilitySpellcasting,
|
|
619
629
|
derivedSpellSlots: derivedSlots.standard,
|
|
620
630
|
pactMagic: derivedSlots.pact,
|
|
621
631
|
spellLimits,
|
package/dist/pc/pc.resolver.d.ts
CHANGED
|
@@ -2,12 +2,28 @@ import type { EntityRegistry } from "@archivist-gg/core";
|
|
|
2
2
|
import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
|
|
3
3
|
import type { BackgroundEntity } from "@archivist-gg/dnd5e/background/background.types";
|
|
4
4
|
import type { FeatEntity } from "@archivist-gg/dnd5e/feat/feat.types";
|
|
5
|
-
import type {
|
|
5
|
+
import type { Ability } from "@archivist-gg/dnd5e";
|
|
6
|
+
import type { Character, ChoiceValue, ResolvedCharacter, ResolvedClass, ResolvedFeature, ResolvedSpell } from "./pc.types.js";
|
|
6
7
|
export interface ResolveResult {
|
|
7
8
|
character: ResolvedCharacter;
|
|
8
9
|
warnings: string[];
|
|
9
10
|
}
|
|
10
11
|
export declare function stripSlug(ref: string | null): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a background's `origin_feat` wikilink into a real FeatEntity + a display
|
|
14
|
+
* name, using ONLY the EntityRegistry (no DOM). Lifted from the builder's
|
|
15
|
+
* background-step so the resolver pipeline and the builder share ONE resolution
|
|
16
|
+
* (R2-m7, [[always-retire-shims-edit-all]]). Handles both path-style refs
|
|
17
|
+
* ("[[SRD 2024/Feats/Alert]]") and bare-slug refs ("[[my-feat]]"), plus the 2024
|
|
18
|
+
* parenthetical-variant refs ("[[SRD 2024/Feats/Magic Initiate (Cleric)]]") that
|
|
19
|
+
* resolve to the BASE feat ("magic-initiate") while keeping the full variant
|
|
20
|
+
* string as the display name. Returns null when the ref is empty or resolves to no
|
|
21
|
+
* feat (an unresolvable ref folds nothing into the pipeline).
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveOriginFeat(entities: EntityRegistry, originFeatRef: string | null): {
|
|
24
|
+
feat: FeatEntity;
|
|
25
|
+
display: string;
|
|
26
|
+
} | null;
|
|
11
27
|
export declare class PCResolver {
|
|
12
28
|
private readonly entities;
|
|
13
29
|
constructor(entities: EntityRegistry);
|
|
@@ -32,6 +48,48 @@ export declare function collectChosenWeaponMasteries(character: Character): {
|
|
|
32
48
|
* Returns bare slugs (no `[[ ]]`).
|
|
33
49
|
*/
|
|
34
50
|
export declare function collectFeatSlugs(character: Character): string[];
|
|
51
|
+
/**
|
|
52
|
+
* Feat→spell application (3d). Walks a feat's OWN `choices` to find its spell
|
|
53
|
+
* picks and turns each into a ResolvedSpell. A feat's spells sit behind a
|
|
54
|
+
* `spell-list` select-inline whose CHOSEN branch nests `select-entity{spell}`
|
|
55
|
+
* picks; the chosen spellcasting ability comes from the feat's
|
|
56
|
+
* `spellcasting-ability` select-inline. `read(childId)` yields the persisted pick
|
|
57
|
+
* for a child choice id (origin feat: `origin_choices["background:feat:<id>"]`;
|
|
58
|
+
* class-slot feat: `choices[lvl]["feat:<id>"]`). Unresolvable spell slugs warn and
|
|
59
|
+
* are skipped, mirroring the known-spell loop. classSlug stays null: a feat spell
|
|
60
|
+
* is not owned by a class for DC/ability; the carried `ability` drives its casting.
|
|
61
|
+
*/
|
|
62
|
+
export declare function collectFeatGrantedSpells(feat: FeatEntity, read: (childId: string) => ChoiceValue | undefined, entities: EntityRegistry, warnings: string[]): ResolvedSpell[];
|
|
63
|
+
/**
|
|
64
|
+
* Item→spell application (P4-T3). Walks the character's equipment for entries whose
|
|
65
|
+
* resolved item is a spell scroll (carries the T1 `scroll_level` marker) AND names a
|
|
66
|
+
* chosen spell via `overrides.spell`, turning each into a
|
|
67
|
+
* ResolvedSpell{ source:"item", classSlug:null, prepared:true, alwaysPrepared:true }.
|
|
68
|
+
* The casting `ability` is the character's OWN spellcasting ability when they have
|
|
69
|
+
* one (`ownAbility`, the first caster class's ability), else the per-instance
|
|
70
|
+
* `overrides.spell_ability`, else undefined (a no-ability scroll is left ability-less:
|
|
71
|
+
* the plugin surfaces it without a DC; an ability is NEVER fabricated here).
|
|
72
|
+
* `entryIndex` records the originating equipment index so the segmented dedupe keeps
|
|
73
|
+
* two scrolls of one spell (and a scroll of a class-known spell) as their own rows.
|
|
74
|
+
* Unresolvable spell slugs warn and are skipped, mirroring the known-spell + feat loops.
|
|
75
|
+
* In-memory only: no KnownSpellObject{source:"item"} is injected (its strict schema
|
|
76
|
+
* omits `ability`).
|
|
77
|
+
*/
|
|
78
|
+
export declare function collectItemGrantedSpells(character: Character, ownAbility: Ability | null, entities: EntityRegistry, warnings: string[]): ResolvedSpell[];
|
|
79
|
+
/**
|
|
80
|
+
* Collapses duplicate resolved spells (3d Minor #2 carry-forward + P4-T3 segmented
|
|
81
|
+
* dedupe). A spell can be emitted more than once: it may be BOTH in
|
|
82
|
+
* `character.spells.known` AND a feat pick, or a feat may be taken as both origin +
|
|
83
|
+
* class-slot. A class-sourced copy owns a real DC via its `classSlug`, so it always
|
|
84
|
+
* wins over a feat copy of the same slug; otherwise first-seen wins. Insertion order
|
|
85
|
+
* is preserved (a later class copy replaces an earlier feat copy in place), so the
|
|
86
|
+
* Spells section never renders duplicate rows while a legitimately class-known copy is
|
|
87
|
+
* never lost. Item-source spells carry INSTANCE identity: they key by
|
|
88
|
+
* `slug + "#" + entryIndex`, so two scrolls of one spell stay two rows and a scroll of
|
|
89
|
+
* a class-known spell keeps its OWN item row, never collapsing into / being collapsed
|
|
90
|
+
* by a class/feat copy. The class/feat slug-only merge is unchanged.
|
|
91
|
+
*/
|
|
92
|
+
export declare function dedupeResolvedSpells(spells: ResolvedSpell[]): ResolvedSpell[];
|
|
35
93
|
/** Selected select-entity values (optional-features) and selected inline
|
|
36
94
|
* options carrying effects[] become synthesized resolved features (SP2 Plan 3 §9).
|
|
37
95
|
* The actions/resources engines consume these synthesized features, and the
|