@iamjameslennon/ddb-mcp 2.7.1 → 2.9.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.
Files changed (101) hide show
  1. package/README.md +2 -0
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +19 -4
  4. package/dist/browser.js.map +1 -1
  5. package/dist/index.js +58 -38
  6. package/dist/index.js.map +1 -1
  7. package/dist/open5e.d.ts +2 -0
  8. package/dist/open5e.d.ts.map +1 -1
  9. package/dist/open5e.js +4 -0
  10. package/dist/open5e.js.map +1 -1
  11. package/dist/tools/campaign.js +1 -1
  12. package/dist/tools/campaign.js.map +1 -1
  13. package/dist/tools/character/ac.d.ts +20 -0
  14. package/dist/tools/character/ac.d.ts.map +1 -0
  15. package/dist/tools/character/ac.js +83 -0
  16. package/dist/tools/character/ac.js.map +1 -0
  17. package/dist/tools/character/actions.d.ts +22 -0
  18. package/dist/tools/character/actions.d.ts.map +1 -0
  19. package/dist/tools/character/actions.js +110 -0
  20. package/dist/tools/character/actions.js.map +1 -0
  21. package/dist/tools/character/core.d.ts +15 -0
  22. package/dist/tools/character/core.d.ts.map +1 -0
  23. package/dist/tools/character/core.js +129 -0
  24. package/dist/tools/character/core.js.map +1 -0
  25. package/dist/tools/character/defenses.d.ts +16 -0
  26. package/dist/tools/character/defenses.d.ts.map +1 -0
  27. package/dist/tools/character/defenses.js +27 -0
  28. package/dist/tools/character/defenses.js.map +1 -0
  29. package/dist/tools/character/definition.d.ts +14 -0
  30. package/dist/tools/character/definition.d.ts.map +1 -0
  31. package/dist/tools/character/definition.js +205 -0
  32. package/dist/tools/character/definition.js.map +1 -0
  33. package/dist/tools/character/features.d.ts +26 -0
  34. package/dist/tools/character/features.d.ts.map +1 -0
  35. package/dist/tools/character/features.js +107 -0
  36. package/dist/tools/character/features.js.map +1 -0
  37. package/dist/tools/character/helpers.d.ts +57 -0
  38. package/dist/tools/character/helpers.d.ts.map +1 -0
  39. package/dist/tools/character/helpers.js +80 -0
  40. package/dist/tools/character/helpers.js.map +1 -0
  41. package/dist/tools/character/identity.d.ts +19 -0
  42. package/dist/tools/character/identity.d.ts.map +1 -0
  43. package/dist/tools/character/identity.js +84 -0
  44. package/dist/tools/character/identity.js.map +1 -0
  45. package/dist/tools/character/inventory.d.ts +21 -0
  46. package/dist/tools/character/inventory.d.ts.map +1 -0
  47. package/dist/tools/character/inventory.js +61 -0
  48. package/dist/tools/character/inventory.js.map +1 -0
  49. package/dist/tools/character/notes.d.ts +20 -0
  50. package/dist/tools/character/notes.d.ts.map +1 -0
  51. package/dist/tools/character/notes.js +63 -0
  52. package/dist/tools/character/notes.js.map +1 -0
  53. package/dist/tools/character/parse.d.ts +13 -0
  54. package/dist/tools/character/parse.d.ts.map +1 -0
  55. package/dist/tools/character/parse.js +82 -0
  56. package/dist/tools/character/parse.js.map +1 -0
  57. package/dist/tools/character/spells.d.ts +26 -0
  58. package/dist/tools/character/spells.d.ts.map +1 -0
  59. package/dist/tools/character/spells.js +237 -0
  60. package/dist/tools/character/spells.js.map +1 -0
  61. package/dist/tools/character/stats.d.ts +33 -0
  62. package/dist/tools/character/stats.d.ts.map +1 -0
  63. package/dist/tools/character/stats.js +372 -0
  64. package/dist/tools/character/stats.js.map +1 -0
  65. package/dist/tools/character/templates.d.ts +22 -0
  66. package/dist/tools/character/templates.d.ts.map +1 -0
  67. package/dist/tools/character/templates.js +61 -0
  68. package/dist/tools/character/templates.js.map +1 -0
  69. package/dist/tools/character/types.d.ts +133 -0
  70. package/dist/tools/character/types.d.ts.map +1 -0
  71. package/dist/tools/character/types.js +12 -0
  72. package/dist/tools/character/types.js.map +1 -0
  73. package/dist/tools/character/vitals.d.ts +34 -0
  74. package/dist/tools/character/vitals.d.ts.map +1 -0
  75. package/dist/tools/character/vitals.js +198 -0
  76. package/dist/tools/character/vitals.js.map +1 -0
  77. package/dist/tools/character/weapons.d.ts +13 -0
  78. package/dist/tools/character/weapons.d.ts.map +1 -0
  79. package/dist/tools/character/weapons.js +79 -0
  80. package/dist/tools/character/weapons.js.map +1 -0
  81. package/dist/tools/character.d.ts +15 -3
  82. package/dist/tools/character.d.ts.map +1 -1
  83. package/dist/tools/character.js +28 -1182
  84. package/dist/tools/character.js.map +1 -1
  85. package/dist/tools/library.d.ts +32 -4
  86. package/dist/tools/library.d.ts.map +1 -1
  87. package/dist/tools/library.js +181 -86
  88. package/dist/tools/library.js.map +1 -1
  89. package/dist/tools/monster.d.ts +2 -0
  90. package/dist/tools/monster.d.ts.map +1 -1
  91. package/dist/tools/monster.js +4 -0
  92. package/dist/tools/monster.js.map +1 -1
  93. package/dist/tools/reference.d.ts +5 -0
  94. package/dist/tools/reference.d.ts.map +1 -1
  95. package/dist/tools/reference.js +76 -69
  96. package/dist/tools/reference.js.map +1 -1
  97. package/dist/tools/search.d.ts +1 -2
  98. package/dist/tools/search.d.ts.map +1 -1
  99. package/dist/tools/search.js +36 -59
  100. package/dist/tools/search.js.map +1 -1
  101. package/package.json +2 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Shared types for the character module.
