@archivist-gg/dnd5e 0.3.29 → 0.3.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/background/background.codec.js +1 -1
  2. package/dist/background/background.parser.js +1 -1
  3. package/dist/background/background.schema.js +1 -1
  4. package/dist/chunk-34ZLX4TM.js +1 -0
  5. package/dist/{chunk-WXL7ABDO.js → chunk-3CHDDX6S.js} +1 -1
  6. package/dist/chunk-4F5F5A3X.js +1 -0
  7. package/dist/{chunk-OV4FG4KO.js → chunk-5NGQM3TO.js} +1 -1
  8. package/dist/{chunk-ADX7435T.js → chunk-655UY3MP.js} +1 -1
  9. package/dist/{chunk-IR5BA2DZ.js → chunk-65VM2BAA.js} +1 -1
  10. package/dist/{chunk-5QDSAZG6.js → chunk-6GFBSYE3.js} +1 -1
  11. package/dist/{chunk-J27N3KUE.js → chunk-6WRU5I75.js} +1 -1
  12. package/dist/{chunk-YWKC2LJY.js → chunk-73HBCVPD.js} +1 -1
  13. package/dist/{chunk-E4E6YEN6.js → chunk-7S4VMK3R.js} +1 -1
  14. package/dist/{chunk-EON7T2SN.js → chunk-7TH4WPSU.js} +1 -1
  15. package/dist/{chunk-EBFLUJIW.js → chunk-A25HLCQ7.js} +1 -1
  16. package/dist/{chunk-M2UA2FAK.js → chunk-FC4OPNZM.js} +1 -1
  17. package/dist/{chunk-7HOOPNF5.js → chunk-FDWQ6P7Z.js} +1 -1
  18. package/dist/{chunk-RR26E7LH.js → chunk-HI2BXTGB.js} +1 -1
  19. package/dist/{chunk-J6FIBUI4.js → chunk-HPBEMAM6.js} +1 -1
  20. package/dist/{chunk-NB4QWMF5.js → chunk-I6J6ZGZB.js} +1 -1
  21. package/dist/{chunk-GKNOCYDT.js → chunk-IK7XM6BW.js} +1 -1
  22. package/dist/{chunk-XFFFTR6O.js → chunk-IOFGBEGA.js} +1 -1
  23. package/dist/{chunk-U7BPRRY5.js → chunk-JLW7XFFL.js} +1 -1
  24. package/dist/{chunk-XCF5R5XX.js → chunk-JOLGJYDS.js} +1 -1
  25. package/dist/{chunk-NU6WP4P5.js → chunk-KGRRQ4US.js} +1 -1
  26. package/dist/chunk-KWETUSIQ.js +1 -0
  27. package/dist/chunk-LXISMSPG.js +1 -0
  28. package/dist/{chunk-2OVDSMPY.js → chunk-MJJQQI44.js} +1 -1
  29. package/dist/{chunk-D2BXAFOL.js → chunk-Q2U7MWMC.js} +1 -1
  30. package/dist/{chunk-AFEWQFQZ.js → chunk-QCCA46KM.js} +1 -1
  31. package/dist/{chunk-C4T6BUSP.js → chunk-RI4YYU75.js} +1 -1
  32. package/dist/{chunk-R2YRQM7G.js → chunk-TGZ6WQUX.js} +1 -1
  33. package/dist/{chunk-PFQPP77Q.js → chunk-YDN6GD2B.js} +1 -1
  34. package/dist/{chunk-VY5ZEOLG.js → chunk-Z362RQTB.js} +1 -1
  35. package/dist/{chunk-VHIE2KYQ.js → chunk-ZK3P4RSE.js} +1 -1
  36. package/dist/{chunk-CCFIINBA.js → chunk-ZKDHCDJ2.js} +1 -1
  37. package/dist/{chunk-DXJ5NKKB.js → chunk-ZYMWQ7PG.js} +1 -1
  38. package/dist/{chunk-KGZXAAFN.js → chunk-ZZ6QHLWX.js} +1 -1
  39. package/dist/class/class.codec.js +1 -1
  40. package/dist/class/class.parser.js +1 -1
  41. package/dist/class/class.schema.js +1 -1
  42. package/dist/class/class.slug.d.ts +1 -0
  43. package/dist/class/class.slug.js +1 -1
  44. package/dist/feat/feat.codec.js +1 -1
  45. package/dist/feat/feat.parser.js +1 -1
  46. package/dist/feat/feat.schema.d.ts +12 -0
  47. package/dist/feat/feat.schema.js +1 -1
  48. package/dist/index.js +17 -13
  49. package/dist/monster/monster.parser.js +1 -1
  50. package/dist/monster/monster.schema.js +1 -1
  51. package/dist/optional-feature/optional-feature.codec.js +1 -1
  52. package/dist/optional-feature/optional-feature.parser.js +1 -1
  53. package/dist/optional-feature/optional-feature.schema.d.ts +13 -0
  54. package/dist/optional-feature/optional-feature.schema.js +1 -1
  55. package/dist/pc/pc.additional-spells.js +1 -1
  56. package/dist/pc/pc.amount-bindings.d.ts +1 -0
  57. package/dist/pc/pc.amount-bindings.js +1 -1
  58. package/dist/pc/pc.decision-engine.js +1 -1
  59. package/dist/pc/pc.entry-overrides.js +1 -1
  60. package/dist/pc/pc.equipment.js +1 -1
  61. package/dist/pc/pc.feature-effects.d.ts +18 -0
  62. package/dist/pc/pc.feature-effects.js +1 -1
  63. package/dist/pc/pc.granted-spends.d.ts +2 -0
  64. package/dist/pc/pc.infusions.js +1 -1
  65. package/dist/pc/pc.item-effects.js +1 -1
  66. package/dist/pc/pc.member-choices.js +1 -1
  67. package/dist/pc/pc.pools.js +1 -1
  68. package/dist/pc/pc.proficiencies.js +1 -1
  69. package/dist/pc/pc.recalc.js +1 -1
  70. package/dist/pc/pc.resolver.js +1 -1
  71. package/dist/pc/pc.resource-seed.js +1 -1
  72. package/dist/pc/pc.resources.js +1 -1
  73. package/dist/pc/pc.rest.js +1 -1
  74. package/dist/pc/pc.schema.d.ts +1 -1
  75. package/dist/pc/pc.spellcasting.js +1 -1
  76. package/dist/pc/pc.types.d.ts +25 -0
  77. package/dist/race/race.codec.js +1 -1
  78. package/dist/race/race.parser.js +1 -1
  79. package/dist/race/race.schema.js +1 -1
  80. package/dist/schemas/choice-schema.js +1 -1
  81. package/dist/schemas/feature-effect-schema.d.ts +12 -0
  82. package/dist/schemas/feature-effect-schema.js +1 -1
  83. package/dist/schemas/feature-schema.js +1 -1
  84. package/dist/schemas/resource-schema.d.ts +1 -0
  85. package/dist/schemas/resource-schema.js +1 -1
  86. package/dist/spell/spell.access.js +1 -1
  87. package/dist/subclass/subclass.codec.js +1 -1
  88. package/dist/subclass/subclass.parser.js +1 -1
  89. package/dist/subclass/subclass.schema.js +1 -1
  90. package/dist/types/feature-effect.d.ts +10 -0
  91. package/dist/types/resource.d.ts +1 -0
  92. package/package.json +1 -1
  93. package/dist/chunk-53SHSS4M.js +0 -1
  94. package/dist/chunk-B2JSF2LL.js +0 -1
  95. package/dist/chunk-CAPYNIGK.js +0 -1
  96. package/dist/chunk-JSI2G6LE.js +0 -1
