@archivist-gg/dnd5e 0.3.27 → 0.3.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/SRD.md +6 -13
- package/README.md +1 -1
- package/dist/{chunk-KEXSF3CH.js → chunk-2OVDSMPY.js} +1 -1
- package/dist/chunk-4AJYEWFQ.js +1 -0
- package/dist/{chunk-CCAVZANF.js → chunk-53SHSS4M.js} +1 -1
- package/dist/{chunk-6J3L2RYZ.js → chunk-5QDSAZG6.js} +1 -1
- package/dist/chunk-6IPWTOLU.js +1 -0
- package/dist/{chunk-BAOZAXB3.js → chunk-7HOOPNF5.js} +1 -1
- package/dist/{chunk-7CFLU2XL.js → chunk-ADX7435T.js} +1 -1
- package/dist/chunk-B2JSF2LL.js +1 -0
- package/dist/{chunk-35HHIMOJ.js → chunk-C4T6BUSP.js} +1 -1
- package/dist/chunk-CLZRWPWT.js +1 -0
- package/dist/{chunk-BWIEA5ZP.js → chunk-CYYVM6H3.js} +1 -1
- package/dist/{chunk-XVXNBWK6.js → chunk-D2BXAFOL.js} +1 -1
- package/dist/chunk-DXJ5NKKB.js +1 -0
- package/dist/{chunk-PKIMOVQG.js → chunk-E4E6YEN6.js} +1 -1
- package/dist/{chunk-WAUNLUFQ.js → chunk-J27N3KUE.js} +1 -1
- package/dist/{chunk-AHEL6LJ5.js → chunk-J6FIBUI4.js} +1 -1
- package/dist/chunk-JSI2G6LE.js +1 -0
- package/dist/{chunk-JGCE4JVX.js → chunk-KGZXAAFN.js} +1 -1
- package/dist/chunk-M2UA2FAK.js +1 -0
- package/dist/{chunk-LVKSX6EQ.js → chunk-NB4QWMF5.js} +1 -1
- package/dist/{chunk-3A4OSTC4.js → chunk-NU6WP4P5.js} +1 -1
- package/dist/{chunk-CEHL7PPC.js → chunk-RR26E7LH.js} +1 -1
- package/dist/{chunk-535ZMMZI.js → chunk-VY5ZEOLG.js} +1 -1
- package/dist/{chunk-TGK4OP7P.js → chunk-XCF5R5XX.js} +1 -1
- package/dist/chunk-YWKC2LJY.js +1 -0
- package/dist/class/class.codec.js +1 -1
- package/dist/class/class.parser.js +1 -1
- package/dist/class/class.schema.js +1 -1
- package/dist/index.js +1 -1
- package/dist/monster/monster.parser.js +1 -1
- package/dist/monster/monster.schema.js +1 -1
- package/dist/pc/pc.additional-spells.js +1 -1
- package/dist/pc/pc.amount-bindings.js +1 -1
- package/dist/pc/pc.decision-engine.d.ts +2 -0
- package/dist/pc/pc.decision-engine.js +1 -1
- package/dist/pc/pc.entry-overrides.js +1 -1
- package/dist/pc/pc.equipment.d.ts +5 -1
- package/dist/pc/pc.equipment.js +1 -1
- package/dist/pc/pc.feature-effects.d.ts +8 -1
- package/dist/pc/pc.feature-effects.js +1 -1
- package/dist/pc/pc.infusions.js +1 -1
- package/dist/pc/pc.item-effects.d.ts +1 -0
- package/dist/pc/pc.item-effects.js +1 -1
- package/dist/pc/pc.member-choices.js +1 -1
- package/dist/pc/pc.parser.js +1 -1
- package/dist/pc/pc.pools.js +1 -1
- package/dist/pc/pc.proficiencies.js +1 -1
- package/dist/pc/pc.proficiency-replacements.d.ts +22 -0
- package/dist/pc/pc.proficiency-replacements.js +1 -0
- package/dist/pc/pc.recalc.d.ts +3 -1
- package/dist/pc/pc.recalc.js +1 -1
- package/dist/pc/pc.resolver.js +1 -1
- package/dist/pc/pc.resource-seed.js +1 -1
- package/dist/pc/pc.resources.js +1 -1
- package/dist/pc/pc.rest.js +1 -1
- package/dist/pc/pc.schema.d.ts +1 -0
- package/dist/pc/pc.schema.js +1 -1
- package/dist/pc/pc.species-increases.d.ts +12 -0
- package/dist/pc/pc.species-increases.js +1 -0
- package/dist/pc/pc.types.d.ts +40 -0
- package/dist/race/race.codec.js +1 -1
- package/dist/race/race.parser.js +1 -1
- package/dist/race/race.schema.js +1 -1
- package/dist/race/race.subspecies.d.ts +12 -0
- package/dist/race/race.subspecies.js +1 -0
- package/dist/schemas/attack-schema.d.ts +1 -0
- package/dist/schemas/feature-schema.js +1 -1
- package/dist/subclass/subclass.codec.js +1 -1
- package/dist/subclass/subclass.parser.js +1 -1
- package/dist/subclass/subclass.schema.js +1 -1
- package/dist/types/attack.d.ts +1 -0
- package/package.json +1 -1
- package/dist/chunk-BPXQOJES.js +0 -1
- package/dist/chunk-FD2VQ3H6.js +0 -1
- package/dist/chunk-GPBPFKUK.js +0 -1
- package/dist/chunk-UWDHEIPY.js +0 -1
- package/dist/chunk-ZREOQMHM.js +0 -1
package/LICENSES/SRD.md
CHANGED
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
# SRD Attribution (CC-BY-4.0)
|
|
2
2
|
|
|
3
|
-
This repository bundles content from the
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
This repository bundles content from the **System Reference Document**, both the 5.1 (2014)
|
|
4
|
+
and 5.2 (2024) editions, licensed under the Creative Commons Attribution 4.0 International
|
|
5
|
+
License (CC-BY-4.0).
|
|
6
6
|
|
|
7
7
|
## Required attribution
|
|
8
8
|
|
|
9
|
-
This work includes material from the System Reference Document 5.1 ("SRD 5.1") by Wizards of
|
|
10
|
-
the Coast LLC and available at https://dnd.wizards.com/resources/systems-reference-document.
|
|
11
|
-
The SRD 5.1 is licensed under the Creative Commons Attribution 4.0 International License,
|
|
12
|
-
available at https://creativecommons.org/licenses/by/4.0/legalcode.
|
|
9
|
+
This work includes material taken from the System Reference Document 5.1 ("SRD 5.1") by Wizards of the Coast LLC and available at https://dnd.wizards.com/resources/systems-reference-document. The SRD 5.1 is licensed under the Creative Commons Attribution 4.0 International License available at https://creativecommons.org/licenses/by/4.0/legalcode.
|
|
13
10
|
|
|
14
|
-
This work includes material from the System Reference Document 5.2 ("SRD 5.2") by Wizards of
|
|
15
|
-
the Coast LLC and available at https://www.dndbeyond.com/srd. The SRD 5.2 is licensed under
|
|
16
|
-
the Creative Commons Attribution 4.0 International License, available at
|
|
17
|
-
https://creativecommons.org/licenses/by/4.0/legalcode.
|
|
11
|
+
This work includes material from the System Reference Document 5.2 ("SRD 5.2") by Wizards of the Coast LLC, available at https://www.dndbeyond.com/srd. The SRD 5.2 is licensed under the Creative Commons Attribution 4.0 International License, available at https://creativecommons.org/licenses/by/4.0/legalcode.
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
Coast. This project is unofficial and not affiliated with or endorsed by Wizards of the Coast.
|
|
13
|
+
This project is unofficial and not affiliated with or endorsed by Wizards of the Coast.
|
|
21
14
|
|
|
22
15
|
## Bundled SRD locations
|
|
23
16
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @archivist-gg/dnd5e
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The fifth edition (2014 and 2024) rules pack of Archivist, the fifth edition toolkit for Obsidian: parsers,
|
|
4
4
|
schemas, codecs and types for every entity type, the dice, formula and tag machinery, the
|
|
5
5
|
player-character engine, and the bundled SRD content. Built on `@archivist-gg/core`.
|
|
6
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveSpellcasting}from"./chunk-PFQPP77Q.js";import{heldPicks}from"./chunk-
|
|
1
|
+
import{resolveSpellcasting}from"./chunk-PFQPP77Q.js";import{heldPicks}from"./chunk-E4E6YEN6.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{isValidMaxFormula}from"./chunk-EAARMPCW.js";function resourceLevelFor(source,resolved){var _a,_b,_c,_d;if(source.kind==="class"){return(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_a.level)!=null?_b:resolved.totalLevel}if(source.kind==="subclass"){return(_d=(_c=resolved.classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_c.level)!=null?_d:resolved.totalLevel}return resolved.totalLevel}function resolveRecovery(entry){var _a;const kind=(_a=entry.restores)!=null?_a:"uses";const restTriggered=(entry.reset==="short-rest"||entry.reset==="long-rest")&&!entry.action;const flavour=kind==="spell-slots"?"manual":restTriggered?"rest":"manual";return{entry,kind,flavour}}function toResolvedResource(r,fallbackName,owner){var _a,_b,_c;return{id:r.id,name:(_a=r.name)!=null?_a:fallbackName,reset:r.reset,maxFormula:r.max_formula,...r.die?{die:r.die}:{},...r.scales_at?{scalesAt:r.scales_at}:{},...((_b=r.recovery)==null?void 0:_b.length)?{recovery:r.recovery.map(resolveRecovery)}:{},...r.rendering_hint?{renderingHint:r.rendering_hint}:{},...r.surface?{surface:r.surface}:{},...((_c=r.equivalent_ids)==null?void 0:_c.length)?{equivalentIds:r.equivalent_ids}:{},owner}}function resolveFeatureResources(features){var _a,_b;const out=new Map;for(const rf of features){for(const r of(_a=rf.feature.resources)!=null?_a:[]){if(out.has(r.id))continue;const owner={kind:"feature",featureId:(_b=rf.feature.id)!=null?_b:rf.feature.name,featureName:rf.feature.name,source:rf.source};out.set(r.id,toResolvedResource(r,rf.feature.name,owner))}}return out}function pickResourceId(entry){return entry.param!=null?entry.key:entry.slug}function resolveResourceIndex(resolved){var _a,_b,_c,_d;const out=new Map(resolveFeatureResources((_a=resolved.features)!=null?_a:[]));for(const pool of(_b=resolved.pools)!=null?_b:[]){const rc=resolved.classes[pool.classIndex];const classSlug=(_c=rc==null?void 0:rc.entity)==null?void 0:_c.slug;if(!classSlug)continue;for(const entry of[...heldPicks(pool),...(_d=pool.grants)!=null?_d:[]]){if(entry.itemBound===true)continue;const uses=entry.entity.uses;const id=pickResourceId(entry);if(!uses||out.has(id))continue;const maxFormula=String(uses.max);if(!isValidMaxFormula(maxFormula)){warnOnce(`pool-uses:${entry.slug}`,`optional feature "${entry.slug}" has a prose uses.max (${JSON.stringify(uses.max)}); no tracker`);continue}const pres=entry.entity;out.set(id,{id,name:entry.entity.name,reset:uses.recharge,maxFormula,...pres.rendering_hint?{renderingHint:pres.rendering_hint}:{},...pres.surface?{surface:pres.surface}:{},owner:{kind:"pool",poolId:pool.id,poolLabel:pool.label,source:{kind:"class",slug:classSlug,level:pool.anchorLevel}}})}}return out}function poolSaveDC(resolved,derived,pool){var _a,_b;const rc=resolved.classes[pool.classIndex];const ability=(_b=(_a=rc==null?void 0:rc.subclass)==null?void 0:_a.spellcasting)==null?void 0:_b.ability;if(!rc||!ability)return null;if(resolveSpellcasting(rc)!==null)return null;return 8+derived.proficiencyBonus+derived.mods[ability]}export{resourceLevelFor,resolveRecovery,resolveFeatureResources,pickResourceId,resolveResourceIndex,poolSaveDC};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{slugify}from"./chunk-63YJPWTM.js";function findSubspeciesParent(registry,child){var _a;const link=child.subspecies_of;if(typeof link!=="string"||!link.trim())return void 0;const inner=link.trim().replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].replace(/\.md$/,"").trim();if(!inner)return void 0;const tail=((_a=inner.split("/").pop())!=null?_a:inner).trim();const prefix=child.slug.includes("_")?child.slug.slice(0,child.slug.indexOf("_")):null;const notSelf=e=>e&&e.slug!==child.slug?e:void 0;let all=null;const races=()=>all!=null?all:all=registry.search("","race",Number.POSITIVE_INFINITY);const tiers=[()=>notSelf(registry.getByTypeAndSlug("race",inner)),()=>notSelf(races().find(e=>e.filePath===`${inner}.md`||e.filePath.endsWith(`/${inner}.md`))),()=>prefix?notSelf(registry.getByTypeAndSlug("race",`${prefix}_race_${slugify(tail)}`)):void 0,()=>prefix?notSelf(races().find(e=>e.slug.startsWith(`${prefix}_race_`)&&e.name===tail)):void 0];for(const tier of tiers){const hit=tier();if(hit)return hit}return void 0}var nonEmpty=s=>typeof s==="string"&&s.trim().length>0;var asList=v=>v===void 0?[]:Array.isArray(v)?v:[v];function mergeSubspecies(child,parent){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t;const fixed=[...(_b=(_a=parent.languages)==null?void 0:_a.fixed)!=null?_b:[]];for(const l of(_d=(_c=child.languages)==null?void 0:_c.fixed)!=null?_d:[])if(!fixed.includes(l))fixed.push(l);const choice=(_g=(_e=child.languages)==null?void 0:_e.choice)!=null?_g:(_f=parent.languages)==null?void 0:_f.choice;const choices=[...(_h=parent.choices)!=null?_h:[],...(_i=child.choices)!=null?_i:[]];const spells=[...asList(parent.additional_spells),...asList(child.additional_spells)];return{...parent,...child,size:(_j=parent.size)!=null?_j:child.size,speed:{...(_k=parent.speed)!=null?_k:{},...(_l=child.speed)!=null?_l:{}},vision:{...(_m=parent.vision)!=null?_m:{},...(_n=child.vision)!=null?_n:{}},ability_score_increases:[...(_o=parent.ability_score_increases)!=null?_o:[],...(_p=child.ability_score_increases)!=null?_p:[]],age:nonEmpty(child.age)?child.age:parent.age,alignment:nonEmpty(child.alignment)?child.alignment:parent.alignment,languages:{fixed,...choice?{choice}:{}},traits:[...(_q=parent.traits)!=null?_q:[],...(_r=child.traits)!=null?_r:[]],...choices.length?{choices}:{},...spells.length?{additional_spells:spells}:{},...((_s=child.creature_type)!=null?_s:parent.creature_type)?{creature_type:(_t=child.creature_type)!=null?_t:parent.creature_type}:{}}}function withSubspeciesParent(race,registry){if(!race||!race.subspecies_of)return race;let out=race;const seen=new Set([race.slug]);let link=race;for(let depth=0;depth<3&&link.subspecies_of;depth++){const hit=findSubspeciesParent(registry,link);if(!hit||seen.has(hit.slug))break;seen.add(hit.slug);const data=hit.data;const parent=data.slug==null?{...data,slug:hit.slug}:data;out=mergeSubspecies(out,parent);link=parent}return out}export{findSubspeciesParent,mergeSubspecies,withSubspeciesParent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spellSource}from"./chunk-PZ3ZZ5H5.js";import{resourceLevelFor}from"./chunk-
|
|
1
|
+
import{spellSource}from"./chunk-PZ3ZZ5H5.js";import{resourceLevelFor}from"./chunk-2OVDSMPY.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{featureObjectSchema}from"./chunk-
|
|
1
|
+
import{featureObjectSchema}from"./chunk-M2UA2FAK.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
|
+
var hasAbilityPoints=h=>{var _a;return((_a=h==null?void 0:h.choices)!=null?_a:[]).some(c=>c.kind==="ability-points")};function backgroundGrantsAbilityIncreases(bg){if(!bg)return false;const pool=bg.ability_score_increases;if(pool)return true;return hasAbilityPoints(bg)||hasAbilityPoints(bg.feature)}function speciesGrantsAbilityIncreases(race){var _a,_b,_c;if(!race)return false;if(((_a=race.ability_score_increases)!=null?_a:[]).some(a=>"ability"in a))return true;if(hasAbilityPoints(race))return true;if(((_b=race.traits)!=null?_b:[]).some(t=>hasAbilityPoints(t)))return true;const subs=(_c=race.subraces)!=null?_c:[];return subs.some(s=>{var _a2;return((_a2=s.ability_score_increases)!=null?_a2:[]).some(a=>a.ability!=null)})}function isOlderSpecies(race){return(race==null?void 0:race.edition)==="2014"}function speciesIncreaseRule(resolved){var _a;const applies=backgroundGrantsAbilityIncreases(resolved.background)&&isOlderSpecies(resolved.race)&&speciesGrantsAbilityIncreases(resolved.race);const kept=((_a=resolved.definition)==null?void 0:_a.keep_species_ability_increases)===true;return{applies,kept,suppressed:applies&&!kept}}export{backgroundGrantsAbilityIncreases,speciesGrantsAbilityIncreases,isOlderSpecies,speciesIncreaseRule};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{classEntitySchema}from"./chunk-
|
|
1
|
+
import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{classEntitySchema}from"./chunk-ADX7435T.js";import{parseYaml}from"@archivist-gg/core";function parseClass(source){const raw=parseYaml(source,["name","slug"]);if(!raw.success)return raw;aliasFeaturesByLevelActionCost(raw.data.features_by_level);const result=classEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`class schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseClass};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-
|
|
1
|
+
import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-M2UA2FAK.js";import{resourceSchema}from"./chunk-CCFIINBA.js";import{startingEquipmentEntrySchema,startingGoldSchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-VHIE2KYQ.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{normalizeRollScope}from"./chunk-FOLHTMSC.js";import{toProfSlug}from"./chunk-VTQ4RWEG.js";import{memberSpellTargets}from"./chunk-J27N3KUE.js";import{heldPicks}from"./chunk-E4E6YEN6.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:{},ability_bonus_terms:[],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:[],damageRollOptions:[]}}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}:{},poolMember:true})};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,rf)}}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 extraAttackSourceOf(rf,label,level,owner,scope){const source=owner!=null?owner:rf==null?void 0:rf.source;if(!source)return void 0;return{name:label,source,...level!==void 0?{level}:{},...(rf==null?void 0:rf.poolMember)?{poolMember:true}:{},...(rf==null?void 0:rf.feature.activatable)===true?{switched:true}:{},...scope?{scope}:{}}}function applyEffect(out,eff,label,level,owner,targets,rf){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q;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);const source=extraAttackSourceOf(rf,label,level,owner,scope);if(scope)out.scopedExtraAttacks.push({count,scope,...source?{source}:{}});else if(count>out.extraAttack){out.extraAttack=count;if(source)out.extraAttackSource=source}}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-roll-option":{const scope=eff.applies_to===void 0?void 0:[].concat(eff.applies_to);out.damageRollOptions.push({mode:eff.mode,...eff.value!==void 0?{value:eff.value}:{},...eff.two_handed?{twoHanded:true}:{},...eff.once_per_turn?{oncePerTurn:true}:{},...((_m=eff.condition)==null?void 0:_m.trim())?{condition:eff.condition.trim()}:{},source:label,...scope?{scope}:{}});break}case"damage-bonus":if(((_n=eff.applies_to)!=null?_n:"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=(_o=eff.spell_scope)!=null?_o: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]=((_p=out.ability_bonus[ab])!=null?_p:0)+eff.amount;((_q=out.ability_bonus_terms)!=null?_q:out.ability_bonus_terms=[]).push({ability:ab,source:label,amount:eff.amount})}break;default:break}}export{emptyFeatureEffectTotals,pushDefenseGrant,mergeDefenseItems,foldsNow,assembleEffectFeatures,foldsOnSelf,selfEffectsOf,computeFeatureEffects,classifyProficiencyEffect,collectProficiencyEffectGrants};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseClass}from"./chunk-
|
|
1
|
+
import{parseClass}from"./chunk-7HOOPNF5.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{toProfSlug}from"./chunk-VTQ4RWEG.js";function replacementChoiceId(domain,value){return`replace-${domain}-${value}`}function replacementKey(r){return`${r.carrier.kind}:${r.choice.id}`}function isReplacementKey(key){return/^(race|background):replace-(skill|tool)-/.test(key)}function replacementOwner(r){return`${r.carrier.name}, in place of ${r.label}`}function replacementPick(r,originChoices){const raw=originChoices==null?void 0:originChoices[replacementKey(r)];const v=Array.isArray(raw)?raw[0]:raw;return typeof v==="string"&&v.trim()?toProfSlug(v):null}function replacementDescription(r){const who=r.others.map(n=>`**${n}**`).join(" and ");const verb=r.others.length>1?"give":"gives";return`Your ${who} already ${verb} you ${r.label}, so ${r.carrier.name}'s ${r.label} adds nothing. The rules let you take a different ${r.domain} instead.`}export{replacementChoiceId,replacementKey,isReplacementKey,replacementOwner,replacementPick,replacementDescription};
|
|
@@ -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 sheetSavedRollSchema=z.object({name:z.string().min(1),on:z.string().min(1),hit:z.enum(["normal","advantage","disadvantage"]).optional(),damage:z.array(z.string().min(1)).optional(),extra:z.string().optional()});var sheetRollsSchema=z.array(z.unknown()).transform(list=>list.flatMap(entry=>{const r=sheetSavedRollSchema.safeParse(entry);return r.success?[r.data]:[]}));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(),rolls:sheetRollsSchema.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
|
+
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 sheetSavedRollSchema=z.object({name:z.string().min(1),on:z.string().min(1),hit:z.enum(["normal","advantage","disadvantage"]).optional(),damage:z.array(z.string().min(1)).optional(),extra:z.string().optional()});var sheetRollsSchema=z.array(z.unknown()).transform(list=>list.flatMap(entry=>{const r=sheetSavedRollSchema.safeParse(entry);return r.success?[r.data]:[]}));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(),rolls:sheetRollsSchema.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"]),keep_species_ability_increases:z.boolean().optional().catch(void 0),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{featureSchema}from"./chunk-
|
|
1
|
+
import{featureSchema}from"./chunk-M2UA2FAK.js";import{choiceSchema}from"./chunk-VHIE2KYQ.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isConsumedOnUse,itemSpellUse,resolveEntryEntity}from"./chunk-E4E6YEN6.js";import{isReadOnceItem}from"./chunk-DVUXUIPV.js";import{requiresAttunement}from"./chunk-YGH7S5ZF.js";import{resolveEntityForEntry}from"./chunk-4IAMSRHD.js";import{featureEffectSchema}from"./chunk-EON7T2SN.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"]);var GATE_VERB="(?:wear|wearing|hold|holding|wield|wielding)";var GATE_SUBJECT="(?:you |you're |you are )?";var ITEM_NAME="([a-z][a-z'-]*(?: [a-z][a-z'-]*){0,2})";var GATE_OBJECT=`(?:it|them|(?:this|these|the) ${ITEM_NAME})`;var GATE_PHRASES=[new RegExp(`^while ${GATE_SUBJECT}${GATE_VERB}(?: or ${GATE_VERB})? ${GATE_OBJECT}$`),new RegExp(`^while ${GATE_SUBJECT}attuned to ${GATE_OBJECT}$`),/^while (?:(?:it is|it's|they are) )?(?:worn|held|wielded)$/,new RegExp(`^while (?:this|the) ${ITEM_NAME} orbits your head$`)];var NOT_AN_ITEM_NAME=new Set(["and","or","with","without","in","on","at","of","to","from","while","when","if","but","against","within","near","until","during","for","is","are","you","your"]);function restatesItemGate(text){const t=(text!=null?text:"").replace(/’/g,"'").trim().toLowerCase().replace(/\s+/g," ").replace(/[.,;:]+$/,"");for(const re of GATE_PHRASES){const m=re.exec(t);if(!m)continue;if(m[1]!==void 0&&m[1].split(" ").some(w=>NOT_AN_ITEM_NAME.has(w)))continue;return true}return false}function withoutGateRestatement(e){if(e.kind==="apply-condition"||e.kind==="immune-condition")return e;if(!("condition"in e)||!restatesItemGate(e.condition))return e;const copy={...e};delete copy.condition;return copy}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(withoutGateRestatement(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,restatesItemGate,readItemEffects,itemRowEffects,buildItemFeatures};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseCastingTime}from"./chunk-CMIEZQL4.js";import{readTableColumn}from"./chunk-CSTAQQGX.js";import{derivePoolLayout}from"./chunk-O776WL7O.js";import{findItemAction,isReadOnceItem,resolveItemAction}from"./chunk-DVUXUIPV.js";import{requiresAttunement}from"./chunk-YGH7S5ZF.js";import{defaultSlotForType,effectiveArmor,isItemEntity,isShieldArmor,resolveEntityForEntry,slotAcTerms}from"./chunk-4IAMSRHD.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{keptSlugFor,resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bucketOf,memoByRevision}from"./chunk-QMEKQTUT.js";import{bareEntitySlug,slugify,twinKey,wikilinkTailSlug}from"./chunk-63YJPWTM.js";import{parseInlineTag}from"./chunk-BREHZNTL.js";import{isCanonicalDamageType}from"./chunk-7FPQJDFD.js";function equivalentResourceIds(id,index){var _a,_b,_c;const out=[];const add=other=>{if(other!==id&&index.has(other)&&!out.includes(other))out.push(other)};for(const other of(_b=(_a=index.get(id))==null?void 0:_a.equivalentIds)!=null?_b:[])add(other);for(const res of index.values())if((_c=res.equivalentIds)==null?void 0:_c.includes(id))add(res.id);return out}function ownedByClass(res,rc){var _a,_b;const s=(_a=res==null?void 0:res.owner)==null?void 0:_a.source;if(!s)return false;if(s.kind==="class")return s.slug===((_b=rc.entity)==null?void 0:_b.slug);if(s.kind==="subclass")return!!rc.subclass&&s.slug===rc.subclass.slug;return false}function payingResourceId(id,index,owner){const candidates=[id,...equivalentResourceIds(id,index)].filter(c=>index.has(c));if(candidates.length===0)return void 0;if(owner){const own=candidates.find(c=>ownedByClass(index.get(c),owner));if(own)return own}return candidates[0]}function classOfSource(source,classes){var _a,_b;if(source.kind==="class")return(_a=classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))!=null?_a:null;if(source.kind==="subclass")return(_b=classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))!=null?_b:null;return null}function bindFeatureConsumers(features,index,classes){return features.map(rf=>{const consumes=rf.feature.consumes;const id=consumes==null?void 0:consumes.resource;if(!consumes||typeof id!=="string"||id.length===0)return rf;const payer=payingResourceId(id,index,classOfSource(rf.source,classes));if(payer===void 0||payer===id)return rf;return{...rf,feature:{...rf.feature,consumes:{...consumes,resource:payer}}}})}var SORTED_OPTIONAL_FEATURES=new WeakMap;function sortedOptionalFeatures(registry){return memoByRevision(SORTED_OPTIONAL_FEATURES,registry,()=>bucketOf(registry,"optional-feature").slice().sort((a,b)=>a.name.localeCompare(b.name)||a.slug.localeCompare(b.slug)))}var SRD_OWNER_PREFIXES=new Set(["srd-5e","srd-2024"]);function levelPrereqMax(d){var _a;return((_a=d.prerequisites)!=null?_a:[]).filter(p=>p.kind==="level").reduce((m,p)=>Math.max(m,p.min),0)}function namedRefKey(name){return name?slugify(name.replace(/\s*\([^)]*\)\s*$/,"")):""}function levelPrereqRefsMet(d,rc){var _a,_b;for(const p of(_a=d.prerequisites)!=null?_a:[]){if(p.kind!=="level")continue;if(p.class&&namedRefKey(p.class.name)!==namedRefKey((_b=rc.entity)==null?void 0:_b.name))return false;if(p.subclass){const sub=rc.subclass;const own=[sub==null?void 0:sub.short_name,sub==null?void 0:sub.name].map(namedRefKey).filter(k=>k!=="");if(!own.includes(namedRefKey(p.subclass.name)))return false}}return true}function optionalFeaturePrereqKeys(d){var _a;return((_a=d.prerequisites)!=null?_a:[]).filter(p=>p.kind==="optionalfeature").map(p=>twinKey(wikilinkTailSlug(p.optionalfeature)))}function withOptionalFeaturePrereqsMet(offered,selected,grants){let open=offered;for(;;){const openSlugs=new Set(open.map(e=>e.slug));const held=new Set([...grants,...selected.filter(e=>openSlugs.has(e.slug))].map(e=>twinKey(e.slug)));const next=open.filter(e=>optionalFeaturePrereqKeys(e.entity).every(k=>held.has(k)));if(next.length===open.length)return next;open=next}}function poolAnchorLevel(entity,pool){let anchorLevel=1;let columnSeen=false;for(let l=1;l<=20;l++){const c=readTableColumn(entity.table,l,[pool.count.column]);if(c!=null)columnSeen=true;if(c!=null&&c>=1){anchorLevel=l;break}}return{anchorLevel,columnSeen}}function resolvePool(rc,classIndex,pool,registry,index,edition){var _a,_b,_c,_d,_e,_f,_g,_h,_i;const entity=rc.entity;const level=rc.level;const ownerBare=bareEntitySlug(entity.slug);const ownerPrefix=entity.slug.split("_")[0];const ownEdition=SRD_OWNER_PREFIXES.has(ownerPrefix)?entity.edition:void 0;const col=pool.count.column;const count=(_a=readTableColumn(entity.table,level,[col]))!=null?_a:0;const{anchorLevel,columnSeen}=poolAnchorLevel(entity,pool);if(!columnSeen){warnOnce(`pool-column:${pool.id}`,`Archivist: pool "${pool.id}" declares count column "${col}", which "${entity.slug}"'s class table carries at no level; the pool resolves count 0 at anchor level 1`)}const ft=pool.source.where.feature_type;const all=sortedOptionalFeatures(registry);const entryOf=(slug,entity2,compendium)=>({slug,entity:entity2,...compendium?{compendium}:{},key:slug,param:null,itemBound:isItemBound(entity2)});const byBare=new Map;const candidates=new Map;for(const e of all){const d=e.data;const entry=entryOf(e.slug,d,e.compendium);const bare=bareEntitySlug(e.slug);byBare.set(bare,entry);if(d.feature_type!==ft)continue;if(!((_b=d.available_to)!=null?_b:[]).some(l=>wikilinkTailSlug(l)===ownerBare))continue;if(levelPrereqMax(d)>level)continue;if(!levelPrereqRefsMet(d,rc))continue;if(ownEdition&&d.edition&&d.edition!==ownEdition)continue;const key=twinKey(e.slug);const group=candidates.get(key);if(group)group.push(entry);else candidates.set(key,[entry])}const collapsed=[];for(const group of candidates.values()){if(group.length===1){collapsed.push(group[0]);continue}const bare=bareEntitySlug(group[0].slug);const owned=group.find(e=>e.slug.split("_")[0]===ownerPrefix);if(!owned){warnOnce(`pool-collapse:${bare}`,`Archivist: pool "${pool.id}" holds ${group.length} cross-edition entries for "${bare}" and none shares the owner's compendium prefix "${ownerPrefix}"; keeping "${group[0].slug}"`)}collapsed.push(owned!=null?owned:group[0])}const grantDecls=[...(_d=(_c=rc.entity)==null?void 0:_c.pool_grants)!=null?_d:[],...(_f=(_e=rc.subclass)==null?void 0:_e.pool_grants)!=null?_f:[]];const grantsRaw=grantDecls.filter(g=>g.pool===pool.id).flatMap(g=>g.grants).filter(g=>g.at_level<=level).map(g=>byBare.get(wikilinkTailSlug(g.feature))).filter(e=>e!=null);const grantedBare=new Set;const grants=grantsRaw.filter(e=>{const key=bareEntitySlug(e.slug);if(grantedBare.has(key))return false;grantedBare.add(key);return true});const offered=collapsed.filter(e=>!grantedBare.has(bareEntitySlug(e.slug)));const bySlugAvailable=new Map(offered.map(e=>[e.slug,e]));const byTwinAvailable=new Map(offered.map(e=>[twinKey(e.slug),e]));const resolveStored=s=>{const exact=bySlugAvailable.get(s);if(exact)return exact;const survivor=byTwinAvailable.get(twinKey(s));if(survivor)return survivor;const full=registry.getByTypeAndSlug("optional-feature",s);if(full)return entryOf(full.slug,full.data,full.compendium);return byBare.get(bareEntitySlug(s))};const raw=(_g=rc.choices[anchorLevel])==null?void 0:_g[pool.id];const selectedSlugs=Array.isArray(raw)?raw:typeof raw==="string"?[raw]:[];const selected=[];const seenKeys=new Set;for(const s of selectedSlugs){const{slugPart,param}=parsePickKey(s);const entry=resolveStored(slugPart);if(!entry)continue;const repeatable=entry.entity.repeatable===true;if(!repeatable&¶m!==null){warnOnce(`pick-param:${pool.id}:${s}`,`Archivist: pool "${pool.id}" pick "${s}" names a parameter, but "${entry.slug}" is not repeatable; the parameter is ignored`)}const nkey=repeatable?normalizedPickKey(s,true):twinKey(entry.slug);if(grantedBare.has(bareEntitySlug(entry.slug))||seenKeys.has(nkey))continue;seenKeys.add(nkey);selected.push({...entry,key:repeatable||param!==null?s:entry.slug,param:repeatable?param:null,...repeatable?{option:resolveCopyOption(entry.entity,param,{classLevel:level,registry,edition})}:{}})}const available=withOptionalFeaturePrereqsMet(offered,selected,grants);const members=[...available,...grants];const layout=derivePoolLayout(members);const votes=new Map;for(const e of members){const id=(_h=e.entity.consumes)==null?void 0:_h.resource;const payer=id?payingResourceId(id,index,rc):void 0;if(!payer)continue;votes.set(payer,((_i=votes.get(payer))!=null?_i:0)+1)}let resource;let bestN=0;for(const[id,n]of votes)if(n>bestN){resource=id;bestN=n}const bind=poolRebinder(rc,pool.id,resource,index);return{id:pool.id,label:pool.label,classIndex,count,anchorLevel,selected:selected.map(bind),available:available.map(bind),grants:grants.map(bind),...layout?{layout}:{},...resource?{resource}:{},...pool.count.label?{countLabel:pool.count.label}:{},...pool.active?{active:pool.active}:{},...pool.head_resource?{headResource:pool.head_resource}:{}}}function poolRebinder(rc,poolId,vote,index){const declared=declaredResourceIds(rc);const copies=new Map;return e=>{const consumes=e.entity.consumes;const id=consumes==null?void 0:consumes.resource;if(!consumes||typeof id!=="string"||id.length===0)return e;const payer=payingResourceId(id,index,rc);if(payer===id)return e;const target=payer!=null?payer:vote!==void 0&&!declared.has(id)?vote:void 0;if(target===void 0)return e;const done=copies.get(e.key);if(done)return done;if(payer===void 0){warnOnce(`pool-rebind:${poolId}:${id}`,`Archivist: pool "${poolId}" members consume "${id}", which this character does not own; bound to the pool's resource "${target}"`)}const copy={...e,entity:{...e.entity,consumes:{...consumes,resource:target}}};copies.set(e.key,copy);return copy}}function declaredResourceIds(rc){var _a;const out=new Set;const add=list=>{for(const r of list!=null?list:[])if(typeof(r==null?void 0:r.id)==="string")out.add(r.id)};for(const owner of[rc.entity,rc.subclass]){if(!owner)continue;add(owner.resources);for(const features of Object.values((_a=owner.features_by_level)!=null?_a:{}))for(const f of features!=null?features:[])add(f.resources)}return out}function resolveAllPools(resolved,registry,index){const out=[];resolved.classes.forEach((rc,classIndex)=>{var _a,_b,_c,_d;if(!rc.entity)return;const decls=[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]];const seen=new Set;for(const pool of decls){if(seen.has(pool.id))continue;seen.add(pool.id);out.push(resolvePool(rc,classIndex,pool,registry,index,(_d=resolved.definition)==null?void 0:_d.edition))}});return out}function strandedPicks(pool){const inAvailable=new Set(pool.available.map(e=>e.slug));return pool.selected.filter(e=>!inAvailable.has(e.slug))}function heldPicks(pool){var _a;const selected=(_a=pool.selected)!=null?_a:[];if(!pool.available)return[...selected];const inAvailable=new Set(pool.available.map(e=>e.slug));return selected.filter(e=>inAvailable.has(e.slug))}function withoutStrandedSites(sites,classes,registry,edition){if(sites.length===0)return sites;const strandedKeys=new Map;const keysOf=(classIndex,poolId)=>{var _a,_b,_c;const at=`${classIndex}:${poolId}`;let keys=strandedKeys.get(at);if(keys)return keys;const rc=classes[classIndex];const decl=(rc==null?void 0:rc.entity)?[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]].find(p=>p.id===poolId):void 0;keys=new Set(rc&&decl?strandedPicks(resolvePool(rc,classIndex,decl,registry,new Map,edition)).map(e=>twinKey(e.slug)):[]);strandedKeys.set(at,keys);return keys};return sites.filter(site=>!keysOf(site.classIndex,site.poolId).has(twinKey(site.memberSlug)))}function poolCountLabel(pool){var _a;return(_a=pool.countLabel)!=null?_a:"Known"}function poolActiveWords(pool){var _a,_b,_c;const a=pool.active;if(!a)return null;return{column:a.column,label:a.label,verb:a.verb,counterLabel:(_a=a.counter_label)!=null?_a:a.label,createLabel:(_b=a.create_label)!=null?_b:"Created",createVerb:(_c=a.create_verb)!=null?_c:"Create"}}function parsePickKey(stored){const i=stored.indexOf("#");return i===-1?{slugPart:stored,param:null}:{slugPart:stored.slice(0,i),param:stored.slice(i+1)}}function normalizedPickKey(stored,repeatable){const{slugPart,param}=parsePickKey(stored);return repeatable?`${bareEntitySlug(slugPart)}#${param!=null?param:""}`:bareEntitySlug(slugPart)}function markerKey(by){const{slugPart,param}=parsePickKey(by);return param===null?bareEntitySlug(slugPart):`${bareEntitySlug(slugPart)}#${param}`}function isItemBound(note){var _a;return!!note.infuse||note.repeatable===true&&!!((_a=note.options)==null?void 0:_a.some(r=>!!r.creates))}var SRD_BOOKS=new Set(["SRD 2024","SRD 5e"]);var lc=v=>String(v!=null?v:"").trim().toLowerCase();var linkSlug=link=>link.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0];var itemsOf=registry=>registry.search("","item",Number.POSITIVE_INFINITY);function matchesFilter(data,f){var _a;const type=lc(data.type);if(!f.rarity.map(lc).includes(lc(data.rarity)))return false;if(f.types&&!f.types.map(lc).includes(type))return false;if((_a=f.exclude_types)==null?void 0:_a.map(lc).includes(type))return false;return!(f.cursed===false&&data.cursed===true)}function rowMatches(row,it){const c=row.creates;if(c.item)return lc(it.name)===lc(row.name)||it.slug===linkSlug(c.item);if(c.variant)return c.variant.candidates.some(l=>bareEntitySlug(linkSlug(l))===bareEntitySlug(it.slug));return!!c.filter&&matchesFilter(it.data,c.filter)}function buildItemIndex(items){const lcType=[],lcRarity=[];const byLcName=new Map,bySlug=new Map,byBare=new Map;const push=(m,k,i)=>{const l=m.get(k);if(l)l.push(i);else m.set(k,[i])};items.forEach((it,i)=>{const data=it.data;lcType.push(lc(data.type));lcRarity.push(lc(data.rarity));push(byLcName,lc(it.name),i);if(!bySlug.has(it.slug))bySlug.set(it.slug,i);push(byBare,bareEntitySlug(it.slug),i)});return{items,lcType,lcRarity,byLcName,bySlug,byBare}}var ITEM_INDEX=new WeakMap;var itemIndexOf=registry=>memoByRevision(ITEM_INDEX,registry,()=>buildItemIndex(itemsOf(registry)));var inBucketOrder=(ix,hits)=>[...hits].sort((a,b)=>a-b).map(i=>ix.items[i]);function rowInstalledIn(row,ix){var _a,_b,_c;const c=row.creates;if(c.item){const hits=new Set((_a=ix.byLcName.get(lc(row.name)))!=null?_a:[]);const own=ix.bySlug.get(linkSlug(c.item));if(own!==void 0)hits.add(own);return inBucketOrder(ix,hits)}if(c.variant){const hits=new Set;for(const l of c.variant.candidates)for(const i of(_b=ix.byBare.get(bareEntitySlug(linkSlug(l))))!=null?_b:[])hits.add(i);return inBucketOrder(ix,hits)}const f=c.filter;if(!f)return[];const rarities=new Set(f.rarity.map(lc));const types=f.types?new Set(f.types.map(lc)):null;const excluded=new Set(((_c=f.exclude_types)!=null?_c:[]).map(lc));return ix.items.filter((it,i)=>rarities.has(ix.lcRarity[i])&&(!types||types.has(ix.lcType[i]))&&!excluded.has(ix.lcType[i])&&!(f.cursed===false&&it.data.cursed===true))}var rowInstalled=(row,registry)=>rowInstalledIn(row,itemIndexOf(registry));function candidateOrder(edition){return(a,b)=>{const ea=edition&&lc(a.data.edition)===edition?0:1;const eb=edition&&lc(b.data.edition)===edition?0:1;if(ea!==eb)return ea-eb;const sa=SRD_BOOKS.has(a.compendium)?0:1,sb=SRD_BOOKS.has(b.compendium)?0:1;if(sa!==sb)return sa-sb;return a.slug<b.slug?-1:a.slug>b.slug?1:0}}function optionCandidates(row,registry,opts={}){return candidatesFrom(rowInstalled(row,registry),registry,opts)}function candidatesFrom(installed,registry,opts){var _a,_b;const visible=(_a=opts.isEntityVisible)!=null?_a:(()=>true);const excluded=((_b=opts.exclude)!=null?_b:[]).map(s=>{var _a2;return registry.getByTypeAndSlug("item",(_a2=keptSlugFor(s))!=null?_a2:s)}).filter(e=>!!e);const exNames=new Set(excluded.map(e=>lc(e.name))),exBares=new Set(excluded.map(e=>bareEntitySlug(e.slug)));const seen=new Set,out=[];for(const e of installed.filter(visible).sort(candidateOrder(opts.edition))){const bare=bareEntitySlug(e.slug);if(seen.has(bare))continue;seen.add(bare);if(exNames.has(lc(e.name))||exBares.has(bare))continue;out.push(e.slug)}return out}function resolveOptionRows(note,registry,opts={}){var _a;const ix=itemIndexOf(registry);return((_a=note.options)!=null?_a:[]).map(row=>{var _a2;const rowItems=rowInstalledIn(row,ix);const candidates=candidatesFrom(rowItems,registry,opts);const anyVisible=candidates.length>0||candidatesFrom(rowItems,registry,{...opts,exclude:[]}).length>0;const installed=rowItems.length>0;return{key:row.key,name:row.name,minLevel:row.min_level,...row.attunement!==void 0?{attunement:row.attunement}:{},arm:row.creates.item?"item":row.creates.variant?"variant":"filter",candidates,availability:anyVisible?"installed":installed?"hidden-only":"not-installed",...rowItemWords(row,candidates[0]?ix.items[(_a2=ix.bySlug.get(candidates[0]))!=null?_a2:-1]:rowItems[0])}})}function rowItemWords(row,item){var _a,_b,_c,_d;const f=row.creates.filter;if(f)return{type:((_a=f.types)==null?void 0:_a[0])?lc(f.types[0]):null,rarity:f.rarity[0]?lc(f.rarity[0]):null,charges:null};const data=(_b=item==null?void 0:item.data)!=null?_b:{};const max=(_c=data.charges)==null?void 0:_c.max;return{type:lc(data.type)||null,rarity:lc(data.rarity)||null,charges:typeof max==="number"&&max>0?{max,...typeof((_d=data.charges)==null?void 0:_d.recharge)==="string"?{recharge:data.charges.recharge}:{}}:null}}function resolveCopyOption(note,param,ctx){var _a,_b,_c;const rows=(_a=note.options)!=null?_a:[];if(param===null||param==="")return{row:null,status:"needs-choice"};if(note.item_choice==="create"){const row=rows.find(r=>r.key===param);if(!row)return{row:null,status:"invalid"};const installed=rowInstalled(row,ctx.registry).sort(candidateOrder(ctx.edition));if(installed.length===0)return{row,status:"not-installed"};const own=row.creates.item?linkSlug(row.creates.item):void 0;const item=row.creates.item?((_b=installed.find(e=>e.slug===own))!=null?_b:installed[0]).slug:void 0;return{row,...item?{item}:{},status:row.min_level<=ctx.classLevel?"ok":"level"}}const slug=(_c=keptSlugFor(param))!=null?_c:param;const it=ctx.registry.getByTypeAndSlug("item",slug);if(!it)return{row:null,item:slug,status:"not-installed"};const matching=rows.filter(r=>rowMatches(r,it)).sort((a,b)=>a.min_level-b.min_level);if(matching.length===0)return{row:null,item:slug,status:"invalid"};return{row:matching[0],item:slug,status:matching[0].min_level<=ctx.classLevel?"ok":"level"}}var MUNDANE=new Set(["","none","mundane"]);var isMagic=data=>{const r=data==null?void 0:data.rarity;return typeof r==="string"&&!MUNDANE.has(r.trim().toLowerCase())};var plainText=item=>item.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|").pop().split("/").pop();function scaledInfuseItem(infuse,classLevel){var _a,_b;let item={...(_a=infuse.item)!=null?_a:{}};const rows=[...(_b=infuse.scales_at)!=null?_b:[]].sort((a,b)=>a.level-b.level);for(const row of rows)if(row.level<=classLevel)item={...item,...row.item};return item}function wrapInfused(entry,note,classLevel,registry){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k;const infuse=note.infuse;const item=scaledInfuseItem(infuse,classLevel);const resist=[...(_a=item.resist)!=null?_a:[],...((_b=infuse.choice)==null?void 0:_b.kind)==="damage-type"&&((_c=entry.infusion)==null?void 0:_c.choice)?[entry.infusion.choice]:[]];const overlay={...item.bonuses?{bonuses:item.bonuses}:{},resist,...item.charges?{charges:item.charges}:{},...item.action?{action:item.action}:{},...item.range?{range:item.range}:{},...infuse.attunement?{attunement:{required:true}}:{}};const base=resolveBaseItem(entry.item,registry);const data=(_d=base==null?void 0:base.data)!=null?_d:null;if(base&&isMagic(data)){const b=data;const bonuses={...(_e=b.bonuses)!=null?_e:{}};for(const[k,v]of Object.entries((_f=item.bonuses)!=null?_f:{}))if(typeof v==="number")bonuses[k]=(typeof bonuses[k]==="number"?bonuses[k]:0)+v;return{entity:{...b,bonuses,resist:[...new Set([...(_g=b.resist)!=null?_g:[],...resist])],attunement:{required:requiresAttunement(b)||!!infuse.attunement}},magicBase:true}}const rarity=(_h=infuse.rarity)!=null?_h:"unknown";if(!base){const text=plainText(entry.item);return{entity:{slug:`infused:${slugify(text)}`,name:text,type:"wondrous item",rarity,...overlay,description:""},magicBase:false}}const name=String((_i=data==null?void 0:data.name)!=null?_i:base.name),description=String((_j=data==null?void 0:data.description)!=null?_j:"");const slotted=base.entityType==="armor"||base.entityType==="weapon"?base:typeof(data==null?void 0:data.base_item)==="string"?resolveBaseItem(data.base_item,registry):null;if(slotted&&(slotted.entityType==="armor"||slotted.entityType==="weapon")){const type=slotted.entityType==="weapon"?"weapon":isShieldArmor(slotted.data)?"shield":"armor";return{entity:{slug:base.slug,name,type,rarity,base_item:`[[${slotted.slug}]]`,...overlay,description},magicBase:false}}return{entity:{slug:base.slug,name,type:String((_k=data==null?void 0:data.type)!=null?_k:"adventuring gear"),rarity,...overlay,description},magicBase:false}}function resolveEntryEntity(entry,index,registry,infusions){const view=!infusions?void 0:"views"in infusions?infusions.views.get(index):infusions.index===index?infusions:void 0;if(view)return{entity:view.entity,entityType:view.entityType};return resolveEntityForEntry(entry.item,registry)}function buildInfusionContext(character,resolved,registry){var _a,_b,_c,_d,_e;const equipment=(_a=character.equipment)!=null?_a:[];const pools=((_b=resolved.pools)!=null?_b:[]).filter(p=>!!p.active||p.selected.some(e=>e.itemBound));if(pools.length===0&&!equipment.some(e=>!!e.infusion))return void 0;const owners=new Map;for(const pool of pools)for(const entry of pool.selected)if(entry.itemBound)owners.set(normalizedPickKey(entry.key,entry.entity.repeatable===true),{pool,entry});const views=new Map,flags=[];const newest=new Map;equipment.forEach((e,i)=>{if(!e.infusion)return;const k=markerKey(e.infusion.by);const j=newest.get(k);if(j===void 0||equipment[j].infusion.seq<e.infusion.seq)newest.set(k,i)});equipment.forEach((e,i)=>{var _a2,_b2,_c2;const m=e.infusion;if(!m)return;const owner=owners.get(markerKey(m.by));const nullView=()=>{var _a3,_b3,_c3,_d2,_e2;return{index:i,kind:m.kind,entity:null,entityType:null,key:m.by,seq:m.seq,poolId:(_a3=owner==null?void 0:owner.pool.id)!=null?_a3:"",classIndex:(_b3=owner==null?void 0:owner.pool.classIndex)!=null?_b3:-1,noteSlug:(_c3=owner==null?void 0:owner.entry.slug)!=null?_c3:"",noteName:(_d2=owner==null?void 0:owner.entry.entity.name)!=null?_d2:"",sourceLabel:(_e2=owner==null?void 0:owner.entry.entity.name)!=null?_e2:""}};if(!owner){flags.push({index:i,reason:"orphan"});if(m.kind==="created")views.set(i,nullView());return}if(newest.get(markerKey(m.by))!==i){flags.push({index:i,reason:"duplicate"});if(m.kind==="created")views.set(i,nullView());return}if(((_a2=e.qty)!=null?_a2:1)>1)flags.push({index:i,reason:"stack"});const classLevel=(_c2=(_b2=resolved.classes[owner.pool.classIndex])==null?void 0:_b2.level)!=null?_c2:0;const base={index:i,kind:m.kind,key:m.by,seq:m.seq,poolId:owner.pool.id,classIndex:owner.pool.classIndex,noteSlug:owner.entry.slug,noteName:owner.entry.entity.name,sourceLabel:owner.entry.entity.name};if(m.kind==="created"){const own=resolveEntityForEntry(e.item,registry);const it=resolveBaseItem(e.item,registry);const opt=owner.entry.option;const fits=!!it&&!!(opt==null?void 0:opt.row)&&(opt.item===it.slug||rowMatches(opt.row,it));if(!fits)flags.push({index:i,reason:"mismatch"});views.set(i,{...base,entity:own.entity,entityType:own.entityType});return}if(!owner.entry.entity.infuse){flags.push({index:i,reason:"orphan"});return}const w=wrapInfused(e,owner.entry.entity,classLevel,registry);if(w.magicBase)flags.push({index:i,reason:"magic-base"});views.set(i,{...base,entity:w.entity,entityType:"item"})});const counters=new Map;for(const pool of pools){const words=poolActiveWords(pool);if(!words)continue;const rc=resolved.classes[pool.classIndex];const max=(_e=readTableColumn((_c=rc==null?void 0:rc.entity)==null?void 0:_c.table,(_d=rc==null?void 0:rc.level)!=null?_d:0,[words.column]))!=null?_e:0;const used=[...views.values()].filter(v=>v.poolId===pool.id&&v.entity!==null).length;counters.set(pool.id,{label:words.counterLabel,used,max,over:used>max})}return{views,counters,flags}}function entryCharges(entry,view,registry){return effectiveItemCharges(entry,registry,view)}function withEntryCharges(entry,view,current,registry){var _a,_b,_c,_d,_e,_f;const overlayMax=(view==null?void 0:view.kind)==="infused"?itemChargesMax(view.entity):void 0;if(overlayMax!==void 0&&entry.infusion)return{...entry,infusion:{...entry.infusion,charges:{current:Math.max(0,Math.min(current,overlayMax))}}};const max=(_e=(_d=(_b=(_a=entry.state)==null?void 0:_a.charges)==null?void 0:_b.max)!=null?_d:(_c=effectiveItemCharges(entry,registry,view))==null?void 0:_c.max)!=null?_e:Math.max(0,current);return{...entry,state:{...(_f=entry.state)!=null?_f:{},charges:{current:Math.max(0,Math.min(current,max)),max}}}}function isMarkedEntry(entry){return!!entry.infusion}function splitOne(equipment,index){var _a,_b;const src=equipment[index];if(!src||((_a=src.qty)!=null?_a:1)<=1)return[...equipment];const one={item:src.item,qty:1,...src.in!==void 0?{in:src.in}:{},...src.overrides?{overrides:src.overrides}:{}};return[...equipment.slice(0,index),{...src,qty:((_b=src.qty)!=null?_b:1)-1},one,...equipment.slice(index+1)]}var refuse=reason=>({ok:false,reason});function endInfusion(equipment,index,registry){const entry=equipment[index];if(!(entry==null?void 0:entry.infusion))return{equipment:[...equipment],ended:[]};const{kind,by}=entry.infusion;if(kind==="infused"){const{infusion:_m,...rest}=entry;const keep=requiresAttunement(resolveEntryEntity(rest,index,registry).entity);const next=keep?rest:(({attuned:_a,...r})=>r)(rest);return{equipment:equipment.map((e,i)=>i===index?next:e),ended:[{index,key:by,kind,item:entry.item}]}}const moved=equipment.map((e,i)=>{if(i===index||entry.id===void 0||e.in!==entry.id)return e;if(entry.in===void 0){const{in:_in,...r}=e;return r}return{...e,in:entry.in}});return{equipment:moved.filter((_,i)=>i!==index),ended:[{index:-1,key:by,kind,item:entry.item}]}}var pickKeyOf=e=>normalizedPickKey(e.key,e.entity.repeatable===true);var nextSeq=equipment=>equipment.reduce((m,e)=>{var _a,_b;return Math.max(m,(_b=(_a=e.infusion)==null?void 0:_a.seq)!=null?_b:0)},0)+1;function ownedPick(resolved,key){var _a,_b;const k=markerKey(key);for(const pool of(_a=resolved.pools)!=null?_a:[]){const entry=pool.selected.find(e=>e.itemBound&&pickKeyOf(e)===k);if(entry)return{pool,entry,stranded:strandedPicks(pool).includes(entry)||((_b=entry.option)==null?void 0:_b.status)==="level"}}return null}var wordsOf=(...texts)=>texts.map(lc).join(" ").split(/[^a-z]+/).filter(w=>w!=="");function shapeOf(found,text,registry){var _a,_b,_c;if(!found)return{kind:"gear",words:wordsOf(text)};const data=(_a=found.data)!=null?_a:{};const words=wordsOf((_b=data.name)!=null?_b:text,data.type);const slotted=found.entityType==="armor"||found.entityType==="weapon"?found:typeof data.base_item==="string"?resolveBaseItem(data.base_item,registry):null;if((slotted==null?void 0:slotted.entityType)==="armor"){const armor=slotted.data;return{kind:isShieldArmor(armor)?"shield":"armor",words,category:lc(armor.category)}}if((slotted==null?void 0:slotted.entityType)==="weapon"){const w=slotted.data;return{kind:"weapon",words,category:lc(w.category),properties:((_c=w.properties)!=null?_c:[]).filter(p=>typeof p==="string").map(lc)}}return{kind:"gear",words}}function admits(t,s){var _a,_b,_c,_d;if(t.kind!==s.kind)return false;if(((_a=t.category)==null?void 0:_a.length)&&!t.category.map(lc).includes(((_b=s.category)!=null?_b:"").split("-")[0]))return false;if(t.property&&!((_c=s.properties)!=null?_c:[]).includes(lc(t.property)))return false;if(((_d=t.name_any)==null?void 0:_d.length)&&!t.name_any.some(n=>{const w=wordsOf(n);return w.length>0&&w.every(x=>s.words.includes(x))}))return false;return true}function targetVerdict(entry,infuse,registry){const found=resolveBaseItem(entry.item,registry);if(!infuse.targets.some(t=>admits(t,shapeOf(found,plainText(entry.item),registry))))return"target-kind";return found&&isMagic(found.data)?"magic-base":"ok"}function newObjectEntry(name,infuse,registry,visible){const want=lc(name);const found=[];for(const type of["armor","weapon","item"]){for(const e of registry.search(name,type,Number.POSITIVE_INFINITY)){if(lc(e.name)===want&&!isMagic(e.data)&&visible(e)&&infuse.targets.some(t=>admits(t,shapeOf(e,e.name,registry))))found.push(e)}}const first=found.sort(candidateOrder(void 0))[0];return first?{item:`[[${first.slug}]]`,qty:1}:{item:name,qty:1}}function endBySeqs(equipment,seqs,registry){let eq=[...equipment];let slots=eq.map((_,i)=>i);const rows=[];for(const{seq,by}of seqs){const i=eq.findIndex(e=>{var _a;return((_a=e.infusion)==null?void 0:_a.seq)===seq&&e.infusion.by===by});if(i===-1)continue;const w=endInfusion(eq,i,registry);for(const row of w.ended)rows.push({row,slot:slots[i]});if(eq[i].infusion.kind==="created")slots=slots.filter((_,j)=>j!==i);eq=w.equipment}return{equipment:eq,ended:rows.map(({row,slot})=>row.kind==="infused"?{...row,index:slots.indexOf(slot)}:row)}}function displaced(equipment,resolved,pool,key){var _a;const k=markerKey(key);const out=equipment.filter(e=>!!e.infusion&&markerKey(e.infusion.by)===k).map(e=>({seq:e.infusion.seq,by:e.infusion.by}));const counter=(_a=resolved.infusions)==null?void 0:_a.counters.get(pool.id);if(!counter)return out;const live=[...resolved.infusions.views.values()].filter(v=>v.poolId===pool.id&&v.classIndex===pool.classIndex&&v.entity!==null&&markerKey(v.key)!==k).sort((a,b)=>a.seq-b.seq);let used=live.length;for(const v of live){if(used+1<=counter.max)break;out.push({seq:v.seq,by:v.key});used--}return out}function infuseEntry(character,resolved,registry,req){var _a,_b,_c,_d,_e,_f,_g;const owned=ownedPick(resolved,req.key);if(!owned)return refuse("not-owned");const infuse=owned.entry.entity.infuse;if(!infuse)return refuse("not-infusing");if(owned.stranded)return refuse("stranded");const wantsChoice=((_a=infuse.choice)==null?void 0:_a.kind)==="damage-type";const choice=lc(req.choice);if(wantsChoice&&choice==="")return refuse("choice-required");if(wantsChoice&&!isCanonicalDamageType(choice))return refuse("bad-choice");if(wantsChoice&&((_b=infuse.choice)==null?void 0:_b.options)&&!infuse.choice.options.some(o=>lc(o)===choice))return refuse("bad-choice");const equipment=(_c=character.equipment)!=null?_c:[];const charges=scaledInfuseItem(infuse,(_e=(_d=resolved.classes[owned.pool.classIndex])==null?void 0:_d.level)!=null?_e:0).charges;const marker={kind:"infused",by:owned.entry.key,seq:nextSeq(equipment),...wantsChoice?{choice}:{},...charges?{charges:{current:charges.max}}:{}};let placed;if(typeof req.target==="number"){const target=equipment[req.target];if(!target)return refuse("no-target");if(target.infusion)return refuse("marked");const verdict=targetVerdict(target,infuse,registry);if(verdict!=="ok")return refuse(verdict);const split=((_f=target.qty)!=null?_f:1)>1;placed=split?splitOne(equipment,req.target):[...equipment];const i=split?req.target+1:req.target;placed[i]={...placed[i],infusion:marker}}else{const name=req.target.newObject.trim();if(name==="")return refuse("no-target");placed=[...equipment,{...newObjectEntry(name,infuse,registry,(_g=req.isEntityVisible)!=null?_g:(()=>true)),infusion:marker}]}return{ok:true,...endBySeqs(placed,displaced(equipment,resolved,owned.pool,owned.entry.key),registry)}}function createEntry(character,resolved,registry,req){var _a,_b;const owned=ownedPick(resolved,req.key);if(!owned)return refuse("not-owned");const note=owned.entry.entity;if(!(note.repeatable===true&&!!((_a=note.options)==null?void 0:_a.some(r=>!!r.creates))))return refuse("not-creating");if(owned.stranded)return refuse("stranded");const opt=owned.entry.option;if(!(opt==null?void 0:opt.row)||opt.status!=="ok")return refuse("invalid-item");const it=registry.getByTypeAndSlug("item",linkSlug(req.item.trim()));if(!it||!(opt.item===it.slug||rowMatches(opt.row,it)))return refuse("invalid-item");const equipment=(_b=character.equipment)!=null?_b:[];const placed=[...equipment,{item:`[[${it.slug}]]`,qty:1,infusion:{kind:"created",by:owned.entry.key,seq:nextSeq(equipment)}}];return{ok:true,...endBySeqs(placed,displaced(equipment,resolved,owned.pool,owned.entry.key),registry)}}function markersWhere(equipment,pick){const out=[];equipment.forEach((e,index)=>{const m=e.infusion;if(m&&pick(m))out.push({index,key:m.by,kind:m.kind,item:e.item,seq:m.seq,by:m.by})});return out}var asRows=list=>list.map(({index,key,kind,item})=>({index,key,kind,item}));var storedKeys=v=>typeof v==="string"?[v]:Array.isArray(v)?v:[];function choiceEnds(character,resolved,req){var _a,_b,_c,_d,_e,_f;const pool=((_a=resolved.pools)!=null?_a:[]).find(p=>p.classIndex===req.classIndex&&p.id===req.choiceKey);if(!pool||!(pool.active||pool.selected.some(e=>e.itemBound)))return[];const choices=(_c=(_b=character.class[req.classIndex])==null?void 0:_b.choices)!=null?_c:{};const kept=new Set(req.next.map(markerKey));for(const lvl of Object.keys(choices))if(Number(lvl)!==req.level)for(const s of storedKeys((_d=choices[Number(lvl)])==null?void 0:_d[req.choiceKey]))kept.add(markerKey(s));const removed=new Set(storedKeys((_e=choices[req.level])==null?void 0:_e[req.choiceKey]).map(markerKey).filter(k=>!kept.has(k)));return markersWhere((_f=character.equipment)!=null?_f:[],m=>removed.has(markerKey(m.by)))}function infusionsEndedByChoice(character,resolved,_registry,req){return asRows(choiceEnds(character,resolved,req))}function reconcileChoiceEdit(character,resolved,registry,req){var _a;const list=choiceEnds(character,resolved,req);return list.length===0?null:endBySeqs((_a=character.equipment)!=null?_a:[],list,registry)}function classEnds(character,resolved,req){var _a,_b,_c,_d,_e;let pools=((_a=resolved.pools)!=null?_a:[]).filter(p=>p.classIndex===req.classIndex);if(!("remove"in req)){const old=(_c=(_b=resolved.classes[req.classIndex])==null?void 0:_b.subclass)!=null?_c:null;if(!old||req.subclass!==null&&bareEntitySlug(linkSlug(req.subclass.trim()))===bareEntitySlug(old.slug))return[];const ids=new Set(((_d=old.selection_pools)!=null?_d:[]).map(p=>p.id));pools=pools.filter(p=>ids.has(p.id))}const owned=new Set;for(const pool of pools)for(const e of pool.selected)if(e.itemBound)owned.add(pickKeyOf(e));return markersWhere((_e=character.equipment)!=null?_e:[],m=>owned.has(markerKey(m.by)))}function infusionsEndedByClassEdit(character,resolved,_registry,req){return asRows(classEnds(character,resolved,req))}function reconcileClassEdit(character,resolved,registry,req){var _a;const list=classEnds(character,resolved,req);return list.length===0?null:endBySeqs((_a=character.equipment)!=null?_a:[],list,registry)}function eligibleTargets(character,resolved,registry,key){var _a,_b;const infuse=(_a=ownedPick(resolved,key))==null?void 0:_a.entry.entity.infuse;if(!infuse)return[];const out=[];((_b=character.equipment)!=null?_b:[]).forEach((e,index)=>{var _a2;if(!e.infusion&&targetVerdict(e,infuse,registry)==="ok")out.push({index,stack:((_a2=e.qty)!=null?_a2:1)>1})});return out}var WEAPON_DEFAULT_ACTION_COST="action";var linkOf=item=>{var _a,_b;return(_b=(_a=item.match(/^\[\[(.+)\]\]$/))==null?void 0:_a[1])!=null?_b:null};var ruleOf=(entry,registry,view)=>resolveEntryEntity(entry,view?view.index:-1,registry,view!=null?view:null);function isWeaponLikeEntry(entry,registry,view){if(!registry)return false;const r=ruleOf(entry,registry,view);return defaultSlotForType(r.entityType,r.entity,registry)==="mainhand"}function itemsRowBranch(entry,registry,view){var _a,_b;const link=linkOf(entry.item);if(!link||!registry)return false;const t=view?view.entityType:(_b=(_a=registry.getBySlug(link))==null?void 0:_a.entityType)!=null?_b:null;return t!=="weapon"&&t!=="armor"&&!isWeaponLikeEntry(entry,registry,view)}function customizableOverrideKeys(entry,registry){const consumed=isConsumedOnUse(entry,registry);const keys=new Set(consumed?["name"]:["name","charges","recovery"]);if(!registry)return keys;const r=ruleOf(entry,registry);const slot=defaultSlotForType(r.entityType,r.entity,registry);const weaponLike=slot==="mainhand";const itemsRow=itemsRowBranch(entry,registry);if(weaponLike){keys.add("bonus");keys.add("damage_bonus");keys.add("extra_damage")}if(slot==="armor"||slot==="shield")keys.add("ac_bonus");if(weaponLike||itemsRow)keys.add("action");if(itemsRow)keys.add("range");const link=linkOf(entry.item);if(r.entityType==="item"&&!consumed&&!(link&&isReadOnceItem(link)))keys.add("resist");return keys}function defaultActionCost(entry,registry,view){var _a,_b,_c,_d,_e;if(isWeaponLikeEntry(entry,registry,view))return WEAPON_DEFAULT_ACTION_COST;const link=linkOf(entry.item);if(!link||!registry||!itemsRowBranch(entry,registry,view))return null;const withoutOverrides={...entry,overrides:void 0};const type=view?(_a=view.entity)==null?void 0:_a.type:(_c=(_b=registry.getBySlug(link))==null?void 0:_b.data)==null?void 0:_c.type;return(_e=(_d=resolveItemAction(link,withoutOverrides,type,{view,spellCost:scrollSpellCost(entry,registry)}))==null?void 0:_d.cost)!=null?_e:null}var SPELL_COST={action:"action",bonus:"bonus-action",reaction:"reaction"};function scrollSpellCost(entry,registry){var _a,_b,_c,_d,_e;const ref=(_a=entry.overrides)==null?void 0:_a.spell;if(!ref||!registry)return void 0;const castingTime=(_d=(_c=registry.getByTypeAndSlug("spell",(_b=linkOf(ref))!=null?_b:ref))==null?void 0:_c.data)==null?void 0:_d.casting_time;const kind=typeof castingTime==="string"?(_e=parseCastingTime(castingTime))==null?void 0:_e.kind:void 0;return kind?SPELL_COST[kind]:void 0}var chargesOf=e=>e==null?void 0:e.charges;function itemChargesMax(entity){const c=chargesOf(entity);if(typeof c==="number")return c>0?c:void 0;const m=c==null?void 0:c.max;return typeof m==="number"&&m>0?m:void 0}var RESET_OF=r=>{const s=String(r!=null?r:"").toLowerCase();return s.includes("dawn")?"dawn":s.includes("short")?"short":s.includes("long")?"long":"special"};function rechargeAmount(c){var _a,_b;const raw=[c.recharge_amount,c.dice].find(v=>typeof v==="string"&&v.trim()!=="");if(!raw)return"1";const bare=raw.trim().replace(/^`+|`+$/g,"");return((_b=(_a=parseInlineTag(bare))==null?void 0:_a.content)!=null?_b:bare).replace(/\s+/g,"")}var recoveryOf=(c,needRecharge)=>!c||typeof c==="number"||needRecharge&&(typeof c.recharge!=="string"||c.recharge.trim()==="")?void 0:{amount:rechargeAmount(c),reset:RESET_OF(c.recharge)};function effectiveItemRecovery(entry,registry,view){var _a,_b;if(isConsumedOnUse(entry,registry,view))return void 0;if(view&&view.entity===null)return void 0;if((view==null?void 0:view.kind)==="infused"&&itemChargesMax(view.entity)!==void 0)return recoveryOf(chargesOf(view.entity),false);if((_a=entry.state)==null?void 0:_a.recovery)return entry.state.recovery;const own=registry?recoveryOf(chargesOf(ruleOf(entry,registry,view).entity),true):void 0;if(own)return own;const link=linkOf(entry.item);return link?(_b=findItemAction(link))==null?void 0:_b.recovery:void 0}function isConsumedOnUse(entry,registry,view){var _a;const link=linkOf(entry.item);if(!link)return false;if((_a=findItemAction(link))==null?void 0:_a.consumed)return true;const entity=entityOf(entry,registry,view);return(entity==null?void 0:entity.type)==="potion"||isScrollEntity(entity)}function isScrollEntity(entity){if(!entity||typeof entity!=="object")return false;return entity.type==="scroll"||isCastableScroll(entity)}function isCastableScroll(entity){return settableSpellLevel(entity)!==null&&!storesSpell(entity)}function settableSpellLevel(entity){if(!entity||typeof entity!=="object")return null;const level=entity.scroll_level;return typeof level==="number"?level:null}function storesSpell(entity){if(settableSpellLevel(entity)===null)return false;const e=entity;if(e.type==="scroll")return false;return itemChargesMax(entity)!==void 0||typeof e.spell_charge_cost==="number"}function storedSpellNumbers(entity){if(!storesSpell(entity))return null;const e=entity;const text=[e.description,...Array.isArray(e.entries)?e.entries:[]].filter(t=>typeof t==="string").join("\n");const fromText=re=>{const m=re.exec(text);return m?parseInt(m[1],10):void 0};const saveDC=typeof e.spell_save_dc==="number"?e.spell_save_dc:fromText(/\bsav(?:e|ing throw) DC (?:is|of) (\d+)/i);const attackBonus=typeof e.spell_attack_bonus==="number"?e.spell_attack_bonus:fromText(/\battack bonus (?:is|of) \+?(-?\d+)/i);if(saveDC===void 0&&attackBonus===void 0)return null;return{...saveDC!==void 0?{saveDC}:{},...attackBonus!==void 0?{attackBonus}:{}}}function itemSpellUse(entry,registry,view){const entity=entityOf(entry,registry,view);if(settableSpellLevel(entity)===null)return null;if(isConsumedOnUse(entry,registry,view))return{kind:"consume"};const declared=entity.spell_charge_cost;const cost=typeof declared==="number"&&Number.isInteger(declared)&&declared>=0?declared:1;const charges=effectiveItemCharges(entry,registry,view);if(cost===0||!charges)return{kind:"at-will"};return{kind:"charges",cost,charges:{current:charges.current,max:charges.max}}}function entityOf(entry,registry,view){if(!registry||!linkOf(entry.item))return null;return ruleOf(entry,registry,view).entity}function effectiveItemCharges(entry,registry,view){var _a,_b,_c,_d,_e,_f;if(isConsumedOnUse(entry,registry,view))return void 0;if(view&&view.entity===null)return void 0;const infused=(view==null?void 0:view.kind)==="infused"?itemChargesMax(view.entity):void 0;if(infused!==void 0)return{current:Math.max(0,Math.min((_c=(_b=(_a=entry.infusion)==null?void 0:_a.charges)==null?void 0:_b.current)!=null?_c:infused,infused)),max:infused};const stored=(_d=entry.state)==null?void 0:_d.charges;if(stored)return stored;const own=registry?itemChargesMax(ruleOf(entry,registry,view).entity):void 0;if(own!==void 0)return{current:own,max:own};const link=linkOf(entry.item);const max=link?(_f=(_e=findItemAction(link))==null?void 0:_e.max_charges)!=null?_f:0:0;return max>0?{current:max,max}:void 0}function effectiveItemArmorClass(entry,registry,view){var _a;if(!registry)return null;const{entity}=ruleOf(entry,registry,view);const armor=effectiveArmor(entity,registry);if(!armor)return null;const shield=isShieldArmor(armor);const bonus=isItemEntity(entity)&&typeof((_a=entity.bonuses)==null?void 0:_a.ac)==="number"?entity.bonuses.ac:0;const terms=slotAcTerms(armor,entry);return{value:terms.armor+terms.override+bonus,shield,addDex:!shield&&armor.ac.add_dex===true}}export{WEAPON_DEFAULT_ACTION_COST,isWeaponLikeEntry,customizableOverrideKeys,defaultActionCost,scrollSpellCost,itemChargesMax,effectiveItemRecovery,isConsumedOnUse,isScrollEntity,isCastableScroll,settableSpellLevel,storesSpell,storedSpellNumbers,itemSpellUse,effectiveItemCharges,effectiveItemArmorClass,poolCountLabel,poolActiveWords,parsePickKey,normalizedPickKey,markerKey,isItemBound,optionCandidates,resolveOptionRows,resolveCopyOption,scaledInfuseItem,resolveEntryEntity,buildInfusionContext,entryCharges,withEntryCharges,isMarkedEntry,splitOne,endInfusion,infuseEntry,createEntry,infusionsEndedByChoice,reconcileChoiceEdit,infusionsEndedByClassEdit,reconcileClassEdit,eligibleTargets,bindFeatureConsumers,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolvePool,resolveAllPools,strandedPicks,heldPicks,withoutStrandedSites};
|
|
1
|
+
import{parseCastingTime}from"./chunk-CMIEZQL4.js";import{derivePoolLayout}from"./chunk-O776WL7O.js";import{readTableColumn}from"./chunk-CSTAQQGX.js";import{findItemAction,isReadOnceItem,resolveItemAction}from"./chunk-DVUXUIPV.js";import{requiresAttunement}from"./chunk-YGH7S5ZF.js";import{defaultSlotForType,effectiveArmor,isItemEntity,isShieldArmor,resolveEntityForEntry,slotAcTerms}from"./chunk-4IAMSRHD.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{keptSlugFor,resolveBaseItem}from"./chunk-PZ4L2EEG.js";import{bucketOf,memoByRevision}from"./chunk-QMEKQTUT.js";import{bareEntitySlug,slugify,twinKey,wikilinkTailSlug}from"./chunk-63YJPWTM.js";import{parseInlineTag}from"./chunk-BREHZNTL.js";import{isCanonicalDamageType}from"./chunk-7FPQJDFD.js";function equivalentResourceIds(id,index){var _a,_b,_c;const out=[];const add=other=>{if(other!==id&&index.has(other)&&!out.includes(other))out.push(other)};for(const other of(_b=(_a=index.get(id))==null?void 0:_a.equivalentIds)!=null?_b:[])add(other);for(const res of index.values())if((_c=res.equivalentIds)==null?void 0:_c.includes(id))add(res.id);return out}function ownedByClass(res,rc){var _a,_b;const s=(_a=res==null?void 0:res.owner)==null?void 0:_a.source;if(!s)return false;if(s.kind==="class")return s.slug===((_b=rc.entity)==null?void 0:_b.slug);if(s.kind==="subclass")return!!rc.subclass&&s.slug===rc.subclass.slug;return false}function payingResourceId(id,index,owner){const candidates=[id,...equivalentResourceIds(id,index)].filter(c=>index.has(c));if(candidates.length===0)return void 0;if(owner){const own=candidates.find(c=>ownedByClass(index.get(c),owner));if(own)return own}return candidates[0]}function classOfSource(source,classes){var _a,_b;if(source.kind==="class")return(_a=classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))!=null?_a:null;if(source.kind==="subclass")return(_b=classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))!=null?_b:null;return null}function bindFeatureConsumers(features,index,classes){return features.map(rf=>{const consumes=rf.feature.consumes;const id=consumes==null?void 0:consumes.resource;if(!consumes||typeof id!=="string"||id.length===0)return rf;const payer=payingResourceId(id,index,classOfSource(rf.source,classes));if(payer===void 0||payer===id)return rf;return{...rf,feature:{...rf.feature,consumes:{...consumes,resource:payer}}}})}var SORTED_OPTIONAL_FEATURES=new WeakMap;function sortedOptionalFeatures(registry){return memoByRevision(SORTED_OPTIONAL_FEATURES,registry,()=>bucketOf(registry,"optional-feature").slice().sort((a,b)=>a.name.localeCompare(b.name)||a.slug.localeCompare(b.slug)))}var SRD_OWNER_PREFIXES=new Set(["srd-5e","srd-2024"]);function levelPrereqMax(d){var _a;return((_a=d.prerequisites)!=null?_a:[]).filter(p=>p.kind==="level").reduce((m,p)=>Math.max(m,p.min),0)}function namedRefKey(name){return name?slugify(name.replace(/\s*\([^)]*\)\s*$/,"")):""}function levelPrereqRefsMet(d,rc){var _a,_b;for(const p of(_a=d.prerequisites)!=null?_a:[]){if(p.kind!=="level")continue;if(p.class&&namedRefKey(p.class.name)!==namedRefKey((_b=rc.entity)==null?void 0:_b.name))return false;if(p.subclass){const sub=rc.subclass;const own=[sub==null?void 0:sub.short_name,sub==null?void 0:sub.name].map(namedRefKey).filter(k=>k!=="");if(!own.includes(namedRefKey(p.subclass.name)))return false}}return true}function optionalFeaturePrereqKeys(d){var _a;return((_a=d.prerequisites)!=null?_a:[]).filter(p=>p.kind==="optionalfeature").map(p=>twinKey(wikilinkTailSlug(p.optionalfeature)))}function withOptionalFeaturePrereqsMet(offered,selected,grants){let open=offered;for(;;){const openSlugs=new Set(open.map(e=>e.slug));const held=new Set([...grants,...selected.filter(e=>openSlugs.has(e.slug))].map(e=>twinKey(e.slug)));const next=open.filter(e=>optionalFeaturePrereqKeys(e.entity).every(k=>held.has(k)));if(next.length===open.length)return next;open=next}}function poolAnchorLevel(entity,pool){let anchorLevel=1;let columnSeen=false;for(let l=1;l<=20;l++){const c=readTableColumn(entity.table,l,[pool.count.column]);if(c!=null)columnSeen=true;if(c!=null&&c>=1){anchorLevel=l;break}}return{anchorLevel,columnSeen}}function resolvePool(rc,classIndex,pool,registry,index,edition){var _a,_b,_c,_d,_e,_f,_g,_h,_i;const entity=rc.entity;const level=rc.level;const ownerBare=bareEntitySlug(entity.slug);const ownerPrefix=entity.slug.split("_")[0];const ownEdition=SRD_OWNER_PREFIXES.has(ownerPrefix)?entity.edition:void 0;const col=pool.count.column;const count=(_a=readTableColumn(entity.table,level,[col]))!=null?_a:0;const{anchorLevel,columnSeen}=poolAnchorLevel(entity,pool);if(!columnSeen){warnOnce(`pool-column:${pool.id}`,`Archivist: pool "${pool.id}" declares count column "${col}", which "${entity.slug}"'s class table carries at no level; the pool resolves count 0 at anchor level 1`)}const ft=pool.source.where.feature_type;const all=sortedOptionalFeatures(registry);const entryOf=(slug,entity2,compendium)=>({slug,entity:entity2,...compendium?{compendium}:{},key:slug,param:null,itemBound:isItemBound(entity2)});const byBare=new Map;const candidates=new Map;for(const e of all){const d=e.data;const entry=entryOf(e.slug,d,e.compendium);const bare=bareEntitySlug(e.slug);byBare.set(bare,entry);if(d.feature_type!==ft)continue;if(!((_b=d.available_to)!=null?_b:[]).some(l=>wikilinkTailSlug(l)===ownerBare))continue;if(levelPrereqMax(d)>level)continue;if(!levelPrereqRefsMet(d,rc))continue;if(ownEdition&&d.edition&&d.edition!==ownEdition)continue;const key=twinKey(e.slug);const group=candidates.get(key);if(group)group.push(entry);else candidates.set(key,[entry])}const collapsed=[];for(const group of candidates.values()){if(group.length===1){collapsed.push(group[0]);continue}const bare=bareEntitySlug(group[0].slug);const owned=group.find(e=>e.slug.split("_")[0]===ownerPrefix);if(!owned){warnOnce(`pool-collapse:${bare}`,`Archivist: pool "${pool.id}" holds ${group.length} cross-edition entries for "${bare}" and none shares the owner's compendium prefix "${ownerPrefix}"; keeping "${group[0].slug}"`)}collapsed.push(owned!=null?owned:group[0])}const grantDecls=[...(_d=(_c=rc.entity)==null?void 0:_c.pool_grants)!=null?_d:[],...(_f=(_e=rc.subclass)==null?void 0:_e.pool_grants)!=null?_f:[]];const grantsRaw=grantDecls.filter(g=>g.pool===pool.id).flatMap(g=>g.grants).filter(g=>g.at_level<=level).map(g=>byBare.get(wikilinkTailSlug(g.feature))).filter(e=>e!=null);const grantedBare=new Set;const grants=grantsRaw.filter(e=>{const key=bareEntitySlug(e.slug);if(grantedBare.has(key))return false;grantedBare.add(key);return true});const offered=collapsed.filter(e=>!grantedBare.has(bareEntitySlug(e.slug)));const bySlugAvailable=new Map(offered.map(e=>[e.slug,e]));const byTwinAvailable=new Map(offered.map(e=>[twinKey(e.slug),e]));const resolveStored=s=>{const exact=bySlugAvailable.get(s);if(exact)return exact;const survivor=byTwinAvailable.get(twinKey(s));if(survivor)return survivor;const full=registry.getByTypeAndSlug("optional-feature",s);if(full)return entryOf(full.slug,full.data,full.compendium);return byBare.get(bareEntitySlug(s))};const raw=(_g=rc.choices[anchorLevel])==null?void 0:_g[pool.id];const selectedSlugs=Array.isArray(raw)?raw:typeof raw==="string"?[raw]:[];const selected=[];const seenKeys=new Set;for(const s of selectedSlugs){const{slugPart,param}=parsePickKey(s);const entry=resolveStored(slugPart);if(!entry)continue;const repeatable=entry.entity.repeatable===true;if(!repeatable&¶m!==null){warnOnce(`pick-param:${pool.id}:${s}`,`Archivist: pool "${pool.id}" pick "${s}" names a parameter, but "${entry.slug}" is not repeatable; the parameter is ignored`)}const nkey=repeatable?normalizedPickKey(s,true):twinKey(entry.slug);if(grantedBare.has(bareEntitySlug(entry.slug))||seenKeys.has(nkey))continue;seenKeys.add(nkey);selected.push({...entry,key:repeatable||param!==null?s:entry.slug,param:repeatable?param:null,...repeatable?{option:resolveCopyOption(entry.entity,param,{classLevel:level,registry,edition})}:{}})}const available=withOptionalFeaturePrereqsMet(offered,selected,grants);const members=[...available,...grants];const layout=derivePoolLayout(members);const votes=new Map;for(const e of members){const id=(_h=e.entity.consumes)==null?void 0:_h.resource;const payer=id?payingResourceId(id,index,rc):void 0;if(!payer)continue;votes.set(payer,((_i=votes.get(payer))!=null?_i:0)+1)}let resource;let bestN=0;for(const[id,n]of votes)if(n>bestN){resource=id;bestN=n}const bind=poolRebinder(rc,pool.id,resource,index);return{id:pool.id,label:pool.label,classIndex,count,anchorLevel,selected:selected.map(bind),available:available.map(bind),grants:grants.map(bind),...layout?{layout}:{},...resource?{resource}:{},...pool.count.label?{countLabel:pool.count.label}:{},...pool.active?{active:pool.active}:{},...pool.head_resource?{headResource:pool.head_resource}:{}}}function poolRebinder(rc,poolId,vote,index){const declared=declaredResourceIds(rc);const copies=new Map;return e=>{const consumes=e.entity.consumes;const id=consumes==null?void 0:consumes.resource;if(!consumes||typeof id!=="string"||id.length===0)return e;const payer=payingResourceId(id,index,rc);if(payer===id)return e;const target=payer!=null?payer:vote!==void 0&&!declared.has(id)?vote:void 0;if(target===void 0)return e;const done=copies.get(e.key);if(done)return done;if(payer===void 0){warnOnce(`pool-rebind:${poolId}:${id}`,`Archivist: pool "${poolId}" members consume "${id}", which this character does not own; bound to the pool's resource "${target}"`)}const copy={...e,entity:{...e.entity,consumes:{...consumes,resource:target}}};copies.set(e.key,copy);return copy}}function declaredResourceIds(rc){var _a;const out=new Set;const add=list=>{for(const r of list!=null?list:[])if(typeof(r==null?void 0:r.id)==="string")out.add(r.id)};for(const owner of[rc.entity,rc.subclass]){if(!owner)continue;add(owner.resources);for(const features of Object.values((_a=owner.features_by_level)!=null?_a:{}))for(const f of features!=null?features:[])add(f.resources)}return out}function resolveAllPools(resolved,registry,index){const out=[];resolved.classes.forEach((rc,classIndex)=>{var _a,_b,_c,_d;if(!rc.entity)return;const decls=[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]];const seen=new Set;for(const pool of decls){if(seen.has(pool.id))continue;seen.add(pool.id);out.push(resolvePool(rc,classIndex,pool,registry,index,(_d=resolved.definition)==null?void 0:_d.edition))}});return out}function strandedPicks(pool){const inAvailable=new Set(pool.available.map(e=>e.slug));return pool.selected.filter(e=>!inAvailable.has(e.slug))}function heldPicks(pool){var _a;const selected=(_a=pool.selected)!=null?_a:[];if(!pool.available)return[...selected];const inAvailable=new Set(pool.available.map(e=>e.slug));return selected.filter(e=>inAvailable.has(e.slug))}function withoutStrandedSites(sites,classes,registry,edition){if(sites.length===0)return sites;const strandedKeys=new Map;const keysOf=(classIndex,poolId)=>{var _a,_b,_c;const at=`${classIndex}:${poolId}`;let keys=strandedKeys.get(at);if(keys)return keys;const rc=classes[classIndex];const decl=(rc==null?void 0:rc.entity)?[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]].find(p=>p.id===poolId):void 0;keys=new Set(rc&&decl?strandedPicks(resolvePool(rc,classIndex,decl,registry,new Map,edition)).map(e=>twinKey(e.slug)):[]);strandedKeys.set(at,keys);return keys};return sites.filter(site=>!keysOf(site.classIndex,site.poolId).has(twinKey(site.memberSlug)))}function poolCountLabel(pool){var _a;return(_a=pool.countLabel)!=null?_a:"Known"}function poolActiveWords(pool){var _a,_b,_c;const a=pool.active;if(!a)return null;return{column:a.column,label:a.label,verb:a.verb,counterLabel:(_a=a.counter_label)!=null?_a:a.label,createLabel:(_b=a.create_label)!=null?_b:"Created",createVerb:(_c=a.create_verb)!=null?_c:"Create"}}function parsePickKey(stored){const i=stored.indexOf("#");return i===-1?{slugPart:stored,param:null}:{slugPart:stored.slice(0,i),param:stored.slice(i+1)}}function normalizedPickKey(stored,repeatable){const{slugPart,param}=parsePickKey(stored);return repeatable?`${bareEntitySlug(slugPart)}#${param!=null?param:""}`:bareEntitySlug(slugPart)}function markerKey(by){const{slugPart,param}=parsePickKey(by);return param===null?bareEntitySlug(slugPart):`${bareEntitySlug(slugPart)}#${param}`}function isItemBound(note){var _a;return!!note.infuse||note.repeatable===true&&!!((_a=note.options)==null?void 0:_a.some(r=>!!r.creates))}var SRD_BOOKS=new Set(["SRD 2024","SRD 5e"]);var lc=v=>String(v!=null?v:"").trim().toLowerCase();var linkSlug=link=>link.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0];var itemsOf=registry=>registry.search("","item",Number.POSITIVE_INFINITY);function matchesFilter(data,f){var _a;const type=lc(data.type);if(!f.rarity.map(lc).includes(lc(data.rarity)))return false;if(f.types&&!f.types.map(lc).includes(type))return false;if((_a=f.exclude_types)==null?void 0:_a.map(lc).includes(type))return false;return!(f.cursed===false&&data.cursed===true)}function rowMatches(row,it){const c=row.creates;if(c.item)return lc(it.name)===lc(row.name)||it.slug===linkSlug(c.item);if(c.variant)return c.variant.candidates.some(l=>bareEntitySlug(linkSlug(l))===bareEntitySlug(it.slug));return!!c.filter&&matchesFilter(it.data,c.filter)}function buildItemIndex(items){const lcType=[],lcRarity=[];const byLcName=new Map,bySlug=new Map,byBare=new Map;const push=(m,k,i)=>{const l=m.get(k);if(l)l.push(i);else m.set(k,[i])};items.forEach((it,i)=>{const data=it.data;lcType.push(lc(data.type));lcRarity.push(lc(data.rarity));push(byLcName,lc(it.name),i);if(!bySlug.has(it.slug))bySlug.set(it.slug,i);push(byBare,bareEntitySlug(it.slug),i)});return{items,lcType,lcRarity,byLcName,bySlug,byBare}}var ITEM_INDEX=new WeakMap;var itemIndexOf=registry=>memoByRevision(ITEM_INDEX,registry,()=>buildItemIndex(itemsOf(registry)));var inBucketOrder=(ix,hits)=>[...hits].sort((a,b)=>a-b).map(i=>ix.items[i]);function rowInstalledIn(row,ix){var _a,_b,_c;const c=row.creates;if(c.item){const hits=new Set((_a=ix.byLcName.get(lc(row.name)))!=null?_a:[]);const own=ix.bySlug.get(linkSlug(c.item));if(own!==void 0)hits.add(own);return inBucketOrder(ix,hits)}if(c.variant){const hits=new Set;for(const l of c.variant.candidates)for(const i of(_b=ix.byBare.get(bareEntitySlug(linkSlug(l))))!=null?_b:[])hits.add(i);return inBucketOrder(ix,hits)}const f=c.filter;if(!f)return[];const rarities=new Set(f.rarity.map(lc));const types=f.types?new Set(f.types.map(lc)):null;const excluded=new Set(((_c=f.exclude_types)!=null?_c:[]).map(lc));return ix.items.filter((it,i)=>rarities.has(ix.lcRarity[i])&&(!types||types.has(ix.lcType[i]))&&!excluded.has(ix.lcType[i])&&!(f.cursed===false&&it.data.cursed===true))}var rowInstalled=(row,registry)=>rowInstalledIn(row,itemIndexOf(registry));function candidateOrder(edition){return(a,b)=>{const ea=edition&&lc(a.data.edition)===edition?0:1;const eb=edition&&lc(b.data.edition)===edition?0:1;if(ea!==eb)return ea-eb;const sa=SRD_BOOKS.has(a.compendium)?0:1,sb=SRD_BOOKS.has(b.compendium)?0:1;if(sa!==sb)return sa-sb;return a.slug<b.slug?-1:a.slug>b.slug?1:0}}function optionCandidates(row,registry,opts={}){return candidatesFrom(rowInstalled(row,registry),registry,opts)}function candidatesFrom(installed,registry,opts){var _a,_b;const visible=(_a=opts.isEntityVisible)!=null?_a:(()=>true);const excluded=((_b=opts.exclude)!=null?_b:[]).map(s=>{var _a2;return registry.getByTypeAndSlug("item",(_a2=keptSlugFor(s))!=null?_a2:s)}).filter(e=>!!e);const exNames=new Set(excluded.map(e=>lc(e.name))),exBares=new Set(excluded.map(e=>bareEntitySlug(e.slug)));const seen=new Set,out=[];for(const e of installed.filter(visible).sort(candidateOrder(opts.edition))){const bare=bareEntitySlug(e.slug);if(seen.has(bare))continue;seen.add(bare);if(exNames.has(lc(e.name))||exBares.has(bare))continue;out.push(e.slug)}return out}function resolveOptionRows(note,registry,opts={}){var _a;const ix=itemIndexOf(registry);return((_a=note.options)!=null?_a:[]).map(row=>{var _a2;const rowItems=rowInstalledIn(row,ix);const candidates=candidatesFrom(rowItems,registry,opts);const anyVisible=candidates.length>0||candidatesFrom(rowItems,registry,{...opts,exclude:[]}).length>0;const installed=rowItems.length>0;return{key:row.key,name:row.name,minLevel:row.min_level,...row.attunement!==void 0?{attunement:row.attunement}:{},arm:row.creates.item?"item":row.creates.variant?"variant":"filter",candidates,availability:anyVisible?"installed":installed?"hidden-only":"not-installed",...rowItemWords(row,candidates[0]?ix.items[(_a2=ix.bySlug.get(candidates[0]))!=null?_a2:-1]:rowItems[0])}})}function rowItemWords(row,item){var _a,_b,_c,_d;const f=row.creates.filter;if(f)return{type:((_a=f.types)==null?void 0:_a[0])?lc(f.types[0]):null,rarity:f.rarity[0]?lc(f.rarity[0]):null,charges:null};const data=(_b=item==null?void 0:item.data)!=null?_b:{};const max=(_c=data.charges)==null?void 0:_c.max;return{type:lc(data.type)||null,rarity:lc(data.rarity)||null,charges:typeof max==="number"&&max>0?{max,...typeof((_d=data.charges)==null?void 0:_d.recharge)==="string"?{recharge:data.charges.recharge}:{}}:null}}function resolveCopyOption(note,param,ctx){var _a,_b,_c;const rows=(_a=note.options)!=null?_a:[];if(param===null||param==="")return{row:null,status:"needs-choice"};if(note.item_choice==="create"){const row=rows.find(r=>r.key===param);if(!row)return{row:null,status:"invalid"};const installed=rowInstalled(row,ctx.registry).sort(candidateOrder(ctx.edition));if(installed.length===0)return{row,status:"not-installed"};const own=row.creates.item?linkSlug(row.creates.item):void 0;const item=row.creates.item?((_b=installed.find(e=>e.slug===own))!=null?_b:installed[0]).slug:void 0;return{row,...item?{item}:{},status:row.min_level<=ctx.classLevel?"ok":"level"}}const slug=(_c=keptSlugFor(param))!=null?_c:param;const it=ctx.registry.getByTypeAndSlug("item",slug);if(!it)return{row:null,item:slug,status:"not-installed"};const matching=rows.filter(r=>rowMatches(r,it)).sort((a,b)=>a.min_level-b.min_level);if(matching.length===0)return{row:null,item:slug,status:"invalid"};return{row:matching[0],item:slug,status:matching[0].min_level<=ctx.classLevel?"ok":"level"}}var MUNDANE=new Set(["","none","mundane"]);var isMagic=data=>{const r=data==null?void 0:data.rarity;return typeof r==="string"&&!MUNDANE.has(r.trim().toLowerCase())};var plainText=item=>item.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|").pop().split("/").pop();function scaledInfuseItem(infuse,classLevel){var _a,_b;let item={...(_a=infuse.item)!=null?_a:{}};const rows=[...(_b=infuse.scales_at)!=null?_b:[]].sort((a,b)=>a.level-b.level);for(const row of rows)if(row.level<=classLevel)item={...item,...row.item};return item}function wrapInfused(entry,note,classLevel,registry){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k;const infuse=note.infuse;const item=scaledInfuseItem(infuse,classLevel);const resist=[...(_a=item.resist)!=null?_a:[],...((_b=infuse.choice)==null?void 0:_b.kind)==="damage-type"&&((_c=entry.infusion)==null?void 0:_c.choice)?[entry.infusion.choice]:[]];const overlay={...item.bonuses?{bonuses:item.bonuses}:{},resist,...item.charges?{charges:item.charges}:{},...item.action?{action:item.action}:{},...item.range?{range:item.range}:{},...infuse.attunement?{attunement:{required:true}}:{}};const base=resolveBaseItem(entry.item,registry);const data=(_d=base==null?void 0:base.data)!=null?_d:null;if(base&&isMagic(data)){const b=data;const bonuses={...(_e=b.bonuses)!=null?_e:{}};for(const[k,v]of Object.entries((_f=item.bonuses)!=null?_f:{}))if(typeof v==="number")bonuses[k]=(typeof bonuses[k]==="number"?bonuses[k]:0)+v;return{entity:{...b,bonuses,resist:[...new Set([...(_g=b.resist)!=null?_g:[],...resist])],attunement:{required:requiresAttunement(b)||!!infuse.attunement}},magicBase:true}}const rarity=(_h=infuse.rarity)!=null?_h:"unknown";if(!base){const text=plainText(entry.item);return{entity:{slug:`infused:${slugify(text)}`,name:text,type:"wondrous item",rarity,...overlay,description:""},magicBase:false}}const name=String((_i=data==null?void 0:data.name)!=null?_i:base.name),description=String((_j=data==null?void 0:data.description)!=null?_j:"");const slotted=base.entityType==="armor"||base.entityType==="weapon"?base:typeof(data==null?void 0:data.base_item)==="string"?resolveBaseItem(data.base_item,registry):null;if(slotted&&(slotted.entityType==="armor"||slotted.entityType==="weapon")){const type=slotted.entityType==="weapon"?"weapon":isShieldArmor(slotted.data)?"shield":"armor";return{entity:{slug:base.slug,name,type,rarity,base_item:`[[${slotted.slug}]]`,...overlay,description},magicBase:false}}return{entity:{slug:base.slug,name,type:String((_k=data==null?void 0:data.type)!=null?_k:"adventuring gear"),rarity,...overlay,description},magicBase:false}}function resolveEntryEntity(entry,index,registry,infusions){const view=!infusions?void 0:"views"in infusions?infusions.views.get(index):infusions.index===index?infusions:void 0;if(view)return{entity:view.entity,entityType:view.entityType};return resolveEntityForEntry(entry.item,registry)}function buildInfusionContext(character,resolved,registry){var _a,_b,_c,_d,_e;const equipment=(_a=character.equipment)!=null?_a:[];const pools=((_b=resolved.pools)!=null?_b:[]).filter(p=>!!p.active||p.selected.some(e=>e.itemBound));if(pools.length===0&&!equipment.some(e=>!!e.infusion))return void 0;const owners=new Map;for(const pool of pools)for(const entry of pool.selected)if(entry.itemBound)owners.set(normalizedPickKey(entry.key,entry.entity.repeatable===true),{pool,entry});const views=new Map,flags=[];const newest=new Map;equipment.forEach((e,i)=>{if(!e.infusion)return;const k=markerKey(e.infusion.by);const j=newest.get(k);if(j===void 0||equipment[j].infusion.seq<e.infusion.seq)newest.set(k,i)});equipment.forEach((e,i)=>{var _a2,_b2,_c2;const m=e.infusion;if(!m)return;const owner=owners.get(markerKey(m.by));const nullView=()=>{var _a3,_b3,_c3,_d2,_e2;return{index:i,kind:m.kind,entity:null,entityType:null,key:m.by,seq:m.seq,poolId:(_a3=owner==null?void 0:owner.pool.id)!=null?_a3:"",classIndex:(_b3=owner==null?void 0:owner.pool.classIndex)!=null?_b3:-1,noteSlug:(_c3=owner==null?void 0:owner.entry.slug)!=null?_c3:"",noteName:(_d2=owner==null?void 0:owner.entry.entity.name)!=null?_d2:"",sourceLabel:(_e2=owner==null?void 0:owner.entry.entity.name)!=null?_e2:""}};if(!owner){flags.push({index:i,reason:"orphan"});if(m.kind==="created")views.set(i,nullView());return}if(newest.get(markerKey(m.by))!==i){flags.push({index:i,reason:"duplicate"});if(m.kind==="created")views.set(i,nullView());return}if(((_a2=e.qty)!=null?_a2:1)>1)flags.push({index:i,reason:"stack"});const classLevel=(_c2=(_b2=resolved.classes[owner.pool.classIndex])==null?void 0:_b2.level)!=null?_c2:0;const base={index:i,kind:m.kind,key:m.by,seq:m.seq,poolId:owner.pool.id,classIndex:owner.pool.classIndex,noteSlug:owner.entry.slug,noteName:owner.entry.entity.name,sourceLabel:owner.entry.entity.name};if(m.kind==="created"){const own=resolveEntityForEntry(e.item,registry);const it=resolveBaseItem(e.item,registry);const opt=owner.entry.option;const fits=!!it&&!!(opt==null?void 0:opt.row)&&(opt.item===it.slug||rowMatches(opt.row,it));if(!fits)flags.push({index:i,reason:"mismatch"});views.set(i,{...base,entity:own.entity,entityType:own.entityType});return}if(!owner.entry.entity.infuse){flags.push({index:i,reason:"orphan"});return}const w=wrapInfused(e,owner.entry.entity,classLevel,registry);if(w.magicBase)flags.push({index:i,reason:"magic-base"});views.set(i,{...base,entity:w.entity,entityType:"item"})});const counters=new Map;for(const pool of pools){const words=poolActiveWords(pool);if(!words)continue;const rc=resolved.classes[pool.classIndex];const max=(_e=readTableColumn((_c=rc==null?void 0:rc.entity)==null?void 0:_c.table,(_d=rc==null?void 0:rc.level)!=null?_d:0,[words.column]))!=null?_e:0;const used=[...views.values()].filter(v=>v.poolId===pool.id&&v.entity!==null).length;counters.set(pool.id,{label:words.counterLabel,used,max,over:used>max})}return{views,counters,flags}}function entryCharges(entry,view,registry){return effectiveItemCharges(entry,registry,view)}function withEntryCharges(entry,view,current,registry){var _a,_b,_c,_d,_e,_f;const overlayMax=(view==null?void 0:view.kind)==="infused"?itemChargesMax(view.entity):void 0;if(overlayMax!==void 0&&entry.infusion)return{...entry,infusion:{...entry.infusion,charges:{current:Math.max(0,Math.min(current,overlayMax))}}};const max=(_e=(_d=(_b=(_a=entry.state)==null?void 0:_a.charges)==null?void 0:_b.max)!=null?_d:(_c=effectiveItemCharges(entry,registry,view))==null?void 0:_c.max)!=null?_e:Math.max(0,current);return{...entry,state:{...(_f=entry.state)!=null?_f:{},charges:{current:Math.max(0,Math.min(current,max)),max}}}}function isMarkedEntry(entry){return!!entry.infusion}function splitOne(equipment,index){var _a,_b;const src=equipment[index];if(!src||((_a=src.qty)!=null?_a:1)<=1)return[...equipment];const one={item:src.item,qty:1,...src.in!==void 0?{in:src.in}:{},...src.overrides?{overrides:src.overrides}:{}};return[...equipment.slice(0,index),{...src,qty:((_b=src.qty)!=null?_b:1)-1},one,...equipment.slice(index+1)]}var refuse=reason=>({ok:false,reason});function endInfusion(equipment,index,registry){const entry=equipment[index];if(!(entry==null?void 0:entry.infusion))return{equipment:[...equipment],ended:[]};const{kind,by}=entry.infusion;if(kind==="infused"){const{infusion:_m,...rest}=entry;const keep=requiresAttunement(resolveEntryEntity(rest,index,registry).entity);const next=keep?rest:(({attuned:_a,...r})=>r)(rest);return{equipment:equipment.map((e,i)=>i===index?next:e),ended:[{index,key:by,kind,item:entry.item}]}}const moved=equipment.map((e,i)=>{if(i===index||entry.id===void 0||e.in!==entry.id)return e;if(entry.in===void 0){const{in:_in,...r}=e;return r}return{...e,in:entry.in}});return{equipment:moved.filter((_,i)=>i!==index),ended:[{index:-1,key:by,kind,item:entry.item}]}}var pickKeyOf=e=>normalizedPickKey(e.key,e.entity.repeatable===true);var nextSeq=equipment=>equipment.reduce((m,e)=>{var _a,_b;return Math.max(m,(_b=(_a=e.infusion)==null?void 0:_a.seq)!=null?_b:0)},0)+1;function ownedPick(resolved,key){var _a,_b;const k=markerKey(key);for(const pool of(_a=resolved.pools)!=null?_a:[]){const entry=pool.selected.find(e=>e.itemBound&&pickKeyOf(e)===k);if(entry)return{pool,entry,stranded:strandedPicks(pool).includes(entry)||((_b=entry.option)==null?void 0:_b.status)==="level"}}return null}var wordsOf=(...texts)=>texts.map(lc).join(" ").split(/[^a-z]+/).filter(w=>w!=="");function shapeOf(found,text,registry){var _a,_b,_c;if(!found)return{kind:"gear",words:wordsOf(text)};const data=(_a=found.data)!=null?_a:{};const words=wordsOf((_b=data.name)!=null?_b:text,data.type);const slotted=found.entityType==="armor"||found.entityType==="weapon"?found:typeof data.base_item==="string"?resolveBaseItem(data.base_item,registry):null;if((slotted==null?void 0:slotted.entityType)==="armor"){const armor=slotted.data;return{kind:isShieldArmor(armor)?"shield":"armor",words,category:lc(armor.category)}}if((slotted==null?void 0:slotted.entityType)==="weapon"){const w=slotted.data;return{kind:"weapon",words,category:lc(w.category),properties:((_c=w.properties)!=null?_c:[]).filter(p=>typeof p==="string").map(lc)}}return{kind:"gear",words}}function admits(t,s){var _a,_b,_c,_d;if(t.kind!==s.kind)return false;if(((_a=t.category)==null?void 0:_a.length)&&!t.category.map(lc).includes(((_b=s.category)!=null?_b:"").split("-")[0]))return false;if(t.property&&!((_c=s.properties)!=null?_c:[]).includes(lc(t.property)))return false;if(((_d=t.name_any)==null?void 0:_d.length)&&!t.name_any.some(n=>{const w=wordsOf(n);return w.length>0&&w.every(x=>s.words.includes(x))}))return false;return true}function targetVerdict(entry,infuse,registry){const found=resolveBaseItem(entry.item,registry);if(!infuse.targets.some(t=>admits(t,shapeOf(found,plainText(entry.item),registry))))return"target-kind";return found&&isMagic(found.data)?"magic-base":"ok"}function newObjectEntry(name,infuse,registry,visible){const want=lc(name);const found=[];for(const type of["armor","weapon","item"]){for(const e of registry.search(name,type,Number.POSITIVE_INFINITY)){if(lc(e.name)===want&&!isMagic(e.data)&&visible(e)&&infuse.targets.some(t=>admits(t,shapeOf(e,e.name,registry))))found.push(e)}}const first=found.sort(candidateOrder(void 0))[0];return first?{item:`[[${first.slug}]]`,qty:1}:{item:name,qty:1}}function endBySeqs(equipment,seqs,registry){let eq=[...equipment];let slots=eq.map((_,i)=>i);const rows=[];for(const{seq,by}of seqs){const i=eq.findIndex(e=>{var _a;return((_a=e.infusion)==null?void 0:_a.seq)===seq&&e.infusion.by===by});if(i===-1)continue;const w=endInfusion(eq,i,registry);for(const row of w.ended)rows.push({row,slot:slots[i]});if(eq[i].infusion.kind==="created")slots=slots.filter((_,j)=>j!==i);eq=w.equipment}return{equipment:eq,ended:rows.map(({row,slot})=>row.kind==="infused"?{...row,index:slots.indexOf(slot)}:row)}}function displaced(equipment,resolved,pool,key){var _a;const k=markerKey(key);const out=equipment.filter(e=>!!e.infusion&&markerKey(e.infusion.by)===k).map(e=>({seq:e.infusion.seq,by:e.infusion.by}));const counter=(_a=resolved.infusions)==null?void 0:_a.counters.get(pool.id);if(!counter)return out;const live=[...resolved.infusions.views.values()].filter(v=>v.poolId===pool.id&&v.classIndex===pool.classIndex&&v.entity!==null&&markerKey(v.key)!==k).sort((a,b)=>a.seq-b.seq);let used=live.length;for(const v of live){if(used+1<=counter.max)break;out.push({seq:v.seq,by:v.key});used--}return out}function infuseEntry(character,resolved,registry,req){var _a,_b,_c,_d,_e,_f,_g;const owned=ownedPick(resolved,req.key);if(!owned)return refuse("not-owned");const infuse=owned.entry.entity.infuse;if(!infuse)return refuse("not-infusing");if(owned.stranded)return refuse("stranded");const wantsChoice=((_a=infuse.choice)==null?void 0:_a.kind)==="damage-type";const choice=lc(req.choice);if(wantsChoice&&choice==="")return refuse("choice-required");if(wantsChoice&&!isCanonicalDamageType(choice))return refuse("bad-choice");if(wantsChoice&&((_b=infuse.choice)==null?void 0:_b.options)&&!infuse.choice.options.some(o=>lc(o)===choice))return refuse("bad-choice");const equipment=(_c=character.equipment)!=null?_c:[];const charges=scaledInfuseItem(infuse,(_e=(_d=resolved.classes[owned.pool.classIndex])==null?void 0:_d.level)!=null?_e:0).charges;const marker={kind:"infused",by:owned.entry.key,seq:nextSeq(equipment),...wantsChoice?{choice}:{},...charges?{charges:{current:charges.max}}:{}};let placed;if(typeof req.target==="number"){const target=equipment[req.target];if(!target)return refuse("no-target");if(target.infusion)return refuse("marked");const verdict=targetVerdict(target,infuse,registry);if(verdict!=="ok")return refuse(verdict);const split=((_f=target.qty)!=null?_f:1)>1;placed=split?splitOne(equipment,req.target):[...equipment];const i=split?req.target+1:req.target;placed[i]={...placed[i],infusion:marker}}else{const name=req.target.newObject.trim();if(name==="")return refuse("no-target");placed=[...equipment,{...newObjectEntry(name,infuse,registry,(_g=req.isEntityVisible)!=null?_g:(()=>true)),infusion:marker}]}return{ok:true,...endBySeqs(placed,displaced(equipment,resolved,owned.pool,owned.entry.key),registry)}}function createEntry(character,resolved,registry,req){var _a,_b;const owned=ownedPick(resolved,req.key);if(!owned)return refuse("not-owned");const note=owned.entry.entity;if(!(note.repeatable===true&&!!((_a=note.options)==null?void 0:_a.some(r=>!!r.creates))))return refuse("not-creating");if(owned.stranded)return refuse("stranded");const opt=owned.entry.option;if(!(opt==null?void 0:opt.row)||opt.status!=="ok")return refuse("invalid-item");const it=registry.getByTypeAndSlug("item",linkSlug(req.item.trim()));if(!it||!(opt.item===it.slug||rowMatches(opt.row,it)))return refuse("invalid-item");const equipment=(_b=character.equipment)!=null?_b:[];const placed=[...equipment,{item:`[[${it.slug}]]`,qty:1,infusion:{kind:"created",by:owned.entry.key,seq:nextSeq(equipment)}}];return{ok:true,...endBySeqs(placed,displaced(equipment,resolved,owned.pool,owned.entry.key),registry)}}function markersWhere(equipment,pick){const out=[];equipment.forEach((e,index)=>{const m=e.infusion;if(m&&pick(m))out.push({index,key:m.by,kind:m.kind,item:e.item,seq:m.seq,by:m.by})});return out}var asRows=list=>list.map(({index,key,kind,item})=>({index,key,kind,item}));var storedKeys=v=>typeof v==="string"?[v]:Array.isArray(v)?v:[];function choiceEnds(character,resolved,req){var _a,_b,_c,_d,_e,_f;const pool=((_a=resolved.pools)!=null?_a:[]).find(p=>p.classIndex===req.classIndex&&p.id===req.choiceKey);if(!pool||!(pool.active||pool.selected.some(e=>e.itemBound)))return[];const choices=(_c=(_b=character.class[req.classIndex])==null?void 0:_b.choices)!=null?_c:{};const kept=new Set(req.next.map(markerKey));for(const lvl of Object.keys(choices))if(Number(lvl)!==req.level)for(const s of storedKeys((_d=choices[Number(lvl)])==null?void 0:_d[req.choiceKey]))kept.add(markerKey(s));const removed=new Set(storedKeys((_e=choices[req.level])==null?void 0:_e[req.choiceKey]).map(markerKey).filter(k=>!kept.has(k)));return markersWhere((_f=character.equipment)!=null?_f:[],m=>removed.has(markerKey(m.by)))}function infusionsEndedByChoice(character,resolved,_registry,req){return asRows(choiceEnds(character,resolved,req))}function reconcileChoiceEdit(character,resolved,registry,req){var _a;const list=choiceEnds(character,resolved,req);return list.length===0?null:endBySeqs((_a=character.equipment)!=null?_a:[],list,registry)}function classEnds(character,resolved,req){var _a,_b,_c,_d,_e;let pools=((_a=resolved.pools)!=null?_a:[]).filter(p=>p.classIndex===req.classIndex);if(!("remove"in req)){const old=(_c=(_b=resolved.classes[req.classIndex])==null?void 0:_b.subclass)!=null?_c:null;if(!old||req.subclass!==null&&bareEntitySlug(linkSlug(req.subclass.trim()))===bareEntitySlug(old.slug))return[];const ids=new Set(((_d=old.selection_pools)!=null?_d:[]).map(p=>p.id));pools=pools.filter(p=>ids.has(p.id))}const owned=new Set;for(const pool of pools)for(const e of pool.selected)if(e.itemBound)owned.add(pickKeyOf(e));return markersWhere((_e=character.equipment)!=null?_e:[],m=>owned.has(markerKey(m.by)))}function infusionsEndedByClassEdit(character,resolved,_registry,req){return asRows(classEnds(character,resolved,req))}function reconcileClassEdit(character,resolved,registry,req){var _a;const list=classEnds(character,resolved,req);return list.length===0?null:endBySeqs((_a=character.equipment)!=null?_a:[],list,registry)}function eligibleTargets(character,resolved,registry,key){var _a,_b;const infuse=(_a=ownedPick(resolved,key))==null?void 0:_a.entry.entity.infuse;if(!infuse)return[];const out=[];((_b=character.equipment)!=null?_b:[]).forEach((e,index)=>{var _a2;if(!e.infusion&&targetVerdict(e,infuse,registry)==="ok")out.push({index,stack:((_a2=e.qty)!=null?_a2:1)>1})});return out}var WEAPON_DEFAULT_ACTION_COST="action";var linkOf=item=>{var _a,_b;return(_b=(_a=item.match(/^\[\[(.+)\]\]$/))==null?void 0:_a[1])!=null?_b:null};var ruleOf=(entry,registry,view)=>resolveEntryEntity(entry,view?view.index:-1,registry,view!=null?view:null);function isWeaponLikeEntry(entry,registry,view){if(!registry)return false;const r=ruleOf(entry,registry,view);return defaultSlotForType(r.entityType,r.entity,registry)==="mainhand"}function itemsRowBranch(entry,registry,view){var _a,_b;const link=linkOf(entry.item);if(!link||!registry)return false;const t=view?view.entityType:(_b=(_a=registry.getBySlug(link))==null?void 0:_a.entityType)!=null?_b:null;return t!=="weapon"&&t!=="armor"&&!isWeaponLikeEntry(entry,registry,view)}function customizableOverrideKeys(entry,registry){const consumed=isConsumedOnUse(entry,registry);const keys=new Set(consumed?["name"]:["name","charges","recovery"]);if(!registry)return keys;const r=ruleOf(entry,registry);const slot=defaultSlotForType(r.entityType,r.entity,registry);const weaponLike=slot==="mainhand";const itemsRow=itemsRowBranch(entry,registry);if(weaponLike){keys.add("bonus");keys.add("damage_bonus");keys.add("extra_damage")}if(slot==="armor"||slot==="shield")keys.add("ac_bonus");if(weaponLike||itemsRow)keys.add("action");if(itemsRow)keys.add("range");const link=linkOf(entry.item);if(r.entityType==="item"&&!consumed&&!(link&&isReadOnceItem(link)))keys.add("resist");return keys}function defaultActionCost(entry,registry,view){var _a,_b,_c,_d,_e;if(isWeaponLikeEntry(entry,registry,view))return WEAPON_DEFAULT_ACTION_COST;const link=linkOf(entry.item);if(!link||!registry||!itemsRowBranch(entry,registry,view))return null;const withoutOverrides={...entry,overrides:void 0};const type=view?(_a=view.entity)==null?void 0:_a.type:(_c=(_b=registry.getBySlug(link))==null?void 0:_b.data)==null?void 0:_c.type;return(_e=(_d=resolveItemAction(link,withoutOverrides,type,{view,spellCost:scrollSpellCost(entry,registry)}))==null?void 0:_d.cost)!=null?_e:null}var SPELL_COST={action:"action",bonus:"bonus-action",reaction:"reaction"};function scrollSpellCost(entry,registry){var _a,_b,_c,_d,_e;const ref=(_a=entry.overrides)==null?void 0:_a.spell;if(!ref||!registry)return void 0;const castingTime=(_d=(_c=registry.getByTypeAndSlug("spell",(_b=linkOf(ref))!=null?_b:ref))==null?void 0:_c.data)==null?void 0:_d.casting_time;const kind=typeof castingTime==="string"?(_e=parseCastingTime(castingTime))==null?void 0:_e.kind:void 0;return kind?SPELL_COST[kind]:void 0}var chargesOf=e=>e==null?void 0:e.charges;function itemChargesMax(entity){const c=chargesOf(entity);if(typeof c==="number")return c>0?c:void 0;const m=c==null?void 0:c.max;return typeof m==="number"&&m>0?m:void 0}var RESET_OF=r=>{const s=String(r!=null?r:"").toLowerCase();return s.includes("dawn")?"dawn":s.includes("short")?"short":s.includes("long")?"long":"special"};function rechargeAmount(c){var _a,_b;const raw=[c.recharge_amount,c.dice].find(v=>typeof v==="string"&&v.trim()!=="");if(!raw)return"1";const bare=raw.trim().replace(/^`+|`+$/g,"");return((_b=(_a=parseInlineTag(bare))==null?void 0:_a.content)!=null?_b:bare).replace(/\s+/g,"")}var recoveryOf=(c,needRecharge)=>!c||typeof c==="number"||needRecharge&&(typeof c.recharge!=="string"||c.recharge.trim()==="")?void 0:{amount:rechargeAmount(c),reset:RESET_OF(c.recharge)};function effectiveItemRecovery(entry,registry,view){var _a,_b;if(isConsumedOnUse(entry,registry,view))return void 0;if(view&&view.entity===null)return void 0;if((view==null?void 0:view.kind)==="infused"&&itemChargesMax(view.entity)!==void 0)return recoveryOf(chargesOf(view.entity),false);if((_a=entry.state)==null?void 0:_a.recovery)return entry.state.recovery;const own=registry?recoveryOf(chargesOf(ruleOf(entry,registry,view).entity),true):void 0;if(own)return own;const link=linkOf(entry.item);return link?(_b=findItemAction(link))==null?void 0:_b.recovery:void 0}function isConsumedOnUse(entry,registry,view){var _a;const link=linkOf(entry.item);if(!link)return false;if((_a=findItemAction(link))==null?void 0:_a.consumed)return true;const entity=entityOf(entry,registry,view);return(entity==null?void 0:entity.type)==="potion"||isScrollEntity(entity)}function isScrollEntity(entity){if(!entity||typeof entity!=="object")return false;return entity.type==="scroll"||isCastableScroll(entity)}function isCastableScroll(entity){return settableSpellLevel(entity)!==null&&!storesSpell(entity)}function settableSpellLevel(entity){if(!entity||typeof entity!=="object")return null;const level=entity.scroll_level;return typeof level==="number"?level:null}function storesSpell(entity){if(settableSpellLevel(entity)===null)return false;const e=entity;if(e.type==="scroll")return false;return itemChargesMax(entity)!==void 0||typeof e.spell_charge_cost==="number"}function storedSpellNumbers(entity){if(!storesSpell(entity))return null;const e=entity;const text=[e.description,...Array.isArray(e.entries)?e.entries:[]].filter(t=>typeof t==="string").join("\n");const fromText=re=>{const m=re.exec(text);return m?parseInt(m[1],10):void 0};const saveDC=typeof e.spell_save_dc==="number"?e.spell_save_dc:fromText(/\bsav(?:e|ing throw) DC (?:is|of) (\d+)/i);const attackBonus=typeof e.spell_attack_bonus==="number"?e.spell_attack_bonus:fromText(/\battack bonus (?:is|of) \+?(-?\d+)/i);if(saveDC===void 0&&attackBonus===void 0)return null;return{...saveDC!==void 0?{saveDC}:{},...attackBonus!==void 0?{attackBonus}:{}}}function itemSpellUse(entry,registry,view){const entity=entityOf(entry,registry,view);if(settableSpellLevel(entity)===null)return null;if(isConsumedOnUse(entry,registry,view))return{kind:"consume"};const declared=entity.spell_charge_cost;const cost=typeof declared==="number"&&Number.isInteger(declared)&&declared>=0?declared:1;const charges=effectiveItemCharges(entry,registry,view);if(cost===0||!charges)return{kind:"at-will"};return{kind:"charges",cost,charges:{current:charges.current,max:charges.max}}}function entityOf(entry,registry,view){if(!registry||!linkOf(entry.item))return null;return ruleOf(entry,registry,view).entity}function effectiveItemCharges(entry,registry,view){var _a,_b,_c,_d,_e,_f;if(isConsumedOnUse(entry,registry,view))return void 0;if(view&&view.entity===null)return void 0;const infused=(view==null?void 0:view.kind)==="infused"?itemChargesMax(view.entity):void 0;if(infused!==void 0)return{current:Math.max(0,Math.min((_c=(_b=(_a=entry.infusion)==null?void 0:_a.charges)==null?void 0:_b.current)!=null?_c:infused,infused)),max:infused};const stored=(_d=entry.state)==null?void 0:_d.charges;if(stored)return stored;const own=registry?itemChargesMax(ruleOf(entry,registry,view).entity):void 0;if(own!==void 0)return{current:own,max:own};const link=linkOf(entry.item);const max=link?(_f=(_e=findItemAction(link))==null?void 0:_e.max_charges)!=null?_f:0:0;return max>0?{current:max,max}:void 0}function effectiveItemArmorClass(entry,registry,view){var _a;if(!registry)return null;const{entity}=ruleOf(entry,registry,view);const armor=effectiveArmor(entity,registry);if(!armor)return null;const shield=isShieldArmor(armor);const bonus=isItemEntity(entity)&&typeof((_a=entity.bonuses)==null?void 0:_a.ac)==="number"?entity.bonuses.ac:0;const terms=slotAcTerms(armor,entry);return{value:terms.armor+terms.override+bonus,shield,addDex:!shield&&armor.ac.add_dex===true}}export{WEAPON_DEFAULT_ACTION_COST,isWeaponLikeEntry,customizableOverrideKeys,defaultActionCost,scrollSpellCost,itemChargesMax,effectiveItemRecovery,isConsumedOnUse,isScrollEntity,isCastableScroll,settableSpellLevel,storesSpell,storedSpellNumbers,itemSpellUse,effectiveItemCharges,effectiveItemArmorClass,poolCountLabel,poolActiveWords,parsePickKey,normalizedPickKey,markerKey,isItemBound,optionCandidates,resolveOptionRows,resolveCopyOption,scaledInfuseItem,resolveEntryEntity,buildInfusionContext,entryCharges,withEntryCharges,isMarkedEntry,splitOne,endInfusion,infuseEntry,createEntry,infusionsEndedByChoice,reconcileChoiceEdit,infusionsEndedByClassEdit,reconcileClassEdit,eligibleTargets,bindFeatureConsumers,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolvePool,resolveAllPools,strandedPicks,heldPicks,withoutStrandedSites};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{heldPicks,parsePickKey,poolAnchorLevel}from"./chunk-PKIMOVQG.js";import{featProgressionCategory}from"./chunk-3QQOATV3.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{bucketOf}from"./chunk-QMEKQTUT.js";import{bareEntitySlug,twinKey,wikilinkTailSlug}from"./chunk-63YJPWTM.js";var OPTIONAL_FEATURE_TYPE_CODE={"MV:B":"maneuver",MV:"maneuver",EI:"invocation",MM:"metamagic","FS:F":"fighting_style"};function spellFilter(choose,edition){const where={edition};for(const part of choose.split("|")){const[rawKey,rawValue=""]=part.split("=");const key=rawKey.trim().toLowerCase();const value=rawValue.trim();if(key==="level"){const n=Number(value.split(";")[0]);if(!Number.isInteger(n))return null;where.level=n}else if(key==="class")where.list=value.toLowerCase();else if(key==="components & miscellaneous"&&/ritual/i.test(value))where.ritual=true}return where}function isTargetChoice(ch){return ch.kind==="select-entity"&&ch.target===true}var PACT_WEAPON_CHOICE_ID="pact-weapon";function pactWeaponPick(sites){for(const site of sites){for(const ch of site.choices){if(ch.kind!=="select-entity"||ch.id!==PACT_WEAPON_CHOICE_ID)continue;const v=site.read(ch.id);const first=Array.isArray(v)?v.find(x=>typeof x==="string"&&x.trim()!==""):v;if(typeof first!=="string"||!first.trim())continue;return first.trim().replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].trim()}}return void 0}function classPactWeaponPick(character,classes){var _a,_b,_c,_d,_e,_f,_g;const inBlock=(choices,block)=>{for(const ch of choices!=null?choices:[]){if(ch.kind==="select-inline"){const sel=block[ch.id];const branch=typeof sel==="string"?ch.options.find(o=>o.value===sel):void 0;const hit=inBlock(branch==null?void 0:branch.choices,block);if(hit)return hit}else if(ch.kind==="select-entity"&&ch.id===PACT_WEAPON_CHOICE_ID){const hit=pactWeaponPick([{choices:[ch],read:id=>block[id]}]);if(hit)return hit}}return void 0};for(let i=0;i<classes.length;i++){const entity=(_a=classes[i])==null?void 0:_a.entity;const entry=character.class[i];if(!entity||!entry)continue;for(const[lvl,raw]of Object.entries((_b=entry.choices)!=null?_b:{})){const block=raw!=null?raw:{};const features=[...(_d=((_c=entity.features_by_level)!=null?_c:{})[Number(lvl)])!=null?_d:[],...(_g=((_f=(_e=classes[i].subclass)==null?void 0:_e.features_by_level)!=null?_f:{})[Number(lvl)])!=null?_g:[]];for(const f of features){const hit=inBlock(f.choices,block);if(hit)return hit}}}return void 0}function progressionCount(p){var _a;if(Array.isArray(p))return 0;return(_a=p["*"])!=null?_a:Math.max(0,...Object.values(p))}function spellChoices(entity,used){var _a,_b;const out=[];for(const block of(_a=entity.additional_spells)!=null?_a:[]){for(const bucket of["known","prepared"]){const byLevel=block[bucket];if(!byLevel||typeof byLevel!=="object")continue;for(const rows of Object.values(byLevel)){for(const row of Array.isArray(rows)?rows:[]){const r=row;if(typeof r.choose!=="string")continue;const where=spellFilter(r.choose,entity.edition);if(!where)continue;const base=where.ritual?"rituals":where.level===0?"cantrips":`spells-${(_b=where.level)!=null?_b:"any"}`;const label=where.ritual?"Rituals":where.level===0?"Cantrips":`Level ${where.level} spells`;let id=base;for(let i=2;used.has(id);i++)id=`${base}-${i}`;used.add(id);out.push({kind:"select-entity",id,label,count:typeof r.count==="number"?r.count:1,entity_type:"spell",where})}}}}return out}function memberChoices(entity){var _a,_b,_c,_d,_e,_f;if(!entity)return[];if((_a=entity.choices)==null?void 0:_a.length)return entity.choices;const out=[];const used=new Set;for(const fp of(_b=entity.feat_progression)!=null?_b:[]){const category=featProgressionCategory(fp.category);const count=progressionCount(fp.progression);if(!category||count<1)continue;const id=used.has("feat")?`feat-${used.size}`:"feat";used.add(id);out.push({kind:"select-entity",id,label:fp.name,count,entity_type:"feat",where:{category,edition:entity.edition}})}for(const op of(_c=entity.optionalfeature_progression)!=null?_c:[]){const codes=(_e=(_d=op.feature_type)!=null?_d:op.featureType)!=null?_e:[];const featureType=codes.map(c=>OPTIONAL_FEATURE_TYPE_CODE[c]).find(t=>!!t);const count=progressionCount(op.progression);if(!featureType||count<1){if(!featureType)warnOnce(`member-of-code:${entity.slug}`,`Archivist: "${entity.slug}" asks for optional features of type ${codes.join(", ")}, which this engine does not map; no pick is offered`);continue}const id=op.name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"option";used.add(id);out.push({kind:"select-entity",id,label:op.name,count,entity_type:"optional-feature",where:{feature_type:featureType,edition:entity.edition}})}out.push(...spellChoices(entity,used));for(const pre of(_f=entity.prerequisites)!=null?_f:[]){if(pre.kind!=="spell-choose")continue;const where=spellFilter(pre.choose,entity.edition);if(!where||used.has("cantrip"))continue;used.add("cantrip");out.push({kind:"select-entity",id:"cantrip",label:where.level===0?"Cantrip":"Spell",count:1,entity_type:"spell",where,target:true})}return out}function memberSpellTargets(member,read){var _a;const refs=[];const open=[];for(const ch of memberChoices(member)){if(ch.kind!=="select-entity"||!isTargetChoice(ch)||ch.entity_type!=="spell")continue;const v=read(ch.id);const picked=(Array.isArray(v)?v:[v]).filter(x=>typeof x==="string"&&x.trim()!=="");if(picked.length)refs.push(...picked);else if(ch.where)open.push(ch.where)}for(const pre of(_a=member.prerequisites)!=null?_a:[])if(pre.kind==="spell-known")refs.push(pre.spell);return refs.length||open.length?{refs,open}:null}function spellMatchesFilter(d,where){var _a,_b;if(where.list&&!((_a=d.classes)!=null?_a:[]).includes(where.list))return false;if(where.level!==void 0&&((_b=d.level)!=null?_b:0)!==where.level)return false;if(where.edition&&d.edition!==where.edition)return false;if(where.ritual&&d.ritual!==true)return false;return true}function spellsReached(targets,spells){if(!targets)return[];const hit=new Set;for(const ref of targets.refs){const full=stripRef(ref);const exact=spells.filter(s=>s.slug===full);const bare=wikilinkTailSlug(ref);for(const s of exact.length?exact:spells.filter(s2=>bareEntitySlug(s2.slug)===bare))hit.add(s.slug)}for(const where of targets.open){const legal=new Set(spells.filter(s=>{var _a;return spellMatchesFilter(s.entity,where)&&!!((_a=s.entity.damage_roll)==null?void 0:_a.trim())}).map(s=>s.slug));if(legal.size===1)hit.add([...legal][0])}return[...new Set(spells.map(s=>s.slug))].filter(slug=>hit.has(slug))}function siteOf(classIndex,level,poolId,pickKey,member,memberSlug,block){const choices=memberChoices(member);if(!choices.length)return null;const prefix=`${poolId}:${pickKey}:`;return{classIndex,level,poolId,pickKey,member,memberSlug,choices,prefix,block,read:id=>block[`${prefix}${id}`]}}function poolMemberSites(classes,registry){const out=[];let byBare=null;let all=null;const lookup=(s,ownerPrefix)=>{all!=null?all:all=bucketOf(registry,"optional-feature");const bare=bareEntitySlug(s);const twin=twinKey(s);const owned=all.find(e=>twinKey(e.slug)===twin&&e.slug.split("_")[0]===ownerPrefix);if(owned)return owned;const direct=registry.getByTypeAndSlug("optional-feature",s);if(direct)return direct;byBare!=null?byBare:byBare=new Map(all.map(e=>[bareEntitySlug(e.slug),e]));return byBare.get(bare)};classes.forEach((rc,classIndex)=>{var _a,_b,_c,_d,_e;if(!rc.entity)return;const seen=new Set;for(const pool of[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]]){if(seen.has(pool.id))continue;seen.add(pool.id);const{anchorLevel}=poolAnchorLevel(rc.entity,pool);const block=(_e=(_d=rc.choices)==null?void 0:_d[anchorLevel])!=null?_e:{};const raw=block[pool.id];const picks=Array.isArray(raw)?raw:typeof raw==="string"?[raw]:[];for(const s of picks){if(typeof s!=="string")continue;const{slugPart,param}=parsePickKey(s);const reg=lookup(slugPart,rc.entity.slug.split("_")[0]);if(!reg)continue;const member=reg.data;const key=member.repeatable===true||param!==null?s:reg.slug;const site=siteOf(classIndex,anchorLevel,pool.id,key,member,reg.slug,block);if(site)out.push(site)}}});return out}function poolMemberSitesOf(resolved){var _a,_b,_c,_d,_e;const out=[];for(const pool of(_a=resolved.pools)!=null?_a:[]){const block=(_e=(_d=(_c=(_b=resolved.classes)==null?void 0:_b[pool.classIndex])==null?void 0:_c.choices)==null?void 0:_d[pool.anchorLevel])!=null?_e:{};for(const e of heldPicks(pool)){const site=siteOf(pool.classIndex,pool.anchorLevel,pool.id,e.key,e.entity,e.slug,block);if(site)out.push(site)}}return out}var stripRef=ref=>ref.replace(/^\[\[/,"").replace(/\]\]$/,"");function featPickSites(classEntries,memberSites,classSlugOf){const out=[];(classEntries!=null?classEntries:[]).forEach((c,classIndex)=>{var _a;for(const[lvl,choiceBlock]of Object.entries((_a=c.choices)!=null?_a:{})){const block=choiceBlock;const feat=block==null?void 0:block.feat;if(!block||typeof feat!=="string")continue;const slug=stripRef(feat);if(!slug)continue;const level=/^\d+$/.test(lvl)?Number(lvl):null;const cls=classSlugOf(classIndex);out.push({slug,classIndex,level,via:cls&&level!==null?{kind:"class",slug:cls,level}:null,read:id=>block[`feat:${id}`]})}});for(const site of memberSites){for(const ch of site.choices){if(ch.kind!=="select-entity"||ch.entity_type!=="feat"||ch.target===true)continue;const v=site.read(ch.id);for(const ref of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof ref!=="string")continue;const slug=stripRef(ref);if(!slug)continue;const cls=classSlugOf(site.classIndex);out.push({slug,classIndex:site.classIndex,level:site.level,via:cls?{kind:"pool",slug:site.memberSlug,name:site.member.name,classSlug:cls,level:site.level}:null,read:id=>site.block[`${site.prefix}feat:${id}`]})}}}return out}function raceFeatSites(race,originChoices){var _a;if(!race)return[];const oc=originChoices!=null?originChoices:{};const out=[];for(const list of[race.choices,...((_a=race.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)]){for(const ch of Array.isArray(list)?list:[]){if((ch==null?void 0:ch.kind)!=="select-entity"||ch.entity_type!=="feat")continue;const v=oc[`race:${ch.id}`];for(const ref of Array.isArray(v)?v:typeof v==="string"?[v]:[]){const slug=typeof ref==="string"?stripRef(ref):"";if(slug)out.push({slug,via:{kind:"race",slug:race.slug},read:id=>oc[`race:feat:${id}`]})}}}return out}function featOfSite(site,feats){var _a;return(_a=feats.find(f=>f.slug===site.slug))!=null?_a:feats.find(f=>bareEntitySlug(f.slug)===bareEntitySlug(site.slug))}function nestedPickKeysToPrune(block,key,next){const prev=block==null?void 0:block[key];if(!block||!Array.isArray(prev))return[];const keep=new Set(next);const gone=prev.filter(k=>typeof k==="string"&&!keep.has(k));if(!gone.length)return[];return Object.keys(block).filter(k=>gone.some(g=>k.startsWith(`${key}:${g}:`)))}export{isTargetChoice,PACT_WEAPON_CHOICE_ID,pactWeaponPick,classPactWeaponPick,memberChoices,memberSpellTargets,spellsReached,poolMemberSites,poolMemberSitesOf,featPickSites,raceFeatSites,featOfSite,nestedPickKeysToPrune};
|
|
1
|
+
import{heldPicks,parsePickKey,poolAnchorLevel}from"./chunk-E4E6YEN6.js";import{featProgressionCategory}from"./chunk-3QQOATV3.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{bucketOf}from"./chunk-QMEKQTUT.js";import{bareEntitySlug,twinKey,wikilinkTailSlug}from"./chunk-63YJPWTM.js";var OPTIONAL_FEATURE_TYPE_CODE={"MV:B":"maneuver",MV:"maneuver",EI:"invocation",MM:"metamagic","FS:F":"fighting_style"};function spellFilter(choose,edition){const where={edition};for(const part of choose.split("|")){const[rawKey,rawValue=""]=part.split("=");const key=rawKey.trim().toLowerCase();const value=rawValue.trim();if(key==="level"){const n=Number(value.split(";")[0]);if(!Number.isInteger(n))return null;where.level=n}else if(key==="class")where.list=value.toLowerCase();else if(key==="components & miscellaneous"&&/ritual/i.test(value))where.ritual=true}return where}function isTargetChoice(ch){return ch.kind==="select-entity"&&ch.target===true}var PACT_WEAPON_CHOICE_ID="pact-weapon";function pactWeaponPick(sites){for(const site of sites){for(const ch of site.choices){if(ch.kind!=="select-entity"||ch.id!==PACT_WEAPON_CHOICE_ID)continue;const v=site.read(ch.id);const first=Array.isArray(v)?v.find(x=>typeof x==="string"&&x.trim()!==""):v;if(typeof first!=="string"||!first.trim())continue;return first.trim().replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].trim()}}return void 0}function classPactWeaponPick(character,classes){var _a,_b,_c,_d,_e,_f,_g;const inBlock=(choices,block)=>{for(const ch of choices!=null?choices:[]){if(ch.kind==="select-inline"){const sel=block[ch.id];const branch=typeof sel==="string"?ch.options.find(o=>o.value===sel):void 0;const hit=inBlock(branch==null?void 0:branch.choices,block);if(hit)return hit}else if(ch.kind==="select-entity"&&ch.id===PACT_WEAPON_CHOICE_ID){const hit=pactWeaponPick([{choices:[ch],read:id=>block[id]}]);if(hit)return hit}}return void 0};for(let i=0;i<classes.length;i++){const entity=(_a=classes[i])==null?void 0:_a.entity;const entry=character.class[i];if(!entity||!entry)continue;for(const[lvl,raw]of Object.entries((_b=entry.choices)!=null?_b:{})){const block=raw!=null?raw:{};const features=[...(_d=((_c=entity.features_by_level)!=null?_c:{})[Number(lvl)])!=null?_d:[],...(_g=((_f=(_e=classes[i].subclass)==null?void 0:_e.features_by_level)!=null?_f:{})[Number(lvl)])!=null?_g:[]];for(const f of features){const hit=inBlock(f.choices,block);if(hit)return hit}}}return void 0}function progressionCount(p){var _a;if(Array.isArray(p))return 0;return(_a=p["*"])!=null?_a:Math.max(0,...Object.values(p))}function spellChoices(entity,used){var _a,_b;const out=[];for(const block of(_a=entity.additional_spells)!=null?_a:[]){for(const bucket of["known","prepared"]){const byLevel=block[bucket];if(!byLevel||typeof byLevel!=="object")continue;for(const rows of Object.values(byLevel)){for(const row of Array.isArray(rows)?rows:[]){const r=row;if(typeof r.choose!=="string")continue;const where=spellFilter(r.choose,entity.edition);if(!where)continue;const base=where.ritual?"rituals":where.level===0?"cantrips":`spells-${(_b=where.level)!=null?_b:"any"}`;const label=where.ritual?"Rituals":where.level===0?"Cantrips":`Level ${where.level} spells`;let id=base;for(let i=2;used.has(id);i++)id=`${base}-${i}`;used.add(id);out.push({kind:"select-entity",id,label,count:typeof r.count==="number"?r.count:1,entity_type:"spell",where})}}}}return out}function memberChoices(entity){var _a,_b,_c,_d,_e,_f;if(!entity)return[];if((_a=entity.choices)==null?void 0:_a.length)return entity.choices;const out=[];const used=new Set;for(const fp of(_b=entity.feat_progression)!=null?_b:[]){const category=featProgressionCategory(fp.category);const count=progressionCount(fp.progression);if(!category||count<1)continue;const id=used.has("feat")?`feat-${used.size}`:"feat";used.add(id);out.push({kind:"select-entity",id,label:fp.name,count,entity_type:"feat",where:{category,edition:entity.edition}})}for(const op of(_c=entity.optionalfeature_progression)!=null?_c:[]){const codes=(_e=(_d=op.feature_type)!=null?_d:op.featureType)!=null?_e:[];const featureType=codes.map(c=>OPTIONAL_FEATURE_TYPE_CODE[c]).find(t=>!!t);const count=progressionCount(op.progression);if(!featureType||count<1){if(!featureType)warnOnce(`member-of-code:${entity.slug}`,`Archivist: "${entity.slug}" asks for optional features of type ${codes.join(", ")}, which this engine does not map; no pick is offered`);continue}const id=op.name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"option";used.add(id);out.push({kind:"select-entity",id,label:op.name,count,entity_type:"optional-feature",where:{feature_type:featureType,edition:entity.edition}})}out.push(...spellChoices(entity,used));for(const pre of(_f=entity.prerequisites)!=null?_f:[]){if(pre.kind!=="spell-choose")continue;const where=spellFilter(pre.choose,entity.edition);if(!where||used.has("cantrip"))continue;used.add("cantrip");out.push({kind:"select-entity",id:"cantrip",label:where.level===0?"Cantrip":"Spell",count:1,entity_type:"spell",where,target:true})}return out}function memberSpellTargets(member,read){var _a;const refs=[];const open=[];for(const ch of memberChoices(member)){if(ch.kind!=="select-entity"||!isTargetChoice(ch)||ch.entity_type!=="spell")continue;const v=read(ch.id);const picked=(Array.isArray(v)?v:[v]).filter(x=>typeof x==="string"&&x.trim()!=="");if(picked.length)refs.push(...picked);else if(ch.where)open.push(ch.where)}for(const pre of(_a=member.prerequisites)!=null?_a:[])if(pre.kind==="spell-known")refs.push(pre.spell);return refs.length||open.length?{refs,open}:null}function spellMatchesFilter(d,where){var _a,_b;if(where.list&&!((_a=d.classes)!=null?_a:[]).includes(where.list))return false;if(where.level!==void 0&&((_b=d.level)!=null?_b:0)!==where.level)return false;if(where.edition&&d.edition!==where.edition)return false;if(where.ritual&&d.ritual!==true)return false;return true}function spellsReached(targets,spells){if(!targets)return[];const hit=new Set;for(const ref of targets.refs){const full=stripRef(ref);const exact=spells.filter(s=>s.slug===full);const bare=wikilinkTailSlug(ref);for(const s of exact.length?exact:spells.filter(s2=>bareEntitySlug(s2.slug)===bare))hit.add(s.slug)}for(const where of targets.open){const legal=new Set(spells.filter(s=>{var _a;return spellMatchesFilter(s.entity,where)&&!!((_a=s.entity.damage_roll)==null?void 0:_a.trim())}).map(s=>s.slug));if(legal.size===1)hit.add([...legal][0])}return[...new Set(spells.map(s=>s.slug))].filter(slug=>hit.has(slug))}function siteOf(classIndex,level,poolId,pickKey,member,memberSlug,block){const choices=memberChoices(member);if(!choices.length)return null;const prefix=`${poolId}:${pickKey}:`;return{classIndex,level,poolId,pickKey,member,memberSlug,choices,prefix,block,read:id=>block[`${prefix}${id}`]}}function poolMemberSites(classes,registry){const out=[];let byBare=null;let all=null;const lookup=(s,ownerPrefix)=>{all!=null?all:all=bucketOf(registry,"optional-feature");const bare=bareEntitySlug(s);const twin=twinKey(s);const owned=all.find(e=>twinKey(e.slug)===twin&&e.slug.split("_")[0]===ownerPrefix);if(owned)return owned;const direct=registry.getByTypeAndSlug("optional-feature",s);if(direct)return direct;byBare!=null?byBare:byBare=new Map(all.map(e=>[bareEntitySlug(e.slug),e]));return byBare.get(bare)};classes.forEach((rc,classIndex)=>{var _a,_b,_c,_d,_e;if(!rc.entity)return;const seen=new Set;for(const pool of[...(_a=rc.entity.selection_pools)!=null?_a:[],...(_c=(_b=rc.subclass)==null?void 0:_b.selection_pools)!=null?_c:[]]){if(seen.has(pool.id))continue;seen.add(pool.id);const{anchorLevel}=poolAnchorLevel(rc.entity,pool);const block=(_e=(_d=rc.choices)==null?void 0:_d[anchorLevel])!=null?_e:{};const raw=block[pool.id];const picks=Array.isArray(raw)?raw:typeof raw==="string"?[raw]:[];for(const s of picks){if(typeof s!=="string")continue;const{slugPart,param}=parsePickKey(s);const reg=lookup(slugPart,rc.entity.slug.split("_")[0]);if(!reg)continue;const member=reg.data;const key=member.repeatable===true||param!==null?s:reg.slug;const site=siteOf(classIndex,anchorLevel,pool.id,key,member,reg.slug,block);if(site)out.push(site)}}});return out}function poolMemberSitesOf(resolved){var _a,_b,_c,_d,_e;const out=[];for(const pool of(_a=resolved.pools)!=null?_a:[]){const block=(_e=(_d=(_c=(_b=resolved.classes)==null?void 0:_b[pool.classIndex])==null?void 0:_c.choices)==null?void 0:_d[pool.anchorLevel])!=null?_e:{};for(const e of heldPicks(pool)){const site=siteOf(pool.classIndex,pool.anchorLevel,pool.id,e.key,e.entity,e.slug,block);if(site)out.push(site)}}return out}var stripRef=ref=>ref.replace(/^\[\[/,"").replace(/\]\]$/,"");function featPickSites(classEntries,memberSites,classSlugOf){const out=[];(classEntries!=null?classEntries:[]).forEach((c,classIndex)=>{var _a;for(const[lvl,choiceBlock]of Object.entries((_a=c.choices)!=null?_a:{})){const block=choiceBlock;const feat=block==null?void 0:block.feat;if(!block||typeof feat!=="string")continue;const slug=stripRef(feat);if(!slug)continue;const level=/^\d+$/.test(lvl)?Number(lvl):null;const cls=classSlugOf(classIndex);out.push({slug,classIndex,level,via:cls&&level!==null?{kind:"class",slug:cls,level}:null,read:id=>block[`feat:${id}`]})}});for(const site of memberSites){for(const ch of site.choices){if(ch.kind!=="select-entity"||ch.entity_type!=="feat"||ch.target===true)continue;const v=site.read(ch.id);for(const ref of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof ref!=="string")continue;const slug=stripRef(ref);if(!slug)continue;const cls=classSlugOf(site.classIndex);out.push({slug,classIndex:site.classIndex,level:site.level,via:cls?{kind:"pool",slug:site.memberSlug,name:site.member.name,classSlug:cls,level:site.level}:null,read:id=>site.block[`${site.prefix}feat:${id}`]})}}}return out}function raceFeatSites(race,originChoices){var _a;if(!race)return[];const oc=originChoices!=null?originChoices:{};const out=[];for(const list of[race.choices,...((_a=race.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)]){for(const ch of Array.isArray(list)?list:[]){if((ch==null?void 0:ch.kind)!=="select-entity"||ch.entity_type!=="feat")continue;const v=oc[`race:${ch.id}`];for(const ref of Array.isArray(v)?v:typeof v==="string"?[v]:[]){const slug=typeof ref==="string"?stripRef(ref):"";if(slug)out.push({slug,via:{kind:"race",slug:race.slug},read:id=>oc[`race:feat:${id}`]})}}}return out}function featOfSite(site,feats){var _a;return(_a=feats.find(f=>f.slug===site.slug))!=null?_a:feats.find(f=>bareEntitySlug(f.slug)===bareEntitySlug(site.slug))}function nestedPickKeysToPrune(block,key,next){const prev=block==null?void 0:block[key];if(!block||!Array.isArray(prev))return[];const keep=new Set(next);const gone=prev.filter(k=>typeof k==="string"&&!keep.has(k));if(!gone.length)return[];return Object.keys(block).filter(k=>gone.some(g=>k.startsWith(`${key}:${g}:`)))}export{isTargetChoice,PACT_WEAPON_CHOICE_ID,pactWeaponPick,classPactWeaponPick,memberChoices,memberSpellTargets,spellsReached,poolMemberSites,poolMemberSitesOf,featPickSites,raceFeatSites,featOfSite,nestedPickKeysToPrune};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{subclassEntitySchema}from"./chunk-
|
|
1
|
+
import{subclassEntitySchema}from"./chunk-NU6WP4P5.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};
|