@archivist-gg/dnd5e 0.3.10 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/SRD.md +38 -3
- package/dist/armor/armor.codec.js +3 -3
- package/dist/armor/armor.parser.js +2 -2
- package/dist/armor/armor.schema.d.ts +1 -0
- package/dist/armor/armor.schema.js +1 -1
- package/dist/armor/armor.types.d.ts +2 -0
- package/dist/background/background.codec.js +5 -5
- package/dist/background/background.parser.js +4 -4
- package/dist/background/background.schema.js +3 -3
- package/dist/chunk-2LULMQTF.js +14 -0
- package/dist/{chunk-CBEKVAX4.js → chunk-4BZ47YJ4.js} +10 -3
- package/dist/{chunk-22MOUU2G.js → chunk-4SLOJXJ4.js} +1 -1
- package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
- package/dist/{chunk-J77CKYV3.js → chunk-5KGV6TF7.js} +1 -1
- package/dist/{chunk-3UNP3G4D.js → chunk-6ZY3U6BQ.js} +1 -1
- package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
- package/dist/{chunk-2M34FLAY.js → chunk-BRGLDWUP.js} +3 -1
- package/dist/chunk-CM5CWO4K.js +735 -0
- package/dist/{chunk-MI7P3NX3.js → chunk-DPM6V7YX.js} +2 -2
- package/dist/chunk-EJP263OP.js +186 -0
- package/dist/{chunk-G247QXWW.js → chunk-EL6QPF6I.js} +1 -1
- package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
- package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
- package/dist/{chunk-PI4LLJG4.js → chunk-FPGXFD2M.js} +2 -2
- package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
- package/dist/{chunk-NWDF5HG3.js → chunk-G7ED5H2G.js} +1 -1
- package/dist/chunk-H5PTKYXL.js +101 -0
- package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
- package/dist/{chunk-PP2UHLBA.js → chunk-HJQNK3J5.js} +8 -0
- package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
- package/dist/chunk-IHE6KVC3.js +13 -0
- package/dist/{chunk-BLRW2UU6.js → chunk-J53ERF6K.js} +2 -2
- package/dist/{chunk-MQ747UCR.js → chunk-JNNNBEUH.js} +65 -2
- package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
- package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
- package/dist/chunk-LBEXLN6I.js +91 -0
- package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
- package/dist/{chunk-OYUEUKKF.js → chunk-LVX6TQ3R.js} +12 -8
- package/dist/{chunk-R747YKS7.js → chunk-M2OWVAZG.js} +1 -1
- package/dist/{chunk-7YU4NPKR.js → chunk-MC5YJ4PB.js} +1 -1
- package/dist/{chunk-JCEV7KYN.js → chunk-MUIU7RZ3.js} +1 -1
- package/dist/{chunk-JSZ4H6AQ.js → chunk-MWCCGPG3.js} +1 -1
- package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
- package/dist/{chunk-S56D6B6C.js → chunk-PLOSP4XQ.js} +3 -3
- package/dist/{chunk-JANNRGJC.js → chunk-PX25R3DK.js} +1 -1
- package/dist/{chunk-V373TRJE.js → chunk-Q5XTEYHD.js} +191 -125
- package/dist/{chunk-MAH6DCRI.js → chunk-Q6UOHCCT.js} +1 -1
- package/dist/{chunk-HLQAFZKQ.js → chunk-QEO7LYTG.js} +216 -95
- package/dist/{chunk-PJMG5XV3.js → chunk-QSBJ6NEM.js} +1 -1
- package/dist/{chunk-BL3VELKP.js → chunk-R2V5LN3I.js} +1 -1
- package/dist/{chunk-4DOMDEBZ.js → chunk-RQNJXADQ.js} +1 -1
- package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
- package/dist/chunk-T5GZBKIQ.js +927 -0
- package/dist/{chunk-PZCE7DJM.js → chunk-UE6LKRXQ.js} +15 -1
- package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
- package/dist/{chunk-QHMWA3SZ.js → chunk-VDPRBUU5.js} +1 -1
- package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
- package/dist/{chunk-V6LJFP4R.js → chunk-X7VZY4ON.js} +2 -2
- package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
- package/dist/{chunk-BIA32MQ5.js → chunk-XJRNEQPD.js} +1 -1
- package/dist/{chunk-OZP6JFGT.js → chunk-XY6X2APM.js} +3 -1
- package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
- package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
- package/dist/{chunk-VQAXTIBW.js → chunk-ZDAEGJH4.js} +2 -0
- package/dist/{chunk-XTRDCSJB.js → chunk-ZMJQUZQH.js} +4 -1
- package/dist/chunk-ZUQW5VBZ.js +89 -0
- package/dist/class/class.codec.js +7 -7
- package/dist/class/class.parser.js +6 -6
- package/dist/class/class.schema.d.ts +10 -0
- package/dist/class/class.schema.js +5 -5
- package/dist/entities/base-item-resolver.js +2 -2
- package/dist/entities/slug.d.ts +18 -8
- package/dist/entities/slug.js +3 -1
- package/dist/feat/feat.codec.js +5 -5
- package/dist/feat/feat.parser.js +4 -4
- package/dist/feat/feat.schema.d.ts +16 -3
- package/dist/feat/feat.schema.js +3 -3
- package/dist/index.js +5277 -2017
- package/dist/item/item.actions-map.d.ts +40 -5
- package/dist/item/item.actions-map.js +5 -84
- package/dist/item/item.attunement.js +3 -9
- package/dist/item/item.bonuses.js +5 -2
- package/dist/item/item.codec.js +3 -3
- package/dist/item/item.conditions.js +4 -1
- package/dist/item/item.conditions.types.d.ts +4 -0
- package/dist/item/item.cost.d.ts +3 -0
- package/dist/item/item.cost.js +29 -0
- package/dist/item/item.icon.d.ts +15 -0
- package/dist/item/item.icon.js +211 -0
- package/dist/item/item.parser.js +2 -2
- package/dist/item/item.schema.d.ts +16 -1
- package/dist/item/item.schema.js +3 -1
- package/dist/item/item.types.d.ts +9 -2
- package/dist/monster/monster.parser.js +5 -5
- package/dist/monster/monster.schema.js +4 -4
- package/dist/optional-feature/optional-feature.codec.js +4 -4
- package/dist/optional-feature/optional-feature.parser.js +3 -3
- package/dist/optional-feature/optional-feature.schema.d.ts +229 -3
- package/dist/optional-feature/optional-feature.schema.js +6 -2
- package/dist/pc/pc.additional-spells.js +4 -4
- package/dist/pc/pc.asi-flatten.d.ts +62 -1
- package/dist/pc/pc.asi-flatten.js +16 -0
- package/dist/pc/pc.conditions.js +1 -1
- package/dist/pc/pc.containment.d.ts +45 -0
- package/dist/pc/pc.containment.js +24 -0
- package/dist/pc/pc.decision-engine.d.ts +21 -3
- package/dist/pc/pc.decision-engine.js +23 -14
- package/dist/pc/pc.entry-overrides.d.ts +79 -0
- package/dist/pc/pc.entry-overrides.js +40 -0
- package/dist/pc/pc.equipment.d.ts +2 -2
- package/dist/pc/pc.equipment.js +18 -7
- package/dist/pc/pc.feature-effects.js +2 -2
- package/dist/pc/pc.infusions.d.ts +220 -0
- package/dist/pc/pc.infusions.js +64 -0
- package/dist/pc/pc.parser.js +18 -1
- package/dist/pc/pc.pools.d.ts +1 -1
- package/dist/pc/pc.pools.js +11 -3
- package/dist/pc/pc.proficiencies.js +21 -14
- package/dist/pc/pc.recalc.d.ts +39 -36
- package/dist/pc/pc.recalc.js +60 -32
- package/dist/pc/pc.resolver.js +21 -14
- package/dist/pc/pc.resource-seed.js +1 -1
- package/dist/pc/pc.resources.d.ts +6 -1
- package/dist/pc/pc.resources.js +3 -1
- package/dist/pc/pc.rest.d.ts +21 -1
- package/dist/pc/pc.rest.js +52 -19
- package/dist/pc/pc.schema.d.ts +14 -0
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.slotting.d.ts +36 -3
- package/dist/pc/pc.slotting.js +13 -5
- package/dist/pc/pc.tool-picks.d.ts +51 -0
- package/dist/pc/pc.tool-picks.js +18 -0
- package/dist/pc/pc.types.d.ts +70 -12
- package/dist/pc/pool-layout.d.ts +14 -0
- package/dist/pc/pool-layout.js +7 -3
- package/dist/race/race.codec.js +6 -6
- package/dist/race/race.parser.js +5 -5
- package/dist/race/race.schema.js +4 -4
- package/dist/schemas/attack-schema.d.ts +1 -1
- package/dist/schemas/choice-schema.js +2 -2
- package/dist/schemas/feature-effect-schema.d.ts +16 -3
- package/dist/schemas/feature-effect-schema.js +1 -1
- package/dist/schemas/feature-schema.js +3 -3
- package/dist/schemas/selection-pool-schema.d.ts +10 -0
- package/dist/schemas/selection-pool-schema.js +1 -1
- package/dist/spell/spell.codec.js +3 -3
- package/dist/spell/spell.parser.js +2 -2
- package/dist/spell/spell.scaling.d.ts +34 -10
- package/dist/spell/spell.scaling.js +36 -4
- package/dist/spell/spell.schema.d.ts +1 -0
- package/dist/spell/spell.schema.js +1 -1
- package/dist/spell/spell.types.d.ts +4 -0
- package/dist/srd/retired-items.d.ts +14 -0
- package/dist/srd/retired-items.js +11 -0
- package/dist/subclass/subclass.codec.js +7 -7
- package/dist/subclass/subclass.parser.js +6 -6
- package/dist/subclass/subclass.schema.d.ts +10 -0
- package/dist/subclass/subclass.schema.js +5 -5
- package/dist/types/choice.d.ts +8 -0
- package/dist/types/equipment-grant.d.ts +18 -1
- package/dist/types/equipment-grant.js +12 -0
- package/dist/types/feature-effect.d.ts +6 -1
- package/dist/types/optional-feature.types.d.ts +79 -1
- package/dist/types/selection-pool.d.ts +16 -1
- package/dist/weapon/weapon.classify.d.ts +10 -8
- package/dist/weapon/weapon.classify.js +2 -2
- package/dist/weapon/weapon.codec.js +3 -3
- package/dist/weapon/weapon.parser.js +2 -2
- package/dist/weapon/weapon.schema.d.ts +1 -0
- package/dist/weapon/weapon.schema.js +1 -1
- package/dist/weapon/weapon.types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-O4SRD3J5.js +0 -165
- package/dist/chunk-WXWPK3LI.js +0 -55
|
@@ -1,34 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
2
|
classifyWeaponRange
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
defaultSlotForType,
|
|
6
|
-
effectiveArmor,
|
|
7
|
-
isItemEntity,
|
|
8
|
-
isWeaponEntity,
|
|
9
|
-
resolveEntityForEntry
|
|
10
|
-
} from "./chunk-UBBKSYBY.js";
|
|
3
|
+
} from "./chunk-YDGMBMYI.js";
|
|
11
4
|
import {
|
|
12
5
|
normKey
|
|
13
6
|
} from "./chunk-RLGQ5PZZ.js";
|
|
7
|
+
import {
|
|
8
|
+
WEAPON_DEFAULT_ACTION_COST,
|
|
9
|
+
resolveEntryEntity
|
|
10
|
+
} from "./chunk-T5GZBKIQ.js";
|
|
11
|
+
import {
|
|
12
|
+
resolveContainment
|
|
13
|
+
} from "./chunk-EJP263OP.js";
|
|
14
14
|
import {
|
|
15
15
|
readNumericBonus
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-HHBD4SQ6.js";
|
|
17
|
+
import {
|
|
18
|
+
defaultSlotForType,
|
|
19
|
+
effectiveArmor,
|
|
20
|
+
effectiveWeapon,
|
|
21
|
+
isItemEntity,
|
|
22
|
+
isShieldArmor,
|
|
23
|
+
isTwoHandedWeapon,
|
|
24
|
+
slotAcTerms
|
|
25
|
+
} from "./chunk-LHZXYFBU.js";
|
|
17
26
|
import {
|
|
18
27
|
resolveBaseItem
|
|
19
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-CM5CWO4K.js";
|
|
20
29
|
import {
|
|
21
30
|
bareEntitySlug
|
|
22
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-ZCTUYGNV.js";
|
|
23
32
|
|
|
24
33
|
// src/weapon/weapon-mastery.ts
|
|
25
34
|
var MASTERY = {
|
|
26
35
|
cleave: { label: "Cleave", description: "If you hit a creature with a melee attack roll using this weapon, you can make an attack roll with the weapon against a second creature within 5 feet of the first that is also within your reach. On a hit, the second creature takes the weapon's damage, but don't add your ability modifier to that damage unless it is negative. You can make this extra attack only once per turn.", gist: "hit a 2nd creature in reach" },
|
|
27
36
|
graze: { label: "Graze", description: "If your attack roll with this weapon misses a creature, you can deal damage to that creature equal to the ability modifier you used to make the attack roll. This damage is the same type dealt by the weapon, and the damage can be increased only by increasing the ability modifier.", gist: "on miss: ability-mod damage" },
|
|
28
37
|
nick: { label: "Nick", description: "When you make the extra attack of the Light property, you can make it as part of the Attack action instead of as a Bonus Action. You can make this extra attack only once per turn.", gist: "extra Light attack (no Bonus Action)" },
|
|
29
|
-
push: { label: "Push", description: "If you hit a creature with this weapon, you can push the creature up to 10 feet straight away from yourself if it is Large or smaller.", gist: "on hit: pushed 10 ft" },
|
|
38
|
+
push: { label: "Push", description: "If you hit a creature with this weapon, you can push the creature up to 10 feet straight away from yourself if it is Large or smaller.", gist: "on hit: pushed 10 ft." },
|
|
30
39
|
sap: { label: "Sap", description: "If you hit a creature with this weapon, that creature has Disadvantage on its next attack roll before the start of your next turn.", gist: "on hit: target Disadvantage" },
|
|
31
|
-
slow: { label: "Slow", description: "If you hit a creature with this weapon and deal damage, you can reduce its Speed by 10 feet until the start of your next turn. If the creature is hit more than once by weapons that have this property, the Speed reduction doesn't exceed 10 feet.", gist: "on hit: -10 ft Speed" },
|
|
40
|
+
slow: { label: "Slow", description: "If you hit a creature with this weapon and deal damage, you can reduce its Speed by 10 feet until the start of your next turn. If the creature is hit more than once by weapons that have this property, the Speed reduction doesn't exceed 10 feet.", gist: "on hit: -10 ft. Speed" },
|
|
32
41
|
topple: { label: "Topple", description: "If you hit a creature with this weapon, you can force the creature to make a Constitution saving throw (DC 8 plus the ability modifier used to make the attack roll and your Proficiency Bonus). On a failed save, the creature has the Prone condition.", gist: "on fail: Prone" },
|
|
33
42
|
vex: { label: "Vex", description: "If you hit a creature with this weapon and deal damage, you have Advantage on your next attack roll against that creature before the end of your next turn.", gist: "on hit: you gain Advantage next" }
|
|
34
43
|
};
|
|
@@ -75,13 +84,15 @@ function unwrapClassSlug(maybeWiki) {
|
|
|
75
84
|
const m = /^\[\[([^\]]+)\]\]$/.exec(maybeWiki);
|
|
76
85
|
return (m ? m[1] : maybeWiki).toLowerCase();
|
|
77
86
|
}
|
|
78
|
-
function buildConditionContext(resolved, equippedSlots) {
|
|
87
|
+
function buildConditionContext(resolved, equippedSlots, registry) {
|
|
79
88
|
var _a, _b;
|
|
80
89
|
return {
|
|
81
90
|
derived: { equippedSlots },
|
|
82
91
|
classList: (_a = resolved.definition.class) != null ? _a : [],
|
|
83
92
|
race: resolved.definition.race,
|
|
84
|
-
subclasses: ((_b = resolved.definition.class) != null ? _b : []).map((c) => c.subclass).filter((s) => typeof s === "string" && s.length > 0).map(unwrapClassSlug)
|
|
93
|
+
subclasses: ((_b = resolved.definition.class) != null ? _b : []).map((c) => c.subclass).filter((s) => typeof s === "string" && s.length > 0).map(unwrapClassSlug),
|
|
94
|
+
// H234 H2: `wielding_two_handed` reads a magic main-hand weapon's base through it.
|
|
95
|
+
registry
|
|
85
96
|
};
|
|
86
97
|
}
|
|
87
98
|
function pushApply(outcome, field, source, pool, onApply) {
|
|
@@ -92,29 +103,30 @@ function pushApply(outcome, field, source, pool, onApply) {
|
|
|
92
103
|
}
|
|
93
104
|
}
|
|
94
105
|
function computeAppliedBonuses(resolved, _profs, registry, warnings) {
|
|
95
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
106
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
96
107
|
const out = emptyAppliedBonuses();
|
|
97
108
|
const equipment = (_a = resolved.definition.equipment) != null ? _a : [];
|
|
98
|
-
const ctx = buildConditionContext(resolved, {});
|
|
99
|
-
for (
|
|
100
|
-
const
|
|
109
|
+
const ctx = buildConditionContext(resolved, {}, registry);
|
|
110
|
+
for (let index = 0; index < equipment.length; index++) {
|
|
111
|
+
const entry = equipment[index];
|
|
112
|
+
const { entity, entityType } = resolveEntryEntity(entry, index, registry, resolved.infusions);
|
|
101
113
|
if (!entity) {
|
|
102
114
|
const slug = unwrapSlug(entry.item);
|
|
103
|
-
if (slug && entry.equipped) warnings.push(`Equipped item [[${slug}]] not found in compendium.`);
|
|
115
|
+
if (slug && entry.equipped && !((_b = resolved.infusions) == null ? void 0 : _b.views.has(index))) warnings.push(`Equipped item [[${slug}]] not found in compendium.`);
|
|
104
116
|
continue;
|
|
105
117
|
}
|
|
106
118
|
if (!isAttunedActive(entry, entity)) continue;
|
|
107
119
|
if (entityType !== "item") continue;
|
|
108
120
|
const item = entity;
|
|
109
|
-
(
|
|
110
|
-
(
|
|
111
|
-
(
|
|
112
|
-
(
|
|
113
|
-
(
|
|
114
|
-
(
|
|
115
|
-
(
|
|
116
|
-
(
|
|
117
|
-
const gs = (
|
|
121
|
+
(_c = item.resist) == null ? void 0 : _c.forEach((s) => out.defenses.resistances.push(s));
|
|
122
|
+
(_d = item.immune) == null ? void 0 : _d.forEach((s) => out.defenses.immunities.push(s));
|
|
123
|
+
(_e = item.vulnerable) == null ? void 0 : _e.forEach((s) => out.defenses.vulnerabilities.push(s));
|
|
124
|
+
(_f = item.condition_immune) == null ? void 0 : _f.forEach((s) => out.defenses.condition_immunities.push(s));
|
|
125
|
+
(_h = (_g = entry.overrides) == null ? void 0 : _g.resist) == null ? void 0 : _h.forEach((s) => out.defenses.resistances.push(s));
|
|
126
|
+
(_j = (_i = entry.overrides) == null ? void 0 : _i.immune) == null ? void 0 : _j.forEach((s) => out.defenses.immunities.push(s));
|
|
127
|
+
(_l = (_k = entry.overrides) == null ? void 0 : _k.vulnerable) == null ? void 0 : _l.forEach((s) => out.defenses.vulnerabilities.push(s));
|
|
128
|
+
(_n = (_m = entry.overrides) == null ? void 0 : _m.condition_immune) == null ? void 0 : _n.forEach((s) => out.defenses.condition_immunities.push(s));
|
|
129
|
+
const gs = (_o = item.grants) == null ? void 0 : _o.senses;
|
|
118
130
|
if (gs) {
|
|
119
131
|
if (typeof gs.darkvision === "number") out.senses.darkvision = Math.max(out.senses.darkvision, gs.darkvision);
|
|
120
132
|
if (typeof gs.blindsight === "number") out.senses.blindsight = Math.max(out.senses.blindsight, gs.blindsight);
|
|
@@ -150,7 +162,7 @@ function computeAppliedBonuses(resolved, _profs, registry, warnings) {
|
|
|
150
162
|
out.spell_save_dc += v;
|
|
151
163
|
}
|
|
152
164
|
);
|
|
153
|
-
if ((
|
|
165
|
+
if ((_p = b.ability_scores) == null ? void 0 : _p.bonus) {
|
|
154
166
|
for (const [k, v] of Object.entries(b.ability_scores.bonus)) {
|
|
155
167
|
if (!isAbilityKey(k)) continue;
|
|
156
168
|
pushApply(
|
|
@@ -165,7 +177,7 @@ function computeAppliedBonuses(resolved, _profs, registry, warnings) {
|
|
|
165
177
|
);
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
|
-
if ((
|
|
180
|
+
if ((_q = b.ability_scores) == null ? void 0 : _q.static) {
|
|
169
181
|
for (const [k, n] of Object.entries(b.ability_scores.static)) {
|
|
170
182
|
if (!isAbilityKey(k) || typeof n !== "number") continue;
|
|
171
183
|
const prev = out.ability_statics[k];
|
|
@@ -227,28 +239,22 @@ function computeAppliedBonuses(resolved, _profs, registry, warnings) {
|
|
|
227
239
|
}
|
|
228
240
|
return out;
|
|
229
241
|
}
|
|
230
|
-
function isTwoHanded(weapon) {
|
|
231
|
-
return weapon.properties.some((p) => p === "two_handed");
|
|
232
|
-
}
|
|
233
242
|
function assignSlots(resolved, registry, warnings) {
|
|
234
|
-
var _a
|
|
243
|
+
var _a;
|
|
235
244
|
const slots = {};
|
|
236
245
|
const eq = (_a = resolved.definition.equipment) != null ? _a : [];
|
|
237
246
|
for (let i = 0; i < eq.length; i++) {
|
|
238
247
|
const entry = eq[i];
|
|
239
248
|
if (!entry.equipped || !entry.slot) continue;
|
|
240
|
-
const { entity, entityType } =
|
|
241
|
-
if (slots[entry.slot])
|
|
242
|
-
warnings.push(`${entry.slot} slot conflict: ${entry.item} ignored (already taken).`);
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
249
|
+
const { entity, entityType } = resolveEntryEntity(entry, i, registry, resolved.infusions);
|
|
250
|
+
if (slots[entry.slot]) continue;
|
|
245
251
|
const placed = { index: i, entity, entityType, entry };
|
|
246
252
|
slots[entry.slot] = placed;
|
|
247
253
|
}
|
|
248
254
|
for (let i = 0; i < eq.length; i++) {
|
|
249
255
|
const entry = eq[i];
|
|
250
256
|
if (!entry.equipped || entry.slot) continue;
|
|
251
|
-
const { entity, entityType } =
|
|
257
|
+
const { entity, entityType } = resolveEntryEntity(entry, i, registry, resolved.infusions);
|
|
252
258
|
if (!entity || !entityType) continue;
|
|
253
259
|
const defaultSlot = defaultSlotForType(entityType, entity, registry);
|
|
254
260
|
if (!defaultSlot) {
|
|
@@ -263,23 +269,45 @@ function assignSlots(resolved, registry, warnings) {
|
|
|
263
269
|
if (defaultSlot === "mainhand") {
|
|
264
270
|
if (!slots.mainhand) slots.mainhand = placed;
|
|
265
271
|
else if (!slots.offhand) slots.offhand = placed;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (slots[defaultSlot]) {
|
|
269
|
-
warnings.push(`${defaultSlot} slot already filled; ${entry.item} ignored.`);
|
|
270
|
-
} else {
|
|
271
|
-
slots[defaultSlot] = placed;
|
|
272
|
-
}
|
|
272
|
+
} else if (!slots[defaultSlot]) {
|
|
273
|
+
slots[defaultSlot] = placed;
|
|
273
274
|
}
|
|
274
275
|
}
|
|
275
|
-
const main = (_b = slots.mainhand) == null ? void 0 : _b.entity;
|
|
276
|
-
if (main && isWeaponEntity(main) && isTwoHanded(main) && slots.shield) {
|
|
277
|
-
warnings.push(`Two-handed weapon equipped; shield ignored.`);
|
|
278
|
-
}
|
|
279
276
|
return slots;
|
|
280
277
|
}
|
|
278
|
+
function pickShield(equippedSlots, equipment, registry, infusions) {
|
|
279
|
+
const slotted = equippedSlots.shield;
|
|
280
|
+
const slottedArmor = effectiveArmor(slotted == null ? void 0 : slotted.entity, registry);
|
|
281
|
+
if (slotted && slottedArmor && isShieldArmor(slottedArmor)) {
|
|
282
|
+
return { index: slotted.index, shield: slottedArmor, entity: slotted.entity, entry: slotted.entry };
|
|
283
|
+
}
|
|
284
|
+
for (let i = 0; i < equipment.length; i++) {
|
|
285
|
+
const entry = equipment[i];
|
|
286
|
+
if (!entry.equipped) continue;
|
|
287
|
+
const { entity } = resolveEntryEntity(entry, i, registry, infusions);
|
|
288
|
+
const armor = effectiveArmor(entity, registry);
|
|
289
|
+
if (armor && isShieldArmor(armor)) return { index: i, shield: armor, entity, entry };
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
function twoHandedShieldWarnings(equipment, registry, warnings, infusions) {
|
|
294
|
+
const equipped = equipment.flatMap((entry, i) => {
|
|
295
|
+
if (!entry.equipped) return [];
|
|
296
|
+
const { entity } = resolveEntryEntity(entry, i, registry, infusions);
|
|
297
|
+
return [{ entry, entity }];
|
|
298
|
+
});
|
|
299
|
+
const isShield = (e) => {
|
|
300
|
+
const armor = effectiveArmor(e.entity, registry);
|
|
301
|
+
return !!armor && isShieldArmor(armor);
|
|
302
|
+
};
|
|
303
|
+
for (const e of equipped) {
|
|
304
|
+
if (!e.entity || !isTwoHandedWeapon(e.entity, registry)) continue;
|
|
305
|
+
if (!equipped.some((other) => other !== e && isShield(other))) continue;
|
|
306
|
+
warnings.push(`${e.entity.name} is two-handed and a Shield is also equipped.`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
281
309
|
function computeAC(equippedSlots, resolved, mods, registry, warnings) {
|
|
282
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
310
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
283
311
|
const breakdown = [];
|
|
284
312
|
const armorSlot = equippedSlots.armor;
|
|
285
313
|
const armorEntity = (_a = armorSlot == null ? void 0 : armorSlot.entity) != null ? _a : null;
|
|
@@ -289,13 +317,25 @@ function computeAC(equippedSlots, resolved, mods, registry, warnings) {
|
|
|
289
317
|
`Magic armor "${armorEntity.name}" base_item ${armorEntity.base_item} did not resolve to a base armor; AC not applied.`
|
|
290
318
|
);
|
|
291
319
|
}
|
|
320
|
+
const acCtx = buildConditionContext(resolved, equippedSlots, registry);
|
|
321
|
+
const skip = /* @__PURE__ */ new Set();
|
|
322
|
+
const slotBonus = (slot) => {
|
|
323
|
+
var _a2, _b2;
|
|
324
|
+
const view = slot ? (_a2 = resolved.infusions) == null ? void 0 : _a2.views.get(slot.index) : void 0;
|
|
325
|
+
if (!slot || !(view == null ? void 0 : view.entity) || !isItemEntity(view.entity) || !isAttunedActive(slot.entry, view.entity)) return 0;
|
|
326
|
+
const out = readNumericBonus((_b2 = view.entity.bonuses) == null ? void 0 : _b2.ac, acCtx);
|
|
327
|
+
if ((out == null ? void 0 : out.kind) !== "applied") return 0;
|
|
328
|
+
skip.add(slot.index);
|
|
329
|
+
return out.value;
|
|
330
|
+
};
|
|
331
|
+
const armorTerms = slotAcTerms(armor, armorSlot == null ? void 0 : armorSlot.entry);
|
|
292
332
|
let ac = 10;
|
|
293
|
-
if (armor) {
|
|
294
|
-
const armorBase = armor
|
|
333
|
+
if (armor && armorTerms.armor !== null) {
|
|
334
|
+
const armorBase = armorTerms.armor + slotBonus(armorSlot);
|
|
295
335
|
ac = armorBase;
|
|
296
|
-
breakdown.push({ source: (
|
|
336
|
+
breakdown.push({ source: (_b = armorEntity == null ? void 0 : armorEntity.name) != null ? _b : armor.name, amount: armorBase, kind: "armor" });
|
|
297
337
|
if (armor.ac.add_dex) {
|
|
298
|
-
const dexCap = (
|
|
338
|
+
const dexCap = (_c = armor.ac.dex_max) != null ? _c : Number.POSITIVE_INFINITY;
|
|
299
339
|
const dexAdd = Math.min(mods.dex, dexCap);
|
|
300
340
|
ac += dexAdd;
|
|
301
341
|
const capped = mods.dex > dexCap;
|
|
@@ -306,28 +346,34 @@ function computeAC(equippedSlots, resolved, mods, registry, warnings) {
|
|
|
306
346
|
breakdown.push({ source: "Base", amount: 10, kind: "unarmored" });
|
|
307
347
|
breakdown.push({ source: "DEX modifier", amount: mods.dex, kind: "dex" });
|
|
308
348
|
}
|
|
309
|
-
const acBonus =
|
|
310
|
-
if (
|
|
349
|
+
const acBonus = armorTerms.override;
|
|
350
|
+
if (acBonus !== 0) {
|
|
311
351
|
ac += acBonus;
|
|
312
|
-
breakdown.push({ source: `${(
|
|
352
|
+
breakdown.push({ source: `${(_d = armorEntity == null ? void 0 : armorEntity.name) != null ? _d : "Armor"} (override)`, amount: acBonus, kind: "override" });
|
|
313
353
|
}
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const n = shield.ac.base + ((_j = shield.ac.flat) != null ? _j : 0);
|
|
354
|
+
const picked = pickShield(equippedSlots, (_e = resolved.definition.equipment) != null ? _e : [], registry, resolved.infusions);
|
|
355
|
+
if (picked) {
|
|
356
|
+
const { shield, entity: shieldEntity } = picked;
|
|
357
|
+
const shieldTerms = slotAcTerms(shield, picked.entry);
|
|
358
|
+
const n = shieldTerms.armor + slotBonus(picked);
|
|
320
359
|
ac += n;
|
|
321
|
-
breakdown.push({ source: (
|
|
360
|
+
breakdown.push({ source: (_f = shieldEntity == null ? void 0 : shieldEntity.name) != null ? _f : shield.name, amount: n, kind: "shield" });
|
|
361
|
+
const shieldAcBonus = shieldTerms.override;
|
|
362
|
+
if (shieldAcBonus !== 0) {
|
|
363
|
+
ac += shieldAcBonus;
|
|
364
|
+
breakdown.push({ source: `${(_g = shieldEntity == null ? void 0 : shieldEntity.name) != null ? _g : shield.name} (override)`, amount: shieldAcBonus, kind: "shield" });
|
|
365
|
+
}
|
|
322
366
|
}
|
|
323
367
|
const acInformational = [];
|
|
324
|
-
const
|
|
325
|
-
for (
|
|
326
|
-
|
|
368
|
+
const acEquipment = (_h = resolved.definition.equipment) != null ? _h : [];
|
|
369
|
+
for (let index = 0; index < acEquipment.length; index++) {
|
|
370
|
+
if (skip.has(index)) continue;
|
|
371
|
+
const entry = acEquipment[index];
|
|
372
|
+
const { entity, entityType } = resolveEntryEntity(entry, index, registry, resolved.infusions);
|
|
327
373
|
if (!entity || entityType !== "item") continue;
|
|
328
374
|
if (!isAttunedActive(entry, entity)) continue;
|
|
329
375
|
const item = entity;
|
|
330
|
-
const out = readNumericBonus((
|
|
376
|
+
const out = readNumericBonus((_i = item.bonuses) == null ? void 0 : _i.ac, acCtx);
|
|
331
377
|
if (!out) continue;
|
|
332
378
|
if (out.kind === "applied") {
|
|
333
379
|
ac += out.value;
|
|
@@ -373,9 +419,9 @@ function isWeaponSlugProficient(weapon, weaponSlug, profs) {
|
|
|
373
419
|
}
|
|
374
420
|
return false;
|
|
375
421
|
}
|
|
376
|
-
function magicBonusesForWeaponEntry(entry, registry, ctx) {
|
|
422
|
+
function magicBonusesForWeaponEntry(entry, registry, ctx, index, infusions) {
|
|
377
423
|
var _a;
|
|
378
|
-
const { entity } =
|
|
424
|
+
const { entity } = resolveEntryEntity(entry, index, registry, infusions);
|
|
379
425
|
const ovr = (_a = entry.overrides) != null ? _a : {};
|
|
380
426
|
const entryAttack = typeof ovr.bonus === "number" ? ovr.bonus : 0;
|
|
381
427
|
const entryDamage = typeof ovr.damage_bonus === "number" ? ovr.damage_bonus : 0;
|
|
@@ -440,8 +486,8 @@ function buildAttackRow(args) {
|
|
|
440
486
|
{ source: magicSource, amount: magic.dmg, kind: "item" }
|
|
441
487
|
];
|
|
442
488
|
const modes = classifyWeaponRange(weapon);
|
|
443
|
-
const fmtRanged = (r) => `${r.normal}/${r.long} ft
|
|
444
|
-
const range = modes.melee ? `${modes.melee.reach} ft
|
|
489
|
+
const fmtRanged = (r) => `${r.normal}/${r.long} ft.`;
|
|
490
|
+
const range = modes.melee ? `${modes.melee.reach} ft.` : modes.ranged ? fmtRanged(modes.ranged) : void 0;
|
|
445
491
|
const thrownRange = modes.melee && modes.ranged ? fmtRanged(modes.ranged) : void 0;
|
|
446
492
|
const stringProps = weapon.properties.filter(
|
|
447
493
|
(p) => typeof p === "string"
|
|
@@ -455,14 +501,17 @@ function buildAttackRow(args) {
|
|
|
455
501
|
toHit,
|
|
456
502
|
damageDice,
|
|
457
503
|
damageType: (_b = magic.damageTypeOverride) != null ? _b : weapon.damage.type,
|
|
458
|
-
// Riders: item damage_riders (Task 2) + the
|
|
504
|
+
// Riders: item damage_riders (Task 2) + the entry's overrides.extra_damage string. The override
|
|
505
|
+
// rider carries NO source: the player typed it on this very row, so the weapons table attributes it
|
|
506
|
+
// to nothing (no "(manual)" in a caption, no hover title on its chip).
|
|
459
507
|
...(() => {
|
|
460
508
|
const riders = [
|
|
461
509
|
...magic.riders,
|
|
462
|
-
...magic.extra ? [{ amount: magic.extra
|
|
510
|
+
...magic.extra ? [{ amount: magic.extra }] : []
|
|
463
511
|
];
|
|
464
512
|
return riders.length ? { damageRiders: riders } : {};
|
|
465
513
|
})(),
|
|
514
|
+
weaponCategory: modes.melee ? "melee" : "ranged",
|
|
466
515
|
properties: finalProps,
|
|
467
516
|
proficient,
|
|
468
517
|
breakdown: { toHit: toHitBreakdown, damage: damageBreakdown },
|
|
@@ -496,7 +545,7 @@ function buildUnarmedRow(mods, proficiencyBonus, spec) {
|
|
|
496
545
|
id: "unarmed-strike",
|
|
497
546
|
name: "Unarmed Strike",
|
|
498
547
|
unarmed: true,
|
|
499
|
-
range: "5 ft",
|
|
548
|
+
range: "5 ft.",
|
|
500
549
|
toHit,
|
|
501
550
|
damageDice,
|
|
502
551
|
damageType: "bludgeoning",
|
|
@@ -507,8 +556,10 @@ function buildUnarmedRow(mods, proficiencyBonus, spec) {
|
|
|
507
556
|
{ source: label, amount: abilityMod, kind: "ability" },
|
|
508
557
|
{ source: "Proficiency bonus", amount: proficiencyBonus, kind: "ability" }
|
|
509
558
|
],
|
|
559
|
+
// T17 T-33: the base term is the one the total sums. With no die the strike deals 1 + mod, so the base is +1
|
|
560
|
+
// (it read +0 beside a total of 1 + mod); a die carries its own base, as a weapon's does, so it stays +0.
|
|
510
561
|
damage: [
|
|
511
|
-
{ source: "Base damage", amount: 0, kind: "ability" },
|
|
562
|
+
{ source: "Base damage", amount: (spec == null ? void 0 : spec.dice) ? 0 : 1, kind: "ability" },
|
|
512
563
|
{ source: label, amount: abilityMod, kind: "ability" }
|
|
513
564
|
]
|
|
514
565
|
},
|
|
@@ -528,45 +579,22 @@ function formatWeaponSubLabel(weapon, properties, modes) {
|
|
|
528
579
|
if (properties.length > 0) parts.push(properties.map(humanizeWeaponToken).join(", "));
|
|
529
580
|
return parts.join(" \xB7 ");
|
|
530
581
|
}
|
|
531
|
-
function computeAttacks(equippedSlots, mods, profs, registry, warnings, proficiencyBonus, ctx, weaponMasteries, weaponAbilities = []) {
|
|
532
|
-
var _a, _b
|
|
582
|
+
function computeAttacks(equippedSlots, equipment, mods, profs, registry, warnings, proficiencyBonus, ctx, weaponMasteries, weaponAbilities = [], infusions) {
|
|
583
|
+
var _a, _b;
|
|
533
584
|
const rows = [];
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
];
|
|
538
|
-
for (const { key, placed } of handedSlots) {
|
|
539
|
-
if (!placed) continue;
|
|
540
|
-
const { entity, entry } = placed;
|
|
541
|
-
if (!entity) continue;
|
|
542
|
-
let weapon = null;
|
|
543
|
-
if (isWeaponEntity(entity)) {
|
|
544
|
-
weapon = entity;
|
|
545
|
-
} else if (isItemEntity(entity) && typeof entity.base_item === "string") {
|
|
546
|
-
const baseSlug = entity.base_item;
|
|
547
|
-
const found = resolveBaseItem(baseSlug, registry);
|
|
548
|
-
if (found && found.entityType === "weapon" && isWeaponEntity(found.data)) {
|
|
549
|
-
weapon = found.data;
|
|
550
|
-
} else {
|
|
551
|
-
warnings.push(`Magic weapon ${entity.name} references missing base_item ${baseSlug}.`);
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
|
-
} else {
|
|
555
|
-
continue;
|
|
556
|
-
}
|
|
557
|
-
const slugFromEntry = (_a = unwrapSlug(entry.item)) != null ? _a : weapon.slug;
|
|
585
|
+
const rowFor = (index, entry, weapon, slotKey, versatileDice) => {
|
|
586
|
+
var _a2, _b2, _c, _d, _e;
|
|
587
|
+
const slugFromEntry = (_a2 = unwrapSlug(entry.item)) != null ? _a2 : weapon.slug;
|
|
558
588
|
const proficient = isWeaponSlugProficient(weapon, slugFromEntry, profs) || isWeaponSlugProficient(weapon, weapon.slug, profs);
|
|
559
589
|
if (!proficient) {
|
|
560
590
|
warnings.push(`Character not proficient with ${weapon.name}; proficiency bonus excluded.`);
|
|
561
591
|
}
|
|
562
592
|
const ability = attackAbility(weapon, mods, weaponAbilities);
|
|
563
|
-
const magic = magicBonusesForWeaponEntry(entry, registry, ctx);
|
|
564
|
-
const ovr = (
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
id: `${placed.index}:standard`,
|
|
569
|
-
name: displayName,
|
|
593
|
+
const magic = magicBonusesForWeaponEntry(entry, registry, ctx, index, infusions);
|
|
594
|
+
const ovr = (_b2 = entry.overrides) != null ? _b2 : {};
|
|
595
|
+
return buildAttackRow({
|
|
596
|
+
id: `${index}:standard`,
|
|
597
|
+
name: (_d = (_c = ovr.name) != null ? _c : magic.itemName) != null ? _d : weapon.name,
|
|
570
598
|
weapon,
|
|
571
599
|
baseDice: weapon.damage.dice,
|
|
572
600
|
ability,
|
|
@@ -574,13 +602,38 @@ function computeAttacks(equippedSlots, mods, profs, registry, warnings, proficie
|
|
|
574
602
|
proficient,
|
|
575
603
|
proficiencyBonus,
|
|
576
604
|
magic,
|
|
577
|
-
slotKey
|
|
578
|
-
actionCost: (_e = ovr.action) != null ? _e :
|
|
605
|
+
slotKey,
|
|
606
|
+
actionCost: (_e = ovr.action) != null ? _e : WEAPON_DEFAULT_ACTION_COST,
|
|
579
607
|
versatileDice,
|
|
580
608
|
weaponMasteries
|
|
581
609
|
});
|
|
582
|
-
|
|
610
|
+
};
|
|
611
|
+
const handedSlots = [
|
|
612
|
+
{ key: "mainhand", placed: equippedSlots.mainhand },
|
|
613
|
+
{ key: "offhand", placed: equippedSlots.offhand }
|
|
614
|
+
];
|
|
615
|
+
for (const { key, placed } of handedSlots) {
|
|
616
|
+
if (!placed) continue;
|
|
617
|
+
const { entity, entry } = placed;
|
|
618
|
+
if (!entity) continue;
|
|
619
|
+
const weapon = effectiveWeapon(entity, registry);
|
|
620
|
+
if (!weapon) {
|
|
621
|
+
if (isItemEntity(entity) && typeof entity.base_item === "string") {
|
|
622
|
+
warnings.push(`Magic weapon ${entity.name} references missing base_item ${entity.base_item}.`);
|
|
623
|
+
}
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
const versatileDice = key === "mainhand" && hasProperty(weapon, "versatile") && typeof weapon.damage.versatile_dice === "string" && !equippedSlots.offhand ? weapon.damage.versatile_dice : void 0;
|
|
627
|
+
rows.push(rowFor(placed.index, entry, weapon, key, versatileDice));
|
|
583
628
|
}
|
|
629
|
+
const handIndex = /* @__PURE__ */ new Set([(_a = equippedSlots.mainhand) == null ? void 0 : _a.index, (_b = equippedSlots.offhand) == null ? void 0 : _b.index]);
|
|
630
|
+
equipment.forEach((entry, index) => {
|
|
631
|
+
if (!entry.equipped || handIndex.has(index)) return;
|
|
632
|
+
const { entity } = resolveEntryEntity(entry, index, registry, infusions);
|
|
633
|
+
const weapon = effectiveWeapon(entity, registry);
|
|
634
|
+
if (!weapon) return;
|
|
635
|
+
rows.push(rowFor(index, entry, weapon));
|
|
636
|
+
});
|
|
584
637
|
return rows;
|
|
585
638
|
}
|
|
586
639
|
function coerceWeight(raw) {
|
|
@@ -593,25 +646,38 @@ function coerceWeight(raw) {
|
|
|
593
646
|
}
|
|
594
647
|
function computeCarriedWeight(resolved, registry) {
|
|
595
648
|
var _a;
|
|
649
|
+
const equipment = (_a = resolved.definition.equipment) != null ? _a : [];
|
|
650
|
+
const view = resolveContainment(equipment, registry);
|
|
651
|
+
const weightlessContainer = equipment.map((entry) => {
|
|
652
|
+
var _a2, _b, _c;
|
|
653
|
+
const data = (_a2 = resolveBaseItem(entry.item, registry)) == null ? void 0 : _a2.data;
|
|
654
|
+
return ((_c = (_b = data == null ? void 0 : data.container) == null ? void 0 : _b.capacity) == null ? void 0 : _c.weightless) === true;
|
|
655
|
+
});
|
|
656
|
+
const exempt = (i) => {
|
|
657
|
+
for (let p = view.parentOf[i]; p !== null; p = view.parentOf[p]) if (weightlessContainer[p]) return true;
|
|
658
|
+
return false;
|
|
659
|
+
};
|
|
596
660
|
let total = 0;
|
|
597
|
-
|
|
661
|
+
equipment.forEach((entry, i) => {
|
|
662
|
+
if (exempt(i)) return;
|
|
598
663
|
const found = resolveBaseItem(entry.item, registry);
|
|
599
|
-
if (!found)
|
|
664
|
+
if (!found) return;
|
|
600
665
|
const entity = found.data;
|
|
601
666
|
const w = coerceWeight(entity.weight);
|
|
602
|
-
if (w === 0)
|
|
667
|
+
if (w === 0) return;
|
|
603
668
|
const qty = typeof entry.qty === "number" && entry.qty >= 0 ? entry.qty : 1;
|
|
604
669
|
total += w * qty;
|
|
605
|
-
}
|
|
670
|
+
});
|
|
606
671
|
return total;
|
|
607
672
|
}
|
|
608
673
|
function computeSlotsAndAttacks(resolved, mods, profs, registry, warnings, proficiencyBonus, weaponAbilities = [], weaponMasteries = [], attunementFloor = 0) {
|
|
609
|
-
var _a, _b, _c;
|
|
674
|
+
var _a, _b, _c, _d, _e;
|
|
610
675
|
const equippedSlots = assignSlots(resolved, registry, warnings);
|
|
611
|
-
|
|
676
|
+
twoHandedShieldWarnings((_a = resolved.definition.equipment) != null ? _a : [], registry, warnings, resolved.infusions);
|
|
677
|
+
const overrides = (_b = resolved.definition.overrides) != null ? _b : {};
|
|
612
678
|
const acOut = computeAC(equippedSlots, resolved, mods, registry, warnings);
|
|
613
|
-
const ctx = buildConditionContext(resolved, equippedSlots);
|
|
614
|
-
const attacks = computeAttacks(equippedSlots, mods, profs, registry, warnings, proficiencyBonus, ctx, weaponMasteries, weaponAbilities);
|
|
679
|
+
const ctx = buildConditionContext(resolved, equippedSlots, registry);
|
|
680
|
+
const attacks = computeAttacks(equippedSlots, (_c = resolved.definition.equipment) != null ? _c : [], mods, profs, registry, warnings, proficiencyBonus, ctx, weaponMasteries, weaponAbilities, resolved.infusions);
|
|
615
681
|
return {
|
|
616
682
|
ac: acOut.ac,
|
|
617
683
|
acBreakdown: acOut.breakdown,
|
|
@@ -620,10 +686,10 @@ function computeSlotsAndAttacks(resolved, mods, profs, registry, warnings, profi
|
|
|
620
686
|
equippedSlots,
|
|
621
687
|
carriedWeight: computeCarriedWeight(resolved, registry),
|
|
622
688
|
// Attunement is persistent: an attuned item still occupies a slot even when unequipped (SRD).
|
|
623
|
-
attunementUsed: ((
|
|
689
|
+
attunementUsed: ((_d = resolved.definition.equipment) != null ? _d : []).filter((e) => e.attuned).length,
|
|
624
690
|
// PRECEDENCE: an explicit character override wins outright (a number the player typed is intent);
|
|
625
691
|
// otherwise the baseline 3 is raised — never lowered — by whatever features granted.
|
|
626
|
-
attunementLimit: (
|
|
692
|
+
attunementLimit: (_e = overrides.attunement_limit) != null ? _e : Math.max(3, attunementFloor)
|
|
627
693
|
};
|
|
628
694
|
}
|
|
629
695
|
|