@archivist-gg/dnd5e 0.3.24 → 0.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/background/background.codec.js +1 -1
  2. package/dist/background/background.parser.js +1 -1
  3. package/dist/background/background.schema.js +1 -1
  4. package/dist/{chunk-6LCNV26D.js → chunk-4SYAKWY4.js} +1 -1
  5. package/dist/{chunk-RL4VY2AL.js → chunk-5XDCM6YK.js} +1 -1
  6. package/dist/{chunk-HR5MKCP2.js → chunk-6R46KYGU.js} +1 -1
  7. package/dist/{chunk-XQMKH4R4.js → chunk-72PRMZRD.js} +1 -1
  8. package/dist/chunk-757KM22B.js +1 -0
  9. package/dist/chunk-CCAVZANF.js +1 -0
  10. package/dist/{chunk-A7H6LX47.js → chunk-CEHL7PPC.js} +1 -1
  11. package/dist/{chunk-BPKG6RZ7.js → chunk-CNMHADNV.js} +1 -1
  12. package/dist/{chunk-BGX36NPE.js → chunk-CSTAQQGX.js} +1 -1
  13. package/dist/{chunk-OTFNINUY.js → chunk-DTB7YBMZ.js} +1 -1
  14. package/dist/{chunk-7UPYRKMF.js → chunk-E3MS4M3N.js} +1 -1
  15. package/dist/{chunk-5FEXHY4U.js → chunk-E7KFJLDR.js} +1 -1
  16. package/dist/{chunk-RDXQAZBA.js → chunk-EPA24PVZ.js} +1 -1
  17. package/dist/{chunk-TLXFGGWH.js → chunk-ETDMOGFO.js} +1 -1
  18. package/dist/chunk-GD7WRCNH.js +1 -0
  19. package/dist/{chunk-GIOV6JW7.js → chunk-GGQDQSIF.js} +1 -1
  20. package/dist/{chunk-334WLI7V.js → chunk-GIQLIBC7.js} +1 -1
  21. package/dist/{chunk-QFIGPOFW.js → chunk-HX7WBOKR.js} +1 -1
  22. package/dist/chunk-J3RP5C7L.js +1 -0
  23. package/dist/chunk-J5GL6FLP.js +1 -0
  24. package/dist/{chunk-PZUPZBTN.js → chunk-KEXSF3CH.js} +1 -1
  25. package/dist/{chunk-N3RYJ7RE.js → chunk-L2DXF7YS.js} +1 -1
  26. package/dist/{chunk-KBFSJ5WE.js → chunk-LHH5XSEA.js} +1 -1
  27. package/dist/{chunk-V6NQ547U.js → chunk-NIWLD33X.js} +1 -1
  28. package/dist/{chunk-2LCGKNVM.js → chunk-NU2Z7MTS.js} +1 -1
  29. package/dist/{chunk-I4O2FIDT.js → chunk-NYPH7RQN.js} +1 -1
  30. package/dist/{chunk-WUHTSLG4.js → chunk-NYTR6NJS.js} +1 -1
  31. package/dist/{chunk-7J5BNH2D.js → chunk-ONCXJMJM.js} +1 -1
  32. package/dist/{chunk-IOCJIWCV.js → chunk-OTRH62HY.js} +1 -1
  33. package/dist/{chunk-NI364WV7.js → chunk-PFQPP77Q.js} +1 -1
  34. package/dist/{chunk-DY6FVAGA.js → chunk-PKIMOVQG.js} +1 -1
  35. package/dist/{chunk-7AKJBRBD.js → chunk-RHIEOYDX.js} +1 -1
  36. package/dist/{chunk-DZKSXSJF.js → chunk-SFK57JAA.js} +1 -1
  37. package/dist/{chunk-KZDDFG4O.js → chunk-VVJXZZ4Z.js} +1 -1
  38. package/dist/{chunk-QBA757AU.js → chunk-WAUNLUFQ.js} +1 -1
  39. package/dist/{chunk-RQGTBHJW.js → chunk-XPF53K54.js} +1 -1
  40. package/dist/{chunk-6ASJ3MVB.js → chunk-ZS5BMNXC.js} +1 -1
  41. package/dist/chunk-ZVL5FXXO.js +1 -0
  42. package/dist/class/class.codec.js +1 -1
  43. package/dist/class/class.parser.js +1 -1
  44. package/dist/class/class.schema.d.ts +2 -2
  45. package/dist/class/class.schema.js +1 -1
  46. package/dist/feat/feat.codec.js +1 -1
  47. package/dist/feat/feat.parser.js +1 -1
  48. package/dist/feat/feat.schema.d.ts +24 -3
  49. package/dist/feat/feat.schema.js +1 -1
  50. package/dist/index.js +9 -9
  51. package/dist/item/item.codec.js +1 -1
  52. package/dist/item/item.parser.js +1 -1
  53. package/dist/item/item.schema.d.ts +3 -0
  54. package/dist/item/item.schema.js +1 -1
  55. package/dist/item/item.types.d.ts +3 -0
  56. package/dist/monster/monster.parser.js +1 -1
  57. package/dist/monster/monster.schema.js +1 -1
  58. package/dist/optional-feature/optional-feature.codec.js +1 -1
  59. package/dist/optional-feature/optional-feature.parser.js +1 -1
  60. package/dist/optional-feature/optional-feature.schema.d.ts +23 -2
  61. package/dist/optional-feature/optional-feature.schema.js +1 -1
  62. package/dist/pc/pc.additional-spells.js +1 -1
  63. package/dist/pc/pc.amount-bindings.d.ts +3 -3
  64. package/dist/pc/pc.amount-bindings.js +1 -1
  65. package/dist/pc/pc.decision-engine.d.ts +6 -0
  66. package/dist/pc/pc.decision-engine.js +1 -1
  67. package/dist/pc/pc.entry-overrides.d.ts +19 -0
  68. package/dist/pc/pc.entry-overrides.js +1 -1
  69. package/dist/pc/pc.equipment.js +1 -1
  70. package/dist/pc/pc.feature-effects.d.ts +13 -8
  71. package/dist/pc/pc.feature-effects.js +1 -1
  72. package/dist/pc/pc.infusions.js +1 -1
  73. package/dist/pc/pc.item-effects.d.ts +1 -0
  74. package/dist/pc/pc.item-effects.js +1 -0
  75. package/dist/pc/pc.member-choices.js +1 -1
  76. package/dist/pc/pc.parser.js +1 -1
  77. package/dist/pc/pc.pools.js +1 -1
  78. package/dist/pc/pc.proficiencies.js +1 -1
  79. package/dist/pc/pc.proficiency-grants.d.ts +3 -1
  80. package/dist/pc/pc.recalc.d.ts +1 -0
  81. package/dist/pc/pc.recalc.js +1 -1
  82. package/dist/pc/pc.resolver.d.ts +9 -0
  83. package/dist/pc/pc.resolver.js +1 -1
  84. package/dist/pc/pc.resource-seed.js +1 -1
  85. package/dist/pc/pc.resources.js +1 -1
  86. package/dist/pc/pc.rest.js +1 -1
  87. package/dist/pc/pc.schema.d.ts +20 -0
  88. package/dist/pc/pc.schema.js +1 -1
  89. package/dist/pc/pc.speeds.d.ts +20 -3
  90. package/dist/pc/pc.spellcasting.js +1 -1
  91. package/dist/pc/pc.table-column.d.ts +3 -0
  92. package/dist/pc/pc.table-column.js +1 -1
  93. package/dist/pc/pc.types.d.ts +5 -0
  94. package/dist/race/race.codec.js +1 -1
  95. package/dist/race/race.parser.js +1 -1
  96. package/dist/race/race.schema.js +1 -1
  97. package/dist/schemas/choice-schema.js +1 -1
  98. package/dist/schemas/feature-effect-schema.d.ts +23 -2
  99. package/dist/schemas/feature-effect-schema.js +1 -1
  100. package/dist/schemas/feature-schema.js +1 -1
  101. package/dist/subclass/subclass.codec.js +1 -1
  102. package/dist/subclass/subclass.parser.js +1 -1
  103. package/dist/subclass/subclass.schema.js +1 -1
  104. package/dist/types/feature-effect.d.ts +8 -2
  105. package/package.json +1 -1
  106. package/dist/chunk-6IC53O3Q.js +0 -1
  107. package/dist/chunk-7LPKI27J.js +0 -1
  108. package/dist/chunk-HCK6IUB3.js +0 -1
  109. package/dist/chunk-IGVRLGLM.js +0 -1
  110. package/dist/chunk-MC6PLWRZ.js +0 -1
  111. package/dist/chunk-PQAVMK3T.js +0 -1
