@archivist-gg/dnd5e 0.3.1 → 0.3.5
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-2VDTW7QO.js +1580 -0
- package/dist/{chunk-ZZGEVJKX.js → chunk-3JOTQW7A.js} +1 -1
- package/dist/{chunk-5ZBE4CWV.js → chunk-3PZHBLFG.js} +1 -1
- 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-5RKLL2AD.js} +5 -1
- package/dist/{chunk-SE7AZDR3.js → chunk-63XQXPZL.js} +29 -3
- package/dist/{chunk-4F6AIZ36.js → chunk-6BFWZW6T.js} +1 -1
- package/dist/{chunk-GJOI2GHP.js → chunk-6GNXYAYP.js} +1 -1
- 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-TLYDBT5F.js → chunk-CGRLQ34U.js} +64 -7
- package/dist/chunk-CJYCVNW2.js +7 -0
- package/dist/{chunk-XLSVNUTK.js → chunk-CV5XDJKU.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-GE4TLPWM.js → chunk-EHDATXP7.js} +1 -1
- package/dist/chunk-EVMUJYUD.js +195 -0
- package/dist/{chunk-K6Q5OUGK.js → chunk-GFZ7PITJ.js} +86 -10
- package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
- package/dist/{chunk-TN6ZLTNU.js → chunk-I2NDWFDD.js} +51 -4
- package/dist/{chunk-3DZ74AKK.js → chunk-IN4M4X7P.js} +8 -2
- package/dist/chunk-IUAAXXNO.js +58 -0
- package/dist/{chunk-NXSWH3AE.js → chunk-IWRVOCT5.js} +1 -1
- package/dist/{chunk-XJNECUPT.js → chunk-JC5UNIVM.js} +19 -0
- package/dist/{chunk-24GFQU7T.js → chunk-JSZ4H6AQ.js} +1 -1
- package/dist/{chunk-XTIQWSFM.js → chunk-KADJZGZY.js} +1 -1
- package/dist/{chunk-L7E2UT5A.js → chunk-KK33PIDN.js} +5 -1
- package/dist/chunk-KPEJMNRD.js +302 -0
- package/dist/chunk-KU3YLF6D.js +106 -0
- package/dist/{chunk-5INR4NSL.js → chunk-LDDCNPHD.js} +1 -1
- package/dist/chunk-LVQLWRCU.js +15 -0
- package/dist/chunk-MI7P3NX3.js +161 -0
- package/dist/{chunk-PHQRGDRQ.js → chunk-N3A5ICBO.js} +5 -1
- package/dist/chunk-O4SRD3J5.js +165 -0
- package/dist/chunk-OAXWSVJB.js +81 -0
- 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-RSDRMH54.js → chunk-RF4TYCA2.js} +1 -1
- package/dist/chunk-RLGQ5PZZ.js +16 -0
- package/dist/chunk-RVXC6ZHY.js +89 -0
- package/dist/chunk-S7REMWW4.js +21 -0
- package/dist/{chunk-7VJ6BOA5.js → chunk-SMLXZUBH.js} +9 -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-BIK4DFWK.js → chunk-ULCQ73LA.js} +1 -1
- package/dist/{chunk-2BWAID3Y.js → chunk-UMWIPLLM.js} +29 -3
- package/dist/chunk-UQ3ZFCWD.js +178 -0
- package/dist/chunk-UXPGW4TI.js +101 -0
- package/dist/chunk-V2MJE6NC.js +133 -0
- package/dist/{chunk-D3CLOBE3.js → chunk-V373TRJE.js} +48 -10
- package/dist/chunk-VQAXTIBW.js +100 -0
- package/dist/chunk-W74BCA7V.js +159 -0
- package/dist/{chunk-WP2CX2JO.js → chunk-WELIKLZF.js} +22 -1
- package/dist/{chunk-MDEJHMKK.js → chunk-WHVLNFTG.js} +26 -5
- package/dist/{chunk-GZ46OVGZ.js → chunk-WSVMLNTO.js} +1 -1
- package/dist/{chunk-4LZJXJJS.js → chunk-WXWPK3LI.js} +6 -2
- package/dist/chunk-X3D6LXUU.js +185 -0
- package/dist/chunk-XJ2F2WO6.js +8 -0
- package/dist/{chunk-73HOFQQ5.js → chunk-Y4AGLCY6.js} +1 -1
- package/dist/chunk-YBLDE5CG.js +42 -0
- package/dist/{chunk-JEYQU3JT.js → chunk-YHYTW5QA.js} +2 -18
- package/dist/{chunk-PZOWBI3B.js → chunk-YLL2QXY2.js} +7 -2
- 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 +239 -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 +185 -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 +31 -2
- package/dist/pc/pc.equipment.js +12 -8
- package/dist/pc/pc.feature-effects.d.ts +234 -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 +133 -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 +85 -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
package/dist/types/feature.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Choice } from "./choice.js";
|
|
2
|
-
import type { Resource, ResourceConsumption } from "./resource.js";
|
|
2
|
+
import type { Resource, ResourceConsumption, ActionCost } from "./resource.js";
|
|
3
3
|
import type { Attack } from "./attack.js";
|
|
4
4
|
import type { FeatureEffect } from "./feature-effect.js";
|
|
5
5
|
import type { Duration } from "../schemas/duration-schema.js";
|
|
@@ -15,6 +15,56 @@ export interface FeatureRecharge {
|
|
|
15
15
|
type: "recharge_on_roll" | "per_day" | "per_short_rest" | "per_long_rest";
|
|
16
16
|
param: number;
|
|
17
17
|
}
|
|
18
|
+
/** The converter's 14-key companion binding (R4-G5 §7, ruling G5-UR2 "declare now, card after the G7 re-emit").
|
|
19
|
+
* DECLARED, not read: the converter withholds the key today (`P9_NOT_EMITTED_FIELDS`), 0 converted and 0 bundle
|
|
20
|
+
* notes carry it, and the Passive-tab card is a G8 booking. Every closed-vocabulary leaf is a plain `string` and
|
|
21
|
+
* every position the converter can emit as null is `| null`, for the reason the schema mirror states: a class,
|
|
22
|
+
* subclass or race parser refuses a WHOLE document on one nested leaf failure, so a mirror stricter than the
|
|
23
|
+
* emitter is a total-loss risk on the day the re-emit lands. */
|
|
24
|
+
export interface FeatureCompanion {
|
|
25
|
+
statblock?: string;
|
|
26
|
+
statblock_wikilink?: string | null;
|
|
27
|
+
count?: string;
|
|
28
|
+
count_scaling?: Array<{
|
|
29
|
+
level?: number;
|
|
30
|
+
count?: string;
|
|
31
|
+
source_quote?: string;
|
|
32
|
+
}>;
|
|
33
|
+
shares_action_economy?: boolean;
|
|
34
|
+
turn_order?: string;
|
|
35
|
+
turn_order_source_quote?: string | null;
|
|
36
|
+
proficiency_bonus_scaled?: Array<{
|
|
37
|
+
stat?: string;
|
|
38
|
+
formula?: string;
|
|
39
|
+
source_quote?: string;
|
|
40
|
+
}>;
|
|
41
|
+
lifecycle?: {
|
|
42
|
+
created_by?: string;
|
|
43
|
+
recreate_on?: string | null;
|
|
44
|
+
previous_instance_perishes?: boolean | null;
|
|
45
|
+
vanishes_if_owner_dies?: boolean | null;
|
|
46
|
+
vanishes_after?: string | null;
|
|
47
|
+
source_quote?: string;
|
|
48
|
+
} | null;
|
|
49
|
+
autonomy?: {
|
|
50
|
+
when?: string;
|
|
51
|
+
behaviour?: string;
|
|
52
|
+
source_quote?: string;
|
|
53
|
+
} | null;
|
|
54
|
+
variants?: Array<{
|
|
55
|
+
axis?: string;
|
|
56
|
+
choices?: string[];
|
|
57
|
+
chosen_at?: string;
|
|
58
|
+
source_quote?: string;
|
|
59
|
+
}>;
|
|
60
|
+
base_statblock?: string | null;
|
|
61
|
+
overrides?: Array<{
|
|
62
|
+
field?: string;
|
|
63
|
+
value?: string;
|
|
64
|
+
source_quote?: string;
|
|
65
|
+
}>;
|
|
66
|
+
source_quote?: string;
|
|
67
|
+
}
|
|
18
68
|
export interface Feature {
|
|
19
69
|
id?: string;
|
|
20
70
|
name: string;
|
|
@@ -38,4 +88,23 @@ export interface Feature {
|
|
|
38
88
|
passive?: boolean;
|
|
39
89
|
/** How long the buff lasts; rendered as a static label (no live countdown). */
|
|
40
90
|
duration?: Duration;
|
|
91
|
+
class_source?: string;
|
|
92
|
+
/** Always "" on every measured carrier — never constrain it non-empty. */
|
|
93
|
+
rendering_hint?: string;
|
|
94
|
+
subclass_short_name?: string;
|
|
95
|
+
subclass_source?: string;
|
|
96
|
+
header?: number;
|
|
97
|
+
is_class_feature_variant?: boolean;
|
|
98
|
+
gain_subclass_feature?: boolean;
|
|
99
|
+
gain_subclass_feature_has_content?: boolean;
|
|
100
|
+
/** 5etools entry type; values {"inset","item"}. */
|
|
101
|
+
type?: string;
|
|
102
|
+
action_cost?: ActionCost;
|
|
103
|
+
save?: {
|
|
104
|
+
ability: string;
|
|
105
|
+
dc_formula: string;
|
|
106
|
+
};
|
|
107
|
+
/** The companion this feature binds (R4-G5 §7). Declared so the class / subclass / race parsers stop stripping
|
|
108
|
+
* it on the day the G7 re-emit lands; nothing reads it in G5. */
|
|
109
|
+
companion?: FeatureCompanion;
|
|
41
110
|
}
|
|
@@ -2,15 +2,24 @@ import type { FeatureEffect } from "./feature-effect.js";
|
|
|
2
2
|
import type { ActionCost, ResetTrigger, ResourceConsumption } from "./resource.js";
|
|
3
3
|
import type { Duration } from "../schemas/duration-schema.js";
|
|
4
4
|
import type { Edition } from "./edition.js";
|
|
5
|
+
import type { AdditionalSpellsEntry, ProgressionEntry } from "../schemas/entity-extras-schema.js";
|
|
5
6
|
/**
|
|
6
7
|
* Documentation-only union of the canonical SRD feature types. The
|
|
7
8
|
* `feature_type` field is now an open string (see {@link OptionalFeatureEntity})
|
|
8
9
|
* so homebrew categories parse; this union is kept purely as a reference list.
|
|
9
10
|
*/
|
|
10
11
|
export type OptionalFeatureKind = "invocation" | "fighting_style" | "metamagic" | "maneuver" | "infusion";
|
|
12
|
+
/** A class/subclass named reference carried by a level prerequisite; mirrors namedRefSchema. */
|
|
13
|
+
export type OptionalFeatureNamedRef = {
|
|
14
|
+
name: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
visible_stats?: boolean;
|
|
17
|
+
};
|
|
11
18
|
export type OptionalFeaturePrerequisite = {
|
|
12
19
|
kind: "level";
|
|
13
20
|
min: number;
|
|
21
|
+
class?: OptionalFeatureNamedRef;
|
|
22
|
+
subclass?: OptionalFeatureNamedRef;
|
|
14
23
|
} | {
|
|
15
24
|
kind: "spell-known";
|
|
16
25
|
spell: string;
|
|
@@ -27,6 +36,14 @@ export type OptionalFeaturePrerequisite = {
|
|
|
27
36
|
} | {
|
|
28
37
|
kind: "other";
|
|
29
38
|
detail: string;
|
|
39
|
+
} | {
|
|
40
|
+
kind: "optionalfeature";
|
|
41
|
+
optionalfeature: string;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "spell-choose";
|
|
44
|
+
choose: string;
|
|
45
|
+
entry?: string;
|
|
46
|
+
entry_summary?: string;
|
|
30
47
|
};
|
|
31
48
|
export interface OptionalFeatureEntity {
|
|
32
49
|
slug: string;
|
|
@@ -57,4 +74,15 @@ export interface OptionalFeatureEntity {
|
|
|
57
74
|
/** Phase 3 activatable buffs: when true, the boon's effects fold only while its
|
|
58
75
|
* slug is present in `Character.state.active_buffs` (toggled in the PoolTab). */
|
|
59
76
|
activatable?: boolean;
|
|
77
|
+
/** Converter extras declared by optional-feature.schema.ts §2.5; all optional.
|
|
78
|
+
* `rendering_hint` is the ONE of these whose VALUES are load-bearing (88 records carry a
|
|
79
|
+
* real marker such as `dice-pool`); reading it is G4's row, declaring it is this one's. */
|
|
80
|
+
rendering_hint?: string;
|
|
81
|
+
additional_spells?: AdditionalSpellsEntry[];
|
|
82
|
+
is_class_feature_variant?: boolean;
|
|
83
|
+
has_fluff_images?: boolean;
|
|
84
|
+
feat_progression?: ProgressionEntry[];
|
|
85
|
+
optionalfeature_progression?: ProgressionEntry[];
|
|
86
|
+
/** One wikilink, or an array of them for the multi-fluff-image emit. */
|
|
87
|
+
image?: string | string[];
|
|
60
88
|
}
|
package/dist/types/resource.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** `either` = recovered by a short OR a long rest (R4-G3a §8.2; the 43 "short or
|
|
2
|
+
* long rest" rows). Kept in step with `resetTriggerEnum` in schemas/resource-schema.ts. */
|
|
3
|
+
export type ResetTrigger = "short-rest" | "long-rest" | "either" | "dawn" | "dusk" | "turn" | "round" | "custom";
|
|
2
4
|
export type ActionCost = "action" | "bonus-action" | "reaction" | "free" | "special";
|
|
3
5
|
export interface ResourceDie {
|
|
4
6
|
base: string;
|
|
@@ -11,6 +13,18 @@ export interface ResourceRecovery {
|
|
|
11
13
|
action?: ActionCost;
|
|
12
14
|
uses?: number;
|
|
13
15
|
reset: ResetTrigger;
|
|
16
|
+
/** The recovery KIND; absent = `uses` (R4-G4 §7, UR2), applied by the RESOLVER
|
|
17
|
+
* (pc/pc.resources.ts `resolveRecovery`) and never by a schema default, because
|
|
18
|
+
* the sheet reads RAW entities. The CARRIERS, re-measured 2026-09-05 after R4-G4
|
|
19
|
+
* T2b's regen shipped the bundle (this sentence was authored at T2, BEFORE that
|
|
20
|
+
* regen, and said ZERO, which it no longer is): `grep -rl "restores:" --include='*.md'`
|
|
21
|
+
* returns the TWO bundle Wizard notes (`SRD 2024/Classes/Wizard.md` and
|
|
22
|
+
* `SRD 5e/Classes/Wizard.md`), whose Arcane Recovery rows T2b's overlay stamps
|
|
23
|
+
* `spell-slots` and which §7.1 measured as the only spell-slot recoveries in shipped
|
|
24
|
+
* data; the embedded `.compendium-bundle/index.json` carries the key on one line for
|
|
25
|
+
* the same two rows; the converter corpus carries it on NO note. Kept in step with
|
|
26
|
+
* `resourceSchema.recovery` in schemas/resource-schema.ts. */
|
|
27
|
+
restores?: "uses" | "spell-slots";
|
|
14
28
|
}
|
|
15
29
|
export interface ResourceScaleStep {
|
|
16
30
|
level: number;
|
|
@@ -34,7 +48,13 @@ export interface ResourceConsumption {
|
|
|
34
48
|
source?: "resource" | "class-column" | "attack-dice";
|
|
35
49
|
resource?: string;
|
|
36
50
|
column?: string;
|
|
51
|
+
/** The MINIMUM spend when `amount_max` is present, otherwise the exact spend. */
|
|
37
52
|
amount: number;
|
|
53
|
+
/** Upper bound of a RANGE spend (`amount` .. `amount_max`), int and positive.
|
|
54
|
+
* DECLARED only in R4-G3a §9: zero emitted carriers, zero readers; spending a
|
|
55
|
+
* range is G4's. Kept in step with `resourceConsumptionSchema` in
|
|
56
|
+
* schemas/resource-schema.ts, whose refine is undefined-safe. */
|
|
57
|
+
amount_max?: number;
|
|
38
58
|
expend_condition?: "roll_succeeds" | "roll_fails" | "target_takes_damage" | "always";
|
|
39
59
|
free_uses?: {
|
|
40
60
|
amount: number;
|
|
@@ -24,8 +24,23 @@ export interface PoolGrant {
|
|
|
24
24
|
at_level: number;
|
|
25
25
|
}>;
|
|
26
26
|
}
|
|
27
|
-
/** Presentation hint for a data-declared tab.
|
|
28
|
-
|
|
27
|
+
/** Presentation hint for a data-declared tab. `dice-pool` / `point-pool` are DERIVED from the
|
|
28
|
+
* members' `rendering_hint` at resolve time onto `ResolvedPool.layout` (pc/pool-layout.ts), and that
|
|
29
|
+
* derivation is UNCONDITIONAL: it runs whether or not the declaration carries a `layout`. R4-G4 T5
|
|
30
|
+
* LANDED the precedence in the plugin: `TabsContainer`'s dynamic-pool-tab loop reads the AUTHORED
|
|
31
|
+
* value first, then `ResolvedPool.layout`, then the `spell-like` default, and `PoolTab`'s `LAYOUTS`
|
|
32
|
+
* registry routes all four members (an unknown string degrades to `spell-like` and never throws).
|
|
33
|
+
* R4-G5 CLOSED that list, and NOT by adding values: `pool-selection` and `stance` never get a layout value
|
|
34
|
+
* (measured, spec §10: the three `stance`-hinted documents are field-identical to three unhinted siblings, and
|
|
35
|
+
* `pool-selection`'s meaning is delivered by `spell-like` plus the §5 head), and `granted-die-to-ally` is a
|
|
36
|
+
* PER-ROW affordance (`EntryAffordance` below), never a pool layout: mapping it here would bury four maneuvers
|
|
37
|
+
* under 39 on one vote of 43. This union keeps its four members and `RENDERING_HINT_LAYOUT` its two keys. */
|
|
38
|
+
export type PoolLayout = "spell-like" | "blocks" | "dice-pool" | "point-pool";
|
|
39
|
+
/** A PER-ENTRY affordance derived from ONE optional feature's own `rendering_hint` (R4-G5 §4.2.1). The sibling of
|
|
40
|
+
* `PoolLayout`, and deliberately not part of it: a layout is a POOL-level MAJORITY vote, so a hint carried by
|
|
41
|
+
* four of 43 maneuvers could never win one, and mapping it would be a monotone loss for the other 39. The table,
|
|
42
|
+
* the derivation and the caption live in `pc/pool-layout.ts`. ONE member today. */
|
|
43
|
+
export type EntryAffordance = "granted-die";
|
|
29
44
|
/** A data-declared tab that renders a pool (one generic pool-tab per declaration). */
|
|
30
45
|
export interface TabDecl {
|
|
31
46
|
id: string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
weaponCodec
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-LDDCNPHD.js";
|
|
4
|
+
import "../chunk-HZA7OE7N.js";
|
|
5
|
+
import "../chunk-2DFENQIJ.js";
|
|
6
|
+
import "../chunk-UA5KS2PL.js";
|
|
6
7
|
export {
|
|
7
8
|
weaponCodec
|
|
8
9
|
};
|
|
@@ -30,5 +30,9 @@ export declare const weaponEntitySchema: z.ZodObject<{
|
|
|
30
30
|
2024: "2024";
|
|
31
31
|
}>;
|
|
32
32
|
entries: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
33
|
+
rendering_hint: z.ZodOptional<z.ZodString>;
|
|
34
|
+
has_fluff: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
has_fluff_images: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
33
37
|
raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
34
38
|
}, z.core.$loose>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Edition } from "@archivist-gg/dnd5e/types/edition";
|
|
2
|
+
import type { imageField } from "@archivist-gg/dnd5e/schemas/entity-extras-schema";
|
|
3
|
+
import type { z } from "zod";
|
|
2
4
|
export type WeaponCategory = "simple-melee" | "simple-ranged" | "martial-melee" | "martial-ranged" | "natural" | string;
|
|
3
5
|
export type DamageType = "acid" | "bludgeoning" | "cold" | "fire" | "force" | "lightning" | "necrotic" | "piercing" | "poison" | "psychic" | "radiant" | "slashing" | "thunder";
|
|
4
6
|
export type ConditionalProperty = {
|
|
@@ -32,5 +34,11 @@ export interface WeaponEntity {
|
|
|
32
34
|
page?: number;
|
|
33
35
|
edition: Edition;
|
|
34
36
|
entries?: unknown[];
|
|
37
|
+
/** Carried as the empty string on every converter weapon carrier today (98). */
|
|
38
|
+
rendering_hint?: string;
|
|
39
|
+
has_fluff?: boolean;
|
|
40
|
+
has_fluff_images?: boolean;
|
|
41
|
+
/** One wikilink, or an array for >= 2 fluff images (images-ON emit). */
|
|
42
|
+
image?: z.infer<typeof imageField>;
|
|
35
43
|
raw?: Record<string, unknown>;
|
|
36
44
|
}
|
package/package.json
CHANGED
package/dist/chunk-5XUXXAQJ.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// src/pc/pc.table-column.ts
|
|
2
|
-
function readTableColumn(table, level, keys) {
|
|
3
|
-
var _a;
|
|
4
|
-
const cols = (_a = table == null ? void 0 : table[level]) == null ? void 0 : _a.columns;
|
|
5
|
-
if (!cols) return null;
|
|
6
|
-
for (const k of keys) {
|
|
7
|
-
const raw = cols[k];
|
|
8
|
-
if (raw === void 0 || raw === null) continue;
|
|
9
|
-
const n = typeof raw === "number" ? raw : parseInt(String(raw), 10);
|
|
10
|
-
if (!Number.isNaN(n)) return n;
|
|
11
|
-
}
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
function numericColumnsAt(table, level) {
|
|
15
|
-
var _a;
|
|
16
|
-
const out = {};
|
|
17
|
-
const cols = (_a = table == null ? void 0 : table[level]) == null ? void 0 : _a.columns;
|
|
18
|
-
if (!cols) return out;
|
|
19
|
-
for (const [k, raw] of Object.entries(cols)) {
|
|
20
|
-
if (raw === void 0 || raw === null) continue;
|
|
21
|
-
const n = typeof raw === "number" ? raw : parseInt(String(raw), 10);
|
|
22
|
-
if (!Number.isNaN(n)) out[k] = n;
|
|
23
|
-
}
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export {
|
|
28
|
-
readTableColumn,
|
|
29
|
-
numericColumnsAt
|
|
30
|
-
};
|
package/dist/chunk-7P65Q426.js
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
// src/monster/monster.parser.ts
|
|
2
|
-
import { parseYaml, toStringSafe } from "@archivist-gg/core";
|
|
3
|
-
var VALID_RECHARGE_TYPES = /* @__PURE__ */ new Set([
|
|
4
|
-
"recharge_on_roll",
|
|
5
|
-
"per_day",
|
|
6
|
-
"per_short_rest",
|
|
7
|
-
"per_long_rest"
|
|
8
|
-
]);
|
|
9
|
-
function parseMonster(source) {
|
|
10
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
11
|
-
const result = parseYaml(source, ["name"]);
|
|
12
|
-
if (!result.success) return result;
|
|
13
|
-
const raw = result.data;
|
|
14
|
-
const monster = {
|
|
15
|
-
name: toStringSafe(raw.name)
|
|
16
|
-
};
|
|
17
|
-
if (raw.size != null) monster.size = toStringSafe(raw.size);
|
|
18
|
-
if (raw.type != null) monster.type = toStringSafe(raw.type);
|
|
19
|
-
if (raw.subtype != null) monster.subtype = toStringSafe(raw.subtype);
|
|
20
|
-
if (raw.alignment != null) monster.alignment = toStringSafe(raw.alignment);
|
|
21
|
-
if (raw.cr != null) monster.cr = toStringSafe(raw.cr);
|
|
22
|
-
if (Array.isArray(raw.ac)) {
|
|
23
|
-
monster.ac = raw.ac.map((entry) => ({
|
|
24
|
-
ac: Number(entry.ac),
|
|
25
|
-
from: Array.isArray(entry.from) ? entry.from.map(String) : void 0
|
|
26
|
-
}));
|
|
27
|
-
}
|
|
28
|
-
if (raw.hp && typeof raw.hp === "object") {
|
|
29
|
-
const hp = raw.hp;
|
|
30
|
-
monster.hp = {
|
|
31
|
-
average: Number(hp.average),
|
|
32
|
-
formula: hp.formula != null ? toStringSafe(hp.formula) : void 0
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
if (raw.speed && typeof raw.speed === "object") {
|
|
36
|
-
const speed = raw.speed;
|
|
37
|
-
monster.speed = {};
|
|
38
|
-
for (const key of ["walk", "fly", "swim", "climb", "burrow"]) {
|
|
39
|
-
if (speed[key] != null) monster.speed[key] = Number(speed[key]);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (raw.abilities && typeof raw.abilities === "object") {
|
|
43
|
-
const ab = raw.abilities;
|
|
44
|
-
monster.abilities = {
|
|
45
|
-
str: Number((_a = ab.str) != null ? _a : 10),
|
|
46
|
-
dex: Number((_b = ab.dex) != null ? _b : 10),
|
|
47
|
-
con: Number((_c = ab.con) != null ? _c : 10),
|
|
48
|
-
int: Number((_d = ab.int) != null ? _d : 10),
|
|
49
|
-
wis: Number((_e = ab.wis) != null ? _e : 10),
|
|
50
|
-
cha: Number((_f = ab.cha) != null ? _f : 10)
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
if (raw.saves && typeof raw.saves === "object") {
|
|
54
|
-
const saves = {};
|
|
55
|
-
for (const [key, val] of Object.entries(raw.saves)) {
|
|
56
|
-
saves[key] = Number(val);
|
|
57
|
-
}
|
|
58
|
-
monster.saves = saves;
|
|
59
|
-
}
|
|
60
|
-
if (raw.skills && typeof raw.skills === "object") {
|
|
61
|
-
const skills = {};
|
|
62
|
-
for (const [key, val] of Object.entries(raw.skills)) {
|
|
63
|
-
skills[key] = Number(val);
|
|
64
|
-
}
|
|
65
|
-
monster.skills = skills;
|
|
66
|
-
}
|
|
67
|
-
if (Array.isArray(raw.senses)) monster.senses = raw.senses.map(String);
|
|
68
|
-
if (raw.passive_perception != null) monster.passive_perception = Number(raw.passive_perception);
|
|
69
|
-
if (Array.isArray(raw.languages)) monster.languages = raw.languages.map(String);
|
|
70
|
-
if (Array.isArray(raw.damage_vulnerabilities)) monster.damage_vulnerabilities = raw.damage_vulnerabilities.map(String);
|
|
71
|
-
if (Array.isArray(raw.damage_resistances)) monster.damage_resistances = raw.damage_resistances.map(String);
|
|
72
|
-
if (Array.isArray(raw.damage_immunities)) monster.damage_immunities = raw.damage_immunities.map(String);
|
|
73
|
-
if (Array.isArray(raw.condition_immunities)) monster.condition_immunities = raw.condition_immunities.map(String);
|
|
74
|
-
const parseAttack = (raw2) => {
|
|
75
|
-
const a = {
|
|
76
|
-
name: toStringSafe(raw2.name),
|
|
77
|
-
type: toStringSafe(raw2.type)
|
|
78
|
-
};
|
|
79
|
-
if (typeof raw2.bonus === "number") a.bonus = raw2.bonus;
|
|
80
|
-
if (typeof raw2.damage === "string") a.damage = raw2.damage;
|
|
81
|
-
if (typeof raw2.damage_type === "string") a.damage_type = raw2.damage_type;
|
|
82
|
-
if (typeof raw2.action === "string") a.action = raw2.action;
|
|
83
|
-
if (Array.isArray(raw2.properties)) a.properties = raw2.properties.map(String);
|
|
84
|
-
if (raw2.range && typeof raw2.range === "object") {
|
|
85
|
-
const r = raw2.range;
|
|
86
|
-
a.range = {};
|
|
87
|
-
if (typeof r.normal === "number") a.range.normal = r.normal;
|
|
88
|
-
if (typeof r.long === "number") a.range.long = r.long;
|
|
89
|
-
if (typeof r.reach === "number") a.range.reach = r.reach;
|
|
90
|
-
}
|
|
91
|
-
if (raw2.extra_damage && typeof raw2.extra_damage === "object") {
|
|
92
|
-
const ed = raw2.extra_damage;
|
|
93
|
-
if (typeof ed.dice === "string" && typeof ed.type === "string") {
|
|
94
|
-
a.extra_damage = { dice: ed.dice, type: ed.type };
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (typeof raw2.condition === "string") a.condition = raw2.condition;
|
|
98
|
-
return a;
|
|
99
|
-
};
|
|
100
|
-
const parseFeatures = (arr) => {
|
|
101
|
-
if (!Array.isArray(arr)) return void 0;
|
|
102
|
-
return arr.map((f) => {
|
|
103
|
-
const feature = {
|
|
104
|
-
name: toStringSafe(f.name),
|
|
105
|
-
// Always set entries to an array so downstream renderers/editors
|
|
106
|
-
// (which call .join/.map directly) keep working.
|
|
107
|
-
entries: Array.isArray(f.entries) ? f.entries.map(String) : []
|
|
108
|
-
};
|
|
109
|
-
if (typeof f.description === "string") feature.description = f.description;
|
|
110
|
-
if (Array.isArray(f.attacks)) {
|
|
111
|
-
feature.attacks = f.attacks.map(parseAttack);
|
|
112
|
-
}
|
|
113
|
-
if (typeof f.action === "string") feature.action = f.action;
|
|
114
|
-
if (f.recharge && typeof f.recharge === "object") {
|
|
115
|
-
const r = f.recharge;
|
|
116
|
-
if (typeof r.type === "string" && VALID_RECHARGE_TYPES.has(r.type) && typeof r.param === "number") {
|
|
117
|
-
feature.recharge = {
|
|
118
|
-
type: r.type,
|
|
119
|
-
param: r.param
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return feature;
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
monster.traits = parseFeatures(raw.traits);
|
|
127
|
-
monster.actions = parseFeatures(raw.actions);
|
|
128
|
-
monster.reactions = parseFeatures(raw.reactions);
|
|
129
|
-
const legendaryArrayRaw = Array.isArray(raw.legendary_actions) ? raw.legendary_actions : raw.legendary;
|
|
130
|
-
monster.legendary_actions = parseFeatures(legendaryArrayRaw);
|
|
131
|
-
if (raw.legendary_action_uses != null) {
|
|
132
|
-
monster.legendary_action_uses = Number(raw.legendary_action_uses);
|
|
133
|
-
} else if (raw.legendary_actions != null && !Array.isArray(raw.legendary_actions) && typeof raw.legendary_actions !== "object") {
|
|
134
|
-
monster.legendary_action_uses = Number(raw.legendary_actions);
|
|
135
|
-
}
|
|
136
|
-
if (raw.legendary_resistance != null) monster.legendary_resistance = Number(raw.legendary_resistance);
|
|
137
|
-
if (raw.columns != null) monster.columns = Number(raw.columns);
|
|
138
|
-
if (!monster.legendary_resistance && monster.traits) {
|
|
139
|
-
const lrIndex = monster.traits.findIndex(
|
|
140
|
-
(t) => {
|
|
141
|
-
var _a2;
|
|
142
|
-
return /^Legendary Resistance\s*\(/i.test((_a2 = t.name) != null ? _a2 : "");
|
|
143
|
-
}
|
|
144
|
-
);
|
|
145
|
-
if (lrIndex !== -1) {
|
|
146
|
-
const match = (_g = monster.traits[lrIndex].name) == null ? void 0 : _g.match(/\((\d+)\/Day\)/i);
|
|
147
|
-
if (match) {
|
|
148
|
-
monster.legendary_resistance = parseInt(match[1], 10);
|
|
149
|
-
monster.traits.splice(lrIndex, 1);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return { success: true, data: monster };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export {
|
|
157
|
-
parseMonster
|
|
158
|
-
};
|
package/dist/chunk-7TEK5KK7.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
// src/types/choice.ts
|
|
2
|
-
var ALL_SKILL_SLUGS = [
|
|
3
|
-
"acrobatics",
|
|
4
|
-
"animal-handling",
|
|
5
|
-
"arcana",
|
|
6
|
-
"athletics",
|
|
7
|
-
"deception",
|
|
8
|
-
"history",
|
|
9
|
-
"insight",
|
|
10
|
-
"intimidation",
|
|
11
|
-
"investigation",
|
|
12
|
-
"medicine",
|
|
13
|
-
"nature",
|
|
14
|
-
"perception",
|
|
15
|
-
"performance",
|
|
16
|
-
"persuasion",
|
|
17
|
-
"religion",
|
|
18
|
-
"sleight-of-hand",
|
|
19
|
-
"stealth",
|
|
20
|
-
"survival"
|
|
21
|
-
];
|
|
22
|
-
var STANDARD_LANGUAGES = [
|
|
23
|
-
"common",
|
|
24
|
-
"dwarvish",
|
|
25
|
-
"elvish",
|
|
26
|
-
"giant",
|
|
27
|
-
"gnomish",
|
|
28
|
-
"goblin",
|
|
29
|
-
"halfling",
|
|
30
|
-
"orc"
|
|
31
|
-
];
|
|
32
|
-
var EXOTIC_LANGUAGES = [
|
|
33
|
-
"abyssal",
|
|
34
|
-
"celestial",
|
|
35
|
-
"deep-speech",
|
|
36
|
-
"draconic",
|
|
37
|
-
"infernal",
|
|
38
|
-
"primordial",
|
|
39
|
-
"sylvan",
|
|
40
|
-
"undercommon"
|
|
41
|
-
];
|
|
42
|
-
var ALL_LANGUAGES = [...STANDARD_LANGUAGES, ...EXOTIC_LANGUAGES];
|
|
43
|
-
|
|
44
|
-
export {
|
|
45
|
-
ALL_SKILL_SLUGS,
|
|
46
|
-
STANDARD_LANGUAGES,
|
|
47
|
-
EXOTIC_LANGUAGES,
|
|
48
|
-
ALL_LANGUAGES
|
|
49
|
-
};
|