3
+ *
4
+ * Phase 1 of the character.ts refactor — see docs/character-refactor.md.
5
+ *
6
+ * `Mod`, `ClassEntry`, `InventoryItem`, `CharData` are all currently aliased
7
+ * to `Record<string, unknown>`. They will be tightened to proper shapes
8
+ * post-refactor (see follow-up A in the refactor doc) — the aliases exist so
9
+ * future tightening is a one-place change instead of a sweep.
10
+ */
11
+ export type CharData = Record<string, unknown>;
12
+ export type Mod = Record<string, unknown>;
13
+ export type ClassEntry = Record<string, unknown>;
14
+ export type InventoryItem = Record<string, unknown>;
15
+ /** `type:"proficiency"` — skill/save/tool/weapon/armor/language proficiency grant. */
16
+ export interface ProficiencyMod {
17
+ type: "proficiency";
18
+ subType: string;
19
+ }
20
+ /** `type:"expertise"` — doubles proficiency bonus on the given skill/tool. */
21
+ export interface ExpertiseMod {
22
+ type: "expertise";
23
+ subType: string;
24
+ }
25
+ /** `type:"half-proficiency"` — half-prof (Jack of All Trades family). */
26
+ export interface HalfProficiencyMod {
27
+ type: "half-proficiency";
28
+ subType: string;
29
+ }
30
+ /**
31
+ * `type:"bonus"` — additive numeric modifier. Most varied mod type in DDB:
32
+ * AC, skill bonuses, ability-score buffs, HP-per-level, initiative, speed,
33
+ * hit/damage. The value is in `value` OR `fixedValue` (use `??` —
34
+ * "whichever is present"), or computed from `statId` (e.g. Gloom Stalker
35
+ * Dread Ambusher adds WIS mod to initiative). `bonusTypes` indicates a
36
+ * dynamic value source (e.g. `[1]` = use the proficiency bonus).
37
+ * `isGranted: false` on a race mod means the player declined the ASI
38
+ * (2024 floating-ASI rule).
39
+ */
40
+ export interface BonusMod {
41
+ type: "bonus";
42
+ subType: string;
43
+ value?: number | null;
44
+ fixedValue?: number | null;
45
+ statId?: number | null;
46
+ isGranted?: boolean;
47
+ bonusTypes?: number[];
48
+ }
49
+ /**
50
+ * `type:"set"` — replaces the base value (e.g. Belt of Giant Strength sets STR
51
+ * to 23, Boots of Striding and Springing set walking speed to 40, Draconic
52
+ * Resilience sets unarmored AC base via `unarmored-armor-class`).
53
+ * `componentId` discriminates dual-encoded set+sense pairs from same-source
54
+ * extensions in the sense calculation.
55
+ */
56
+ export interface SetMod {
57
+ type: "set";
58
+ subType: string;
59
+ value?: number | null;
60
+ fixedValue?: number | null;
61
+ statId?: number | null;
62
+ componentId?: number;
63
+ }
64
+ /**
65
+ * `type:"set-base"` — baseline-establishing set, used by senses (e.g. race
66
+ * darkvision baseline 60 ft.). Functionally identical to `set` for the
67
+ * baseline pass; the distinct type exists because DDB sometimes emits both.
68
+ */
69
+ export interface SetBaseMod {
70
+ type: "set-base";
71
+ subType: string;
72
+ value?: number | null;
73
+ fixedValue?: number | null;
74
+ componentId?: number;
75
+ }
76
+ /**
77
+ * `type:"sense"` — grants or extends a sense (Darkvision, Blindsight, etc.).
78
+ * Pass 2 of the sense calculation uses `componentId` to decide whether the mod
79
+ * is a dual encoding of the baseline (take max) or an extension from a
80
+ * different source (additive — Gloom Stalker Umbral Sight +30 ft on race
81
+ * darkvision 60 ft).
82
+ */
83
+ export interface SenseMod {
84
+ type: "sense";
85
+ subType: string;
86
+ value?: number | null;
87
+ componentId?: number;
88
+ }
89
+ /** `type:"resistance"` — damage resistance grant (e.g. "fire", "cold"). */
90
+ export interface ResistanceMod {
91
+ type: "resistance";
92
+ subType: string;
93
+ }
94
+ /** `type:"immunity"` — damage immunity grant (e.g. "poison", "psychic"). */
95
+ export interface ImmunityMod {
96
+ type: "immunity";
97
+ subType: string;
98
+ }
99
+ /** `type:"vulnerability"` — damage vulnerability grant. */
100
+ export interface VulnerabilityMod {
101
+ type: "vulnerability";
102
+ subType: string;
103
+ }
104
+ /**
105
+ * `type:"language"` — language proficiency grant. The standard race/class/feat
106
+ * source for languages. The other two storage mechanisms (custom proficiencies
107
+ * with `type: 3`, and `characterValues` entries with `typeId: 35`) live
108
+ * outside `modifiers` and don't use this interface.
109
+ */
110
+ export interface LanguageMod {
111
+ type: "language";
112
+ subType: string;
113
+ }
114
+ export type ParseSection = "summary" | "combat" | "spells" | "inventory" | "features" | "concentration" | "notes" | "full";
115
+ /**
116
+ * The shared context object passed to every per-domain computer module.
117
+ *
118
+ * Computed once by `computeCoreStats(char)` (Phase 2) and threaded through
119
+ * vitals/stats/spells/etc. Avoids each module re-deriving statMods,
120
+ * profBonus, allMods, etc.
121
+ */
122
+ export interface CoreStats {
123
+ readonly char: CharData;
124
+ readonly allMods: readonly Mod[];
125
+ readonly statTotals: readonly number[];
126
+ readonly statMods: readonly number[];
127
+ readonly profBonus: number;
128
+ readonly totalLevel: number;
129
+ readonly classes: readonly ClassEntry[];
130
+ readonly inventory: readonly InventoryItem[];
131
+ readonly resolveTemplates: (text: string, classLevel?: number) => string;
132
+ }
133
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/character/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared types for the character module.
3
+ *
4
+ * Phase 1 of the character.ts refactor — see docs/character-refactor.md.
5
+ *
6
+ * `Mod`, `ClassEntry`, `InventoryItem`, `CharData` are all currently aliased
7
+ * to `Record<string, unknown>`. They will be tightened to proper shapes
8
+ * post-refactor (see follow-up A in the refactor doc) — the aliases exist so
9
+ * future tightening is a one-place change instead of a sweep.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/tools/character/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Vitals domain — HP, hit dice, speed (all 5 modes), initiative, death saves.
3
+ * Owns the vitals block.
4
+ *
5
+ * Phase 3 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * AC is its own module ([Phase 4 → ac.ts]) — `formatVitalsBlock` takes it as
8
+ * a separate parameter rather than including it in `Vitals`, since AC isn't
9
+ * a vitals concern.
10
+ */
11
+ import type { CoreStats } from "./types.js";
12
+ export interface HitPoints {
13
+ current: number;
14
+ max: number;
15
+ temp: number;
16
+ }
17
+ export interface DeathSaves {
18
+ successes: number;
19
+ failures: number;
20
+ }
21
+ export interface Vitals {
22
+ hp: HitPoints;
23
+ hitDice: string[];
24
+ initiative: number;
25
+ speed: string[];
26
+ deathSaves: DeathSaves;
27
+ }
28
+ export declare function computeVitals(core: CoreStats): Vitals;
29
+ /**
30
+ * `ac` is computed by ./ac.js (Phase 4) and threaded in here separately
31
+ * because AC has its own module. `profBonus` is from CoreStats.
32
+ */
33
+ export declare function formatVitalsBlock(v: Vitals, ac: number, profBonus: number): string[];
34
+ //# sourceMappingURL=vitals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitals.d.ts","sourceRoot":"","sources":["../../../src/tools/character/vitals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAwB,SAAS,EAAO,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,SAAS;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AACzE,MAAM,WAAW,UAAU;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;AAEnE,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,SAAS,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;CACxB;AAmKD,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAQrD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpF"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Vitals domain — HP, hit dice, speed (all 5 modes), initiative, death saves.
3
+ * Owns the vitals block.
4
+ *
5
+ * Phase 3 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * AC is its own module ([Phase 4 → ac.ts]) — `formatVitalsBlock` takes it as
8
+ * a separate parameter rather than including it in `Vitals`, since AC isn't
9
+ * a vitals concern.
10
+ */
11
+ import { arr, hasRemarkableAthlete, isBonusMod, isHalfProficiencyMod, isSetMod, num, obj, signed, str } from "./helpers.js";
12
+ // ── HP ───────────────────────────────────────────────────────────────────────
13
+ function computeHp(core) {
14
+ const { char, allMods, statMods, totalLevel } = core;
15
+ // baseHitPoints does NOT include the CON modifier — must add conMod × level.
16
+ const conMod = statMods[2];
17
+ // Tough feat and Dwarven Toughness grant type:"bonus" subType:"hit-points-per-level" (value 2 or 1).
18
+ const hpPerLevelBonus = allMods
19
+ .filter(m => isBonusMod(m) && m.subType === "hit-points-per-level")
20
+ .reduce((s, m) => s + num(m.value ?? m.fixedValue), 0);
21
+ // When the player rolls for HP (or manually edits their max), DDB stores the
22
+ // final value in `overrideHitPoints`. This already includes CON mod and any
23
+ // hit-points-per-level features baked in — we must NOT add them on top.
24
+ // `bonusHitPoints` (items, Aid, etc.) still stacks on top either way.
25
+ // A literal 0 is treated as "not overridden" — defensive against malformed data.
26
+ const override = num(char.overrideHitPoints);
27
+ const bonus = num(char.bonusHitPoints);
28
+ const max = override > 0
29
+ ? override + bonus
30
+ : num(char.baseHitPoints) + bonus + ((conMod + hpPerLevelBonus) * totalLevel);
31
+ const current = max - num(char.removedHitPoints);
32
+ const temp = num(char.temporaryHitPoints);
33
+ return { current, max, temp };
34
+ }
35
+ // ── Hit dice ─────────────────────────────────────────────────────────────────
36
+ function computeHitDice(classes) {
37
+ return classes.map(c => {
38
+ const die = num(obj(c.definition).hitDice);
39
+ const lvl = num(c.level);
40
+ const used = num(c.hitDiceUsed);
41
+ return `${lvl}d${die} (${lvl - used} remaining)`;
42
+ });
43
+ }
44
+ // ── Speed ────────────────────────────────────────────────────────────────────
45
+ function computeSpeed(core) {
46
+ const { char, allMods } = core;
47
+ const weightSpeeds = obj(obj(obj(char.race).weightSpeeds).normal);
48
+ // Tasha's optional class features (Roving, Canny, Tireless, etc.) live in
49
+ // char.options.class. When preferences.enableOptionalClassFeatures is
50
+ // false, DDB does NOT include them in char.classes[].classFeatures, but
51
+ // their modifiers still appear in char.modifiers.class with
52
+ // `isGranted: true`. The website ignores those orphan modifiers; we must
53
+ // too. Discriminator: the modifier's componentId must match the id of a
54
+ // feature actually present in classFeatures/subclassFeatures. Hand-built
55
+ // fixtures don't set componentId at all (cid=0) — those bypass the filter
56
+ // unchanged.
57
+ const grantedClassFeatureIds = new Set();
58
+ for (const c of arr(char.classes)) {
59
+ for (const cf of arr(c.classFeatures)) {
60
+ const id = num(obj(cf.definition).id);
61
+ if (id)
62
+ grantedClassFeatureIds.add(id);
63
+ }
64
+ for (const cf of arr(obj(c.subclassDefinition).classFeatures)) {
65
+ const id = num(obj(cf.definition).id);
66
+ if (id)
67
+ grantedClassFeatureIds.add(id);
68
+ }
69
+ }
70
+ // Build the set of modifier object identities (by reference) that originate
71
+ // from a class/subclass category but whose componentId is orphaned — these
72
+ // must be skipped. Other sources (race, feat, item, background, condition)
73
+ // never get filtered.
74
+ const skippedClassMods = new Set();
75
+ for (const [source, list] of Object.entries(obj(char.modifiers))) {
76
+ if (source !== "class" && source !== "subclass")
77
+ continue;
78
+ for (const m of arr(list)) {
79
+ const cid = num(m.componentId);
80
+ if (cid !== 0 && !grantedClassFeatureIds.has(cid))
81
+ skippedClassMods.add(m);
82
+ }
83
+ }
84
+ const isApplicable = (m) => !skippedClassMods.has(m);
85
+ // DDB uses three subType patterns for speed modifiers:
86
+ // - `innate-speed-{axis}` — race-granted base / overrides (e.g. Dwarven slow speed)
87
+ // - `speed-{axis}` — class/feat/subclass axis-specific bonus (e.g. Scout's Superior Mobility, Ranger's Roving)
88
+ // - `speed` (no axis suffix) — generic walking-speed bonus (e.g. Barbarian Fast Movement, Mobile feat, Longstrider)
89
+ // `set` mods override the base axis speed; `bonus` mods stack on top.
90
+ const speedCalc = (axis, base, fallback = 0) => {
91
+ const subTypes = new Set([`innate-speed-${axis}`, `speed-${axis}`]);
92
+ // The bare "speed" subType is a walking-default bonus only; never applies to fly/swim/climb/burrow.
93
+ if (axis === "walking")
94
+ subTypes.add("speed");
95
+ const override = allMods
96
+ .filter(m => isSetMod(m) && subTypes.has(m.subType) && num(m.value ?? m.fixedValue) > 0 && isApplicable(m))
97
+ .reduce((max, m) => Math.max(max, num(m.value ?? m.fixedValue)), 0);
98
+ const bonus = allMods
99
+ .filter(m => isBonusMod(m) && subTypes.has(m.subType) && isApplicable(m))
100
+ .reduce((s, m) => s + num(m.value ?? m.fixedValue), 0);
101
+ return (override || base || fallback) + bonus;
102
+ };
103
+ // Monk Unarmored Movement uses "unarmored-movement" rather than "innate-speed-walking".
104
+ // Per PHB: only applies "while you are not wearing armor or wielding a
105
+ // shield." Gate on the absence of any equipped item with filterType="Armor"
106
+ // (which covers both body armor and shields, since DDB uses armorTypeId
107
+ // 1/2/3 for light/medium/heavy and 4 for shield, all under the same
108
+ // filterType).
109
+ const hasEquippedArmorOrShield = arr(char.inventory).some(i => i.equipped === true && str(obj(i.definition).filterType) === "Armor");
110
+ const unarmoredMoveBonus = hasEquippedArmorOrShield
111
+ ? 0
112
+ : allMods
113
+ .filter(m => isBonusMod(m) && m.subType === "unarmored-movement" && isApplicable(m))
114
+ .reduce((s, m) => s + num(m.value ?? m.fixedValue), 0);
115
+ const walkSpeed = speedCalc("walking", num(weightSpeeds.walk), 30) + unarmoredMoveBonus;
116
+ const flySpeed = speedCalc("flying", num(weightSpeeds.fly));
117
+ const swimSpeed = speedCalc("swimming", num(weightSpeeds.swim));
118
+ const climbSpeed = speedCalc("climbing", num(weightSpeeds.climb));
119
+ const burrowSpeed = speedCalc("burrowing", num(weightSpeeds.burrow));
120
+ const parts = [`${walkSpeed} ft.`];
121
+ if (flySpeed > 0)
122
+ parts.push(`fly ${flySpeed} ft.`);
123
+ if (swimSpeed > 0)
124
+ parts.push(`swim ${swimSpeed} ft.`);
125
+ if (climbSpeed > 0)
126
+ parts.push(`climb ${climbSpeed} ft.`);
127
+ if (burrowSpeed > 0)
128
+ parts.push(`burrow ${burrowSpeed} ft.`);
129
+ return parts;
130
+ }
131
+ // ── Initiative ───────────────────────────────────────────────────────────────
132
+ function computeInitiative(core) {
133
+ const { allMods, statMods, classes, profBonus } = core;
134
+ const dexMod = statMods[1];
135
+ const initiativeBonus = allMods
136
+ .filter(m => isBonusMod(m) && m.subType === "initiative")
137
+ .reduce((s, m) => {
138
+ // bonusTypes [1] means the bonus value is the proficiency bonus, not a fixed number
139
+ const usesProfBonus = arr(m.bonusTypes).includes(1) && (m.fixedValue == null && m.value == null);
140
+ if (usesProfBonus)
141
+ return s + profBonus;
142
+ if (m.value != null)
143
+ return s + num(m.value);
144
+ if (m.fixedValue != null)
145
+ return s + num(m.fixedValue);
146
+ // statId-based bonus (e.g. Gloom Stalker Dread Ambusher adds WIS mod to initiative)
147
+ const sid = num(m.statId);
148
+ return s + (sid > 0 ? statMods[sid - 1] : 0);
149
+ }, 0);
150
+ // Half-proficiency to initiative comes from two distinct sources:
151
+ //
152
+ // 1. Bard's Jack of All Trades emits an explicit
153
+ // `type:"half-proficiency" subType:"initiative"` modifier (in addition
154
+ // to its `subType:"ability-checks"` modifier that drives skills).
155
+ // PHB rule: round DOWN.
156
+ // 2. Champion Fighter's Remarkable Athlete emits NO modifier at all —
157
+ // detection is by subclass name + level (see hasRemarkableAthlete).
158
+ // PHB rule: round UP.
159
+ //
160
+ // We must NOT infer initiative half-prof from `subType:"ability-checks"`
161
+ // alone — the DDB website doesn't. If a character has both JoAT and RA
162
+ // somehow (Bard 2 / Champion 7 multiclass), take the max rather than
163
+ // double-stacking.
164
+ const joatInit = allMods.some(m => isHalfProficiencyMod(m) && m.subType === "initiative")
165
+ ? Math.floor(profBonus / 2)
166
+ : 0;
167
+ const raInit = hasRemarkableAthlete(classes) ? Math.ceil(profBonus / 2) : 0;
168
+ return dexMod + initiativeBonus + Math.max(joatInit, raInit);
169
+ }
170
+ // ── Death saves ──────────────────────────────────────────────────────────────
171
+ function computeDeathSaves(char) {
172
+ const ds = obj(char.deathSaves);
173
+ return { successes: num(ds.successCount), failures: num(ds.failCount) };
174
+ }
175
+ // ── Public API ───────────────────────────────────────────────────────────────
176
+ export function computeVitals(core) {
177
+ return {
178
+ hp: computeHp(core),
179
+ hitDice: computeHitDice(core.classes),
180
+ initiative: computeInitiative(core),
181
+ speed: computeSpeed(core),
182
+ deathSaves: computeDeathSaves(core.char),
183
+ };
184
+ }
185
+ /**
186
+ * `ac` is computed by ./ac.js (Phase 4) and threaded in here separately
187
+ * because AC has its own module. `profBonus` is from CoreStats.
188
+ */
189
+ export function formatVitalsBlock(v, ac, profBonus) {
190
+ return [
191
+ `HP: ${v.hp.current}/${v.hp.max} Temp HP: ${v.hp.temp || "—"} Prof Bonus: ${signed(profBonus)}`,
192
+ `Hit Dice: ${v.hitDice.join(" / ")}`,
193
+ `AC: ${ac} Initiative: ${signed(v.initiative)} Speed: ${v.speed.join(", ")}`,
194
+ `Death Saves: Successes ${v.deathSaves.successes}/3 Failures ${v.deathSaves.failures}/3`,
195
+ ``,
196
+ ];
197
+ }
198
+ //# sourceMappingURL=vitals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitals.js","sourceRoot":"","sources":["../../../src/tools/character/vitals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Weapons domain — weapon attack rolls for equipped inventory weapons.
3
+ *
4
+ * Phase 6a of the character.ts refactor — see docs/character-refactor.md.
5
+ *
6
+ * Owns ability-mod selection (finesse, ranged, Martial Arts monk weapons),
7
+ * proficiency bonus, magic enhancement (+1/+2/+3 from grantedModifiers), and
8
+ * duplicate consolidation (×2 daggers, etc.). Output is pre-formatted lines
9
+ * to preserve byte-for-byte parity with the original inline code.
10
+ */
11
+ import type { CoreStats } from "./types.js";
12
+ export declare function computeWeaponAttacks(core: CoreStats): string[];
13
+ //# sourceMappingURL=weapons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weapons.d.ts","sourceRoot":"","sources":["../../../src/tools/character/weapons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,CAgF9D"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Weapons domain — weapon attack rolls for equipped inventory weapons.
3
+ *
4
+ * Phase 6a of the character.ts refactor — see docs/character-refactor.md.
5
+ *
6
+ * Owns ability-mod selection (finesse, ranged, Martial Arts monk weapons),
7
+ * proficiency bonus, magic enhancement (+1/+2/+3 from grantedModifiers), and
8
+ * duplicate consolidation (×2 daggers, etc.). Output is pre-formatted lines
9
+ * to preserve byte-for-byte parity with the original inline code.
10
+ */
11
+ import { arr, isBonusMod, isProficiencyMod, num, obj, signed, str } from "./helpers.js";
12
+ export function computeWeaponAttacks(core) {
13
+ const { allMods, classes, inventory, statMods, profBonus } = core;
14
+ const dexMod = statMods[1];
15
+ const weaponProfSlugs = new Set(allMods.filter(isProficiencyMod).map(m => m.subType));
16
+ const isWeaponProficient = (def) => {
17
+ const catId = num(def.categoryId); // 1=simple, 2=martial
18
+ const typeName = str(def.type).toLowerCase().replace(/[,\s]+/g, "-");
19
+ return (catId === 1 && weaponProfSlugs.has("simple-weapons")) ||
20
+ (catId === 2 && weaponProfSlugs.has("martial-weapons")) ||
21
+ weaponProfSlugs.has(typeName);
22
+ };
23
+ // Martial Arts: allows DEX for monk weapons (simple melee + shortsword, no Two-Handed/Heavy)
24
+ const hasMartialArts = allMods.some(m => str(m.subType) === "martial-arts") ||
25
+ classes.some(c => arr(c.classFeatures).some(cf => str(obj(cf.definition).name) === "Martial Arts" &&
26
+ num(obj(cf.definition).requiredLevel || 1) <= num(c.level)));
27
+ const weaponInventoryMap = new Map();
28
+ for (const i of inventory) {
29
+ const def = obj(i.definition);
30
+ if (str(def.filterType) !== "Weapon")
31
+ continue;
32
+ if (i.equipped !== true)
33
+ continue; // only show equipped weapons in ACTIONS
34
+ const wName = str(def.name);
35
+ const dmg = obj(def.damage);
36
+ const dmgDice = str(dmg.diceString);
37
+ const dmgType = str(def.damageType).toLowerCase();
38
+ const attackType = num(def.attackType); // 1=melee, 2=ranged
39
+ const props = arr(def.properties).map(p => str(p.name));
40
+ const isFinesse = props.includes("Finesse");
41
+ const isRanged = attackType === 2;
42
+ const range = num(def.range);
43
+ const longRange = num(def.longRange);
44
+ const mastery = str(def.mastery);
45
+ // Magic enhancement bonus from grantedModifiers (e.g. +1 weapon)
46
+ const magicBonus = arr(def.grantedModifiers)
47
+ .filter(gm => isBonusMod(gm) && gm.subType === "magic")
48
+ .reduce((s, gm) => s + num(gm.value ?? gm.fixedValue), 0);
49
+ // Monk weapons: simple melee or shortsword, no Two-Handed/Heavy
50
+ const isMonkWeapon = hasMartialArts &&
51
+ !props.includes("Two-Handed") && !props.includes("Heavy") &&
52
+ ((num(def.categoryId) === 1 && attackType === 1) || str(def.name) === "Shortsword");
53
+ // Ability modifier for attack/damage
54
+ const usesDex = isRanged || ((isFinesse || isMonkWeapon) && dexMod > statMods[0]);
55
+ const abilityMod = usesDex ? dexMod : statMods[0];
56
+ const profMod = isWeaponProficient(def) ? profBonus : 0;
57
+ const hitBonus = abilityMod + profMod + magicBonus;
58
+ const dmgBonus = abilityMod + magicBonus;
59
+ const dmgStr = dmgBonus !== 0 ? `${dmgDice}${signed(dmgBonus)}` : dmgDice;
60
+ const rangeStr = isRanged ? `range ${range}/${longRange} ft.` : `reach 5 ft.`;
61
+ const propsStr = [...props, ...(mastery ? [mastery] : [])].join(", ");
62
+ const line = `• ${wName.padEnd(16)} ${signed(hitBonus)} to hit ${dmgStr} ${dmgType} ${rangeStr}${propsStr ? ` ${propsStr}` : ""}`;
63
+ // Consolidate duplicates by key
64
+ const key = wName + dmgDice;
65
+ const existing = weaponInventoryMap.get(key);
66
+ if (existing) {
67
+ existing.qty += num(i.quantity) || 1;
68
+ }
69
+ else {
70
+ weaponInventoryMap.set(key, { lines: [line], qty: num(i.quantity) || 1 });
71
+ }
72
+ }
73
+ const weaponAttacks = [];
74
+ for (const { lines, qty } of weaponInventoryMap.values()) {
75
+ weaponAttacks.push(qty > 1 ? lines[0].replace("•", `• ×${qty}`) : lines[0]);
76
+ }
77
+ return weaponAttacks;
78
+ }
79
+ //# sourceMappingURL=weapons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weapons.js","sourceRoot":"","sources":["../../../src/tools/character/weapons.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Public API surface for character tools. The 1000-line `parseCharacterData`
3
+ * and 220-line `getDefinition` that used to live here have been carved into
4
+ * per-domain modules under `./character/` — see docs/character-refactor.md.
5
+ *
6
+ * What stays here: network/IO (getCharacter, downloadCharacter,
7
+ * listCharacters, findCharacterByName), the in-process JSON cache, and
8
+ * thin re-exports of the moved entry points.
9
+ */
10
+ import type { ParseSection } from "./character/types.js";
11
+ export { parseCharacterData } from "./character/parse.js";
12
+ export { getDefinition } from "./character/definition.js";
13
+ /** Wipe the in-process character JSON cache. */
14
+ export declare function clearCharacterCache(): void;
1
15
  /**
2
16
  * Resolve a character name to a numeric ID using the character list API.
3
17
  * Resolution order: exact match → substring match → Levenshtein ≤3 on full
@@ -8,8 +22,7 @@ export declare function findCharacterByName(name: string): Promise<{
8
22
  id: string;
9
23
  name: string;
10
24
  } | null>;
11
- export declare function parseCharacterData(raw: Record<string, unknown>, sections?: "summary" | "combat" | "spells" | "inventory" | "features" | "concentration" | "notes" | "full"): string;
12
- export declare function parseCharacter(characterId: string, sections?: "summary" | "combat" | "spells" | "inventory" | "features" | "concentration" | "notes" | "full"): Promise<string>;
25
+ export declare function parseCharacter(characterId: string, sections?: ParseSection): Promise<string>;
13
26
  /**
14
27
  * Fetch raw character JSON from the DnD Beyond API.
15
28
  * Uses saved session cookies — no browser needed after initial login.
@@ -17,5 +30,4 @@ export declare function parseCharacter(characterId: string, sections?: "summary"
17
30
  export declare function getCharacter(characterId: string): Promise<string>;
18
31
  export declare function downloadCharacter(characterId: string, outputPath?: string): Promise<string>;
19
32
  export declare function listCharacters(): Promise<string>;
20
- export declare function getDefinition(characterId: string, query: string): Promise<string>;
21
33
  //# sourceMappingURL=character.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"character.d.ts","sourceRoot":"","sources":["../../src/tools/character.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA8BpG;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,QAAQ,GAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,eAAe,GAAG,OAAO,GAAG,MAAe,GACjH,MAAM,CA++BR;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,eAAe,GAAG,OAAO,GAAG,MAAe,GACjH,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAkCtD;AA2MD,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAiBjB"}
1
+ {"version":3,"file":"character.d.ts","sourceRoot":"","sources":["../../src/tools/character.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAW1D,gDAAgD;AAChD,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAoCpG;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,YAAqB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAkCtD"}