@@ -1 +1 @@
1
- import{backgroundCodec}from"../chunk-WUHTSLG4.js";import"../chunk-KZDDFG4O.js";import"../chunk-N3RYJ7RE.js";import"../chunk-TKIEPC6F.js";import"../chunk-KBFSJ5WE.js";import"../chunk-6IC53O3Q.js";import"../chunk-I26FHSI6.js";export{backgroundCodec};
1
+ import{backgroundCodec}from"../chunk-NYTR6NJS.js";import"../chunk-VVJXZZ4Z.js";import"../chunk-L2DXF7YS.js";import"../chunk-TKIEPC6F.js";import"../chunk-LHH5XSEA.js";import"../chunk-ZVL5FXXO.js";import"../chunk-I26FHSI6.js";export{backgroundCodec};
@@ -1 +1 @@
1
- import{parseBackground}from"../chunk-KZDDFG4O.js";import"../chunk-N3RYJ7RE.js";import"../chunk-TKIEPC6F.js";import"../chunk-KBFSJ5WE.js";import"../chunk-6IC53O3Q.js";import"../chunk-I26FHSI6.js";export{parseBackground};
1
+ import{parseBackground}from"../chunk-VVJXZZ4Z.js";import"../chunk-L2DXF7YS.js";import"../chunk-TKIEPC6F.js";import"../chunk-LHH5XSEA.js";import"../chunk-ZVL5FXXO.js";import"../chunk-I26FHSI6.js";export{parseBackground};
@@ -1 +1 @@
1
- import{backgroundEntitySchema,langProfSchema}from"../chunk-N3RYJ7RE.js";import"../chunk-TKIEPC6F.js";import"../chunk-KBFSJ5WE.js";import"../chunk-6IC53O3Q.js";import"../chunk-I26FHSI6.js";export{backgroundEntitySchema,langProfSchema};
1
+ import{backgroundEntitySchema,langProfSchema}from"../chunk-L2DXF7YS.js";import"../chunk-TKIEPC6F.js";import"../chunk-LHH5XSEA.js";import"../chunk-ZVL5FXXO.js";import"../chunk-I26FHSI6.js";export{backgroundEntitySchema,langProfSchema};
@@ -1 +1 @@
1
- import{featureSchema}from"./chunk-V6NQ547U.js";import{choiceSchema}from"./chunk-KBFSJ5WE.js";import{additionalSpellsEntrySchema,imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var sizeEnum=z.enum(["tiny","small","medium","large","huge"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var speedSchema=z.object({walk:z.number().int().nonnegative().optional(),fly:z.number().int().nonnegative().optional(),swim:z.number().int().nonnegative().optional(),climb:z.number().int().nonnegative().optional(),burrow:z.number().int().nonnegative().optional(),hover:z.boolean().optional()});var visionSchema=z.object({darkvision:z.number().int().nonnegative().optional(),blindsight:z.number().int().nonnegative().optional(),tremorsense:z.number().int().nonnegative().optional(),truesight:z.number().int().nonnegative().optional()});var fixedAsiSchema=z.object({ability:abilityEnum,amount:z.number().int()});var choiceAsiSchema=z.object({choose:z.number().int().positive(),pool:z.array(abilityEnum).nonempty(),amount:z.number().int()});var asiSchema=z.union([fixedAsiSchema,choiceAsiSchema]);var languagesSchema=z.object({fixed:z.array(z.string()),choice:z.object({count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])}).optional()});var raceEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),size:sizeEnum,speed:speedSchema,ability_score_increases:z.array(asiSchema),age:z.string(),alignment:z.string(),vision:visionSchema,languages:languagesSchema,variant_label:z.string().min(1),traits:z.array(featureSchema),choices:z.array(choiceSchema).optional(),subspecies_of:z.string().regex(wikilinkRegex).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),creature_type:z.array(z.string().min(1)).optional(),creature_type_tags:z.array(z.string().min(1)).optional(),additional_spells:z.union([z.array(additionalSpellsEntrySchema),additionalSpellsEntrySchema]).optional(),trait_tags:z.unknown().optional(),lineage:z.unknown().optional(),height_and_weight:z.unknown().optional(),sound_clip:z.unknown().optional(),image:imageField});export{fixedAsiSchema,raceEntitySchema};
1
+ import{featureSchema}from"./chunk-NIWLD33X.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{additionalSpellsEntrySchema,imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var sizeEnum=z.enum(["tiny","small","medium","large","huge"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var speedSchema=z.object({walk:z.number().int().nonnegative().optional(),fly:z.number().int().nonnegative().optional(),swim:z.number().int().nonnegative().optional(),climb:z.number().int().nonnegative().optional(),burrow:z.number().int().nonnegative().optional(),hover:z.boolean().optional()});var visionSchema=z.object({darkvision:z.number().int().nonnegative().optional(),blindsight:z.number().int().nonnegative().optional(),tremorsense:z.number().int().nonnegative().optional(),truesight:z.number().int().nonnegative().optional()});var fixedAsiSchema=z.object({ability:abilityEnum,amount:z.number().int()});var choiceAsiSchema=z.object({choose:z.number().int().positive(),pool:z.array(abilityEnum).nonempty(),amount:z.number().int()});var asiSchema=z.union([fixedAsiSchema,choiceAsiSchema]);var languagesSchema=z.object({fixed:z.array(z.string()),choice:z.object({count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])}).optional()});var raceEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),size:sizeEnum,speed:speedSchema,ability_score_increases:z.array(asiSchema),age:z.string(),alignment:z.string(),vision:visionSchema,languages:languagesSchema,variant_label:z.string().min(1),traits:z.array(featureSchema),choices:z.array(choiceSchema).optional(),subspecies_of:z.string().regex(wikilinkRegex).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),creature_type:z.array(z.string().min(1)).optional(),creature_type_tags:z.array(z.string().min(1)).optional(),additional_spells:z.union([z.array(additionalSpellsEntrySchema),additionalSpellsEntrySchema]).optional(),trait_tags:z.unknown().optional(),lineage:z.unknown().optional(),height_and_weight:z.unknown().optional(),sound_clip:z.unknown().optional(),image:imageField});export{fixedAsiSchema,raceEntitySchema};
@@ -1 +1 @@
1
- import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var tier1Conditions=[z.object({kind:z.literal("no_armor")}),z.object({kind:z.literal("no_shield")}),z.object({kind:z.literal("wielding_two_handed")}),z.object({kind:z.literal("is_class"),value:z.string()}),z.object({kind:z.literal("is_race"),value:z.string()}),z.object({kind:z.literal("is_subclass"),value:z.string()})];var tier2Conditions=[z.object({kind:z.literal("vs_creature_type"),value:z.string()}),z.object({kind:z.literal("vs_attack_type"),value:z.enum(["ranged","melee"])}),z.object({kind:z.literal("on_attack_type"),value:z.enum(["ranged","melee"])}),z.object({kind:z.literal("with_weapon_property"),value:z.string()}),z.object({kind:z.literal("vs_spell_save")})];var tier3Conditions=[z.object({kind:z.literal("lighting"),value:z.enum(["dim","bright","daylight","darkness"])}),z.object({kind:z.literal("underwater")}),z.object({kind:z.literal("movement_state"),value:z.enum(["flying","swimming","climbing","mounted"])})];var tier4Conditions=[z.object({kind:z.literal("has_condition"),value:z.string()}),z.object({kind:z.literal("is_concentrating")}),z.object({kind:z.literal("bloodied")})];var rawCondition=z.object({kind:z.literal("raw"),text:z.string()});var conditionSchema=z.lazy(()=>z.discriminatedUnion("kind",[...tier1Conditions,...tier2Conditions,...tier3Conditions,...tier4Conditions,rawCondition,z.object({kind:z.literal("any_of"),conditions:z.array(conditionSchema)})]));var conditionalBonusSchema=z.object({value:z.number().int(),when:z.array(conditionSchema)});var numberOrConditional=z.union([z.number().int(),conditionalBonusSchema]);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var bonusesSchema=z.object({ac:numberOrConditional.optional(),weapon_attack:numberOrConditional.optional(),weapon_damage:numberOrConditional.optional(),spell_attack:numberOrConditional.optional(),spell_save_dc:numberOrConditional.optional(),saving_throws:numberOrConditional.optional(),spell_damage:numberOrConditional.optional(),ability_check:numberOrConditional.optional(),proficiency_bonus:numberOrConditional.optional(),saving_throw_concentration:numberOrConditional.optional(),ability_scores:z.object({static:z.object({str:z.number().int().optional(),dex:z.number().int().optional(),con:z.number().int().optional(),int:z.number().int().optional(),wis:z.number().int().optional(),cha:z.number().int().optional()}).optional(),bonus:z.object({str:numberOrConditional.optional(),dex:numberOrConditional.optional(),con:numberOrConditional.optional(),int:numberOrConditional.optional(),wis:numberOrConditional.optional(),cha:numberOrConditional.optional()}).optional(),choose:z.array(z.strictObject({from:z.array(abilityEnum),count:z.number().int().positive(),amount:z.number().int().optional()})).optional()}).optional(),speed:z.object({walk:numberOrConditional.optional(),fly:z.union([numberOrConditional,z.literal("walk")]).optional(),swim:numberOrConditional.optional(),climb:numberOrConditional.optional()}).optional()});var chargesSchema=z.object({max:z.number().int(),dice:z.string().optional(),recharge:z.string().optional(),recharge_amount:z.string().optional(),destroy_on_empty:z.object({roll:z.string(),threshold:z.number().int(),effect:z.string().optional()}).optional()});var attachedSpellsSchema=z.object({charges:z.record(z.string(),z.array(z.string())).optional(),daily:z.record(z.string(),z.array(z.string())).optional(),will:z.array(z.string()).optional(),rest:z.record(z.string(),z.array(z.string())).optional(),limited:z.record(z.string(),z.array(z.string())).optional(),other:z.array(z.string()).optional(),ability:z.string().optional(),ritual:z.array(z.string()).optional()});var attunementTagSchema=z.union([z.object({class:z.string(),subclass:z.string().optional(),alignment:z.union([z.string(),z.array(z.string())]).optional()}),z.object({alignment:z.union([z.string(),z.array(z.string())]),race:z.string().optional()}),z.object({race:z.string(),alignment:z.union([z.string(),z.array(z.string())]).optional()}),z.object({creature_type:z.string(),size:z.string().optional()}),z.object({spellcasting:z.boolean()}),z.object({background:z.string()}),z.object({psionics:z.boolean()}),z.object({int:z.number().int()}),z.object({skill_proficiency:z.array(z.string())}),z.object({language_proficiency:z.array(z.string())})]);var attunementCanonicalSchema=z.object({required:z.boolean(),restriction:z.string().optional(),tags:z.array(attunementTagSchema).optional()});var grantsSchema=z.object({proficiency:z.boolean().optional(),languages:z.union([z.boolean(),z.array(z.string())]).optional(),senses:z.object({darkvision:z.number().optional(),tremorsense:z.number().optional(),truesight:z.number().optional(),blindsight:z.number().optional()}).optional()});var containerCapacitySchema=z.strictObject({weight:z.array(z.number()).optional(),item:z.array(z.record(z.string(),z.number())).optional(),weightless:z.boolean().optional(),volume:z.array(z.number()).optional()});var containerSchema=z.object({capacity_weight:z.number().optional(),holds_items:z.boolean().optional(),pack_contents:z.array(z.string()).optional(),pack_atomic:z.boolean().optional(),capacity:containerCapacitySchema.optional()});var lightSchema=z.object({bright_radius:z.number(),dim_radius:z.number()});var lightEntrySchema=z.strictObject({bright:z.number().optional(),dim:z.number().optional(),shape:z.string().optional()});var itemEntitySchema=z.object({name:z.string().min(1),slug:z.string().optional(),type:z.string().optional(),rarity:z.string().optional(),base_item:z.string().optional(),bonuses:bonusesSchema.optional(),resist:z.array(z.string()).optional(),immune:z.array(z.string()).optional(),vulnerable:z.array(z.string()).optional(),condition_immune:z.array(z.string()).optional(),charges:z.union([chargesSchema,z.number().int().nonnegative()]).optional(),attached_spells:attachedSpellsSchema.optional(),attunement:z.union([attunementCanonicalSchema,z.boolean(),z.string()]).optional(),grants:grantsSchema.optional(),container:containerSchema.optional(),light:z.union([lightSchema,z.array(lightEntrySchema).nonempty()]).optional(),cursed:z.boolean().optional(),sentient:z.boolean().optional(),tattoo:z.boolean().optional(),focus:z.union([z.boolean(),z.string(),z.array(z.string())]).optional(),tier:z.enum(["major","minor"]).optional(),damage:z.union([z.object({dice:z.string(),type:z.string(),versatile_dice:z.string().optional()}),z.string()]).optional(),weapon_category:z.string().optional(),armor_category:z.string().optional(),weight:z.union([z.number(),z.string()]).optional(),cost:z.string().optional(),source:z.string().optional(),page:z.number().int().optional(),edition:z.string().optional(),description:z.string().optional(),entries:z.array(z.unknown()).optional(),effects:z.array(z.unknown()).optional(),damage_riders:z.array(z.object({amount:z.string(),damage_type:z.string(),applies_to:z.enum(["weapon","spell","all"]).optional(),condition:z.string().optional()})).optional(),scroll_level:z.number().optional(),unidentified:z.boolean().optional(),masked_category:z.string().optional(),modify_speed:z.strictObject({equal:z.record(z.string(),z.string()).optional(),static:z.record(z.string(),z.number()).optional(),multiply:z.record(z.string(),z.number()).optional(),bonus:z.record(z.string(),z.number()).optional()}).optional(),speed_on_use:z.boolean().optional(),rendering_hint:z.string().optional(),icon:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),image:imageField,raw:z.record(z.string(),z.unknown()).optional(),damage_dice:z.string().optional(),damage_type:z.string().optional(),properties:z.array(z.string()).optional(),mastery:z.array(z.string().min(1)).optional(),recharge:z.string().optional(),curse:z.boolean().optional()});export{conditionSchema,containerSchema,itemEntitySchema};
1
+ import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var tier1Conditions=[z.object({kind:z.literal("no_armor")}),z.object({kind:z.literal("no_shield")}),z.object({kind:z.literal("wielding_two_handed")}),z.object({kind:z.literal("is_class"),value:z.string()}),z.object({kind:z.literal("is_race"),value:z.string()}),z.object({kind:z.literal("is_subclass"),value:z.string()})];var tier2Conditions=[z.object({kind:z.literal("vs_creature_type"),value:z.string()}),z.object({kind:z.literal("vs_attack_type"),value:z.enum(["ranged","melee"])}),z.object({kind:z.literal("on_attack_type"),value:z.enum(["ranged","melee"])}),z.object({kind:z.literal("with_weapon_property"),value:z.string()}),z.object({kind:z.literal("vs_spell_save")})];var tier3Conditions=[z.object({kind:z.literal("lighting"),value:z.enum(["dim","bright","daylight","darkness"])}),z.object({kind:z.literal("underwater")}),z.object({kind:z.literal("movement_state"),value:z.enum(["flying","swimming","climbing","mounted"])})];var tier4Conditions=[z.object({kind:z.literal("has_condition"),value:z.string()}),z.object({kind:z.literal("is_concentrating")}),z.object({kind:z.literal("bloodied")})];var rawCondition=z.object({kind:z.literal("raw"),text:z.string()});var conditionSchema=z.lazy(()=>z.discriminatedUnion("kind",[...tier1Conditions,...tier2Conditions,...tier3Conditions,...tier4Conditions,rawCondition,z.object({kind:z.literal("any_of"),conditions:z.array(conditionSchema)})]));var conditionalBonusSchema=z.object({value:z.number().int(),when:z.array(conditionSchema)});var numberOrConditional=z.union([z.number().int(),conditionalBonusSchema]);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var bonusesSchema=z.object({ac:numberOrConditional.optional(),weapon_attack:numberOrConditional.optional(),weapon_damage:numberOrConditional.optional(),spell_attack:numberOrConditional.optional(),spell_save_dc:numberOrConditional.optional(),saving_throws:numberOrConditional.optional(),spell_damage:numberOrConditional.optional(),ability_check:numberOrConditional.optional(),proficiency_bonus:numberOrConditional.optional(),saving_throw_concentration:numberOrConditional.optional(),ability_scores:z.object({static:z.object({str:z.number().int().optional(),dex:z.number().int().optional(),con:z.number().int().optional(),int:z.number().int().optional(),wis:z.number().int().optional(),cha:z.number().int().optional()}).optional(),bonus:z.object({str:numberOrConditional.optional(),dex:numberOrConditional.optional(),con:numberOrConditional.optional(),int:numberOrConditional.optional(),wis:numberOrConditional.optional(),cha:numberOrConditional.optional()}).optional(),choose:z.array(z.strictObject({from:z.array(abilityEnum),count:z.number().int().positive(),amount:z.number().int().optional()})).optional()}).optional(),speed:z.object({walk:numberOrConditional.optional(),fly:z.union([numberOrConditional,z.literal("walk")]).optional(),swim:numberOrConditional.optional(),climb:numberOrConditional.optional()}).optional()});var chargesSchema=z.object({max:z.number().int(),dice:z.string().optional(),recharge:z.string().optional(),recharge_amount:z.string().optional(),destroy_on_empty:z.object({roll:z.string(),threshold:z.number().int(),effect:z.string().optional()}).optional()});var attachedSpellsSchema=z.object({charges:z.record(z.string(),z.array(z.string())).optional(),daily:z.record(z.string(),z.array(z.string())).optional(),will:z.array(z.string()).optional(),rest:z.record(z.string(),z.array(z.string())).optional(),limited:z.record(z.string(),z.array(z.string())).optional(),other:z.array(z.string()).optional(),ability:z.string().optional(),ritual:z.array(z.string()).optional()});var attunementTagSchema=z.union([z.object({class:z.string(),subclass:z.string().optional(),alignment:z.union([z.string(),z.array(z.string())]).optional()}),z.object({alignment:z.union([z.string(),z.array(z.string())]),race:z.string().optional()}),z.object({race:z.string(),alignment:z.union([z.string(),z.array(z.string())]).optional()}),z.object({creature_type:z.string(),size:z.string().optional()}),z.object({spellcasting:z.boolean()}),z.object({background:z.string()}),z.object({psionics:z.boolean()}),z.object({int:z.number().int()}),z.object({skill_proficiency:z.array(z.string())}),z.object({language_proficiency:z.array(z.string())})]);var attunementCanonicalSchema=z.object({required:z.boolean(),restriction:z.string().optional(),tags:z.array(attunementTagSchema).optional()});var grantsSchema=z.object({proficiency:z.boolean().optional(),languages:z.union([z.boolean(),z.array(z.string())]).optional(),senses:z.object({darkvision:z.number().optional(),tremorsense:z.number().optional(),truesight:z.number().optional(),blindsight:z.number().optional()}).optional()});var containerCapacitySchema=z.strictObject({weight:z.array(z.number()).optional(),item:z.array(z.record(z.string(),z.number())).optional(),weightless:z.boolean().optional(),volume:z.array(z.number()).optional()});var containerSchema=z.object({capacity_weight:z.number().optional(),holds_items:z.boolean().optional(),pack_contents:z.array(z.string()).optional(),pack_atomic:z.boolean().optional(),capacity:containerCapacitySchema.optional()});var lightSchema=z.object({bright_radius:z.number(),dim_radius:z.number()});var lightEntrySchema=z.strictObject({bright:z.number().optional(),dim:z.number().optional(),shape:z.string().optional()});var itemEntitySchema=z.object({name:z.string().min(1),slug:z.string().optional(),type:z.string().optional(),rarity:z.string().optional(),base_item:z.string().optional(),bonuses:bonusesSchema.optional(),resist:z.array(z.string()).optional(),immune:z.array(z.string()).optional(),vulnerable:z.array(z.string()).optional(),condition_immune:z.array(z.string()).optional(),charges:z.union([chargesSchema,z.number().int().nonnegative()]).optional(),attached_spells:attachedSpellsSchema.optional(),attunement:z.union([attunementCanonicalSchema,z.boolean(),z.string()]).optional(),grants:grantsSchema.optional(),container:containerSchema.optional(),light:z.union([lightSchema,z.array(lightEntrySchema).nonempty()]).optional(),cursed:z.boolean().optional(),sentient:z.boolean().optional(),tattoo:z.boolean().optional(),focus:z.union([z.boolean(),z.string(),z.array(z.string())]).optional(),tier:z.enum(["major","minor"]).optional(),damage:z.union([z.object({dice:z.string(),type:z.string(),versatile_dice:z.string().optional()}),z.string()]).optional(),weapon_category:z.string().optional(),armor_category:z.string().optional(),weight:z.union([z.number(),z.string()]).optional(),cost:z.string().optional(),source:z.string().optional(),page:z.number().int().optional(),edition:z.string().optional(),description:z.string().optional(),entries:z.array(z.unknown()).optional(),effects:z.array(z.unknown()).optional(),damage_riders:z.array(z.object({amount:z.string(),damage_type:z.string(),applies_to:z.enum(["weapon","spell","all"]).optional(),condition:z.string().optional()})).optional(),scroll_level:z.number().optional(),spell_charge_cost:z.number().int().nonnegative().optional(),spell_save_dc:z.number().int().positive().optional(),spell_attack_bonus:z.number().int().optional(),unidentified:z.boolean().optional(),masked_category:z.string().optional(),modify_speed:z.strictObject({equal:z.record(z.string(),z.string()).optional(),static:z.record(z.string(),z.number()).optional(),multiply:z.record(z.string(),z.number()).optional(),bonus:z.record(z.string(),z.number()).optional()}).optional(),speed_on_use:z.boolean().optional(),rendering_hint:z.string().optional(),icon:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),image:imageField,raw:z.record(z.string(),z.unknown()).optional(),damage_dice:z.string().optional(),damage_type:z.string().optional(),properties:z.array(z.string()).optional(),mastery:z.array(z.string().min(1)).optional(),recharge:z.string().optional(),curse:z.boolean().optional()});export{conditionSchema,containerSchema,itemEntitySchema};
@@ -1 +1 @@
1
- import{parseRace}from"./chunk-BPKG6RZ7.js";import yaml from"js-yaml";var raceCodec={parse(doc){return parseRace(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{raceCodec};
1
+ import{parseRace}from"./chunk-CNMHADNV.js";import yaml from"js-yaml";var raceCodec={parse(doc){return parseRace(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{raceCodec};
@@ -1 +1 @@
1
- import{parseItem}from"./chunk-7LPKI27J.js";import yaml from"js-yaml";var itemCodec={parse(doc){return parseItem(doc.body)},serialize(item){return yaml.dump(item,{lineWidth:-1,sortKeys:false})}};export{itemCodec};
1
+ import{parseItem}from"./chunk-757KM22B.js";import yaml from"js-yaml";var itemCodec={parse(doc){return parseItem(doc.body)},serialize(item){return yaml.dump(item,{lineWidth:-1,sortKeys:false})}};export{itemCodec};
@@ -0,0 +1 @@
1
+ import{itemEntitySchema}from"./chunk-5XDCM6YK.js";import{parseYaml}from"@archivist-gg/core";var KNOWN_KEYS=new Set(["name","slug","type","rarity","base_item","bonuses","resist","immune","vulnerable","condition_immune","charges","attached_spells","attunement","grants","container","light","cursed","sentient","focus","tier","tattoo","damage","weapon_category","armor_category","weight","cost","source","page","edition","description","entries","effects","damage_riders","raw","scroll_level","spell_charge_cost","spell_save_dc","spell_attack_bonus","unidentified","masked_category","modify_speed","rendering_hint","icon","has_fluff","has_fluff_images","image","speed_on_use","mastery","damage_dice","damage_type","properties","recharge","curse"]);function migrateAttunement(raw){const legacy=raw.requires_attunement;if(raw.attunement===void 0&&typeof legacy==="boolean"){raw.attunement={required:legacy}}if(legacy!==void 0){delete raw.requires_attunement}const v=raw.attunement;if(v===void 0||v===null)return;if(typeof v==="object"&&!Array.isArray(v))return;if(typeof v==="boolean"){raw.attunement={required:v}}else if(typeof v==="string"){raw.attunement={required:true,restriction:v}}}function parseItem(source){var _a;const raw=parseYaml(source,["name"]);if(!raw.success)return raw;migrateAttunement(raw.data);const result=itemEntitySchema.safeParse(raw.data);if(!result.success){return{success:false,error:`item schema validation failed: ${result.error.message}`}}const entity=result.data;const extras={};for(const[k,v]of Object.entries(raw.data)){if(!KNOWN_KEYS.has(k))extras[k]=v}if(Object.keys(extras).length>0){entity.raw={...(_a=entity.raw)!=null?_a:{},...extras}}return{success:true,data:entity}}export{parseItem};
@@ -0,0 +1 @@
1
+ import{spellSource}from"./chunk-PZ3ZZ5H5.js";import{resourceLevelFor}from"./chunk-KEXSF3CH.js";import{addToRoll}from"./chunk-VIP3FH2O.js";import{baseClassName}from"./chunk-CAPYNIGK.js";function ownerClassSlug(source,resolved){var _a,_b,_c;if(!source)return null;if(source.kind==="class")return source.slug;if(source.kind==="subclass")return(_c=(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_a.entity)==null?void 0:_b.slug)!=null?_c:null;if(source.kind==="feat"&&source.via){if(source.via.kind==="class")return source.via.slug;if(source.via.kind==="pool")return source.via.classSlug}return null}function casterRow(classSlug,derived){var _a,_b;const rows=(_a=derived.spellcastingClasses)!=null?_a:[];const own=classSlug?rows.find(c=>baseClassName(c.classSlug)===baseClassName(classSlug)):void 0;return(_b=own!=null?own:rows[0])!=null?_b:null}function amountBindingsFor(owner,resolved,derived){var _a,_b;const classSlug=ownerClassSlug(owner,resolved);const classSource=classSlug?{kind:"class",slug:classSlug,level:0}:owner;const classLevel=classSource?resourceLevelFor(classSource,resolved):resolved.totalLevel;const row=casterRow(classSlug,derived);const className=classSlug?(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===classSlug}))==null?void 0:_a.entity)==null?void 0:_b.name:void 0;const classNames=resolved.classes.map(c=>{var _a2;return(_a2=c.entity)==null?void 0:_a2.name}).filter(n=>typeof n==="string"&&n.length>0);return{level:resolved.totalLevel,class_level:classLevel,prof:derived.proficiencyBonus,str_mod:derived.mods.str,dex_mod:derived.mods.dex,con_mod:derived.mods.con,int_mod:derived.mods.int,wis_mod:derived.mods.wis,cha_mod:derived.mods.cha,columns:{},...row?{spell_mod:derived.mods[row.ability],spell_dc:row.saveDC}:{},...className?{class_name:className}:{},...classNames.length>0?{class_names:classNames}:{}}}function spellcastingFor(spell,derived){var _a,_b,_c,_d,_e;const caster=casterOf(spell,derived);const own=spell.itemCasting;if(!own)return caster;return{ability:(_a=caster==null?void 0:caster.ability)!=null?_a:null,saveDC:(_c=(_b=own.saveDC)!=null?_b:caster==null?void 0:caster.saveDC)!=null?_c:0,attackBonus:(_e=(_d=own.attackBonus)!=null?_d:caster==null?void 0:caster.attackBonus)!=null?_e:0}}function casterOf(spell,derived){var _a,_b;if((spellSource(spell).ownAbility||spell.classSlug==null)&&spell.ability){const own=(_a=derived.abilitySpellcasting)==null?void 0:_a[spell.ability];if(own)return{ability:spell.ability,saveDC:own.saveDC,attackBonus:own.attackBonus}}const row=casterRow((_b=spell.classSlug)!=null?_b:null,derived);return row?{ability:row.ability,saveDC:row.saveDC,attackBonus:row.attackBonus}:null}function spellAmountBindings(spell,resolved,derived){const cast=spellcastingFor(spell,derived);const base=amountBindingsFor(spell.classSlug?{kind:"class",slug:spell.classSlug,level:0}:void 0,resolved,derived);const out={...base};delete out.spell_mod;delete out.spell_dc;if(!cast)return out;return cast.ability?{...out,spell_mod:derived.mods[cast.ability],spell_dc:cast.saveDC}:{...out,spell_dc:cast.saveDC}}function spellRollBonus(spell){var _a;const roll=(_a=spell.damage_roll)==null?void 0:_a.trim();const text=spell.description;if(!roll||!text)return null;const esc=roll.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");const re=new RegExp(`(?<![\\w])${esc}\`?\\s*(?:plus|\\+)\\s*your\\s+spellcasting\\s+(?:ability\\s+)?modifier`,"i");return re.test(text)?"{spell_mod}":null}function foldsIntoRoll(rider,spell){var _a,_b;const own=((_b=(_a=spell.entity.damage)==null?void 0:_a.types)!=null?_b:[]).map(t=>t.toLowerCase());return!rider.condition&&(!rider.damage_type||own.includes(rider.damage_type.toLowerCase()))}var reaching=(spell,derived)=>{var _a;return((_a=derived.spellDamageRiders)!=null?_a:[]).filter(r=>{var _a2;return(_a2=r.spells)==null?void 0:_a2.includes(spell.slug)})};function addSpellDamageRiders(roll,spell,derived){return addToRoll(roll,reaching(spell,derived).filter(r=>foldsIntoRoll(r,spell)).map(r=>r.amount))}function spellDamageRiderLines(spell,derived){return reaching(spell,derived).filter(r=>!foldsIntoRoll(r,spell)).map(r=>({amount:r.amount,...r.damage_type?{damage_type:r.damage_type}:{},...r.source?{source:r.source}:{},...r.condition?{condition:r.condition}:{}}))}export{ownerClassSlug,amountBindingsFor,spellcastingFor,spellAmountBindings,spellRollBonus,addSpellDamageRiders,spellDamageRiderLines};
@@ -1 +1 @@
1
- import{RACE_STRUCTURAL_PSEUDO}from"./chunk-UBUKCRZ3.js";import{heldPicks}from"./chunk-DY6FVAGA.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{memoByRevision}from"./chunk-QMEKQTUT.js";import{slugify}from"./chunk-63YJPWTM.js";import{mirrorSpellShapes}from"./chunk-4KVVAENP.js";import{ABILITY_KEYS}from"./chunk-EVT7MGAC.js";var entriesOf=a=>Array.isArray(a)?a:a&&typeof a==="object"?[a]:[];var editionOf=x=>{const e=x==null?void 0:x.edition;return typeof e==="string"?e:void 0};var prefixOf=slug=>{var _a;return(_a=slug.split("_")[0])!=null?_a:slug};function normalizeSpellRef(ref){var _a,_b,_c;if(typeof ref!=="string")return null;let s=ref.trim();const wl=/^\[\[(.+)\]\]$/.exec(s);if(wl){const target=(_a=wl[1].split("|")[0])!=null?_a:"";const tail=(_b=target.split("/").pop())!=null?_b:target;const w=slugify(tail.replace(/#.*$/,"").trim());return w.length>0?w:null}s=s.replace(/#.*$/,"");s=(_c=s.split("|")[0])!=null?_c:"";const out=slugify(s.trim());return out.length>0?out:null}function buildSpellNameIndex(entities){return memoByRevision(SPELL_NAME_INDEX,entities,()=>spellNameIndexOf(entities))}var SPELL_NAME_INDEX=new WeakMap;function spellNameIndexOf(entities){var _a;const byName=new Map;for(const e of entities.search("","spell",Number.POSITIVE_INFINITY)){const raw=e.data.name;const key=slugify(typeof raw==="string"?raw:e.name);const list=(_a=byName.get(key))!=null?_a:[];list.push(e);byName.set(key,list)}return{byName}}function resolveSpellByName(opts){var _a;const{entities,index,nameSlug,carrierSlug,carrierEdition,alreadyCollected}=opts;const own=alreadyCollected.find(s=>{var _a2;return slugify(String((_a2=s.entity.name)!=null?_a2:""))===nameSlug});if(own)return{entity:own.entity,slug:own.slug};const exact=entities.getByTypeAndSlug("spell",`${prefixOf(carrierSlug)}_spell_${nameSlug}`);if(exact)return{entity:mirrorSpellShapes(exact.data),slug:exact.slug};const cands=(_a=index.byName.get(nameSlug))!=null?_a:[];if(cands.length===0){warnOnce(`addspells:miss:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches no spell in the compendium`);return null}const prefix=prefixOf(carrierSlug);let pool=cands.filter(e=>prefixOf(e.slug)===prefix);if(pool.length===0)pool=cands;if(carrierEdition!==void 0){const same=pool.filter(e=>editionOf(e.data)===carrierEdition);if(same.length>0)pool=same}pool=[...pool].sort((a,b)=>a.slug<b.slug?-1:a.slug>b.slug?1:0);if(pool.length>1)warnOnce(`addspells:multi:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches ${cands.length} spells; using "${pool[0].slug}"`);return{entity:mirrorSpellShapes(pool[0].data),slug:pool[0].slug}}var hasContentSelectInline=choices=>Array.isArray(choices)&&choices.some(c=>(c==null?void 0:c.kind)==="select-inline"&&typeof c.id==="string"&&!RACE_STRUCTURAL_PSEUDO.has(c.id)||Array.isArray(c==null?void 0:c.options)&&c.options.some(o=>hasContentSelectInline(o==null?void 0:o.choices)));function raceIsUngated(race){var _a;const r=race;if(hasContentSelectInline(r.choices))return false;return!((_a=r.traits)!=null?_a:[]).some(t=>hasContentSelectInline(t==null?void 0:t.choices))}var readAbility=(v,own)=>{if(v&&typeof v==="object"&&"choose"in v)return"choose";if(typeof v!=="string")return void 0;if(v==="inherit")return own!=null?own:void 0;return ABILITY_KEYS.includes(v)?v:void 0};var entryHasInSliceLeaf=(e,comparand,own)=>readAbility(e.ability,own)!=="choose"&&["known","prepared"].some(b=>{const lv=e[b];return!!lv&&typeof lv==="object"&&!Array.isArray(lv)&&Object.entries(lv).some(([k,v])=>(k==="_"||Number(k)<=comparand)&&Array.isArray(v)&&v.some(x=>typeof x==="string"))});function chosenRaceOptionKeys(race,read){var _a;const out=new Set;const r=race;const lists=[r.choices,...((_a=r.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)];for(const list of lists){for(const c of Array.isArray(list)?list:[]){if((c==null?void 0:c.kind)!=="select-inline"||typeof c.id!=="string"||RACE_STRUCTURAL_PSEUDO.has(c.id))continue;const v=read(c.id);for(const value of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof value!=="string")continue;out.add(slugify(value));const opt=(Array.isArray(c.options)?c.options:[]).find(o=>(o==null?void 0:o.value)===value);if(typeof(opt==null?void 0:opt.label)==="string")out.add(slugify(opt.label))}}}return out}function innateLeaves(innate,comparand){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const strings=v=>Array.isArray(v)?v.filter(x=>typeof x==="string"):v&&typeof v==="object"?Object.values(v).flatMap(strings):[];return Object.entries(innate).filter(([k])=>k==="_"||Number(k)<=comparand).flatMap(([,v])=>strings(v))}function memberAtWillLeaves(innate,comparand,slug){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const out=[];for(const[k,v]of Object.entries(innate)){if(!(k==="_"||Number(k)<=comparand))continue;if(Array.isArray(v)){out.push(...v);continue}for(const[usage,list]of v&&typeof v==="object"?Object.entries(v):[]){if(usage==="will"&&Array.isArray(list))out.push(...list);else warnOnce(`addspells:usage:${slug}:innate:${k}:${usage}`,`archivist: additional_spells on "${slug}" innate.${k}.${usage} is a usage economy (skipped; G8)`)}}return out}function collectAdditionalSpells(args){var _a,_b;const{race,feats,classes,totalLevel,ownAbility,alreadyCollected,entities,warnings}=args;const raceChoice=(_a=args.raceChoice)!=null?_a:(()=>void 0);let index=null;const indexOf=()=>index!=null?index:index=buildSpellNameIndex(entities);const out=[];const carriers=[];const asRaw=x=>x==null?void 0:x.additional_spells;if(race&&raceIsUngated(race))carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:entriesOf(asRaw(race)),comparand:totalLevel,classSlug:null});else if(race){const chosen=chosenRaceOptionKeys(race,raceChoice);for(const e of entriesOf(asRaw(race))){if(typeof e.name==="string"&&chosen.has(slugify(e.name))){carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:[e],comparand:totalLevel,classSlug:null})}}}for(const f of feats)carriers.push({root:"feat",slug:f.slug,edition:editionOf(f),entries:entriesOf(asRaw(f)),comparand:totalLevel,classSlug:null});for(const c of classes){if(!c.entity)continue;carriers.push({root:"class",slug:c.entity.slug,edition:editionOf(c.entity),entries:entriesOf(asRaw(c.entity)),comparand:c.level,classSlug:c.entity.slug});if(c.subclass)carriers.push({root:"subclass",slug:c.subclass.slug,edition:editionOf(c.subclass),entries:entriesOf(asRaw(c.subclass)),comparand:c.level,classSlug:c.entity.slug})}for(const pool of(_b=args.pools)!=null?_b:[]){const c=classes[pool.classIndex];if(!(c==null?void 0:c.entity))continue;for(const m of[...heldPicks(pool),...pool.grants]){if(m.itemBound===true)continue;carriers.push({root:"member",slug:m.slug,edition:editionOf(m.entity),entries:entriesOf(asRaw(m.entity)),comparand:c.level,classSlug:c.entity.slug})}}for(const car of carriers){if(car.entries.length===0)continue;if(car.entries.length>1){if(car.entries.some(e=>entryHasInSliceLeaf(e,car.comparand,ownAbility)))warnOnce(`addspells:siblings:${car.slug}`,`archivist: additional_spells on "${car.slug}" has ${car.entries.length} sibling entries (a choose-one grant); skipped`);continue}const entry=car.entries[0];let ability=readAbility(entry.ability,ownAbility);if(ability==="choose"&&car.root==="race"){const pick=raceChoice("spellcasting-ability");const allowed=entry.ability.choose;ability=typeof pick==="string"&&Array.isArray(allowed)&&allowed.includes(pick)?pick:"choose"}if(ability==="choose")continue;const buckets=["known","prepared"].map(bucket=>{const levels=entry[bucket];return[bucket,!levels||typeof levels!=="object"||Array.isArray(levels)?[]:Object.entries(levels)]});if(car.root==="race")buckets.push(["innate",[["_",innateLeaves(entry.innate,car.comparand)]]]);if(car.root==="member")buckets.push(["at-will",[["_",memberAtWillLeaves(entry.innate,car.comparand,car.slug)]]]);for(const[bucket,levelEntries]of buckets){for(const[k,v]of levelEntries){if(!(k==="_"||Number(k)<=car.comparand))continue;if(!Array.isArray(v)){warnOnce(`addspells:usage:${car.slug}:${bucket}:${k}`,`archivist: additional_spells on "${car.slug}" ${bucket}.${k} is a usage economy (skipped; G8)`);continue}for(const leaf of v){const nameSlug=normalizeSpellRef(leaf);if(!nameSlug)continue;const hit=resolveSpellByName({entities,index:indexOf(),nameSlug,carrierSlug:car.slug,carrierEdition:car.edition,alreadyCollected:[...alreadyCollected,...out]});if(!hit){warnings.push(`additional_spells ref "${String(leaf)}" on ${car.slug} not found in compendium.`);continue}out.push({entity:hit.entity,slug:hit.slug,classSlug:car.classSlug,source:car.root==="race"?"race":car.root==="feat"?"feat":"class",prepared:true,alwaysPrepared:true,...ability?{ability}:{},...bucket==="at-will"?{atWill:true}:{}})}}}}return out}export{prefixOf,normalizeSpellRef,buildSpellNameIndex,resolveSpellByName,raceIsUngated,chosenRaceOptionKeys,collectAdditionalSpells};
1
+ import{RACE_STRUCTURAL_PSEUDO}from"./chunk-UBUKCRZ3.js";import{heldPicks}from"./chunk-PKIMOVQG.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{memoByRevision}from"./chunk-QMEKQTUT.js";import{slugify}from"./chunk-63YJPWTM.js";import{mirrorSpellShapes}from"./chunk-4KVVAENP.js";import{ABILITY_KEYS}from"./chunk-EVT7MGAC.js";var entriesOf=a=>Array.isArray(a)?a:a&&typeof a==="object"?[a]:[];var editionOf=x=>{const e=x==null?void 0:x.edition;return typeof e==="string"?e:void 0};var prefixOf=slug=>{var _a;return(_a=slug.split("_")[0])!=null?_a:slug};function normalizeSpellRef(ref){var _a,_b,_c;if(typeof ref!=="string")return null;let s=ref.trim();const wl=/^\[\[(.+)\]\]$/.exec(s);if(wl){const target=(_a=wl[1].split("|")[0])!=null?_a:"";const tail=(_b=target.split("/").pop())!=null?_b:target;const w=slugify(tail.replace(/#.*$/,"").trim());return w.length>0?w:null}s=s.replace(/#.*$/,"");s=(_c=s.split("|")[0])!=null?_c:"";const out=slugify(s.trim());return out.length>0?out:null}function buildSpellNameIndex(entities){return memoByRevision(SPELL_NAME_INDEX,entities,()=>spellNameIndexOf(entities))}var SPELL_NAME_INDEX=new WeakMap;function spellNameIndexOf(entities){var _a;const byName=new Map;for(const e of entities.search("","spell",Number.POSITIVE_INFINITY)){const raw=e.data.name;const key=slugify(typeof raw==="string"?raw:e.name);const list=(_a=byName.get(key))!=null?_a:[];list.push(e);byName.set(key,list)}return{byName}}function resolveSpellByName(opts){var _a;const{entities,index,nameSlug,carrierSlug,carrierEdition,alreadyCollected}=opts;const own=alreadyCollected.find(s=>{var _a2;return slugify(String((_a2=s.entity.name)!=null?_a2:""))===nameSlug});if(own)return{entity:own.entity,slug:own.slug};const exact=entities.getByTypeAndSlug("spell",`${prefixOf(carrierSlug)}_spell_${nameSlug}`);if(exact)return{entity:mirrorSpellShapes(exact.data),slug:exact.slug};const cands=(_a=index.byName.get(nameSlug))!=null?_a:[];if(cands.length===0){warnOnce(`addspells:miss:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches no spell in the compendium`);return null}const prefix=prefixOf(carrierSlug);let pool=cands.filter(e=>prefixOf(e.slug)===prefix);if(pool.length===0)pool=cands;if(carrierEdition!==void 0){const same=pool.filter(e=>editionOf(e.data)===carrierEdition);if(same.length>0)pool=same}pool=[...pool].sort((a,b)=>a.slug<b.slug?-1:a.slug>b.slug?1:0);if(pool.length>1)warnOnce(`addspells:multi:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches ${cands.length} spells; using "${pool[0].slug}"`);return{entity:mirrorSpellShapes(pool[0].data),slug:pool[0].slug}}var hasContentSelectInline=choices=>Array.isArray(choices)&&choices.some(c=>(c==null?void 0:c.kind)==="select-inline"&&typeof c.id==="string"&&!RACE_STRUCTURAL_PSEUDO.has(c.id)||Array.isArray(c==null?void 0:c.options)&&c.options.some(o=>hasContentSelectInline(o==null?void 0:o.choices)));function raceIsUngated(race){var _a;const r=race;if(hasContentSelectInline(r.choices))return false;return!((_a=r.traits)!=null?_a:[]).some(t=>hasContentSelectInline(t==null?void 0:t.choices))}var readAbility=(v,own)=>{if(v&&typeof v==="object"&&"choose"in v)return"choose";if(typeof v!=="string")return void 0;if(v==="inherit")return own!=null?own:void 0;return ABILITY_KEYS.includes(v)?v:void 0};var entryHasInSliceLeaf=(e,comparand,own)=>readAbility(e.ability,own)!=="choose"&&["known","prepared"].some(b=>{const lv=e[b];return!!lv&&typeof lv==="object"&&!Array.isArray(lv)&&Object.entries(lv).some(([k,v])=>(k==="_"||Number(k)<=comparand)&&Array.isArray(v)&&v.some(x=>typeof x==="string"))});function chosenRaceOptionKeys(race,read){var _a;const out=new Set;const r=race;const lists=[r.choices,...((_a=r.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)];for(const list of lists){for(const c of Array.isArray(list)?list:[]){if((c==null?void 0:c.kind)!=="select-inline"||typeof c.id!=="string"||RACE_STRUCTURAL_PSEUDO.has(c.id))continue;const v=read(c.id);for(const value of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof value!=="string")continue;out.add(slugify(value));const opt=(Array.isArray(c.options)?c.options:[]).find(o=>(o==null?void 0:o.value)===value);if(typeof(opt==null?void 0:opt.label)==="string")out.add(slugify(opt.label))}}}return out}function innateLeaves(innate,comparand){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const strings=v=>Array.isArray(v)?v.filter(x=>typeof x==="string"):v&&typeof v==="object"?Object.values(v).flatMap(strings):[];return Object.entries(innate).filter(([k])=>k==="_"||Number(k)<=comparand).flatMap(([,v])=>strings(v))}function memberAtWillLeaves(innate,comparand,slug){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const out=[];for(const[k,v]of Object.entries(innate)){if(!(k==="_"||Number(k)<=comparand))continue;if(Array.isArray(v)){out.push(...v);continue}for(const[usage,list]of v&&typeof v==="object"?Object.entries(v):[]){if(usage==="will"&&Array.isArray(list))out.push(...list);else warnOnce(`addspells:usage:${slug}:innate:${k}:${usage}`,`archivist: additional_spells on "${slug}" innate.${k}.${usage} is a usage economy (skipped; G8)`)}}return out}function collectAdditionalSpells(args){var _a,_b;const{race,feats,classes,totalLevel,ownAbility,alreadyCollected,entities,warnings}=args;const raceChoice=(_a=args.raceChoice)!=null?_a:(()=>void 0);let index=null;const indexOf=()=>index!=null?index:index=buildSpellNameIndex(entities);const out=[];const carriers=[];const asRaw=x=>x==null?void 0:x.additional_spells;if(race&&raceIsUngated(race))carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:entriesOf(asRaw(race)),comparand:totalLevel,classSlug:null});else if(race){const chosen=chosenRaceOptionKeys(race,raceChoice);for(const e of entriesOf(asRaw(race))){if(typeof e.name==="string"&&chosen.has(slugify(e.name))){carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:[e],comparand:totalLevel,classSlug:null})}}}for(const f of feats)carriers.push({root:"feat",slug:f.slug,edition:editionOf(f),entries:entriesOf(asRaw(f)),comparand:totalLevel,classSlug:null});for(const c of classes){if(!c.entity)continue;carriers.push({root:"class",slug:c.entity.slug,edition:editionOf(c.entity),entries:entriesOf(asRaw(c.entity)),comparand:c.level,classSlug:c.entity.slug});if(c.subclass)carriers.push({root:"subclass",slug:c.subclass.slug,edition:editionOf(c.subclass),entries:entriesOf(asRaw(c.subclass)),comparand:c.level,classSlug:c.entity.slug})}for(const pool of(_b=args.pools)!=null?_b:[]){const c=classes[pool.classIndex];if(!(c==null?void 0:c.entity))continue;for(const m of[...heldPicks(pool),...pool.grants]){if(m.itemBound===true)continue;carriers.push({root:"member",slug:m.slug,edition:editionOf(m.entity),entries:entriesOf(asRaw(m.entity)),comparand:c.level,classSlug:c.entity.slug})}}for(const car of carriers){if(car.entries.length===0)continue;if(car.entries.length>1){if(car.entries.some(e=>entryHasInSliceLeaf(e,car.comparand,ownAbility)))warnOnce(`addspells:siblings:${car.slug}`,`archivist: additional_spells on "${car.slug}" has ${car.entries.length} sibling entries (a choose-one grant); skipped`);continue}const entry=car.entries[0];let ability=readAbility(entry.ability,ownAbility);if(ability==="choose"&&car.root==="race"){const pick=raceChoice("spellcasting-ability");const allowed=entry.ability.choose;ability=typeof pick==="string"&&Array.isArray(allowed)&&allowed.includes(pick)?pick:"choose"}if(ability==="choose")continue;const buckets=["known","prepared"].map(bucket=>{const levels=entry[bucket];return[bucket,!levels||typeof levels!=="object"||Array.isArray(levels)?[]:Object.entries(levels)]});if(car.root==="race")buckets.push(["innate",[["_",innateLeaves(entry.innate,car.comparand)]]]);if(car.root==="member")buckets.push(["at-will",[["_",memberAtWillLeaves(entry.innate,car.comparand,car.slug)]]]);for(const[bucket,levelEntries]of buckets){for(const[k,v]of levelEntries){if(!(k==="_"||Number(k)<=car.comparand))continue;if(!Array.isArray(v)){warnOnce(`addspells:usage:${car.slug}:${bucket}:${k}`,`archivist: additional_spells on "${car.slug}" ${bucket}.${k} is a usage economy (skipped; G8)`);continue}for(const leaf of v){const nameSlug=normalizeSpellRef(leaf);if(!nameSlug)continue;const hit=resolveSpellByName({entities,index:indexOf(),nameSlug,carrierSlug:car.slug,carrierEdition:car.edition,alreadyCollected:[...alreadyCollected,...out]});if(!hit){warnings.push(`additional_spells ref "${String(leaf)}" on ${car.slug} not found in compendium.`);continue}out.push({entity:hit.entity,slug:hit.slug,classSlug:car.classSlug,source:car.root==="race"?"race":car.root==="feat"?"feat":"class",prepared:true,alwaysPrepared:true,...ability?{ability}:{},...bucket==="at-will"?{atWill:true}:{}})}}}}return out}export{prefixOf,normalizeSpellRef,buildSpellNameIndex,resolveSpellByName,raceIsUngated,chosenRaceOptionKeys,collectAdditionalSpells};
@@ -1 +1 @@
1
- import{raceEntitySchema}from"./chunk-6LCNV26D.js";import{aliasFeatureListActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseRace(source){const raw=parseYaml(source,["name","slug"]);if(!raw.success)return raw;aliasFeatureListActionCost(raw.data.traits);const result=raceEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`race schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseRace};
1
+ import{raceEntitySchema}from"./chunk-4SYAKWY4.js";import{aliasFeatureListActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseRace(source){const raw=parseYaml(source,["name","slug"]);if(!raw.success)return raw;aliasFeatureListActionCost(raw.data.traits);const result=raceEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`race schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseRace};
@@ -1 +1 @@
1
- function readTableColumn(table,level,keys){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return null;for(const k of keys){const raw=cols[k];if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))return n}return null}function numericColumnsAt(table,level){var _a;const out={};const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return out;for(const[k,raw]of Object.entries(cols)){if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))out[k]=n}return out}var COUNT_COLUMNS={"weapon-mastery":["Weapon Mastery"]};function countColumnsFor(choiceId){if(!Object.prototype.hasOwnProperty.call(COUNT_COLUMNS,choiceId))return void 0;return COUNT_COLUMNS[choiceId]}function diceColumnAt(table,level,key){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols||!Object.prototype.hasOwnProperty.call(cols,key))return null;const raw=cols[key];if(typeof raw!=="string")return null;const cell=raw.trim();return/^\d+d\d+$/i.test(cell)?cell:null}var UNARMED_DIE_COLUMNS={"martial-arts":"Martial Arts"};function unarmedDieColumnFor(featureSlug){if(!Object.prototype.hasOwnProperty.call(UNARMED_DIE_COLUMNS,featureSlug))return void 0;return UNARMED_DIE_COLUMNS[featureSlug]}export{readTableColumn,numericColumnsAt,COUNT_COLUMNS,countColumnsFor,diceColumnAt,UNARMED_DIE_COLUMNS,unarmedDieColumnFor};
1
+ function readTableColumn(table,level,keys){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return null;for(const k of keys){const raw=cols[k];if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))return n}return null}function numericColumnsAt(table,level){var _a;const out={};const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols)return out;for(const[k,raw]of Object.entries(cols)){if(raw===void 0||raw===null)continue;const n=typeof raw==="number"?raw:parseInt(String(raw),10);if(!Number.isNaN(n))out[k]=n}return out}var COUNT_COLUMNS={"weapon-mastery":["Weapon Mastery"]};function countColumnsFor(choiceId){if(!Object.prototype.hasOwnProperty.call(COUNT_COLUMNS,choiceId))return void 0;return COUNT_COLUMNS[choiceId]}function diceColumnAt(table,level,key){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols||!Object.prototype.hasOwnProperty.call(cols,key))return null;const raw=cols[key];if(typeof raw!=="string")return null;const cell=raw.trim();return/^\d+d\d+$/i.test(cell)?cell:null}function tableCellAt(table,level,key){var _a;const cols=(_a=table==null?void 0:table[level])==null?void 0:_a.columns;if(!cols||!Object.prototype.hasOwnProperty.call(cols,key))return null;const raw=cols[key];const cell=typeof raw==="number"?String(raw):typeof raw==="string"?raw.trim():"";if(/^\d+d\d+$/i.test(cell))return cell;if(!/^[+-]?\d+$/.test(cell))return null;const n=parseInt(cell,10);return n===0?null:String(n)}var UNARMED_DIE_COLUMNS={"martial-arts":"Martial Arts"};function unarmedDieColumnFor(featureSlug){if(!Object.prototype.hasOwnProperty.call(UNARMED_DIE_COLUMNS,featureSlug))return void 0;return UNARMED_DIE_COLUMNS[featureSlug]}export{readTableColumn,numericColumnsAt,COUNT_COLUMNS,countColumnsFor,diceColumnAt,tableCellAt,UNARMED_DIE_COLUMNS,unarmedDieColumnFor};
@@ -1 +1 @@
1
- import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-V6NQ547U.js";import{resourceSchema}from"./chunk-CCFIINBA.js";import{startingEquipmentEntrySchema,startingGoldSchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-KBFSJ5WE.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var armorCategoryEnum=z.enum(["light","medium","heavy","shield"]);var weaponCategoryEnum=z.enum(["simple","martial"]);var hitDieEnum=z.enum(["d6","d8","d10","d12"]);var editionEnum=z.enum(["2014","2024"]);var weaponProficiencySchema=z.object({fixed:z.array(z.string()).optional(),categories:z.array(weaponCategoryEnum).optional(),conditional:z.array(z.object({category:weaponCategoryEnum,where_property:z.array(z.string()).nonempty()})).optional()}).refine(w=>{var _a,_b,_c,_d,_e,_f;return((_b=(_a=w.fixed)==null?void 0:_a.length)!=null?_b:0)+((_d=(_c=w.categories)==null?void 0:_c.length)!=null?_d:0)+((_f=(_e=w.conditional)==null?void 0:_e.length)!=null?_f:0)>0},{message:"weapon proficiency must declare at least one of fixed/categories/conditional"});var toolProficiencySchema=z.object({fixed:z.array(z.string()).optional(),choice:z.object({count:z.number().int().positive(),from:z.array(z.string()).nonempty()}).optional()}).refine(t=>{var _a,_b;return((_b=(_a=t.fixed)==null?void 0:_a.length)!=null?_b:0)>0||t.choice!==void 0},{message:"tool proficiency must declare fixed or choice"});var spellcastingSchema=z.object({caster_type:casterTypeEnum,ability:abilityEnum,preparation:z.enum(["known","prepared"]),spell_list:z.string().min(1)});var weaponMasterySchema=z.object({starting_count:z.number().int().nonnegative().optional(),scaling:z.record(z.string(),z.number().int().nonnegative()).optional()});var classTableRowSchema=z.object({prof_bonus:z.number().int().positive(),columns:z.record(z.string(),z.union([z.string(),z.number()])).optional(),feature_ids:z.array(z.string())});var classEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),hit_die:hitDieEnum,primary_abilities:z.array(abilityEnum).nonempty(),standard_array:z.strictObject({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}).optional(),saving_throws:z.array(abilityEnum).length(2),proficiencies:z.object({armor:z.array(armorCategoryEnum),weapons:weaponProficiencySchema,tools:toolProficiencySchema.optional()}),skill_choices:z.object({count:z.number().int().positive(),from:z.array(skillEnum).nonempty()}),choices:z.array(choiceSchema).optional(),starting_equipment:z.array(startingEquipmentEntrySchema),starting_gold:startingGoldSchema.optional(),spellcasting:spellcastingSchema.nullable(),subclass_level:z.number().int().positive(),subclass_feature_name:z.string().min(1),weapon_mastery:weaponMasterySchema.nullable(),epic_boon_level:z.number().int().positive().nullable(),table:z.record(z.string(),classTableRowSchema),features_by_level:z.record(z.string(),z.array(featureSchema)),resources:z.array(resourceSchema),selection_pools:z.array(selectionPoolSchema).optional(),pool_grants:z.array(poolGrantSchema).optional(),tabs:z.array(tabDeclSchema).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),table_col_labels:z.array(z.string().min(1)).optional(),starting_equipment_additional_from_background:z.boolean().optional(),multiclassing:z.unknown().optional(),cantrip_progression:z.array(z.number()).optional(),prepared_spells:z.string().min(1).optional(),prepared_spells_change:z.string().min(1).optional(),prepared_spells_progression:z.array(z.number()).optional(),spells_known_progression:z.array(z.number()).optional(),spells_known_progression_fixed:z.array(z.number()).optional(),spells_known_progression_fixed_allow_lower_level:z.boolean().optional(),spells_known_progression_fixed_by_level:z.record(z.string(),z.record(z.string(),z.number())).optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),image:imageField});export{classEntitySchema};
1
+ import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-NIWLD33X.js";import{resourceSchema}from"./chunk-CCFIINBA.js";import{startingEquipmentEntrySchema,startingGoldSchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var armorCategoryEnum=z.enum(["light","medium","heavy","shield"]);var weaponCategoryEnum=z.enum(["simple","martial"]);var hitDieEnum=z.enum(["d6","d8","d10","d12"]);var editionEnum=z.enum(["2014","2024"]);var weaponProficiencySchema=z.object({fixed:z.array(z.string()).optional(),categories:z.array(weaponCategoryEnum).optional(),conditional:z.array(z.object({category:weaponCategoryEnum,where_property:z.array(z.string()).nonempty()})).optional()}).refine(w=>{var _a,_b,_c,_d,_e,_f;return((_b=(_a=w.fixed)==null?void 0:_a.length)!=null?_b:0)+((_d=(_c=w.categories)==null?void 0:_c.length)!=null?_d:0)+((_f=(_e=w.conditional)==null?void 0:_e.length)!=null?_f:0)>0},{message:"weapon proficiency must declare at least one of fixed/categories/conditional"});var toolProficiencySchema=z.object({fixed:z.array(z.string()).optional(),choice:z.object({count:z.number().int().positive(),from:z.array(z.string()).nonempty()}).optional()}).refine(t=>{var _a,_b;return((_b=(_a=t.fixed)==null?void 0:_a.length)!=null?_b:0)>0||t.choice!==void 0},{message:"tool proficiency must declare fixed or choice"});var spellcastingSchema=z.object({caster_type:casterTypeEnum,ability:abilityEnum,preparation:z.enum(["known","prepared"]),spell_list:z.string().min(1)});var weaponMasterySchema=z.object({starting_count:z.number().int().nonnegative().optional(),scaling:z.record(z.string(),z.number().int().nonnegative()).optional()});var classTableRowSchema=z.object({prof_bonus:z.number().int().positive(),columns:z.record(z.string(),z.union([z.string(),z.number()])).optional(),feature_ids:z.array(z.string())});var classEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),hit_die:hitDieEnum,primary_abilities:z.array(abilityEnum).nonempty(),standard_array:z.strictObject({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}).optional(),saving_throws:z.array(abilityEnum).length(2),proficiencies:z.object({armor:z.array(armorCategoryEnum),weapons:weaponProficiencySchema,tools:toolProficiencySchema.optional()}),skill_choices:z.object({count:z.number().int().positive(),from:z.array(skillEnum).nonempty()}),choices:z.array(choiceSchema).optional(),starting_equipment:z.array(startingEquipmentEntrySchema),starting_gold:startingGoldSchema.optional(),spellcasting:spellcastingSchema.nullable(),subclass_level:z.number().int().positive(),subclass_feature_name:z.string().min(1),weapon_mastery:weaponMasterySchema.nullable(),epic_boon_level:z.number().int().positive().nullable(),table:z.record(z.string(),classTableRowSchema),features_by_level:z.record(z.string(),z.array(featureSchema)),resources:z.array(resourceSchema),selection_pools:z.array(selectionPoolSchema).optional(),pool_grants:z.array(poolGrantSchema).optional(),tabs:z.array(tabDeclSchema).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),table_col_labels:z.array(z.string().min(1)).optional(),starting_equipment_additional_from_background:z.boolean().optional(),multiclassing:z.unknown().optional(),cantrip_progression:z.array(z.number()).optional(),prepared_spells:z.string().min(1).optional(),prepared_spells_change:z.string().min(1).optional(),prepared_spells_progression:z.array(z.number()).optional(),spells_known_progression:z.array(z.number()).optional(),spells_known_progression_fixed:z.array(z.number()).optional(),spells_known_progression_fixed_allow_lower_level:z.boolean().optional(),spells_known_progression_fixed_by_level:z.record(z.string(),z.record(z.string(),z.number())).optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),image:imageField});export{classEntitySchema};
@@ -1 +1 @@
1
- import{qualifiedGrantCovers}from"./chunk-T55DELVL.js";import{classifyWeaponRange}from"./chunk-SEOASDO4.js";import{resolveContainment}from"./chunk-4E2GIWJE.js";import{itemBenefitsActive,itemLabel,itemRowEffects}from"./chunk-PQAVMK3T.js";import{pushDefenseGrant}from"./chunk-HCK6IUB3.js";import{normKey}from"./chunk-VTQ4RWEG.js";import{WEAPON_DEFAULT_ACTION_COST,resolveEntryEntity}from"./chunk-DY6FVAGA.js";import{isActivatedSpeedItem}from"./chunk-DVUXUIPV.js";import{readNumericBonus}from"./chunk-NEMX7QGG.js";import{defaultSlotForType,effectiveArmor,effectiveWeapon,isItemEntity,isShieldArmor,isTwoHandedWeapon,slotAcTerms}from"./chunk-4IAMSRHD.js";import{resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bareEntitySlug}from"./chunk-63YJPWTM.js";var MASTERY={cleave:{label:"Cleave",description:"If you hit a creature with a melee attack roll using this weapon, you can make an attack roll with the weapon against a second creature within 5 feet of the first that is also within your reach. On a hit, the second creature takes the weapon's damage, but don't add your ability modifier to that damage unless it is negative. You can make this extra attack only once per turn.",gist:"hit a 2nd creature in reach"},graze:{label:"Graze",description:"If your attack roll with this weapon misses a creature, you can deal damage to that creature equal to the ability modifier you used to make the attack roll. This damage is the same type dealt by the weapon, and the damage can be increased only by increasing the ability modifier.",gist:"on miss: ability-mod damage"},nick:{label:"Nick",description:"When you make the extra attack of the Light property, you can make it as part of the Attack action instead of as a Bonus Action. You can make this extra attack only once per turn.",gist:"extra Light attack (no Bonus Action)"},push:{label:"Push",description:"If you hit a creature with this weapon, you can push the creature up to 10 feet straight away from yourself if it is Large or smaller.",gist:"on hit: pushed 10 ft."},sap:{label:"Sap",description:"If you hit a creature with this weapon, that creature has Disadvantage on its next attack roll before the start of your next turn.",gist:"on hit: target Disadvantage"},slow:{label:"Slow",description:"If you hit a creature with this weapon and deal damage, you can reduce its Speed by 10 feet until the start of your next turn. If the creature is hit more than once by weapons that have this property, the Speed reduction doesn't exceed 10 feet.",gist:"on hit: -10 ft. Speed"},topple:{label:"Topple",description:"If you hit a creature with this weapon, you can force the creature to make a Constitution saving throw (DC 8 plus the ability modifier used to make the attack roll and your Proficiency Bonus). On a failed save, the creature has the Prone condition.",gist:"on fail: Prone"},vex:{label:"Vex",description:"If you hit a creature with this weapon and deal damage, you have Advantage on your next attack roll against that creature before the end of your next turn.",gist:"on hit: you gain Advantage next"}};function masteryGist(slug){var _a;return(_a=MASTERY[slug])==null?void 0:_a.gist}function masteryDerived(slug,abilityMod,proficiencyBonus){if(slug==="topple")return{label:"Save DC",value:8+proficiencyBonus+abilityMod};if(slug==="graze")return{label:"On miss",value:abilityMod};return void 0}var ABILITY_KEYS=["str","dex","con","int","wis","cha"];function isAbilityKey(k){return ABILITY_KEYS.includes(k)}function emptyAppliedBonuses(){return{ability_bonuses:{},ability_statics:{},save_bonus:0,save_terms:[],speed_bonuses:{walk:0,fly:null,swim:0,climb:0},speed_walk_set:0,speed_walk_set_terms:[],speed_terms:[],spell_attack:0,spell_save_dc:0,defenses:{resistances:[],immunities:[],vulnerabilities:[],condition_immunities:[]},informational:[],senses:{darkvision:0,blindsight:0,tremorsense:0,truesight:0}}}function unwrapSlug(item){const m=item.match(/^\[\[(.+)\]\]$/);return m?m[1]:null}function unwrapClassSlug(maybeWiki){if(!maybeWiki)return"";const m=/^\[\[([^\]]+)\]\]$/.exec(maybeWiki);return(m?m[1]:maybeWiki).toLowerCase()}function buildConditionContext(resolved,equippedSlots,registry){var _a,_b;return{derived:{equippedSlots},classList:(_a=resolved.definition.class)!=null?_a:[],race:resolved.definition.race,subclasses:((_b=resolved.definition.class)!=null?_b:[]).map(c=>c.subclass).filter(s=>typeof s==="string"&&s.length>0).map(unwrapClassSlug),registry}}function pushApply(outcome,field,source,pool,onApply){if(!outcome)return;if(outcome.kind==="applied")onApply(outcome.value);else if(outcome.kind==="informational"){pool.push({field,source,value:outcome.value,conditions:outcome.conditions})}}function isOtherSpeedMode(mode){return mode==="fly"||mode==="swim"||mode==="climb"||mode==="burrow"}function computeAppliedBonuses(resolved,_profs,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t;const out=emptyAppliedBonuses();const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const ctx=buildConditionContext(resolved,{},registry);for(let index=0;index<equipment.length;index++){const entry=equipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity){const slug=unwrapSlug(entry.item);if(slug&&entry.equipped&&!((_b=resolved.infusions)==null?void 0:_b.views.has(index)))warnings.push(`Equipped item [[${slug}]] not found in compendium.`);continue}if(!itemBenefitsActive(entry,entity,registry,(_c=resolved.infusions)==null?void 0:_c.views.get(index)))continue;if(entityType!=="item")continue;const item=entity;const label=itemLabel(entry,item);const grant=(bucket,values)=>{for(const v of values!=null?values:[])if(typeof v==="string")pushDefenseGrant(out.defenses[bucket],v,label,void 0,{index,name:label})};grant("resistances",item.resist);grant("immunities",item.immune);grant("vulnerabilities",item.vulnerable);grant("condition_immunities",item.condition_immune);grant("resistances",(_d=entry.overrides)==null?void 0:_d.resist);grant("immunities",(_e=entry.overrides)==null?void 0:_e.immune);grant("vulnerabilities",(_f=entry.overrides)==null?void 0:_f.vulnerable);grant("condition_immunities",(_g=entry.overrides)==null?void 0:_g.condition_immune);const gs=(_h=item.grants)==null?void 0:_h.senses;if(gs){if(typeof gs.darkvision==="number")out.senses.darkvision=Math.max(out.senses.darkvision,gs.darkvision);if(typeof gs.blindsight==="number")out.senses.blindsight=Math.max(out.senses.blindsight,gs.blindsight);if(typeof gs.tremorsense==="number")out.senses.tremorsense=Math.max(out.senses.tremorsense,gs.tremorsense);if(typeof gs.truesight==="number")out.senses.truesight=Math.max(out.senses.truesight,gs.truesight)}const floor=(_j=(_i=item.modify_speed)==null?void 0:_i.static)==null?void 0:_j.walk;if(typeof floor==="number"&&floor>0){out.speed_walk_set=Math.max(out.speed_walk_set,floor);out.speed_walk_set_terms.push({source:label,amount:floor})}const activatedSpeed=isActivatedSpeedItem(String((_k=item.slug)!=null?_k:"")||((_l=unwrapSlug(entry.item))!=null?_l:entry.item),item);const itemSpeed=(mode,kind,amount)=>{if(!activatedSpeed&&isOtherSpeedMode(mode))out.speed_terms.push({mode,kind,source:label,amount})};for(const[mode,n]of Object.entries((_n=(_m=item.modify_speed)==null?void 0:_m.static)!=null?_n:{}))if(typeof n==="number"&&n>0)itemSpeed(mode,"grant",n);for(const[mode,to]of Object.entries((_p=(_o=item.modify_speed)==null?void 0:_o.equal)!=null?_p:{}))if(to==="walk")itemSpeed(mode,"walk",0);const b=item.bonuses;if(!b)continue;const saveSource=(_r=(_q=entry.overrides)==null?void 0:_q.name)!=null?_r:item.name;pushApply(readNumericBonus(b.saving_throws,ctx),"saving_throws",saveSource,out.informational,v=>{out.save_bonus+=v;out.save_terms.push({source:saveSource,amount:v})});pushApply(readNumericBonus(b.spell_attack,ctx),"spell_attack",item.name,out.informational,v=>{out.spell_attack+=v});pushApply(readNumericBonus(b.spell_save_dc,ctx),"spell_save_dc",item.name,out.informational,v=>{out.spell_save_dc+=v});if((_s=b.ability_scores)==null?void 0:_s.bonus){for(const[k,v]of Object.entries(b.ability_scores.bonus)){if(!isAbilityKey(k))continue;pushApply(readNumericBonus(v,ctx),`ability_scores.bonus.${k}`,item.name,out.informational,val=>{var _a2;out.ability_bonuses[k]=((_a2=out.ability_bonuses[k])!=null?_a2:0)+val})}}if((_t=b.ability_scores)==null?void 0:_t.static){for(const[k,n]of Object.entries(b.ability_scores.static)){if(!isAbilityKey(k)||typeof n!=="number")continue;const prev=out.ability_statics[k];if(prev===void 0){out.ability_statics[k]=n}else{if(n!==prev){warnings.push(`Multiple static ${k.toUpperCase()} bonuses on equipped+attuned items; using highest (${Math.max(prev,n)}).`)}out.ability_statics[k]=Math.max(prev,n)}}}if(b.speed){pushApply(readNumericBonus(b.speed.walk,ctx),"speed.walk",item.name,out.informational,v=>{out.speed_bonuses.walk+=v;out.speed_terms.push({mode:"walk",kind:"bonus",source:label,amount:v})});if(b.speed.fly==="walk"){out.speed_bonuses.fly="walk";itemSpeed("fly","walk",0)}else{pushApply(readNumericBonus(b.speed.fly,ctx),"speed.fly",item.name,out.informational,v=>{const cur=out.speed_bonuses.fly;out.speed_bonuses.fly=(typeof cur==="number"?cur:0)+v;itemSpeed("fly","grant",v)})}pushApply(readNumericBonus(b.speed.swim,ctx),"speed.swim",item.name,out.informational,v=>{out.speed_bonuses.swim+=v;itemSpeed("swim","grant",v)});pushApply(readNumericBonus(b.speed.climb,ctx),"speed.climb",item.name,out.informational,v=>{out.speed_bonuses.climb+=v;itemSpeed("climb","grant",v)})}}return out}function assignSlots(resolved,registry,warnings){var _a;const slots={};const eq=(_a=resolved.definition.equipment)!=null?_a:[];for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||!entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(slots[entry.slot])continue;const placed={index:i,entity,entityType,entry};slots[entry.slot]=placed}for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(!entity||!entityType)continue;const defaultSlot=defaultSlotForType(entityType,entity,registry);if(!defaultSlot){if(isItemEntity(entity)&&typeof entity.base_item==="string"&&entity.base_item.length>0){warnings.push(`Magic item "${entity.name}" base_item ${entity.base_item} did not resolve to a base weapon or armor; not slotted (AC/attack not applied).`)}continue}const placed={index:i,entity,entityType,entry};if(defaultSlot==="mainhand"){if(!slots.mainhand)slots.mainhand=placed;else if(!slots.offhand)slots.offhand=placed}else if(!slots[defaultSlot]){slots[defaultSlot]=placed}}return slots}function pickShield(equippedSlots,equipment,registry,infusions){const slotted=equippedSlots.shield;const slottedArmor=effectiveArmor(slotted==null?void 0:slotted.entity,registry);if(slotted&&slottedArmor&&isShieldArmor(slottedArmor)){return{index:slotted.index,shield:slottedArmor,entity:slotted.entity,entry:slotted.entry}}for(let i=0;i<equipment.length;i++){const entry=equipment[i];if(!entry.equipped)continue;const{entity}=resolveEntryEntity(entry,i,registry,infusions);const armor=effectiveArmor(entity,registry);if(armor&&isShieldArmor(armor))return{index:i,shield:armor,entity,entry}}return null}function twoHandedShieldWarnings(equipment,registry,warnings,infusions){const equipped=equipment.flatMap((entry,i)=>{if(!entry.equipped)return[];const{entity}=resolveEntryEntity(entry,i,registry,infusions);return[{entry,entity}]});const isShield=e=>{const armor=effectiveArmor(e.entity,registry);return!!armor&&isShieldArmor(armor)};for(const e of equipped){if(!e.entity||!isTwoHandedWeapon(e.entity,registry))continue;if(!equipped.some(other=>other!==e&&isShield(other)))continue;warnings.push(`${e.entity.name} is two-handed and a Shield is also equipped.`)}}function computeAC(equippedSlots,resolved,mods,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const breakdown=[];const armorSlot=equippedSlots.armor;const armorEntity=(_a=armorSlot==null?void 0:armorSlot.entity)!=null?_a:null;const armor=effectiveArmor(armorEntity,registry);if(isItemEntity(armorEntity)&&typeof armorEntity.base_item==="string"&&!armor){warnings.push(`Magic armor "${armorEntity.name}" base_item ${armorEntity.base_item} did not resolve to a base armor; AC not applied.`)}const acCtx=buildConditionContext(resolved,equippedSlots,registry);const skip=new Set;const slotBonus=slot=>{var _a2,_b2;const view=slot?(_a2=resolved.infusions)==null?void 0:_a2.views.get(slot.index):void 0;if(!slot||!(view==null?void 0:view.entity)||!isItemEntity(view.entity)||!itemBenefitsActive(slot.entry,view.entity,registry,view))return 0;const out=readNumericBonus((_b2=view.entity.bonuses)==null?void 0:_b2.ac,acCtx);if((out==null?void 0:out.kind)!=="applied")return 0;skip.add(slot.index);return out.value};const armorTerms=slotAcTerms(armor,armorSlot==null?void 0:armorSlot.entry);let ac=10;if(armor&&armorTerms.armor!==null){const armorBase=armorTerms.armor+slotBonus(armorSlot);ac=armorBase;breakdown.push({source:(_b=armorEntity==null?void 0:armorEntity.name)!=null?_b:armor.name,amount:armorBase,kind:"armor"});if(armor.ac.add_dex){const dexCap=(_c=armor.ac.dex_max)!=null?_c:Number.POSITIVE_INFINITY;const dexAdd=Math.min(mods.dex,dexCap);ac+=dexAdd;const capped=mods.dex>dexCap;breakdown.push({source:`DEX modifier${capped?" (capped)":""}`,amount:dexAdd,kind:"dex"})}}else{ac=10+mods.dex;breakdown.push({source:"Base",amount:10,kind:"unarmored"});breakdown.push({source:"DEX modifier",amount:mods.dex,kind:"dex"})}const acBonus=armorTerms.override;if(acBonus!==0){ac+=acBonus;breakdown.push({source:`${(_d=armorEntity==null?void 0:armorEntity.name)!=null?_d:"Armor"} (override)`,amount:acBonus,kind:"override"})}const picked=pickShield(equippedSlots,(_e=resolved.definition.equipment)!=null?_e:[],registry,resolved.infusions);if(picked){const{shield,entity:shieldEntity}=picked;const shieldTerms=slotAcTerms(shield,picked.entry);const n=shieldTerms.armor+slotBonus(picked);ac+=n;breakdown.push({source:(_f=shieldEntity==null?void 0:shieldEntity.name)!=null?_f:shield.name,amount:n,kind:"shield"});const shieldAcBonus=shieldTerms.override;if(shieldAcBonus!==0){ac+=shieldAcBonus;breakdown.push({source:`${(_g=shieldEntity==null?void 0:shieldEntity.name)!=null?_g:shield.name} (override)`,amount:shieldAcBonus,kind:"shield"})}}const acInformational=[];const acEquipment=(_h=resolved.definition.equipment)!=null?_h:[];for(let index=0;index<acEquipment.length;index++){if(skip.has(index))continue;const entry=acEquipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity||entityType!=="item")continue;if(!itemBenefitsActive(entry,entity,registry,(_i=resolved.infusions)==null?void 0:_i.views.get(index)))continue;const item=entity;const out=readNumericBonus((_j=item.bonuses)==null?void 0:_j.ac,acCtx);if(!out)continue;if(out.kind==="applied"){ac+=out.value;breakdown.push({source:item.name,amount:out.value,kind:"item"})}else if(out.kind==="informational"){acInformational.push({field:"ac",source:item.name,value:out.value,conditions:out.conditions})}}return{ac,breakdown,informational:acInformational}}function hasProperty(weapon,prop){return weapon.properties.some(p=>p===prop)}function attackAbility(weapon,mods,weaponAbilities){const modes=classifyWeaponRange(weapon);const finesse=hasProperty(weapon,"finesse");if(modes.melee){const scoped=weaponAbilities.find(o2=>{var _a;return(_a=o2.weaponSlugs)==null?void 0:_a.includes(bareEntitySlug(weapon.slug))});const glob=weaponAbilities.find(o2=>!o2.weaponSlugs);const o=scoped!=null?scoped:glob;if(o)return o.ability;if(finesse)return mods.dex>=mods.str?"dex":"str";return"str"}return finesse&&mods.str>mods.dex?"str":"dex"}function pactScopedAbilities(overrides,pactPicked,isPact){if(!overrides.some(o=>o.pactWeapon))return overrides;return overrides.flatMap(o=>{if(!o.pactWeapon)return[o];return!pactPicked||isPact?[{ability:o.ability}]:[]})}function pactWeaponIndexes(resolved,registry){var _a;const pick=resolved.pactWeapon;if(!pick)return null;const out=new Set;const bare=bareEntitySlug(pick);((_a=resolved.definition.equipment)!=null?_a:[]).forEach((entry,i)=>{var _a2;if(typeof entry.item!=="string")return;const slugs=[unwrapSlug(entry.item),registry?(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.slug:void 0];if(slugs.some(s=>!!s&&(s===pick||bareEntitySlug(s)===bare)))out.add(i)});return out.size?out:null}function isWeaponSlugProficient(weapon,weaponSlug,profs){const wp=profs.weapons;if(wp.specific.some(e=>e===weaponSlug||normKey(e)===normKey(weapon.name)))return true;if(wp.specific.some(e=>qualifiedGrantCovers(e,weapon)))return true;const cat=weapon.category;if(typeof cat==="string"){if(/^simple\b/.test(cat)&&wp.categories.includes("simple"))return true;if(/^martial\b/.test(cat)&&wp.categories.includes("martial"))return true;if(wp.categories.includes(cat))return true}return false}function magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions){var _a,_b,_c,_d;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const ovr=(_a=entry.overrides)!=null?_a:{};const entryAttack=typeof ovr.bonus==="number"?ovr.bonus:0;const entryDamage=typeof ovr.damage_bonus==="number"?ovr.damage_bonus:0;const extra=typeof ovr.extra_damage==="string"?ovr.extra_damage:void 0;let itemAttack=0;let itemDamage=0;let sourceName;let itemName;let damageTypeOverride;let propertiesOverride;const informational=[];let itemRiders=[];let critRange;const conditionalCrits=[];if(entity&&isItemEntity(entity)){sourceName=entity.name;itemName=entity.name;damageTypeOverride=typeof entity.damage_type==="string"&&entity.damage_type.length>0?entity.damage_type:void 0;propertiesOverride=Array.isArray(entity.properties)&&entity.properties.length>0?entity.properties:void 0}if(entity&&isItemEntity(entity)&&itemBenefitsActive(entry,entity,registry,infusions==null?void 0:infusions.views.get(index))){const b=entity.bonuses;const atkOut=readNumericBonus(b==null?void 0:b.weapon_attack,ctx);const dmgOut=readNumericBonus(b==null?void 0:b.weapon_damage,ctx);if((atkOut==null?void 0:atkOut.kind)==="applied")itemAttack=atkOut.value;else if((atkOut==null?void 0:atkOut.kind)==="informational")informational.push({field:"weapon_attack",source:entity.name,value:atkOut.value,conditions:atkOut.conditions});if((dmgOut==null?void 0:dmgOut.kind)==="applied")itemDamage=dmgOut.value;else if((dmgOut==null?void 0:dmgOut.kind)==="informational")informational.push({field:"weapon_damage",source:entity.name,value:dmgOut.value,conditions:dmgOut.conditions});itemRiders=Array.isArray(entity.damage_riders)?entity.damage_riders.filter(r=>{var _a2;return((_a2=r.applies_to)!=null?_a2:"weapon")!=="spell"}).map(r=>({amount:r.amount,damage_type:r.damage_type,source:entity.name,...r.condition?{condition:r.condition}:{}})):[];for(const eff of itemRowEffects(entity)){if(eff.kind==="damage-bonus"&&((_b=eff.applies_to)!=null?_b:"weapon")!=="spell"){itemRiders.push({amount:eff.amount,damage_type:eff.damage_type,source:entity.name,...eff.condition?{condition:eff.condition}:{}})}else if(eff.kind==="crit-range"&&((_c=eff.applies_to)!=null?_c:"weapon")!=="spell"){if((_d=eff.condition)==null?void 0:_d.trim())conditionalCrits.push({minRoll:eff.min_roll,condition:eff.condition.trim(),source:entity.name});else critRange=Math.min(critRange!=null?critRange:20,eff.min_roll)}}}return{...critRange!==void 0&&critRange<20?{critRange}:{},...conditionalCrits.length?{conditionalCrits}:{},atk:itemAttack+entryAttack,dmg:itemDamage+entryDamage,extra,sourceName,itemName,damageTypeOverride,propertiesOverride,informational,riders:itemRiders}}function buildAttackRow(args){var _a,_b,_c,_d;const{id,name,weapon,baseDice,ability,mods,proficient,proficiencyBonus,magic,weaponMasteries}=args;const abilityMod=mods[ability];const pb=proficient?proficiencyBonus:0;const toHit=abilityMod+pb+magic.atk;const dmgFlat=abilityMod+magic.dmg;const formatDice=dice=>`${dice}${dmgFlat>=0?"+":""}${dmgFlat}`.replace(/\+0$/,"");const damageDice=formatDice(baseDice);const magicSource=magic.sourceName?`${magic.sourceName} bonus`:"Magic weapon";const toHitBreakdown=[{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficient?proficiencyBonus:0,kind:"ability"},{source:magicSource,amount:magic.atk,kind:"item"}];const damageBreakdown=[{source:"Base damage",amount:0,kind:"ability"},{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:magicSource,amount:magic.dmg,kind:"item"}];const modes=classifyWeaponRange(weapon);const fmtRanged=r=>r.long>r.normal?`${r.normal}/${r.long} ft.`:`${r.normal} ft.`;const range=modes.melee?`${modes.melee.reach} ft.`:modes.ranged?fmtRanged(modes.ranged):void 0;const thrownRange=modes.melee&&modes.ranged?fmtRanged(modes.ranged):void 0;const stringProps=weapon.properties.filter(p=>typeof p==="string");const finalProps=(_a=magic.propertiesOverride)!=null?_a:stringProps;const row={id,name,...range!==void 0?{range}:{},...thrownRange!==void 0?{thrownRange}:{},toHit,damageDice,damageType:(_b=magic.damageTypeOverride)!=null?_b:weapon.damage.type,...(()=>{const riders=[...magic.riders,...magic.extra?[{amount:magic.extra}]:[]];return riders.length?{damageRiders:riders}:{}})(),weaponCategory:modes.melee?"melee":"ranged",properties:finalProps,proficient,breakdown:{toHit:toHitBreakdown,damage:damageBreakdown},informational:args.magic.informational.length>0?args.magic.informational:void 0,slotKey:args.slotKey,subLabel:formatWeaponSubLabel(weapon,finalProps,modes),actionCost:args.actionCost,versatile:args.versatileDice?{damageDice:formatDice(args.versatileDice)}:void 0,...magic.critRange!==void 0?{critRange:magic.critRange}:{},...((_c=magic.conditionalCrits)==null?void 0:_c.length)?{conditionalCrits:magic.conditionalCrits}:{}};const mSlug=(_d=weapon.mastery)==null?void 0:_d[0];if(mSlug&&proficient&&weaponMasteries.includes(bareEntitySlug(weapon.slug))){const g=MASTERY[mSlug];if(g){const derived=masteryDerived(mSlug,mods[ability],proficiencyBonus);row.mastery={slug:mSlug,label:g.label,description:g.description,gist:masteryGist(mSlug),...derived?{derived}:{}}}}return row}function buildUnarmedRow(mods,proficiencyBonus,spec){var _a;const candidates=["str",...(_a=spec==null?void 0:spec.abilities)!=null?_a:[]];let ability="str";for(const ab of candidates)if(mods[ab]>=mods[ability])ability=ab;const abilityMod=mods[ability];const toHit=abilityMod+proficiencyBonus;const flat=`${abilityMod>=0?"+":""}${abilityMod}`.replace(/^\+0$/,"");const damageDice=(spec==null?void 0:spec.dice)?`${spec.dice}${flat}`:String(Math.max(0,1+abilityMod));const label=`${ability.toUpperCase()} modifier`;return{id:"unarmed-strike",name:"Unarmed Strike",unarmed:true,range:"5 ft.",toHit,damageDice,damageType:"bludgeoning",properties:[],proficient:true,breakdown:{toHit:[{source:label,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficiencyBonus,kind:"ability"}],damage:[{source:"Base damage",amount:(spec==null?void 0:spec.dice)?0:1,kind:"ability"},{source:label,amount:abilityMod,kind:"ability"}]},subLabel:"Unarmed",actionCost:"action"}}function buildFeatureAttackRows(resolved,mods,profs,proficiencyBonus,weaponAbilities=[]){var _a,_b,_c;const rows=[];const abilities=weaponAbilities.filter(o=>!o.pactWeapon);for(const rf of(_a=resolved.features)!=null?_a:[]){if(rf.renderSuppressed||rf.buildOnly)continue;const featureId=(_b=rf.feature.id)!=null?_b:rf.feature.name;((_c=rf.feature.attacks)!=null?_c:[]).forEach((a,n)=>{var _a2,_b2,_c2,_d,_e,_f,_g;if(!a.weapon_category||a.type!=="melee"&&a.type!=="ranged"||typeof a.damage!=="string"||!a.damage.trim())return;const long=(_c2=(_a2=a.range)==null?void 0:_a2.long)!=null?_c2:(_b2=a.range)==null?void 0:_b2.normal;const weapon={name:a.name,slug:`feature-attack_${featureId}_${n}`,category:`${a.weapon_category}-${a.type}`,damage:{dice:a.damage.trim(),type:(_d=a.damage_type)!=null?_d:""},properties:((_e=a.properties)!=null?_e:[]).map(p=>p.trim().toLowerCase()),...((_f=a.range)==null?void 0:_f.normal)!==void 0&&long!==void 0?{range:{normal:a.range.normal,long}}:{},...a.mastery?{mastery:[a.mastery.trim().toLowerCase()]}:{}};const proficient=isWeaponSlugProficient(weapon,weapon.slug,profs);const row=buildAttackRow({id:`feature-attack:${rf.source.kind}:${rf.source.slug}:${featureId}:${n}`,name:a.name,weapon,baseDice:weapon.damage.dice,ability:attackAbility(weapon,mods,abilities),mods,proficient,proficiencyBonus,magic:{atk:0,dmg:0,informational:[],riders:[]},actionCost:(_g=a.action)!=null?_g:WEAPON_DEFAULT_ACTION_COST,weaponMasteries:a.mastery?[bareEntitySlug(weapon.slug)]:[]});row.grantedBy=rf.feature.name;rows.push(row)})}return rows}function humanizeWeaponToken(s){return s.replace(/[-_]/g," ").replace(/(^|[\s(])\w/g,c=>c.toUpperCase())}function formatWeaponSubLabel(weapon,properties,modes){const parts=[];if(weapon.category){const cat=modes.melee&&/ranged/.test(weapon.category)?weapon.category.replace("ranged","melee"):weapon.category;parts.push(humanizeWeaponToken(cat))}if(properties.length>0)parts.push(properties.map(humanizeWeaponToken).join(", "));return parts.join(" \xB7 ")}function computeAttacks(equippedSlots,equipment,mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities=[],infusions,pactIndexes=null){var _a,_b;const rows=[];const rowFor=(index,entry,weapon,slotKey,versatileDice)=>{var _a2,_b2,_c,_d,_e;const slugFromEntry=(_a2=unwrapSlug(entry.item))!=null?_a2:weapon.slug;const proficient=isWeaponSlugProficient(weapon,slugFromEntry,profs)||isWeaponSlugProficient(weapon,weapon.slug,profs);if(!proficient){warnings.push(`Character not proficient with ${weapon.name}; proficiency bonus excluded.`)}const isPact=(pactIndexes==null?void 0:pactIndexes.has(index))===true;const ability=attackAbility(weapon,mods,pactScopedAbilities(weaponAbilities,pactIndexes!==null,isPact));const magic=magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions);const ovr=(_b2=entry.overrides)!=null?_b2:{};const row=buildAttackRow({id:`${index}:standard`,name:(_d=(_c=ovr.name)!=null?_c:magic.itemName)!=null?_d:weapon.name,weapon,baseDice:weapon.damage.dice,ability,mods,proficient,proficiencyBonus,magic,slotKey,actionCost:(_e=ovr.action)!=null?_e:WEAPON_DEFAULT_ACTION_COST,versatileDice,weaponMasteries});if(isPact)row.pactWeapon=true;return row};const handedSlots=[{key:"mainhand",placed:equippedSlots.mainhand},{key:"offhand",placed:equippedSlots.offhand}];for(const{key,placed}of handedSlots){if(!placed)continue;const{entity,entry}=placed;if(!entity)continue;const weapon=effectiveWeapon(entity,registry);if(!weapon){if(isItemEntity(entity)&&typeof entity.base_item==="string"){warnings.push(`Magic weapon ${entity.name} references missing base_item ${entity.base_item}.`)}continue}const versatileDice=key==="mainhand"&&hasProperty(weapon,"versatile")&&typeof weapon.damage.versatile_dice==="string"&&!equippedSlots.offhand?weapon.damage.versatile_dice:void 0;rows.push(rowFor(placed.index,entry,weapon,key,versatileDice))}const handIndex=new Set([(_a=equippedSlots.mainhand)==null?void 0:_a.index,(_b=equippedSlots.offhand)==null?void 0:_b.index]);equipment.forEach((entry,index)=>{if(!entry.equipped||handIndex.has(index))return;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const weapon=effectiveWeapon(entity,registry);if(!weapon)return;rows.push(rowFor(index,entry,weapon))});return rows}function coerceWeight(raw){if(typeof raw==="number"&&Number.isFinite(raw)&&raw>=0)return raw;if(typeof raw==="string"){const n=Number.parseFloat(raw);if(Number.isFinite(n)&&n>=0)return n}return 0}function computeCarriedWeight(resolved,registry){var _a;const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const view=resolveContainment(equipment,registry);const weightlessContainer=equipment.map(entry=>{var _a2,_b,_c;const data=(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.data;return((_c=(_b=data==null?void 0:data.container)==null?void 0:_b.capacity)==null?void 0:_c.weightless)===true});const exempt=i=>{for(let p=view.parentOf[i];p!==null;p=view.parentOf[p])if(weightlessContainer[p])return true;return false};let total=0;equipment.forEach((entry,i)=>{if(exempt(i))return;const found=resolveBaseItem(entry.item,registry);if(!found)return;const entity=found.data;const w=coerceWeight(entity.weight);if(w===0)return;const qty=typeof entry.qty==="number"&&entry.qty>=0?entry.qty:1;total+=w*qty});return total}function computeSlotsAndAttacks(resolved,mods,profs,registry,warnings,proficiencyBonus,weaponAbilities=[],weaponMasteries=[],attunementFloor=0){var _a,_b,_c,_d,_e;const equippedSlots=assignSlots(resolved,registry,warnings);twoHandedShieldWarnings((_a=resolved.definition.equipment)!=null?_a:[],registry,warnings,resolved.infusions);const overrides=(_b=resolved.definition.overrides)!=null?_b:{};const acOut=computeAC(equippedSlots,resolved,mods,registry,warnings);const ctx=buildConditionContext(resolved,equippedSlots,registry);const attacks=computeAttacks(equippedSlots,(_c=resolved.definition.equipment)!=null?_c:[],mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities,resolved.infusions,pactWeaponIndexes(resolved,registry));return{ac:acOut.ac,acBreakdown:acOut.breakdown,acInformational:acOut.informational,attacks,equippedSlots,carriedWeight:computeCarriedWeight(resolved,registry),attunementUsed:((_d=resolved.definition.equipment)!=null?_d:[]).filter(e=>e.attuned).length,attunementLimit:(_e=overrides.attunement_limit)!=null?_e:Math.max(3,attunementFloor)}}export{emptyAppliedBonuses,computeAppliedBonuses,pactWeaponIndexes,isWeaponSlugProficient,buildUnarmedRow,buildFeatureAttackRows,computeSlotsAndAttacks};
1
+ import{qualifiedGrantCovers}from"./chunk-T55DELVL.js";import{classifyWeaponRange}from"./chunk-SEOASDO4.js";import{resolveContainment}from"./chunk-4E2GIWJE.js";import{pushDefenseGrant}from"./chunk-GD7WRCNH.js";import{normKey}from"./chunk-VTQ4RWEG.js";import{itemBenefitsActive,itemLabel,itemRowEffects}from"./chunk-J3RP5C7L.js";import{WEAPON_DEFAULT_ACTION_COST,resolveEntryEntity}from"./chunk-PKIMOVQG.js";import{isActivatedSpeedItem}from"./chunk-DVUXUIPV.js";import{readNumericBonus}from"./chunk-NEMX7QGG.js";import{defaultSlotForType,effectiveArmor,effectiveWeapon,isItemEntity,isShieldArmor,isTwoHandedWeapon,slotAcTerms}from"./chunk-4IAMSRHD.js";import{resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bareEntitySlug}from"./chunk-63YJPWTM.js";var MASTERY={cleave:{label:"Cleave",description:"If you hit a creature with a melee attack roll using this weapon, you can make an attack roll with the weapon against a second creature within 5 feet of the first that is also within your reach. On a hit, the second creature takes the weapon's damage, but don't add your ability modifier to that damage unless it is negative. You can make this extra attack only once per turn.",gist:"hit a 2nd creature in reach"},graze:{label:"Graze",description:"If your attack roll with this weapon misses a creature, you can deal damage to that creature equal to the ability modifier you used to make the attack roll. This damage is the same type dealt by the weapon, and the damage can be increased only by increasing the ability modifier.",gist:"on miss: ability-mod damage"},nick:{label:"Nick",description:"When you make the extra attack of the Light property, you can make it as part of the Attack action instead of as a Bonus Action. You can make this extra attack only once per turn.",gist:"extra Light attack (no Bonus Action)"},push:{label:"Push",description:"If you hit a creature with this weapon, you can push the creature up to 10 feet straight away from yourself if it is Large or smaller.",gist:"on hit: pushed 10 ft."},sap:{label:"Sap",description:"If you hit a creature with this weapon, that creature has Disadvantage on its next attack roll before the start of your next turn.",gist:"on hit: target Disadvantage"},slow:{label:"Slow",description:"If you hit a creature with this weapon and deal damage, you can reduce its Speed by 10 feet until the start of your next turn. If the creature is hit more than once by weapons that have this property, the Speed reduction doesn't exceed 10 feet.",gist:"on hit: -10 ft. Speed"},topple:{label:"Topple",description:"If you hit a creature with this weapon, you can force the creature to make a Constitution saving throw (DC 8 plus the ability modifier used to make the attack roll and your Proficiency Bonus). On a failed save, the creature has the Prone condition.",gist:"on fail: Prone"},vex:{label:"Vex",description:"If you hit a creature with this weapon and deal damage, you have Advantage on your next attack roll against that creature before the end of your next turn.",gist:"on hit: you gain Advantage next"}};function masteryGist(slug){var _a;return(_a=MASTERY[slug])==null?void 0:_a.gist}function masteryDerived(slug,abilityMod,proficiencyBonus){if(slug==="topple")return{label:"Save DC",value:8+proficiencyBonus+abilityMod};if(slug==="graze")return{label:"On miss",value:abilityMod};return void 0}var ABILITY_KEYS=["str","dex","con","int","wis","cha"];function isAbilityKey(k){return ABILITY_KEYS.includes(k)}function emptyAppliedBonuses(){return{ability_bonuses:{},ability_statics:{},save_bonus:0,save_terms:[],speed_bonuses:{walk:0,fly:null,swim:0,climb:0},speed_walk_set:0,speed_walk_set_terms:[],speed_terms:[],spell_attack:0,spell_save_dc:0,defenses:{resistances:[],immunities:[],vulnerabilities:[],condition_immunities:[]},informational:[],senses:{darkvision:0,blindsight:0,tremorsense:0,truesight:0}}}function unwrapSlug(item){const m=item.match(/^\[\[(.+)\]\]$/);return m?m[1]:null}function unwrapClassSlug(maybeWiki){if(!maybeWiki)return"";const m=/^\[\[([^\]]+)\]\]$/.exec(maybeWiki);return(m?m[1]:maybeWiki).toLowerCase()}function buildConditionContext(resolved,equippedSlots,registry){var _a,_b;return{derived:{equippedSlots},classList:(_a=resolved.definition.class)!=null?_a:[],race:resolved.definition.race,subclasses:((_b=resolved.definition.class)!=null?_b:[]).map(c=>c.subclass).filter(s=>typeof s==="string"&&s.length>0).map(unwrapClassSlug),registry}}function pushApply(outcome,field,source,pool,onApply){if(!outcome)return;if(outcome.kind==="applied")onApply(outcome.value);else if(outcome.kind==="informational"){pool.push({field,source,value:outcome.value,conditions:outcome.conditions})}}function isOtherSpeedMode(mode){return mode==="fly"||mode==="swim"||mode==="climb"||mode==="burrow"}function computeAppliedBonuses(resolved,_profs,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t;const out=emptyAppliedBonuses();const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const ctx=buildConditionContext(resolved,{},registry);for(let index=0;index<equipment.length;index++){const entry=equipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity){const slug=unwrapSlug(entry.item);if(slug&&entry.equipped&&!((_b=resolved.infusions)==null?void 0:_b.views.has(index)))warnings.push(`Equipped item [[${slug}]] not found in compendium.`);continue}if(!itemBenefitsActive(entry,entity,registry,(_c=resolved.infusions)==null?void 0:_c.views.get(index)))continue;if(entityType!=="item")continue;const item=entity;const label=itemLabel(entry,item);const grant=(bucket,values)=>{for(const v of values!=null?values:[])if(typeof v==="string")pushDefenseGrant(out.defenses[bucket],v,label,void 0,{index,name:label})};grant("resistances",item.resist);grant("immunities",item.immune);grant("vulnerabilities",item.vulnerable);grant("condition_immunities",item.condition_immune);grant("resistances",(_d=entry.overrides)==null?void 0:_d.resist);grant("immunities",(_e=entry.overrides)==null?void 0:_e.immune);grant("vulnerabilities",(_f=entry.overrides)==null?void 0:_f.vulnerable);grant("condition_immunities",(_g=entry.overrides)==null?void 0:_g.condition_immune);const gs=(_h=item.grants)==null?void 0:_h.senses;if(gs){if(typeof gs.darkvision==="number")out.senses.darkvision=Math.max(out.senses.darkvision,gs.darkvision);if(typeof gs.blindsight==="number")out.senses.blindsight=Math.max(out.senses.blindsight,gs.blindsight);if(typeof gs.tremorsense==="number")out.senses.tremorsense=Math.max(out.senses.tremorsense,gs.tremorsense);if(typeof gs.truesight==="number")out.senses.truesight=Math.max(out.senses.truesight,gs.truesight)}const floor=(_j=(_i=item.modify_speed)==null?void 0:_i.static)==null?void 0:_j.walk;if(typeof floor==="number"&&floor>0){out.speed_walk_set=Math.max(out.speed_walk_set,floor);out.speed_walk_set_terms.push({source:label,amount:floor})}const activatedSpeed=isActivatedSpeedItem(String((_k=item.slug)!=null?_k:"")||((_l=unwrapSlug(entry.item))!=null?_l:entry.item),item);const itemSpeed=(mode,kind,amount)=>{if(!activatedSpeed&&isOtherSpeedMode(mode))out.speed_terms.push({mode,kind,source:label,amount})};for(const[mode,n]of Object.entries((_n=(_m=item.modify_speed)==null?void 0:_m.static)!=null?_n:{}))if(typeof n==="number"&&n>0)itemSpeed(mode,"grant",n);for(const[mode,to]of Object.entries((_p=(_o=item.modify_speed)==null?void 0:_o.equal)!=null?_p:{}))if(to==="walk")itemSpeed(mode,"walk",0);const b=item.bonuses;if(!b)continue;const saveSource=(_r=(_q=entry.overrides)==null?void 0:_q.name)!=null?_r:item.name;pushApply(readNumericBonus(b.saving_throws,ctx),"saving_throws",saveSource,out.informational,v=>{out.save_bonus+=v;out.save_terms.push({source:saveSource,amount:v})});pushApply(readNumericBonus(b.spell_attack,ctx),"spell_attack",item.name,out.informational,v=>{out.spell_attack+=v});pushApply(readNumericBonus(b.spell_save_dc,ctx),"spell_save_dc",item.name,out.informational,v=>{out.spell_save_dc+=v});if((_s=b.ability_scores)==null?void 0:_s.bonus){for(const[k,v]of Object.entries(b.ability_scores.bonus)){if(!isAbilityKey(k))continue;pushApply(readNumericBonus(v,ctx),`ability_scores.bonus.${k}`,item.name,out.informational,val=>{var _a2;out.ability_bonuses[k]=((_a2=out.ability_bonuses[k])!=null?_a2:0)+val})}}if((_t=b.ability_scores)==null?void 0:_t.static){for(const[k,n]of Object.entries(b.ability_scores.static)){if(!isAbilityKey(k)||typeof n!=="number")continue;const prev=out.ability_statics[k];if(prev===void 0){out.ability_statics[k]=n}else{if(n!==prev){warnings.push(`Multiple static ${k.toUpperCase()} bonuses on equipped+attuned items; using highest (${Math.max(prev,n)}).`)}out.ability_statics[k]=Math.max(prev,n)}}}if(b.speed){pushApply(readNumericBonus(b.speed.walk,ctx),"speed.walk",item.name,out.informational,v=>{out.speed_bonuses.walk+=v;out.speed_terms.push({mode:"walk",kind:"bonus",source:label,amount:v})});if(b.speed.fly==="walk"){out.speed_bonuses.fly="walk";itemSpeed("fly","walk",0)}else{pushApply(readNumericBonus(b.speed.fly,ctx),"speed.fly",item.name,out.informational,v=>{const cur=out.speed_bonuses.fly;out.speed_bonuses.fly=(typeof cur==="number"?cur:0)+v;itemSpeed("fly","grant",v)})}pushApply(readNumericBonus(b.speed.swim,ctx),"speed.swim",item.name,out.informational,v=>{out.speed_bonuses.swim+=v;itemSpeed("swim","grant",v)});pushApply(readNumericBonus(b.speed.climb,ctx),"speed.climb",item.name,out.informational,v=>{out.speed_bonuses.climb+=v;itemSpeed("climb","grant",v)})}}return out}function assignSlots(resolved,registry,warnings){var _a;const slots={};const eq=(_a=resolved.definition.equipment)!=null?_a:[];for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||!entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(slots[entry.slot])continue;const placed={index:i,entity,entityType,entry};slots[entry.slot]=placed}for(let i=0;i<eq.length;i++){const entry=eq[i];if(!entry.equipped||entry.slot)continue;const{entity,entityType}=resolveEntryEntity(entry,i,registry,resolved.infusions);if(!entity||!entityType)continue;const defaultSlot=defaultSlotForType(entityType,entity,registry);if(!defaultSlot){if(isItemEntity(entity)&&typeof entity.base_item==="string"&&entity.base_item.length>0){warnings.push(`Magic item "${entity.name}" base_item ${entity.base_item} did not resolve to a base weapon or armor; not slotted (AC/attack not applied).`)}continue}const placed={index:i,entity,entityType,entry};if(defaultSlot==="mainhand"){if(!slots.mainhand)slots.mainhand=placed;else if(!slots.offhand)slots.offhand=placed}else if(!slots[defaultSlot]){slots[defaultSlot]=placed}}return slots}function pickShield(equippedSlots,equipment,registry,infusions){const slotted=equippedSlots.shield;const slottedArmor=effectiveArmor(slotted==null?void 0:slotted.entity,registry);if(slotted&&slottedArmor&&isShieldArmor(slottedArmor)){return{index:slotted.index,shield:slottedArmor,entity:slotted.entity,entry:slotted.entry}}for(let i=0;i<equipment.length;i++){const entry=equipment[i];if(!entry.equipped)continue;const{entity}=resolveEntryEntity(entry,i,registry,infusions);const armor=effectiveArmor(entity,registry);if(armor&&isShieldArmor(armor))return{index:i,shield:armor,entity,entry}}return null}function twoHandedShieldWarnings(equipment,registry,warnings,infusions){const equipped=equipment.flatMap((entry,i)=>{if(!entry.equipped)return[];const{entity}=resolveEntryEntity(entry,i,registry,infusions);return[{entry,entity}]});const isShield=e=>{const armor=effectiveArmor(e.entity,registry);return!!armor&&isShieldArmor(armor)};for(const e of equipped){if(!e.entity||!isTwoHandedWeapon(e.entity,registry))continue;if(!equipped.some(other=>other!==e&&isShield(other)))continue;warnings.push(`${e.entity.name} is two-handed and a Shield is also equipped.`)}}function computeAC(equippedSlots,resolved,mods,registry,warnings){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const breakdown=[];const armorSlot=equippedSlots.armor;const armorEntity=(_a=armorSlot==null?void 0:armorSlot.entity)!=null?_a:null;const armor=effectiveArmor(armorEntity,registry);if(isItemEntity(armorEntity)&&typeof armorEntity.base_item==="string"&&!armor){warnings.push(`Magic armor "${armorEntity.name}" base_item ${armorEntity.base_item} did not resolve to a base armor; AC not applied.`)}const acCtx=buildConditionContext(resolved,equippedSlots,registry);const skip=new Set;const slotBonus=slot=>{var _a2,_b2;const view=slot?(_a2=resolved.infusions)==null?void 0:_a2.views.get(slot.index):void 0;if(!slot||!(view==null?void 0:view.entity)||!isItemEntity(view.entity)||!itemBenefitsActive(slot.entry,view.entity,registry,view))return 0;const out=readNumericBonus((_b2=view.entity.bonuses)==null?void 0:_b2.ac,acCtx);if((out==null?void 0:out.kind)!=="applied")return 0;skip.add(slot.index);return out.value};const armorTerms=slotAcTerms(armor,armorSlot==null?void 0:armorSlot.entry);let ac=10;if(armor&&armorTerms.armor!==null){const armorBase=armorTerms.armor+slotBonus(armorSlot);ac=armorBase;breakdown.push({source:(_b=armorEntity==null?void 0:armorEntity.name)!=null?_b:armor.name,amount:armorBase,kind:"armor"});if(armor.ac.add_dex){const dexCap=(_c=armor.ac.dex_max)!=null?_c:Number.POSITIVE_INFINITY;const dexAdd=Math.min(mods.dex,dexCap);ac+=dexAdd;const capped=mods.dex>dexCap;breakdown.push({source:`DEX modifier${capped?" (capped)":""}`,amount:dexAdd,kind:"dex"})}}else{ac=10+mods.dex;breakdown.push({source:"Base",amount:10,kind:"unarmored"});breakdown.push({source:"DEX modifier",amount:mods.dex,kind:"dex"})}const acBonus=armorTerms.override;if(acBonus!==0){ac+=acBonus;breakdown.push({source:`${(_d=armorEntity==null?void 0:armorEntity.name)!=null?_d:"Armor"} (override)`,amount:acBonus,kind:"override"})}const picked=pickShield(equippedSlots,(_e=resolved.definition.equipment)!=null?_e:[],registry,resolved.infusions);if(picked){const{shield,entity:shieldEntity}=picked;const shieldTerms=slotAcTerms(shield,picked.entry);const n=shieldTerms.armor+slotBonus(picked);ac+=n;breakdown.push({source:(_f=shieldEntity==null?void 0:shieldEntity.name)!=null?_f:shield.name,amount:n,kind:"shield"});const shieldAcBonus=shieldTerms.override;if(shieldAcBonus!==0){ac+=shieldAcBonus;breakdown.push({source:`${(_g=shieldEntity==null?void 0:shieldEntity.name)!=null?_g:shield.name} (override)`,amount:shieldAcBonus,kind:"shield"})}}const acInformational=[];const acEquipment=(_h=resolved.definition.equipment)!=null?_h:[];for(let index=0;index<acEquipment.length;index++){if(skip.has(index))continue;const entry=acEquipment[index];const{entity,entityType}=resolveEntryEntity(entry,index,registry,resolved.infusions);if(!entity||entityType!=="item")continue;if(!itemBenefitsActive(entry,entity,registry,(_i=resolved.infusions)==null?void 0:_i.views.get(index)))continue;const item=entity;const out=readNumericBonus((_j=item.bonuses)==null?void 0:_j.ac,acCtx);if(!out)continue;if(out.kind==="applied"){ac+=out.value;breakdown.push({source:item.name,amount:out.value,kind:"item"})}else if(out.kind==="informational"){acInformational.push({field:"ac",source:item.name,value:out.value,conditions:out.conditions})}}return{ac,breakdown,informational:acInformational}}function hasProperty(weapon,prop){return weapon.properties.some(p=>p===prop)}function attackAbility(weapon,mods,weaponAbilities){const modes=classifyWeaponRange(weapon);const finesse=hasProperty(weapon,"finesse");if(modes.melee){const scoped=weaponAbilities.find(o2=>{var _a;return(_a=o2.weaponSlugs)==null?void 0:_a.includes(bareEntitySlug(weapon.slug))});const glob=weaponAbilities.find(o2=>!o2.weaponSlugs);const o=scoped!=null?scoped:glob;if(o)return o.ability;if(finesse)return mods.dex>=mods.str?"dex":"str";return"str"}return finesse&&mods.str>mods.dex?"str":"dex"}function pactScopedAbilities(overrides,pactPicked,isPact){if(!overrides.some(o=>o.pactWeapon))return overrides;return overrides.flatMap(o=>{if(!o.pactWeapon)return[o];return!pactPicked||isPact?[{ability:o.ability}]:[]})}function pactWeaponIndexes(resolved,registry){var _a;const pick=resolved.pactWeapon;if(!pick)return null;const out=new Set;const bare=bareEntitySlug(pick);((_a=resolved.definition.equipment)!=null?_a:[]).forEach((entry,i)=>{var _a2;if(typeof entry.item!=="string")return;const slugs=[unwrapSlug(entry.item),registry?(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.slug:void 0];if(slugs.some(s=>!!s&&(s===pick||bareEntitySlug(s)===bare)))out.add(i)});return out.size?out:null}function isWeaponSlugProficient(weapon,weaponSlug,profs){const wp=profs.weapons;if(wp.specific.some(e=>e===weaponSlug||normKey(e)===normKey(weapon.name)))return true;if(wp.specific.some(e=>qualifiedGrantCovers(e,weapon)))return true;const cat=weapon.category;if(typeof cat==="string"){if(/^simple\b/.test(cat)&&wp.categories.includes("simple"))return true;if(/^martial\b/.test(cat)&&wp.categories.includes("martial"))return true;if(wp.categories.includes(cat))return true}return false}function magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions){var _a,_b,_c,_d;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const ovr=(_a=entry.overrides)!=null?_a:{};const entryAttack=typeof ovr.bonus==="number"?ovr.bonus:0;const entryDamage=typeof ovr.damage_bonus==="number"?ovr.damage_bonus:0;const extra=typeof ovr.extra_damage==="string"?ovr.extra_damage:void 0;let itemAttack=0;let itemDamage=0;let sourceName;let itemName;let damageTypeOverride;let propertiesOverride;const informational=[];let itemRiders=[];let critRange;const conditionalCrits=[];if(entity&&isItemEntity(entity)){sourceName=entity.name;itemName=entity.name;damageTypeOverride=typeof entity.damage_type==="string"&&entity.damage_type.length>0?entity.damage_type:void 0;propertiesOverride=Array.isArray(entity.properties)&&entity.properties.length>0?entity.properties:void 0}if(entity&&isItemEntity(entity)&&itemBenefitsActive(entry,entity,registry,infusions==null?void 0:infusions.views.get(index))){const b=entity.bonuses;const atkOut=readNumericBonus(b==null?void 0:b.weapon_attack,ctx);const dmgOut=readNumericBonus(b==null?void 0:b.weapon_damage,ctx);if((atkOut==null?void 0:atkOut.kind)==="applied")itemAttack=atkOut.value;else if((atkOut==null?void 0:atkOut.kind)==="informational")informational.push({field:"weapon_attack",source:entity.name,value:atkOut.value,conditions:atkOut.conditions});if((dmgOut==null?void 0:dmgOut.kind)==="applied")itemDamage=dmgOut.value;else if((dmgOut==null?void 0:dmgOut.kind)==="informational")informational.push({field:"weapon_damage",source:entity.name,value:dmgOut.value,conditions:dmgOut.conditions});itemRiders=Array.isArray(entity.damage_riders)?entity.damage_riders.filter(r=>{var _a2;return((_a2=r.applies_to)!=null?_a2:"weapon")!=="spell"}).map(r=>({amount:r.amount,damage_type:r.damage_type,source:entity.name,...r.condition?{condition:r.condition}:{}})):[];for(const eff of itemRowEffects(entity)){if(eff.kind==="damage-bonus"&&((_b=eff.applies_to)!=null?_b:"weapon")!=="spell"){itemRiders.push({amount:eff.amount,damage_type:eff.damage_type,source:entity.name,...eff.condition?{condition:eff.condition}:{}})}else if(eff.kind==="crit-range"&&((_c=eff.applies_to)!=null?_c:"weapon")!=="spell"){if((_d=eff.condition)==null?void 0:_d.trim())conditionalCrits.push({minRoll:eff.min_roll,condition:eff.condition.trim(),source:entity.name});else critRange=Math.min(critRange!=null?critRange:20,eff.min_roll)}}}return{...critRange!==void 0&&critRange<20?{critRange}:{},...conditionalCrits.length?{conditionalCrits}:{},atk:itemAttack+entryAttack,dmg:itemDamage+entryDamage,extra,sourceName,itemName,damageTypeOverride,propertiesOverride,informational,riders:itemRiders}}function buildAttackRow(args){var _a,_b,_c,_d;const{id,name,weapon,baseDice,ability,mods,proficient,proficiencyBonus,magic,weaponMasteries}=args;const abilityMod=mods[ability];const pb=proficient?proficiencyBonus:0;const toHit=abilityMod+pb+magic.atk;const dmgFlat=abilityMod+magic.dmg;const formatDice=dice=>`${dice}${dmgFlat>=0?"+":""}${dmgFlat}`.replace(/\+0$/,"");const damageDice=formatDice(baseDice);const magicSource=magic.sourceName?`${magic.sourceName} bonus`:"Magic weapon";const toHitBreakdown=[{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficient?proficiencyBonus:0,kind:"ability"},{source:magicSource,amount:magic.atk,kind:"item"}];const damageBreakdown=[{source:"Base damage",amount:0,kind:"ability"},{source:`${ability.toUpperCase()} modifier`,amount:abilityMod,kind:"ability"},{source:magicSource,amount:magic.dmg,kind:"item"}];const modes=classifyWeaponRange(weapon);const fmtRanged=r=>r.long>r.normal?`${r.normal}/${r.long} ft.`:`${r.normal} ft.`;const range=modes.melee?`${modes.melee.reach} ft.`:modes.ranged?fmtRanged(modes.ranged):void 0;const thrownRange=modes.melee&&modes.ranged?fmtRanged(modes.ranged):void 0;const stringProps=weapon.properties.filter(p=>typeof p==="string");const finalProps=(_a=magic.propertiesOverride)!=null?_a:stringProps;const row={id,name,...range!==void 0?{range}:{},...thrownRange!==void 0?{thrownRange}:{},toHit,damageDice,damageType:(_b=magic.damageTypeOverride)!=null?_b:weapon.damage.type,...(()=>{const riders=[...magic.riders,...magic.extra?[{amount:magic.extra}]:[]];return riders.length?{damageRiders:riders}:{}})(),weaponCategory:modes.melee?"melee":"ranged",properties:finalProps,proficient,breakdown:{toHit:toHitBreakdown,damage:damageBreakdown},informational:args.magic.informational.length>0?args.magic.informational:void 0,slotKey:args.slotKey,subLabel:formatWeaponSubLabel(weapon,finalProps,modes),actionCost:args.actionCost,versatile:args.versatileDice?{damageDice:formatDice(args.versatileDice)}:void 0,...magic.critRange!==void 0?{critRange:magic.critRange}:{},...((_c=magic.conditionalCrits)==null?void 0:_c.length)?{conditionalCrits:magic.conditionalCrits}:{}};const mSlug=(_d=weapon.mastery)==null?void 0:_d[0];if(mSlug&&proficient&&weaponMasteries.includes(bareEntitySlug(weapon.slug))){const g=MASTERY[mSlug];if(g){const derived=masteryDerived(mSlug,mods[ability],proficiencyBonus);row.mastery={slug:mSlug,label:g.label,description:g.description,gist:masteryGist(mSlug),...derived?{derived}:{}}}}return row}function buildUnarmedRow(mods,proficiencyBonus,spec){var _a;const candidates=["str",...(_a=spec==null?void 0:spec.abilities)!=null?_a:[]];let ability="str";for(const ab of candidates)if(mods[ab]>=mods[ability])ability=ab;const abilityMod=mods[ability];const toHit=abilityMod+proficiencyBonus;const flat=`${abilityMod>=0?"+":""}${abilityMod}`.replace(/^\+0$/,"");const damageDice=(spec==null?void 0:spec.dice)?`${spec.dice}${flat}`:String(Math.max(0,1+abilityMod));const label=`${ability.toUpperCase()} modifier`;return{id:"unarmed-strike",name:"Unarmed Strike",unarmed:true,range:"5 ft.",toHit,damageDice,damageType:"bludgeoning",properties:[],proficient:true,breakdown:{toHit:[{source:label,amount:abilityMod,kind:"ability"},{source:"Proficiency bonus",amount:proficiencyBonus,kind:"ability"}],damage:[{source:"Base damage",amount:(spec==null?void 0:spec.dice)?0:1,kind:"ability"},{source:label,amount:abilityMod,kind:"ability"}]},subLabel:"Unarmed",actionCost:"action"}}function buildFeatureAttackRows(resolved,mods,profs,proficiencyBonus,weaponAbilities=[]){var _a,_b,_c;const rows=[];const abilities=weaponAbilities.filter(o=>!o.pactWeapon);for(const rf of(_a=resolved.features)!=null?_a:[]){if(rf.renderSuppressed||rf.buildOnly)continue;const featureId=(_b=rf.feature.id)!=null?_b:rf.feature.name;((_c=rf.feature.attacks)!=null?_c:[]).forEach((a,n)=>{var _a2,_b2,_c2,_d,_e,_f,_g;if(!a.weapon_category||a.type!=="melee"&&a.type!=="ranged"||typeof a.damage!=="string"||!a.damage.trim())return;const long=(_c2=(_a2=a.range)==null?void 0:_a2.long)!=null?_c2:(_b2=a.range)==null?void 0:_b2.normal;const weapon={name:a.name,slug:`feature-attack_${featureId}_${n}`,category:`${a.weapon_category}-${a.type}`,damage:{dice:a.damage.trim(),type:(_d=a.damage_type)!=null?_d:""},properties:((_e=a.properties)!=null?_e:[]).map(p=>p.trim().toLowerCase()),...((_f=a.range)==null?void 0:_f.normal)!==void 0&&long!==void 0?{range:{normal:a.range.normal,long}}:{},...a.mastery?{mastery:[a.mastery.trim().toLowerCase()]}:{}};const proficient=isWeaponSlugProficient(weapon,weapon.slug,profs);const row=buildAttackRow({id:`feature-attack:${rf.source.kind}:${rf.source.slug}:${featureId}:${n}`,name:a.name,weapon,baseDice:weapon.damage.dice,ability:attackAbility(weapon,mods,abilities),mods,proficient,proficiencyBonus,magic:{atk:0,dmg:0,informational:[],riders:[]},actionCost:(_g=a.action)!=null?_g:WEAPON_DEFAULT_ACTION_COST,weaponMasteries:a.mastery?[bareEntitySlug(weapon.slug)]:[]});row.grantedBy=rf.feature.name;rows.push(row)})}return rows}function humanizeWeaponToken(s){return s.replace(/[-_]/g," ").replace(/(^|[\s(])\w/g,c=>c.toUpperCase())}function formatWeaponSubLabel(weapon,properties,modes){const parts=[];if(weapon.category){const cat=modes.melee&&/ranged/.test(weapon.category)?weapon.category.replace("ranged","melee"):weapon.category;parts.push(humanizeWeaponToken(cat))}if(properties.length>0)parts.push(properties.map(humanizeWeaponToken).join(", "));return parts.join(" \xB7 ")}function computeAttacks(equippedSlots,equipment,mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities=[],infusions,pactIndexes=null){var _a,_b;const rows=[];const rowFor=(index,entry,weapon,slotKey,versatileDice)=>{var _a2,_b2,_c,_d,_e;const slugFromEntry=(_a2=unwrapSlug(entry.item))!=null?_a2:weapon.slug;const proficient=isWeaponSlugProficient(weapon,slugFromEntry,profs)||isWeaponSlugProficient(weapon,weapon.slug,profs);if(!proficient){warnings.push(`Character not proficient with ${weapon.name}; proficiency bonus excluded.`)}const isPact=(pactIndexes==null?void 0:pactIndexes.has(index))===true;const ability=attackAbility(weapon,mods,pactScopedAbilities(weaponAbilities,pactIndexes!==null,isPact));const magic=magicBonusesForWeaponEntry(entry,registry,ctx,index,infusions);const ovr=(_b2=entry.overrides)!=null?_b2:{};const row=buildAttackRow({id:`${index}:standard`,name:(_d=(_c=ovr.name)!=null?_c:magic.itemName)!=null?_d:weapon.name,weapon,baseDice:weapon.damage.dice,ability,mods,proficient,proficiencyBonus,magic,slotKey,actionCost:(_e=ovr.action)!=null?_e:WEAPON_DEFAULT_ACTION_COST,versatileDice,weaponMasteries});if(isPact)row.pactWeapon=true;return row};const handedSlots=[{key:"mainhand",placed:equippedSlots.mainhand},{key:"offhand",placed:equippedSlots.offhand}];for(const{key,placed}of handedSlots){if(!placed)continue;const{entity,entry}=placed;if(!entity)continue;const weapon=effectiveWeapon(entity,registry);if(!weapon){if(isItemEntity(entity)&&typeof entity.base_item==="string"&&!resolveBaseItem(entity.base_item,registry)){warnings.push(`Magic weapon ${entity.name} references missing base_item ${entity.base_item}.`)}continue}const versatileDice=key==="mainhand"&&hasProperty(weapon,"versatile")&&typeof weapon.damage.versatile_dice==="string"&&!equippedSlots.offhand?weapon.damage.versatile_dice:void 0;rows.push(rowFor(placed.index,entry,weapon,key,versatileDice))}const handIndex=new Set([(_a=equippedSlots.mainhand)==null?void 0:_a.index,(_b=equippedSlots.offhand)==null?void 0:_b.index]);equipment.forEach((entry,index)=>{if(!entry.equipped||handIndex.has(index))return;const{entity}=resolveEntryEntity(entry,index,registry,infusions);const weapon=effectiveWeapon(entity,registry);if(!weapon)return;rows.push(rowFor(index,entry,weapon))});return rows}function coerceWeight(raw){if(typeof raw==="number"&&Number.isFinite(raw)&&raw>=0)return raw;if(typeof raw==="string"){const n=Number.parseFloat(raw);if(Number.isFinite(n)&&n>=0)return n}return 0}function computeCarriedWeight(resolved,registry){var _a;const equipment=(_a=resolved.definition.equipment)!=null?_a:[];const view=resolveContainment(equipment,registry);const weightlessContainer=equipment.map(entry=>{var _a2,_b,_c;const data=(_a2=resolveBaseItem(entry.item,registry))==null?void 0:_a2.data;return((_c=(_b=data==null?void 0:data.container)==null?void 0:_b.capacity)==null?void 0:_c.weightless)===true});const exempt=i=>{for(let p=view.parentOf[i];p!==null;p=view.parentOf[p])if(weightlessContainer[p])return true;return false};let total=0;equipment.forEach((entry,i)=>{if(exempt(i))return;const found=resolveBaseItem(entry.item,registry);if(!found)return;const entity=found.data;const w=coerceWeight(entity.weight);if(w===0)return;const qty=typeof entry.qty==="number"&&entry.qty>=0?entry.qty:1;total+=w*qty});return total}function computeSlotsAndAttacks(resolved,mods,profs,registry,warnings,proficiencyBonus,weaponAbilities=[],weaponMasteries=[],attunementFloor=0){var _a,_b,_c,_d,_e;const equippedSlots=assignSlots(resolved,registry,warnings);twoHandedShieldWarnings((_a=resolved.definition.equipment)!=null?_a:[],registry,warnings,resolved.infusions);const overrides=(_b=resolved.definition.overrides)!=null?_b:{};const acOut=computeAC(equippedSlots,resolved,mods,registry,warnings);const ctx=buildConditionContext(resolved,equippedSlots,registry);const attacks=computeAttacks(equippedSlots,(_c=resolved.definition.equipment)!=null?_c:[],mods,profs,registry,warnings,proficiencyBonus,ctx,weaponMasteries,weaponAbilities,resolved.infusions,pactWeaponIndexes(resolved,registry));return{ac:acOut.ac,acBreakdown:acOut.breakdown,acInformational:acOut.informational,attacks,equippedSlots,carriedWeight:computeCarriedWeight(resolved,registry),attunementUsed:((_d=resolved.definition.equipment)!=null?_d:[]).filter(e=>e.attuned).length,attunementLimit:(_e=overrides.attunement_limit)!=null?_e:Math.max(3,attunementFloor)}}export{emptyAppliedBonuses,computeAppliedBonuses,pactWeaponIndexes,isWeaponSlugProficient,buildUnarmedRow,buildFeatureAttackRows,computeSlotsAndAttacks};
@@ -1 +1 @@
1
- import{CONDITION_SLUGS}from"./chunk-KM75CC6Q.js";import{z}from"zod";var conditionSlugEnum=z.enum(CONDITION_SLUGS);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var proficiencyTri=z.enum(["none","proficient","expertise"]);var slotEnum=z.enum(["mainhand","offhand","armor","shield"]);var equipmentEntryOverridesSchema=z.object({name:z.string().optional(),bonus:z.number().int().optional(),damage_bonus:z.number().int().optional(),extra_damage:z.string().optional(),ac_bonus:z.number().int().optional(),action:z.enum(["action","bonus-action","reaction","free","special"]).optional(),range:z.string().optional(),resist:z.array(z.string()).optional(),immune:z.array(z.string()).optional(),vulnerable:z.array(z.string()).optional(),condition_immune:z.array(z.string()).optional(),spell:z.string().optional(),spell_ability:abilityEnum.optional()}).strict();var equipmentEntryStateSchema=z.object({charges:z.object({current:z.number().int().nonnegative(),max:z.number().int().nonnegative()}).optional(),recovery:z.object({amount:z.string(),reset:z.enum(["dawn","short","long","special"])}).optional(),depletion_risk:z.object({trigger:z.string(),roll:z.string(),threshold:z.number().int(),effect:z.string()}).optional()}).strict();var entryRefField=z.preprocess(v=>typeof v==="number"?String(v):typeof v==="string"&&v.length>0?v:void 0,z.string().optional());var infusionMarkerSchema=z.object({kind:z.enum(["infused","created"]),by:z.string().min(1),seq:z.number().int().min(1),choice:z.string().min(1).optional(),charges:z.object({current:z.number().int().nonnegative()}).optional()});var equipmentEntrySchema=z.object({item:z.string().min(1),equipped:z.boolean().optional(),attuned:z.boolean().optional(),qty:z.number().int().positive().optional(),notes:z.string().optional(),slot:slotEnum.nullable().optional(),overrides:equipmentEntryOverridesSchema.optional(),state:equipmentEntryStateSchema.optional(),granted_by:z.string().optional(),id:entryRefField,in:entryRefField,infusion:infusionMarkerSchema.optional()});var characterOverridesShape=z.object({scores:z.partialRecord(abilityEnum,z.number().int()).optional(),saves:z.partialRecord(abilityEnum,z.object({bonus:z.number().int().optional(),proficient:z.boolean().optional()})).optional(),skills:z.partialRecord(skillEnum,z.object({bonus:z.number().int(),proficiency:proficiencyTri.optional()})).optional(),passives:z.object({perception:z.number().int().optional(),investigation:z.number().int().optional(),insight:z.number().int().optional()}).partial().optional(),hp:z.object({max:z.number().int().positive().optional(),rolled:z.number().int().positive().optional(),modifier:z.number().int().optional()}).optional(),ac:z.number().int().optional(),speed:z.number().int().optional(),initiative:z.number().int().optional(),spellcasting_ability_by_class:z.record(z.string(),abilityEnum).optional(),spellcasting_ability:abilityEnum.optional(),spell_slots:z.record(z.coerce.number().int(),z.number().int().nonnegative()).optional(),attunement_limit:z.number().int().nonnegative().optional(),languages:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),tools:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional(),proficiency:z.record(z.string(),proficiencyTri).optional()}).optional(),weapons:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),armor:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),defenses:z.object({resistances:z.object({remove:z.array(z.string()).optional()}).optional(),immunities:z.object({remove:z.array(z.string()).optional()}).optional(),vulnerabilities:z.object({remove:z.array(z.string()).optional()}).optional(),condition_immunities:z.object({remove:z.array(z.string()).optional()}).optional()}).optional()});var characterOverridesSchema=characterOverridesShape.default({});var characterStateSchema=z.object({hp:z.object({current:z.number().int(),max:z.number().int(),temp:z.number().int().nonnegative()}),hit_dice:z.record(z.string(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots:z.record(z.coerce.number().int(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots_pact:z.object({level:z.number().int().nonnegative(),used:z.number().int().nonnegative(),total:z.number().int().nonnegative()}).optional(),concentration:z.string().nullable().default(null),conditions:z.array(conditionSlugEnum).default([]),exhaustion:z.number().int().min(0).max(6).default(0),death_saves:z.object({successes:z.number().int().min(0).max(3),failures:z.number().int().min(0).max(3)}).optional(),inspiration:z.number().int().nonnegative().default(0),currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),feature_uses:z.record(z.string(),z.object({used:z.number().int().nonnegative(),max:z.number().int().nonnegative()})).default({}),feature_rolls:z.record(z.string(),z.array(z.number().int().refine(n=>n!==0&&Math.abs(n)<=999,"banked rolls are nonzero, |value| 1..999"))).default({}),active_buffs:z.array(z.string()).optional(),attuned_items:z.array(z.string()).optional()});var choiceValueSchema=z.union([z.string(),z.array(z.string()),z.record(z.string(),z.unknown())]).catch(ctx=>ctx.value);var classEntrySchema=z.object({name:z.string().min(1),level:z.number().int().min(1).max(20),subclass:z.string().nullable().default(null),choices:z.record(z.coerce.number().int(),z.record(z.string(),choiceValueSchema).catch(ctx=>ctx.value)).default({})});var spellOverrideSchema=z.object({slug:z.string().min(1),overrides:z.record(z.string(),z.unknown()).default({})});var knownSpellObjectSchema=z.object({spell:z.string().min(1),class:z.string().optional(),source:z.enum(["class","feat","item","race","domain"]).optional(),prepared:z.boolean().optional(),always_prepared:z.boolean().optional()}).strict();var knownSpellEntrySchema=z.union([z.string().min(1),knownSpellObjectSchema]);var sheetViewFilterSchema=z.object({show:z.array(z.string().min(1)).optional(),hide:z.array(z.string().min(1)).optional()});var sheetPoolViewSchema=z.object({show:z.enum(["known","granted","not-known"]).optional().catch(void 0),off:z.record(z.string(),z.array(z.string())).optional(),folded:z.array(z.string().min(1)).optional()});var sheetStateSchema=z.object({layout:z.object({saves:z.enum(["section"]).optional().catch(void 0),body:z.enum(["wide"]).optional().catch(void 0)}).optional(),favorites:z.array(z.string().min(1)).optional(),filters:z.object({actions:sheetViewFilterSchema.optional(),passive:sheetViewFilterSchema.optional()}).optional(),pools:z.record(z.string(),sheetPoolViewSchema).optional()});var characterSchema=z.object({name:z.string().min(1),edition:z.enum(["2014","2024"]),builder:z.boolean().optional(),alignment:z.string().optional(),age:z.string().optional(),race:z.string().nullable().default(null),subrace:z.string().nullable().default(null),background:z.string().nullable().default(null),class:z.array(classEntrySchema).default([]),origin_choices:z.record(z.string(),choiceValueSchema).default({}),abilities:z.object({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}),ability_method:z.enum(["standard-array","point-buy","archivist-point-buy","rolled","manual"]),builder_rolls:z.array(z.number().int()).optional(),builder_equipment_mode:z.enum(["starting","gold","empty"]).optional(),skills:z.object({proficient:z.array(skillEnum).default([]),expertise:z.array(skillEnum).default([])}).default({proficient:[],expertise:[]}),spells:z.object({known:z.array(knownSpellEntrySchema).default([]),overrides:z.array(spellOverrideSchema).default([]),view:z.enum(["by-level","table"]).optional()}).default({known:[],overrides:[]}),equipment:z.array(equipmentEntrySchema).default([]),overrides:characterOverridesSchema,currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),additional_features:z.array(z.string().min(1)).default([]),notes:z.string().optional(),defenses:z.object({resistances:z.array(z.string()).default([]),immunities:z.array(z.string()).default([]),vulnerabilities:z.array(z.string()).default([]),condition_immunities:z.array(z.string()).default([])}).partial().optional(),sheet:sheetStateSchema.optional(),state:characterStateSchema});export{characterOverridesShape,characterSchema};
1
+ import{CONDITION_SLUGS}from"./chunk-KM75CC6Q.js";import{z}from"zod";var conditionSlugEnum=z.enum(CONDITION_SLUGS);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var skillEnum=z.enum(["acrobatics","animal-handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight-of-hand","stealth","survival"]);var proficiencyTri=z.enum(["none","proficient","expertise"]);var slotEnum=z.enum(["mainhand","offhand","armor","shield"]);var equipmentEntryOverridesSchema=z.object({name:z.string().optional(),bonus:z.number().int().optional(),damage_bonus:z.number().int().optional(),extra_damage:z.string().optional(),ac_bonus:z.number().int().optional(),action:z.enum(["action","bonus-action","reaction","free","special"]).optional(),range:z.string().optional(),resist:z.array(z.string()).optional(),immune:z.array(z.string()).optional(),vulnerable:z.array(z.string()).optional(),condition_immune:z.array(z.string()).optional(),spell:z.string().optional(),spell_ability:abilityEnum.optional()}).strict();var equipmentEntryStateSchema=z.object({charges:z.object({current:z.number().int().nonnegative(),max:z.number().int().nonnegative()}).optional(),recovery:z.object({amount:z.string(),reset:z.enum(["dawn","short","long","special"])}).optional(),depletion_risk:z.object({trigger:z.string(),roll:z.string(),threshold:z.number().int(),effect:z.string()}).optional()}).strict();var entryRefField=z.preprocess(v=>typeof v==="number"?String(v):typeof v==="string"&&v.length>0?v:void 0,z.string().optional());var infusionMarkerSchema=z.object({kind:z.enum(["infused","created"]),by:z.string().min(1),seq:z.number().int().min(1),choice:z.string().min(1).optional(),charges:z.object({current:z.number().int().nonnegative()}).optional()});var equipmentEntrySchema=z.object({item:z.string().min(1),equipped:z.boolean().optional(),attuned:z.boolean().optional(),qty:z.number().int().positive().optional(),notes:z.string().optional(),slot:slotEnum.nullable().optional(),overrides:equipmentEntryOverridesSchema.optional(),state:equipmentEntryStateSchema.optional(),granted_by:z.string().optional(),id:entryRefField,in:entryRefField,infusion:infusionMarkerSchema.optional()});var characterOverridesShape=z.object({scores:z.partialRecord(abilityEnum,z.number().int()).optional(),saves:z.partialRecord(abilityEnum,z.object({bonus:z.number().int().optional(),proficient:z.boolean().optional()})).optional(),skills:z.partialRecord(skillEnum,z.object({bonus:z.number().int(),proficiency:proficiencyTri.optional()})).optional(),passives:z.object({perception:z.number().int().optional(),investigation:z.number().int().optional(),insight:z.number().int().optional()}).partial().optional(),hp:z.object({max:z.number().int().positive().optional(),rolled:z.number().int().positive().optional(),modifier:z.number().int().optional()}).optional(),ac:z.number().int().optional(),speed:z.number().int().optional(),initiative:z.number().int().optional(),spellcasting_ability_by_class:z.record(z.string(),abilityEnum).optional(),spellcasting_ability:abilityEnum.optional(),spell_slots:z.record(z.coerce.number().int(),z.number().int().nonnegative()).optional(),attunement_limit:z.number().int().nonnegative().optional(),languages:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),tools:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional(),proficiency:z.record(z.string(),proficiencyTri).optional()}).optional(),weapons:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),armor:z.object({add:z.array(z.string()).optional(),remove:z.array(z.string()).optional()}).optional(),defenses:z.object({resistances:z.object({remove:z.array(z.string()).optional()}).optional(),immunities:z.object({remove:z.array(z.string()).optional()}).optional(),vulnerabilities:z.object({remove:z.array(z.string()).optional()}).optional(),condition_immunities:z.object({remove:z.array(z.string()).optional()}).optional()}).optional()});var characterOverridesSchema=characterOverridesShape.default({});var characterStateSchema=z.object({hp:z.object({current:z.number().int(),max:z.number().int(),temp:z.number().int().nonnegative()}),hit_dice:z.record(z.string(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots:z.record(z.coerce.number().int(),z.object({used:z.number().int().nonnegative(),total:z.number().int().nonnegative()})).default({}),spell_slots_pact:z.object({level:z.number().int().nonnegative(),used:z.number().int().nonnegative(),total:z.number().int().nonnegative()}).optional(),concentration:z.string().nullable().default(null),conditions:z.array(conditionSlugEnum).default([]),exhaustion:z.number().int().min(0).max(6).default(0),death_saves:z.object({successes:z.number().int().min(0).max(3),failures:z.number().int().min(0).max(3)}).optional(),inspiration:z.number().int().nonnegative().default(0),currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),feature_uses:z.record(z.string(),z.object({used:z.number().int().nonnegative(),max:z.number().int().nonnegative()})).default({}),feature_rolls:z.record(z.string(),z.array(z.number().int().refine(n=>n!==0&&Math.abs(n)<=999,"banked rolls are nonzero, |value| 1..999"))).default({}),active_buffs:z.array(z.string()).optional(),attuned_items:z.array(z.string()).optional()});var choiceValueSchema=z.union([z.string(),z.array(z.string()),z.record(z.string(),z.unknown())]).catch(ctx=>ctx.value);var classEntrySchema=z.object({name:z.string().min(1),level:z.number().int().min(1).max(20),subclass:z.string().nullable().default(null),choices:z.record(z.coerce.number().int(),z.record(z.string(),choiceValueSchema).catch(ctx=>ctx.value)).default({})});var spellOverrideSchema=z.object({slug:z.string().min(1),overrides:z.record(z.string(),z.unknown()).default({})});var knownSpellObjectSchema=z.object({spell:z.string().min(1),class:z.string().optional(),source:z.enum(["class","feat","item","race","domain"]).optional(),prepared:z.boolean().optional(),always_prepared:z.boolean().optional()}).strict();var knownSpellEntrySchema=z.union([z.string().min(1),knownSpellObjectSchema]);var sheetViewFilterSchema=z.object({show:z.array(z.string().min(1)).optional(),hide:z.array(z.string().min(1)).optional()});var sheetPoolViewSchema=z.object({show:z.enum(["known","granted","not-known"]).optional().catch(void 0),off:z.record(z.string(),z.array(z.string())).optional(),folded:z.array(z.string().min(1)).optional()});var sheetStateSchema=z.object({layout:z.object({saves:z.enum(["section"]).optional().catch(void 0),body:z.enum(["wide"]).optional().catch(void 0)}).optional(),favorites:z.array(z.string().min(1)).optional(),filters:z.object({actions:sheetViewFilterSchema.optional(),passive:sheetViewFilterSchema.optional()}).optional(),pools:z.record(z.string(),sheetPoolViewSchema).optional()});var characterSchema=z.object({name:z.string().min(1),edition:z.enum(["2014","2024"]),builder:z.boolean().optional(),alignment:z.string().optional(),age:z.string().optional(),race:z.string().nullable().default(null),subrace:z.string().nullable().default(null),background:z.string().nullable().default(null),class:z.array(classEntrySchema).default([]),origin_choices:z.record(z.string(),choiceValueSchema).default({}),abilities:z.object({str:z.number().int(),dex:z.number().int(),con:z.number().int(),int:z.number().int(),wis:z.number().int(),cha:z.number().int()}),ability_method:z.enum(["standard-array","point-buy","archivist-point-buy","rolled","manual"]),builder_rolls:z.array(z.number().int()).optional(),builder_equipment_mode:z.enum(["starting","gold","empty"]).optional(),skills:z.object({proficient:z.array(skillEnum).default([]),expertise:z.array(skillEnum).default([]),half:z.array(skillEnum).optional()}).default({proficient:[],expertise:[]}),spells:z.object({known:z.array(knownSpellEntrySchema).default([]),overrides:z.array(spellOverrideSchema).default([]),view:z.enum(["by-level","table"]).optional()}).default({known:[],overrides:[]}),equipment:z.array(equipmentEntrySchema).default([]),overrides:characterOverridesSchema,currency:z.object({cp:z.number().int().nonnegative(),sp:z.number().int().nonnegative(),ep:z.number().int().nonnegative(),gp:z.number().int().nonnegative(),pp:z.number().int().nonnegative()}).optional(),additional_features:z.array(z.string().min(1)).default([]),notes:z.string().optional(),defenses:z.object({resistances:z.array(z.string()).default([]),immunities:z.array(z.string()).default([]),vulnerabilities:z.array(z.string()).default([]),condition_immunities:z.array(z.string()).default([])}).partial().optional(),sheet:sheetStateSchema.optional(),state:characterStateSchema});export{characterOverridesShape,characterSchema};
@@ -1 +1 @@
1
- import{parseClass}from"./chunk-RQGTBHJW.js";import yaml from"js-yaml";var classCodec={parse(doc){return parseClass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{classCodec};
1
+ import{parseClass}from"./chunk-XPF53K54.js";import yaml from"js-yaml";var classCodec={parse(doc){return parseClass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{classCodec};
@@ -1 +1 @@
1
- import{subclassEntitySchema}from"./chunk-7J5BNH2D.js";import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseSubclass(source){const raw=parseYaml(source,["name","slug","parent_class"]);if(!raw.success)return raw;aliasFeaturesByLevelActionCost(raw.data.features_by_level);const result=subclassEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`subclass schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseSubclass};
1
+ import{subclassEntitySchema}from"./chunk-ONCXJMJM.js";import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseSubclass(source){const raw=parseYaml(source,["name","slug","parent_class"]);if(!raw.success)return raw;aliasFeaturesByLevelActionCost(raw.data.features_by_level);const result=subclassEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`subclass schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseSubclass};
@@ -0,0 +1 @@
1
+ import{normalizeRollScope}from"./chunk-FOLHTMSC.js";import{toProfSlug}from"./chunk-VTQ4RWEG.js";import{memberSpellTargets}from"./chunk-WAUNLUFQ.js";import{heldPicks}from"./chunk-PKIMOVQG.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{bareEntitySlug}from"./chunk-63YJPWTM.js";import{normalizeAbility}from"./chunk-EVT7MGAC.js";function emptyFeatureEffectTotals(){return{initiative_bonus:0,initiative_terms:[],initiative_amount_terms:[],skill_bonus_terms:[],save_bonus_terms:[],half_proficiency_terms:[],hp_per_level_bonus:0,hp_per_level_terms:[],speed_walk_bonus:0,speed_walk_terms:[],speed_terms:[],ignore_armor_strength:[],speed_walk_set:0,attunement_set:0,ability_bonus:{},senses:{darkvision:0,blindsight:0,tremorsense:0,truesight:0},ac_terms:[],resistances:[],immunities:[],vulnerabilities:[],condition_immunities:[],proficiencies:{skills:[],skillExpertise:[],tools:[],languages:[],saves:[],armor:[],weapons:[]},weaponAbilities:[],rollModifiers:[],saveOutcomes:[],critRange:20,conditionalCrits:[],extraAttack:0,scopedExtraAttacks:[],attackNotes:[],damageBonuses:[],spellDamageBonuses:[]}}function pushUnique(list,value){const key=value.trim().toLowerCase();if(!key)return;if(!list.some(v=>v.trim().toLowerCase()===key))list.push(value.trim())}function pushDefenseGrant(list,value,source,condition,item){var _a;const key=value.trim().toLowerCase();if(!key)return;const existing=list.find(g=>g.value.trim().toLowerCase()===key);if(existing){if(!existing.sources.includes(source))existing.sources.push(source);if(!existing.condition&&condition)existing.condition=condition;if(item)mergeDefenseItems((_a=existing.items)!=null?_a:existing.items=[],[item]);return}list.push({value:value.trim(),sources:[source],...condition?{condition}:{},...item?{items:[item]}:{}})}function mergeDefenseItems(into,from){for(const it of from)if(!into.some(x=>x.index===it.index))into.push({...it})}function ownerItem(owner,label){return(owner==null?void 0:owner.kind)==="item"?{index:owner.index,name:label}:void 0}var NAMED_COLUMN=/^column\(\s*'([^']+)'\s*\)$/;function foldsNow(rf,activeBuffs){if(rf.feature.activatable!==true)return true;const id=rf.feature.id;return!!id&&activeBuffs.has(id)}function assembleEffectFeatures(resolved){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j;const activeBuffs=new Set((_b=(_a=resolved.state)==null?void 0:_a.active_buffs)!=null?_b:[]);const featureIds=new Set(((_c=resolved.features)!=null?_c:[]).map(f=>f.feature.id).filter(id=>!!id));const aliases=[];for(const pool of(_d=resolved.pools)!=null?_d:[]){for(const entry of[...(_e=pool.selected)!=null?_e:[],...(_f=pool.grants)!=null?_f:[]]){if(activeBuffs.has(entry.slug))continue;const bare=bareEntitySlug(entry.slug);for(const stored of activeBuffs){if(featureIds.has(stored))continue;if(bareEntitySlug(stored)===bare){aliases.push(entry.slug);break}}}}for(const a of aliases)activeBuffs.add(a);const buffFeatures=[];const pushBoon=(item,pool)=>{var _a2,_b2,_c2,_d2,_e2,_f2,_g2,_h2,_i2,_j2,_k;const e=item.entity;if(!e||item.itemBound===true||((_b2=(_a2=e.effects)==null?void 0:_a2.length)!=null?_b2:0)===0)return;const block=(_f2=(_e2=(_d2=(_c2=resolved.classes)==null?void 0:_c2[pool.classIndex])==null?void 0:_d2.choices)==null?void 0:_e2[pool.anchorLevel])!=null?_f2:{};const spellTargets=memberSpellTargets(e,id=>{var _a3;return block[`${pool.id}:${(_a3=item.key)!=null?_a3:item.slug}:${id}`]});buffFeatures.push({feature:{id:item.slug,name:e.name,activatable:(_g2=e.activatable)!=null?_g2:false,effects:e.effects},source:{kind:"class",slug:(_k=(_j2=(_i2=(_h2=resolved.classes)==null?void 0:_h2[pool.classIndex])==null?void 0:_i2.entity)==null?void 0:_j2.slug)!=null?_k:pool.id,level:pool.anchorLevel},...spellTargets?{spellTargets}:{}})};for(const pool of(_g=resolved.pools)!=null?_g:[]){for(const sel of heldPicks(pool))pushBoon(sel,pool);for(const g of(_h=pool.grants)!=null?_h:[])pushBoon(g,pool)}return{features:[...(_i=resolved.features)!=null?_i:[],...buffFeatures,...(_j=resolved.itemFeatures)!=null?_j:[]],activeBuffs}}function foldsOnSelf(eff){if(eff.subject===void 0||eff.subject==="self")return true;warnOnce(eff.subject,`archivist: unrecognised effect subject "${eff.subject}" (only "self" folds)`);return false}function selfEffectsOf(f){var _a;return((_a=f.effects)!=null?_a:[]).filter(foldsOnSelf)}function computeFeatureEffects(features,opts){var _a,_b,_c;const out=emptyFeatureEffectTotals();for(const rf of features){if(!foldsNow(rf,(_a=opts==null?void 0:opts.activeBuffs)!=null?_a:new Set))continue;const level=(_b=opts==null?void 0:opts.levelFor)==null?void 0:_b.call(opts,rf.source);for(const eff of selfEffectsOf(rf.feature)){const effect=columnScaledRider(eff,rf,level,opts==null?void 0:opts.tableDiceFor,opts==null?void 0:opts.tableCellFor);if(effect)applyEffect(out,effect,(_c=rf.feature.name)!=null?_c:"Feature",level,rf.source,rf.spellTargets)}}return out}function classifyProficiencyEffect(eff){if(eff.kind!=="proficiency")return null;const raw=eff.value;const expertise=eff.expertise===true;switch(eff.proficiency_type){case"skill":return{bucket:"skills",value:toProfSlug(raw),raw,expertise};case"tool":return{bucket:"tools",value:toProfSlug(raw),raw,expertise};case"language":return{bucket:"languages",value:toProfSlug(raw),raw,expertise};case"armor":return{bucket:"armor",value:raw.toLowerCase(),raw,expertise};case"weapon":return{bucket:"weapons",value:raw.toLowerCase(),raw,expertise};default:{const ab=normalizeAbility(raw);return ab?{bucket:"saves",value:ab,raw,expertise}:null}}}function collectProficiencyEffectGrants(features,activeBuffs){const out={skills:[],tools:[],languages:[],saves:[],armor:[],weapons:[]};for(const rf of features){if(!foldsNow(rf,activeBuffs))continue;for(const eff of selfEffectsOf(rf.feature)){const c=classifyProficiencyEffect(eff);if(!c)continue;out[c.bucket].push({value:c.value,raw:c.raw,sourceKind:rf.source.kind,sourceSlug:rf.source.slug,...c.expertise?{expertise:true}:{}})}}return out}function scaled(base,key,scalesAt,level){if(level===void 0||!(scalesAt==null?void 0:scalesAt.length))return base;let best=base;let bestLevel=-1;for(const step of scalesAt){if(step.level>level||step.level<=bestLevel)continue;const v=step[key];if(typeof v!=="number")continue;best=v;bestLevel=step.level}return best}function columnScaledRider(eff,rf,level,tableDiceFor,tableCellFor){var _a;if(eff.kind!=="damage-bonus")return eff;const named=NAMED_COLUMN.exec(eff.amount.trim());if(named){const cell=(_a=tableCellFor==null?void 0:tableCellFor(rf.source,named[1]))!=null?_a:null;return cell?{...eff,amount:cell}:null}if(level===void 0||!tableDiceFor)return eff;const src=rf.source;const column=rf.feature.name;if(src.kind!=="class"&&src.kind!=="subclass"||!column)return eff;const atGain=tableDiceFor(src,column,src.level);if(!atGain||atGain.toLowerCase()!==eff.amount.trim().toLowerCase())return eff;const now=tableDiceFor(src,column,level);return now?{...eff,amount:now}:eff}function riderScope(appliesTo){if(appliesTo===void 0||appliesTo==="all"||appliesTo==="spell")return void 0;return Array.isArray(appliesTo)?[...appliesTo]:[appliesTo]}function applyEffect(out,eff,label,level,owner,targets){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o;switch(eff.kind){case"initiative-bonus":if(typeof eff.value==="number"){out.initiative_bonus+=eff.value;out.initiative_terms.push({label,value:eff.value})}else if(typeof eff.amount==="string"){out.initiative_amount_terms.push({label,amount:eff.amount,...owner?{owner}:{}})}break;case"skill-bonus":out.skill_bonus_terms.push({skills:eff.skills.map(toProfSlug),ability:eff.ability,minimum:(_a=eff.minimum)!=null?_a:0,label});break;case"save-bonus":out.save_bonus_terms.push({saves:[...(_b=eff.saves)!=null?_b:[]],ability:eff.ability,minimum:(_c=eff.minimum)!=null?_c:0,...eff.inactive_while?{inactiveWhile:eff.inactive_while}:{},label});break;case"half-proficiency":out.half_proficiency_terms.push({skills:((_d=eff.skills)!=null?_d:[]).map(toProfSlug),round:(_e=eff.round)!=null?_e:"down",label});break;case"hp-per-level-bonus":out.hp_per_level_bonus+=eff.value;out.hp_per_level_terms.push({label,value:eff.value});break;case"speed-bonus":{const gate=eff.inactive_while===void 0?void 0:[].concat(eff.inactive_while);const qualifiers={...eff.condition?{condition:eff.condition}:{},...gate?{inactiveWhile:gate}:{}};if(eff.equal_to==="walk"){out.speed_terms.push({mode:eff.mode,label,value:0,set:false,equalsWalk:true,...qualifiers});break}const value=scaled((_f=eff.value)!=null?_f:0,"value",eff.scales_at,level);out.speed_terms.push({mode:eff.mode,label,value,set:eff.set===true,...qualifiers});if(eff.mode==="walk"&&!gate){if(eff.set)out.speed_walk_set=Math.max(out.speed_walk_set,value);else{out.speed_walk_bonus+=value;out.speed_walk_terms.push({label,value})}}break}case"speed-rule":if(eff.flag==="ignore-armor-strength")out.ignore_armor_strength.push(label);break;case"attunement-limit":{out.attunement_set=Math.max(out.attunement_set,scaled(eff.value,"value",eff.scales_at,level));break}case"sense":out.senses[eff.type]=Math.max(out.senses[eff.type],eff.range);break;case"resistance":pushDefenseGrant(out.resistances,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"immunity":pushDefenseGrant(out.immunities,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"vulnerability":pushDefenseGrant(out.vulnerabilities,eff.damage_type,label,eff.condition,ownerItem(owner,label));break;case"immune-condition":if(!eff.while)pushDefenseGrant(out.condition_immunities,eff.condition,label,void 0,ownerItem(owner,label));else if((owner==null?void 0:owner.kind)==="item")pushDefenseGrant(out.condition_immunities,eff.condition,label,eff.while,ownerItem(owner,label));break;case"proficiency":{const c=classifyProficiencyEffect(eff);if(!c)break;if(c.bucket==="saves"){pushUnique(out.proficiencies.saves,c.value)}else{pushUnique(out.proficiencies[c.bucket],c.value)}if(c.expertise&&c.bucket==="skills")pushUnique(out.proficiencies.skillExpertise,c.value);break}case"ac-bonus":out.ac_terms.push({value:eff.value,requires_armor:eff.requires_armor===true,label,condition:eff.condition});break;case"weapon-ability":{if(eff.ability!=="spellcasting"){const w=eff.weapons;if(w==="pact-weapon"){out.weaponAbilities.push({ability:eff.ability,pactWeapon:true});break}const weaponSlugs=!w||w==="chosen"?void 0:Array.isArray(w)?w.map(bareEntitySlug):[bareEntitySlug(w)];out.weaponAbilities.push({ability:eff.ability,weaponSlugs})}break}case"roll-modifier":{const rolls=eff.roll==="any"?["ability-check","saving-throw","attack"]:[eff.roll];const scopes=(_g=normalizeRollScope(eff.scope,rolls[0]))!=null?_g:[eff.scope];for(const roll of rolls)for(const scope of scopes)out.rollModifiers.push({mode:eff.mode,roll,scope,condition:eff.condition,label});break}case"save-outcome":out.saveOutcomes.push({ability:eff.ability==="any"?void 0:eff.ability,on_success:eff.on_success,on_failure:eff.on_failure,appliesTo:(_h=eff.applies_to)!=null?_h:void 0,condition:eff.condition,label});break;case"crit-range":if(((_i=eff.applies_to)!=null?_i:"weapon")==="spell")break;if((_j=eff.condition)==null?void 0:_j.trim())out.conditionalCrits.push({minRoll:eff.min_roll,condition:eff.condition.trim(),source:label});else out.critRange=Math.min(out.critRange,eff.min_roll);break;case"extra-attack":{const count=scaled(eff.count,"count",eff.scales_at,level);const scope=riderScope(eff.applies_to);if(scope)out.scopedExtraAttacks.push({count,scope});else out.extraAttack=Math.max(out.extraAttack,count)}break;case"reroll-damage":{const qualifiers=[eff.once_per_die?"once/die":"",(_l=(_k=eff.condition)==null?void 0:_k.trim())!=null?_l:""].filter(q=>q!=="");out.attackNotes.push(`Reroll ${eff.max_reroll}s${qualifiers.length?` (${qualifiers.join(", ")})`:""}`)}break;case"attack-rule":if(eff.flag==="no-ranged-in-melee-disadvantage")out.attackNotes.push("No disadvantage firing in melee");break;case"damage-bonus":if(((_m=eff.applies_to)!=null?_m:"weapon")!=="spell"){const scope=riderScope(eff.applies_to);out.damageBonuses.push({amount:eff.amount,damage_type:eff.damage_type,source:label,...eff.condition?{condition:eff.condition}:{},...scope?{scope}:{},...owner?{owner}:{}})}if(eff.applies_to==="spell"||eff.applies_to==="all"){const spellScope=(_n=eff.spell_scope)!=null?_n:eff.applies_to==="all"?{}:void 0;out.spellDamageBonuses.push({amount:eff.amount,damage_type:eff.damage_type,source:label,...eff.condition?{condition:eff.condition}:{},...owner?{owner}:{},...targets?{targets}:{},...spellScope?{scope:spellScope}:{}})}break;case"ability-score-increase":if(eff.abilities==="chosen")break;for(const ab of eff.abilities)out.ability_bonus[ab]=((_o=out.ability_bonus[ab])!=null?_o:0)+eff.amount;break;default:break}}export{emptyFeatureEffectTotals,pushDefenseGrant,mergeDefenseItems,foldsNow,assembleEffectFeatures,foldsOnSelf,selfEffectsOf,computeFeatureEffects,classifyProficiencyEffect,collectProficiencyEffectGrants};
@@ -1 +1 @@
1
- import{parseOptionalFeature}from"./chunk-DZKSXSJF.js";import yaml from"js-yaml";var optionalFeatureCodec={parse(doc){return parseOptionalFeature(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{optionalFeatureCodec};
1
+ import{parseOptionalFeature}from"./chunk-SFK57JAA.js";import yaml from"js-yaml";var optionalFeatureCodec={parse(doc){return parseOptionalFeature(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{optionalFeatureCodec};
@@ -1 +1 @@
1
- import{actionCostEnum,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-KBFSJ5WE.js";import{featureEffectSchema}from"./chunk-6IC53O3Q.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var categoryEnum=z.enum(["origin","general","fighting-style","epic-boon"]);var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("level"),min:z.number().int().positive()}),z.object({kind:z.literal("spellcaster")}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["armor","weapon","tool","skill","saving-throw"]),value:z.string().min(1)}),z.object({kind:z.literal("race"),slug:z.string().min(1)}),z.object({kind:z.literal("class"),slug:z.string().min(1)}),z.object({kind:z.literal("feat"),slug:z.string().min(1)}),z.object({kind:z.literal("campaign"),slug:z.string().min(1)}),z.object({kind:z.literal("exclusive-feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("feature"),slug:z.string().min(1)}),z.object({kind:z.literal("other"),detail:z.string().min(1)}),z.object({kind:z.literal("feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("background"),slug:z.string().min(1)})]);var featEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),category:categoryEnum,description:z.string(),prerequisites:z.array(prerequisiteSchema),benefits:z.array(z.string()),effects:z.array(featureEffectSchema),grants_asi:z.object({amount:z.number().int().positive(),pool:z.array(abilityEnum).optional()}).nullable(),repeatable:z.boolean(),choices:z.array(choiceSchema),rendering_hint:z.string().optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),trait_tags:z.unknown().optional(),optionalfeature_progression:z.array(progressionSchema).optional(),resources:z.array(resourceSchema).optional(),action_cost:actionCostEnum.optional(),image:imageField});export{featEntitySchema};
1
+ import{actionCostEnum,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-LHH5XSEA.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var categoryEnum=z.enum(["origin","general","fighting-style","epic-boon"]);var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("level"),min:z.number().int().positive()}),z.object({kind:z.literal("spellcaster")}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["armor","weapon","tool","skill","saving-throw"]),value:z.string().min(1)}),z.object({kind:z.literal("race"),slug:z.string().min(1)}),z.object({kind:z.literal("class"),slug:z.string().min(1)}),z.object({kind:z.literal("feat"),slug:z.string().min(1)}),z.object({kind:z.literal("campaign"),slug:z.string().min(1)}),z.object({kind:z.literal("exclusive-feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("feature"),slug:z.string().min(1)}),z.object({kind:z.literal("other"),detail:z.string().min(1)}),z.object({kind:z.literal("feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("background"),slug:z.string().min(1)})]);var featEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),category:categoryEnum,description:z.string(),prerequisites:z.array(prerequisiteSchema),benefits:z.array(z.string()),effects:z.array(featureEffectSchema),grants_asi:z.object({amount:z.number().int().positive(),pool:z.array(abilityEnum).optional()}).nullable(),repeatable:z.boolean(),choices:z.array(choiceSchema),rendering_hint:z.string().optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),trait_tags:z.unknown().optional(),optionalfeature_progression:z.array(progressionSchema).optional(),resources:z.array(resourceSchema).optional(),action_cost:actionCostEnum.optional(),image:imageField});export{featEntitySchema};
@@ -1 +1 @@
1
- import{featureObjectSchema}from"./chunk-V6NQ547U.js";import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var str=z.string();var num=z.number();var bool=z.boolean();var strArr=z.array(z.string());var damageQualifierSchema=z.object({get types(){return z.array(z.union([str,damageQualifierSchema])).optional()},note:str.optional(),pre_note:str.optional(),cond:bool.optional(),special:str.optional()});var qualifierList=z.array(z.union([str,damageQualifierSchema])).optional();var speedValue=z.union([num,z.object({number:num,condition:str.optional()})]);var monsterSpeedSchema=z.object({walk:speedValue.optional(),fly:speedValue.optional(),swim:speedValue.optional(),climb:speedValue.optional(),burrow:speedValue.optional(),hover:bool.optional(),can_hover:bool.optional(),alternate:z.record(str,z.array(z.object({number:num,condition:str.optional()}))).optional(),choose:z.object({from:strArr,amount:num,note:str.optional()}).optional()});var monsterTypeSchema=z.object({type:z.union([str,z.object({choose:strArr})]),tags:z.array(z.union([str,z.object({tag:str,prefix:str,prefix_hidden:bool.optional()})])).optional(),sidekick_type:str.optional(),sidekick_tags:strArr.optional(),swarm_size:str.optional(),sidekick_hidden:bool.optional()});var monsterCRSchema=z.object({cr:str,lair:str.optional(),coven:str.optional(),xp:num.optional(),xp_lair:num.optional()});var monsterACSchema=z.object({ac:num.optional(),from:strArr.optional(),condition:str.optional(),braces:bool.optional(),special:str.optional()});var monsterHPSchema=z.object({average:num.optional(),formula:str.optional(),special:str.optional()});var alignmentEntrySchema=z.object({alignment:strArr.optional(),chance:num.optional(),note:str.optional(),special:str.optional()});var spellEntry=z.union([str,z.object({entry:str,hidden:bool.optional()})]);var spellList=z.array(spellEntry);var spellLevel=z.object({slots:num.optional(),lower:num.optional(),spells:strArr});var monsterSpellcastingSchema=z.object({name:str.optional(),type:str.optional(),headerEntries:strArr.optional(),footerEntries:strArr.optional(),ability:str.optional(),displayAs:str.optional(),hidden:strArr.optional(),spells:z.record(str,spellLevel).optional(),will:spellList.optional(),ritual:spellList.optional(),daily:z.record(str,spellList).optional(),rest:z.record(str,spellList).optional(),restLong:z.record(str,spellList).optional(),recharge:z.record(str,spellList).optional(),legendary:z.record(str,spellList).optional(),charges:z.record(str,spellList).optional(),chargesItem:str.optional()});var initiativeSchema=z.union([num,z.object({proficiency:num.optional(),advantage_mode:str.optional()})]);var gearEntrySchema=z.union([str,z.object({item:str,quantity:num.optional(),displayName:str.optional()})]);var featureArr=z.array(featureObjectSchema).optional();var monsterSchema=z.object({name:str.min(1),size:z.union([str,strArr]).optional(),size_note:str.optional(),type:z.union([str,monsterTypeSchema]).optional(),subtype:str.optional(),alignment:z.union([str,z.array(z.union([str,alignmentEntrySchema]))]).optional(),alignment_prefix:str.optional(),cr:z.union([str,monsterCRSchema]).optional(),pb_note:str.optional(),ac:z.array(monsterACSchema).optional(),hp:monsterHPSchema.optional(),speed:monsterSpeedSchema.optional(),abilities:z.object({str:num,dex:num,con:num,int:num,wis:num,cha:num}).optional(),saves:z.record(str,num).optional(),skills:z.record(str,num).optional(),skills_other:z.array(z.unknown()).optional(),senses:strArr.nullable().optional(),passive_perception:num.optional(),languages:strArr.nullable().optional(),damage_vulnerabilities:qualifierList,damage_resistances:qualifierList,damage_immunities:qualifierList,condition_immunities:qualifierList,traits:featureArr,actions:featureArr,bonus_actions:featureArr,reactions:featureArr,legendary_actions:featureArr,mythic:featureArr,mythic_header:strArr.optional(),legendary_action_uses:num.optional(),legendary_resistance:num.optional(),legendary_actions_lair_count:num.optional(),section_headers:z.array(z.object({section:str,header:strArr})).optional(),action_note:str.optional(),reaction_note:str.optional(),spellcasting:z.array(monsterSpellcastingSchema).optional(),legendary_group:z.object({name:str,source:str}).optional(),lair_actions:z.array(z.unknown()).optional(),regional_actions:z.array(z.unknown()).optional(),variant:z.array(z.unknown()).optional(),initiative:initiativeSchema.optional(),gear:z.array(gearEntrySchema).optional(),is_named_creature:bool.optional(),is_npc:bool.optional(),familiar:bool.optional(),short_name:z.union([str,bool]).optional(),level:num.optional(),dragon_age:str.optional(),dragon_casting_color:str.optional(),environment:strArr.optional(),treasure:strArr.optional(),attached_items:strArr.optional(),group:strArr.nullable().optional(),summoned_by_spell:str.optional(),summoned_by_spell_level:num.optional(),summoned_by_class:str.optional(),trait_tags:strArr.optional(),action_tags:strArr.optional(),sense_tags:strArr.optional(),language_tags:strArr.optional(),spellcasting_tags:strArr.optional(),misc_tags:strArr.optional(),damage_tags:strArr.optional(),damage_tags_spell:strArr.optional(),damage_tags_legendary:strArr.optional(),condition_inflict:strArr.optional(),condition_inflict_spell:strArr.optional(),condition_inflict_legendary:strArr.optional(),saving_throw_forced:strArr.optional(),saving_throw_forced_spell:strArr.optional(),saving_throw_forced_legendary:strArr.optional(),has_fluff:bool.optional(),has_fluff_images:bool.optional(),has_token:bool.optional(),token_credit:str.optional(),token_custom:bool.optional(),sound_clip:z.object({type:str,path:str}).optional(),alt_art:z.array(z.object({name:str,source:str.optional(),page:num.optional()})).optional(),image:imageField,thumbnail:imageField,rendering_hint:str.optional(),columns:num.optional(),slug:str.optional(),edition:str.optional(),source:str.optional(),raw:z.record(str,z.unknown()).optional()});var MONSTER_KNOWN_KEYS=new Set(Object.keys(monsterSchema.shape));export{damageQualifierSchema,monsterSpeedSchema,monsterTypeSchema,monsterCRSchema,monsterACSchema,monsterHPSchema,alignmentEntrySchema,monsterSpellcastingSchema,initiativeSchema,gearEntrySchema,monsterSchema,MONSTER_KNOWN_KEYS};
1
+ import{featureObjectSchema}from"./chunk-NIWLD33X.js";import{imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var str=z.string();var num=z.number();var bool=z.boolean();var strArr=z.array(z.string());var damageQualifierSchema=z.object({get types(){return z.array(z.union([str,damageQualifierSchema])).optional()},note:str.optional(),pre_note:str.optional(),cond:bool.optional(),special:str.optional()});var qualifierList=z.array(z.union([str,damageQualifierSchema])).optional();var speedValue=z.union([num,z.object({number:num,condition:str.optional()})]);var monsterSpeedSchema=z.object({walk:speedValue.optional(),fly:speedValue.optional(),swim:speedValue.optional(),climb:speedValue.optional(),burrow:speedValue.optional(),hover:bool.optional(),can_hover:bool.optional(),alternate:z.record(str,z.array(z.object({number:num,condition:str.optional()}))).optional(),choose:z.object({from:strArr,amount:num,note:str.optional()}).optional()});var monsterTypeSchema=z.object({type:z.union([str,z.object({choose:strArr})]),tags:z.array(z.union([str,z.object({tag:str,prefix:str,prefix_hidden:bool.optional()})])).optional(),sidekick_type:str.optional(),sidekick_tags:strArr.optional(),swarm_size:str.optional(),sidekick_hidden:bool.optional()});var monsterCRSchema=z.object({cr:str,lair:str.optional(),coven:str.optional(),xp:num.optional(),xp_lair:num.optional()});var monsterACSchema=z.object({ac:num.optional(),from:strArr.optional(),condition:str.optional(),braces:bool.optional(),special:str.optional()});var monsterHPSchema=z.object({average:num.optional(),formula:str.optional(),special:str.optional()});var alignmentEntrySchema=z.object({alignment:strArr.optional(),chance:num.optional(),note:str.optional(),special:str.optional()});var spellEntry=z.union([str,z.object({entry:str,hidden:bool.optional()})]);var spellList=z.array(spellEntry);var spellLevel=z.object({slots:num.optional(),lower:num.optional(),spells:strArr});var monsterSpellcastingSchema=z.object({name:str.optional(),type:str.optional(),headerEntries:strArr.optional(),footerEntries:strArr.optional(),ability:str.optional(),displayAs:str.optional(),hidden:strArr.optional(),spells:z.record(str,spellLevel).optional(),will:spellList.optional(),ritual:spellList.optional(),daily:z.record(str,spellList).optional(),rest:z.record(str,spellList).optional(),restLong:z.record(str,spellList).optional(),recharge:z.record(str,spellList).optional(),legendary:z.record(str,spellList).optional(),charges:z.record(str,spellList).optional(),chargesItem:str.optional()});var initiativeSchema=z.union([num,z.object({proficiency:num.optional(),advantage_mode:str.optional()})]);var gearEntrySchema=z.union([str,z.object({item:str,quantity:num.optional(),displayName:str.optional()})]);var featureArr=z.array(featureObjectSchema).optional();var monsterSchema=z.object({name:str.min(1),size:z.union([str,strArr]).optional(),size_note:str.optional(),type:z.union([str,monsterTypeSchema]).optional(),subtype:str.optional(),alignment:z.union([str,z.array(z.union([str,alignmentEntrySchema]))]).optional(),alignment_prefix:str.optional(),cr:z.union([str,monsterCRSchema]).optional(),pb_note:str.optional(),ac:z.array(monsterACSchema).optional(),hp:monsterHPSchema.optional(),speed:monsterSpeedSchema.optional(),abilities:z.object({str:num,dex:num,con:num,int:num,wis:num,cha:num}).optional(),saves:z.record(str,num).optional(),skills:z.record(str,num).optional(),skills_other:z.array(z.unknown()).optional(),senses:strArr.nullable().optional(),passive_perception:num.optional(),languages:strArr.nullable().optional(),damage_vulnerabilities:qualifierList,damage_resistances:qualifierList,damage_immunities:qualifierList,condition_immunities:qualifierList,traits:featureArr,actions:featureArr,bonus_actions:featureArr,reactions:featureArr,legendary_actions:featureArr,mythic:featureArr,mythic_header:strArr.optional(),legendary_action_uses:num.optional(),legendary_resistance:num.optional(),legendary_actions_lair_count:num.optional(),section_headers:z.array(z.object({section:str,header:strArr})).optional(),action_note:str.optional(),reaction_note:str.optional(),spellcasting:z.array(monsterSpellcastingSchema).optional(),legendary_group:z.object({name:str,source:str}).optional(),lair_actions:z.array(z.unknown()).optional(),regional_actions:z.array(z.unknown()).optional(),variant:z.array(z.unknown()).optional(),initiative:initiativeSchema.optional(),gear:z.array(gearEntrySchema).optional(),is_named_creature:bool.optional(),is_npc:bool.optional(),familiar:bool.optional(),short_name:z.union([str,bool]).optional(),level:num.optional(),dragon_age:str.optional(),dragon_casting_color:str.optional(),environment:strArr.optional(),treasure:strArr.optional(),attached_items:strArr.optional(),group:strArr.nullable().optional(),summoned_by_spell:str.optional(),summoned_by_spell_level:num.optional(),summoned_by_class:str.optional(),trait_tags:strArr.optional(),action_tags:strArr.optional(),sense_tags:strArr.optional(),language_tags:strArr.optional(),spellcasting_tags:strArr.optional(),misc_tags:strArr.optional(),damage_tags:strArr.optional(),damage_tags_spell:strArr.optional(),damage_tags_legendary:strArr.optional(),condition_inflict:strArr.optional(),condition_inflict_spell:strArr.optional(),condition_inflict_legendary:strArr.optional(),saving_throw_forced:strArr.optional(),saving_throw_forced_spell:strArr.optional(),saving_throw_forced_legendary:strArr.optional(),has_fluff:bool.optional(),has_fluff_images:bool.optional(),has_token:bool.optional(),token_credit:str.optional(),token_custom:bool.optional(),sound_clip:z.object({type:str,path:str}).optional(),alt_art:z.array(z.object({name:str,source:str.optional(),page:num.optional()})).optional(),image:imageField,thumbnail:imageField,rendering_hint:str.optional(),columns:num.optional(),slug:str.optional(),edition:str.optional(),source:str.optional(),raw:z.record(str,z.unknown()).optional()});var MONSTER_KNOWN_KEYS=new Set(Object.keys(monsterSchema.shape));export{damageQualifierSchema,monsterSpeedSchema,monsterTypeSchema,monsterCRSchema,monsterACSchema,monsterHPSchema,alignmentEntrySchema,monsterSpellcastingSchema,initiativeSchema,gearEntrySchema,monsterSchema,MONSTER_KNOWN_KEYS};
@@ -0,0 +1 @@
1
+ import{isConsumedOnUse,itemSpellUse,resolveEntryEntity}from"./chunk-PKIMOVQG.js";import{isReadOnceItem}from"./chunk-DVUXUIPV.js";import{requiresAttunement}from"./chunk-YGH7S5ZF.js";import{resolveEntityForEntry}from"./chunk-4IAMSRHD.js";import{featureEffectSchema}from"./chunk-ZVL5FXXO.js";var linkSlug=item=>{var _a,_b;return(_b=(_a=/^\[\[(.+?)(\|.*)?\]\]$/.exec(item.trim()))==null?void 0:_a[1])!=null?_b:null};function itemBenefitsActive(entry,entity,registry,view){var _a;if(!entry.equipped)return false;if(requiresAttunement(entity)&&entry.attuned!==true)return false;if(isConsumedOnUse(entry,registry,view))return false;const slug=entity==null?void 0:entity.slug;if(isReadOnceItem(typeof slug==="string"&&slug?slug:(_a=linkSlug(entry.item))!=null?_a:entry.item))return false;return true}function itemSpellCastable(entry,registry,view){const use=itemSpellUse(entry,registry,view);if(!use||!registry)return false;if(use.kind==="consume")return true;const entity=view?view.entity:resolveEntityForEntry(entry.item,registry).entity;return itemBenefitsActive(entry,entity,registry,view)}function itemLabel(entry,entity){var _a,_b,_c,_d;return(_d=(_a=entry.overrides)==null?void 0:_a.name)!=null?_d:String((_c=(_b=entity==null?void 0:entity.name)!=null?_b:linkSlug(entry.item))!=null?_c:entry.item)}var ITEM_ROW_KINDS=new Set(["damage-bonus","crit-range","reroll-damage","extra-attack","weapon-ability","attack-rule"]);function readItemEffects(entity){const raw=entity==null?void 0:entity.effects;const effects=[];const invalid=[];if(!Array.isArray(raw))return{effects,invalid};for(const e of raw){const parsed=featureEffectSchema.safeParse(e);if(parsed.success)effects.push(parsed.data);else invalid.push(typeof(e==null?void 0:e.kind)==="string"?String(e.kind):"unknown")}return{effects,invalid}}function itemRowEffects(entity){return readItemEffects(entity).effects.filter(e=>ITEM_ROW_KINDS.has(e.kind))}function buildItemFeatures(equipment,registry,infusions,warnings){const out=[];if(typeof registry.getBySlug!=="function")return out;equipment.forEach((entry,index)=>{var _a,_b;if(!entry.equipped)return;const{entity,entityType}=resolveEntryEntity(entry,index,registry,infusions);if(!entity||entityType!=="item")return;if(!itemBenefitsActive(entry,entity,registry,infusions==null?void 0:infusions.views.get(index)))return;const{effects,invalid}=readItemEffects(entity);const name=itemLabel(entry,entity);if(invalid.length){warnings.push(`${name}: the sheet cannot read ${invalid.length===1?"this effect":"these effects"} (${invalid.join(", ")}); ignored.`)}const own=effects.filter(e=>!ITEM_ROW_KINDS.has(e.kind));if(own.length===0)return;const slug=String((_b=(_a=entity.slug)!=null?_a:linkSlug(entry.item))!=null?_b:entry.item);out.push({feature:{id:`item:${index}:${slug}`,name,activatable:false,effects:own},source:{kind:"item",slug,index}})});return out}export{itemBenefitsActive,itemSpellCastable,itemLabel,ITEM_ROW_KINDS,readItemEffects,itemRowEffects,buildItemFeatures};