@archivist-gg/dnd5e 0.3.1 → 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 +26 -0
- package/dist/background/background.schema.js +5 -4
- 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-6IRYTM5V.js → chunk-DPUJDOKV.js} +119 -28
- 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-BIK4DFWK.js → chunk-HJ5EEZ47.js} +1 -1
- package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
- package/dist/{chunk-TN6ZLTNU.js → chunk-I2NDWFDD.js} +51 -4
- 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-SE7AZDR3.js → chunk-JRDPUDT5.js} +29 -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-5ZBE4CWV.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-D3CLOBE3.js → chunk-OSQFPGLM.js} +44 -8
- 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 +2033 -6907
- 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 +105 -17
- package/dist/pc/pc.decision-engine.js +28 -12
- 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 -8
- 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 +54 -29
- package/dist/pc/pc.proficiencies.js +74 -95
- package/dist/pc/pc.proficiency-grants.d.ts +58 -0
- package/dist/pc/pc.proficiency-normalize.d.ts +24 -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 +1 -1
- package/dist/pc/pc.recalc.d.ts +69 -14
- package/dist/pc/pc.recalc.js +261 -122
- 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 +139 -3
- package/dist/pc/pc.schema.js +4 -2
- package/dist/pc/pc.slotting.js +3 -3
- package/dist/pc/pc.spellcasting.d.ts +75 -6
- package/dist/pc/pc.spellcasting.js +16 -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 +251 -12
- 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 +53 -2
- package/dist/types/choice.js +13 -1
- 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-5XUXXAQJ.js +0 -30
- package/dist/chunk-7P65Q426.js +0 -158
- package/dist/chunk-7TEK5KK7.js +0 -49
- package/dist/chunk-AIRFC5NQ.js +0 -143
- package/dist/chunk-CZPMTQOY.js +0 -68
- package/dist/chunk-N2JE7BWL.js +0 -81
- package/dist/chunk-NXR3BD2V.js +0 -90
- package/dist/chunk-O5EYMKFH.js +0 -6
- package/dist/chunk-Q5K6LWBZ.js +0 -45
- package/dist/chunk-TNUFPIXI.js +0 -1110
- package/dist/chunk-TZK36BU7.js +0 -38
- package/dist/chunk-W7HWMMBF.js +0 -46
- package/dist/chunk-Y4I74YEG.js +0 -33
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
imageField
|
|
3
|
+
} from "./chunk-UA5KS2PL.js";
|
|
4
|
+
|
|
5
|
+
// src/spell/spell.schema.ts
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var castingOptionSchema = z.object({
|
|
8
|
+
type: z.string(),
|
|
9
|
+
damage_roll: z.string().optional(),
|
|
10
|
+
target_count: z.number().optional(),
|
|
11
|
+
duration: z.string().optional(),
|
|
12
|
+
range: z.number().optional(),
|
|
13
|
+
concentration: z.boolean().optional(),
|
|
14
|
+
shape_size: z.number().optional(),
|
|
15
|
+
desc: z.string().optional()
|
|
16
|
+
});
|
|
17
|
+
var spellMaterialSchema = z.union([
|
|
18
|
+
z.boolean(),
|
|
19
|
+
z.string(),
|
|
20
|
+
z.strictObject({
|
|
21
|
+
text: z.string(),
|
|
22
|
+
cost: z.number().optional(),
|
|
23
|
+
consume: z.union([z.boolean(), z.string()]).optional()
|
|
24
|
+
})
|
|
25
|
+
]);
|
|
26
|
+
var spellComponentsObjectSchema = z.strictObject({
|
|
27
|
+
v: z.boolean().optional(),
|
|
28
|
+
s: z.boolean().optional(),
|
|
29
|
+
m: spellMaterialSchema.optional(),
|
|
30
|
+
r: z.boolean().optional()
|
|
31
|
+
});
|
|
32
|
+
var spellDurationEntrySchema = z.discriminatedUnion("type", [
|
|
33
|
+
z.strictObject({
|
|
34
|
+
type: z.literal("permanent"),
|
|
35
|
+
ends: z.array(z.enum(["dispel", "trigger"])).nonempty()
|
|
36
|
+
}),
|
|
37
|
+
z.strictObject({
|
|
38
|
+
type: z.literal("timed"),
|
|
39
|
+
duration: z.strictObject({
|
|
40
|
+
type: z.enum(["minute", "hour"]),
|
|
41
|
+
amount: z.number().int().positive(),
|
|
42
|
+
up_to: z.boolean().optional()
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
]);
|
|
46
|
+
var spellEntitySchema = z.object({
|
|
47
|
+
name: z.string().min(1),
|
|
48
|
+
level: z.number().int().min(0).optional(),
|
|
49
|
+
school: z.string().optional(),
|
|
50
|
+
casting_time: z.string().optional(),
|
|
51
|
+
range: z.string().optional(),
|
|
52
|
+
// Union arms per §3.2; `parseSpell` normalises the structured arms back to the corpus's own
|
|
53
|
+
// string form, so `Spell.components` / `Spell.duration` stay `string` and no consumer changes.
|
|
54
|
+
components: z.union([z.string(), spellComponentsObjectSchema]).optional(),
|
|
55
|
+
duration: z.union([z.string(), z.array(spellDurationEntrySchema).nonempty()]).optional(),
|
|
56
|
+
concentration: z.boolean().optional(),
|
|
57
|
+
ritual: z.boolean().optional(),
|
|
58
|
+
classes: z.array(z.string()).optional(),
|
|
59
|
+
description: z.string().optional(),
|
|
60
|
+
at_higher_levels: z.array(z.string()).optional(),
|
|
61
|
+
damage: z.object({ types: z.array(z.string()) }).optional(),
|
|
62
|
+
saving_throw: z.object({ ability: z.string() }).optional(),
|
|
63
|
+
casting_options: z.array(castingOptionSchema).optional(),
|
|
64
|
+
// §2 · the fourteen converter keys this root refused before R4-G2. Doc counts are MEASURED over
|
|
65
|
+
// the frozen tree; the two zero-carrier keys are declared because the root is `.strict()` and an
|
|
66
|
+
// images-ON run (`image`) or a non-images-gated fluff flag (`has_fluff_images`) would otherwise
|
|
67
|
+
// refuse the whole document. Declared-only: NO rendering this phase (booked to G8 by name).
|
|
68
|
+
rendering_hint: z.string().optional(),
|
|
69
|
+
// 1,048 docs — NEVER .min(1): every value is ''
|
|
70
|
+
misc_tags: z.array(z.string()).optional(),
|
|
71
|
+
// 769
|
|
72
|
+
area_tags: z.array(z.string()).optional(),
|
|
73
|
+
// 707
|
|
74
|
+
condition_inflict: z.array(z.string()).optional(),
|
|
75
|
+
// 194
|
|
76
|
+
affects_creature_type: z.array(z.string()).optional(),
|
|
77
|
+
// 87
|
|
78
|
+
spell_attack: z.enum(["melee", "ranged"]).optional(),
|
|
79
|
+
// 77 (ranged 44 / melee 33)
|
|
80
|
+
ability_check: z.array(z.string()).optional(),
|
|
81
|
+
// 61
|
|
82
|
+
damage_resist: z.array(z.string()).optional(),
|
|
83
|
+
// 35
|
|
84
|
+
damage_immune: z.array(z.string()).optional(),
|
|
85
|
+
// 21
|
|
86
|
+
condition_immune: z.array(z.string()).optional(),
|
|
87
|
+
// 11
|
|
88
|
+
damage_vulnerable: z.array(z.string()).optional(),
|
|
89
|
+
// 2
|
|
90
|
+
has_fluff: z.boolean().optional(),
|
|
91
|
+
// 1
|
|
92
|
+
image: imageField,
|
|
93
|
+
// 0 today; `imageField` already ends .optional()
|
|
94
|
+
has_fluff_images: z.boolean().optional()
|
|
95
|
+
// 0 today
|
|
96
|
+
}).strict();
|
|
97
|
+
|
|
98
|
+
export {
|
|
99
|
+
spellEntitySchema
|
|
100
|
+
};
|
|
@@ -203,6 +203,10 @@ var CONDITIONS = [
|
|
|
203
203
|
"Unconscious"
|
|
204
204
|
];
|
|
205
205
|
var STANDARD_SENSES = ["Blindsight", "Darkvision", "Tremorsense", "Truesight"];
|
|
206
|
+
var STANDARD_ACTIONS = {
|
|
207
|
+
"2014": ["Attack", "Cast a Spell", "Dash", "Disengage", "Dodge", "Help", "Hide", "Ready", "Search", "Use an Object"],
|
|
208
|
+
"2024": ["Attack", "Dash", "Disengage", "Dodge", "Help", "Hide", "Influence", "Magic", "Ready", "Search", "Study", "Utilize"]
|
|
209
|
+
};
|
|
206
210
|
var ALIGNMENT_ETHICAL = ["Lawful", "Neutral", "Chaotic", "Unaligned", "Any"];
|
|
207
211
|
var ALIGNMENT_MORAL = ["Good", "Neutral", "Evil"];
|
|
208
212
|
var ALL_SECTIONS = [
|
|
@@ -214,6 +218,20 @@ var ALL_SECTIONS = [
|
|
|
214
218
|
"Lair Actions",
|
|
215
219
|
"Mythic Actions"
|
|
216
220
|
];
|
|
221
|
+
var ABILITY_NAME_TO_KEY = {
|
|
222
|
+
strength: "str",
|
|
223
|
+
dexterity: "dex",
|
|
224
|
+
constitution: "con",
|
|
225
|
+
intelligence: "int",
|
|
226
|
+
wisdom: "wis",
|
|
227
|
+
charisma: "cha"
|
|
228
|
+
};
|
|
229
|
+
function normalizeAbility(value) {
|
|
230
|
+
var _a;
|
|
231
|
+
const k = value.trim().toLowerCase();
|
|
232
|
+
if (ABILITY_KEYS.includes(k)) return k;
|
|
233
|
+
return (_a = ABILITY_NAME_TO_KEY[k]) != null ? _a : null;
|
|
234
|
+
}
|
|
217
235
|
|
|
218
236
|
export {
|
|
219
237
|
CR_PROFICIENCY,
|
|
@@ -229,7 +247,10 @@ export {
|
|
|
229
247
|
DAMAGE_NONMAGICAL_VARIANTS,
|
|
230
248
|
CONDITIONS,
|
|
231
249
|
STANDARD_SENSES,
|
|
250
|
+
STANDARD_ACTIONS,
|
|
232
251
|
ALIGNMENT_ETHICAL,
|
|
233
252
|
ALIGNMENT_MORAL,
|
|
234
|
-
ALL_SECTIONS
|
|
253
|
+
ALL_SECTIONS,
|
|
254
|
+
ABILITY_NAME_TO_KEY,
|
|
255
|
+
normalizeAbility
|
|
235
256
|
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// src/schemas/feature-effect-schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var abilityEnum = z.enum(["str", "dex", "con", "int", "wis", "cha"]);
|
|
4
|
+
var subjectField = z.string().min(1).optional();
|
|
5
|
+
var conditionField = z.string().optional();
|
|
6
|
+
var featureEffectSchema = z.discriminatedUnion("kind", [
|
|
7
|
+
z.object({ kind: z.literal("initiative-bonus"), value: z.number().int(), condition: conditionField, subject: subjectField }),
|
|
8
|
+
// `condition` here is the condition NAME (frightened, poisoned); the qualifier is `while`.
|
|
9
|
+
z.object({ kind: z.literal("immune-condition"), condition: z.string().min(1), while: z.string().optional(), subject: subjectField }),
|
|
10
|
+
z.object({ kind: z.literal("resistance"), damage_type: z.string().min(1), condition: conditionField, subject: subjectField }),
|
|
11
|
+
z.object({ kind: z.literal("hp-per-level-bonus"), value: z.number().int(), condition: conditionField, subject: subjectField }),
|
|
12
|
+
z.object({
|
|
13
|
+
kind: z.literal("speed-bonus"),
|
|
14
|
+
mode: z.enum(["walk", "fly", "swim", "climb", "burrow"]),
|
|
15
|
+
value: z.number().int(),
|
|
16
|
+
// when true, value is an absolute floor (Math.max), not additive; currently
|
|
17
|
+
// only surfaced for mode:"walk" · other modes have no derived speed yet.
|
|
18
|
+
set: z.boolean().optional(),
|
|
19
|
+
// R4-G7 §7.3: the WHOLE progression lives inside the effect, because the overlay's `class_features`
|
|
20
|
+
// map is keyed `<class>:<feature-slug>` with no level component and, after §7.1's fold, the sheet
|
|
21
|
+
// reads exactly ONE copy of a repeated feature. The engine takes the highest entry at or below the
|
|
22
|
+
// effect's OWN source level (`levelFor`), and applies it to the additive bonus and to a `set` floor
|
|
23
|
+
// alike. The Monk's Unarmored Movement is the shipped carrier shape.
|
|
24
|
+
scales_at: z.array(z.object({ level: z.number().int().min(1).max(20), value: z.number().int() })).optional(),
|
|
25
|
+
condition: conditionField,
|
|
26
|
+
subject: subjectField
|
|
27
|
+
}),
|
|
28
|
+
z.object({
|
|
29
|
+
kind: z.literal("sense"),
|
|
30
|
+
type: z.enum(["darkvision", "blindsight", "tremorsense", "truesight"]),
|
|
31
|
+
range: z.number().int().nonnegative(),
|
|
32
|
+
condition: conditionField,
|
|
33
|
+
subject: subjectField
|
|
34
|
+
}),
|
|
35
|
+
// `condition` here is the condition NAME being applied.
|
|
36
|
+
z.object({
|
|
37
|
+
kind: z.literal("apply-condition"),
|
|
38
|
+
condition: z.string().min(1),
|
|
39
|
+
duration: z.string().optional(),
|
|
40
|
+
ends_on: z.array(z.string()).optional(),
|
|
41
|
+
save_repeat: z.object({ ability: z.string().min(1), timing: z.string().min(1) }).optional(),
|
|
42
|
+
subject: subjectField
|
|
43
|
+
}),
|
|
44
|
+
z.object({
|
|
45
|
+
kind: z.literal("damage-bonus"),
|
|
46
|
+
// intentionally an open string, NOT a damage-type enum: must accept the
|
|
47
|
+
// literal "chosen" (player-selected damage type at action time) alongside
|
|
48
|
+
// canonical damage types. Do not tighten to an enum.
|
|
49
|
+
damage_type: z.string().min(1),
|
|
50
|
+
amount: z.string().min(1),
|
|
51
|
+
applies_to: z.enum(["weapon", "spell", "all"]).optional(),
|
|
52
|
+
condition: conditionField,
|
|
53
|
+
subject: subjectField
|
|
54
|
+
}),
|
|
55
|
+
z.object({
|
|
56
|
+
kind: z.literal("proficiency"),
|
|
57
|
+
proficiency_type: z.enum(["skill", "tool", "language", "saving-throw", "armor", "weapon"]),
|
|
58
|
+
value: z.string().min(1),
|
|
59
|
+
expertise: z.boolean().optional(),
|
|
60
|
+
condition: conditionField,
|
|
61
|
+
subject: subjectField
|
|
62
|
+
}),
|
|
63
|
+
z.object({ kind: z.literal("ac-bonus"), value: z.number().int(), requires_armor: z.boolean().optional(), condition: conditionField, subject: subjectField }),
|
|
64
|
+
z.object({
|
|
65
|
+
kind: z.literal("unarmored-ac"),
|
|
66
|
+
abilities: z.array(abilityEnum),
|
|
67
|
+
base: z.number().int().optional(),
|
|
68
|
+
allow_shield: z.boolean().optional(),
|
|
69
|
+
condition: conditionField,
|
|
70
|
+
subject: subjectField
|
|
71
|
+
}),
|
|
72
|
+
z.object({
|
|
73
|
+
kind: z.literal("unarmed-strike"),
|
|
74
|
+
// R4-G7 §7.2: a bare die expression, `<count>d<faces>`. `resolveUnarmedStrike` averages the flat arm with
|
|
75
|
+
// /^(\d+)d(\d+)$/ and silently averages anything else as 1, so a modifier tail ("1d6+1") or a missing
|
|
76
|
+
// half ("d6", "1d") must refuse here rather than mis-average there. The `i` arm keeps an authored `1D6`.
|
|
77
|
+
dice: z.union([z.string().regex(/^\d+d\d+$/i), z.object({ column: z.string().min(1) })]).optional(),
|
|
78
|
+
abilities: z.array(abilityEnum).nonempty().optional(),
|
|
79
|
+
condition: conditionField,
|
|
80
|
+
subject: subjectField
|
|
81
|
+
}),
|
|
82
|
+
z.object({
|
|
83
|
+
kind: z.literal("weapon-ability"),
|
|
84
|
+
ability: z.union([abilityEnum, z.literal("spellcasting")]),
|
|
85
|
+
weapons: z.union([z.literal("chosen"), z.string(), z.array(z.string())]).optional(),
|
|
86
|
+
condition: conditionField,
|
|
87
|
+
subject: subjectField
|
|
88
|
+
}),
|
|
89
|
+
z.object({
|
|
90
|
+
kind: z.literal("roll-modifier"),
|
|
91
|
+
mode: z.enum(["advantage", "disadvantage", "reroll", "add-d4"]),
|
|
92
|
+
roll: z.enum(["ability-check", "saving-throw", "attack", "any"]),
|
|
93
|
+
scope: z.string().optional(),
|
|
94
|
+
condition: conditionField,
|
|
95
|
+
subject: subjectField
|
|
96
|
+
}),
|
|
97
|
+
z.object({
|
|
98
|
+
kind: z.literal("extra-attack"),
|
|
99
|
+
// `count` is EXTRA attacks, never total attacks: the engine renders `1 + count`.
|
|
100
|
+
count: z.number().int().positive(),
|
|
101
|
+
// R4-G7 §7.3, the `speed-bonus` twin: the SRD 5e Fighter's one Extra Attack feature carries its whole
|
|
102
|
+
// 5 / 11 / 20 progression here, because `bucketFeaturesByLevel` emits one overlay record into every
|
|
103
|
+
// `gained_at` bucket and a per-copy count cannot be authored.
|
|
104
|
+
scales_at: z.array(z.object({ level: z.number().int().min(1).max(20), count: z.number().int().positive() })).optional(),
|
|
105
|
+
condition: conditionField,
|
|
106
|
+
subject: subjectField
|
|
107
|
+
}),
|
|
108
|
+
z.object({
|
|
109
|
+
kind: z.literal("crit-range"),
|
|
110
|
+
min_roll: z.number().int().min(2).max(20),
|
|
111
|
+
applies_to: z.enum(["weapon", "spell", "all"]).optional(),
|
|
112
|
+
condition: conditionField,
|
|
113
|
+
subject: subjectField
|
|
114
|
+
}),
|
|
115
|
+
z.object({
|
|
116
|
+
kind: z.literal("reroll-damage"),
|
|
117
|
+
max_reroll: z.number().int().positive(),
|
|
118
|
+
applies_to: z.enum(["weapon", "spell", "all"]).optional(),
|
|
119
|
+
once_per_die: z.boolean().optional(),
|
|
120
|
+
condition: conditionField,
|
|
121
|
+
subject: subjectField
|
|
122
|
+
}),
|
|
123
|
+
z.object({ kind: z.literal("attack-rule"), flag: z.enum(["no-ranged-in-melee-disadvantage"]), condition: conditionField, subject: subjectField }),
|
|
124
|
+
// R4-G1a declared these seven converter-emitted arms with the engine folding NOTHING for them
|
|
125
|
+
// (spec D3). R4-G3a §3-§7 gives SIX of them semantics: immunity / vulnerability FOLD (defenses
|
|
126
|
+
// pane); temp-hp / heal / extra-action are still NOT folded, the plugin reads them raw as
|
|
127
|
+
// row-local captions; save-outcome FOLDS (save-chip tag rail).
|
|
128
|
+
// `ability-score-increase` folds FLAT at the fold since R4-G3b §4 (fixed-list arms only; `chosen` arms
|
|
129
|
+
// are the ASI slot's second encoding; `max` is unread by user ruling).
|
|
130
|
+
// Damage immunity / vulnerability. NOT `immune-condition`, which is condition immunity.
|
|
131
|
+
z.object({ kind: z.literal("immunity"), damage_type: z.string().min(1), condition: conditionField, subject: subjectField }),
|
|
132
|
+
z.object({ kind: z.literal("vulnerability"), damage_type: z.string().min(1), condition: conditionField, subject: subjectField }),
|
|
133
|
+
// `amount` is the open non-empty STRING `damage-bonus.amount` already uses: "2d6", "5", "your Artificer level".
|
|
134
|
+
z.object({ kind: z.literal("temp-hp"), amount: z.string().min(1), condition: conditionField, subject: subjectField }),
|
|
135
|
+
z.object({ kind: z.literal("heal"), amount: z.string().min(1), condition: conditionField, subject: subjectField }),
|
|
136
|
+
z.object({
|
|
137
|
+
kind: z.literal("ability-score-increase"),
|
|
138
|
+
// "chosen" follows `weapon-ability.weapons`; the list follows `unarmored-ac.abilities`.
|
|
139
|
+
abilities: z.union([z.literal("chosen"), z.array(abilityEnum).min(1)]),
|
|
140
|
+
amount: z.number().int().positive(),
|
|
141
|
+
// Required-WITH-NULL, never optional: "the prose stated no cap" and "the extractor forgot" must not look alike.
|
|
142
|
+
choose: z.number().int().positive().nullable(),
|
|
143
|
+
max: z.number().int().positive().nullable(),
|
|
144
|
+
condition: conditionField,
|
|
145
|
+
subject: subjectField
|
|
146
|
+
}).refine((e) => e.abilities === "chosen" === (e.choose !== null), {
|
|
147
|
+
path: ["choose"],
|
|
148
|
+
message: 'choose is required IFF abilities is "chosen": a fixed LIST is its own count'
|
|
149
|
+
}),
|
|
150
|
+
// `extra-action` is an additional ACTION on your turn; `extra-attack` is attacks WITHIN the Attack action.
|
|
151
|
+
z.object({
|
|
152
|
+
kind: z.literal("extra-action"),
|
|
153
|
+
count: z.number().int().positive(),
|
|
154
|
+
action_type: z.enum(["action", "bonus-action", "reaction"]),
|
|
155
|
+
condition: conditionField,
|
|
156
|
+
subject: subjectField
|
|
157
|
+
}),
|
|
158
|
+
// `save-outcome` remaps the OUTCOME; `roll-modifier` modifies the ROLL.
|
|
159
|
+
z.object({
|
|
160
|
+
kind: z.literal("save-outcome"),
|
|
161
|
+
ability: z.union([abilityEnum, z.literal("any")]),
|
|
162
|
+
on_success: z.enum(["none", "half", "full"]),
|
|
163
|
+
on_failure: z.enum(["none", "half", "full"]),
|
|
164
|
+
applies_to: z.string().nullable(),
|
|
165
|
+
condition: conditionField,
|
|
166
|
+
subject: subjectField
|
|
167
|
+
})
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
featureEffectSchema
|
|
172
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
slugify
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6X4KUDMU.js";
|
|
4
4
|
|
|
5
5
|
// src/entities/base-item-resolver.ts
|
|
6
6
|
function unwrapWikilink(input) {
|
|
@@ -10,7 +10,11 @@ function unwrapWikilink(input) {
|
|
|
10
10
|
const pipe = inner.indexOf("|");
|
|
11
11
|
return pipe === -1 ? inner : inner.slice(0, pipe);
|
|
12
12
|
}
|
|
13
|
-
var FOLDER_TO_TYPE = {
|
|
13
|
+
var FOLDER_TO_TYPE = {
|
|
14
|
+
Weapons: "weapon",
|
|
15
|
+
Armor: "armor",
|
|
16
|
+
"Magic Items": "item"
|
|
17
|
+
};
|
|
14
18
|
function vaultPathToSlug(target) {
|
|
15
19
|
const segments = target.split("/").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
16
20
|
if (segments.length === 0) return "";
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
raceEntitySchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FDBWYMZK.js";
|
|
4
|
+
import {
|
|
5
|
+
aliasFeatureListActionCost
|
|
6
|
+
} from "./chunk-4U55VNC7.js";
|
|
4
7
|
|
|
5
8
|
// src/race/race.parser.ts
|
|
6
9
|
import { parseYaml } from "@archivist-gg/core";
|
|
7
10
|
function parseRace(source) {
|
|
8
11
|
const raw = parseYaml(source, ["name", "slug"]);
|
|
9
12
|
if (!raw.success) return raw;
|
|
13
|
+
aliasFeatureListActionCost(raw.data.traits);
|
|
10
14
|
const result = raceEntitySchema.safeParse({ edition: "2014", ...raw.data });
|
|
11
15
|
if (!result.success) {
|
|
12
16
|
return { success: false, error: `race schema validation failed: ${result.error.message}` };
|