@archivist-gg/dnd5e 0.3.0 → 0.3.4
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 +25 -6
- package/dist/armor/armor.codec.js +4 -3
- package/dist/armor/armor.parser.js +3 -2
- package/dist/armor/armor.schema.d.ts +4 -0
- package/dist/armor/armor.schema.js +2 -1
- package/dist/armor/armor.types.d.ts +8 -0
- package/dist/background/background.codec.js +7 -6
- package/dist/background/background.parser.js +6 -5
- package/dist/background/background.schema.d.ts +34 -0
- package/dist/background/background.schema.js +9 -6
- package/dist/background/background.types.d.ts +22 -0
- package/dist/{chunk-4TIJKN6O.js → chunk-23LZLBJK.js} +1 -1
- package/dist/{chunk-AFKTJXRA.js → chunk-2DFENQIJ.js} +18 -0
- package/dist/chunk-2FRUSVZS.js +489 -0
- package/dist/chunk-4FWNK4FD.js +159 -0
- package/dist/chunk-4U55VNC7.js +22 -0
- package/dist/{chunk-4JHOHWBI.js → chunk-4XTNPNQB.js} +1 -1
- package/dist/{chunk-HCP3GMHS.js → chunk-5N2GW72F.js} +15 -2
- package/dist/{chunk-42Y5IJKT.js → chunk-5U5FFFA3.js} +5 -1
- package/dist/{chunk-4F6AIZ36.js → chunk-5XMQPTHD.js} +1 -1
- package/dist/{chunk-GJOI2GHP.js → chunk-6GNXYAYP.js} +1 -1
- package/dist/chunk-6PKV5V2H.js +178 -0
- package/dist/{chunk-66XXW2Z2.js → chunk-6PXTNCBP.js} +2 -2
- package/dist/chunk-6X2NV665.js +33 -0
- package/dist/{chunk-LV4SNWZQ.js → chunk-6X4KUDMU.js} +8 -1
- package/dist/{chunk-ZMR77DDL.js → chunk-AW3EHF3L.js} +1 -1
- package/dist/chunk-CJYCVNW2.js +7 -0
- package/dist/chunk-COEOOQX2.js +133 -0
- package/dist/{chunk-XTIQWSFM.js → chunk-D5U7GMPX.js} +1 -1
- package/dist/{chunk-RAWJTA45.js → chunk-DEEHHLAP.js} +1 -1
- package/dist/chunk-DPUJDOKV.js +365 -0
- package/dist/{chunk-73HOFQQ5.js → chunk-ESS46GR4.js} +1 -1
- package/dist/chunk-EVMUJYUD.js +195 -0
- package/dist/{chunk-2BWAID3Y.js → chunk-FDBWYMZK.js} +29 -3
- package/dist/{chunk-K6Q5OUGK.js → chunk-GFZ7PITJ.js} +86 -10
- package/dist/chunk-H7KBLR4X.js +81 -0
- package/dist/{chunk-L7E2UT5A.js → chunk-HB7XZXDK.js} +5 -1
- package/dist/{chunk-VTYUBINW.js → chunk-HJ5EEZ47.js} +1 -1
- package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
- package/dist/{chunk-A4WENOUQ.js → chunk-I2NDWFDD.js} +52 -8
- package/dist/{chunk-RSDRMH54.js → chunk-IMZFOOVL.js} +1 -1
- package/dist/{chunk-3DZ74AKK.js → chunk-IN4M4X7P.js} +8 -2
- package/dist/chunk-IUAAXXNO.js +58 -0
- package/dist/{chunk-XJNECUPT.js → chunk-JC5UNIVM.js} +19 -0
- package/dist/chunk-JJ46T5XX.js +297 -0
- package/dist/{chunk-TUIFSVLI.js → chunk-JRDPUDT5.js} +30 -3
- package/dist/{chunk-24GFQU7T.js → chunk-JSZ4H6AQ.js} +1 -1
- package/dist/chunk-KU3YLF6D.js +106 -0
- package/dist/{chunk-5INR4NSL.js → chunk-LDDCNPHD.js} +1 -1
- package/dist/{chunk-DZXSWSBP.js → chunk-LMBAEIP6.js} +1 -1
- package/dist/chunk-LVQLWRCU.js +15 -0
- package/dist/chunk-MI7P3NX3.js +161 -0
- package/dist/chunk-O4SRD3J5.js +165 -0
- package/dist/{chunk-EMOORSQ7.js → chunk-OSQFPGLM.js} +45 -6
- package/dist/chunk-OZP6JFGT.js +162 -0
- package/dist/{chunk-NAEPSZAM.js → chunk-PDJSUH24.js} +24 -2
- package/dist/chunk-PP2UHLBA.js +50 -0
- package/dist/chunk-PVCEA4HZ.js +6 -0
- package/dist/{chunk-XLSVNUTK.js → chunk-R3VAKWKW.js} +1 -1
- package/dist/chunk-RIXI5D3R.js +89 -0
- package/dist/chunk-RLGQ5PZZ.js +16 -0
- package/dist/chunk-S7REMWW4.js +21 -0
- package/dist/{chunk-7VJ6BOA5.js → chunk-SMLXZUBH.js} +9 -1
- package/dist/{chunk-NXSWH3AE.js → chunk-T26ZVCL5.js} +1 -1
- package/dist/chunk-TOM66P2P.js +38 -0
- package/dist/chunk-UA5KS2PL.js +26 -0
- package/dist/{chunk-N6N74K6X.js → chunk-UBBKSYBY.js} +1 -1
- package/dist/{chunk-353WXS6S.js → chunk-UIRMA5KM.js} +1 -1
- package/dist/{chunk-GE4TLPWM.js → chunk-US5IKYCW.js} +1 -1
- package/dist/chunk-UXPGW4TI.js +101 -0
- package/dist/chunk-VQAXTIBW.js +100 -0
- package/dist/{chunk-WP2CX2JO.js → chunk-WELIKLZF.js} +22 -1
- package/dist/chunk-WPWOHGPI.js +172 -0
- package/dist/{chunk-GZ46OVGZ.js → chunk-WSVMLNTO.js} +1 -1
- package/dist/{chunk-4LZJXJJS.js → chunk-WXWPK3LI.js} +6 -2
- package/dist/{chunk-ZZGEVJKX.js → chunk-XBQMCEI2.js} +1 -1
- package/dist/{chunk-PHQRGDRQ.js → chunk-XGOFP7AQ.js} +5 -1
- package/dist/chunk-XJ2F2WO6.js +8 -0
- package/dist/chunk-XQCSGNXE.js +1580 -0
- package/dist/chunk-YBLDE5CG.js +42 -0
- package/dist/{chunk-JEYQU3JT.js → chunk-YHYTW5QA.js} +2 -18
- package/dist/{chunk-TLYDBT5F.js → chunk-YJJTISBN.js} +64 -7
- package/dist/{chunk-PZOWBI3B.js → chunk-YLL2QXY2.js} +7 -2
- package/dist/{chunk-MDEJHMKK.js → chunk-ZONJ66NE.js} +26 -5
- package/dist/class/class.codec.js +12 -9
- package/dist/class/class.parser.js +11 -8
- package/dist/class/class.schema.d.ts +55 -3
- package/dist/class/class.schema.js +9 -7
- package/dist/class/class.types.d.ts +48 -3
- package/dist/condition/condition.codec.d.ts +9 -0
- package/dist/condition/condition.entity-type.d.ts +2 -0
- package/dist/condition/condition.parser.d.ts +13 -0
- package/dist/condition/condition.parser.js +7 -0
- package/dist/condition/condition.schema.d.ts +29 -0
- package/dist/condition/condition.types.d.ts +15 -0
- package/dist/condition/condition.types.js +0 -0
- package/dist/dnd/constants.d.ts +22 -0
- package/dist/dnd/constants.js +9 -3
- package/dist/dnd/formula-tags.js +2 -2
- package/dist/dnd/math.d.ts +26 -0
- package/dist/dnd/math.js +12 -2
- package/dist/dnd/prose-tags.js +1 -1
- package/dist/dnd/resource-formula.d.ts +36 -10
- package/dist/dnd/resource-formula.js +10 -155
- package/dist/dnd/srd-tag-converter.js +3 -3
- package/dist/dnd/tag-grammar.js +1 -1
- package/dist/dnd/warn-once.d.ts +2 -0
- package/dist/dnd/warn-once.js +8 -0
- package/dist/entities/base-item-resolver.js +2 -2
- package/dist/entities/slug.d.ts +13 -0
- package/dist/entities/slug.js +5 -3
- package/dist/entities/wikilink-display.d.ts +3 -0
- package/dist/entities/wikilink-display.js +10 -0
- package/dist/feat/feat.category-codes.d.ts +32 -0
- package/dist/feat/feat.category-codes.js +14 -0
- package/dist/feat/feat.codec.js +7 -5
- package/dist/feat/feat.parser.js +6 -4
- package/dist/feat/feat.schema.d.ts +230 -0
- package/dist/feat/feat.schema.js +5 -3
- package/dist/feat/feat.types.d.ts +37 -1
- package/dist/index.js +2120 -6923
- package/dist/item/item.ai-schema.d.ts +1 -1
- package/dist/item/item.codec.js +4 -3
- package/dist/item/item.enrichment.js +4 -4
- package/dist/item/item.parser.js +3 -2
- package/dist/item/item.schema.d.ts +69 -3
- package/dist/item/item.schema.js +2 -1
- package/dist/item/item.types.d.ts +69 -3
- package/dist/monster/monster.codec.d.ts +7 -6
- package/dist/monster/monster.enrichment.js +4 -4
- package/dist/monster/monster.format.d.ts +135 -0
- package/dist/monster/monster.format.js +78 -0
- package/dist/monster/monster.parser.d.ts +6 -1
- package/dist/monster/monster.parser.js +10 -1
- package/dist/monster/monster.schema.d.ts +369 -0
- package/dist/monster/monster.schema.js +34 -0
- package/dist/monster/monster.types.d.ts +200 -14
- package/dist/optional-feature/optional-feature.codec.js +6 -5
- package/dist/optional-feature/optional-feature.parser.js +5 -4
- package/dist/optional-feature/optional-feature.schema.d.ts +176 -0
- package/dist/optional-feature/optional-feature.schema.js +4 -3
- package/dist/pack.d.ts +1 -1
- package/dist/pc/conditions.constants.d.ts +0 -1
- package/dist/pc/conditions.constants.js +1 -3
- package/dist/pc/decision-recognizer.js +1 -1
- package/dist/pc/pc.additional-spells.d.ts +47 -0
- package/dist/pc/pc.additional-spells.js +23 -0
- package/dist/pc/pc.asi-flatten.d.ts +18 -0
- package/dist/pc/pc.decision-engine.d.ts +106 -5
- package/dist/pc/pc.decision-engine.js +28 -10
- package/dist/pc/pc.defense-normalize.d.ts +11 -0
- package/dist/pc/pc.defense-normalize.js +6 -0
- package/dist/pc/pc.equipment.d.ts +30 -1
- package/dist/pc/pc.equipment.js +12 -7
- package/dist/pc/pc.feature-effects.d.ts +225 -11
- package/dist/pc/pc.feature-effects.js +21 -5
- package/dist/pc/pc.parser.js +2 -2
- package/dist/pc/pc.pools.d.ts +11 -3
- package/dist/pc/pc.pools.js +9 -13
- package/dist/pc/pc.proficiencies.d.ts +60 -4
- package/dist/pc/pc.proficiencies.js +89 -37
- package/dist/pc/pc.proficiency-grants.d.ts +58 -0
- package/dist/pc/pc.proficiency-normalize.d.ts +29 -0
- package/dist/pc/pc.proficiency-normalize.js +12 -0
- package/dist/pc/pc.proficiency-query.d.ts +13 -0
- package/dist/pc/pc.proficiency-query.js +5 -1
- package/dist/pc/pc.recalc.d.ts +69 -14
- package/dist/pc/pc.recalc.js +291 -142
- package/dist/pc/pc.resolver.d.ts +34 -8
- package/dist/pc/pc.resolver.js +27 -12
- package/dist/pc/pc.resource-seed.d.ts +3 -2
- package/dist/pc/pc.resource-seed.js +19 -17
- package/dist/pc/pc.resources.d.ts +87 -0
- package/dist/pc/pc.resources.js +21 -0
- package/dist/pc/pc.rest.d.ts +10 -1
- package/dist/pc/pc.rest.js +66 -12
- package/dist/pc/pc.schema.d.ts +147 -7
- package/dist/pc/pc.schema.js +4 -2
- package/dist/pc/pc.slotting.js +3 -3
- package/dist/pc/pc.spellcasting.d.ts +80 -7
- package/dist/pc/pc.spellcasting.js +18 -6
- package/dist/pc/pc.table-column.d.ts +23 -0
- package/dist/pc/pc.table-column.js +13 -3
- package/dist/pc/pc.types.d.ts +253 -16
- package/dist/pc/pool-layout.d.ts +47 -0
- package/dist/pc/pool-layout.js +16 -0
- package/dist/pc/roll-scope.d.ts +2 -0
- package/dist/pc/roll-scope.js +8 -0
- package/dist/pc/roll-tag-labels.d.ts +40 -0
- package/dist/pc/roll-tag-labels.js +17 -0
- package/dist/pc/spell-source.d.ts +21 -0
- package/dist/pc/spell-source.js +13 -0
- package/dist/race/race.codec.js +9 -7
- package/dist/race/race.parser.js +8 -6
- package/dist/race/race.schema.d.ts +51 -1
- package/dist/race/race.schema.js +8 -5
- package/dist/race/race.structural.d.ts +7 -0
- package/dist/race/race.structural.js +6 -0
- package/dist/race/race.types.d.ts +20 -0
- package/dist/schemas/attack-schema.d.ts +5 -0
- package/dist/schemas/caster-type-schema.d.ts +14 -0
- package/dist/schemas/caster-type-schema.js +6 -0
- package/dist/schemas/choice-schema.js +2 -2
- package/dist/schemas/entity-extras-schema.d.ts +53 -0
- package/dist/schemas/entity-extras-schema.js +10 -0
- package/dist/schemas/equipment-grant-schema.d.ts +2 -0
- package/dist/schemas/equipment-grant-schema.js +1 -1
- package/dist/schemas/feature-alias.d.ts +34 -0
- package/dist/schemas/feature-effect-schema.d.ts +124 -0
- package/dist/schemas/feature-effect-schema.js +1 -1
- package/dist/schemas/feature-schema.d.ts +8 -0
- package/dist/schemas/feature-schema.js +6 -4
- package/dist/schemas/resource-schema.d.ts +43 -0
- package/dist/schemas/resource-schema.js +1 -1
- package/dist/schemas/selection-pool-schema.d.ts +2 -0
- package/dist/schemas/selection-pool-schema.js +1 -1
- package/dist/spell/spell.access.js +23 -3
- package/dist/spell/spell.codec.js +4 -3
- package/dist/spell/spell.enrichment.js +4 -4
- package/dist/spell/spell.parser.d.ts +30 -0
- package/dist/spell/spell.parser.js +9 -2
- package/dist/spell/spell.scaling.d.ts +27 -6
- package/dist/spell/spell.scaling.js +25 -6
- package/dist/spell/spell.schema.d.ts +44 -2
- package/dist/spell/spell.schema.js +2 -1
- package/dist/spell/spell.types.d.ts +14 -0
- package/dist/subclass/subclass.codec.d.ts +1 -1
- package/dist/subclass/subclass.codec.js +11 -8
- package/dist/subclass/subclass.parser.js +10 -7
- package/dist/subclass/subclass.schema.d.ts +54 -7
- package/dist/subclass/subclass.schema.js +8 -6
- package/dist/subclass/subclass.types.d.ts +20 -2
- package/dist/types/choice.d.ts +56 -0
- package/dist/types/choice.js +21 -3
- package/dist/types/equipment-grant.d.ts +8 -1
- package/dist/types/feature-effect.d.ts +78 -23
- package/dist/types/feature.d.ts +70 -1
- package/dist/types/optional-feature.types.d.ts +28 -0
- package/dist/types/resource.d.ts +21 -1
- package/dist/types/selection-pool.d.ts +17 -2
- package/dist/weapon/weapon.classify.js +2 -2
- package/dist/weapon/weapon.codec.js +4 -3
- package/dist/weapon/weapon.parser.js +3 -2
- package/dist/weapon/weapon.schema.d.ts +4 -0
- package/dist/weapon/weapon.schema.js +2 -1
- package/dist/weapon/weapon.types.d.ts +8 -0
- package/package.json +2 -2
- package/dist/chunk-5MZSB6OM.js +0 -1089
- package/dist/chunk-5XUXXAQJ.js +0 -30
- package/dist/chunk-7P65Q426.js +0 -158
- package/dist/chunk-AIRFC5NQ.js +0 -143
- package/dist/chunk-BH6AMZVY.js +0 -25
- package/dist/chunk-CZPMTQOY.js +0 -68
- package/dist/chunk-M2EMFD6S.js +0 -269
- package/dist/chunk-N2JE7BWL.js +0 -81
- package/dist/chunk-NXR3BD2V.js +0 -90
- package/dist/chunk-Q5K6LWBZ.js +0 -45
- package/dist/chunk-TZK36BU7.js +0 -38
- package/dist/chunk-W7HWMMBF.js +0 -46
- package/dist/chunk-Y4I74YEG.js +0 -33
package/dist/dnd/constants.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Edition } from "../types/edition.js";
|
|
1
2
|
export declare const CR_PROFICIENCY: Record<string, number>;
|
|
2
3
|
export declare const CR_XP: Record<string, number>;
|
|
3
4
|
export declare const ALL_CR_VALUES: string[];
|
|
@@ -11,6 +12,27 @@ export declare const DAMAGE_TYPES: string[];
|
|
|
11
12
|
export declare const DAMAGE_NONMAGICAL_VARIANTS: string[];
|
|
12
13
|
export declare const CONDITIONS: string[];
|
|
13
14
|
export declare const STANDARD_SENSES: string[];
|
|
15
|
+
/** R4-G7 T8 RIDER-22 (F-STDACT) · the standard combat actions any character can take, per rules edition, in the book's
|
|
16
|
+
* alphabetical order. The plugin's Actions tab reads the character's edition, so this is rendering data, never a
|
|
17
|
+
* renderer constant (it printed ONE union of both editions). 2014 is the PHB chapter 9 list; 2024 is the 2024 action
|
|
18
|
+
* list, which drops Cast a Spell (now Magic) and Use an Object (now Utilize) and adds Influence and Study. No rules
|
|
19
|
+
* glossary ships in the SRD 2024 bundle; its prose names ten of the twelve as "the <X> action" and none of the 2014-only
|
|
20
|
+
* names (measured 2026-09-15 over the plugin repo's `.compendium-bundle/SRD 2024`). */
|
|
21
|
+
export declare const STANDARD_ACTIONS: Record<Edition, readonly string[]>;
|
|
14
22
|
export declare const ALIGNMENT_ETHICAL: string[];
|
|
15
23
|
export declare const ALIGNMENT_MORAL: string[];
|
|
16
24
|
export declare const ALL_SECTIONS: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Full ability NAME (lower-case) → canonical three-letter key. Distinct from `ABILITY_NAMES`
|
|
27
|
+
* above, which is the OTHER direction and yields the display casing ("str" → "STR").
|
|
28
|
+
*
|
|
29
|
+
* Moved here from `pc/pc.feature-effects.ts` in R4-G3a §6.2.3, where it was private: the scope
|
|
30
|
+
* normaliser (`pc/roll-scope.ts`) needs exactly the same vocabulary, and a second copy is the
|
|
31
|
+
* defect class this phase exists to remove. `src/dnd/*` imports nothing from `src/pc/*`, so the
|
|
32
|
+
* move introduces no cycle; the type is spelled `(typeof ABILITY_KEYS)[number]` rather than the
|
|
33
|
+
* `Ability` alias so this module keeps its zero imports.
|
|
34
|
+
*/
|
|
35
|
+
export declare const ABILITY_NAME_TO_KEY: Record<string, (typeof ABILITY_KEYS)[number]>;
|
|
36
|
+
/** Accepts a canonical key ("dex") or a full ability name ("Dexterity"), any casing / padding;
|
|
37
|
+
* returns the canonical key, or null when the value is neither. */
|
|
38
|
+
export declare function normalizeAbility(value: string): (typeof ABILITY_KEYS)[number] | null;
|
package/dist/dnd/constants.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ABILITY_KEYS,
|
|
3
3
|
ABILITY_NAMES,
|
|
4
|
+
ABILITY_NAME_TO_KEY,
|
|
4
5
|
ALIGNMENT_ETHICAL,
|
|
5
6
|
ALIGNMENT_MORAL,
|
|
6
7
|
ALL_CR_VALUES,
|
|
@@ -14,11 +15,14 @@ import {
|
|
|
14
15
|
DAMAGE_TYPES,
|
|
15
16
|
SIZE_HIT_DICE,
|
|
16
17
|
SKILL_ABILITY,
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
STANDARD_ACTIONS,
|
|
19
|
+
STANDARD_SENSES,
|
|
20
|
+
normalizeAbility
|
|
21
|
+
} from "../chunk-WELIKLZF.js";
|
|
19
22
|
export {
|
|
20
23
|
ABILITY_KEYS,
|
|
21
24
|
ABILITY_NAMES,
|
|
25
|
+
ABILITY_NAME_TO_KEY,
|
|
22
26
|
ALIGNMENT_ETHICAL,
|
|
23
27
|
ALIGNMENT_MORAL,
|
|
24
28
|
ALL_CR_VALUES,
|
|
@@ -32,5 +36,7 @@ export {
|
|
|
32
36
|
DAMAGE_TYPES,
|
|
33
37
|
SIZE_HIT_DICE,
|
|
34
38
|
SKILL_ABILITY,
|
|
35
|
-
|
|
39
|
+
STANDARD_ACTIONS,
|
|
40
|
+
STANDARD_SENSES,
|
|
41
|
+
normalizeAbility
|
|
36
42
|
};
|
package/dist/dnd/formula-tags.js
CHANGED
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
abilityModifier,
|
|
7
7
|
formatModifier
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-PDJSUH24.js";
|
|
9
9
|
import {
|
|
10
10
|
ABILITY_KEYS
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-WELIKLZF.js";
|
|
12
12
|
|
|
13
13
|
// src/dnd/formula-tags.ts
|
|
14
14
|
function resolveSlugForTag(slug, tagType, registry) {
|
package/dist/dnd/math.d.ts
CHANGED
|
@@ -22,3 +22,29 @@ export declare function passivePerception(wisScore: number, perceptionProf: "non
|
|
|
22
22
|
export declare function attackBonus(abilityScore: number, profBonus: number): number;
|
|
23
23
|
export declare function saveDC(abilityScore: number, profBonus: number): number;
|
|
24
24
|
export declare function abilityNameToKey(name: string): (typeof ABILITY_KEYS)[number] | null;
|
|
25
|
+
/** Is `type` one of the canonical damage types, whatever its casing? A rider whose declared type is
|
|
26
|
+
* anything else, a sentinel (`weapon`) or prose ("same as the weapon's type"), INHERITS the weapon row's
|
|
27
|
+
* own damage type; `pc.recalc.ts` resolves that where the rider is merged onto the row, never in a
|
|
28
|
+
* renderer, and never from a list of prose spellings. The ONE exception is the schema's own sentinel
|
|
29
|
+
* {@link CHOSEN_DAMAGE_TYPE}, which means the player's choice, not the row's type (R4-G7 T8 RIDER-13). */
|
|
30
|
+
export declare function isCanonicalDamageType(type: string): boolean;
|
|
31
|
+
/** The schema's own damage-type sentinel for a rider whose type the PLAYER picks when the damage is dealt
|
|
32
|
+
* (`feature-effect-schema.ts`, the `damage-bonus` arm: "player-selected damage type at action time"). It is a
|
|
33
|
+
* declared schema value, not a prose spelling, so it never inherits the weapon row's type: the rider keeps it,
|
|
34
|
+
* and the sheet prints the amount with no type and {@link CHOSEN_DAMAGE_TYPE_NOTE} in the row's caption
|
|
35
|
+
* (R4-G7 T8 RIDER-13). */
|
|
36
|
+
export declare const CHOSEN_DAMAGE_TYPE = "chosen";
|
|
37
|
+
/** The caption words a renderer prints for a {@link CHOSEN_DAMAGE_TYPE} rider in place of a damage type. One
|
|
38
|
+
* constant, so no renderer spells the phrase itself. */
|
|
39
|
+
export declare const CHOSEN_DAMAGE_TYPE_NOTE = "damage type of your choice";
|
|
40
|
+
/** Is `type` the {@link CHOSEN_DAMAGE_TYPE} sentinel, whatever its casing or surrounding space? */
|
|
41
|
+
export declare function isChosenDamageType(type: string | undefined): boolean;
|
|
42
|
+
/** Can a damage rider be printed INSIDE the damage text, as a dice chip? Only when it reads as a dice
|
|
43
|
+
* expression or a (signed) number, optionally followed by ONE canonical damage type: `1d6`, `+2`,
|
|
44
|
+
* `1d6 fire`. Anything else is prose ("your Wisdom modifier necrotic", "half your fighter level
|
|
45
|
+
* slashing") and belongs in the row's caption instead (R4-G7 T6a E-4 (c)).
|
|
46
|
+
*
|
|
47
|
+
* `text` is the rider's PRINTED form, its amount plus its resolved damage type, because a shipped
|
|
48
|
+
* rider may carry the type inside the amount itself (`{amount: "1d6 fire"}` with no `damage_type`, the
|
|
49
|
+
* migrated manual override of `pc.equipment.ts`). */
|
|
50
|
+
export declare function isRenderableDamageText(text: string): boolean;
|
package/dist/dnd/math.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CHOSEN_DAMAGE_TYPE,
|
|
3
|
+
CHOSEN_DAMAGE_TYPE_NOTE,
|
|
2
4
|
abilityModifier,
|
|
3
5
|
abilityNameToKey,
|
|
4
6
|
attackBonus,
|
|
@@ -6,6 +8,9 @@ import {
|
|
|
6
8
|
formatModifier,
|
|
7
9
|
hitDiceSizeFromCreatureSize,
|
|
8
10
|
hpFromHitDice,
|
|
11
|
+
isCanonicalDamageType,
|
|
12
|
+
isChosenDamageType,
|
|
13
|
+
isRenderableDamageText,
|
|
9
14
|
parseHitDiceFormula,
|
|
10
15
|
passive,
|
|
11
16
|
passivePerception,
|
|
@@ -14,9 +19,11 @@ import {
|
|
|
14
19
|
saveDC,
|
|
15
20
|
savingThrow,
|
|
16
21
|
skillBonus
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
22
|
+
} from "../chunk-PDJSUH24.js";
|
|
23
|
+
import "../chunk-WELIKLZF.js";
|
|
19
24
|
export {
|
|
25
|
+
CHOSEN_DAMAGE_TYPE,
|
|
26
|
+
CHOSEN_DAMAGE_TYPE_NOTE,
|
|
20
27
|
abilityModifier,
|
|
21
28
|
abilityNameToKey,
|
|
22
29
|
attackBonus,
|
|
@@ -24,6 +31,9 @@ export {
|
|
|
24
31
|
formatModifier,
|
|
25
32
|
hitDiceSizeFromCreatureSize,
|
|
26
33
|
hpFromHitDice,
|
|
34
|
+
isCanonicalDamageType,
|
|
35
|
+
isChosenDamageType,
|
|
36
|
+
isRenderableDamageText,
|
|
27
37
|
parseHitDiceFormula,
|
|
28
38
|
passive,
|
|
29
39
|
passivePerception,
|
package/dist/dnd/prose-tags.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/dnd/prose-tags.ts
|
|
2
2
|
function convert5eToolsTags(text) {
|
|
3
|
-
const rewritten = text.replace(/\{@atk\s+mw,rw\}/gi, "Melee or Ranged Weapon Attack:").replace(/\{@atk\s+mws\}/gi, "Melee or Ranged Weapon Attack:").replace(/\{@atk\s+msw\}/gi, "Melee or Ranged Spell Attack:").replace(/\{@atk\s+mw\}/gi, "Melee Weapon Attack:").replace(/\{@atk\s+rw\}/gi, "Ranged Weapon Attack:").replace(/\{@atk\s+ms\}/gi, "Melee Spell Attack:").replace(/\{@atk\s+rs\}/gi, "Ranged Spell Attack:").replace(/\{@hit\s+(\d+)\}/gi, "`atk:+$1`").replace(/\{@h\}
|
|
3
|
+
const rewritten = text.replace(/\{@atk\s+mw,rw\}/gi, "Melee or Ranged Weapon Attack:").replace(/\{@atk\s+mws\}/gi, "Melee or Ranged Weapon Attack:").replace(/\{@atk\s+msw\}/gi, "Melee or Ranged Spell Attack:").replace(/\{@atk\s+mw\}/gi, "Melee Weapon Attack:").replace(/\{@atk\s+rw\}/gi, "Ranged Weapon Attack:").replace(/\{@atk\s+ms\}/gi, "Melee Spell Attack:").replace(/\{@atk\s+rs\}/gi, "Ranged Spell Attack:").replace(/\{@hit\s+(\d+)\}/gi, "`atk:+$1`").replace(/\{@h\}\s*/gi, "Hit: ").replace(/\{@damage\s+([^}]+)\}/gi, "`damage:$1`").replace(/\{@dice\s+([^}]+)\}/gi, "`roll:$1`").replace(/\{@d20\s+([^}]+)\}/gi, "`roll:d20$1`").replace(/\{@dc\s+(\d+)\}/gi, "`dc:$1`").replace(/\{@recharge\s+(\d)\}/gi, "(Recharge $1-6)").replace(/\{@recharge\}/gi, "(Recharge)").replace(/\{@chance\s+(\d+)\}/gi, "$1% chance").replace(/\{@b(?:old)?\s+([^}]+)\}/gi, "**$1**").replace(/\{@i(?:talic)?\s+([^}]+)\}/gi, "_$1_").replace(/\{@s(?:trike)?\s+([^}]+)\}/gi, "~~$1~~").replace(/\{@note\s+([^}]+)\}/gi, "($1)").replace(/\{@spell\s+([^|}]+)[^}]*\}/gi, "_$1_").replace(/\{@item\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@creature\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@condition\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@skill\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@sense\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@action\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@status\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@ability\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@class\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@feat\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@background\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@race\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@disease\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@hazard\s+([^|}]+)[^}]*\}/gi, "**$1**").replace(/\{@plane\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@language\s+([^|}]+)[^}]*\}/gi, "$1").replace(/\{@book\s+([^|}]+)[^}]*\}/gi, "_$1_").replace(/\{@adventure\s+([^|}]+)[^}]*\}/gi, "_$1_").replace(/\{@\w+\s+([^}]+)\}/g, "$1");
|
|
4
4
|
return decorateProseDice(rewritten);
|
|
5
5
|
}
|
|
6
6
|
function decorateProseDice(text) {
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tiny DSL for Resource.max_formula and Resource.recovery[].amount (SP4d). Grammar:
|
|
2
|
+
* Tiny DSL for Resource.max_formula and Resource.recovery[].amount (SP4d; R4-G4 §6 added max / min). Grammar:
|
|
3
3
|
* expr := term (('+' | '-') term)*
|
|
4
4
|
* term := factor (('*' | '/') factor)*
|
|
5
|
-
* factor := number | string-arg-only | ident | '{' ident '}' |
|
|
5
|
+
* factor := number | string-arg-only | ident | '{' ident '}' | fn1 '(' expr ')' | fnN '(' expr (',' expr)+ ')'
|
|
6
6
|
* | "column" '(' string ')' | '(' expr ')'
|
|
7
|
-
*
|
|
7
|
+
* fn1 := 'ceil' | 'floor' (exactly one argument)
|
|
8
|
+
* fnN := 'max' | 'min' (two or more comma-separated arguments)
|
|
8
9
|
* ident := level | class_level | prof | <abil>_mod
|
|
9
|
-
* The single-quoted string literal (e.g. 'Seals') is valid ONLY as the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* The single-quoted string literal (e.g. 'Seals') is valid ONLY as the argument to column(...).
|
|
11
|
+
* '*' and '/' bind tighter than '+'/'-'. '/' is real division; wrap in ceil()/floor() for integer
|
|
12
|
+
* results (e.g. "ceil({class_level}/2)"). "max(1, {cha_mod})" is how the data says "a minimum of once".
|
|
13
|
+
* `AT_WILL_MAX` (999) is the at-will sentinel: it evaluates as the literal 999; R4-G4 T3 (§5) taught
|
|
14
|
+
* the plugin's charge boxes to render "at will" for it instead of 999 boxes (the `opts.atWill` branch
|
|
15
|
+
* at the head of `renderChargeBoxes`, fed by the `atWill: fu.max === AT_WILL_MAX` opt its callers
|
|
16
|
+
* pass). Measured 2026-09-05 on the plugin tree that carries T7b with
|
|
17
|
+
* `grep -rn "atWill:" packages/obsidian/src`: FOUR lines, the two T3 feature trackers
|
|
18
|
+
* `renderCardResource` and `renderFirstResourceTracker`, T5's pool-tab dice head `renderPoolHead`,
|
|
19
|
+
* and T7b's `renderPickTracker`, which draws a pool pick's own `uses` on the pool row, the granted
|
|
20
|
+
* row and the boon row.
|
|
14
21
|
*/
|
|
15
22
|
export interface FormulaBindings {
|
|
16
23
|
level: number;
|
|
@@ -27,6 +34,7 @@ export interface FormulaBindings {
|
|
|
27
34
|
* Read by the `column('Name')` accessor; missing name → 0. */
|
|
28
35
|
columns: Record<string, number>;
|
|
29
36
|
}
|
|
37
|
+
export declare const AT_WILL_MAX = 999;
|
|
30
38
|
export declare function isValidMaxFormula(formula: string): boolean;
|
|
31
39
|
export declare function evaluateMaxFormula(formula: string, bindings: FormulaBindings): number;
|
|
32
40
|
export interface ScalableResource {
|
|
@@ -36,6 +44,24 @@ export interface ScalableResource {
|
|
|
36
44
|
max: string;
|
|
37
45
|
}[];
|
|
38
46
|
}
|
|
39
|
-
/** The max-formula string in effect at `totalLevel`: the highest `scales_at`
|
|
40
|
-
*
|
|
47
|
+
/** The max-formula string in effect at `totalLevel`: the highest `scales_at` step whose level
|
|
48
|
+
* ≤ totalLevel (the FIRST declaration wins on a duplicate level; a `level: 0` step is skipped), else
|
|
49
|
+
* the base `max_formula`. Parse-free, so a die-string step comes back as the die string. Its one
|
|
50
|
+
* production caller, the plugin's `seedFeatureUses` (`pc.resource-seed.ts`), moved to
|
|
51
|
+
* `resolveMaxCountAt` in R4-G4 T3, so it is now TEST-ONLY: zero callers in this repo's `src/` and zero
|
|
52
|
+
* in the plugin's `packages/obsidian/src/`, pinned by this repo's `tests/resource-formula.test.ts`
|
|
53
|
+
* (its Bardic-Die-2024 and duplicate-level-tie cases) and by the plugin's cross-repo file of the same
|
|
54
|
+
* name (its `describe("resolveMaxAt")` block). */
|
|
41
55
|
export declare function resolveMaxAt(totalLevel: number, resource: ScalableResource): string;
|
|
56
|
+
/** The max COUNT in effect at `level`: the highest `scales_at` step at or below `level` whose `max`
|
|
57
|
+
* PARSES under the DSL, else the base `max_formula` if it parses, else null. Ties break exactly as
|
|
58
|
+
* `resolveMaxAt` breaks them (the FIRST declaration at a duplicate level wins, a `level: 0` step is
|
|
59
|
+
* skipped), so a duplicate-level pair of PARSING steps cannot make the count and the die label pick
|
|
60
|
+
* different steps; where one member of the pair is a die string they DO pick different steps
|
|
61
|
+
* (`[{level:3,max:"1d8"},{level:3,max:"3"}]` at 3 reads 3 here and "1d8" there), which is the same
|
|
62
|
+
* parse-vs-string divergence described next. A step that does not parse is a die size (Bardic Die
|
|
63
|
+
* 2024: "1d8" at 5), not a count, and is skipped HERE while `resolveMaxAt` still returns it; a base
|
|
64
|
+
* that does not parse (Sneak Attack "1d6") is a damage die, correctly no tracker. `resolveMaxAt`
|
|
65
|
+
* keeps the parse-free string lookup; R4-G4 T3 handed its one production caller, the plugin seed, to
|
|
66
|
+
* this function (see its docblock), so a null here is what the seed warns on and leaves un-seeded. */
|
|
67
|
+
export declare function resolveMaxCountAt(level: number, resource: ScalableResource, bindings: FormulaBindings): number | null;
|
|
@@ -1,159 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"con_mod",
|
|
9
|
-
"int_mod",
|
|
10
|
-
"wis_mod",
|
|
11
|
-
"cha_mod"
|
|
12
|
-
]);
|
|
13
|
-
var FUNCS = /* @__PURE__ */ new Set(["ceil", "floor"]);
|
|
14
|
-
function tokenize(input) {
|
|
15
|
-
input = input.trim();
|
|
16
|
-
const tokens = [];
|
|
17
|
-
const re = /\s*('[^']*'|\{[a-z_]+\}|[a-z_]+|\d+|[+\-*/()])/y;
|
|
18
|
-
let i = 0;
|
|
19
|
-
while (i < input.length) {
|
|
20
|
-
re.lastIndex = i;
|
|
21
|
-
const m = re.exec(input);
|
|
22
|
-
if (!m || m.index !== i) return null;
|
|
23
|
-
const raw = m[1];
|
|
24
|
-
i = re.lastIndex;
|
|
25
|
-
if (/^\d+$/.test(raw)) tokens.push({ kind: "num", value: parseInt(raw, 10) });
|
|
26
|
-
else if (raw.startsWith("'")) tokens.push({ kind: "str", value: raw.slice(1, -1) });
|
|
27
|
-
else if (raw === "(") tokens.push({ kind: "lparen" });
|
|
28
|
-
else if (raw === ")") tokens.push({ kind: "rparen" });
|
|
29
|
-
else if (raw === "+" || raw === "-" || raw === "*" || raw === "/") tokens.push({ kind: "op", op: raw });
|
|
30
|
-
else {
|
|
31
|
-
const braced = raw.startsWith("{");
|
|
32
|
-
const name = braced ? raw.slice(1, -1) : raw;
|
|
33
|
-
if (!braced && FUNCS.has(name)) tokens.push({ kind: "fn", name });
|
|
34
|
-
else if (!braced && name === "column") tokens.push({ kind: "col" });
|
|
35
|
-
else if (IDENTS.has(name)) tokens.push({ kind: "id", name });
|
|
36
|
-
else return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return tokens.length > 0 ? tokens : null;
|
|
40
|
-
}
|
|
41
|
-
function evalTokens(tokens, b) {
|
|
42
|
-
let pos = 0;
|
|
43
|
-
const peek = () => tokens[pos];
|
|
44
|
-
const factor = () => {
|
|
45
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
46
|
-
const t = peek();
|
|
47
|
-
if (!t) return null;
|
|
48
|
-
if (t.kind === "num") {
|
|
49
|
-
pos++;
|
|
50
|
-
return t.value;
|
|
51
|
-
}
|
|
52
|
-
if (t.kind === "id") {
|
|
53
|
-
const val = b[t.name];
|
|
54
|
-
if (val === void 0) return null;
|
|
55
|
-
pos++;
|
|
56
|
-
return val;
|
|
57
|
-
}
|
|
58
|
-
if (t.kind === "fn") {
|
|
59
|
-
pos++;
|
|
60
|
-
if (((_a = peek()) == null ? void 0 : _a.kind) !== "lparen") return null;
|
|
61
|
-
pos++;
|
|
62
|
-
const inner = expr();
|
|
63
|
-
if (inner === null) return null;
|
|
64
|
-
if (((_b = peek()) == null ? void 0 : _b.kind) !== "rparen") return null;
|
|
65
|
-
pos++;
|
|
66
|
-
return t.name === "ceil" ? Math.ceil(inner) : Math.floor(inner);
|
|
67
|
-
}
|
|
68
|
-
if (t.kind === "col") {
|
|
69
|
-
pos++;
|
|
70
|
-
if (((_c = peek()) == null ? void 0 : _c.kind) !== "lparen") return null;
|
|
71
|
-
pos++;
|
|
72
|
-
const s = peek();
|
|
73
|
-
if (!s || s.kind !== "str") return null;
|
|
74
|
-
pos++;
|
|
75
|
-
if (((_d = peek()) == null ? void 0 : _d.kind) !== "rparen") return null;
|
|
76
|
-
pos++;
|
|
77
|
-
return (_f = (_e = b.columns) == null ? void 0 : _e[s.value]) != null ? _f : 0;
|
|
78
|
-
}
|
|
79
|
-
if (t.kind === "lparen") {
|
|
80
|
-
pos++;
|
|
81
|
-
const inner = expr();
|
|
82
|
-
if (inner === null) return null;
|
|
83
|
-
if (((_g = peek()) == null ? void 0 : _g.kind) !== "rparen") return null;
|
|
84
|
-
pos++;
|
|
85
|
-
return inner;
|
|
86
|
-
}
|
|
87
|
-
return null;
|
|
88
|
-
};
|
|
89
|
-
const term = () => {
|
|
90
|
-
var _a;
|
|
91
|
-
let v = factor();
|
|
92
|
-
if (v === null) return null;
|
|
93
|
-
while (((_a = peek()) == null ? void 0 : _a.kind) === "op" && (peek().op === "*" || peek().op === "/")) {
|
|
94
|
-
const op = peek().op;
|
|
95
|
-
pos++;
|
|
96
|
-
const r = factor();
|
|
97
|
-
if (r === null) return null;
|
|
98
|
-
v = op === "*" ? v * r : v / r;
|
|
99
|
-
}
|
|
100
|
-
return v;
|
|
101
|
-
};
|
|
102
|
-
const expr = () => {
|
|
103
|
-
var _a;
|
|
104
|
-
let v = term();
|
|
105
|
-
if (v === null) return null;
|
|
106
|
-
while (((_a = peek()) == null ? void 0 : _a.kind) === "op" && (peek().op === "+" || peek().op === "-")) {
|
|
107
|
-
const op = peek().op;
|
|
108
|
-
pos++;
|
|
109
|
-
const r = term();
|
|
110
|
-
if (r === null) return null;
|
|
111
|
-
v = op === "+" ? v + r : v - r;
|
|
112
|
-
}
|
|
113
|
-
return v;
|
|
114
|
-
};
|
|
115
|
-
const result = expr();
|
|
116
|
-
if (result === null || pos !== tokens.length) return null;
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
var ZERO = {
|
|
120
|
-
level: 1,
|
|
121
|
-
class_level: 1,
|
|
122
|
-
prof: 2,
|
|
123
|
-
str_mod: 0,
|
|
124
|
-
dex_mod: 0,
|
|
125
|
-
con_mod: 0,
|
|
126
|
-
int_mod: 0,
|
|
127
|
-
wis_mod: 0,
|
|
128
|
-
cha_mod: 0,
|
|
129
|
-
columns: {}
|
|
130
|
-
};
|
|
131
|
-
function isValidMaxFormula(formula) {
|
|
132
|
-
const toks = tokenize(formula);
|
|
133
|
-
if (!toks) return false;
|
|
134
|
-
return evalTokens(toks, ZERO) !== null;
|
|
135
|
-
}
|
|
136
|
-
function evaluateMaxFormula(formula, bindings) {
|
|
137
|
-
const toks = tokenize(formula);
|
|
138
|
-
if (!toks) throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);
|
|
139
|
-
const v = evalTokens(toks, bindings);
|
|
140
|
-
if (v === null) throw new Error(`invalid max_formula: ${JSON.stringify(formula)}`);
|
|
141
|
-
return v;
|
|
142
|
-
}
|
|
143
|
-
function resolveMaxAt(totalLevel, resource) {
|
|
144
|
-
var _a;
|
|
145
|
-
let chosen = resource.max_formula;
|
|
146
|
-
let best = 0;
|
|
147
|
-
for (const step of (_a = resource.scales_at) != null ? _a : []) {
|
|
148
|
-
if (step.level <= totalLevel && step.level > best) {
|
|
149
|
-
best = step.level;
|
|
150
|
-
chosen = step.max;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return chosen;
|
|
154
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
AT_WILL_MAX,
|
|
3
|
+
evaluateMaxFormula,
|
|
4
|
+
isValidMaxFormula,
|
|
5
|
+
resolveMaxAt,
|
|
6
|
+
resolveMaxCountAt
|
|
7
|
+
} from "../chunk-EVMUJYUD.js";
|
|
155
8
|
export {
|
|
9
|
+
AT_WILL_MAX,
|
|
156
10
|
evaluateMaxFormula,
|
|
157
11
|
isValidMaxFormula,
|
|
158
|
-
resolveMaxAt
|
|
12
|
+
resolveMaxAt,
|
|
13
|
+
resolveMaxCountAt
|
|
159
14
|
};
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
STATIC_FALLBACK_CONTEXT,
|
|
3
3
|
convertDescToTags,
|
|
4
4
|
detectSpellcastingAbility
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-DEEHHLAP.js";
|
|
6
|
+
import "../chunk-PDJSUH24.js";
|
|
7
|
+
import "../chunk-WELIKLZF.js";
|
|
8
8
|
export {
|
|
9
9
|
STATIC_FALLBACK_CONTEXT,
|
|
10
10
|
convertDescToTags,
|
package/dist/dnd/tag-grammar.js
CHANGED
package/dist/entities/slug.d.ts
CHANGED
|
@@ -10,3 +10,16 @@ export declare function slugify(name: string): string;
|
|
|
10
10
|
* `parts.slice(2).join("_")`. Tolerates a nullish slug (degrades to "") so a
|
|
11
11
|
* malformed entity can't hard-crash the builder; the resolver backfills real slugs. */
|
|
12
12
|
export declare function bareEntitySlug(slug: string | null | undefined): string;
|
|
13
|
+
/** "[[SRD 2024/Classes/Fighter]]" to "fighter" (tail segment, slugified).
|
|
14
|
+
*
|
|
15
|
+
* The tail goes through the SAME `slugify` that mints registry slugs, so an apostrophe is DELETED rather than
|
|
16
|
+
* hyphenated ("Mage's Bane" to "mages-bane", where the old hand-rolled regex minted "mage-s-bane" and missed
|
|
17
|
+
* every time). Only ever call this on a human NAME tail, never on a full `<prefix>_<name>` slug, which slugify
|
|
18
|
+
* would destroy: `pc.decision-engine.ts`'s `resolveEntityRef` is the function that strips a `[[wikilink]]`
|
|
19
|
+
* WITHOUT slugifying, and it is the one to use for a STORED slug.
|
|
20
|
+
*
|
|
21
|
+
* MOVED here from `pc.decision-engine.ts` in R4-G5 T1, beside `bareEntitySlug`, so `pc.pools.ts` can use it
|
|
22
|
+
* without importing the decision engine: the engine imports `pc.pools` for `strandedPicks`, and the old
|
|
23
|
+
* direction would be a cycle. The engine keeps a re-export, so its three plugin importers and its own test
|
|
24
|
+
* are untouched. */
|
|
25
|
+
export declare function wikilinkTailSlug(link: string): string;
|
package/dist/entities/slug.js
CHANGED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** The human name of a wikilink target: `[[Player's Handbook (2024)/OptionalFeatures/Pact of the Blade]]` →
|
|
2
|
+
* "Pact of the Blade"; `[[path|Alias]]` → "Alias". The converter emits vault PATHS with no alias. */
|
|
3
|
+
export declare function wikilinkDisplayName(link: string): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/entities/wikilink-display.ts
|
|
2
|
+
function wikilinkDisplayName(link) {
|
|
3
|
+
const inner = link.trim().replace(/^\[\[/, "").replace(/\]\]$/, "");
|
|
4
|
+
const afterAlias = inner.includes("|") ? inner.slice(inner.lastIndexOf("|") + 1) : inner;
|
|
5
|
+
const afterSlash = afterAlias.includes("/") ? afterAlias.slice(afterAlias.lastIndexOf("/") + 1) : afterAlias;
|
|
6
|
+
return afterSlash.trim();
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
wikilinkDisplayName
|
|
10
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { FeatCategory } from "../types/choice.js";
|
|
2
|
+
/** 5etools feat `category` codes, as DATA beside the schema (never a renderer switch). The converter emits the raw
|
|
3
|
+
* code on `exclusive-feat-category` and `feat-category` prerequisites (today only "D", on 14 documents; the G7
|
|
4
|
+
* handoff asks it for a name). `FS:P` and `FS:R` are the Paladin- and Ranger-scoped fighting-style categories.
|
|
5
|
+
* Measured in data/feats.json: G 80, EB 29, O 25, D 13, FS 10, DG 9, FS:P 1, FS:R 1. Unknown codes fall back to
|
|
6
|
+
* the code itself. */
|
|
7
|
+
export declare const FEAT_CATEGORY_CODE_LABELS: Readonly<Record<string, string>>;
|
|
8
|
+
export declare function featCategoryLabel(code: string): string;
|
|
9
|
+
/** 5etools `feat_progression.category` codes to the ENGINE's `FeatCategory` vocabulary (R4-G5 §3.2.5,
|
|
10
|
+
* invariant 3): the DATA table the class-side progression reader maps through, beside the label table above.
|
|
11
|
+
* MEASURED over the converted corpus 2026-09-07: 18 `feat_progression` rows across 15 documents, codes
|
|
12
|
+
* {EB 13, FS 4, FS:P 1, FS:R 1, O 1}. The FS four are Fighter 2024 (level 1), Paladin 2024 and Ranger 2024
|
|
13
|
+
* (level 2, each carrying `["FS","FS:P"]` / `["FS","FS:R"]`) and the Champion 2024 SUBCLASS (level 7); the 13
|
|
14
|
+
* EB rows are the 12 PHB 2024 classes plus the Eberron Artificer, all at level 19. The single `O` row sits on
|
|
15
|
+
* an OPTIONAL FEATURE (Lessons of the First Ones) with a `"*"` progression key, outside the class walk, so `O`
|
|
16
|
+
* and `G` have zero live class-side carriers and are declared for completeness. `D` (Dragonmark) and `DG`
|
|
17
|
+
* (Dark Gift) map to NOTHING on purpose: they are not player-choosable feat categories in this vocabulary, and
|
|
18
|
+
* a row carrying only those emits no decision and warns once at the reader. G7 handoff (spec §11): the
|
|
19
|
+
* converter re-emits these codes in engine vocabulary and this table retires. */
|
|
20
|
+
export declare const FEAT_PROGRESSION_CATEGORY: Readonly<Record<string, FeatCategory>>;
|
|
21
|
+
/** The ONE `FeatCategory` to optional-feature `feature_type` pairing (R4-G5 §3.2.5). The shape-B suppression
|
|
22
|
+
* reads it to decide that a class carrying a fighting-style `feat_progression` row must NOT also be offered the
|
|
23
|
+
* recognizer's `fighting_style` optional-feature synthetic at that level. `Partial<Record<...>>` because three
|
|
24
|
+
* of the four categories pair with nothing, which is also what makes the lookup return `string | undefined`
|
|
25
|
+
* without an own-property guard. */
|
|
26
|
+
export declare const FEATURE_TYPE_FOR_CATEGORY: Readonly<Partial<Record<FeatCategory, string>>>;
|
|
27
|
+
/** Reduce a `feat_progression` entry's `category` ARRAY to ONE engine category: the FIRST code that maps wins, so
|
|
28
|
+
* the shipped `["FS","FS:P"]` (Paladin) and `["FS","FS:R"]` (Ranger) each yield exactly ONE decision instead of
|
|
29
|
+
* two. OWN-property guarded (invariant 3): the codes come from converter data, so `constructor` would otherwise
|
|
30
|
+
* index a FUNCTION through the prototype chain. Returns undefined when nothing maps (an all-`D` row); the
|
|
31
|
+
* CALLER warns, because this stays pure. */
|
|
32
|
+
export declare function featProgressionCategory(codes: readonly string[] | undefined): FeatCategory | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FEATURE_TYPE_FOR_CATEGORY,
|
|
3
|
+
FEAT_CATEGORY_CODE_LABELS,
|
|
4
|
+
FEAT_PROGRESSION_CATEGORY,
|
|
5
|
+
featCategoryLabel,
|
|
6
|
+
featProgressionCategory
|
|
7
|
+
} from "../chunk-YBLDE5CG.js";
|
|
8
|
+
export {
|
|
9
|
+
FEATURE_TYPE_FOR_CATEGORY,
|
|
10
|
+
FEAT_CATEGORY_CODE_LABELS,
|
|
11
|
+
FEAT_PROGRESSION_CATEGORY,
|
|
12
|
+
featCategoryLabel,
|
|
13
|
+
featProgressionCategory
|
|
14
|
+
};
|
package/dist/feat/feat.codec.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
featCodec
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-ESS46GR4.js";
|
|
4
|
+
import "../chunk-D5U7GMPX.js";
|
|
5
|
+
import "../chunk-RIXI5D3R.js";
|
|
6
|
+
import "../chunk-YLL2QXY2.js";
|
|
7
|
+
import "../chunk-T26ZVCL5.js";
|
|
8
|
+
import "../chunk-WPWOHGPI.js";
|
|
9
|
+
import "../chunk-UA5KS2PL.js";
|
|
8
10
|
export {
|
|
9
11
|
featCodec
|
|
10
12
|
};
|
package/dist/feat/feat.parser.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseFeat
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-D5U7GMPX.js";
|
|
4
|
+
import "../chunk-RIXI5D3R.js";
|
|
5
|
+
import "../chunk-YLL2QXY2.js";
|
|
6
|
+
import "../chunk-T26ZVCL5.js";
|
|
7
|
+
import "../chunk-WPWOHGPI.js";
|
|
8
|
+
import "../chunk-UA5KS2PL.js";
|
|
7
9
|
export {
|
|
8
10
|
parseFeat
|
|
9
11
|
};
|