@@ -1 +1 @@
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&&param!==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&&param!==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,classOfSource,bindFeatureConsumers,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolvePool,resolveAllPools,strandedPicks,heldPicks,withoutStrandedSites};
@@ -1 +1 @@
1
- import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var subjectField=z.string().min(1).optional();var conditionField=z.string().optional();var weaponScopeEnum=z.enum(["weapon","melee","ranged","unarmed","finesse","thrown","heavy","pact-weapon"]);var speedGateEnum=z.enum(["heavy-armor","armor","shield"]);var spellScopeSchema=z.object({list:z.string().min(1).optional(),level:z.number().int().min(0).max(9).optional(),school:z.string().min(1).optional(),damage_types:z.array(z.string().min(1)).min(1).optional(),damage_type_pick:z.string().min(1).optional(),spells:z.array(z.string().min(1)).min(1).optional(),once:z.boolean().optional()}).strict();var featureEffectSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("initiative-bonus"),value:z.number().int().optional(),amount:z.string().min(1).optional(),condition:conditionField,subject:subjectField}).refine(e=>e.value===void 0!==(e.amount===void 0),{path:["value"],message:"initiative-bonus takes exactly one of `value` (a number) or `amount` (a formula)"}),z.object({kind:z.literal("skill-bonus"),skills:z.array(z.string().min(1)).nonempty(),ability:abilityEnum,minimum:z.number().int().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("save-bonus"),ability:abilityEnum,minimum:z.number().int().optional(),saves:z.array(abilityEnum).nonempty().optional(),inactive_while:z.enum(["incapacitated","unconscious"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("half-proficiency"),skills:z.array(z.string().min(1)).nonempty().optional(),round:z.enum(["down","up"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("immune-condition"),condition:z.string().min(1),while:z.string().optional(),subject:subjectField}),z.object({kind:z.literal("resistance"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("hp-per-level-bonus"),value:z.number().int(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("speed-bonus"),mode:z.enum(["walk","fly","swim","climb","burrow"]),value:z.number().int().optional(),equal_to:z.literal("walk").optional(),set:z.boolean().optional(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),value:z.number().int()})).optional(),inactive_while:z.union([speedGateEnum,z.array(speedGateEnum).nonempty()]).optional(),condition:conditionField,subject:subjectField}).refine(e=>e.value===void 0!==(e.equal_to===void 0),{path:["value"],message:"speed-bonus takes exactly one of `value` (feet) or `equal_to: walk`"}).refine(e=>e.equal_to===void 0||e.mode!=="walk"&&e.set===void 0&&e.scales_at===void 0,{path:["equal_to"],message:"`equal_to: walk` grants a mode other than walk, never with `set` or `scales_at`"}),z.object({kind:z.literal("speed-rule"),flag:z.enum(["ignore-armor-strength"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("attunement-limit"),value:z.number().int().positive(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),value:z.number().int().positive()})).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("sense"),type:z.enum(["darkvision","blindsight","tremorsense","truesight"]),range:z.number().int().nonnegative(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("apply-condition"),condition:z.string().min(1),duration:z.string().optional(),ends_on:z.array(z.string()).optional(),save_repeat:z.object({ability:z.string().min(1),timing:z.string().min(1)}).optional(),subject:subjectField}),z.object({kind:z.literal("damage-bonus"),damage_type:z.string().min(1),amount:z.string().min(1),applies_to:z.union([z.enum(["spell","all"]),weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),spell_scope:spellScopeSchema.optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["skill","tool","language","saving-throw","armor","weapon"]),value:z.string().min(1),expertise:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("ac-bonus"),value:z.number().int(),requires_armor:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("unarmored-ac"),abilities:z.array(abilityEnum),base:z.number().int().optional(),allow_shield:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("unarmed-strike"),dice:z.union([z.string().regex(/^\d+d\d+$/i),z.object({column:z.string().min(1)})]).optional(),abilities:z.array(abilityEnum).nonempty().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("weapon-ability"),ability:z.union([abilityEnum,z.literal("spellcasting")]),weapons:z.union([z.literal("chosen"),z.string(),z.array(z.string())]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("roll-modifier"),mode:z.enum(["advantage","disadvantage","reroll","add-d4"]),roll:z.enum(["ability-check","saving-throw","attack","any"]),scope:z.string().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("extra-attack"),count:z.number().int().positive(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),count:z.number().int().positive()})).optional(),applies_to:z.union([weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("crit-range"),min_roll:z.number().int().min(2).max(20),applies_to:z.enum(["weapon","spell","all"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("reroll-damage"),max_reroll:z.number().int().positive(),applies_to:z.enum(["weapon","spell","all"]).optional(),once_per_die:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("attack-rule"),flag:z.enum(["no-ranged-in-melee-disadvantage"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("damage-roll-option"),mode:z.enum(["reroll-weapon-dice-keep-higher","min-die-face","reroll-below"]),value:z.number().int().min(2).optional(),applies_to:z.union([weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),two_handed:z.boolean().optional(),once_per_turn:z.boolean().optional(),condition:conditionField,subject:subjectField}).refine(e=>e.mode==="reroll-weapon-dice-keep-higher"===(e.value===void 0),{path:["value"],message:"damage-roll-option: `min-die-face` and `reroll-below` take a `value` (the face); keep-higher takes none"}),z.object({kind:z.literal("immunity"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("vulnerability"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("temp-hp"),amount:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("heal"),amount:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("ability-score-increase"),abilities:z.union([z.literal("chosen"),z.array(abilityEnum).min(1)]),amount:z.number().int().positive(),choose:z.number().int().positive().nullable(),max:z.number().int().positive().nullable(),condition:conditionField,subject:subjectField}).refine(e=>e.abilities==="chosen"===(e.choose!==null),{path:["choose"],message:'choose is required IFF abilities is "chosen": a fixed LIST is its own count'}),z.object({kind:z.literal("extra-action"),count:z.number().int().positive(),action_type:z.enum(["action","bonus-action","reaction"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("save-outcome"),ability:z.union([abilityEnum,z.literal("any")]),on_success:z.enum(["none","half","full"]),on_failure:z.enum(["none","half","full"]),applies_to:z.string().nullable(),condition:conditionField,subject:subjectField})]);export{featureEffectSchema};
1
+ import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var subjectField=z.string().min(1).optional();var conditionField=z.string().optional();var weaponScopeEnum=z.enum(["weapon","melee","ranged","unarmed","finesse","thrown","heavy","pact-weapon"]);var speedGateEnum=z.enum(["heavy-armor","armor","shield"]);var spellScopeSchema=z.object({list:z.string().min(1).optional(),level:z.number().int().min(0).max(9).optional(),school:z.string().min(1).optional(),damage_types:z.array(z.string().min(1)).min(1).optional(),damage_type_pick:z.string().min(1).optional(),spells:z.array(z.string().min(1)).min(1).optional(),once:z.boolean().optional()}).strict();var featureEffectSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("initiative-bonus"),value:z.number().int().optional(),amount:z.string().min(1).optional(),condition:conditionField,subject:subjectField}).refine(e=>e.value===void 0!==(e.amount===void 0),{path:["value"],message:"initiative-bonus takes exactly one of `value` (a number) or `amount` (a formula)"}),z.object({kind:z.literal("skill-bonus"),skills:z.array(z.string().min(1)).nonempty(),ability:abilityEnum,minimum:z.number().int().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("save-bonus"),ability:abilityEnum,minimum:z.number().int().optional(),saves:z.array(abilityEnum).nonempty().optional(),inactive_while:z.enum(["incapacitated","unconscious"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("half-proficiency"),skills:z.array(z.string().min(1)).nonempty().optional(),round:z.enum(["down","up"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("immune-condition"),condition:z.string().min(1),while:z.string().optional(),subject:subjectField}),z.object({kind:z.literal("resistance"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("hp-per-level-bonus"),value:z.number().int(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("speed-bonus"),mode:z.enum(["walk","fly","swim","climb","burrow"]),value:z.number().int().optional(),equal_to:z.literal("walk").optional(),set:z.boolean().optional(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),value:z.number().int()})).optional(),inactive_while:z.union([speedGateEnum,z.array(speedGateEnum).nonempty()]).optional(),condition:conditionField,subject:subjectField}).refine(e=>e.value===void 0!==(e.equal_to===void 0),{path:["value"],message:"speed-bonus takes exactly one of `value` (feet) or `equal_to: walk`"}).refine(e=>e.equal_to===void 0||e.mode!=="walk"&&e.set===void 0&&e.scales_at===void 0,{path:["equal_to"],message:"`equal_to: walk` grants a mode other than walk, never with `set` or `scales_at`"}),z.object({kind:z.literal("speed-rule"),flag:z.enum(["ignore-armor-strength"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("attunement-limit"),value:z.number().int().positive(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),value:z.number().int().positive()})).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("sense"),type:z.enum(["darkvision","blindsight","tremorsense","truesight"]),range:z.number().int().nonnegative(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("apply-condition"),condition:z.string().min(1),duration:z.string().optional(),ends_on:z.array(z.string()).optional(),save_repeat:z.object({ability:z.string().min(1),timing:z.string().min(1)}).optional(),subject:subjectField}),z.object({kind:z.literal("damage-bonus"),damage_type:z.string().min(1),amount:z.string().min(1),applies_to:z.union([z.enum(["spell","all"]),weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),spell_scope:spellScopeSchema.optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["skill","tool","language","saving-throw","armor","weapon"]),value:z.string().min(1),expertise:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("ac-bonus"),value:z.number().int(),requires_armor:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("unarmored-ac"),abilities:z.array(abilityEnum),base:z.number().int().optional(),allow_shield:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("unarmed-strike"),dice:z.union([z.string().regex(/^\d+d\d+$/i),z.object({column:z.string().min(1)})]).optional(),abilities:z.array(abilityEnum).nonempty().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("weapon-ability"),ability:z.union([abilityEnum,z.literal("spellcasting")]),weapons:z.union([z.literal("chosen"),z.string(),z.array(z.string())]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("roll-modifier"),mode:z.enum(["advantage","disadvantage","reroll","add-d4"]),roll:z.enum(["ability-check","saving-throw","attack","any"]),scope:z.string().optional(),spell_class:z.string().min(1).optional(),condition:conditionField,subject:subjectField}).refine(e=>e.spell_class===void 0||e.roll==="attack",{path:["spell_class"],message:"roll-modifier: `spell_class` is read only with `roll: attack`"}),z.object({kind:z.literal("extra-attack"),count:z.number().int().positive(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),count:z.number().int().positive()})).optional(),applies_to:z.union([weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("crit-range"),min_roll:z.number().int().min(2).max(20),applies_to:z.enum(["weapon","spell","all"]).optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("reroll-damage"),max_reroll:z.number().int().positive(),applies_to:z.enum(["weapon","spell","all"]).optional(),once_per_die:z.boolean().optional(),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("attack-rule"),flag:z.enum(["no-ranged-in-melee-disadvantage"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("spell-bonus"),save_dc:z.number().int().optional(),attack:z.number().int().optional(),spell_class:z.string().min(1).optional(),subject:subjectField}).refine(e=>e.save_dc!==void 0||e.attack!==void 0,{path:["save_dc"],message:"spell-bonus takes at least one of `save_dc` or `attack`"}),z.object({kind:z.literal("extra-cantrips"),count:z.number().int().positive(),class:z.string().min(1).optional(),subject:subjectField}),z.object({kind:z.literal("damage-roll-option"),mode:z.enum(["reroll-weapon-dice-keep-higher","min-die-face","reroll-below"]),value:z.number().int().min(2).optional(),applies_to:z.union([weaponScopeEnum,z.array(weaponScopeEnum).min(1)]).optional(),two_handed:z.boolean().optional(),once_per_turn:z.boolean().optional(),condition:conditionField,subject:subjectField}).refine(e=>e.mode==="reroll-weapon-dice-keep-higher"===(e.value===void 0),{path:["value"],message:"damage-roll-option: `min-die-face` and `reroll-below` take a `value` (the face); keep-higher takes none"}),z.object({kind:z.literal("immunity"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("vulnerability"),damage_type:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("temp-hp"),amount:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("heal"),amount:z.string().min(1),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("ability-score-increase"),abilities:z.union([z.literal("chosen"),z.array(abilityEnum).min(1)]),amount:z.number().int().positive(),choose:z.number().int().positive().nullable(),max:z.number().int().positive().nullable(),condition:conditionField,subject:subjectField}).refine(e=>e.abilities==="chosen"===(e.choose!==null),{path:["choose"],message:'choose is required IFF abilities is "chosen": a fixed LIST is its own count'}),z.object({kind:z.literal("extra-action"),count:z.number().int().positive(),action_type:z.enum(["action","bonus-action","reaction"]),condition:conditionField,subject:subjectField}),z.object({kind:z.literal("save-outcome"),ability:z.union([abilityEnum,z.literal("any")]),on_success:z.enum(["none","half","full"]),on_failure:z.enum(["none","half","full"]),applies_to:z.string().nullable(),condition:conditionField,subject:subjectField})]);export{featureEffectSchema};
@@ -1 +1 @@
1
- import{featEntitySchema}from"./chunk-AFEWQFQZ.js";import{parseYaml}from"@archivist-gg/core";function parseFeat(source){const raw=parseYaml(source,["name","slug"]);if(!raw.success)return raw;const result=featEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`feat schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseFeat};
1
+ import{featEntitySchema}from"./chunk-QCCA46KM.js";import{parseYaml}from"@archivist-gg/core";function parseFeat(source){const raw=parseYaml(source,["name","slug"]);if(!raw.success)return raw;const result=featEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`feat schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseFeat};
@@ -1 +1 @@
1
- import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resourceConsumptionSchema,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-VHIE2KYQ.js";import{featureEffectSchema}from"./chunk-EON7T2SN.js";import{z as z2}from"zod";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var attackSchema=z.object({name:z.string().min(1),type:z.enum(["melee","ranged","spell"]),ability:z.union([abilityEnum,z.array(abilityEnum).nonempty()]).optional(),damage:z.string().optional(),damage_type:z.string().optional(),action:z.enum(["action","bonus-action","reaction"]).optional(),properties:z.array(z.string()).optional(),range:z.object({normal:z.number().int().nonnegative().optional(),long:z.number().int().nonnegative().optional(),reach:z.number().int().nonnegative().optional()}).optional(),condition:z.string().optional(),bonus:z.number().optional(),extra_damage:z.object({dice:z.string(),type:z.string()}).optional(),weapon_category:z.enum(["simple","martial"]).optional(),mastery:z.string().min(1).optional(),unarmed:z.boolean().optional()});var companionSchema=z2.object({statblock:z2.string().optional(),statblock_wikilink:z2.string().nullable().optional(),count:z2.string().optional(),count_scaling:z2.array(z2.object({level:z2.number().optional(),count:z2.string().optional(),source_quote:z2.string().optional()})).optional(),shares_action_economy:z2.boolean().optional(),turn_order:z2.string().optional(),turn_order_source_quote:z2.string().nullable().optional(),proficiency_bonus_scaled:z2.array(z2.object({stat:z2.string().optional(),formula:z2.string().optional(),source_quote:z2.string().optional()})).optional(),lifecycle:z2.object({created_by:z2.string().optional(),recreate_on:z2.string().nullable().optional(),previous_instance_perishes:z2.boolean().nullable().optional(),vanishes_if_owner_dies:z2.boolean().nullable().optional(),vanishes_after:z2.string().nullable().optional(),source_quote:z2.string().optional()}).nullable().optional(),autonomy:z2.object({when:z2.string().optional(),behaviour:z2.string().optional(),source_quote:z2.string().optional()}).nullable().optional(),variants:z2.array(z2.object({axis:z2.string().optional(),choices:z2.array(z2.string()).optional(),chosen_at:z2.string().optional(),source_quote:z2.string().optional()})).optional(),base_statblock:z2.string().nullable().optional(),overrides:z2.array(z2.object({field:z2.string().optional(),value:z2.string().optional(),source_quote:z2.string().optional()})).optional(),source_quote:z2.string().optional()});var featureObjectSchema=z2.lazy(()=>z2.object({id:z2.string().min(1).optional(),name:z2.string().min(1),description:z2.string().optional(),entries:z2.array(z2.string()).optional(),choices:z2.array(choiceSchema).optional(),grants_resource:z2.string().optional(),consumes:resourceConsumptionSchema.optional(),attacks:z2.array(attackSchema).optional(),action:z2.enum(["action","bonus-action","reaction","free","special"]).optional(),trigger:z2.string().optional(),dc_formula:z2.string().optional(),effects:z2.array(featureEffectSchema).optional(),sub_features:z2.array(featureSchemaTyped).optional(),resources:z2.array(resourceSchema).optional(),activatable:z2.boolean().optional(),passive:z2.boolean().optional(),duration:durationSchema.optional(),class_source:z2.string().min(1).optional(),rendering_hint:z2.string().optional(),subclass_short_name:z2.string().min(1).optional(),subclass_source:z2.string().min(1).optional(),header:z2.number().optional(),is_class_feature_variant:z2.boolean().optional(),gain_subclass_feature:z2.boolean().optional(),gain_subclass_feature_has_content:z2.boolean().optional(),type:z2.string().min(1).optional(),recharge:z2.object({type:z2.enum(["recharge_on_roll","per_day","per_short_rest","per_long_rest"]),param:z2.number()}).optional(),action_cost:actionCostEnum.optional(),save:z2.object({ability:z2.string().min(1),dc_formula:z2.string().min(1)}).optional(),companion:companionSchema.optional()}));var featureSchemaTyped=featureObjectSchema.refine(f=>f.description!==void 0||f.entries!==void 0&&f.entries.length>0,{message:"feature requires either description or non-empty entries"});var featureSchema=featureSchemaTyped;export{featureObjectSchema,featureSchema};
1
+ import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resourceConsumptionSchema,resourceSchema}from"./chunk-ZKDHCDJ2.js";import{choiceSchema}from"./chunk-ZK3P4RSE.js";import{featureEffectSchema}from"./chunk-7TH4WPSU.js";import{z as z2}from"zod";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var attackSchema=z.object({name:z.string().min(1),type:z.enum(["melee","ranged","spell"]),ability:z.union([abilityEnum,z.array(abilityEnum).nonempty()]).optional(),damage:z.string().optional(),damage_type:z.string().optional(),action:z.enum(["action","bonus-action","reaction"]).optional(),properties:z.array(z.string()).optional(),range:z.object({normal:z.number().int().nonnegative().optional(),long:z.number().int().nonnegative().optional(),reach:z.number().int().nonnegative().optional()}).optional(),condition:z.string().optional(),bonus:z.number().optional(),extra_damage:z.object({dice:z.string(),type:z.string()}).optional(),weapon_category:z.enum(["simple","martial"]).optional(),mastery:z.string().min(1).optional(),unarmed:z.boolean().optional()});var companionSchema=z2.object({statblock:z2.string().optional(),statblock_wikilink:z2.string().nullable().optional(),count:z2.string().optional(),count_scaling:z2.array(z2.object({level:z2.number().optional(),count:z2.string().optional(),source_quote:z2.string().optional()})).optional(),shares_action_economy:z2.boolean().optional(),turn_order:z2.string().optional(),turn_order_source_quote:z2.string().nullable().optional(),proficiency_bonus_scaled:z2.array(z2.object({stat:z2.string().optional(),formula:z2.string().optional(),source_quote:z2.string().optional()})).optional(),lifecycle:z2.object({created_by:z2.string().optional(),recreate_on:z2.string().nullable().optional(),previous_instance_perishes:z2.boolean().nullable().optional(),vanishes_if_owner_dies:z2.boolean().nullable().optional(),vanishes_after:z2.string().nullable().optional(),source_quote:z2.string().optional()}).nullable().optional(),autonomy:z2.object({when:z2.string().optional(),behaviour:z2.string().optional(),source_quote:z2.string().optional()}).nullable().optional(),variants:z2.array(z2.object({axis:z2.string().optional(),choices:z2.array(z2.string()).optional(),chosen_at:z2.string().optional(),source_quote:z2.string().optional()})).optional(),base_statblock:z2.string().nullable().optional(),overrides:z2.array(z2.object({field:z2.string().optional(),value:z2.string().optional(),source_quote:z2.string().optional()})).optional(),source_quote:z2.string().optional()});var featureObjectSchema=z2.lazy(()=>z2.object({id:z2.string().min(1).optional(),name:z2.string().min(1),description:z2.string().optional(),entries:z2.array(z2.string()).optional(),choices:z2.array(choiceSchema).optional(),grants_resource:z2.string().optional(),consumes:resourceConsumptionSchema.optional(),attacks:z2.array(attackSchema).optional(),action:z2.enum(["action","bonus-action","reaction","free","special"]).optional(),trigger:z2.string().optional(),dc_formula:z2.string().optional(),effects:z2.array(featureEffectSchema).optional(),sub_features:z2.array(featureSchemaTyped).optional(),resources:z2.array(resourceSchema).optional(),activatable:z2.boolean().optional(),passive:z2.boolean().optional(),duration:durationSchema.optional(),class_source:z2.string().min(1).optional(),rendering_hint:z2.string().optional(),subclass_short_name:z2.string().min(1).optional(),subclass_source:z2.string().min(1).optional(),header:z2.number().optional(),is_class_feature_variant:z2.boolean().optional(),gain_subclass_feature:z2.boolean().optional(),gain_subclass_feature_has_content:z2.boolean().optional(),type:z2.string().min(1).optional(),recharge:z2.object({type:z2.enum(["recharge_on_roll","per_day","per_short_rest","per_long_rest"]),param:z2.number()}).optional(),action_cost:actionCostEnum.optional(),save:z2.object({ability:z2.string().min(1),dc_formula:z2.string().min(1)}).optional(),companion:companionSchema.optional()}));var featureSchemaTyped=featureObjectSchema.refine(f=>f.description!==void 0||f.entries!==void 0&&f.entries.length>0,{message:"feature requires either description or non-empty entries"});var featureSchema=featureSchemaTyped;export{featureObjectSchema,featureSchema};
@@ -1 +1 @@
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
+ import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{classEntitySchema}from"./chunk-655UY3MP.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{RACE_STRUCTURAL_PSEUDO}from"./chunk-UBUKCRZ3.js";import{heldPicks}from"./chunk-E4E6YEN6.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{memoByRevision}from"./chunk-QMEKQTUT.js";import{slugify}from"./chunk-63YJPWTM.js";import{mirrorSpellShapes}from"./chunk-4KVVAENP.js";import{ABILITY_KEYS}from"./chunk-EVT7MGAC.js";var entriesOf=a=>Array.isArray(a)?a:a&&typeof a==="object"?[a]:[];var editionOf=x=>{const e=x==null?void 0:x.edition;return typeof e==="string"?e:void 0};var prefixOf=slug=>{var _a;return(_a=slug.split("_")[0])!=null?_a:slug};function normalizeSpellRef(ref){var _a,_b,_c;if(typeof ref!=="string")return null;let s=ref.trim();const wl=/^\[\[(.+)\]\]$/.exec(s);if(wl){const target=(_a=wl[1].split("|")[0])!=null?_a:"";const tail=(_b=target.split("/").pop())!=null?_b:target;const w=slugify(tail.replace(/#.*$/,"").trim());return w.length>0?w:null}s=s.replace(/#.*$/,"");s=(_c=s.split("|")[0])!=null?_c:"";const out=slugify(s.trim());return out.length>0?out:null}function buildSpellNameIndex(entities){return memoByRevision(SPELL_NAME_INDEX,entities,()=>spellNameIndexOf(entities))}var SPELL_NAME_INDEX=new WeakMap;function spellNameIndexOf(entities){var _a;const byName=new Map;for(const e of entities.search("","spell",Number.POSITIVE_INFINITY)){const raw=e.data.name;const key=slugify(typeof raw==="string"?raw:e.name);const list=(_a=byName.get(key))!=null?_a:[];list.push(e);byName.set(key,list)}return{byName}}function resolveSpellByName(opts){var _a;const{entities,index,nameSlug,carrierSlug,carrierEdition,alreadyCollected}=opts;const own=alreadyCollected.find(s=>{var _a2;return slugify(String((_a2=s.entity.name)!=null?_a2:""))===nameSlug});if(own)return{entity:own.entity,slug:own.slug};const exact=entities.getByTypeAndSlug("spell",`${prefixOf(carrierSlug)}_spell_${nameSlug}`);if(exact)return{entity:mirrorSpellShapes(exact.data),slug:exact.slug};const cands=(_a=index.byName.get(nameSlug))!=null?_a:[];if(cands.length===0){warnOnce(`addspells:miss:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches no spell in the compendium`);return null}const prefix=prefixOf(carrierSlug);let pool=cands.filter(e=>prefixOf(e.slug)===prefix);if(pool.length===0)pool=cands;if(carrierEdition!==void 0){const same=pool.filter(e=>editionOf(e.data)===carrierEdition);if(same.length>0)pool=same}pool=[...pool].sort((a,b)=>a.slug<b.slug?-1:a.slug>b.slug?1:0);if(pool.length>1)warnOnce(`addspells:multi:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches ${cands.length} spells; using "${pool[0].slug}"`);return{entity:mirrorSpellShapes(pool[0].data),slug:pool[0].slug}}var hasContentSelectInline=choices=>Array.isArray(choices)&&choices.some(c=>(c==null?void 0:c.kind)==="select-inline"&&typeof c.id==="string"&&!RACE_STRUCTURAL_PSEUDO.has(c.id)||Array.isArray(c==null?void 0:c.options)&&c.options.some(o=>hasContentSelectInline(o==null?void 0:o.choices)));function raceIsUngated(race){var _a;const r=race;if(hasContentSelectInline(r.choices))return false;return!((_a=r.traits)!=null?_a:[]).some(t=>hasContentSelectInline(t==null?void 0:t.choices))}var readAbility=(v,own)=>{if(v&&typeof v==="object"&&"choose"in v)return"choose";if(typeof v!=="string")return void 0;if(v==="inherit")return own!=null?own:void 0;return ABILITY_KEYS.includes(v)?v:void 0};var entryHasInSliceLeaf=(e,comparand,own)=>readAbility(e.ability,own)!=="choose"&&["known","prepared"].some(b=>{const lv=e[b];return!!lv&&typeof lv==="object"&&!Array.isArray(lv)&&Object.entries(lv).some(([k,v])=>(k==="_"||Number(k)<=comparand)&&Array.isArray(v)&&v.some(x=>typeof x==="string"))});function chosenRaceOptionKeys(race,read){var _a;const out=new Set;const r=race;const lists=[r.choices,...((_a=r.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)];for(const list of lists){for(const c of Array.isArray(list)?list:[]){if((c==null?void 0:c.kind)!=="select-inline"||typeof c.id!=="string"||RACE_STRUCTURAL_PSEUDO.has(c.id))continue;const v=read(c.id);for(const value of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof value!=="string")continue;out.add(slugify(value));const opt=(Array.isArray(c.options)?c.options:[]).find(o=>(o==null?void 0:o.value)===value);if(typeof(opt==null?void 0:opt.label)==="string")out.add(slugify(opt.label))}}}return out}function innateLeaves(innate,comparand){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const strings=v=>Array.isArray(v)?v.filter(x=>typeof x==="string"):v&&typeof v==="object"?Object.values(v).flatMap(strings):[];return Object.entries(innate).filter(([k])=>k==="_"||Number(k)<=comparand).flatMap(([,v])=>strings(v))}function memberAtWillLeaves(innate,comparand,slug){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const out=[];for(const[k,v]of Object.entries(innate)){if(!(k==="_"||Number(k)<=comparand))continue;if(Array.isArray(v)){out.push(...v);continue}for(const[usage,list]of v&&typeof v==="object"?Object.entries(v):[]){if(usage==="will"&&Array.isArray(list))out.push(...list);else warnOnce(`addspells:usage:${slug}:innate:${k}:${usage}`,`archivist: additional_spells on "${slug}" innate.${k}.${usage} is a usage economy (skipped; G8)`)}}return out}function collectAdditionalSpells(args){var _a,_b;const{race,feats,classes,totalLevel,ownAbility,alreadyCollected,entities,warnings}=args;const raceChoice=(_a=args.raceChoice)!=null?_a:(()=>void 0);let index=null;const indexOf=()=>index!=null?index:index=buildSpellNameIndex(entities);const out=[];const carriers=[];const asRaw=x=>x==null?void 0:x.additional_spells;if(race&&raceIsUngated(race))carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:entriesOf(asRaw(race)),comparand:totalLevel,classSlug:null});else if(race){const chosen=chosenRaceOptionKeys(race,raceChoice);for(const e of entriesOf(asRaw(race))){if(typeof e.name==="string"&&chosen.has(slugify(e.name))){carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:[e],comparand:totalLevel,classSlug:null})}}}for(const f of feats)carriers.push({root:"feat",slug:f.slug,edition:editionOf(f),entries:entriesOf(asRaw(f)),comparand:totalLevel,classSlug:null});for(const c of classes){if(!c.entity)continue;carriers.push({root:"class",slug:c.entity.slug,edition:editionOf(c.entity),entries:entriesOf(asRaw(c.entity)),comparand:c.level,classSlug:c.entity.slug});if(c.subclass)carriers.push({root:"subclass",slug:c.subclass.slug,edition:editionOf(c.subclass),entries:entriesOf(asRaw(c.subclass)),comparand:c.level,classSlug:c.entity.slug})}for(const pool of(_b=args.pools)!=null?_b:[]){const c=classes[pool.classIndex];if(!(c==null?void 0:c.entity))continue;for(const m of[...heldPicks(pool),...pool.grants]){if(m.itemBound===true)continue;carriers.push({root:"member",slug:m.slug,edition:editionOf(m.entity),entries:entriesOf(asRaw(m.entity)),comparand:c.level,classSlug:c.entity.slug})}}for(const car of carriers){if(car.entries.length===0)continue;if(car.entries.length>1){if(car.entries.some(e=>entryHasInSliceLeaf(e,car.comparand,ownAbility)))warnOnce(`addspells:siblings:${car.slug}`,`archivist: additional_spells on "${car.slug}" has ${car.entries.length} sibling entries (a choose-one grant); skipped`);continue}const entry=car.entries[0];let ability=readAbility(entry.ability,ownAbility);if(ability==="choose"&&car.root==="race"){const pick=raceChoice("spellcasting-ability");const allowed=entry.ability.choose;ability=typeof pick==="string"&&Array.isArray(allowed)&&allowed.includes(pick)?pick:"choose"}if(ability==="choose")continue;const buckets=["known","prepared"].map(bucket=>{const levels=entry[bucket];return[bucket,!levels||typeof levels!=="object"||Array.isArray(levels)?[]:Object.entries(levels)]});if(car.root==="race")buckets.push(["innate",[["_",innateLeaves(entry.innate,car.comparand)]]]);if(car.root==="member")buckets.push(["at-will",[["_",memberAtWillLeaves(entry.innate,car.comparand,car.slug)]]]);for(const[bucket,levelEntries]of buckets){for(const[k,v]of levelEntries){if(!(k==="_"||Number(k)<=car.comparand))continue;if(!Array.isArray(v)){warnOnce(`addspells:usage:${car.slug}:${bucket}:${k}`,`archivist: additional_spells on "${car.slug}" ${bucket}.${k} is a usage economy (skipped; G8)`);continue}for(const leaf of v){const nameSlug=normalizeSpellRef(leaf);if(!nameSlug)continue;const hit=resolveSpellByName({entities,index:indexOf(),nameSlug,carrierSlug:car.slug,carrierEdition:car.edition,alreadyCollected:[...alreadyCollected,...out]});if(!hit){warnings.push(`additional_spells ref "${String(leaf)}" on ${car.slug} not found in compendium.`);continue}out.push({entity:hit.entity,slug:hit.slug,classSlug:car.classSlug,source:car.root==="race"?"race":car.root==="feat"?"feat":"class",prepared:true,alwaysPrepared:true,...ability?{ability}:{},...bucket==="at-will"?{atWill:true}:{}})}}}}return out}export{prefixOf,normalizeSpellRef,buildSpellNameIndex,resolveSpellByName,raceIsUngated,chosenRaceOptionKeys,collectAdditionalSpells};
1
+ import{RACE_STRUCTURAL_PSEUDO}from"./chunk-UBUKCRZ3.js";import{heldPicks}from"./chunk-7S4VMK3R.js";import{warnOnce}from"./chunk-DZITM5AG.js";import{memoByRevision}from"./chunk-QMEKQTUT.js";import{slugify}from"./chunk-63YJPWTM.js";import{mirrorSpellShapes}from"./chunk-4KVVAENP.js";import{ABILITY_KEYS}from"./chunk-EVT7MGAC.js";var entriesOf=a=>Array.isArray(a)?a:a&&typeof a==="object"?[a]:[];var editionOf=x=>{const e=x==null?void 0:x.edition;return typeof e==="string"?e:void 0};var prefixOf=slug=>{var _a;return(_a=slug.split("_")[0])!=null?_a:slug};function normalizeSpellRef(ref){var _a,_b,_c;if(typeof ref!=="string")return null;let s=ref.trim();const wl=/^\[\[(.+)\]\]$/.exec(s);if(wl){const target=(_a=wl[1].split("|")[0])!=null?_a:"";const tail=(_b=target.split("/").pop())!=null?_b:target;const w=slugify(tail.replace(/#.*$/,"").trim());return w.length>0?w:null}s=s.replace(/#.*$/,"");s=(_c=s.split("|")[0])!=null?_c:"";const out=slugify(s.trim());return out.length>0?out:null}function buildSpellNameIndex(entities){return memoByRevision(SPELL_NAME_INDEX,entities,()=>spellNameIndexOf(entities))}var SPELL_NAME_INDEX=new WeakMap;function spellNameIndexOf(entities){var _a;const byName=new Map;for(const e of entities.search("","spell",Number.POSITIVE_INFINITY)){const raw=e.data.name;const key=slugify(typeof raw==="string"?raw:e.name);const list=(_a=byName.get(key))!=null?_a:[];list.push(e);byName.set(key,list)}return{byName}}function resolveSpellByName(opts){var _a;const{entities,index,nameSlug,carrierSlug,carrierEdition,alreadyCollected}=opts;const own=alreadyCollected.find(s=>{var _a2;return slugify(String((_a2=s.entity.name)!=null?_a2:""))===nameSlug});if(own)return{entity:own.entity,slug:own.slug};const exact=entities.getByTypeAndSlug("spell",`${prefixOf(carrierSlug)}_spell_${nameSlug}`);if(exact)return{entity:mirrorSpellShapes(exact.data),slug:exact.slug};const cands=(_a=index.byName.get(nameSlug))!=null?_a:[];if(cands.length===0){warnOnce(`addspells:miss:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches no spell in the compendium`);return null}const prefix=prefixOf(carrierSlug);let pool=cands.filter(e=>prefixOf(e.slug)===prefix);if(pool.length===0)pool=cands;if(carrierEdition!==void 0){const same=pool.filter(e=>editionOf(e.data)===carrierEdition);if(same.length>0)pool=same}pool=[...pool].sort((a,b)=>a.slug<b.slug?-1:a.slug>b.slug?1:0);if(pool.length>1)warnOnce(`addspells:multi:${nameSlug}`,`archivist: additional_spells ref "${nameSlug}" matches ${cands.length} spells; using "${pool[0].slug}"`);return{entity:mirrorSpellShapes(pool[0].data),slug:pool[0].slug}}var hasContentSelectInline=choices=>Array.isArray(choices)&&choices.some(c=>(c==null?void 0:c.kind)==="select-inline"&&typeof c.id==="string"&&!RACE_STRUCTURAL_PSEUDO.has(c.id)||Array.isArray(c==null?void 0:c.options)&&c.options.some(o=>hasContentSelectInline(o==null?void 0:o.choices)));function raceIsUngated(race){var _a;const r=race;if(hasContentSelectInline(r.choices))return false;return!((_a=r.traits)!=null?_a:[]).some(t=>hasContentSelectInline(t==null?void 0:t.choices))}var readAbility=(v,own)=>{if(v&&typeof v==="object"&&"choose"in v)return"choose";if(typeof v!=="string")return void 0;if(v==="inherit")return own!=null?own:void 0;return ABILITY_KEYS.includes(v)?v:void 0};var entryHasInSliceLeaf=(e,comparand,own)=>readAbility(e.ability,own)!=="choose"&&["known","prepared"].some(b=>{const lv=e[b];return!!lv&&typeof lv==="object"&&!Array.isArray(lv)&&Object.entries(lv).some(([k,v])=>(k==="_"||Number(k)<=comparand)&&Array.isArray(v)&&v.some(x=>typeof x==="string"))});function chosenRaceOptionKeys(race,read){var _a;const out=new Set;const r=race;const lists=[r.choices,...((_a=r.traits)!=null?_a:[]).map(t=>t==null?void 0:t.choices)];for(const list of lists){for(const c of Array.isArray(list)?list:[]){if((c==null?void 0:c.kind)!=="select-inline"||typeof c.id!=="string"||RACE_STRUCTURAL_PSEUDO.has(c.id))continue;const v=read(c.id);for(const value of Array.isArray(v)?v:typeof v==="string"?[v]:[]){if(typeof value!=="string")continue;out.add(slugify(value));const opt=(Array.isArray(c.options)?c.options:[]).find(o=>(o==null?void 0:o.value)===value);if(typeof(opt==null?void 0:opt.label)==="string")out.add(slugify(opt.label))}}}return out}function innateLeaves(innate,comparand){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const strings=v=>Array.isArray(v)?v.filter(x=>typeof x==="string"):v&&typeof v==="object"?Object.values(v).flatMap(strings):[];return Object.entries(innate).filter(([k])=>k==="_"||Number(k)<=comparand).flatMap(([,v])=>strings(v))}function memberAtWillLeaves(innate,comparand,slug){if(!innate||typeof innate!=="object"||Array.isArray(innate))return[];const out=[];for(const[k,v]of Object.entries(innate)){if(!(k==="_"||Number(k)<=comparand))continue;if(Array.isArray(v)){out.push(...v);continue}for(const[usage,list]of v&&typeof v==="object"?Object.entries(v):[]){if(usage==="will"&&Array.isArray(list))out.push(...list);else warnOnce(`addspells:usage:${slug}:innate:${k}:${usage}`,`archivist: additional_spells on "${slug}" innate.${k}.${usage} is a usage economy (skipped; G8)`)}}return out}function collectAdditionalSpells(args){var _a,_b;const{race,feats,classes,totalLevel,ownAbility,alreadyCollected,entities,warnings}=args;const raceChoice=(_a=args.raceChoice)!=null?_a:(()=>void 0);let index=null;const indexOf=()=>index!=null?index:index=buildSpellNameIndex(entities);const out=[];const carriers=[];const asRaw=x=>x==null?void 0:x.additional_spells;if(race&&raceIsUngated(race))carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:entriesOf(asRaw(race)),comparand:totalLevel,classSlug:null});else if(race){const chosen=chosenRaceOptionKeys(race,raceChoice);for(const e of entriesOf(asRaw(race))){if(typeof e.name==="string"&&chosen.has(slugify(e.name))){carriers.push({root:"race",slug:race.slug,edition:editionOf(race),entries:[e],comparand:totalLevel,classSlug:null})}}}for(const f of feats)carriers.push({root:"feat",slug:f.slug,edition:editionOf(f),entries:entriesOf(asRaw(f)),comparand:totalLevel,classSlug:null});for(const c of classes){if(!c.entity)continue;carriers.push({root:"class",slug:c.entity.slug,edition:editionOf(c.entity),entries:entriesOf(asRaw(c.entity)),comparand:c.level,classSlug:c.entity.slug});if(c.subclass)carriers.push({root:"subclass",slug:c.subclass.slug,edition:editionOf(c.subclass),entries:entriesOf(asRaw(c.subclass)),comparand:c.level,classSlug:c.entity.slug})}for(const pool of(_b=args.pools)!=null?_b:[]){const c=classes[pool.classIndex];if(!(c==null?void 0:c.entity))continue;for(const m of[...heldPicks(pool),...pool.grants]){if(m.itemBound===true)continue;carriers.push({root:"member",slug:m.slug,edition:editionOf(m.entity),entries:entriesOf(asRaw(m.entity)),comparand:c.level,classSlug:c.entity.slug})}}for(const car of carriers){if(car.entries.length===0)continue;if(car.entries.length>1){if(car.entries.some(e=>entryHasInSliceLeaf(e,car.comparand,ownAbility)))warnOnce(`addspells:siblings:${car.slug}`,`archivist: additional_spells on "${car.slug}" has ${car.entries.length} sibling entries (a choose-one grant); skipped`);continue}const entry=car.entries[0];let ability=readAbility(entry.ability,ownAbility);if(ability==="choose"&&car.root==="race"){const pick=raceChoice("spellcasting-ability");const allowed=entry.ability.choose;ability=typeof pick==="string"&&Array.isArray(allowed)&&allowed.includes(pick)?pick:"choose"}if(ability==="choose")continue;const buckets=["known","prepared"].map(bucket=>{const levels=entry[bucket];return[bucket,!levels||typeof levels!=="object"||Array.isArray(levels)?[]:Object.entries(levels)]});if(car.root==="race")buckets.push(["innate",[["_",innateLeaves(entry.innate,car.comparand)]]]);if(car.root==="member")buckets.push(["at-will",[["_",memberAtWillLeaves(entry.innate,car.comparand,car.slug)]]]);for(const[bucket,levelEntries]of buckets){for(const[k,v]of levelEntries){if(!(k==="_"||Number(k)<=car.comparand))continue;if(!Array.isArray(v)){warnOnce(`addspells:usage:${car.slug}:${bucket}:${k}`,`archivist: additional_spells on "${car.slug}" ${bucket}.${k} is a usage economy (skipped; G8)`);continue}for(const leaf of v){const nameSlug=normalizeSpellRef(leaf);if(!nameSlug)continue;const hit=resolveSpellByName({entities,index:indexOf(),nameSlug,carrierSlug:car.slug,carrierEdition:car.edition,alreadyCollected:[...alreadyCollected,...out]});if(!hit){warnings.push(`additional_spells ref "${String(leaf)}" on ${car.slug} not found in compendium.`);continue}out.push({entity:hit.entity,slug:hit.slug,classSlug:car.classSlug,source:car.root==="race"?"race":car.root==="feat"?"feat":"class",prepared:true,alwaysPrepared:true,...ability?{ability}:{},...bucket==="at-will"?{atWill:true}:{}})}}}}return out}export{prefixOf,normalizeSpellRef,buildSpellNameIndex,resolveSpellByName,raceIsUngated,chosenRaceOptionKeys,collectAdditionalSpells};
@@ -1 +1 @@
1
- import{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};
1
+ import{subclassEntitySchema}from"./chunk-KGRRQ4US.js";import{aliasFeaturesByLevelActionCost}from"./chunk-S5UCI27C.js";import{parseYaml}from"@archivist-gg/core";function parseSubclass(source){const raw=parseYaml(source,["name","slug","parent_class"]);if(!raw.success)return raw;aliasFeaturesByLevelActionCost(raw.data.features_by_level);const result=subclassEntitySchema.safeParse({edition:"2014",...raw.data});if(!result.success){return{success:false,error:`subclass schema validation failed: ${result.error.message}`}}return{success:true,data:result.data}}export{parseSubclass};
@@ -1 +1 @@
1
- import{parseSubclass}from"./chunk-J6FIBUI4.js";import yaml from"js-yaml";var subclassCodec={parse(doc){return parseSubclass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{subclassCodec};
1
+ import{parseSubclass}from"./chunk-HPBEMAM6.js";import yaml from"js-yaml";var subclassCodec={parse(doc){return parseSubclass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{subclassCodec};
@@ -1 +1 @@
1
- import{parseFeat}from"./chunk-EBFLUJIW.js";import yaml from"js-yaml";var featCodec={parse(doc){return parseFeat(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{featCodec};
1
+ import{parseFeat}from"./chunk-A25HLCQ7.js";import yaml from"js-yaml";var featCodec={parse(doc){return parseFeat(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{featCodec};
@@ -1 +1 @@
1
- import{startingEquipmentEntrySchema}from"./chunk-TKIEPC6F.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 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 wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var toolProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),items:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.array(z.string()).nonempty()})]);var langProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),languages:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])})]);var suggestedCharSchema=z.object({personality_traits:z.record(z.string(),z.string()).optional(),ideals:z.record(z.string(),z.object({name:z.string().optional(),desc:z.string(),alignment:z.string().optional()})).optional(),bonds:z.record(z.string(),z.string()).optional(),flaws:z.record(z.string(),z.string()).optional()});var backgroundEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),skill_proficiencies:z.array(skillEnum),tool_proficiencies:z.array(toolProfSchema),language_proficiencies:z.array(langProfSchema),equipment:z.array(startingEquipmentEntrySchema),feature:z.object({name:z.string().min(1),description:z.string().min(1)}),ability_score_increases:z.object({pool:z.array(abilityEnum).length(3)}).nullable(),origin_feat:z.string().regex(wikilinkRegex).nullable(),suggested_characteristics:suggestedCharSchema.nullable(),choices:z.array(choiceSchema).optional(),rendering_hint:z.string().optional(),has_fluff_images:z.boolean().optional(),tables:z.array(z.object({name:z.string().min(1),dice:z.string().min(1),rows:z.array(z.object({roll:z.string(),text:z.string()}))})).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),prerequisites:z.array(z.object({kind:z.literal("campaign"),slug:z.string().min(1)})).optional(),image:imageField});export{langProfSchema,backgroundEntitySchema};
1
+ import{startingEquipmentEntrySchema}from"./chunk-TKIEPC6F.js";import{choiceSchema}from"./chunk-ZK3P4RSE.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 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 wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var toolProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),items:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.array(z.string()).nonempty()})]);var langProfSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("fixed"),languages:z.array(z.string()).nonempty()}),z.object({kind:z.literal("choice"),count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])})]);var suggestedCharSchema=z.object({personality_traits:z.record(z.string(),z.string()).optional(),ideals:z.record(z.string(),z.object({name:z.string().optional(),desc:z.string(),alignment:z.string().optional()})).optional(),bonds:z.record(z.string(),z.string()).optional(),flaws:z.record(z.string(),z.string()).optional()});var backgroundEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),skill_proficiencies:z.array(skillEnum),tool_proficiencies:z.array(toolProfSchema),language_proficiencies:z.array(langProfSchema),equipment:z.array(startingEquipmentEntrySchema),feature:z.object({name:z.string().min(1),description:z.string().min(1)}),ability_score_increases:z.object({pool:z.array(abilityEnum).length(3)}).nullable(),origin_feat:z.string().regex(wikilinkRegex).nullable(),suggested_characteristics:suggestedCharSchema.nullable(),choices:z.array(choiceSchema).optional(),rendering_hint:z.string().optional(),has_fluff_images:z.boolean().optional(),tables:z.array(z.object({name:z.string().min(1),dice:z.string().min(1),rows:z.array(z.object({roll:z.string(),text:z.string()}))})).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),prerequisites:z.array(z.object({kind:z.literal("campaign"),slug:z.string().min(1)})).optional(),image:imageField});export{langProfSchema,backgroundEntitySchema};
@@ -1 +1 @@
1
- import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resetTriggerEnum,resourceConsumptionSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-VHIE2KYQ.js";import{featureEffectSchema}from"./chunk-EON7T2SN.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var editionEnum=z.enum(["2014","2024"]);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var namedRefSchema=z.object({name:z.string().min(1),source:z.string().min(1).optional(),visible_stats:z.boolean().optional()});var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("level"),min:z.number().int().positive(),class:namedRefSchema.optional(),subclass:namedRefSchema.optional()}),z.object({kind:z.literal("spell-known"),spell:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("pact"),pact:z.enum(["tome","blade","chain","talisman"])}),z.object({kind:z.literal("class"),class:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("other"),detail:z.string()}),z.object({kind:z.literal("optionalfeature"),optionalfeature:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("spell-choose"),choose:z.string().min(1),entry:z.string().optional(),entry_summary:z.string().optional()})]);var usesSchema=z.object({max:z.union([z.number(),z.string()]),recharge:resetTriggerEnum,recovery:z.array(z.object({id:z.string().min(1),name:z.string().min(1),amount:z.union([z.number(),z.string()]),reset:resetTriggerEnum,restores:z.enum(["uses","spell-slots"]).optional()})).optional()});var filterSpecSchema=z.object({rarity:z.array(z.string().min(1)).min(1),types:z.array(z.string().min(1)).optional(),exclude_types:z.array(z.string().min(1)).optional(),cursed:z.literal(false).optional()}).strict();var optionCreatesSchema=z.object({item:z.string().regex(wikilinkRegex).optional(),variant:z.object({candidates:z.array(z.string().regex(wikilinkRegex)).min(1)}).strict().optional(),filter:filterSpecSchema.optional()}).strict().refine(c=>[c.item,c.variant,c.filter].filter(a=>a!==void 0).length===1,{message:"creates needs exactly one of item, variant, filter"});var optionRowSchema=z.object({key:z.string().regex(/^[a-z0-9][a-z0-9._-]*$/,"an option key is lower-case, with no '#' and no whitespace"),name:z.string().min(1),min_level:z.number().int().min(1).max(20),attunement:z.boolean().optional(),creates:optionCreatesSchema}).strict();var infuseItemSchema=z.object({bonuses:z.object({ac:z.number().int().optional(),weapon_attack:z.number().int().optional(),weapon_damage:z.number().int().optional(),spell_attack:z.number().int().optional(),saving_throws:z.number().int().optional(),speed:z.object({walk:z.number().int().optional(),fly:z.number().int().optional(),swim:z.number().int().optional(),climb:z.number().int().optional()}).strict().optional()}).strict().optional(),resist:z.array(z.string().min(1)).optional(),charges:z.object({max:z.number().int().min(1),dice:z.string().optional(),recharge:z.string().optional(),recharge_amount:z.string().optional()}).strict().optional(),action:actionCostEnum.optional(),range:z.string().min(1).optional()}).strict();var infuseBlockSchema=z.object({targets:z.array(z.object({kind:z.enum(["armor","shield","weapon","gear"]),category:z.array(z.string().min(1)).min(1).optional(),property:z.string().min(1).optional(),name_any:z.array(z.string().min(1)).min(1).optional()}).strict()).min(1),targets_label:z.string().min(1).optional(),new_object:z.string().min(1).optional(),rarity:z.string().min(1).optional(),attunement:z.object({required:z.literal(true)}).strict().optional(),choice:z.object({kind:z.literal("damage-type"),options:z.array(z.string().min(1)).min(1).optional()}).strict().optional(),item:infuseItemSchema.optional(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),item:infuseItemSchema}).strict()).optional()}).strict().refine(b=>{var _a;return((_a=b.scales_at)!=null?_a:[]).every((r,i,a)=>i===0||a[i-1].level<r.level)},{message:"scales_at levels ascend"});var optionalFeatureEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),feature_type:z.string().min(1),description:z.string(),prerequisites:z.array(prerequisiteSchema),available_to:z.array(z.string().regex(wikilinkRegex)),effects:z.array(featureEffectSchema),action_cost:actionCostEnum.nullable().optional(),uses:usesSchema.nullable().optional(),consumes:resourceConsumptionSchema.nullable().optional(),duration:durationSchema.nullable().optional(),passive:z.boolean().optional(),activatable:z.boolean().optional(),rendering_hint:z.string().optional(),surface:z.enum(["band","tab"]).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),is_class_feature_variant:z.boolean().optional(),has_fluff_images:z.boolean().optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),image:imageField,repeatable:z.literal(true).optional(),item_choice:z.enum(["learn","create"]).optional(),options:z.array(optionRowSchema).optional(),infuse:infuseBlockSchema.optional(),choices:z.array(choiceSchema).optional()}).superRefine((d,ctx)=>{var _a;if(d.repeatable&&(!d.options||!d.item_choice))ctx.addIssue({code:"custom",message:"a repeatable note needs options and item_choice"});const keys=((_a=d.options)!=null?_a:[]).map(o=>o.key);if(new Set(keys).size!==keys.length)ctx.addIssue({code:"custom",message:"option keys are unique"})});export{optionRowSchema,infuseBlockSchema,optionalFeatureEntitySchema};
1
+ import{durationSchema}from"./chunk-ZE46ADXS.js";import{actionCostEnum,resetTriggerEnum,resourceConsumptionSchema}from"./chunk-ZKDHCDJ2.js";import{choiceSchema}from"./chunk-ZK3P4RSE.js";import{featureEffectSchema}from"./chunk-7TH4WPSU.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var editionEnum=z.enum(["2014","2024"]);var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var namedRefSchema=z.object({name:z.string().min(1),source:z.string().min(1).optional(),visible_stats:z.boolean().optional()});var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("level"),min:z.number().int().positive(),class:namedRefSchema.optional(),subclass:namedRefSchema.optional()}),z.object({kind:z.literal("spell-known"),spell:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("pact"),pact:z.enum(["tome","blade","chain","talisman"])}),z.object({kind:z.literal("class"),class:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("other"),detail:z.string()}),z.object({kind:z.literal("optionalfeature"),optionalfeature:z.string().regex(wikilinkRegex)}),z.object({kind:z.literal("spell-choose"),choose:z.string().min(1),entry:z.string().optional(),entry_summary:z.string().optional()})]);var usesSchema=z.object({max:z.union([z.number(),z.string()]),recharge:resetTriggerEnum,recovery:z.array(z.object({id:z.string().min(1),name:z.string().min(1),amount:z.union([z.number(),z.string()]),reset:resetTriggerEnum,restores:z.enum(["uses","spell-slots"]).optional()})).optional()});var filterSpecSchema=z.object({rarity:z.array(z.string().min(1)).min(1),types:z.array(z.string().min(1)).optional(),exclude_types:z.array(z.string().min(1)).optional(),cursed:z.literal(false).optional()}).strict();var optionCreatesSchema=z.object({item:z.string().regex(wikilinkRegex).optional(),variant:z.object({candidates:z.array(z.string().regex(wikilinkRegex)).min(1)}).strict().optional(),filter:filterSpecSchema.optional()}).strict().refine(c=>[c.item,c.variant,c.filter].filter(a=>a!==void 0).length===1,{message:"creates needs exactly one of item, variant, filter"});var optionRowSchema=z.object({key:z.string().regex(/^[a-z0-9][a-z0-9._-]*$/,"an option key is lower-case, with no '#' and no whitespace"),name:z.string().min(1),min_level:z.number().int().min(1).max(20),attunement:z.boolean().optional(),creates:optionCreatesSchema}).strict();var infuseItemSchema=z.object({bonuses:z.object({ac:z.number().int().optional(),weapon_attack:z.number().int().optional(),weapon_damage:z.number().int().optional(),spell_attack:z.number().int().optional(),saving_throws:z.number().int().optional(),speed:z.object({walk:z.number().int().optional(),fly:z.number().int().optional(),swim:z.number().int().optional(),climb:z.number().int().optional()}).strict().optional()}).strict().optional(),resist:z.array(z.string().min(1)).optional(),charges:z.object({max:z.number().int().min(1),dice:z.string().optional(),recharge:z.string().optional(),recharge_amount:z.string().optional()}).strict().optional(),action:actionCostEnum.optional(),range:z.string().min(1).optional()}).strict();var infuseBlockSchema=z.object({targets:z.array(z.object({kind:z.enum(["armor","shield","weapon","gear"]),category:z.array(z.string().min(1)).min(1).optional(),property:z.string().min(1).optional(),name_any:z.array(z.string().min(1)).min(1).optional()}).strict()).min(1),targets_label:z.string().min(1).optional(),new_object:z.string().min(1).optional(),rarity:z.string().min(1).optional(),attunement:z.object({required:z.literal(true)}).strict().optional(),choice:z.object({kind:z.literal("damage-type"),options:z.array(z.string().min(1)).min(1).optional()}).strict().optional(),item:infuseItemSchema.optional(),scales_at:z.array(z.object({level:z.number().int().min(1).max(20),item:infuseItemSchema}).strict()).optional()}).strict().refine(b=>{var _a;return((_a=b.scales_at)!=null?_a:[]).every((r,i,a)=>i===0||a[i-1].level<r.level)},{message:"scales_at levels ascend"});var optionalFeatureEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),feature_type:z.string().min(1),description:z.string(),prerequisites:z.array(prerequisiteSchema),available_to:z.array(z.string().regex(wikilinkRegex)),effects:z.array(featureEffectSchema),action_cost:actionCostEnum.nullable().optional(),uses:usesSchema.nullable().optional(),consumes:resourceConsumptionSchema.nullable().optional(),duration:durationSchema.nullable().optional(),passive:z.boolean().optional(),activatable:z.boolean().optional(),rendering_hint:z.string().optional(),surface:z.enum(["band","tab"]).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),is_class_feature_variant:z.boolean().optional(),has_fluff_images:z.boolean().optional(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),image:imageField,repeatable:z.literal(true).optional(),item_choice:z.enum(["learn","create"]).optional(),options:z.array(optionRowSchema).optional(),infuse:infuseBlockSchema.optional(),choices:z.array(choiceSchema).optional()}).superRefine((d,ctx)=>{var _a;if(d.repeatable&&(!d.options||!d.item_choice))ctx.addIssue({code:"custom",message:"a repeatable note needs options and item_choice"});const keys=((_a=d.options)!=null?_a:[]).map(o=>o.key);if(new Set(keys).size!==keys.length)ctx.addIssue({code:"custom",message:"option keys are unique"})});export{optionRowSchema,infuseBlockSchema,optionalFeatureEntitySchema};
@@ -1 +1 @@
1
- import{parseRace}from"./chunk-KGZXAAFN.js";import yaml from"js-yaml";var raceCodec={parse(doc){return parseRace(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{raceCodec};
1
+ import{parseRace}from"./chunk-ZZ6QHLWX.js";import yaml from"js-yaml";var raceCodec={parse(doc){return parseRace(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{raceCodec};
@@ -1 +1 @@
1
- import{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{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var editionEnum=z.enum(["2014","2024"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var spellcastingSchema=z.object({caster_type:casterTypeEnum.optional(),ability:abilityEnum,preparation:z.enum(["known","prepared"]).optional(),spell_list:z.string().min(1).optional()});var subclassTableRowSchema=z.object({columns:z.record(z.string(),z.union([z.string(),z.number()])).optional()});var subclassEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),parent_class:z.string().regex(wikilinkRegex,"parent_class must be a wikilink like [[rogue]]"),edition:editionEnum,source:z.string().min(1),description:z.string(),spellcasting:spellcastingSchema.nullable().optional(),table:z.record(z.string(),subclassTableRowSchema).optional(),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(),short_name:z.string().min(1).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),fluff:z.unknown().optional(),table_col_labels:z.array(z.string().min(1)).optional(),cantrip_progression:z.array(z.number()).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(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),image:imageField});export{subclassEntitySchema};
1
+ import{poolGrantSchema,selectionPoolSchema,tabDeclSchema}from"./chunk-GCYUCIDN.js";import{casterTypeEnum}from"./chunk-X22SISGM.js";import{featureSchema}from"./chunk-FC4OPNZM.js";import{resourceSchema}from"./chunk-ZKDHCDJ2.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var editionEnum=z.enum(["2014","2024"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var spellcastingSchema=z.object({caster_type:casterTypeEnum.optional(),ability:abilityEnum,preparation:z.enum(["known","prepared"]).optional(),spell_list:z.string().min(1).optional()});var subclassTableRowSchema=z.object({columns:z.record(z.string(),z.union([z.string(),z.number()])).optional()});var subclassEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),parent_class:z.string().regex(wikilinkRegex,"parent_class must be a wikilink like [[rogue]]"),edition:editionEnum,source:z.string().min(1),description:z.string(),spellcasting:spellcastingSchema.nullable().optional(),table:z.record(z.string(),subclassTableRowSchema).optional(),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(),short_name:z.string().min(1).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),fluff:z.unknown().optional(),table_col_labels:z.array(z.string().min(1)).optional(),cantrip_progression:z.array(z.number()).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(),feat_progression:z.array(progressionSchema).optional(),optionalfeature_progression:z.array(progressionSchema).optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),image:imageField});export{subclassEntitySchema};
@@ -0,0 +1 @@
1
+ import{normalizeRollScope}from"./chunk-FOLHTMSC.js";import{toProfSlug}from"./chunk-VTQ4RWEG.js";import{memberSpellTargets}from"./chunk-6WRU5I75.js";import{heldPicks}from"./chunk-7S4VMK3R.js";import{CONDITION_SLUGS}from"./chunk-KM75CC6Q.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:[],spell_bonus_terms:[],cantrip_bonus_terms:[],applied_conditions:[]}}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:metamagicSpellOnly(e)},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 metamagicSpellOnly(e){if(e.feature_type!=="metamagic")return e.effects;return e.effects.map(eff=>{var _a;return eff.kind==="roll-modifier"&&eff.roll==="attack"&&!((_a=eff.spell_class)==null?void 0:_a.trim())?{...eff,spell_class:"any"}:eff})}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 conditionSlugOf(name){const key=name.trim().toLowerCase();return CONDITION_SLUGS.includes(key)?key:null}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,_r,_s,_t,_u,_v;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];const spellClass=eff.roll==="attack"?((_h=eff.spell_class)==null?void 0:_h.trim())||void 0:void 0;for(const roll of rolls)for(const scope of scopes)out.rollModifiers.push({mode:eff.mode,roll,scope,condition:eff.condition,label,...spellClass?{spellClass}:{}});break}case"spell-bonus":out.spell_bonus_terms.push({label,saveDC:(_i=eff.save_dc)!=null?_i:0,attack:(_j=eff.attack)!=null?_j:0,...((_k=eff.spell_class)==null?void 0:_k.trim())?{spellClass:eff.spell_class.trim()}:{}});break;case"extra-cantrips":out.cantrip_bonus_terms.push({label,count:eff.count,...((_l=eff.class)==null?void 0:_l.trim())?{class:eff.class.trim()}:{},...owner?{owner}:{}});break;case"apply-condition":{if((rf==null?void 0:rf.feature.activatable)!==true||!rf.feature.id||rf.source.kind==="item")break;const condition=conditionSlugOf(eff.condition);if(!condition){warnOnce(`apply-condition:${eff.condition}`,`archivist: "${label}" gives "${eff.condition}", which is not one of the 14 conditions; nothing applied`);break}out.applied_conditions.push({condition,label,buffKey:rf.feature.id});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:(_m=eff.applies_to)!=null?_m:void 0,condition:eff.condition,label});break;case"crit-range":if(((_n=eff.applies_to)!=null?_n:"weapon")==="spell")break;if((_o=eff.condition)==null?void 0:_o.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":"",(_q=(_p=eff.condition)==null?void 0:_p.trim())!=null?_q:""].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}:{},...((_r=eff.condition)==null?void 0:_r.trim())?{condition:eff.condition.trim()}:{},source:label,...scope?{scope}:{}});break}case"damage-bonus":if(((_s=eff.applies_to)!=null?_s:"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=(_t=eff.spell_scope)!=null?_t: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]=((_u=out.ability_bonus[ab])!=null?_u:0)+eff.amount;((_v=out.ability_bonus_terms)!=null?_v: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};
@@ -0,0 +1 @@
1
+ import{spellSource}from"./chunk-PZ3ZZ5H5.js";import{resourceLevelFor}from"./chunk-MJJQQI44.js";import{addToRoll}from"./chunk-VIP3FH2O.js";import{baseClassName}from"./chunk-4F5F5A3X.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,_f;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,classSlug:(_f=caster==null?void 0:caster.classSlug)!=null?_f:null}}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,classSlug:null}}const row=casterRow((_b=spell.classSlug)!=null?_b:null,derived);return row?{ability:row.ability,saveDC:row.saveDC,attackBonus:row.attackBonus,classSlug:row.classSlug}: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{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};
1
+ import{resolveSpellcasting}from"./chunk-YDN6GD2B.js";import{heldPicks}from"./chunk-7S4VMK3R.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};
@@ -1 +1 @@
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};
1
+ import{featureSchema}from"./chunk-FC4OPNZM.js";import{choiceSchema}from"./chunk-ZK3P4RSE.js";import{additionalSpellsEntrySchema,imageField}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var sizeEnum=z.enum(["tiny","small","medium","large","huge"]);var wikilinkRegex=/^\[\[[^[\]]+\]\]$/;var speedSchema=z.object({walk:z.number().int().nonnegative().optional(),fly:z.number().int().nonnegative().optional(),swim:z.number().int().nonnegative().optional(),climb:z.number().int().nonnegative().optional(),burrow:z.number().int().nonnegative().optional(),hover:z.boolean().optional()});var visionSchema=z.object({darkvision:z.number().int().nonnegative().optional(),blindsight:z.number().int().nonnegative().optional(),tremorsense:z.number().int().nonnegative().optional(),truesight:z.number().int().nonnegative().optional()});var fixedAsiSchema=z.object({ability:abilityEnum,amount:z.number().int()});var choiceAsiSchema=z.object({choose:z.number().int().positive(),pool:z.array(abilityEnum).nonempty(),amount:z.number().int()});var asiSchema=z.union([fixedAsiSchema,choiceAsiSchema]);var languagesSchema=z.object({fixed:z.array(z.string()),choice:z.object({count:z.number().int().positive(),from:z.union([z.string(),z.array(z.string())])}).optional()});var raceEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),description:z.string(),size:sizeEnum,speed:speedSchema,ability_score_increases:z.array(asiSchema),age:z.string(),alignment:z.string(),vision:visionSchema,languages:languagesSchema,variant_label:z.string().min(1),traits:z.array(featureSchema),choices:z.array(choiceSchema).optional(),subspecies_of:z.string().regex(wikilinkRegex).optional(),rendering_hint:z.string().optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),creature_type:z.array(z.string().min(1)).optional(),creature_type_tags:z.array(z.string().min(1)).optional(),additional_spells:z.union([z.array(additionalSpellsEntrySchema),additionalSpellsEntrySchema]).optional(),trait_tags:z.unknown().optional(),lineage:z.unknown().optional(),height_and_weight:z.unknown().optional(),sound_clip:z.unknown().optional(),image:imageField});export{fixedAsiSchema,raceEntitySchema};
@@ -1 +1 @@
1
- import{actionCostEnum,resourceSchema}from"./chunk-CCFIINBA.js";import{choiceSchema}from"./chunk-VHIE2KYQ.js";import{featureEffectSchema}from"./chunk-EON7T2SN.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var categoryEnum=z.enum(["origin","general","fighting-style","epic-boon"]);var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("level"),min:z.number().int().positive()}),z.object({kind:z.literal("spellcaster")}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["armor","weapon","tool","skill","saving-throw"]),value:z.string().min(1)}),z.object({kind:z.literal("race"),slug:z.string().min(1)}),z.object({kind:z.literal("class"),slug:z.string().min(1)}),z.object({kind:z.literal("feat"),slug:z.string().min(1)}),z.object({kind:z.literal("campaign"),slug:z.string().min(1)}),z.object({kind:z.literal("exclusive-feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("feature"),slug:z.string().min(1)}),z.object({kind:z.literal("other"),detail:z.string().min(1)}),z.object({kind:z.literal("feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("background"),slug:z.string().min(1)})]);var featEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),category:categoryEnum,description:z.string(),prerequisites:z.array(prerequisiteSchema),benefits:z.array(z.string()),effects:z.array(featureEffectSchema),grants_asi:z.object({amount:z.number().int().positive(),pool:z.array(abilityEnum).optional()}).nullable(),repeatable:z.boolean(),choices:z.array(choiceSchema),rendering_hint:z.string().optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),trait_tags:z.unknown().optional(),optionalfeature_progression:z.array(progressionSchema).optional(),resources:z.array(resourceSchema).optional(),action_cost:actionCostEnum.optional(),image:imageField});export{featEntitySchema};
1
+ import{actionCostEnum,resourceSchema}from"./chunk-ZKDHCDJ2.js";import{choiceSchema}from"./chunk-ZK3P4RSE.js";import{featureEffectSchema}from"./chunk-7TH4WPSU.js";import{additionalSpellsEntrySchema,imageField,progressionSchema}from"./chunk-I26FHSI6.js";import{z}from"zod";var abilityEnum=z.enum(["str","dex","con","int","wis","cha"]);var editionEnum=z.enum(["2014","2024"]);var categoryEnum=z.enum(["origin","general","fighting-style","epic-boon"]);var prerequisiteSchema=z.discriminatedUnion("kind",[z.object({kind:z.literal("ability"),ability:abilityEnum,min:z.number().int().positive()}),z.object({kind:z.literal("level"),min:z.number().int().positive()}),z.object({kind:z.literal("spellcaster")}),z.object({kind:z.literal("proficiency"),proficiency_type:z.enum(["armor","weapon","tool","skill","saving-throw"]),value:z.string().min(1)}),z.object({kind:z.literal("race"),slug:z.string().min(1)}),z.object({kind:z.literal("class"),slug:z.string().min(1)}),z.object({kind:z.literal("feat"),slug:z.string().min(1)}),z.object({kind:z.literal("campaign"),slug:z.string().min(1)}),z.object({kind:z.literal("exclusive-feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("feature"),slug:z.string().min(1)}),z.object({kind:z.literal("other"),detail:z.string().min(1)}),z.object({kind:z.literal("feat-category"),slug:z.string().min(1)}),z.object({kind:z.literal("background"),slug:z.string().min(1)})]);var featEntitySchema=z.object({slug:z.string().min(1),name:z.string().min(1),edition:editionEnum,source:z.string().min(1),category:categoryEnum,description:z.string(),prerequisites:z.array(prerequisiteSchema),benefits:z.array(z.string()),effects:z.array(featureEffectSchema),grants_asi:z.object({amount:z.number().int().positive(),pool:z.array(abilityEnum).optional()}).nullable(),repeatable:z.boolean(),choices:z.array(choiceSchema),rendering_hint:z.string().optional(),additional_spells:z.array(additionalSpellsEntrySchema).optional(),has_fluff:z.boolean().optional(),has_fluff_images:z.boolean().optional(),trait_tags:z.unknown().optional(),optionalfeature_progression:z.array(progressionSchema).optional(),resources:z.array(resourceSchema).optional(),action_cost:actionCostEnum.optional(),image:imageField});export{featEntitySchema};
@@ -1 +1 @@
1
- import{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};
1
+ import{parseClass}from"./chunk-FDWQ6P7Z.js";import yaml from"js-yaml";var classCodec={parse(doc){return parseClass(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{classCodec};
@@ -1 +1 @@
1
- import{parseOptionalFeature}from"./chunk-OV4FG4KO.js";import yaml from"js-yaml";var optionalFeatureCodec={parse(doc){return parseOptionalFeature(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{optionalFeatureCodec};
1
+ import{parseOptionalFeature}from"./chunk-5NGQM3TO.js";import yaml from"js-yaml";var optionalFeatureCodec={parse(doc){return parseOptionalFeature(doc.body)},serialize(entity){return yaml.dump(entity,{lineWidth:-1,sortKeys:false})}};export{optionalFeatureCodec};