@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/pc/pc.recalc.js
CHANGED
|
@@ -4,47 +4,88 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
collectChosenAbilityPoints,
|
|
6
6
|
collectChosenProficiencies
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import
|
|
7
|
+
} from "../chunk-XQCSGNXE.js";
|
|
8
|
+
import {
|
|
9
|
+
resourceLevelFor
|
|
10
|
+
} from "../chunk-UXPGW4TI.js";
|
|
9
11
|
import {
|
|
10
12
|
computeSpellLimits,
|
|
11
13
|
deriveSpellSlots,
|
|
14
|
+
effectiveSpellcastingAbility,
|
|
12
15
|
resolveSpellcasting
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-DPUJDOKV.js";
|
|
17
|
+
import "../chunk-O4SRD3J5.js";
|
|
18
|
+
import "../chunk-PP2UHLBA.js";
|
|
19
|
+
import {
|
|
20
|
+
diceColumnAt,
|
|
21
|
+
unarmedDieColumnFor
|
|
22
|
+
} from "../chunk-IUAAXXNO.js";
|
|
23
|
+
import "../chunk-YHYTW5QA.js";
|
|
24
|
+
import "../chunk-MI7P3NX3.js";
|
|
25
|
+
import "../chunk-PVCEA4HZ.js";
|
|
26
|
+
import {
|
|
27
|
+
toDefenseSlug
|
|
28
|
+
} from "../chunk-XJ2F2WO6.js";
|
|
16
29
|
import {
|
|
30
|
+
buildUnarmedRow,
|
|
17
31
|
computeAppliedBonuses,
|
|
18
32
|
computeSlotsAndAttacks,
|
|
19
33
|
emptyAppliedBonuses
|
|
20
|
-
} from "../chunk-
|
|
21
|
-
import "../chunk-
|
|
22
|
-
import "../chunk-
|
|
34
|
+
} from "../chunk-OSQFPGLM.js";
|
|
35
|
+
import "../chunk-UIRMA5KM.js";
|
|
36
|
+
import "../chunk-UBBKSYBY.js";
|
|
23
37
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
assembleEffectFeatures,
|
|
39
|
+
computeFeatureEffects,
|
|
40
|
+
foldsNow,
|
|
41
|
+
selfEffectsOf
|
|
42
|
+
} from "../chunk-JJ46T5XX.js";
|
|
43
|
+
import "../chunk-TOM66P2P.js";
|
|
44
|
+
import "../chunk-KU3YLF6D.js";
|
|
45
|
+
import "../chunk-RLGQ5PZZ.js";
|
|
26
46
|
import "../chunk-LWFTHJIE.js";
|
|
27
47
|
import "../chunk-DNAJRMNN.js";
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
48
|
+
import "../chunk-LVQLWRCU.js";
|
|
49
|
+
import "../chunk-WXWPK3LI.js";
|
|
50
|
+
import "../chunk-6X4KUDMU.js";
|
|
51
|
+
import "../chunk-YBLDE5CG.js";
|
|
52
|
+
import {
|
|
53
|
+
evaluateMaxFormula,
|
|
54
|
+
isValidMaxFormula
|
|
55
|
+
} from "../chunk-EVMUJYUD.js";
|
|
30
56
|
import "../chunk-VTTA2ALZ.js";
|
|
57
|
+
import "../chunk-OZP6JFGT.js";
|
|
58
|
+
import "../chunk-VQAXTIBW.js";
|
|
31
59
|
import {
|
|
32
60
|
abilityModifier,
|
|
33
61
|
attackBonus,
|
|
62
|
+
isCanonicalDamageType,
|
|
63
|
+
isChosenDamageType,
|
|
34
64
|
passive,
|
|
35
65
|
passivePerception,
|
|
36
66
|
proficiencyFromLevel,
|
|
37
67
|
saveDC,
|
|
38
68
|
savingThrow,
|
|
39
69
|
skillBonus
|
|
40
|
-
} from "../chunk-
|
|
70
|
+
} from "../chunk-PDJSUH24.js";
|
|
41
71
|
import {
|
|
42
72
|
ABILITY_KEYS,
|
|
43
73
|
ALL_SKILLS,
|
|
44
74
|
SKILL_ABILITY
|
|
45
|
-
} from "../chunk-
|
|
75
|
+
} from "../chunk-WELIKLZF.js";
|
|
76
|
+
import "../chunk-4U55VNC7.js";
|
|
77
|
+
import "../chunk-UA5KS2PL.js";
|
|
46
78
|
|
|
47
79
|
// src/pc/pc.recalc.ts
|
|
80
|
+
var WEAPON_CATEGORY_WORDS = /* @__PURE__ */ new Set([
|
|
81
|
+
"simple",
|
|
82
|
+
"martial",
|
|
83
|
+
"simple-melee",
|
|
84
|
+
"simple-ranged",
|
|
85
|
+
"martial-melee",
|
|
86
|
+
"martial-ranged",
|
|
87
|
+
"natural"
|
|
88
|
+
]);
|
|
48
89
|
function phbAverageForDie(hitDieStr) {
|
|
49
90
|
const n = parseDieSize(hitDieStr);
|
|
50
91
|
if (n == null) return 4;
|
|
@@ -86,7 +127,9 @@ function collectClassAsiBranch(resolved) {
|
|
|
86
127
|
const out = {};
|
|
87
128
|
for (const c of resolved.classes) {
|
|
88
129
|
for (const [, choice] of Object.entries(c.choices)) {
|
|
89
|
-
const
|
|
130
|
+
const block = choice;
|
|
131
|
+
if (typeof (block == null ? void 0 : block.feat) === "string") continue;
|
|
132
|
+
const asi = block == null ? void 0 : block.asi;
|
|
90
133
|
if (!asi) continue;
|
|
91
134
|
for (const ab of ABILITY_KEYS) {
|
|
92
135
|
const v = asi[ab];
|
|
@@ -96,8 +139,8 @@ function collectClassAsiBranch(resolved) {
|
|
|
96
139
|
}
|
|
97
140
|
return out;
|
|
98
141
|
}
|
|
99
|
-
function abilityBonusBreakdown(resolved) {
|
|
100
|
-
var _a, _b, _c, _d, _e, _f;
|
|
142
|
+
function abilityBonusBreakdown(resolved, featureEffects) {
|
|
143
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
101
144
|
const race = flattenRaceAsi(resolved.race);
|
|
102
145
|
const origin = collectChosenAbilityPoints(resolved);
|
|
103
146
|
const sub = subraceAsi(resolved);
|
|
@@ -114,7 +157,7 @@ function abilityBonusBreakdown(resolved) {
|
|
|
114
157
|
const bonus = (_d = f.ability_bonuses) == null ? void 0 : _d[ab];
|
|
115
158
|
if (typeof bonus === "number") feat += bonus;
|
|
116
159
|
}
|
|
117
|
-
out[ab] = { species, background: (_e = origin.background[ab]) != null ? _e : 0, class: (_f = classAsi[ab]) != null ? _f : 0, feat };
|
|
160
|
+
out[ab] = { species, background: (_e = origin.background[ab]) != null ? _e : 0, class: ((_f = classAsi[ab]) != null ? _f : 0) + ((_g = featureEffects == null ? void 0 : featureEffects.ability_bonus[ab]) != null ? _g : 0), feat };
|
|
118
161
|
}
|
|
119
162
|
return out;
|
|
120
163
|
}
|
|
@@ -149,65 +192,123 @@ function hpLevelCount(classes) {
|
|
|
149
192
|
function multiclassMaxHP(classes, conMod) {
|
|
150
193
|
return Math.max(1, hitDiceAverageSum(classes) + conMod * hpLevelCount(classes));
|
|
151
194
|
}
|
|
195
|
+
function resolveRiderAmount(amount, bindings) {
|
|
196
|
+
if (!amount.includes("{")) return amount;
|
|
197
|
+
const formula = amount.replace(/\{prof_bonus\}/g, "{prof}");
|
|
198
|
+
if (!isValidMaxFormula(formula)) return amount;
|
|
199
|
+
return String(evaluateMaxFormula(formula, bindings));
|
|
200
|
+
}
|
|
201
|
+
function resolveDamageRider(rider, rowDamageType, bindings) {
|
|
202
|
+
const out = { ...rider, amount: resolveRiderAmount(rider.amount, bindings) };
|
|
203
|
+
if (rider.damage_type !== void 0 && !isChosenDamageType(rider.damage_type)) {
|
|
204
|
+
const resolved = isCanonicalDamageType(rider.damage_type) ? rider.damage_type : rowDamageType;
|
|
205
|
+
if (resolved) out.damage_type = resolved;
|
|
206
|
+
else delete out.damage_type;
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
152
210
|
function unarmoredAC(resolved, mods, warnings) {
|
|
153
211
|
return unarmoredACBreakdown(resolved, mods, warnings).total;
|
|
154
212
|
}
|
|
155
|
-
function unarmoredACBreakdown(resolved, mods, warnings) {
|
|
156
|
-
var _a, _b, _c, _d, _e
|
|
213
|
+
function unarmoredACBreakdown(resolved, mods, warnings, shieldBonus = 0) {
|
|
214
|
+
var _a, _b, _c, _d, _e;
|
|
157
215
|
const baseTerms = [
|
|
158
216
|
{ source: "Unarmored", amount: 10, kind: "unarmored" },
|
|
159
217
|
{ source: "DEX modifier", amount: mods.dex, kind: "dex" }
|
|
160
218
|
];
|
|
219
|
+
const { activeBuffs } = assembleEffectFeatures(resolved);
|
|
220
|
+
const candidates = [
|
|
221
|
+
{ total: 10 + mods.dex, terms: baseTerms, shieldAllowed: true }
|
|
222
|
+
];
|
|
161
223
|
for (const rf of resolved.features) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
];
|
|
169
|
-
let total = base + mods.dex;
|
|
224
|
+
if (!foldsNow(rf, activeBuffs)) continue;
|
|
225
|
+
for (const eff of selfEffectsOf(rf.feature)) {
|
|
226
|
+
if (eff.kind !== "unarmored-ac") continue;
|
|
227
|
+
const base = (_a = eff.base) != null ? _a : 10;
|
|
228
|
+
const terms = [{ source: "Unarmored", amount: base, kind: "unarmored" }];
|
|
229
|
+
let total = base;
|
|
170
230
|
for (const ab of eff.abilities) {
|
|
171
|
-
|
|
172
|
-
terms.push({ source: `${ab.toUpperCase()} modifier (${(_c = rf.feature.name) != null ? _c : "Unarmored"})`, amount: mods[ab], kind: "ability" });
|
|
231
|
+
terms.push(ab === "dex" ? { source: "DEX modifier", amount: mods.dex, kind: "dex" } : { source: `${ab.toUpperCase()} modifier (${(_b = rf.feature.name) != null ? _b : "Unarmored"})`, amount: mods[ab], kind: "ability" });
|
|
173
232
|
total += mods[ab];
|
|
174
233
|
}
|
|
175
|
-
|
|
234
|
+
candidates.push({ total, terms, shieldAllowed: eff.allow_shield === true });
|
|
176
235
|
}
|
|
177
236
|
}
|
|
237
|
+
if (candidates.length > 1) {
|
|
238
|
+
const applied = (c) => c.total + (c.shieldAllowed ? shieldBonus : 0);
|
|
239
|
+
let best = candidates[0];
|
|
240
|
+
for (const c of candidates) if (applied(c) > applied(best)) best = c;
|
|
241
|
+
return best;
|
|
242
|
+
}
|
|
178
243
|
for (const rf of resolved.features) {
|
|
179
244
|
const feat = rf.feature;
|
|
180
|
-
if ((
|
|
245
|
+
if ((_c = feat.unarmored_defense) == null ? void 0 : _c.ability) {
|
|
181
246
|
const ab = feat.unarmored_defense.ability;
|
|
182
|
-
const amt = (
|
|
247
|
+
const amt = (_d = mods[ab]) != null ? _d : 0;
|
|
183
248
|
const terms = [
|
|
184
249
|
...baseTerms,
|
|
185
250
|
{ source: `${ab.toUpperCase()} modifier (Unarmored Defense)`, amount: amt, kind: "ability" }
|
|
186
251
|
];
|
|
187
|
-
return { total: 10 + mods.dex + amt, terms };
|
|
252
|
+
return { total: 10 + mods.dex + amt, terms, shieldAllowed: true };
|
|
188
253
|
}
|
|
189
254
|
}
|
|
190
255
|
for (const rf of resolved.features) {
|
|
191
|
-
const name = ((
|
|
256
|
+
const name = ((_e = rf.feature.name) != null ? _e : "").toLowerCase();
|
|
192
257
|
if (!/unarmored\s*defense/.test(name)) continue;
|
|
193
258
|
if (rf.source.kind === "class" && rf.source.slug.includes("monk")) {
|
|
194
|
-
warnings.push(`Unarmored Defense detected by name on ${rf.source.slug}; populate unarmored_defense:{ability:wis} flag for accuracy.`);
|
|
195
259
|
const terms = [
|
|
196
260
|
...baseTerms,
|
|
197
261
|
{ source: "WIS modifier (Unarmored Defense)", amount: mods.wis, kind: "ability" }
|
|
198
262
|
];
|
|
199
|
-
return { total: 10 + mods.dex + mods.wis, terms };
|
|
263
|
+
return { total: 10 + mods.dex + mods.wis, terms, shieldAllowed: true };
|
|
200
264
|
}
|
|
201
265
|
if (rf.source.kind === "class" && rf.source.slug.includes("barbarian")) {
|
|
202
|
-
warnings.push(`Unarmored Defense detected by name on ${rf.source.slug}; populate unarmored_defense:{ability:con} flag for accuracy.`);
|
|
203
266
|
const terms = [
|
|
204
267
|
...baseTerms,
|
|
205
268
|
{ source: "CON modifier (Unarmored Defense)", amount: mods.con, kind: "ability" }
|
|
206
269
|
];
|
|
207
|
-
return { total: 10 + mods.dex + mods.con, terms };
|
|
270
|
+
return { total: 10 + mods.dex + mods.con, terms, shieldAllowed: true };
|
|
208
271
|
}
|
|
209
272
|
}
|
|
210
|
-
return { total: 10 + mods.dex, terms: baseTerms };
|
|
273
|
+
return { total: 10 + mods.dex, terms: baseTerms, shieldAllowed: true };
|
|
274
|
+
}
|
|
275
|
+
function resolveUnarmedStrike(resolved) {
|
|
276
|
+
var _a, _b, _c;
|
|
277
|
+
const dice = [];
|
|
278
|
+
const abilities = /* @__PURE__ */ new Set();
|
|
279
|
+
const classOf = (rf) => rf.source.kind === "class" ? resolved.classes.find((c) => {
|
|
280
|
+
var _a2;
|
|
281
|
+
return ((_a2 = c.entity) == null ? void 0 : _a2.slug) === rf.source.slug;
|
|
282
|
+
}) : void 0;
|
|
283
|
+
const readDie = (rf, d) => {
|
|
284
|
+
var _a2, _b2;
|
|
285
|
+
if (typeof d === "string") return d;
|
|
286
|
+
if (!d) return void 0;
|
|
287
|
+
const cls = classOf(rf);
|
|
288
|
+
return cls ? (_b2 = diceColumnAt((_a2 = cls.entity) == null ? void 0 : _a2.table, cls.level, d.column)) != null ? _b2 : void 0 : void 0;
|
|
289
|
+
};
|
|
290
|
+
for (const rf of resolved.features) {
|
|
291
|
+
const authored = selfEffectsOf(rf.feature).filter((e) => e.kind === "unarmed-strike");
|
|
292
|
+
for (const e of authored) {
|
|
293
|
+
const d2 = readDie(rf, e.dice);
|
|
294
|
+
if (d2) dice.push(d2);
|
|
295
|
+
for (const ab of (_a = e.abilities) != null ? _a : []) abilities.add(ab);
|
|
296
|
+
}
|
|
297
|
+
if (authored.length || rf.source.kind !== "class") continue;
|
|
298
|
+
const slug = ((_c = (_b = rf.feature.id) != null ? _b : rf.feature.name) != null ? _c : "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
299
|
+
const column = unarmedDieColumnFor(slug);
|
|
300
|
+
if (!column) continue;
|
|
301
|
+
const d = readDie(rf, { column });
|
|
302
|
+
if (!d) continue;
|
|
303
|
+
dice.push(d);
|
|
304
|
+
abilities.add("dex");
|
|
305
|
+
}
|
|
306
|
+
const avg = (d) => {
|
|
307
|
+
const m = /^(\d+)d(\d+)$/i.exec(d);
|
|
308
|
+
return m ? Number(m[1]) * (Number(m[2]) + 1) / 2 : 1;
|
|
309
|
+
};
|
|
310
|
+
const best = dice.sort((a, b) => avg(b) - avg(a))[0];
|
|
311
|
+
return { ...best ? { dice: best } : {}, ...abilities.size ? { abilities: [...abilities] } : {} };
|
|
211
312
|
}
|
|
212
313
|
function initiativeBonus(dexMod, feats, edition) {
|
|
213
314
|
let bonus = dexMod;
|
|
@@ -308,28 +409,67 @@ function computeAbilityScores(resolved, overrides) {
|
|
|
308
409
|
}
|
|
309
410
|
return out;
|
|
310
411
|
}
|
|
311
|
-
function
|
|
412
|
+
function normalizeArmorProf(input) {
|
|
312
413
|
var _a, _b;
|
|
313
414
|
if (!input) return { categories: [], specific: [] };
|
|
314
|
-
if (Array.isArray(input)) return { categories:
|
|
415
|
+
if (Array.isArray(input)) return { categories: input, specific: [] };
|
|
315
416
|
return { categories: (_a = input.categories) != null ? _a : [], specific: (_b = input.specific) != null ? _b : [] };
|
|
316
417
|
}
|
|
418
|
+
function normalizeWeaponToolProf(input) {
|
|
419
|
+
var _a, _b, _c;
|
|
420
|
+
if (!input) return { categories: [], specific: [] };
|
|
421
|
+
if (Array.isArray(input)) return { categories: [], specific: input };
|
|
422
|
+
return { categories: (_a = input.categories) != null ? _a : [], specific: ((_b = input.fixed) != null ? _b : []).concat((_c = input.specific) != null ? _c : []) };
|
|
423
|
+
}
|
|
317
424
|
function mergeInto(target, source) {
|
|
318
425
|
for (const c of source.categories) if (!target.categories.includes(c)) target.categories.push(c);
|
|
319
426
|
for (const s of source.specific) if (!target.specific.includes(s)) target.specific.push(s);
|
|
320
427
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
428
|
+
var ORIGIN_RANK = { manual: 0, equipment: 1, grant: 2 };
|
|
429
|
+
function composeDefenseEntries(manual, equipment, grants) {
|
|
430
|
+
var _a;
|
|
431
|
+
const byValue = /* @__PURE__ */ new Map();
|
|
432
|
+
const consider = (list, origin) => {
|
|
433
|
+
for (const raw of list) {
|
|
434
|
+
const value = toDefenseSlug(raw);
|
|
435
|
+
if (!value) continue;
|
|
436
|
+
const existing = byValue.get(value);
|
|
437
|
+
if (!existing) {
|
|
438
|
+
byValue.set(value, { value, label: raw.trim(), origin });
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (ORIGIN_RANK[origin] > ORIGIN_RANK[existing.origin]) existing.origin = origin;
|
|
330
442
|
}
|
|
443
|
+
};
|
|
444
|
+
consider(manual, "manual");
|
|
445
|
+
consider(equipment, "equipment");
|
|
446
|
+
for (const g of grants) {
|
|
447
|
+
const value = toDefenseSlug(g.value);
|
|
448
|
+
if (!value) continue;
|
|
449
|
+
const existing = byValue.get(value);
|
|
450
|
+
if (!existing) {
|
|
451
|
+
byValue.set(value, {
|
|
452
|
+
value,
|
|
453
|
+
label: g.value.trim(),
|
|
454
|
+
origin: "grant",
|
|
455
|
+
sources: [...g.sources],
|
|
456
|
+
...g.condition ? { condition: g.condition } : {}
|
|
457
|
+
});
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
if (ORIGIN_RANK.grant > ORIGIN_RANK[existing.origin]) existing.origin = "grant";
|
|
461
|
+
const sources = (_a = existing.sources) != null ? _a : existing.sources = [];
|
|
462
|
+
for (const src of g.sources) if (!sources.includes(src)) sources.push(src);
|
|
463
|
+
if (!existing.condition && g.condition) existing.condition = g.condition;
|
|
331
464
|
}
|
|
332
|
-
return
|
|
465
|
+
return [...byValue.values()];
|
|
466
|
+
}
|
|
467
|
+
function suppress(resolved, bucket, entries) {
|
|
468
|
+
var _a, _b, _c, _d, _e;
|
|
469
|
+
const suppressed = new Set(
|
|
470
|
+
((_e = (_d = (_c = (_b = (_a = resolved.definition) == null ? void 0 : _a.overrides) == null ? void 0 : _b.defenses) == null ? void 0 : _c[bucket]) == null ? void 0 : _d.remove) != null ? _e : []).map(toDefenseSlug)
|
|
471
|
+
);
|
|
472
|
+
return entries.filter((e) => !suppressed.has(e.value));
|
|
333
473
|
}
|
|
334
474
|
function computeProficiencies(resolved) {
|
|
335
475
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
@@ -340,31 +480,31 @@ function computeProficiencies(resolved) {
|
|
|
340
480
|
for (const c of resolved.classes) {
|
|
341
481
|
const p = (_a = c.entity) == null ? void 0 : _a.proficiencies;
|
|
342
482
|
if (!p) continue;
|
|
343
|
-
mergeInto(armor,
|
|
344
|
-
mergeInto(weapons,
|
|
345
|
-
mergeInto(tools,
|
|
483
|
+
mergeInto(armor, normalizeArmorProf(p.armor));
|
|
484
|
+
mergeInto(weapons, normalizeWeaponToolProf(p.weapons));
|
|
485
|
+
mergeInto(tools, normalizeWeaponToolProf(p.tools));
|
|
346
486
|
(_b = p.languages) == null ? void 0 : _b.forEach((l) => languages.add(l));
|
|
347
487
|
}
|
|
348
488
|
const racePr = (_c = resolved.race) == null ? void 0 : _c.proficiencies;
|
|
349
489
|
if (racePr) {
|
|
350
|
-
mergeInto(armor,
|
|
351
|
-
mergeInto(weapons,
|
|
352
|
-
mergeInto(tools,
|
|
490
|
+
mergeInto(armor, normalizeArmorProf(racePr.armor));
|
|
491
|
+
mergeInto(weapons, normalizeWeaponToolProf(racePr.weapons));
|
|
492
|
+
mergeInto(tools, normalizeWeaponToolProf(racePr.tools));
|
|
353
493
|
(_d = racePr.languages) == null ? void 0 : _d.forEach((l) => languages.add(l));
|
|
354
494
|
}
|
|
355
495
|
const bgPr = (_e = resolved.background) == null ? void 0 : _e.proficiencies;
|
|
356
496
|
if (bgPr) {
|
|
357
|
-
mergeInto(armor,
|
|
358
|
-
mergeInto(weapons,
|
|
359
|
-
mergeInto(tools,
|
|
497
|
+
mergeInto(armor, normalizeArmorProf(bgPr.armor));
|
|
498
|
+
mergeInto(weapons, normalizeWeaponToolProf(bgPr.weapons));
|
|
499
|
+
mergeInto(tools, normalizeWeaponToolProf(bgPr.tools));
|
|
360
500
|
(_f = bgPr.languages) == null ? void 0 : _f.forEach((l) => languages.add(l));
|
|
361
501
|
}
|
|
362
502
|
for (const f of resolved.feats) {
|
|
363
503
|
const grants = f.grants_proficiency;
|
|
364
504
|
if (!grants) continue;
|
|
365
|
-
mergeInto(armor,
|
|
366
|
-
mergeInto(weapons,
|
|
367
|
-
mergeInto(tools,
|
|
505
|
+
mergeInto(armor, normalizeArmorProf(grants.armor));
|
|
506
|
+
mergeInto(weapons, normalizeWeaponToolProf(grants.weapons));
|
|
507
|
+
mergeInto(tools, normalizeWeaponToolProf(grants.tools));
|
|
368
508
|
(_g = grants.languages) == null ? void 0 : _g.forEach((l) => languages.add(l));
|
|
369
509
|
}
|
|
370
510
|
return {
|
|
@@ -376,28 +516,12 @@ function computeProficiencies(resolved) {
|
|
|
376
516
|
};
|
|
377
517
|
}
|
|
378
518
|
function recalc(resolved, registry) {
|
|
379
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V
|
|
519
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V;
|
|
380
520
|
const warnings = [];
|
|
381
521
|
const overrides = (_a = resolved.definition.overrides) != null ? _a : {};
|
|
382
522
|
const chosenProfs = collectChosenProficiencies(resolved);
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
const pushBoon = (item, pool) => {
|
|
386
|
-
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
387
|
-
const e = item.entity;
|
|
388
|
-
if (!e || ((_b2 = (_a2 = e.effects) == null ? void 0 : _a2.length) != null ? _b2 : 0) === 0) return;
|
|
389
|
-
buffFeatures.push({
|
|
390
|
-
feature: { id: item.slug, name: e.name, activatable: (_c2 = e.activatable) != null ? _c2 : false, effects: e.effects },
|
|
391
|
-
// source is inert for the fold; attribute to the pool's owning class
|
|
392
|
-
// (never a hardcoded class) so the generic engine carries no homebrew name.
|
|
393
|
-
source: { kind: "class", slug: (_f2 = (_e2 = (_d2 = resolved.classes[pool.classIndex]) == null ? void 0 : _d2.entity) == null ? void 0 : _e2.slug) != null ? _f2 : pool.id, level: pool.anchorLevel }
|
|
394
|
-
});
|
|
395
|
-
};
|
|
396
|
-
for (const pool of (_c = resolved.pools) != null ? _c : []) {
|
|
397
|
-
for (const sel of (_d = pool.selected) != null ? _d : []) pushBoon(sel, pool);
|
|
398
|
-
for (const g of (_e = pool.grants) != null ? _e : []) pushBoon(g, pool);
|
|
399
|
-
}
|
|
400
|
-
const featureEffects = computeFeatureEffects([...resolved.features, ...buffFeatures], { activeBuffs });
|
|
523
|
+
const { features: effectFeatures, activeBuffs } = assembleEffectFeatures(resolved);
|
|
524
|
+
const featureEffects = computeFeatureEffects(effectFeatures, { activeBuffs, levelFor: (src) => resourceLevelFor(src, resolved) });
|
|
401
525
|
const profsForApply = computeProficiencies(resolved);
|
|
402
526
|
for (const t of chosenProfs.tools) {
|
|
403
527
|
if (!profsForApply.tools.specific.includes(t)) profsForApply.tools.specific.push(t);
|
|
@@ -405,6 +529,9 @@ function recalc(resolved, registry) {
|
|
|
405
529
|
for (const l of chosenProfs.languages) {
|
|
406
530
|
if (!profsForApply.languages.includes(l)) profsForApply.languages.push(l);
|
|
407
531
|
}
|
|
532
|
+
for (const w of chosenProfs.weapons) {
|
|
533
|
+
if (!profsForApply.weapons.specific.includes(w)) profsForApply.weapons.specific.push(w);
|
|
534
|
+
}
|
|
408
535
|
for (const t of featureEffects.proficiencies.tools) {
|
|
409
536
|
if (!profsForApply.tools.specific.includes(t)) profsForApply.tools.specific.push(t);
|
|
410
537
|
}
|
|
@@ -416,6 +543,9 @@ function recalc(resolved, registry) {
|
|
|
416
543
|
}
|
|
417
544
|
for (const w of featureEffects.proficiencies.weapons) {
|
|
418
545
|
if (!profsForApply.weapons.categories.includes(w)) profsForApply.weapons.categories.push(w);
|
|
546
|
+
if (!WEAPON_CATEGORY_WORDS.has(w) && !profsForApply.weapons.specific.includes(w)) {
|
|
547
|
+
profsForApply.weapons.specific.push(w);
|
|
548
|
+
}
|
|
419
549
|
}
|
|
420
550
|
profsForApply.languages.sort();
|
|
421
551
|
const applied = registry ? computeAppliedBonuses(resolved, profsForApply, registry, warnings) : emptyAppliedBonuses();
|
|
@@ -432,7 +562,7 @@ function recalc(resolved, registry) {
|
|
|
432
562
|
const scores = { ...baseScores };
|
|
433
563
|
for (const ab of ABILITY_KEYS) {
|
|
434
564
|
const bonus = applied.ability_bonuses[ab];
|
|
435
|
-
|
|
565
|
+
scores[ab] += (typeof bonus === "number" ? bonus : 0) + ((_b = featureEffects.ability_bonus[ab]) != null ? _b : 0);
|
|
436
566
|
}
|
|
437
567
|
for (const ab of ABILITY_KEYS) {
|
|
438
568
|
const stat = applied.ability_statics[ab];
|
|
@@ -459,31 +589,32 @@ function recalc(resolved, registry) {
|
|
|
459
589
|
resolved.definition.edition,
|
|
460
590
|
scores
|
|
461
591
|
);
|
|
462
|
-
const firstClass = (
|
|
463
|
-
const saveProfs = new Set((
|
|
592
|
+
const firstClass = (_d = (_c = resolved.classes[0]) == null ? void 0 : _c.entity) != null ? _d : null;
|
|
593
|
+
const saveProfs = new Set((_e = firstClass == null ? void 0 : firstClass.saving_throws) != null ? _e : []);
|
|
464
594
|
for (const ab of featureEffects.proficiencies.saves) saveProfs.add(ab);
|
|
595
|
+
for (const ab of chosenProfs.saves) saveProfs.add(ab);
|
|
465
596
|
const saves = {};
|
|
466
597
|
for (const ab of ABILITY_KEYS) {
|
|
467
|
-
const override = (
|
|
468
|
-
const prof = (
|
|
598
|
+
const override = (_f = overrides.saves) == null ? void 0 : _f[ab];
|
|
599
|
+
const prof = (_g = override == null ? void 0 : override.proficient) != null ? _g : saveProfs.has(ab);
|
|
469
600
|
const derivedBonus = savingThrow(scores[ab], prof, proficiencyBonus) + applied.save_bonus + conditionEffects.d20_test_penalty;
|
|
470
|
-
const bonus = (
|
|
601
|
+
const bonus = (_h = override == null ? void 0 : override.bonus) != null ? _h : derivedBonus;
|
|
471
602
|
saves[ab] = { bonus, proficient: prof };
|
|
472
603
|
}
|
|
473
604
|
const profSet = /* @__PURE__ */ new Set([
|
|
474
605
|
...resolved.definition.skills.proficient,
|
|
475
|
-
...(
|
|
606
|
+
...(_j = (_i = resolved.background) == null ? void 0 : _i.skill_proficiencies) != null ? _j : [],
|
|
476
607
|
...chosenProfs.skills,
|
|
477
608
|
...featureEffects.proficiencies.skills
|
|
478
609
|
]);
|
|
479
|
-
const expSet = /* @__PURE__ */ new Set([...resolved.definition.skills.expertise, ...chosenProfs.expertise]);
|
|
610
|
+
const expSet = /* @__PURE__ */ new Set([...resolved.definition.skills.expertise, ...chosenProfs.expertise, ...featureEffects.proficiencies.skillExpertise]);
|
|
480
611
|
const skills = {};
|
|
481
612
|
for (const skill of ALL_SKILLS) {
|
|
482
613
|
const skillKey = skillSlugFromDisplay(skill);
|
|
483
614
|
const ab = SKILL_ABILITY[skillSlugToAbilityLookup(skillKey)];
|
|
484
|
-
const override = (
|
|
485
|
-
const tri = (
|
|
486
|
-
const bonus = (
|
|
615
|
+
const override = (_k = overrides.skills) == null ? void 0 : _k[skillKey];
|
|
616
|
+
const tri = (_l = override == null ? void 0 : override.proficiency) != null ? _l : expSet.has(skillKey) ? "expertise" : profSet.has(skillKey) ? "proficient" : "none";
|
|
617
|
+
const bonus = (_m = override == null ? void 0 : override.bonus) != null ? _m : skillBonus(scores[ab], tri, proficiencyBonus) + conditionEffects.d20_test_penalty;
|
|
487
618
|
skills[skillKey] = {
|
|
488
619
|
bonus,
|
|
489
620
|
proficiency: tri,
|
|
@@ -494,12 +625,12 @@ function recalc(resolved, registry) {
|
|
|
494
625
|
const investigationTri = skills.investigation.proficiency;
|
|
495
626
|
const insightTri = skills.insight.proficiency;
|
|
496
627
|
const passives = {
|
|
497
|
-
perception: (
|
|
498
|
-
investigation: (
|
|
499
|
-
insight: (
|
|
628
|
+
perception: (_o = (_n = overrides.passives) == null ? void 0 : _n.perception) != null ? _o : passivePerception(scores.wis, perceptionTri, proficiencyBonus),
|
|
629
|
+
investigation: (_q = (_p = overrides.passives) == null ? void 0 : _p.investigation) != null ? _q : passive(scores.int, investigationTri, proficiencyBonus),
|
|
630
|
+
insight: (_s = (_r = overrides.passives) == null ? void 0 : _r.insight) != null ? _s : passive(scores.wis, insightTri, proficiencyBonus)
|
|
500
631
|
};
|
|
501
|
-
const hpRolled = (
|
|
502
|
-
const hpModifier = (
|
|
632
|
+
const hpRolled = (_u = (_t = overrides.hp) == null ? void 0 : _t.rolled) != null ? _u : null;
|
|
633
|
+
const hpModifier = (_w = (_v = overrides.hp) == null ? void 0 : _v.modifier) != null ? _w : null;
|
|
503
634
|
const averageDiceSum = hitDiceAverageSum(resolved.classes);
|
|
504
635
|
const conLevels = hpLevelCount(resolved.classes);
|
|
505
636
|
const diceSum = hpRolled != null ? hpRolled : averageDiceSum;
|
|
@@ -507,7 +638,7 @@ function recalc(resolved, registry) {
|
|
|
507
638
|
const diceConClamped = Math.max(1, diceConRaw);
|
|
508
639
|
const hpMaxDerived = diceConClamped + featureEffects.hp_per_level_bonus * totalLevel + (hpModifier != null ? hpModifier : 0);
|
|
509
640
|
const hpMaxAfterConditions = Math.max(0, Math.floor(hpMaxDerived * conditionEffects.hp_max_multiplier));
|
|
510
|
-
const hpMax = (
|
|
641
|
+
const hpMax = (_y = (_x = overrides.hp) == null ? void 0 : _x.max) != null ? _y : hpMaxAfterConditions;
|
|
511
642
|
const hpBreakdown = {
|
|
512
643
|
diceSum,
|
|
513
644
|
diceSource: hpRolled != null ? "rolled" : "average",
|
|
@@ -525,23 +656,20 @@ function recalc(resolved, registry) {
|
|
|
525
656
|
exhaustionMultiplier: conditionEffects.hp_max_multiplier,
|
|
526
657
|
exhaustionLevel: conditionEffects.exhaustion_level,
|
|
527
658
|
derivedMax: hpMaxAfterConditions,
|
|
528
|
-
override: (
|
|
659
|
+
override: (_A = (_z = overrides.hp) == null ? void 0 : _z.max) != null ? _A : null,
|
|
529
660
|
final: hpMax
|
|
530
661
|
};
|
|
531
|
-
const featureAcTermsFor = (hasArmor) => featureEffects.ac_terms.filter((t) => !t.requires_armor || hasArmor).map((t) => ({ source: t.label, amount: t.value, kind: "feature" }));
|
|
662
|
+
const featureAcTermsFor = (hasArmor) => featureEffects.ac_terms.filter((t) => !t.requires_armor || hasArmor).map((t) => ({ source: t.label, amount: t.value, kind: "feature", condition: t.condition }));
|
|
532
663
|
const sumTerms = (terms) => terms.reduce((s, t) => s + t.amount, 0);
|
|
533
664
|
const weaponAbilities = [...featureEffects.weaponAbilities];
|
|
534
|
-
const wantsSpellcasting = resolved.features.some((rf) =>
|
|
535
|
-
var _a2;
|
|
536
|
-
return ((_a2 = rf.feature.effects) != null ? _a2 : []).some((e) => e.kind === "weapon-ability" && e.ability === "spellcasting");
|
|
537
|
-
});
|
|
665
|
+
const wantsSpellcasting = resolved.features.some((rf) => selfEffectsOf(rf.feature).some((e) => e.kind === "weapon-ability" && e.ability === "spellcasting"));
|
|
538
666
|
if (wantsSpellcasting) {
|
|
539
667
|
let primaryCasterAbility = null;
|
|
540
668
|
for (const c of resolved.classes) {
|
|
541
669
|
if (!c.entity) continue;
|
|
542
670
|
const profile = resolveSpellcasting(c);
|
|
543
671
|
if (profile) {
|
|
544
|
-
primaryCasterAbility = profile.ability;
|
|
672
|
+
primaryCasterAbility = effectiveSpellcastingAbility(c.entity.slug, profile.ability, overrides);
|
|
545
673
|
break;
|
|
546
674
|
}
|
|
547
675
|
}
|
|
@@ -552,16 +680,17 @@ function recalc(resolved, registry) {
|
|
|
552
680
|
let acBreakdownDerived = [];
|
|
553
681
|
let acInformationalDerived = [];
|
|
554
682
|
if (registry) {
|
|
555
|
-
derivedEquipment = computeSlotsAndAttacks(resolved, mods, profsForApply, registry, warnings, proficiencyBonus, weaponAbilities, (
|
|
683
|
+
derivedEquipment = computeSlotsAndAttacks(resolved, mods, profsForApply, registry, warnings, proficiencyBonus, weaponAbilities, (_B = resolved.weaponMasteries) != null ? _B : []);
|
|
556
684
|
if (derivedEquipment.equippedSlots.armor) {
|
|
557
685
|
const featTerms = featureAcTermsFor(true);
|
|
558
686
|
acDerived = derivedEquipment.ac + sumTerms(featTerms);
|
|
559
687
|
acBreakdownDerived = [...derivedEquipment.acBreakdown, ...featTerms];
|
|
560
688
|
acInformationalDerived = derivedEquipment.acInformational;
|
|
561
689
|
} else {
|
|
562
|
-
const
|
|
690
|
+
const shieldBonus = derivedEquipment.acBreakdown.filter((b) => b.kind === "shield").reduce((sum, b) => sum + b.amount, 0);
|
|
691
|
+
const { total: unarmored, terms: unarmoredTerms, shieldAllowed } = unarmoredACBreakdown(resolved, mods, warnings, shieldBonus);
|
|
563
692
|
const additive = derivedEquipment.acBreakdown.filter(
|
|
564
|
-
(b) => b.kind === "item" || b.kind === "override" || b.kind === "shield"
|
|
693
|
+
(b) => b.kind === "item" || b.kind === "override" || b.kind === "shield" && shieldAllowed
|
|
565
694
|
);
|
|
566
695
|
const featTerms = featureAcTermsFor(false);
|
|
567
696
|
const additiveSum = additive.reduce((sum, b) => sum + b.amount, 0);
|
|
@@ -575,16 +704,16 @@ function recalc(resolved, registry) {
|
|
|
575
704
|
acDerived = total + sumTerms(featTerms);
|
|
576
705
|
acBreakdownDerived = [...terms, ...featTerms];
|
|
577
706
|
}
|
|
578
|
-
const ac = (
|
|
707
|
+
const ac = (_C = overrides.ac) != null ? _C : acDerived;
|
|
579
708
|
const additiveSpeed = speedFromRace(resolved) + applied.speed_bonuses.walk + featureEffects.speed_walk_bonus;
|
|
580
709
|
const baseSpeed = Math.max(featureEffects.speed_walk_set, additiveSpeed);
|
|
581
710
|
const adjustedSpeed = baseSpeed * conditionEffects.speed_multiplier - conditionEffects.speed_reduction_ft;
|
|
582
711
|
const conditionSpeed = conditionEffects.speed_floor_zero ? 0 : Math.max(0, Math.floor(adjustedSpeed));
|
|
583
|
-
const speed = (
|
|
712
|
+
const speed = (_D = overrides.speed) != null ? _D : conditionSpeed;
|
|
584
713
|
if (!resolved.race) warnings.push("No race resolved; speed defaulted to 30.");
|
|
585
|
-
const init = (
|
|
714
|
+
const init = (_E = overrides.initiative) != null ? _E : initiativeBonus(mods.dex, resolved.feats, resolved.definition.edition) + featureEffects.initiative_bonus;
|
|
586
715
|
const senses = {
|
|
587
|
-
darkvision: Math.max((
|
|
716
|
+
darkvision: Math.max((_H = (_G = (_F = resolved.race) == null ? void 0 : _F.vision) == null ? void 0 : _G.darkvision) != null ? _H : 0, featureEffects.senses.darkvision, applied.senses.darkvision),
|
|
588
717
|
blindsight: Math.max(featureEffects.senses.blindsight, applied.senses.blindsight),
|
|
589
718
|
tremorsense: Math.max(featureEffects.senses.tremorsense, applied.senses.tremorsense),
|
|
590
719
|
truesight: Math.max(featureEffects.senses.truesight, applied.senses.truesight)
|
|
@@ -596,19 +725,22 @@ function recalc(resolved, registry) {
|
|
|
596
725
|
if (!c.entity) continue;
|
|
597
726
|
const profile = resolveSpellcasting(c);
|
|
598
727
|
if (!profile) continue;
|
|
599
|
-
const
|
|
600
|
-
const
|
|
728
|
+
const ab = effectiveSpellcastingAbility(c.entity.slug, profile.ability, overrides);
|
|
729
|
+
const dc = saveDC(scores[ab], proficiencyBonus) + applied.spell_save_dc;
|
|
730
|
+
const atk = attackBonus(scores[ab], proficiencyBonus) + applied.spell_attack;
|
|
601
731
|
spellcastingClasses.push({
|
|
602
732
|
classSlug: c.entity.slug,
|
|
603
733
|
className: c.entity.name,
|
|
604
|
-
ability:
|
|
605
|
-
|
|
606
|
-
|
|
734
|
+
ability: ab,
|
|
735
|
+
defaultAbility: profile.ability,
|
|
736
|
+
saveDC: dc,
|
|
737
|
+
attackBonus: atk,
|
|
607
738
|
casterType: profile.casterType,
|
|
608
|
-
preparation: profile.preparation
|
|
739
|
+
preparation: profile.preparation,
|
|
740
|
+
spellList: profile.spellList
|
|
609
741
|
});
|
|
610
742
|
slotInputs.push({ casterType: profile.casterType, level: c.level });
|
|
611
|
-
limitInputs.push({ classSlug: c.entity.slug, level: c.level, profile, abilityScore: scores[
|
|
743
|
+
limitInputs.push({ classSlug: c.entity.slug, level: c.level, profile, abilityScore: scores[ab] });
|
|
612
744
|
}
|
|
613
745
|
const spellcasting = spellcastingClasses.length > 0 ? {
|
|
614
746
|
ability: spellcastingClasses[0].ability,
|
|
@@ -627,24 +759,39 @@ function recalc(resolved, registry) {
|
|
|
627
759
|
const derivedSlots = deriveSpellSlots(slotInputs);
|
|
628
760
|
const spellLimits = computeSpellLimits(limitInputs);
|
|
629
761
|
const defenses = {
|
|
630
|
-
resistances:
|
|
631
|
-
(
|
|
762
|
+
resistances: suppress(resolved, "resistances", composeDefenseEntries(
|
|
763
|
+
(_J = (_I = resolved.definition.defenses) == null ? void 0 : _I.resistances) != null ? _J : [],
|
|
632
764
|
applied.defenses.resistances,
|
|
633
765
|
featureEffects.resistances
|
|
634
|
-
|
|
635
|
-
immunities:
|
|
636
|
-
(
|
|
637
|
-
applied.defenses.immunities
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
766
|
+
)),
|
|
767
|
+
immunities: suppress(resolved, "immunities", composeDefenseEntries(
|
|
768
|
+
(_L = (_K = resolved.definition.defenses) == null ? void 0 : _K.immunities) != null ? _L : [],
|
|
769
|
+
applied.defenses.immunities,
|
|
770
|
+
featureEffects.immunities
|
|
771
|
+
)),
|
|
772
|
+
vulnerabilities: suppress(resolved, "vulnerabilities", composeDefenseEntries(
|
|
773
|
+
(_N = (_M = resolved.definition.defenses) == null ? void 0 : _M.vulnerabilities) != null ? _N : [],
|
|
774
|
+
applied.defenses.vulnerabilities,
|
|
775
|
+
featureEffects.vulnerabilities
|
|
776
|
+
)),
|
|
777
|
+
condition_immunities: suppress(resolved, "condition_immunities", composeDefenseEntries(
|
|
778
|
+
(_P = (_O = resolved.definition.defenses) == null ? void 0 : _O.condition_immunities) != null ? _P : [],
|
|
645
779
|
applied.defenses.condition_immunities,
|
|
646
780
|
featureEffects.condition_immunities
|
|
647
|
-
|
|
781
|
+
))
|
|
782
|
+
};
|
|
783
|
+
const attackRows = [...(_Q = derivedEquipment == null ? void 0 : derivedEquipment.attacks) != null ? _Q : [], buildUnarmedRow(mods, proficiencyBonus, resolveUnarmedStrike(resolved))];
|
|
784
|
+
const riderBindings = {
|
|
785
|
+
level: totalLevel,
|
|
786
|
+
class_level: totalLevel,
|
|
787
|
+
prof: proficiencyBonus,
|
|
788
|
+
str_mod: mods.str,
|
|
789
|
+
dex_mod: mods.dex,
|
|
790
|
+
con_mod: mods.con,
|
|
791
|
+
int_mod: mods.int,
|
|
792
|
+
wis_mod: mods.wis,
|
|
793
|
+
cha_mod: mods.cha,
|
|
794
|
+
columns: {}
|
|
648
795
|
};
|
|
649
796
|
return {
|
|
650
797
|
totalLevel,
|
|
@@ -685,9 +832,9 @@ function recalc(resolved, registry) {
|
|
|
685
832
|
// untouched rows keep `critRange`/`attackNotes` ABSENT (not 20 / not []).
|
|
686
833
|
// crit-range: folded weapon crit threshold, only when an effect lowered it.
|
|
687
834
|
// attackNotes: reroll-damage / attack-rule captions, only when non-empty.
|
|
688
|
-
attacks:
|
|
835
|
+
attacks: attackRows.map((a) => {
|
|
689
836
|
var _a2;
|
|
690
|
-
const riders = [...(_a2 = a.damageRiders) != null ? _a2 : [], ...featureEffects.damageBonuses];
|
|
837
|
+
const riders = [...(_a2 = a.damageRiders) != null ? _a2 : [], ...featureEffects.damageBonuses].map((r) => resolveDamageRider(r, a.damageType, riderBindings));
|
|
691
838
|
return {
|
|
692
839
|
...a,
|
|
693
840
|
toHit: a.toHit + conditionEffects.d20_test_penalty,
|
|
@@ -696,12 +843,13 @@ function recalc(resolved, registry) {
|
|
|
696
843
|
...riders.length ? { damageRiders: riders } : {}
|
|
697
844
|
};
|
|
698
845
|
}),
|
|
699
|
-
equippedSlots: (
|
|
700
|
-
carriedWeight: (
|
|
701
|
-
attunementUsed: (
|
|
702
|
-
attunementLimit: (
|
|
846
|
+
equippedSlots: (_R = derivedEquipment == null ? void 0 : derivedEquipment.equippedSlots) != null ? _R : {},
|
|
847
|
+
carriedWeight: (_S = derivedEquipment == null ? void 0 : derivedEquipment.carriedWeight) != null ? _S : 0,
|
|
848
|
+
attunementUsed: (_T = derivedEquipment == null ? void 0 : derivedEquipment.attunementUsed) != null ? _T : 0,
|
|
849
|
+
attunementLimit: (_V = derivedEquipment == null ? void 0 : derivedEquipment.attunementLimit) != null ? _V : (_U = overrides.attunement_limit) != null ? _U : 3,
|
|
703
850
|
conditionEffects,
|
|
704
|
-
rollModifiers: featureEffects.rollModifiers
|
|
851
|
+
rollModifiers: featureEffects.rollModifiers,
|
|
852
|
+
saveOutcomes: featureEffects.saveOutcomes
|
|
705
853
|
};
|
|
706
854
|
}
|
|
707
855
|
export {
|
|
@@ -718,6 +866,7 @@ export {
|
|
|
718
866
|
parseDieSize,
|
|
719
867
|
phbAverageForDie,
|
|
720
868
|
recalc,
|
|
869
|
+
resolveUnarmedStrike,
|
|
721
870
|
speedFromRace,
|
|
722
871
|
unarmoredAC,
|
|
723
872
|
unarmoredACBreakdown
|