@archivist-gg/dnd5e 0.3.27 → 0.3.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSES/SRD.md +6 -13
  2. package/README.md +1 -1
  3. package/dist/{chunk-KEXSF3CH.js → chunk-2OVDSMPY.js} +1 -1
  4. package/dist/chunk-4AJYEWFQ.js +1 -0
  5. package/dist/{chunk-CCAVZANF.js → chunk-53SHSS4M.js} +1 -1
  6. package/dist/{chunk-6J3L2RYZ.js → chunk-5QDSAZG6.js} +1 -1
  7. package/dist/chunk-6IPWTOLU.js +1 -0
  8. package/dist/{chunk-BAOZAXB3.js → chunk-7HOOPNF5.js} +1 -1
  9. package/dist/{chunk-7CFLU2XL.js → chunk-ADX7435T.js} +1 -1
  10. package/dist/chunk-B2JSF2LL.js +1 -0
  11. package/dist/{chunk-35HHIMOJ.js → chunk-C4T6BUSP.js} +1 -1
  12. package/dist/chunk-CLZRWPWT.js +1 -0
  13. package/dist/{chunk-BWIEA5ZP.js → chunk-CYYVM6H3.js} +1 -1
  14. package/dist/{chunk-XVXNBWK6.js → chunk-D2BXAFOL.js} +1 -1
  15. package/dist/chunk-DXJ5NKKB.js +1 -0
  16. package/dist/{chunk-PKIMOVQG.js → chunk-E4E6YEN6.js} +1 -1
  17. package/dist/{chunk-WAUNLUFQ.js → chunk-J27N3KUE.js} +1 -1
  18. package/dist/{chunk-AHEL6LJ5.js → chunk-J6FIBUI4.js} +1 -1
  19. package/dist/chunk-JSI2G6LE.js +1 -0
  20. package/dist/{chunk-JGCE4JVX.js → chunk-KGZXAAFN.js} +1 -1
  21. package/dist/chunk-M2UA2FAK.js +1 -0
  22. package/dist/{chunk-LVKSX6EQ.js → chunk-NB4QWMF5.js} +1 -1
  23. package/dist/{chunk-3A4OSTC4.js → chunk-NU6WP4P5.js} +1 -1
  24. package/dist/{chunk-CEHL7PPC.js → chunk-RR26E7LH.js} +1 -1
  25. package/dist/{chunk-535ZMMZI.js → chunk-VY5ZEOLG.js} +1 -1
  26. package/dist/{chunk-TGK4OP7P.js → chunk-XCF5R5XX.js} +1 -1
  27. package/dist/chunk-YWKC2LJY.js +1 -0
  28. package/dist/class/class.codec.js +1 -1
  29. package/dist/class/class.parser.js +1 -1
  30. package/dist/class/class.schema.js +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/monster/monster.parser.js +1 -1
  33. package/dist/monster/monster.schema.js +1 -1
  34. package/dist/pc/pc.additional-spells.js +1 -1
  35. package/dist/pc/pc.amount-bindings.js +1 -1
  36. package/dist/pc/pc.decision-engine.d.ts +2 -0
  37. package/dist/pc/pc.decision-engine.js +1 -1
  38. package/dist/pc/pc.entry-overrides.js +1 -1
  39. package/dist/pc/pc.equipment.d.ts +5 -1
  40. package/dist/pc/pc.equipment.js +1 -1
  41. package/dist/pc/pc.feature-effects.d.ts +8 -1
  42. package/dist/pc/pc.feature-effects.js +1 -1
  43. package/dist/pc/pc.infusions.js +1 -1
  44. package/dist/pc/pc.item-effects.d.ts +1 -0
  45. package/dist/pc/pc.item-effects.js +1 -1
  46. package/dist/pc/pc.member-choices.js +1 -1
  47. package/dist/pc/pc.parser.js +1 -1
  48. package/dist/pc/pc.pools.js +1 -1
  49. package/dist/pc/pc.proficiencies.js +1 -1
  50. package/dist/pc/pc.proficiency-replacements.d.ts +22 -0
  51. package/dist/pc/pc.proficiency-replacements.js +1 -0
  52. package/dist/pc/pc.recalc.d.ts +3 -1
  53. package/dist/pc/pc.recalc.js +1 -1
  54. package/dist/pc/pc.resolver.js +1 -1
  55. package/dist/pc/pc.resource-seed.js +1 -1
  56. package/dist/pc/pc.resources.js +1 -1
  57. package/dist/pc/pc.rest.js +1 -1
  58. package/dist/pc/pc.schema.d.ts +1 -0
  59. package/dist/pc/pc.schema.js +1 -1
  60. package/dist/pc/pc.species-increases.d.ts +12 -0
  61. package/dist/pc/pc.species-increases.js +1 -0
  62. package/dist/pc/pc.types.d.ts +40 -0
  63. package/dist/race/race.codec.js +1 -1
  64. package/dist/race/race.parser.js +1 -1
  65. package/dist/race/race.schema.js +1 -1
  66. package/dist/race/race.subspecies.d.ts +12 -0
  67. package/dist/race/race.subspecies.js +1 -0
  68. package/dist/schemas/attack-schema.d.ts +1 -0
  69. package/dist/schemas/feature-schema.js +1 -1
  70. package/dist/subclass/subclass.codec.js +1 -1
  71. package/dist/subclass/subclass.parser.js +1 -1
  72. package/dist/subclass/subclass.schema.js +1 -1
  73. package/dist/types/attack.d.ts +1 -0
  74. package/package.json +1 -1
  75. package/dist/chunk-BPXQOJES.js +0 -1
  76. package/dist/chunk-FD2VQ3H6.js +0 -1
  77. package/dist/chunk-GPBPFKUK.js +0 -1
  78. package/dist/chunk-UWDHEIPY.js +0 -1
  79. package/dist/chunk-ZREOQMHM.js +0 -1
@@ -1 +1 @@
1
- import{PACT_WEAPON_CHOICE_ID,classPactWeaponPick,featOfSite,featPickSites,isTargetChoice,memberChoices,memberSpellTargets,nestedPickKeysToPrune,pactWeaponPick,poolMemberSites,poolMemberSitesOf,raceFeatSites,spellsReached}from"../chunk-WAUNLUFQ.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{PACT_WEAPON_CHOICE_ID,classPactWeaponPick,featOfSite,featPickSites,isTargetChoice,memberChoices,memberSpellTargets,nestedPickKeysToPrune,pactWeaponPick,poolMemberSites,poolMemberSitesOf,raceFeatSites,spellsReached};
1
+ import{PACT_WEAPON_CHOICE_ID,classPactWeaponPick,featOfSite,featPickSites,isTargetChoice,memberChoices,memberSpellTargets,nestedPickKeysToPrune,pactWeaponPick,poolMemberSites,poolMemberSitesOf,raceFeatSites,spellsReached}from"../chunk-J27N3KUE.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{PACT_WEAPON_CHOICE_ID,classPactWeaponPick,featOfSite,featPickSites,isTargetChoice,memberChoices,memberSpellTargets,nestedPickKeysToPrune,pactWeaponPick,poolMemberSites,poolMemberSitesOf,raceFeatSites,spellsReached};
@@ -1 +1 @@
1
- import{characterSchema}from"../chunk-BWIEA5ZP.js";import"../chunk-KM75CC6Q.js";import{keptSlugForLink}from"../chunk-PZ4L2EEG.js";import"../chunk-63YJPWTM.js";import*as yaml from"js-yaml";function parsePC(source){var _a;let raw;try{raw=yaml.load(source)}catch(e){const msg=e instanceof Error?e.message:String(e);return{success:false,error:`YAML parse error: ${msg}`}}if(!raw||typeof raw!=="object"){return{success:false,error:"Invalid YAML: expected an object"}}const result=characterSchema.safeParse(raw);if(!result.success){const issue=result.error.issues[0];const path=issue.path.length?issue.path.join("."):"(root)";return{success:false,error:`${path}: ${issue.message}`}}const data=result.data;const legacyState=data.state;const legacyCurrency=legacyState.currency;if(legacyCurrency&&!data.currency){data.currency=legacyCurrency}if(legacyCurrency){delete legacyState.currency}if(legacyState.attuned_items){delete legacyState.attuned_items}for(const entry of(_a=data.equipment)!=null?_a:[]){if(typeof entry.item!=="string")continue;const next=migrateRetiredItemLink(entry.item);if(next!==null)entry.item=next}return{success:true,data}}function migrateRetiredItemLink(item){var _a;const m=/^\[\[([^\]|]+)(\|[^\]]*)?\]\]$/.exec(item.trim());const kept=keptSlugForLink(m?m[1]:item);if(kept===void 0)return null;return m?`[[${kept}${(_a=m[2])!=null?_a:""}]]`:kept}export{parsePC};
1
+ import{characterSchema}from"../chunk-CYYVM6H3.js";import"../chunk-KM75CC6Q.js";import{keptSlugForLink}from"../chunk-PZ4L2EEG.js";import"../chunk-63YJPWTM.js";import*as yaml from"js-yaml";function parsePC(source){var _a;let raw;try{raw=yaml.load(source)}catch(e){const msg=e instanceof Error?e.message:String(e);return{success:false,error:`YAML parse error: ${msg}`}}if(!raw||typeof raw!=="object"){return{success:false,error:"Invalid YAML: expected an object"}}const result=characterSchema.safeParse(raw);if(!result.success){const issue=result.error.issues[0];const path=issue.path.length?issue.path.join("."):"(root)";return{success:false,error:`${path}: ${issue.message}`}}const data=result.data;const legacyState=data.state;const legacyCurrency=legacyState.currency;if(legacyCurrency&&!data.currency){data.currency=legacyCurrency}if(legacyCurrency){delete legacyState.currency}if(legacyState.attuned_items){delete legacyState.attuned_items}if(data.keep_species_ability_increases!==true)delete data.keep_species_ability_increases;for(const entry of(_a=data.equipment)!=null?_a:[]){if(typeof entry.item!=="string")continue;const next=migrateRetiredItemLink(entry.item);if(next!==null)entry.item=next}return{success:true,data}}function migrateRetiredItemLink(item){var _a;const m=/^\[\[([^\]|]+)(\|[^\]]*)?\]\]$/.exec(item.trim());const kept=keptSlugForLink(m?m[1]:item);if(kept===void 0)return null;return m?`[[${kept}${(_a=m[2])!=null?_a:""}]]`:kept}export{parsePC};
@@ -1 +1 @@
1
- import{heldPicks,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolveAllPools,resolvePool,strandedPicks,withoutStrandedSites}from"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{heldPicks,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolveAllPools,resolvePool,strandedPicks,withoutStrandedSites};
1
+ import{heldPicks,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolveAllPools,resolvePool,strandedPicks,withoutStrandedSites}from"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{heldPicks,levelPrereqMax,levelPrereqRefsMet,poolAnchorLevel,resolveAllPools,resolvePool,strandedPicks,withoutStrandedSites};
@@ -1 +1 @@
1
- import{qualifiedGrantCovers}from"../chunk-T55DELVL.js";import"../chunk-SEOASDO4.js";import{collectChosenProficiencies,collectProficiencyGrants,computeEffectiveProficiencies,computeSuppressedProficiencies}from"../chunk-FD2VQ3H6.js";import"../chunk-2EOGK6R6.js";import"../chunk-RQZCGXUZ.js";import"../chunk-BPXQOJES.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import{normKey,proficiencyKey,proficiencyLabel,toProfSlug,weaponProfKey}from"../chunk-VTQ4RWEG.js";import"../chunk-UWDHEIPY.js";import"../chunk-WAUNLUFQ.js";import"../chunk-CEHL7PPC.js";import"../chunk-UBUKCRZ3.js";import"../chunk-KEXSF3CH.js";import"../chunk-PFQPP77Q.js";import"../chunk-QVWT67WA.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";function collectProficiencySources(resolved){const g=collectProficiencyGrants(resolved);const chosen=collectChosenProficiencies(resolved);return{...g,chosenLanguages:chosen.languages,chosenTools:chosen.tools,chosenWeapons:chosen.weapons}}function aggregateProficiencies(resolved){const{armor,weapons}=composeArmorWeapons(resolved);const effective=computeEffectiveProficiencies(resolved);return{armor:armor.kept,weapons:weapons.kept,tools:effective.tools,languages:effective.languages}}function proficiencyOverview(resolved,kind){if(kind==="armor"||kind==="weapons"){const c=composeArmorWeapons(resolved)[kind];return{effective:c.kept,removed:c.suppressed}}return{effective:computeEffectiveProficiencies(resolved)[kind],removed:computeSuppressedProficiencies(resolved)[kind]}}function weaponCoveredBy(effective,weapon){const cat=typeof weapon.category==="string"?weapon.category:"";const base=cat.split("-")[0];return effective.find(e=>{const key=weaponProfKey(e.value);if((key==="simple"||key==="martial")&&key===base)return true;if(cat&&key===normKey(cat))return true;return qualifiedGrantCovers(e.value,weapon)})}function composeArmorWeapons(resolved){const src=collectProficiencySources(resolved);return{armor:applyKindOverrides(resolved,"armor",composeGrantEntries([src.classArmor,src.featArmor,src.effectArmor])),weapons:applyKindOverrides(resolved,"weapons",composeGrantEntries([src.classWeaponFixed,src.classWeaponCategories,src.featWeapons,src.effectWeapons],src.chosenWeapons))}}function applyKindOverrides(resolved,kind,entries){var _a,_b,_c,_d;const ov=(_b=(_a=resolved.definition)==null?void 0:_a.overrides)==null?void 0:_b[kind];const key=v=>proficiencyKey(kind,v);const all=[...entries];for(const v of(_c=ov==null?void 0:ov.add)!=null?_c:[]){if(!all.some(e=>key(e.value)===key(v)))all.push({value:v,label:prettyName(v),sources:[],origin:"manual"})}const removes=new Set(((_d=ov==null?void 0:ov.remove)!=null?_d:[]).map(key));const byLabel=(a,b)=>a.label<b.label?-1:a.label>b.label?1:0;return{kept:all.filter(e=>!removes.has(key(e.value))).sort(byLabel),suppressed:all.filter(e=>removes.has(key(e.value))).sort(byLabel)}}function composeGrantEntries(buckets,picks=[]){const byKey=new Map;for(const bucket of buckets){for(const g of bucket){const key=toProfSlug(g.value);const existing=byKey.get(key);if(!existing){byKey.set(key,{value:g.value,label:prettyName(g.value),sources:[g.source],origin:"grant"});continue}if(!existing.sources.includes(g.source))existing.sources.push(g.source)}}for(const v of picks){const k=toProfSlug(v);if(!byKey.has(k))byKey.set(k,{value:v,label:prettyName(v),sources:[],origin:"pick"})}return[...byKey.values()].sort((a,b)=>a.label<b.label?-1:a.label>b.label?1:0)}function prettyName(slug){return proficiencyLabel(slug)}export{aggregateProficiencies,collectProficiencySources,proficiencyOverview,weaponCoveredBy};
1
+ import{qualifiedGrantCovers}from"../chunk-T55DELVL.js";import"../chunk-SEOASDO4.js";import{collectChosenProficiencies,collectProficiencyGrants,computeEffectiveProficiencies,computeSuppressedProficiencies}from"../chunk-JSI2G6LE.js";import"../chunk-2EOGK6R6.js";import"../chunk-4AJYEWFQ.js";import"../chunk-RQZCGXUZ.js";import"../chunk-CLZRWPWT.js";import"../chunk-B2JSF2LL.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import{normKey,proficiencyKey,proficiencyLabel,toProfSlug,weaponProfKey}from"../chunk-VTQ4RWEG.js";import"../chunk-DXJ5NKKB.js";import"../chunk-J27N3KUE.js";import"../chunk-RR26E7LH.js";import"../chunk-UBUKCRZ3.js";import"../chunk-2OVDSMPY.js";import"../chunk-PFQPP77Q.js";import"../chunk-QVWT67WA.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";function collectProficiencySources(resolved){const g=collectProficiencyGrants(resolved);const chosen=collectChosenProficiencies(resolved);return{...g,chosenLanguages:chosen.languages,chosenTools:chosen.tools,chosenWeapons:chosen.weapons}}function aggregateProficiencies(resolved){const{armor,weapons}=composeArmorWeapons(resolved);const effective=computeEffectiveProficiencies(resolved);return{armor:armor.kept,weapons:weapons.kept,tools:effective.tools,languages:effective.languages}}function proficiencyOverview(resolved,kind){if(kind==="armor"||kind==="weapons"){const c=composeArmorWeapons(resolved)[kind];return{effective:c.kept,removed:c.suppressed}}return{effective:computeEffectiveProficiencies(resolved)[kind],removed:computeSuppressedProficiencies(resolved)[kind]}}function weaponCoveredBy(effective,weapon){const cat=typeof weapon.category==="string"?weapon.category:"";const base=cat.split("-")[0];return effective.find(e=>{const key=weaponProfKey(e.value);if((key==="simple"||key==="martial")&&key===base)return true;if(cat&&key===normKey(cat))return true;return qualifiedGrantCovers(e.value,weapon)})}function composeArmorWeapons(resolved){const src=collectProficiencySources(resolved);return{armor:applyKindOverrides(resolved,"armor",composeGrantEntries([src.classArmor,src.featArmor,src.effectArmor])),weapons:applyKindOverrides(resolved,"weapons",composeGrantEntries([src.classWeaponFixed,src.classWeaponCategories,src.featWeapons,src.effectWeapons],src.chosenWeapons))}}function applyKindOverrides(resolved,kind,entries){var _a,_b,_c,_d;const ov=(_b=(_a=resolved.definition)==null?void 0:_a.overrides)==null?void 0:_b[kind];const key=v=>proficiencyKey(kind,v);const all=[...entries];for(const v of(_c=ov==null?void 0:ov.add)!=null?_c:[]){if(!all.some(e=>key(e.value)===key(v)))all.push({value:v,label:prettyName(v),sources:[],origin:"manual"})}const removes=new Set(((_d=ov==null?void 0:ov.remove)!=null?_d:[]).map(key));const byLabel=(a,b)=>a.label<b.label?-1:a.label>b.label?1:0;return{kept:all.filter(e=>!removes.has(key(e.value))).sort(byLabel),suppressed:all.filter(e=>removes.has(key(e.value))).sort(byLabel)}}function composeGrantEntries(buckets,picks=[]){const byKey=new Map;for(const bucket of buckets){for(const g of bucket){const key=toProfSlug(g.value);const existing=byKey.get(key);if(!existing){byKey.set(key,{value:g.value,label:prettyName(g.value),sources:[g.source],origin:"grant"});continue}if(!existing.sources.includes(g.source))existing.sources.push(g.source)}}for(const v of picks){const k=toProfSlug(v);if(!byKey.has(k))byKey.set(k,{value:v,label:prettyName(v),sources:[],origin:"pick"})}return[...byKey.values()].sort((a,b)=>a.label<b.label?-1:a.label>b.label?1:0)}function prettyName(slug){return proficiencyLabel(slug)}export{aggregateProficiencies,collectProficiencySources,proficiencyOverview,weaponCoveredBy};
@@ -0,0 +1,22 @@
1
+ import type { Choice } from "@archivist-gg/dnd5e/types/choice";
2
+ export type ReplacementDomain = "skill" | "tool";
3
+ export interface ProficiencyReplacement {
4
+ domain: ReplacementDomain;
5
+ value: string;
6
+ label: string;
7
+ carrier: {
8
+ kind: "background" | "race";
9
+ slug: string;
10
+ name: string;
11
+ };
12
+ others: string[];
13
+ choice: Extract<Choice, {
14
+ kind: "select-proficiency";
15
+ }>;
16
+ }
17
+ export declare function replacementChoiceId(domain: ReplacementDomain, value: string): string;
18
+ export declare function replacementKey(r: Pick<ProficiencyReplacement, "carrier" | "choice">): string;
19
+ export declare function isReplacementKey(key: string): boolean;
20
+ export declare function replacementOwner(r: Pick<ProficiencyReplacement, "carrier" | "label">): string;
21
+ export declare function replacementPick(r: Pick<ProficiencyReplacement, "carrier" | "choice">, originChoices: Record<string, unknown> | undefined): string | null;
22
+ export declare function replacementDescription(r: Pick<ProficiencyReplacement, "domain" | "label" | "carrier" | "others">): string;
@@ -0,0 +1 @@
1
+ import{isReplacementKey,replacementChoiceId,replacementDescription,replacementKey,replacementOwner,replacementPick}from"../chunk-CLZRWPWT.js";import"../chunk-VTQ4RWEG.js";export{isReplacementKey,replacementChoiceId,replacementDescription,replacementKey,replacementOwner,replacementPick};
@@ -5,13 +5,14 @@ import type { EntityRegistry } from "@archivist-gg/core";
5
5
  import { type UnarmedStrikeSpec } from "./pc.equipment.js";
6
6
  import { type FeatureEffectTotals } from "./pc.feature-effects.js";
7
7
  import type { WeaponScope } from "../types/feature-effect.js";
8
- import type { ACTerm, AttackRow, DamageRider, DerivedStats, ProficiencySet, ResolvedCharacter, ResolvedClass, CharacterOverrides } from "./pc.types.js";
8
+ import type { AbilityScoreBreakdown, ACTerm, AppliedBonuses, AttackRow, DamageRider, DerivedStats, ProficiencySet, ResolvedCharacter, ResolvedClass, CharacterOverrides } from "./pc.types.js";
9
9
  export declare function phbAverageForDie(hitDieStr: string): number;
10
10
  export declare function parseDieSize(die: string | number | undefined | null): number | null;
11
11
  export declare function flattenRaceAsi(race: RaceEntity | null): Partial<Record<Ability, number>>;
12
12
  export declare function collectClassAsiBranch(resolved: ResolvedCharacter): Partial<Record<Ability, number>>;
13
13
  export declare function abilityBonusBreakdown(resolved: ResolvedCharacter, featureEffects?: FeatureEffectTotals): Record<Ability, {
14
14
  species: number;
15
+ speciesNotUsed: number;
15
16
  background: number;
16
17
  class: number;
17
18
  feat: number;
@@ -36,6 +37,7 @@ export declare function initiativeBonus(dexMod: number, feats: FeatEntity[], edi
36
37
  export declare function speedFromRace(resolved: ResolvedCharacter): number;
37
38
  export declare function collectClassFeatAbilityPoints(resolved: ResolvedCharacter): Partial<Record<Ability, number>>;
38
39
  export declare function computeAbilityScores(resolved: ResolvedCharacter, overrides: CharacterOverrides): Record<Ability, number>;
40
+ export declare function abilityScoreBreakdowns(resolved: ResolvedCharacter, overrides: CharacterOverrides, applied: AppliedBonuses, featureEffects: FeatureEffectTotals, scores: Record<Ability, number>): Record<Ability, AbilityScoreBreakdown>;
39
41
  export declare function computeProficiencies(resolved: ResolvedCharacter): {
40
42
  armor: ProficiencySet;
41
43
  weapons: ProficiencySet;
@@ -1 +1 @@
1
- import{buildFeatureAttackRows,buildUnarmedRow,computeAppliedBonuses,computeSlotsAndAttacks,emptyAppliedBonuses,pactWeaponIndexes}from"../chunk-GPBPFKUK.js";import"../chunk-T55DELVL.js";import"../chunk-SEOASDO4.js";import{amountBindingsFor,ownerClassSlug}from"../chunk-CCAVZANF.js";import"../chunk-PZ3ZZ5H5.js";import{computeConditionEffects,speedConditionNames}from"../chunk-VA3ZWV7C.js";import"../chunk-4E2GIWJE.js";import{collectChosenAbilityPoints,collectChosenProficiencies}from"../chunk-FD2VQ3H6.js";import"../chunk-2EOGK6R6.js";import"../chunk-RQZCGXUZ.js";import{assembleEffectFeatures,computeFeatureEffects,foldsNow,mergeDefenseItems,selfEffectsOf}from"../chunk-BPXQOJES.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import{proficiencyKey}from"../chunk-VTQ4RWEG.js";import{itemLabel}from"../chunk-UWDHEIPY.js";import{featPickSites,poolMemberSitesOf,spellsReached}from"../chunk-WAUNLUFQ.js";import"../chunk-CEHL7PPC.js";import"../chunk-UBUKCRZ3.js";import{resourceLevelFor}from"../chunk-KEXSF3CH.js";import{computeSpellLimits,deriveSpellSlots,effectiveSpellcastingAbility,resolveSpellcasting}from"../chunk-PFQPP77Q.js";import{legacyAsiBranch}from"../chunk-QVWT67WA.js";import{toDefenseSlug}from"../chunk-LR6UMA5V.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import{diceColumnAt,tableCellAt,unarmedDieColumnFor}from"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-NEMX7QGG.js";import"../chunk-56JK6VCL.js";import{effectiveArmor,isShieldArmor}from"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import{resolveAmountText}from"../chunk-VIP3FH2O.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import{bareEntitySlug,slugify}from"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import{abilityModifier,attackBonus,isCanonicalDamageType,isChosenDamageType,proficiencyFromLevel,saveDC,savingThrow,skillBonus}from"../chunk-7FPQJDFD.js";import{ABILITY_KEYS,ALL_SKILLS,SKILL_ABILITY}from"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";var lower=s=>(s!=null?s:"").trim().toLowerCase();function namedSpellSlug(ref){var _a;const inner=ref.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0];return slugify((_a=inner.split("/").pop())!=null?_a:inner)}function dealsDamage(spell){var _a,_b;return((_b=(_a=spell.damage)==null?void 0:_a.types)!=null?_b:[]).some(t=>t.trim()!=="")}function spellsInScope(scope,spells,pickedTypes){var _a,_b;if(!scope)return[];const picked=scope.damage_type_pick!==void 0?pickedTypes(scope.damage_type_pick).map(lower):null;const types=(_a=scope.damage_types)==null?void 0:_a.map(lower);const named=(_b=scope.spells)==null?void 0:_b.map(namedSpellSlug);const hit=spells.filter(({slug,entity:e})=>{var _a2,_b2,_c,_d,_e;if(!dealsDamage(e))return false;const own=((_b2=(_a2=e.damage)==null?void 0:_a2.types)!=null?_b2:[]).map(lower);if(scope.list!==void 0&&!((_c=e.classes)!=null?_c:[]).map(lower).includes(lower(scope.list)))return false;if(scope.level!==void 0&&((_d=e.level)!=null?_d:0)!==scope.level)return false;if(scope.school!==void 0&&lower(e.school)!==lower(scope.school))return false;if(types&&!own.some(t=>types.includes(t)))return false;if(picked&&!own.some(t=>picked.includes(t)))return false;if(named&&!named.includes(bareEntitySlug(slug))&&!named.includes(slugify((_e=e.name)!=null?_e:"")))return false;return true});return[...new Set(hit.map(s=>s.slug))]}function pickedDamageTypes(resolved,choiceId){var _a,_b,_c,_d,_e,_f;const out=new Set;for(const c of(_a=resolved.classes)!=null?_a:[]){for(const owner of[c.entity,c.subclass]){for(const[lvl,feats]of Object.entries((_b=owner==null?void 0:owner.features_by_level)!=null?_b:{})){for(const feat of feats!=null?feats:[]){for(const ch of(_c=feat.choices)!=null?_c:[]){if(ch.kind!=="select-inline"||ch.id!==choiceId)continue;const sel=((_e=(_d=c.choices)==null?void 0:_d[Number(lvl)])!=null?_e:{})[ch.id];if(typeof sel!=="string")continue;const opt=ch.options.find(o=>o.value===sel);for(const word of`${sel} ${(_f=opt==null?void 0:opt.label)!=null?_f:""}`.split(/[^A-Za-z]+/)){if(word&&isCanonicalDamageType(word))out.add(word.toLowerCase())}}}}}}return[...out]}var OTHER_MODES=["fly","swim","climb","burrow"];function wornArmor(slots,registry){const body=slots==null?void 0:slots.armor;const armor=body&&registry?effectiveArmor(body.entity,registry):null;const isBody=armor!==null&&!isShieldArmor(armor);const score=isBody?strengthRequirementOf(armor):void 0;return{heavy:isBody&&armor.category==="heavy",armor:isBody,shield:(slots==null?void 0:slots.shield)!==void 0,strength:body&&isBody&&typeof score==="number"&&score>0?{label:itemLabel(body.entry,body.entity),score}:null}}function strengthRequirementOf(armor){var _a;return(_a=armor.strength_requirement)!=null?_a:armor.strength_required}function speedTermActive(t,worn){var _a;const holds=w=>w==="heavy-armor"?worn.heavy:w==="armor"?worn.armor:worn.shield;return!((_a=t.inactiveWhile)!=null?_a:[]).some(holds)}function armorStrengthPenalty(worn,str,ignoredBy){if(!worn.strength||str>=worn.strength.score||ignoredBy.length>0)return null;return{source:`${worn.strength.label} (Strength ${str} < ${worn.strength.score})`,amount:-ARMOR_STRENGTH_PENALTY}}var ARMOR_STRENGTH_PENALTY=10;function speedAfterConditions(pre,ce){if(ce.speed_floor_zero)return 0;return Math.max(0,Math.floor(pre*ce.speed_multiplier-ce.speed_reduction_ft))}var term=(source,amount,condition)=>({source,amount,...condition?{condition}:{}});function walkTerms(i,species){var _a,_b,_c;const terms=[term(species,i.walk.race)];for(const f of i.resolved.feats){const bonus=f.speed_bonus;if(typeof bonus==="number"&&bonus!==0)terms.push(term((_a=f.name)!=null?_a:"Feat",bonus))}for(const t of i.applied.speed_terms)if(t.mode==="walk"&&t.kind==="bonus")terms.push(term(t.source,t.amount));for(const t of i.features.speed_terms)if(t.mode==="walk"&&!t.set)terms.push(term(t.label,t.value,t.condition));if(i.armorPenalty)terms.push(i.armorPenalty.term);if(i.walk.base>i.walk.additive){const itemWins=i.applied.speed_walk_set===i.walk.base&&i.applied.speed_walk_set>i.features.speed_walk_set;const source=itemWins?(_b=i.applied.speed_walk_set_terms.find(t=>t.amount===i.walk.base))==null?void 0:_b.source:(_c=i.features.speed_terms.find(t=>t.mode==="walk"&&t.set&&t.value===i.walk.base))==null?void 0:_c.label;terms.push(term(source!=null?source:"Minimum speed",i.walk.base-i.walk.additive))}if(i.walk.final!==i.walk.base)terms.push(term(conditionLabel(i),i.walk.final-i.walk.base));return terms}var conditionLabel=i=>i.conditionNames.join(", ")||"Conditions";function otherLine(i,mode,species){var _a,_b,_c,_d,_e;const grants=[];const own=(_b=(_a=i.resolved.race)==null?void 0:_a.speed)==null?void 0:_b[mode];if(typeof own==="number"&&own>0)grants.push(term(species,own));for(const t of i.features.speed_terms)if(t.mode===mode&&t.set&&t.value>0)grants.push(term(t.label,t.value,t.condition));for(const t of i.applied.speed_terms)if(t.mode===mode&&t.kind==="grant"&&t.amount>0)grants.push(term(t.source,t.amount));for(const t of i.applied.speed_terms)if(t.mode===mode&&t.kind==="walk")grants.push({...term(t.source,i.walk.base),equalsWalk:true});for(const t of i.features.speed_terms)if(t.mode===mode&&t.equalsWalk)grants.push({...term(t.label,i.walk.base,t.condition),equalsWalk:true});if(grants.length===0)return null;const penalty=((_c=i.armorPenalty)==null?void 0:_c.everyMode)?-i.armorPenalty.term.amount:0;const after=g=>g.equalsWalk?g.amount:g.amount-Math.min(penalty,g.amount);const best=grants.reduce((a,b)=>after(b)>after(a)?b:a);if(best.amount<=0)return null;const{equalsWalk,...bestTerm}=best;const bonuses=i.features.speed_terms.filter(t=>t.mode===mode&&!t.set&&!t.equalsWalk&&t.value!==0).map(t=>term(t.label,t.value,t.condition));const terms=[bestTerm,...bonuses];if(i.armorPenalty&&penalty>0&&!equalsWalk){const cut=Math.min(penalty,terms.reduce((s,t)=>s+t.amount,0));if(cut>0)terms.push({...i.armorPenalty.term,amount:-cut})}const pre=terms.reduce((s,t)=>s+t.amount,0);const value=speedAfterConditions(pre,i.conditions);if(value!==pre)terms.push(term(conditionLabel(i),value-pre));return{mode,value,...equalsWalk&&bonuses.length===0?{equalsWalk:true}:{},...mode==="fly"&&((_e=(_d=i.resolved.race)==null?void 0:_d.speed)==null?void 0:_e.hover)===true&&typeof own==="number"&&own>0?{hover:true}:{},terms}}function buildSpeedLines(i){var _a,_b;const species=(_b=(_a=i.resolved.race)==null?void 0:_a.name)!=null?_b:"Base speed";const lines=[{mode:"walk",value:i.walk.final,terms:walkTerms(i,species)}];for(const mode of OTHER_MODES){const line=otherLine(i,mode,species);if(line)lines.push(line)}return lines}var WEAPON_CATEGORY_WORDS=new Set(["simple","martial","simple-melee","simple-ranged","martial-melee","martial-ranged","natural"]);function phbAverageForDie(hitDieStr){const n=parseDieSize(hitDieStr);if(n==null)return 4;return Math.floor(n/2)+1}function parseDieSize(die){if(die==null)return null;if(typeof die==="number")return die;const m=die.match(/^d?(\d+)$/i);return m?parseInt(m[1],10):null}function skillSlugFromDisplay(display){return display.toLowerCase().replace(/\s+/g,"-")}function skillSlugToAbilityLookup(slug){return slug.replace(/-/g," ")}function flattenRaceAsi(race){var _a;const out={};if(!(race==null?void 0:race.ability_score_increases))return out;for(const asi of race.ability_score_increases){if("ability"in asi){out[asi.ability]=((_a=out[asi.ability])!=null?_a:0)+asi.amount}}return out}function subraceAsi(resolved){var _a,_b,_c,_d,_e;const subSlug=(_b=(_a=resolved.definition.subrace)==null?void 0:_a.replace(/\[\[|\]\]/g,""))!=null?_b:null;if(!subSlug)return[];const subraces=(_d=(_c=resolved.race)==null?void 0:_c.subraces)!=null?_d:[];const sub=subraces.find(s=>s.slug===subSlug);return(_e=sub==null?void 0:sub.ability_score_increases)!=null?_e:[]}function collectClassAsiBranch(resolved){var _a;const out={};for(const c of resolved.classes){for(const choice of Object.values(c.choices)){const alloc=legacyAsiBranch(choice);if(!alloc)continue;for(const ab of ABILITY_KEYS){const v=alloc[ab];if(typeof v==="number")out[ab]=((_a=out[ab])!=null?_a:0)+v}}}return out}function abilityBonusBreakdown(resolved,featureEffects){var _a,_b,_c,_d,_e,_f,_g,_h;const race=flattenRaceAsi(resolved.race);const origin=collectChosenAbilityPoints(resolved);const sub=subraceAsi(resolved);const classAsi=collectClassAsiBranch(resolved);const featPoints=collectClassFeatAbilityPoints(resolved);const out={};for(const ab of ABILITY_KEYS){let species=((_a=race[ab])!=null?_a:0)+((_b=origin.race[ab])!=null?_b:0);for(const asi of sub){if(asi.ability===ab&&typeof asi.amount==="number")species+=asi.amount}let feat=(_c=featPoints[ab])!=null?_c:0;for(const f of resolved.feats){const bonus=(_d=f.ability_bonuses)==null?void 0:_d[ab];if(typeof bonus==="number")feat+=bonus;feat+=(_e=fixedFeatAbilityIncrease(f)[ab])!=null?_e:0}out[ab]={species,background:(_f=origin.background[ab])!=null?_f:0,class:((_g=classAsi[ab])!=null?_g:0)+((_h=featureEffects==null?void 0:featureEffects.ability_bonus[ab])!=null?_h:0),feat}}return out}function fixedFeatAbilityIncrease(f){var _a;const g=f.grants_asi;if(!g||typeof g.amount!=="number"||g.amount<=0||!Array.isArray(g.pool)||g.pool.length!==1)return{};if(((_a=f.choices)!=null?_a:[]).some(c=>c.kind==="ability-points"))return{};const ab=g.pool[0];return ABILITY_KEYS.includes(ab)?{[ab]:g.amount}:{}}function hitDiceAverageSum(classes){var _a;let total=0;let firstLevelCounted=false;for(const c of classes){const die=parseDieSize((_a=c.entity)==null?void 0:_a.hit_die);if(!c.entity||die==null||c.level<1)continue;for(let lvl=1;lvl<=c.level;lvl++){if(!firstLevelCounted){total+=die;firstLevelCounted=true}else{total+=Math.floor(die/2)+1}}}return total}function hpLevelCount(classes){var _a;let count=0;for(const c of classes){const die=parseDieSize((_a=c.entity)==null?void 0:_a.hit_die);if(!c.entity||die==null||c.level<1)continue;count+=c.level}return count}function multiclassMaxHP(classes,conMod){return Math.max(1,hitDiceAverageSum(classes)+conMod*hpLevelCount(classes))}function resolveDamageRider(rider,rowDamageType,bindings){const{owner,scope:_scope,...rest}=rider;const out={...rest,amount:resolveAmountText(rider.amount,bindings(owner))};if(rider.damage_type!==void 0&&!isChosenDamageType(rider.damage_type)){const resolved=isCanonicalDamageType(rider.damage_type)?rider.damage_type:rowDamageType;if(resolved)out.damage_type=resolved;else delete out.damage_type}return out}function riderReachesRow(rider,row,opts){return scopeReachesRow(rider.scope,row,opts)}function scopeReachesRow(scope,row,opts){if(!(scope==null?void 0:scope.length))return true;return scope.some(word=>{switch(word){case"weapon":return row.unarmed!==true;case"pact-weapon":return(opts==null?void 0:opts.pactPicked)===true?row.pactWeapon===true:row.unarmed!==true;case"unarmed":return row.unarmed===true;case"melee":case"ranged":return row.weaponCategory===word;case"finesse":case"thrown":case"heavy":return row.properties.includes(word)}})}function unarmoredAC(resolved,mods,warnings){return unarmoredACBreakdown(resolved,mods,warnings).total}function unarmoredACBreakdown(resolved,mods,warnings,shieldBonus=0){var _a,_b,_c,_d,_e,_f;const baseTerms=[{source:"Unarmored",amount:10,kind:"unarmored"},{source:"DEX modifier",amount:mods.dex,kind:"dex"}];const{activeBuffs}=assembleEffectFeatures(resolved);const candidates=[{total:10+mods.dex,terms:baseTerms,shieldAllowed:true}];for(const rf of[...resolved.features,...(_a=resolved.itemFeatures)!=null?_a:[]]){if(!foldsNow(rf,activeBuffs))continue;for(const eff of selfEffectsOf(rf.feature)){if(eff.kind!=="unarmored-ac")continue;const base=(_b=eff.base)!=null?_b:10;const terms=[{source:"Unarmored",amount:base,kind:"unarmored"}];let total=base;for(const ab of eff.abilities){terms.push(ab==="dex"?{source:"DEX modifier",amount:mods.dex,kind:"dex"}:{source:`${ab.toUpperCase()} modifier (${(_c=rf.feature.name)!=null?_c:"Unarmored"})`,amount:mods[ab],kind:"ability"});total+=mods[ab]}candidates.push({total,terms,shieldAllowed:eff.allow_shield===true})}}if(candidates.length>1){const applied=c=>c.total+(c.shieldAllowed?shieldBonus:0);let best=candidates[0];for(const c of candidates)if(applied(c)>applied(best))best=c;return best}for(const rf of resolved.features){const feat=rf.feature;if((_d=feat.unarmored_defense)==null?void 0:_d.ability){const ab=feat.unarmored_defense.ability;const amt=(_e=mods[ab])!=null?_e:0;const terms=[...baseTerms,{source:`${ab.toUpperCase()} modifier (Unarmored Defense)`,amount:amt,kind:"ability"}];return{total:10+mods.dex+amt,terms,shieldAllowed:true}}}for(const rf of resolved.features){const name=((_f=rf.feature.name)!=null?_f:"").toLowerCase();if(!/unarmored\s*defense/.test(name))continue;if(rf.source.kind==="class"&&rf.source.slug.includes("monk")){const terms=[...baseTerms,{source:"WIS modifier (Unarmored Defense)",amount:mods.wis,kind:"ability"}];return{total:10+mods.dex+mods.wis,terms,shieldAllowed:true}}if(rf.source.kind==="class"&&rf.source.slug.includes("barbarian")){const terms=[...baseTerms,{source:"CON modifier (Unarmored Defense)",amount:mods.con,kind:"ability"}];return{total:10+mods.dex+mods.con,terms,shieldAllowed:true}}}return{total:10+mods.dex,terms:baseTerms,shieldAllowed:true}}function resolveUnarmedStrike(resolved){var _a,_b,_c;const dice=[];const abilities=new Set;const classOf=rf=>rf.source.kind==="class"?resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===rf.source.slug}):void 0;const readDie=(rf,d)=>{var _a2,_b2;if(typeof d==="string")return d;if(!d)return void 0;const cls=classOf(rf);return cls?(_b2=diceColumnAt((_a2=cls.entity)==null?void 0:_a2.table,cls.level,d.column))!=null?_b2:void 0:void 0};for(const rf of resolved.features){const authored=selfEffectsOf(rf.feature).filter(e=>e.kind==="unarmed-strike");for(const e of authored){const d2=readDie(rf,e.dice);if(d2)dice.push(d2);for(const ab of(_a=e.abilities)!=null?_a:[])abilities.add(ab)}if(authored.length||rf.source.kind!=="class")continue;const slug=((_c=(_b=rf.feature.id)!=null?_b:rf.feature.name)!=null?_c:"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"");const column=unarmedDieColumnFor(slug);if(!column)continue;const d=readDie(rf,{column});if(!d)continue;dice.push(d);abilities.add("dex")}const avg=d=>{const m=/^(\d+)d(\d+)$/i.exec(d);return m?Number(m[1])*(Number(m[2])+1)/2:1};const best=dice.sort((a,b)=>avg(b)-avg(a))[0];return{...best?{dice:best}:{},...abilities.size?{abilities:[...abilities]}:{}}}function initiativeBonus(dexMod,feats,edition){var _a,_b,_c;let bonus=dexMod;for(const f of feats){const featEdition=(_a=f.edition)!=null?_a:edition;const hasData=((_b=f.effects)!=null?_b:[]).some(e=>e.kind==="initiative-bonus");if(bareEntitySlug((_c=f.slug)!=null?_c:"")==="alert"&&featEdition==="2014"&&!hasData)bonus+=5;const initBonus=f.initiative_bonus;if(typeof initBonus==="number")bonus+=initBonus}return bonus}function speedFromRace(resolved){var _a,_b,_c;const base=(_c=(_b=(_a=resolved.race)==null?void 0:_a.speed)==null?void 0:_b.walk)!=null?_c:30;let extra=0;for(const f of resolved.feats){const bonus=f.speed_bonus;if(typeof bonus==="number")extra+=bonus}return base+extra}function collectClassFeatAbilityPoints(resolved){var _a,_b;const out={};const stripRef=ref=>ref.replace(/^\[\[/,"").replace(/\]\]$/,"");const featBySlug=new Map;for(const f of resolved.feats)featBySlug.set(f.slug,f);const sites=featPickSites(resolved.classes,poolMemberSitesOf(resolved),ci=>{var _a2,_b2,_c,_d;return(_d=(_c=(_b2=(_a2=resolved.classes)==null?void 0:_a2[ci])==null?void 0:_b2.entity)==null?void 0:_c.slug)!=null?_d:null});for(const site of sites){{const feat=featBySlug.get(stripRef(site.slug));if(!feat)continue;for(const ch of(_a=feat.choices)!=null?_a:[]){if(ch.kind!=="ability-points")continue;const raw=site.read(ch.id);if(!raw||typeof raw!=="object"||Array.isArray(raw))continue;let left=ch.points;for(const ab of ABILITY_KEYS){if(ch.pool&&!ch.pool.includes(ab))continue;const v=raw[ab];if(typeof v!=="number"||v<=0||left<=0)continue;const take=Math.min(v,ch.max_per,left);out[ab]=((_b=out[ab])!=null?_b:0)+take;left-=take}}}}return out}function computeAbilityScores(resolved,overrides){var _a,_b,_c,_d,_e,_f,_g;const out={...resolved.definition.abilities};const raceBonuses=flattenRaceAsi(resolved.race);for(const ab of ABILITY_KEYS){const b=raceBonuses[ab];if(typeof b==="number")out[ab]=((_a=out[ab])!=null?_a:0)+b}for(const asi of subraceAsi(resolved)){if(asi.ability&&typeof asi.amount==="number")out[asi.ability]=((_b=out[asi.ability])!=null?_b:0)+asi.amount}const originPoints=collectChosenAbilityPoints(resolved);for(const src of[originPoints.race,originPoints.background]){for(const ab of ABILITY_KEYS){const v=src[ab];if(typeof v==="number")out[ab]=((_c=out[ab])!=null?_c:0)+v}}const classAsi=collectClassAsiBranch(resolved);for(const ab of ABILITY_KEYS){const v=classAsi[ab];if(typeof v==="number")out[ab]=((_d=out[ab])!=null?_d:0)+v}const featPoints=collectClassFeatAbilityPoints(resolved);for(const ab of ABILITY_KEYS){const v=featPoints[ab];if(typeof v==="number")out[ab]=((_e=out[ab])!=null?_e:0)+v}for(const f of resolved.feats){const bonuses=f.ability_bonuses;if(bonuses){for(const ab of ABILITY_KEYS){const v=bonuses[ab];if(typeof v==="number")out[ab]=((_f=out[ab])!=null?_f:0)+v}}for(const[ab,v]of Object.entries(fixedFeatAbilityIncrease(f)))out[ab]=((_g=out[ab])!=null?_g:0)+v}if(overrides.scores){for(const ab of ABILITY_KEYS){const v=overrides.scores[ab];if(typeof v==="number")out[ab]=v}}for(const ab of ABILITY_KEYS){if(typeof out[ab]!=="number")out[ab]=10}return out}function normalizeArmorProf(input){var _a,_b;if(!input)return{categories:[],specific:[]};if(Array.isArray(input))return{categories:input,specific:[]};return{categories:(_a=input.categories)!=null?_a:[],specific:(_b=input.specific)!=null?_b:[]}}function normalizeWeaponToolProf(input){var _a,_b,_c;if(!input)return{categories:[],specific:[]};if(Array.isArray(input))return{categories:[],specific:input};return{categories:(_a=input.categories)!=null?_a:[],specific:((_b=input.fixed)!=null?_b:[]).concat((_c=input.specific)!=null?_c:[])}}function mergeInto(target,source){for(const c of source.categories)if(!target.categories.includes(c))target.categories.push(c);for(const s of source.specific)if(!target.specific.includes(s))target.specific.push(s)}function applyArmorWeaponOverrides(profs,overrides){var _a,_b;for(const kind of["armor","weapons"]){const ov=overrides==null?void 0:overrides[kind];if(!ov)continue;const set=profs[kind];const key=v=>proficiencyKey(kind,v);const removes=new Set(((_a=ov.remove)!=null?_a:[]).map(key));for(const v of(_b=ov.add)!=null?_b:[]){const k=key(v);if(removes.has(k))continue;const category=kind==="armor"||k==="simple"||k==="martial";const target=category?set.categories:set.specific;if(!target.some(e=>key(e)===k))target.push(category?k:v)}set.categories=set.categories.filter(e=>!removes.has(key(e)));set.specific=set.specific.filter(e=>!removes.has(key(e)))}}var ORIGIN_RANK={manual:0,equipment:1,grant:2};function composeDefenseEntries(manual,equipment,grants){const byValue=new Map;for(const raw of manual){const value=toDefenseSlug(raw);if(!value||byValue.has(value))continue;byValue.set(value,{value,label:raw.trim(),origin:"manual"})}const consider=(list,origin)=>{var _a,_b,_c,_d;for(const g of list){const value=toDefenseSlug(g.value);if(!value)continue;const existing=byValue.get(value);if(!existing){byValue.set(value,{value,label:g.value.trim(),origin,sources:[...g.sources],...g.condition?{condition:g.condition}:{},...((_a=g.items)==null?void 0:_a.length)?{items:g.items.map(it=>({...it}))}:{}});continue}if(ORIGIN_RANK[origin]>ORIGIN_RANK[existing.origin])existing.origin=origin;const sources=(_b=existing.sources)!=null?_b:existing.sources=[];for(const src of g.sources)if(!sources.includes(src))sources.push(src);if(!existing.condition&&g.condition)existing.condition=g.condition;if((_c=g.items)==null?void 0:_c.length)mergeDefenseItems((_d=existing.items)!=null?_d:existing.items=[],g.items)}};consider(equipment,"equipment");consider(grants,"grant");return[...byValue.values()]}function suppress(resolved,bucket,entries){var _a,_b,_c,_d,_e;const suppressed=new Set(((_e=(_d=(_c=(_b=(_a=resolved.definition)==null?void 0:_a.overrides)==null?void 0:_b.defenses)==null?void 0:_c[bucket])==null?void 0:_d.remove)!=null?_e:[]).map(toDefenseSlug));return entries.filter(e=>!suppressed.has(e.value))}function computeProficiencies(resolved){var _a,_b,_c,_d,_e,_f,_g;const armor={categories:[],specific:[]};const weapons={categories:[],specific:[]};const tools={categories:[],specific:[]};const languages=new Set;for(const c of resolved.classes){const p=(_a=c.entity)==null?void 0:_a.proficiencies;if(!p)continue;mergeInto(armor,normalizeArmorProf(p.armor));mergeInto(weapons,normalizeWeaponToolProf(p.weapons));mergeInto(tools,normalizeWeaponToolProf(p.tools));(_b=p.languages)==null?void 0:_b.forEach(l=>languages.add(l))}const racePr=(_c=resolved.race)==null?void 0:_c.proficiencies;if(racePr){mergeInto(armor,normalizeArmorProf(racePr.armor));mergeInto(weapons,normalizeWeaponToolProf(racePr.weapons));mergeInto(tools,normalizeWeaponToolProf(racePr.tools));(_d=racePr.languages)==null?void 0:_d.forEach(l=>languages.add(l))}const bgPr=(_e=resolved.background)==null?void 0:_e.proficiencies;if(bgPr){mergeInto(armor,normalizeArmorProf(bgPr.armor));mergeInto(weapons,normalizeWeaponToolProf(bgPr.weapons));mergeInto(tools,normalizeWeaponToolProf(bgPr.tools));(_f=bgPr.languages)==null?void 0:_f.forEach(l=>languages.add(l))}for(const f of resolved.feats){const grants=f.grants_proficiency;if(!grants)continue;mergeInto(armor,normalizeArmorProf(grants.armor));mergeInto(weapons,normalizeWeaponToolProf(grants.weapons));mergeInto(tools,normalizeWeaponToolProf(grants.tools));(_g=grants.languages)==null?void 0:_g.forEach(l=>languages.add(l))}return{armor,weapons,tools,languages:Array.from(languages).sort(),saves:[]}}var HAND_SET_HALF_SOURCE="Set by you";function recalc(resolved,registry){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t,_u,_v,_w,_x,_y,_z,_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P,_Q,_R,_S,_T,_U,_V,_W,_X,_Y,_Z,__,_$,_aa,_ba;const warnings=[];const overrides=(_a=resolved.definition.overrides)!=null?_a:{};const chosenProfs=collectChosenProficiencies(resolved);const{features:effectFeatures,activeBuffs}=assembleEffectFeatures(resolved);const tableDiceFor=(src,column,level)=>{var _a2;const cls=src.kind==="class"?resolved.classes.find(c=>{var _a3;return((_a3=c.entity)==null?void 0:_a3.slug)===src.slug}):src.kind==="subclass"?resolved.classes.find(c=>{var _a3;return((_a3=c.subclass)==null?void 0:_a3.slug)===src.slug}):void 0;return cls?diceColumnAt((_a2=cls.entity)==null?void 0:_a2.table,level,column):null};const tableCellFor=(src,column)=>{var _a2;const slug=ownerClassSlug(src,resolved);const cls=slug?resolved.classes.find(c=>{var _a3;return((_a3=c.entity)==null?void 0:_a3.slug)===slug}):void 0;return cls?tableCellAt((_a2=cls.entity)==null?void 0:_a2.table,cls.level,column):null};const featureEffects=computeFeatureEffects(effectFeatures,{activeBuffs,levelFor:src=>resourceLevelFor(src,resolved),tableDiceFor,tableCellFor});const profsForApply=computeProficiencies(resolved);for(const t of chosenProfs.tools){if(!profsForApply.tools.specific.includes(t))profsForApply.tools.specific.push(t)}for(const l of chosenProfs.languages){if(!profsForApply.languages.includes(l))profsForApply.languages.push(l)}for(const w of chosenProfs.weapons){if(!profsForApply.weapons.specific.includes(w))profsForApply.weapons.specific.push(w)}for(const t of featureEffects.proficiencies.tools){if(!profsForApply.tools.specific.includes(t))profsForApply.tools.specific.push(t)}for(const l of featureEffects.proficiencies.languages){if(!profsForApply.languages.includes(l))profsForApply.languages.push(l)}for(const a of featureEffects.proficiencies.armor){if(!profsForApply.armor.categories.includes(a))profsForApply.armor.categories.push(a)}for(const w of featureEffects.proficiencies.weapons){if(!profsForApply.weapons.categories.includes(w))profsForApply.weapons.categories.push(w);if(!WEAPON_CATEGORY_WORDS.has(w)&&!profsForApply.weapons.specific.includes(w)){profsForApply.weapons.specific.push(w)}}profsForApply.languages.sort();applyArmorWeaponOverrides(profsForApply,(_b=resolved.definition)==null?void 0:_b.overrides);const applied=registry?computeAppliedBonuses(resolved,profsForApply,registry,warnings):emptyAppliedBonuses();const savesInformational=applied.informational.filter(i=>i.field==="saving_throws");const spellcastingInformational=applied.informational.filter(i=>i.field==="spell_attack"||i.field==="spell_save_dc");const speedInformational=applied.informational.filter(i=>i.field.startsWith("speed."));const baseScores=computeAbilityScores(resolved,overrides);const scores={...baseScores};for(const ab of ABILITY_KEYS){const bonus=applied.ability_bonuses[ab];scores[ab]+=(typeof bonus==="number"?bonus:0)+((_c=featureEffects.ability_bonus[ab])!=null?_c:0)}for(const ab of ABILITY_KEYS){const stat=applied.ability_statics[ab];if(typeof stat==="number"&&stat>scores[ab])scores[ab]=stat}if(overrides.scores){for(const ab of ABILITY_KEYS){const o=overrides.scores[ab];if(typeof o==="number")scores[ab]=o}}const mods={str:abilityModifier(scores.str),dex:abilityModifier(scores.dex),con:abilityModifier(scores.con),int:abilityModifier(scores.int),wis:abilityModifier(scores.wis),cha:abilityModifier(scores.cha)};const totalLevel=resolved.classes.reduce((s,c)=>s+c.level,0);const proficiencyBonus=proficiencyFromLevel(totalLevel||1);const conditionEffects=computeConditionEffects(resolved.state,resolved.definition.edition,scores);const firstClass=(_e=(_d=resolved.classes[0])==null?void 0:_d.entity)!=null?_e:null;const saveProfs=new Set((_f=firstClass==null?void 0:firstClass.saving_throws)!=null?_f:[]);for(const ab of featureEffects.proficiencies.saves)saveProfs.add(ab);for(const ab of chosenProfs.saves)saveProfs.add(ab);const saves={};const saveBreakdowns={};const activeSaveBonusTerms=featureEffects.save_bonus_terms.filter(t=>{var _a2;return t.inactiveWhile==="incapacitated"?!conditionEffects.actions_disabled:t.inactiveWhile==="unconscious"?!((_a2=resolved.state.conditions)!=null?_a2:[]).includes("unconscious"):true});for(const ab of ABILITY_KEYS){const override=(_g=overrides.saves)==null?void 0:_g[ab];const prof=(_h=override==null?void 0:override.proficient)!=null?_h:saveProfs.has(ab);const featureTerms=[];for(const t of activeSaveBonusTerms){if(t.saves.length>0&&!t.saves.includes(ab))continue;const amount=Math.max(t.minimum,mods[t.ability]);const prior=featureTerms.find(x=>x.source===t.label);if(prior===void 0)featureTerms.push({source:t.label,amount});else if(amount>prior.amount)prior.amount=amount}const derivedBonus=savingThrow(scores[ab],prof,proficiencyBonus)+applied.save_bonus+featureTerms.reduce((sum,t)=>sum+t.amount,0)+conditionEffects.d20_test_penalty;const bonus=(_i=override==null?void 0:override.bonus)!=null?_i:derivedBonus;saves[ab]={bonus,proficient:prof};saveBreakdowns[ab]=[{source:ab.toUpperCase(),amount:mods[ab]},...prof?[{source:"Proficiency",amount:proficiencyBonus}]:[],...applied.save_terms.map(t=>({...t})),...featureTerms,...conditionEffects.d20_test_penalty?[{source:`Exhaustion ${conditionEffects.exhaustion_level}`,amount:conditionEffects.d20_test_penalty}]:[]]}const profSet=new Set([...resolved.definition.skills.proficient,...(_k=(_j=resolved.background)==null?void 0:_j.skill_proficiencies)!=null?_k:[],...chosenProfs.skills,...featureEffects.proficiencies.skills]);const expSet=new Set([...resolved.definition.skills.expertise,...chosenProfs.expertise,...featureEffects.proficiencies.skillExpertise]);const skills={};const skillBreakdowns={};for(const skill of ALL_SKILLS){const skillKey=skillSlugFromDisplay(skill);const ab=SKILL_ABILITY[skillSlugToAbilityLookup(skillKey)];const override=(_l=overrides.skills)==null?void 0:_l[skillKey];const tri=(_m=override==null?void 0:override.proficiency)!=null?_m:expSet.has(skillKey)?"expertise":profSet.has(skillKey)?"proficient":"none";const skillTerms=featureEffects.skill_bonus_terms.filter(t=>t.skills.includes(skillKey)).map(t=>({source:t.label,amount:Math.max(t.minimum,mods[t.ability])}));const halfProfTerms=tri!=="none"?[]:[...featureEffects.half_proficiency_terms.filter(t=>t.skills.length===0||t.skills.includes(skillKey)).map(t=>({source:t.label,amount:t.round==="up"?Math.ceil(proficiencyBonus/2):Math.floor(proficiencyBonus/2)})),...((_n=resolved.definition.skills.half)==null?void 0:_n.includes(skillKey))?[{source:HAND_SET_HALF_SOURCE,amount:Math.floor(proficiencyBonus/2)}]:[]];const halfProfBest=halfProfTerms.length?halfProfTerms.reduce((best,t)=>t.amount>best.amount?t:best):null;const bonus=(_p=override==null?void 0:override.bonus)!=null?_p:skillBonus(scores[ab],tri,proficiencyBonus)+skillTerms.reduce((sum,t)=>sum+t.amount,0)+((_o=halfProfBest==null?void 0:halfProfBest.amount)!=null?_o:0)+conditionEffects.d20_test_penalty;skillBreakdowns[skillKey]=[{source:ab.toUpperCase(),amount:mods[ab]},...tri!=="none"?[{source:tri==="expertise"?"Expertise":"Proficiency",amount:proficiencyBonus*(tri==="expertise"?2:1)}]:[],...skillTerms,...halfProfBest?[halfProfBest]:[],...conditionEffects.d20_test_penalty?[{source:"Conditions",amount:conditionEffects.d20_test_penalty}]:[]];skills[skillKey]={bonus,proficiency:tri,ability:ab,...halfProfBest?{halfProficiency:{source:halfProfBest.source,amount:halfProfBest.amount}}:{}}}const passives={perception:(_r=(_q=overrides.passives)==null?void 0:_q.perception)!=null?_r:10+skills.perception.bonus,investigation:(_t=(_s=overrides.passives)==null?void 0:_s.investigation)!=null?_t:10+skills.investigation.bonus,insight:(_v=(_u=overrides.passives)==null?void 0:_u.insight)!=null?_v:10+skills.insight.bonus};const hpRolled=(_x=(_w=overrides.hp)==null?void 0:_w.rolled)!=null?_x:null;const hpModifier=(_z=(_y=overrides.hp)==null?void 0:_y.modifier)!=null?_z:null;const averageDiceSum=hitDiceAverageSum(resolved.classes);const conLevels=hpLevelCount(resolved.classes);const diceSum=hpRolled!=null?hpRolled:averageDiceSum;const diceConRaw=diceSum+mods.con*conLevels;const diceConClamped=Math.max(1,diceConRaw);const hpMaxDerived=diceConClamped+featureEffects.hp_per_level_bonus*totalLevel+(hpModifier!=null?hpModifier:0);const hpMaxAfterConditions=Math.max(0,Math.floor(hpMaxDerived*conditionEffects.hp_max_multiplier));const hpMax=(_B=(_A=overrides.hp)==null?void 0:_A.max)!=null?_B:hpMaxAfterConditions;const hpBreakdown={diceSum,diceSource:hpRolled!=null?"rolled":"average",averageDiceSum,conMod:mods.con,conLevels,clampApplied:diceConClamped!==diceConRaw,perLevelTerms:featureEffects.hp_per_level_terms.map(t=>({label:t.label,perLevel:t.value,levels:totalLevel,total:t.value*totalLevel})),modifier:hpModifier,exhaustionMultiplier:conditionEffects.hp_max_multiplier,exhaustionLevel:conditionEffects.exhaustion_level,derivedMax:hpMaxAfterConditions,override:(_D=(_C=overrides.hp)==null?void 0:_C.max)!=null?_D:null,final:hpMax};const featureAcTermsFor=hasArmor=>featureEffects.ac_terms.filter(t=>!t.requires_armor||hasArmor).map(t=>({source:t.label,amount:t.value,kind:"feature",condition:t.condition}));const sumTerms=terms=>terms.reduce((s,t)=>s+t.amount,0);const weaponAbilities=[...featureEffects.weaponAbilities];const wantsSpellcasting=resolved.features.some(rf=>selfEffectsOf(rf.feature).some(e=>e.kind==="weapon-ability"&&e.ability==="spellcasting"));if(wantsSpellcasting){let primaryCasterAbility=null;for(const c of resolved.classes){if(!c.entity)continue;const profile=resolveSpellcasting(c);if(profile){primaryCasterAbility=effectiveSpellcastingAbility(c.entity.slug,profile.ability,overrides);break}}if(primaryCasterAbility)weaponAbilities.unshift({ability:primaryCasterAbility})}let derivedEquipment=null;let acDerived;let acBreakdownDerived=[];let acInformationalDerived=[];if(registry){derivedEquipment=computeSlotsAndAttacks(resolved,mods,profsForApply,registry,warnings,proficiencyBonus,weaponAbilities,(_E=resolved.weaponMasteries)!=null?_E:[],featureEffects.attunement_set);if(derivedEquipment.equippedSlots.armor){const featTerms=featureAcTermsFor(true);acDerived=derivedEquipment.ac+sumTerms(featTerms);acBreakdownDerived=[...derivedEquipment.acBreakdown,...featTerms];acInformationalDerived=derivedEquipment.acInformational}else{const shieldBonus=derivedEquipment.acBreakdown.filter(b=>b.kind==="shield").reduce((sum,b)=>sum+b.amount,0);const{total:unarmored,terms:unarmoredTerms,shieldAllowed}=unarmoredACBreakdown(resolved,mods,warnings,shieldBonus);const additive=derivedEquipment.acBreakdown.filter(b=>b.kind==="item"||b.kind==="override"||b.kind==="shield"&&shieldAllowed);const featTerms=featureAcTermsFor(false);const additiveSum=additive.reduce((sum,b)=>sum+b.amount,0);acDerived=unarmored+additiveSum+sumTerms(featTerms);acBreakdownDerived=[...unarmoredTerms,...additive,...featTerms];acInformationalDerived=derivedEquipment.acInformational}}else{const{total,terms}=unarmoredACBreakdown(resolved,mods,warnings);const featTerms=featureAcTermsFor(false);acDerived=total+sumTerms(featTerms);acBreakdownDerived=[...terms,...featTerms]}const ac=(_F=overrides.ac)!=null?_F:acDerived;const worn=wornArmor(derivedEquipment==null?void 0:derivedEquipment.equippedSlots,registry);const featureSpeedTerms=featureEffects.speed_terms.filter(t=>speedTermActive(t,worn));const gatedWalk=featureSpeedTerms.filter(t=>t.mode==="walk"&&t.inactiveWhile!==void 0);const featureWalkBonus=featureEffects.speed_walk_bonus+gatedWalk.filter(t=>!t.set).reduce((sum,t)=>sum+t.value,0);const featureWalkFloor=Math.max(featureEffects.speed_walk_set,...gatedWalk.filter(t=>t.set).map(t=>t.value));const armorPenalty=armorStrengthPenalty(worn,scores.str,featureEffects.ignore_armor_strength);const additiveSpeed=speedFromRace(resolved)+applied.speed_bonuses.walk+featureWalkBonus+((_G=armorPenalty==null?void 0:armorPenalty.amount)!=null?_G:0);const baseSpeed=Math.max(featureWalkFloor,applied.speed_walk_set,additiveSpeed);const adjustedSpeed=baseSpeed*conditionEffects.speed_multiplier-conditionEffects.speed_reduction_ft;const conditionSpeed=conditionEffects.speed_floor_zero?0:Math.max(0,Math.floor(adjustedSpeed));const speed=(_H=overrides.speed)!=null?_H:conditionSpeed;const raceSpeed=(_K=(_J=(_I=resolved.race)==null?void 0:_I.speed)==null?void 0:_J.walk)!=null?_K:30;const speeds=buildSpeedLines({resolved,applied,features:{speed_terms:featureSpeedTerms,speed_walk_set:featureWalkFloor},conditions:conditionEffects,conditionNames:speedConditionNames(resolved.state,resolved.definition.edition),walk:{race:raceSpeed,additive:additiveSpeed,base:baseSpeed,final:conditionSpeed},armorPenalty:armorPenalty?{term:armorPenalty,everyMode:resolved.definition.edition==="2024"}:null});const speedBreakdown=speeds[0].terms;if(!resolved.race)warnings.push("No race resolved; speed defaulted to 30.");const initiativeAmountTerms=featureEffects.initiative_amount_terms.flatMap(term2=>{const text=resolveAmountText(term2.amount,amountBindingsFor(term2.owner,resolved,{proficiencyBonus,mods,spellcastingClasses:[]}));const n=Number(text);if(!Number.isInteger(n)){warnings.push(`${term2.label}: initiative amount "${term2.amount}" is not a number; nothing added.`);return[]}return[{source:term2.label,amount:n}]});const init=(_L=overrides.initiative)!=null?_L:initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)+featureEffects.initiative_bonus+initiativeAmountTerms.reduce((s,t)=>s+t.amount,0);const initiativeBreakdown=[{source:"DEX",amount:mods.dex},...initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)!==mods.dex?[{source:"Feats",amount:initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)-mods.dex}]:[],...featureEffects.initiative_terms.map(term2=>({source:term2.label,amount:term2.value})),...initiativeAmountTerms];const senses={darkvision:Math.max((_O=(_N=(_M=resolved.race)==null?void 0:_M.vision)==null?void 0:_N.darkvision)!=null?_O:0,featureEffects.senses.darkvision,applied.senses.darkvision),blindsight:Math.max(featureEffects.senses.blindsight,applied.senses.blindsight),tremorsense:Math.max(featureEffects.senses.tremorsense,applied.senses.tremorsense),truesight:Math.max(featureEffects.senses.truesight,applied.senses.truesight)};const spellcastingClasses=[];const slotInputs=[];const limitInputs=[];for(const c of resolved.classes){if(!c.entity)continue;const profile=resolveSpellcasting(c);if(!profile)continue;const ab=effectiveSpellcastingAbility(c.entity.slug,profile.ability,overrides);const dc=saveDC(scores[ab],proficiencyBonus)+applied.spell_save_dc;const atk=attackBonus(scores[ab],proficiencyBonus)+applied.spell_attack;spellcastingClasses.push({classSlug:c.entity.slug,className:c.entity.name,ability:ab,defaultAbility:profile.ability,saveDC:dc,attackBonus:atk,casterType:profile.casterType,preparation:profile.preparation,spellList:profile.spellList});slotInputs.push({casterType:profile.casterType,level:c.level});limitInputs.push({classSlug:c.entity.slug,level:c.level,profile,abilityScore:scores[ab]})}const spellcasting=spellcastingClasses.length>0?{ability:spellcastingClasses[0].ability,saveDC:spellcastingClasses[0].saveDC,attackBonus:spellcastingClasses[0].attackBonus}:null;const abilitySpellcasting={};for(const s of resolved.spells){const ab=s.ability;if(!ab||abilitySpellcasting[ab])continue;abilitySpellcasting[ab]={saveDC:saveDC(scores[ab],proficiencyBonus)+applied.spell_save_dc,attackBonus:attackBonus(scores[ab],proficiencyBonus)+applied.spell_attack}}const derivedSlots=deriveSpellSlots(slotInputs);const spellLimits=computeSpellLimits(limitInputs);const defenses={resistances:suppress(resolved,"resistances",composeDefenseEntries((_Q=(_P=resolved.definition.defenses)==null?void 0:_P.resistances)!=null?_Q:[],applied.defenses.resistances,featureEffects.resistances)),immunities:suppress(resolved,"immunities",composeDefenseEntries((_S=(_R=resolved.definition.defenses)==null?void 0:_R.immunities)!=null?_S:[],applied.defenses.immunities,featureEffects.immunities)),vulnerabilities:suppress(resolved,"vulnerabilities",composeDefenseEntries((_U=(_T=resolved.definition.defenses)==null?void 0:_T.vulnerabilities)!=null?_U:[],applied.defenses.vulnerabilities,featureEffects.vulnerabilities)),condition_immunities:suppress(resolved,"condition_immunities",composeDefenseEntries((_W=(_V=resolved.definition.defenses)==null?void 0:_V.condition_immunities)!=null?_W:[],applied.defenses.condition_immunities,featureEffects.condition_immunities))};const attackRows=[...(_X=derivedEquipment==null?void 0:derivedEquipment.attacks)!=null?_X:[],...buildFeatureAttackRows(resolved,mods,profsForApply,proficiencyBonus,weaponAbilities),buildUnarmedRow(mods,proficiencyBonus,resolveUnarmedStrike(resolved))];const scopeOpts={pactPicked:pactWeaponIndexes(resolved,registry)!==null};const riderBindings=owner=>amountBindingsFor(owner,resolved,{proficiencyBonus,mods,spellcastingClasses});const ownSpells=(_Y=resolved.spells)!=null?_Y:[];const spellDamageRiders=featureEffects.spellDamageBonuses.flatMap(r=>{const reached=new Set([...spellsReached(r.targets,ownSpells),...spellsInScope(r.scope,ownSpells,id=>pickedDamageTypes(resolved,id))]);const spells=[...new Set(ownSpells.map(s=>s.slug))].filter(slug=>reached.has(slug));if(!spells.length)return[];const{owner,targets:_targets,scope,damage_type,...rest}=r;return[{...rest,amount:resolveAmountText(r.amount,riderBindings(owner)),...damage_type&&isCanonicalDamageType(damage_type)?{damage_type}:{},...(scope==null?void 0:scope.once)?{once:true}:{},spells}]});const scopedExtra=featureEffects.scopedExtraAttacks;const rowAttacks=attackRows.map(a=>scopedExtra.length?1+Math.max(featureEffects.extraAttack,...scopedExtra.filter(x=>scopeReachesRow(x.scope,a,scopeOpts)).map(x=>x.count)):void 0);return{totalLevel,proficiencyBonus,scores,mods,saves,proficiencies:profsForApply,skills,statBreakdowns:{skills:skillBreakdowns,saves:saveBreakdowns,speed:speedBreakdown,initiative:initiativeBreakdown},passives,senses,hp:{max:hpMax,current:resolved.state.hp.current,temp:resolved.state.hp.temp},hpBreakdown,ac,speed,speeds,initiative:init,spellcasting,spellcastingClasses,abilitySpellcasting,derivedSpellSlots:derivedSlots.standard,pactMagic:derivedSlots.pact,spellLimits,warnings,defenses,acBreakdown:acBreakdownDerived,acInformational:acInformationalDerived,savesInformational,spellcastingInformational,speedInformational,attacksPerAction:Math.max(1+featureEffects.extraAttack,...rowAttacks.filter(n=>n!==void 0)),attacks:attackRows.map((a,i)=>{var _a2,_b2,_c2;const critRange=Math.min((_a2=a.critRange)!=null?_a2:20,featureEffects.critRange);const conditionalCrits=[...(_b2=a.conditionalCrits)!=null?_b2:[],...featureEffects.conditionalCrits].filter(c=>c.minRoll<critRange);const riders=[...(_c2=a.damageRiders)!=null?_c2:[],...featureEffects.damageBonuses.filter(r=>riderReachesRow(r,a,scopeOpts))].map(r=>resolveDamageRider(r,a.damageType,riderBindings));const rollOptions=featureEffects.damageRollOptions.filter(o=>scopeReachesRow(o.scope,a,scopeOpts)).map(({scope:_scope,...o})=>o);const{critRange:_ownCrit,conditionalCrits:_ownConditional,...row}=a;return{...row,toHit:a.toHit+conditionEffects.d20_test_penalty,...critRange<20?{critRange}:{},...conditionalCrits.length?{conditionalCrits}:{},...featureEffects.attackNotes.length?{attackNotes:featureEffects.attackNotes}:{},...riders.length?{damageRiders:riders}:{},...rollOptions.length?{damageRollOptions:rollOptions}:{},...rowAttacks[i]!==void 0?{attacksPerAction:rowAttacks[i]}:{}}}),...spellDamageRiders.length?{spellDamageRiders}:{},equippedSlots:(_Z=derivedEquipment==null?void 0:derivedEquipment.equippedSlots)!=null?_Z:{},carriedWeight:(__=derivedEquipment==null?void 0:derivedEquipment.carriedWeight)!=null?__:0,attunementUsed:(_$=derivedEquipment==null?void 0:derivedEquipment.attunementUsed)!=null?_$:0,attunementLimit:(_ba=derivedEquipment==null?void 0:derivedEquipment.attunementLimit)!=null?_ba:(_aa=overrides.attunement_limit)!=null?_aa:Math.max(3,featureEffects.attunement_set),conditionEffects,rollModifiers:featureEffects.rollModifiers,saveOutcomes:featureEffects.saveOutcomes}}export{HAND_SET_HALF_SOURCE,abilityBonusBreakdown,collectClassAsiBranch,collectClassFeatAbilityPoints,computeAbilityScores,computeProficiencies,fixedFeatAbilityIncrease,flattenRaceAsi,hitDiceAverageSum,hpLevelCount,initiativeBonus,multiclassMaxHP,parseDieSize,phbAverageForDie,recalc,resolveUnarmedStrike,riderReachesRow,scopeReachesRow,speedFromRace,unarmoredAC,unarmoredACBreakdown};
1
+ import{speciesIncreaseRule}from"../chunk-6IPWTOLU.js";import{buildFeatureAttackRows,buildUnarmedRow,computeAppliedBonuses,computeSlotsAndAttacks,emptyAppliedBonuses,pactWeaponIndexes}from"../chunk-YWKC2LJY.js";import"../chunk-T55DELVL.js";import"../chunk-SEOASDO4.js";import{amountBindingsFor,ownerClassSlug}from"../chunk-53SHSS4M.js";import"../chunk-PZ3ZZ5H5.js";import{computeConditionEffects,speedConditionNames}from"../chunk-VA3ZWV7C.js";import"../chunk-4E2GIWJE.js";import{collectChosenAbilityPoints,collectChosenProficiencies}from"../chunk-JSI2G6LE.js";import"../chunk-2EOGK6R6.js";import"../chunk-4AJYEWFQ.js";import"../chunk-RQZCGXUZ.js";import"../chunk-CLZRWPWT.js";import{assembleEffectFeatures,computeFeatureEffects,foldsNow,mergeDefenseItems,selfEffectsOf}from"../chunk-B2JSF2LL.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import{proficiencyKey}from"../chunk-VTQ4RWEG.js";import{itemLabel}from"../chunk-DXJ5NKKB.js";import{featPickSites,poolMemberSitesOf,spellsReached}from"../chunk-J27N3KUE.js";import"../chunk-RR26E7LH.js";import"../chunk-UBUKCRZ3.js";import{resourceLevelFor}from"../chunk-2OVDSMPY.js";import{computeSpellLimits,deriveSpellSlots,effectiveSpellcastingAbility,resolveSpellcasting}from"../chunk-PFQPP77Q.js";import{legacyAsiBranch}from"../chunk-QVWT67WA.js";import{toDefenseSlug}from"../chunk-LR6UMA5V.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import{diceColumnAt,tableCellAt,unarmedDieColumnFor}from"../chunk-CSTAQQGX.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-NEMX7QGG.js";import"../chunk-56JK6VCL.js";import{effectiveArmor,isShieldArmor}from"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import{resolveAmountText}from"../chunk-VIP3FH2O.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import{bareEntitySlug,slugify}from"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import{abilityModifier,attackBonus,isCanonicalDamageType,isChosenDamageType,proficiencyFromLevel,saveDC,savingThrow,skillBonus}from"../chunk-7FPQJDFD.js";import{ABILITY_KEYS,ALL_SKILLS,SKILL_ABILITY}from"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";var lower=s=>(s!=null?s:"").trim().toLowerCase();function namedSpellSlug(ref){var _a;const inner=ref.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0];return slugify((_a=inner.split("/").pop())!=null?_a:inner)}function dealsDamage(spell){var _a,_b;return((_b=(_a=spell.damage)==null?void 0:_a.types)!=null?_b:[]).some(t=>t.trim()!=="")}function spellsInScope(scope,spells,pickedTypes){var _a,_b;if(!scope)return[];const picked=scope.damage_type_pick!==void 0?pickedTypes(scope.damage_type_pick).map(lower):null;const types=(_a=scope.damage_types)==null?void 0:_a.map(lower);const named=(_b=scope.spells)==null?void 0:_b.map(namedSpellSlug);const hit=spells.filter(({slug,entity:e})=>{var _a2,_b2,_c,_d,_e;if(!dealsDamage(e))return false;const own=((_b2=(_a2=e.damage)==null?void 0:_a2.types)!=null?_b2:[]).map(lower);if(scope.list!==void 0&&!((_c=e.classes)!=null?_c:[]).map(lower).includes(lower(scope.list)))return false;if(scope.level!==void 0&&((_d=e.level)!=null?_d:0)!==scope.level)return false;if(scope.school!==void 0&&lower(e.school)!==lower(scope.school))return false;if(types&&!own.some(t=>types.includes(t)))return false;if(picked&&!own.some(t=>picked.includes(t)))return false;if(named&&!named.includes(bareEntitySlug(slug))&&!named.includes(slugify((_e=e.name)!=null?_e:"")))return false;return true});return[...new Set(hit.map(s=>s.slug))]}function pickedDamageTypes(resolved,choiceId){var _a,_b,_c,_d,_e,_f;const out=new Set;for(const c of(_a=resolved.classes)!=null?_a:[]){for(const owner of[c.entity,c.subclass]){for(const[lvl,feats]of Object.entries((_b=owner==null?void 0:owner.features_by_level)!=null?_b:{})){for(const feat of feats!=null?feats:[]){for(const ch of(_c=feat.choices)!=null?_c:[]){if(ch.kind!=="select-inline"||ch.id!==choiceId)continue;const sel=((_e=(_d=c.choices)==null?void 0:_d[Number(lvl)])!=null?_e:{})[ch.id];if(typeof sel!=="string")continue;const opt=ch.options.find(o=>o.value===sel);for(const word of`${sel} ${(_f=opt==null?void 0:opt.label)!=null?_f:""}`.split(/[^A-Za-z]+/)){if(word&&isCanonicalDamageType(word))out.add(word.toLowerCase())}}}}}}return[...out]}var OTHER_MODES=["fly","swim","climb","burrow"];function wornArmor(slots,registry){const body=slots==null?void 0:slots.armor;const armor=body&&registry?effectiveArmor(body.entity,registry):null;const isBody=armor!==null&&!isShieldArmor(armor);const score=isBody?strengthRequirementOf(armor):void 0;return{heavy:isBody&&armor.category==="heavy",armor:isBody,shield:(slots==null?void 0:slots.shield)!==void 0,strength:body&&isBody&&typeof score==="number"&&score>0?{label:itemLabel(body.entry,body.entity),score}:null}}function strengthRequirementOf(armor){var _a;return(_a=armor.strength_requirement)!=null?_a:armor.strength_required}function speedTermActive(t,worn){var _a;const holds=w=>w==="heavy-armor"?worn.heavy:w==="armor"?worn.armor:worn.shield;return!((_a=t.inactiveWhile)!=null?_a:[]).some(holds)}function armorStrengthPenalty(worn,str,ignoredBy){if(!worn.strength||str>=worn.strength.score||ignoredBy.length>0)return null;return{source:`${worn.strength.label} (Strength ${str} < ${worn.strength.score})`,amount:-ARMOR_STRENGTH_PENALTY}}var ARMOR_STRENGTH_PENALTY=10;function speedAfterConditions(pre,ce){if(ce.speed_floor_zero)return 0;return Math.max(0,Math.floor(pre*ce.speed_multiplier-ce.speed_reduction_ft))}var term=(source,amount,condition)=>({source,amount,...condition?{condition}:{}});function walkTerms(i,species){var _a,_b,_c;const terms=[term(species,i.walk.race)];for(const f of i.resolved.feats){const bonus=f.speed_bonus;if(typeof bonus==="number"&&bonus!==0)terms.push(term((_a=f.name)!=null?_a:"Feat",bonus))}for(const t of i.applied.speed_terms)if(t.mode==="walk"&&t.kind==="bonus")terms.push(term(t.source,t.amount));for(const t of i.features.speed_terms)if(t.mode==="walk"&&!t.set)terms.push(term(t.label,t.value,t.condition));if(i.armorPenalty)terms.push(i.armorPenalty.term);if(i.walk.base>i.walk.additive){const itemWins=i.applied.speed_walk_set===i.walk.base&&i.applied.speed_walk_set>i.features.speed_walk_set;const source=itemWins?(_b=i.applied.speed_walk_set_terms.find(t=>t.amount===i.walk.base))==null?void 0:_b.source:(_c=i.features.speed_terms.find(t=>t.mode==="walk"&&t.set&&t.value===i.walk.base))==null?void 0:_c.label;terms.push(term(source!=null?source:"Minimum speed",i.walk.base-i.walk.additive))}if(i.walk.final!==i.walk.base)terms.push(term(conditionLabel(i),i.walk.final-i.walk.base));return terms}var conditionLabel=i=>i.conditionNames.join(", ")||"Conditions";function otherLine(i,mode,species){var _a,_b,_c,_d,_e;const grants=[];const own=(_b=(_a=i.resolved.race)==null?void 0:_a.speed)==null?void 0:_b[mode];if(typeof own==="number"&&own>0)grants.push(term(species,own));for(const t of i.features.speed_terms)if(t.mode===mode&&t.set&&t.value>0)grants.push(term(t.label,t.value,t.condition));for(const t of i.applied.speed_terms)if(t.mode===mode&&t.kind==="grant"&&t.amount>0)grants.push(term(t.source,t.amount));for(const t of i.applied.speed_terms)if(t.mode===mode&&t.kind==="walk")grants.push({...term(t.source,i.walk.base),equalsWalk:true});for(const t of i.features.speed_terms)if(t.mode===mode&&t.equalsWalk)grants.push({...term(t.label,i.walk.base,t.condition),equalsWalk:true});if(grants.length===0)return null;const penalty=((_c=i.armorPenalty)==null?void 0:_c.everyMode)?-i.armorPenalty.term.amount:0;const after=g=>g.equalsWalk?g.amount:g.amount-Math.min(penalty,g.amount);const best=grants.reduce((a,b)=>after(b)>after(a)?b:a);if(best.amount<=0)return null;const{equalsWalk,...bestTerm}=best;const bonuses=i.features.speed_terms.filter(t=>t.mode===mode&&!t.set&&!t.equalsWalk&&t.value!==0).map(t=>term(t.label,t.value,t.condition));const terms=[bestTerm,...bonuses];if(i.armorPenalty&&penalty>0&&!equalsWalk){const cut=Math.min(penalty,terms.reduce((s,t)=>s+t.amount,0));if(cut>0)terms.push({...i.armorPenalty.term,amount:-cut})}const pre=terms.reduce((s,t)=>s+t.amount,0);const value=speedAfterConditions(pre,i.conditions);if(value!==pre)terms.push(term(conditionLabel(i),value-pre));return{mode,value,...equalsWalk&&bonuses.length===0?{equalsWalk:true}:{},...mode==="fly"&&((_e=(_d=i.resolved.race)==null?void 0:_d.speed)==null?void 0:_e.hover)===true&&typeof own==="number"&&own>0?{hover:true}:{},terms}}function buildSpeedLines(i){var _a,_b;const species=(_b=(_a=i.resolved.race)==null?void 0:_a.name)!=null?_b:"Base speed";const lines=[{mode:"walk",value:i.walk.final,terms:walkTerms(i,species)}];for(const mode of OTHER_MODES){const line=otherLine(i,mode,species);if(line)lines.push(line)}return lines}var WEAPON_CATEGORY_WORDS=new Set(["simple","martial","simple-melee","simple-ranged","martial-melee","martial-ranged","natural"]);function phbAverageForDie(hitDieStr){const n=parseDieSize(hitDieStr);if(n==null)return 4;return Math.floor(n/2)+1}function parseDieSize(die){if(die==null)return null;if(typeof die==="number")return die;const m=die.match(/^d?(\d+)$/i);return m?parseInt(m[1],10):null}function skillSlugFromDisplay(display){return display.toLowerCase().replace(/\s+/g,"-")}function skillSlugToAbilityLookup(slug){return slug.replace(/-/g," ")}function flattenRaceAsi(race){var _a;const out={};if(!(race==null?void 0:race.ability_score_increases))return out;for(const asi of race.ability_score_increases){if("ability"in asi){out[asi.ability]=((_a=out[asi.ability])!=null?_a:0)+asi.amount}}return out}function subraceAsi(resolved){var _a,_b,_c,_d,_e;const subSlug=(_b=(_a=resolved.definition.subrace)==null?void 0:_a.replace(/\[\[|\]\]/g,""))!=null?_b:null;if(!subSlug)return[];const subraces=(_d=(_c=resolved.race)==null?void 0:_c.subraces)!=null?_d:[];const sub=subraces.find(s=>s.slug===subSlug);return(_e=sub==null?void 0:sub.ability_score_increases)!=null?_e:[]}function collectClassAsiBranch(resolved){var _a;const out={};for(const c of resolved.classes){for(const choice of Object.values(c.choices)){const alloc=legacyAsiBranch(choice);if(!alloc)continue;for(const ab of ABILITY_KEYS){const v=alloc[ab];if(typeof v==="number")out[ab]=((_a=out[ab])!=null?_a:0)+v}}}return out}function abilityBonusBreakdown(resolved,featureEffects){var _a,_b,_c,_d,_e,_f,_g;const species=speciesIncreaseTotals(resolved);const suppressed=speciesIncreaseRule(resolved).suppressed;const origin=collectChosenAbilityPoints(resolved);const classAsi=collectClassAsiBranch(resolved);const featPoints=collectClassFeatAbilityPoints(resolved);const out={};for(const ab of ABILITY_KEYS){let feat=(_a=featPoints[ab])!=null?_a:0;for(const f of resolved.feats){const bonus=(_b=f.ability_bonuses)==null?void 0:_b[ab];if(typeof bonus==="number")feat+=bonus;feat+=(_c=fixedFeatAbilityIncrease(f)[ab])!=null?_c:0}const sp=(_d=species[ab])!=null?_d:0;out[ab]={species:suppressed?0:sp,speciesNotUsed:suppressed?sp:0,background:(_e=origin.background[ab])!=null?_e:0,class:((_f=classAsi[ab])!=null?_f:0)+((_g=featureEffects==null?void 0:featureEffects.ability_bonus[ab])!=null?_g:0),feat}}return out}function speciesIncreaseTotals(resolved){var _a,_b;const out={...flattenRaceAsi(resolved.race)};for(const asi of subraceAsi(resolved)){if(asi.ability&&typeof asi.amount==="number")out[asi.ability]=((_a=out[asi.ability])!=null?_a:0)+asi.amount}const picked=collectChosenAbilityPoints(resolved).race;for(const ab of ABILITY_KEYS){const v=picked[ab];if(typeof v==="number")out[ab]=((_b=out[ab])!=null?_b:0)+v}return out}function fixedFeatAbilityIncrease(f){var _a;const g=f.grants_asi;if(!g||typeof g.amount!=="number"||g.amount<=0||!Array.isArray(g.pool)||g.pool.length!==1)return{};if(((_a=f.choices)!=null?_a:[]).some(c=>c.kind==="ability-points"))return{};const ab=g.pool[0];return ABILITY_KEYS.includes(ab)?{[ab]:g.amount}:{}}function hitDiceAverageSum(classes){var _a;let total=0;let firstLevelCounted=false;for(const c of classes){const die=parseDieSize((_a=c.entity)==null?void 0:_a.hit_die);if(!c.entity||die==null||c.level<1)continue;for(let lvl=1;lvl<=c.level;lvl++){if(!firstLevelCounted){total+=die;firstLevelCounted=true}else{total+=Math.floor(die/2)+1}}}return total}function hpLevelCount(classes){var _a;let count=0;for(const c of classes){const die=parseDieSize((_a=c.entity)==null?void 0:_a.hit_die);if(!c.entity||die==null||c.level<1)continue;count+=c.level}return count}function multiclassMaxHP(classes,conMod){return Math.max(1,hitDiceAverageSum(classes)+conMod*hpLevelCount(classes))}function resolveDamageRider(rider,rowDamageType,bindings){const{owner,scope:_scope,...rest}=rider;const out={...rest,amount:resolveAmountText(rider.amount,bindings(owner))};if(rider.damage_type!==void 0&&!isChosenDamageType(rider.damage_type)){const resolved=isCanonicalDamageType(rider.damage_type)?rider.damage_type:rowDamageType;if(resolved)out.damage_type=resolved;else delete out.damage_type}return out}function riderReachesRow(rider,row,opts){return scopeReachesRow(rider.scope,row,opts)}function scopeReachesRow(scope,row,opts){if(!(scope==null?void 0:scope.length))return true;const unarmedStrike=row.unarmed===true||row.naturalWeapon===true;return scope.some(word=>{switch(word){case"weapon":return!unarmedStrike;case"pact-weapon":return(opts==null?void 0:opts.pactPicked)===true?row.pactWeapon===true:!unarmedStrike;case"unarmed":return unarmedStrike;case"melee":case"ranged":return row.weaponCategory===word;case"finesse":case"thrown":case"heavy":return row.properties.includes(word)}})}function unarmoredAC(resolved,mods,warnings){return unarmoredACBreakdown(resolved,mods,warnings).total}function unarmoredACBreakdown(resolved,mods,warnings,shieldBonus=0){var _a,_b,_c,_d,_e,_f;const baseTerms=[{source:"Unarmored",amount:10,kind:"unarmored"},{source:"DEX modifier",amount:mods.dex,kind:"dex"}];const{activeBuffs}=assembleEffectFeatures(resolved);const candidates=[{total:10+mods.dex,terms:baseTerms,shieldAllowed:true}];for(const rf of[...resolved.features,...(_a=resolved.itemFeatures)!=null?_a:[]]){if(!foldsNow(rf,activeBuffs))continue;for(const eff of selfEffectsOf(rf.feature)){if(eff.kind!=="unarmored-ac")continue;const base=(_b=eff.base)!=null?_b:10;const terms=[{source:"Unarmored",amount:base,kind:"unarmored"}];let total=base;for(const ab of eff.abilities){terms.push(ab==="dex"?{source:"DEX modifier",amount:mods.dex,kind:"dex"}:{source:`${ab.toUpperCase()} modifier (${(_c=rf.feature.name)!=null?_c:"Unarmored"})`,amount:mods[ab],kind:"ability"});total+=mods[ab]}candidates.push({total,terms,shieldAllowed:eff.allow_shield===true})}}if(candidates.length>1){const applied=c=>c.total+(c.shieldAllowed?shieldBonus:0);let best=candidates[0];for(const c of candidates)if(applied(c)>applied(best))best=c;return best}for(const rf of resolved.features){const feat=rf.feature;if((_d=feat.unarmored_defense)==null?void 0:_d.ability){const ab=feat.unarmored_defense.ability;const amt=(_e=mods[ab])!=null?_e:0;const terms=[...baseTerms,{source:`${ab.toUpperCase()} modifier (Unarmored Defense)`,amount:amt,kind:"ability"}];return{total:10+mods.dex+amt,terms,shieldAllowed:true}}}for(const rf of resolved.features){const name=((_f=rf.feature.name)!=null?_f:"").toLowerCase();if(!/unarmored\s*defense/.test(name))continue;if(rf.source.kind==="class"&&rf.source.slug.includes("monk")){const terms=[...baseTerms,{source:"WIS modifier (Unarmored Defense)",amount:mods.wis,kind:"ability"}];return{total:10+mods.dex+mods.wis,terms,shieldAllowed:true}}if(rf.source.kind==="class"&&rf.source.slug.includes("barbarian")){const terms=[...baseTerms,{source:"CON modifier (Unarmored Defense)",amount:mods.con,kind:"ability"}];return{total:10+mods.dex+mods.con,terms,shieldAllowed:true}}}return{total:10+mods.dex,terms:baseTerms,shieldAllowed:true}}function resolveUnarmedStrike(resolved){var _a,_b,_c;const dice=[];const abilities=new Set;const classOf=rf=>rf.source.kind==="class"?resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===rf.source.slug}):void 0;const readDie=(rf,d)=>{var _a2,_b2;if(typeof d==="string")return d;if(!d)return void 0;const cls=classOf(rf);return cls?(_b2=diceColumnAt((_a2=cls.entity)==null?void 0:_a2.table,cls.level,d.column))!=null?_b2:void 0:void 0};for(const rf of resolved.features){const authored=selfEffectsOf(rf.feature).filter(e=>e.kind==="unarmed-strike");for(const e of authored){const d2=readDie(rf,e.dice);if(d2)dice.push(d2);for(const ab of(_a=e.abilities)!=null?_a:[])abilities.add(ab)}if(authored.length||rf.source.kind!=="class")continue;const slug=((_c=(_b=rf.feature.id)!=null?_b:rf.feature.name)!=null?_c:"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"");const column=unarmedDieColumnFor(slug);if(!column)continue;const d=readDie(rf,{column});if(!d)continue;dice.push(d);abilities.add("dex")}const avg=d=>{const m=/^(\d+)d(\d+)$/i.exec(d);return m?Number(m[1])*(Number(m[2])+1)/2:1};const best=dice.sort((a,b)=>avg(b)-avg(a))[0];return{...best?{dice:best}:{},...abilities.size?{abilities:[...abilities]}:{}}}function initiativeBonus(dexMod,feats,edition){var _a,_b,_c;let bonus=dexMod;for(const f of feats){const featEdition=(_a=f.edition)!=null?_a:edition;const hasData=((_b=f.effects)!=null?_b:[]).some(e=>e.kind==="initiative-bonus");if(bareEntitySlug((_c=f.slug)!=null?_c:"")==="alert"&&featEdition==="2014"&&!hasData)bonus+=5;const initBonus=f.initiative_bonus;if(typeof initBonus==="number")bonus+=initBonus}return bonus}function speedFromRace(resolved){var _a,_b,_c;const base=(_c=(_b=(_a=resolved.race)==null?void 0:_a.speed)==null?void 0:_b.walk)!=null?_c:30;let extra=0;for(const f of resolved.feats){const bonus=f.speed_bonus;if(typeof bonus==="number")extra+=bonus}return base+extra}function collectClassFeatAbilityPoints(resolved){var _a;const out={};for(const t of classFeatAbilityPointTerms(resolved))out[t.ability]=((_a=out[t.ability])!=null?_a:0)+t.amount;return out}function classFeatAbilityPointTerms(resolved){var _a;const out=[];const stripRef=ref=>ref.replace(/^\[\[/,"").replace(/\]\]$/,"");const featBySlug=new Map;for(const f of resolved.feats)featBySlug.set(f.slug,f);const sites=featPickSites(resolved.classes,poolMemberSitesOf(resolved),ci=>{var _a2,_b,_c,_d;return(_d=(_c=(_b=(_a2=resolved.classes)==null?void 0:_a2[ci])==null?void 0:_b.entity)==null?void 0:_c.slug)!=null?_d:null});for(const site of sites){{const feat=featBySlug.get(stripRef(site.slug));if(!feat)continue;for(const ch of(_a=feat.choices)!=null?_a:[]){if(ch.kind!=="ability-points")continue;const raw=site.read(ch.id);if(!raw||typeof raw!=="object"||Array.isArray(raw))continue;let left=ch.points;for(const ab of ABILITY_KEYS){if(ch.pool&&!ch.pool.includes(ab))continue;const v=raw[ab];if(typeof v!=="number"||v<=0||left<=0)continue;const take=Math.min(v,ch.max_per,left);out.push({feat,ability:ab,amount:take});left-=take}}}}return out}function computeAbilityScores(resolved,overrides){var _a,_b,_c,_d,_e,_f;const out={...resolved.definition.abilities};if(!speciesIncreaseRule(resolved).suppressed){const species=speciesIncreaseTotals(resolved);for(const ab of ABILITY_KEYS){const b=species[ab];if(typeof b==="number")out[ab]=((_a=out[ab])!=null?_a:0)+b}}const originPoints=collectChosenAbilityPoints(resolved);for(const ab of ABILITY_KEYS){const v=originPoints.background[ab];if(typeof v==="number")out[ab]=((_b=out[ab])!=null?_b:0)+v}const classAsi=collectClassAsiBranch(resolved);for(const ab of ABILITY_KEYS){const v=classAsi[ab];if(typeof v==="number")out[ab]=((_c=out[ab])!=null?_c:0)+v}const featPoints=collectClassFeatAbilityPoints(resolved);for(const ab of ABILITY_KEYS){const v=featPoints[ab];if(typeof v==="number")out[ab]=((_d=out[ab])!=null?_d:0)+v}for(const f of resolved.feats){const bonuses=f.ability_bonuses;if(bonuses){for(const ab of ABILITY_KEYS){const v=bonuses[ab];if(typeof v==="number")out[ab]=((_e=out[ab])!=null?_e:0)+v}}for(const[ab,v]of Object.entries(fixedFeatAbilityIncrease(f)))out[ab]=((_f=out[ab])!=null?_f:0)+v}if(overrides.scores){for(const ab of ABILITY_KEYS){const v=overrides.scores[ab];if(typeof v==="number")out[ab]=v}}for(const ab of ABILITY_KEYS){if(typeof out[ab]!=="number")out[ab]=10}return out}function abilityScoreBreakdowns(resolved,overrides,applied,featureEffects,scores){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n;const suppressed=speciesIncreaseRule(resolved).suppressed;const species=speciesIncreaseTotals(resolved);const origin=collectChosenAbilityPoints(resolved);const classAsi=collectClassAsiBranch(resolved);const featTerms=classFeatAbilityPointTerms(resolved);const out={};for(const ab of ABILITY_KEYS){const base=(_a=resolved.definition.abilities)==null?void 0:_a[ab];const terms=[{source:"Base score",amount:typeof base==="number"?base:10}];const add=(source,amount,notUsed=false)=>{if(!amount)return;const prior=terms.find((t,i)=>i>0&&t.source===source&&t.notUsed===true===notUsed);if(prior)prior.amount+=amount;else terms.push(notUsed?{source,amount,notUsed:true}:{source,amount})};add((_c=(_b=resolved.race)==null?void 0:_b.name)!=null?_c:"Species",(_d=species[ab])!=null?_d:0,suppressed);add((_f=(_e=resolved.background)==null?void 0:_e.name)!=null?_f:"Background",(_g=origin.background[ab])!=null?_g:0);add("Ability Score Improvement",(_h=classAsi[ab])!=null?_h:0);for(const t of featTerms)if(t.ability===ab)add(t.feat.name,t.amount);for(const f of resolved.feats){const bonus=(_i=f.ability_bonuses)==null?void 0:_i[ab];if(typeof bonus==="number")add(f.name,bonus);add(f.name,(_j=fixedFeatAbilityIncrease(f)[ab])!=null?_j:0)}for(const t of(_k=applied.ability_terms)!=null?_k:[])if(t.ability===ab)add(t.source,t.amount);for(const t of(_l=featureEffects.ability_bonus_terms)!=null?_l:[])if(t.ability===ab)add(t.source,t.amount);const sum=terms.reduce((n,t)=>n+(t.notUsed?0:t.amount),0);const b={total:scores[ab],terms};let best;for(const t of(_m=applied.ability_static_terms)!=null?_m:[])if(t.ability===ab&&(!best||t.value>best.value))best={source:t.source,value:t.value};if(best&&best.value>sum)b.set=best;const o=(_n=overrides.scores)==null?void 0:_n[ab];if(typeof o==="number")b.override=o;out[ab]=b}return out}function normalizeArmorProf(input){var _a,_b;if(!input)return{categories:[],specific:[]};if(Array.isArray(input))return{categories:input,specific:[]};return{categories:(_a=input.categories)!=null?_a:[],specific:(_b=input.specific)!=null?_b:[]}}function normalizeWeaponToolProf(input){var _a,_b,_c;if(!input)return{categories:[],specific:[]};if(Array.isArray(input))return{categories:[],specific:input};return{categories:(_a=input.categories)!=null?_a:[],specific:((_b=input.fixed)!=null?_b:[]).concat((_c=input.specific)!=null?_c:[])}}function mergeInto(target,source){for(const c of source.categories)if(!target.categories.includes(c))target.categories.push(c);for(const s of source.specific)if(!target.specific.includes(s))target.specific.push(s)}function applyArmorWeaponOverrides(profs,overrides){var _a,_b;for(const kind of["armor","weapons"]){const ov=overrides==null?void 0:overrides[kind];if(!ov)continue;const set=profs[kind];const key=v=>proficiencyKey(kind,v);const removes=new Set(((_a=ov.remove)!=null?_a:[]).map(key));for(const v of(_b=ov.add)!=null?_b:[]){const k=key(v);if(removes.has(k))continue;const category=kind==="armor"||k==="simple"||k==="martial";const target=category?set.categories:set.specific;if(!target.some(e=>key(e)===k))target.push(category?k:v)}set.categories=set.categories.filter(e=>!removes.has(key(e)));set.specific=set.specific.filter(e=>!removes.has(key(e)))}}var ORIGIN_RANK={manual:0,equipment:1,grant:2};function composeDefenseEntries(manual,equipment,grants){const byValue=new Map;for(const raw of manual){const value=toDefenseSlug(raw);if(!value||byValue.has(value))continue;byValue.set(value,{value,label:raw.trim(),origin:"manual"})}const consider=(list,origin)=>{var _a,_b,_c,_d;for(const g of list){const value=toDefenseSlug(g.value);if(!value)continue;const existing=byValue.get(value);if(!existing){byValue.set(value,{value,label:g.value.trim(),origin,sources:[...g.sources],...g.condition?{condition:g.condition}:{},...((_a=g.items)==null?void 0:_a.length)?{items:g.items.map(it=>({...it}))}:{}});continue}if(ORIGIN_RANK[origin]>ORIGIN_RANK[existing.origin])existing.origin=origin;const sources=(_b=existing.sources)!=null?_b:existing.sources=[];for(const src of g.sources)if(!sources.includes(src))sources.push(src);if(!existing.condition&&g.condition)existing.condition=g.condition;if((_c=g.items)==null?void 0:_c.length)mergeDefenseItems((_d=existing.items)!=null?_d:existing.items=[],g.items)}};consider(equipment,"equipment");consider(grants,"grant");return[...byValue.values()]}function suppress(resolved,bucket,entries){var _a,_b,_c,_d,_e;const suppressed=new Set(((_e=(_d=(_c=(_b=(_a=resolved.definition)==null?void 0:_a.overrides)==null?void 0:_b.defenses)==null?void 0:_c[bucket])==null?void 0:_d.remove)!=null?_e:[]).map(toDefenseSlug));return entries.filter(e=>!suppressed.has(e.value))}function computeProficiencies(resolved){var _a,_b,_c,_d,_e,_f,_g;const armor={categories:[],specific:[]};const weapons={categories:[],specific:[]};const tools={categories:[],specific:[]};const languages=new Set;for(const c of resolved.classes){const p=(_a=c.entity)==null?void 0:_a.proficiencies;if(!p)continue;mergeInto(armor,normalizeArmorProf(p.armor));mergeInto(weapons,normalizeWeaponToolProf(p.weapons));mergeInto(tools,normalizeWeaponToolProf(p.tools));(_b=p.languages)==null?void 0:_b.forEach(l=>languages.add(l))}const racePr=(_c=resolved.race)==null?void 0:_c.proficiencies;if(racePr){mergeInto(armor,normalizeArmorProf(racePr.armor));mergeInto(weapons,normalizeWeaponToolProf(racePr.weapons));mergeInto(tools,normalizeWeaponToolProf(racePr.tools));(_d=racePr.languages)==null?void 0:_d.forEach(l=>languages.add(l))}const bgPr=(_e=resolved.background)==null?void 0:_e.proficiencies;if(bgPr){mergeInto(armor,normalizeArmorProf(bgPr.armor));mergeInto(weapons,normalizeWeaponToolProf(bgPr.weapons));mergeInto(tools,normalizeWeaponToolProf(bgPr.tools));(_f=bgPr.languages)==null?void 0:_f.forEach(l=>languages.add(l))}for(const f of resolved.feats){const grants=f.grants_proficiency;if(!grants)continue;mergeInto(armor,normalizeArmorProf(grants.armor));mergeInto(weapons,normalizeWeaponToolProf(grants.weapons));mergeInto(tools,normalizeWeaponToolProf(grants.tools));(_g=grants.languages)==null?void 0:_g.forEach(l=>languages.add(l))}return{armor,weapons,tools,languages:Array.from(languages).sort(),saves:[]}}var HAND_SET_HALF_SOURCE="Set by you";function recalc(resolved,registry){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_s,_t,_u,_v,_w,_x,_y,_z,_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P,_Q,_R,_S,_T,_U,_V,_W,_X,_Y,_Z,__,_$,_aa,_ba;const warnings=[];const overrides=(_a=resolved.definition.overrides)!=null?_a:{};const chosenProfs=collectChosenProficiencies(resolved);const{features:effectFeatures,activeBuffs}=assembleEffectFeatures(resolved);const tableDiceFor=(src,column,level)=>{var _a2;const cls=src.kind==="class"?resolved.classes.find(c=>{var _a3;return((_a3=c.entity)==null?void 0:_a3.slug)===src.slug}):src.kind==="subclass"?resolved.classes.find(c=>{var _a3;return((_a3=c.subclass)==null?void 0:_a3.slug)===src.slug}):void 0;return cls?diceColumnAt((_a2=cls.entity)==null?void 0:_a2.table,level,column):null};const tableCellFor=(src,column)=>{var _a2;const slug=ownerClassSlug(src,resolved);const cls=slug?resolved.classes.find(c=>{var _a3;return((_a3=c.entity)==null?void 0:_a3.slug)===slug}):void 0;return cls?tableCellAt((_a2=cls.entity)==null?void 0:_a2.table,cls.level,column):null};const featureEffects=computeFeatureEffects(effectFeatures,{activeBuffs,levelFor:src=>resourceLevelFor(src,resolved),tableDiceFor,tableCellFor});const profsForApply=computeProficiencies(resolved);for(const t of chosenProfs.tools){if(!profsForApply.tools.specific.includes(t))profsForApply.tools.specific.push(t)}for(const l of chosenProfs.languages){if(!profsForApply.languages.includes(l))profsForApply.languages.push(l)}for(const w of chosenProfs.weapons){if(!profsForApply.weapons.specific.includes(w))profsForApply.weapons.specific.push(w)}for(const t of featureEffects.proficiencies.tools){if(!profsForApply.tools.specific.includes(t))profsForApply.tools.specific.push(t)}for(const l of featureEffects.proficiencies.languages){if(!profsForApply.languages.includes(l))profsForApply.languages.push(l)}for(const a of featureEffects.proficiencies.armor){if(!profsForApply.armor.categories.includes(a))profsForApply.armor.categories.push(a)}for(const w of featureEffects.proficiencies.weapons){if(!profsForApply.weapons.categories.includes(w))profsForApply.weapons.categories.push(w);if(!WEAPON_CATEGORY_WORDS.has(w)&&!profsForApply.weapons.specific.includes(w)){profsForApply.weapons.specific.push(w)}}profsForApply.languages.sort();applyArmorWeaponOverrides(profsForApply,(_b=resolved.definition)==null?void 0:_b.overrides);const applied=registry?computeAppliedBonuses(resolved,profsForApply,registry,warnings):emptyAppliedBonuses();const savesInformational=applied.informational.filter(i=>i.field==="saving_throws");const spellcastingInformational=applied.informational.filter(i=>i.field==="spell_attack"||i.field==="spell_save_dc");const speedInformational=applied.informational.filter(i=>i.field.startsWith("speed."));const baseScores=computeAbilityScores(resolved,overrides);const scores={...baseScores};for(const ab of ABILITY_KEYS){const bonus=applied.ability_bonuses[ab];scores[ab]+=(typeof bonus==="number"?bonus:0)+((_c=featureEffects.ability_bonus[ab])!=null?_c:0)}for(const ab of ABILITY_KEYS){const stat=applied.ability_statics[ab];if(typeof stat==="number"&&stat>scores[ab])scores[ab]=stat}if(overrides.scores){for(const ab of ABILITY_KEYS){const o=overrides.scores[ab];if(typeof o==="number")scores[ab]=o}}const mods={str:abilityModifier(scores.str),dex:abilityModifier(scores.dex),con:abilityModifier(scores.con),int:abilityModifier(scores.int),wis:abilityModifier(scores.wis),cha:abilityModifier(scores.cha)};const totalLevel=resolved.classes.reduce((s,c)=>s+c.level,0);const proficiencyBonus=proficiencyFromLevel(totalLevel||1);const conditionEffects=computeConditionEffects(resolved.state,resolved.definition.edition,scores);const firstClass=(_e=(_d=resolved.classes[0])==null?void 0:_d.entity)!=null?_e:null;const saveProfs=new Set((_f=firstClass==null?void 0:firstClass.saving_throws)!=null?_f:[]);for(const ab of featureEffects.proficiencies.saves)saveProfs.add(ab);for(const ab of chosenProfs.saves)saveProfs.add(ab);const saves={};const saveBreakdowns={};const activeSaveBonusTerms=featureEffects.save_bonus_terms.filter(t=>{var _a2;return t.inactiveWhile==="incapacitated"?!conditionEffects.actions_disabled:t.inactiveWhile==="unconscious"?!((_a2=resolved.state.conditions)!=null?_a2:[]).includes("unconscious"):true});for(const ab of ABILITY_KEYS){const override=(_g=overrides.saves)==null?void 0:_g[ab];const prof=(_h=override==null?void 0:override.proficient)!=null?_h:saveProfs.has(ab);const featureTerms=[];for(const t of activeSaveBonusTerms){if(t.saves.length>0&&!t.saves.includes(ab))continue;const amount=Math.max(t.minimum,mods[t.ability]);const prior=featureTerms.find(x=>x.source===t.label);if(prior===void 0)featureTerms.push({source:t.label,amount});else if(amount>prior.amount)prior.amount=amount}const derivedBonus=savingThrow(scores[ab],prof,proficiencyBonus)+applied.save_bonus+featureTerms.reduce((sum,t)=>sum+t.amount,0)+conditionEffects.d20_test_penalty;const bonus=(_i=override==null?void 0:override.bonus)!=null?_i:derivedBonus;saves[ab]={bonus,proficient:prof};saveBreakdowns[ab]=[{source:ab.toUpperCase(),amount:mods[ab]},...prof?[{source:"Proficiency",amount:proficiencyBonus}]:[],...applied.save_terms.map(t=>({...t})),...featureTerms,...conditionEffects.d20_test_penalty?[{source:`Exhaustion ${conditionEffects.exhaustion_level}`,amount:conditionEffects.d20_test_penalty}]:[]]}const profSet=new Set([...resolved.definition.skills.proficient,...(_k=(_j=resolved.background)==null?void 0:_j.skill_proficiencies)!=null?_k:[],...chosenProfs.skills,...featureEffects.proficiencies.skills]);const expSet=new Set([...resolved.definition.skills.expertise,...chosenProfs.expertise,...featureEffects.proficiencies.skillExpertise]);const skills={};const skillBreakdowns={};for(const skill of ALL_SKILLS){const skillKey=skillSlugFromDisplay(skill);const ab=SKILL_ABILITY[skillSlugToAbilityLookup(skillKey)];const override=(_l=overrides.skills)==null?void 0:_l[skillKey];const tri=(_m=override==null?void 0:override.proficiency)!=null?_m:expSet.has(skillKey)?"expertise":profSet.has(skillKey)?"proficient":"none";const skillTerms=featureEffects.skill_bonus_terms.filter(t=>t.skills.includes(skillKey)).map(t=>({source:t.label,amount:Math.max(t.minimum,mods[t.ability])}));const halfProfTerms=tri!=="none"?[]:[...featureEffects.half_proficiency_terms.filter(t=>t.skills.length===0||t.skills.includes(skillKey)).map(t=>({source:t.label,amount:t.round==="up"?Math.ceil(proficiencyBonus/2):Math.floor(proficiencyBonus/2)})),...((_n=resolved.definition.skills.half)==null?void 0:_n.includes(skillKey))?[{source:HAND_SET_HALF_SOURCE,amount:Math.floor(proficiencyBonus/2)}]:[]];const halfProfBest=halfProfTerms.length?halfProfTerms.reduce((best,t)=>t.amount>best.amount?t:best):null;const bonus=(_p=override==null?void 0:override.bonus)!=null?_p:skillBonus(scores[ab],tri,proficiencyBonus)+skillTerms.reduce((sum,t)=>sum+t.amount,0)+((_o=halfProfBest==null?void 0:halfProfBest.amount)!=null?_o:0)+conditionEffects.d20_test_penalty;skillBreakdowns[skillKey]=[{source:ab.toUpperCase(),amount:mods[ab]},...tri!=="none"?[{source:tri==="expertise"?"Expertise":"Proficiency",amount:proficiencyBonus*(tri==="expertise"?2:1)}]:[],...skillTerms,...halfProfBest?[halfProfBest]:[],...conditionEffects.d20_test_penalty?[{source:"Conditions",amount:conditionEffects.d20_test_penalty}]:[]];skills[skillKey]={bonus,proficiency:tri,ability:ab,...halfProfBest?{halfProficiency:{source:halfProfBest.source,amount:halfProfBest.amount}}:{}}}const passives={perception:(_r=(_q=overrides.passives)==null?void 0:_q.perception)!=null?_r:10+skills.perception.bonus,investigation:(_t=(_s=overrides.passives)==null?void 0:_s.investigation)!=null?_t:10+skills.investigation.bonus,insight:(_v=(_u=overrides.passives)==null?void 0:_u.insight)!=null?_v:10+skills.insight.bonus};const hpRolled=(_x=(_w=overrides.hp)==null?void 0:_w.rolled)!=null?_x:null;const hpModifier=(_z=(_y=overrides.hp)==null?void 0:_y.modifier)!=null?_z:null;const averageDiceSum=hitDiceAverageSum(resolved.classes);const conLevels=hpLevelCount(resolved.classes);const diceSum=hpRolled!=null?hpRolled:averageDiceSum;const diceConRaw=diceSum+mods.con*conLevels;const diceConClamped=Math.max(1,diceConRaw);const hpMaxDerived=diceConClamped+featureEffects.hp_per_level_bonus*totalLevel+(hpModifier!=null?hpModifier:0);const hpMaxAfterConditions=Math.max(0,Math.floor(hpMaxDerived*conditionEffects.hp_max_multiplier));const hpMax=(_B=(_A=overrides.hp)==null?void 0:_A.max)!=null?_B:hpMaxAfterConditions;const hpBreakdown={diceSum,diceSource:hpRolled!=null?"rolled":"average",averageDiceSum,conMod:mods.con,conLevels,clampApplied:diceConClamped!==diceConRaw,perLevelTerms:featureEffects.hp_per_level_terms.map(t=>({label:t.label,perLevel:t.value,levels:totalLevel,total:t.value*totalLevel})),modifier:hpModifier,exhaustionMultiplier:conditionEffects.hp_max_multiplier,exhaustionLevel:conditionEffects.exhaustion_level,derivedMax:hpMaxAfterConditions,override:(_D=(_C=overrides.hp)==null?void 0:_C.max)!=null?_D:null,final:hpMax};const featureAcTermsFor=hasArmor=>featureEffects.ac_terms.filter(t=>!t.requires_armor||hasArmor).map(t=>({source:t.label,amount:t.value,kind:"feature",condition:t.condition}));const sumTerms=terms=>terms.reduce((s,t)=>s+t.amount,0);const weaponAbilities=[...featureEffects.weaponAbilities];const wantsSpellcasting=resolved.features.some(rf=>selfEffectsOf(rf.feature).some(e=>e.kind==="weapon-ability"&&e.ability==="spellcasting"));if(wantsSpellcasting){let primaryCasterAbility=null;for(const c of resolved.classes){if(!c.entity)continue;const profile=resolveSpellcasting(c);if(profile){primaryCasterAbility=effectiveSpellcastingAbility(c.entity.slug,profile.ability,overrides);break}}if(primaryCasterAbility)weaponAbilities.unshift({ability:primaryCasterAbility})}let derivedEquipment=null;let acDerived;let acBreakdownDerived=[];let acInformationalDerived=[];if(registry){derivedEquipment=computeSlotsAndAttacks(resolved,mods,profsForApply,registry,warnings,proficiencyBonus,weaponAbilities,(_E=resolved.weaponMasteries)!=null?_E:[],featureEffects.attunement_set);if(derivedEquipment.equippedSlots.armor){const featTerms=featureAcTermsFor(true);acDerived=derivedEquipment.ac+sumTerms(featTerms);acBreakdownDerived=[...derivedEquipment.acBreakdown,...featTerms];acInformationalDerived=derivedEquipment.acInformational}else{const shieldBonus=derivedEquipment.acBreakdown.filter(b=>b.kind==="shield").reduce((sum,b)=>sum+b.amount,0);const{total:unarmored,terms:unarmoredTerms,shieldAllowed}=unarmoredACBreakdown(resolved,mods,warnings,shieldBonus);const additive=derivedEquipment.acBreakdown.filter(b=>b.kind==="item"||b.kind==="override"||b.kind==="shield"&&shieldAllowed);const featTerms=featureAcTermsFor(false);const additiveSum=additive.reduce((sum,b)=>sum+b.amount,0);acDerived=unarmored+additiveSum+sumTerms(featTerms);acBreakdownDerived=[...unarmoredTerms,...additive,...featTerms];acInformationalDerived=derivedEquipment.acInformational}}else{const{total,terms}=unarmoredACBreakdown(resolved,mods,warnings);const featTerms=featureAcTermsFor(false);acDerived=total+sumTerms(featTerms);acBreakdownDerived=[...terms,...featTerms]}const ac=(_F=overrides.ac)!=null?_F:acDerived;const worn=wornArmor(derivedEquipment==null?void 0:derivedEquipment.equippedSlots,registry);const featureSpeedTerms=featureEffects.speed_terms.filter(t=>speedTermActive(t,worn));const gatedWalk=featureSpeedTerms.filter(t=>t.mode==="walk"&&t.inactiveWhile!==void 0);const featureWalkBonus=featureEffects.speed_walk_bonus+gatedWalk.filter(t=>!t.set).reduce((sum,t)=>sum+t.value,0);const featureWalkFloor=Math.max(featureEffects.speed_walk_set,...gatedWalk.filter(t=>t.set).map(t=>t.value));const armorPenalty=armorStrengthPenalty(worn,scores.str,featureEffects.ignore_armor_strength);const additiveSpeed=speedFromRace(resolved)+applied.speed_bonuses.walk+featureWalkBonus+((_G=armorPenalty==null?void 0:armorPenalty.amount)!=null?_G:0);const baseSpeed=Math.max(featureWalkFloor,applied.speed_walk_set,additiveSpeed);const adjustedSpeed=baseSpeed*conditionEffects.speed_multiplier-conditionEffects.speed_reduction_ft;const conditionSpeed=conditionEffects.speed_floor_zero?0:Math.max(0,Math.floor(adjustedSpeed));const speed=(_H=overrides.speed)!=null?_H:conditionSpeed;const raceSpeed=(_K=(_J=(_I=resolved.race)==null?void 0:_I.speed)==null?void 0:_J.walk)!=null?_K:30;const speeds=buildSpeedLines({resolved,applied,features:{speed_terms:featureSpeedTerms,speed_walk_set:featureWalkFloor},conditions:conditionEffects,conditionNames:speedConditionNames(resolved.state,resolved.definition.edition),walk:{race:raceSpeed,additive:additiveSpeed,base:baseSpeed,final:conditionSpeed},armorPenalty:armorPenalty?{term:armorPenalty,everyMode:resolved.definition.edition==="2024"}:null});const speedBreakdown=speeds[0].terms;if(!resolved.race)warnings.push("No race resolved; speed defaulted to 30.");const initiativeAmountTerms=featureEffects.initiative_amount_terms.flatMap(term2=>{const text=resolveAmountText(term2.amount,amountBindingsFor(term2.owner,resolved,{proficiencyBonus,mods,spellcastingClasses:[]}));const n=Number(text);if(!Number.isInteger(n)){warnings.push(`${term2.label}: initiative amount "${term2.amount}" is not a number; nothing added.`);return[]}return[{source:term2.label,amount:n}]});const init=(_L=overrides.initiative)!=null?_L:initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)+featureEffects.initiative_bonus+initiativeAmountTerms.reduce((s,t)=>s+t.amount,0);const initiativeBreakdown=[{source:"DEX",amount:mods.dex},...initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)!==mods.dex?[{source:"Feats",amount:initiativeBonus(mods.dex,resolved.feats,resolved.definition.edition)-mods.dex}]:[],...featureEffects.initiative_terms.map(term2=>({source:term2.label,amount:term2.value})),...initiativeAmountTerms];const senses={darkvision:Math.max((_O=(_N=(_M=resolved.race)==null?void 0:_M.vision)==null?void 0:_N.darkvision)!=null?_O:0,featureEffects.senses.darkvision,applied.senses.darkvision),blindsight:Math.max(featureEffects.senses.blindsight,applied.senses.blindsight),tremorsense:Math.max(featureEffects.senses.tremorsense,applied.senses.tremorsense),truesight:Math.max(featureEffects.senses.truesight,applied.senses.truesight)};const spellcastingClasses=[];const slotInputs=[];const limitInputs=[];for(const c of resolved.classes){if(!c.entity)continue;const profile=resolveSpellcasting(c);if(!profile)continue;const ab=effectiveSpellcastingAbility(c.entity.slug,profile.ability,overrides);const dc=saveDC(scores[ab],proficiencyBonus)+applied.spell_save_dc;const atk=attackBonus(scores[ab],proficiencyBonus)+applied.spell_attack;spellcastingClasses.push({classSlug:c.entity.slug,className:c.entity.name,ability:ab,defaultAbility:profile.ability,saveDC:dc,attackBonus:atk,casterType:profile.casterType,preparation:profile.preparation,spellList:profile.spellList});slotInputs.push({casterType:profile.casterType,level:c.level});limitInputs.push({classSlug:c.entity.slug,level:c.level,profile,abilityScore:scores[ab]})}const spellcasting=spellcastingClasses.length>0?{ability:spellcastingClasses[0].ability,saveDC:spellcastingClasses[0].saveDC,attackBonus:spellcastingClasses[0].attackBonus}:null;const abilitySpellcasting={};for(const s of resolved.spells){const ab=s.ability;if(!ab||abilitySpellcasting[ab])continue;abilitySpellcasting[ab]={saveDC:saveDC(scores[ab],proficiencyBonus)+applied.spell_save_dc,attackBonus:attackBonus(scores[ab],proficiencyBonus)+applied.spell_attack}}const derivedSlots=deriveSpellSlots(slotInputs);const spellLimits=computeSpellLimits(limitInputs);const defenses={resistances:suppress(resolved,"resistances",composeDefenseEntries((_Q=(_P=resolved.definition.defenses)==null?void 0:_P.resistances)!=null?_Q:[],applied.defenses.resistances,featureEffects.resistances)),immunities:suppress(resolved,"immunities",composeDefenseEntries((_S=(_R=resolved.definition.defenses)==null?void 0:_R.immunities)!=null?_S:[],applied.defenses.immunities,featureEffects.immunities)),vulnerabilities:suppress(resolved,"vulnerabilities",composeDefenseEntries((_U=(_T=resolved.definition.defenses)==null?void 0:_T.vulnerabilities)!=null?_U:[],applied.defenses.vulnerabilities,featureEffects.vulnerabilities)),condition_immunities:suppress(resolved,"condition_immunities",composeDefenseEntries((_W=(_V=resolved.definition.defenses)==null?void 0:_V.condition_immunities)!=null?_W:[],applied.defenses.condition_immunities,featureEffects.condition_immunities))};const unarmedSpec=resolveUnarmedStrike(resolved);const attackRows=[...(_X=derivedEquipment==null?void 0:derivedEquipment.attacks)!=null?_X:[],...buildFeatureAttackRows(resolved,mods,profsForApply,proficiencyBonus,weaponAbilities,{unarmedAbilities:unarmedSpec.abilities,activeBuffs}),buildUnarmedRow(mods,proficiencyBonus,unarmedSpec)];const scopeOpts={pactPicked:pactWeaponIndexes(resolved,registry)!==null};const riderBindings=owner=>amountBindingsFor(owner,resolved,{proficiencyBonus,mods,spellcastingClasses});const ownSpells=(_Y=resolved.spells)!=null?_Y:[];const spellDamageRiders=featureEffects.spellDamageBonuses.flatMap(r=>{const reached=new Set([...spellsReached(r.targets,ownSpells),...spellsInScope(r.scope,ownSpells,id=>pickedDamageTypes(resolved,id))]);const spells=[...new Set(ownSpells.map(s=>s.slug))].filter(slug=>reached.has(slug));if(!spells.length)return[];const{owner,targets:_targets,scope,damage_type,...rest}=r;return[{...rest,amount:resolveAmountText(r.amount,riderBindings(owner)),...damage_type&&isCanonicalDamageType(damage_type)?{damage_type}:{},...(scope==null?void 0:scope.once)?{once:true}:{},spells}]});const scopedExtra=featureEffects.scopedExtraAttacks;const rowExtra=attackRows.map(a=>{if(!scopedExtra.length)return void 0;let best={count:featureEffects.extraAttack,source:featureEffects.extraAttackSource};for(const x of scopedExtra)if(x.count>best.count&&scopeReachesRow(x.scope,a,scopeOpts))best={count:x.count,source:x.source};return{count:1+best.count,...best.count>0&&best.source?{source:best.source}:{}}});const rowAttacks=rowExtra.map(r=>r==null?void 0:r.count);return{totalLevel,proficiencyBonus,scores,mods,saves,proficiencies:profsForApply,skills,statBreakdowns:{skills:skillBreakdowns,saves:saveBreakdowns,speed:speedBreakdown,initiative:initiativeBreakdown,abilities:abilityScoreBreakdowns(resolved,overrides,applied,featureEffects,scores)},passives,senses,hp:{max:hpMax,current:resolved.state.hp.current,temp:resolved.state.hp.temp},hpBreakdown,ac,speed,speeds,initiative:init,spellcasting,spellcastingClasses,abilitySpellcasting,derivedSpellSlots:derivedSlots.standard,pactMagic:derivedSlots.pact,spellLimits,warnings,defenses,acBreakdown:acBreakdownDerived,acInformational:acInformationalDerived,savesInformational,spellcastingInformational,speedInformational,attacksPerAction:Math.max(1+featureEffects.extraAttack,...rowAttacks.filter(n=>n!==void 0)),...featureEffects.extraAttackSource?{extraAttackSource:featureEffects.extraAttackSource}:{},attacks:attackRows.map((a,i)=>{var _a2,_b2,_c2,_d2,_e2;const critRange=Math.min((_a2=a.critRange)!=null?_a2:20,featureEffects.critRange);const conditionalCrits=[...(_b2=a.conditionalCrits)!=null?_b2:[],...featureEffects.conditionalCrits].filter(c=>c.minRoll<critRange);const riders=[...(_c2=a.damageRiders)!=null?_c2:[],...featureEffects.damageBonuses.filter(r=>riderReachesRow(r,a,scopeOpts))].map(r=>resolveDamageRider(r,a.damageType,riderBindings));const rollOptions=featureEffects.damageRollOptions.filter(o=>scopeReachesRow(o.scope,a,scopeOpts)).map(({scope:_scope,...o})=>o);const{critRange:_ownCrit,conditionalCrits:_ownConditional,...row}=a;return{...row,toHit:a.toHit+conditionEffects.d20_test_penalty,...critRange<20?{critRange}:{},...conditionalCrits.length?{conditionalCrits}:{},...featureEffects.attackNotes.length?{attackNotes:featureEffects.attackNotes}:{},...riders.length?{damageRiders:riders}:{},...rollOptions.length?{damageRollOptions:rollOptions}:{},...rowAttacks[i]!==void 0?{attacksPerAction:rowAttacks[i]}:{},...((_d2=rowExtra[i])==null?void 0:_d2.source)?{extraAttackSource:(_e2=rowExtra[i])==null?void 0:_e2.source}:{}}}),...spellDamageRiders.length?{spellDamageRiders}:{},equippedSlots:(_Z=derivedEquipment==null?void 0:derivedEquipment.equippedSlots)!=null?_Z:{},carriedWeight:(__=derivedEquipment==null?void 0:derivedEquipment.carriedWeight)!=null?__:0,attunementUsed:(_$=derivedEquipment==null?void 0:derivedEquipment.attunementUsed)!=null?_$:0,attunementLimit:(_ba=derivedEquipment==null?void 0:derivedEquipment.attunementLimit)!=null?_ba:(_aa=overrides.attunement_limit)!=null?_aa:Math.max(3,featureEffects.attunement_set),conditionEffects,rollModifiers:featureEffects.rollModifiers,saveOutcomes:featureEffects.saveOutcomes}}export{HAND_SET_HALF_SOURCE,abilityBonusBreakdown,abilityScoreBreakdowns,collectClassAsiBranch,collectClassFeatAbilityPoints,computeAbilityScores,computeProficiencies,fixedFeatAbilityIncrease,flattenRaceAsi,hitDiceAverageSum,hpLevelCount,initiativeBonus,multiclassMaxHP,parseDieSize,phbAverageForDie,recalc,resolveUnarmedStrike,riderReachesRow,scopeReachesRow,speedFromRace,unarmoredAC,unarmoredACBreakdown};
@@ -1 +1 @@
1
- import{PCResolver,collectAdditionalFeatures,collectChosenGrantedFeatures,collectChosenWeaponMasteries,collectFeatChoiceGrants,collectFeatGrantedSpells,collectFeatPicks,collectItemGrantedSpells,collectResolvedFeatures,dedupeResolvedSpells,resolveOriginFeat,stripSlug}from"../chunk-FD2VQ3H6.js";import"../chunk-2EOGK6R6.js";import"../chunk-RQZCGXUZ.js";import"../chunk-BPXQOJES.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import"../chunk-VTQ4RWEG.js";import"../chunk-UWDHEIPY.js";import"../chunk-WAUNLUFQ.js";import"../chunk-CEHL7PPC.js";import"../chunk-UBUKCRZ3.js";import"../chunk-KEXSF3CH.js";import"../chunk-PFQPP77Q.js";import"../chunk-QVWT67WA.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{PCResolver,collectAdditionalFeatures,collectChosenGrantedFeatures,collectChosenWeaponMasteries,collectFeatChoiceGrants,collectFeatGrantedSpells,collectFeatPicks,collectItemGrantedSpells,collectResolvedFeatures,dedupeResolvedSpells,resolveOriginFeat,stripSlug};
1
+ import{PCResolver,collectAdditionalFeatures,collectChosenGrantedFeatures,collectChosenWeaponMasteries,collectFeatChoiceGrants,collectFeatGrantedSpells,collectFeatPicks,collectItemGrantedSpells,collectResolvedFeatures,dedupeResolvedSpells,resolveOriginFeat,stripSlug}from"../chunk-JSI2G6LE.js";import"../chunk-2EOGK6R6.js";import"../chunk-4AJYEWFQ.js";import"../chunk-RQZCGXUZ.js";import"../chunk-CLZRWPWT.js";import"../chunk-B2JSF2LL.js";import"../chunk-FOLHTMSC.js";import"../chunk-4JEF3CET.js";import"../chunk-VTQ4RWEG.js";import"../chunk-DXJ5NKKB.js";import"../chunk-J27N3KUE.js";import"../chunk-RR26E7LH.js";import"../chunk-UBUKCRZ3.js";import"../chunk-2OVDSMPY.js";import"../chunk-PFQPP77Q.js";import"../chunk-QVWT67WA.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-3LWOVRLA.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-3QQOATV3.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-4KVVAENP.js";import"../chunk-7EL3GWWJ.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";import"../chunk-S5UCI27C.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{PCResolver,collectAdditionalFeatures,collectChosenGrantedFeatures,collectChosenWeaponMasteries,collectFeatChoiceGrants,collectFeatGrantedSpells,collectFeatPicks,collectItemGrantedSpells,collectResolvedFeatures,dedupeResolvedSpells,resolveOriginFeat,stripSlug};
@@ -1 +1 @@
1
- import{resourceLevelFor}from"../chunk-KEXSF3CH.js";import"../chunk-PFQPP77Q.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import{numericColumnsAt}from"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";function resourceBindings(resolved,derived,source){var _a,_b,_c,_d;const classLevel=resourceLevelFor(source,resolved);let table;if(source.kind==="class")table=(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_a.entity)==null?void 0:_b.table;else if(source.kind==="subclass")table=(_d=(_c=resolved.classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_c.subclass)==null?void 0:_d.table;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:numericColumnsAt(table,classLevel)}}export{resourceBindings};
1
+ import{resourceLevelFor}from"../chunk-2OVDSMPY.js";import"../chunk-PFQPP77Q.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import{numericColumnsAt}from"../chunk-CSTAQQGX.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";function resourceBindings(resolved,derived,source){var _a,_b,_c,_d;const classLevel=resourceLevelFor(source,resolved);let table;if(source.kind==="class")table=(_b=(_a=resolved.classes.find(c=>{var _a2;return((_a2=c.entity)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_a.entity)==null?void 0:_b.table;else if(source.kind==="subclass")table=(_d=(_c=resolved.classes.find(c=>{var _a2;return((_a2=c.subclass)==null?void 0:_a2.slug)===source.slug}))==null?void 0:_c.subclass)==null?void 0:_d.table;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:numericColumnsAt(table,classLevel)}}export{resourceBindings};
@@ -1 +1 @@
1
- import{pickResourceId,poolSaveDC,resolveFeatureResources,resolveRecovery,resolveResourceIndex,resourceLevelFor}from"../chunk-KEXSF3CH.js";import"../chunk-PFQPP77Q.js";import"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{pickResourceId,poolSaveDC,resolveFeatureResources,resolveRecovery,resolveResourceIndex,resourceLevelFor};
1
+ import{pickResourceId,poolSaveDC,resolveFeatureResources,resolveRecovery,resolveResourceIndex,resourceLevelFor}from"../chunk-2OVDSMPY.js";import"../chunk-PFQPP77Q.js";import"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";export{pickResourceId,poolSaveDC,resolveFeatureResources,resolveRecovery,resolveResourceIndex,resourceLevelFor};
@@ -1 +1 @@
1
- import{resolveResourceIndex}from"../chunk-KEXSF3CH.js";import"../chunk-PFQPP77Q.js";import{effectiveItemCharges,effectiveItemRecovery}from"../chunk-PKIMOVQG.js";import"../chunk-CMIEZQL4.js";import"../chunk-CSTAQQGX.js";import"../chunk-O776WL7O.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";function resolveItemName(entry,registry){var _a;if(!registry)return void 0;const ref=entry.item.match(/^\[\[(.+?)\]\]$/);const slug=ref?ref[1]:entry.item;return(_a=registry.getBySlug(slug))==null?void 0:_a.name}var RESTORED_BY={"short-rest":"short",either:"short",short:"short","long-rest":"long",long:"long",dawn:"long",dusk:"long",turn:null,round:null,custom:null,special:null};var REST_SPAN={short:1,long:2};function earliestRestoringRest(reset){return Object.prototype.hasOwnProperty.call(RESTORED_BY,reset)?RESTORED_BY[reset]:null}function restRestores(type,reset){const earliest=earliestRestoringRest(reset);return earliest!==null&&REST_SPAN[earliest]<=REST_SPAN[type]}function pushPartialRecoveries(cats,character,index,type){var _a,_b;for(const[key,fu]of Object.entries((_a=character.state.feature_uses)!=null?_a:{})){if(fu.used<=0)continue;const res=index.get(key);if(!((_b=res==null?void 0:res.recovery)==null?void 0:_b.length))continue;if(restRestores(type,res.reset))continue;const entry=res.recovery.find(r=>r.kind==="uses"&&r.flavour==="rest"&&restRestores(type,r.entry.reset));if(!entry)continue;const amount=entry.entry.amount;const restore=amount==="all"?"all":typeof amount==="number"?amount:Number(amount);if(restore!=="all"&&!Number.isFinite(restore))continue;const n=restore==="all"?fu.used:Math.min(fu.used,restore);cats.push({id:`feature:${key}`,label:res.name,preview:`${n} of ${fu.used} used restored`,restore})}}function pushBuffEnds(cats,character,resolved){var _a,_b,_c,_d,_e,_f,_g;const structured=d=>!!d&&typeof d==="object";for(const key of(_a=character.state.active_buffs)!=null?_a:[]){let found=false;let name=key;for(const rf of(_b=resolved.features)!=null?_b:[]){if(rf.feature.id===key&&structured(rf.feature.duration)){found=true;name=(_c=rf.feature.name)!=null?_c:key;break}}if(!found){for(const pool of(_d=resolved.pools)!=null?_d:[]){const entry=[...(_e=pool.selected)!=null?_e:[],...(_f=pool.grants)!=null?_f:[]].find(e=>e.slug===key);if(entry&&structured(entry.entity.duration)){found=true;name=(_g=entry.entity.name)!=null?_g:key;break}}}if(!found)continue;cats.push({id:`buff:${key}`,label:`End ${name}`,preview:"active \u2192 ended"})}}function computeRestPlan(character,resolved,derived,registry,type){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n;const cats=[];let hdRegainDist;const index=resolveResourceIndex(resolved);const pact=character.state.spell_slots_pact;if(pact&&pact.used>0){cats.push({id:"pact-slots",label:"Pact Magic Slots",preview:"all reset"})}if(type==="long"){if(character.state.hp.current<derived.hp.max){cats.push({id:"hp-to-max",label:"Hit Points",preview:`${character.state.hp.current} \u2192 ${derived.hp.max}`})}if(character.state.exhaustion>0){cats.push({id:"exhaustion",label:"Exhaustion",preview:`${character.state.exhaustion} \u2192 ${character.state.exhaustion-1}`})}const hpModifier=(_b=(_a=character.overrides)==null?void 0:_a.hp)==null?void 0:_b.modifier;if(hpModifier!==void 0){const signed=hpModifier>0?`+${hpModifier}`:`${hpModifier}`;cats.push({id:"hp-modifier-reset",label:"Max HP Modifier",preview:`${signed} \u2192 cleared`})}const slotsUsed=Object.values((_c=character.state.spell_slots)!=null?_c:{}).reduce((s,slot)=>{var _a2;return s+((_a2=slot.used)!=null?_a2:0)},0);if(slotsUsed>0){cats.push({id:"spell-slots",label:"Spell Slots",preview:"all reset"})}const totalLevel=(_d=resolved.totalLevel)!=null?_d:0;const regainBudget=Math.max(1,Math.floor(totalLevel/2));const pools=Object.entries((_e=character.state.hit_dice)!=null?_e:{}).map(([die,hd])=>({die,used:hd.used,total:hd.total})).filter(p=>p.used>0).sort((a,b)=>b.used-a.used);if(pools.length>0){let left=regainBudget;const dist=[];for(const p of pools){if(left===0)break;const give=Math.min(p.used,left);if(give>0)dist.push({die:p.die,give,targetUsed:p.used-give});left-=give}const totalGive=dist.reduce((s,d)=>s+d.give,0);if(totalGive>0){const detail=dist.map(d=>`${d.die}: +${d.give}`).join(", ");cats.push({id:"hd-regain",label:"Hit Dice",preview:`+${totalGive} (${detail})`});hdRegainDist=dist.map(d=>({die:d.die,targetUsed:d.targetUsed}))}}for(const[key,fu]of Object.entries((_f=character.state.feature_uses)!=null?_f:{})){const banked=(_g=character.state.feature_rolls)==null?void 0:_g[key];const bankedRolls=banked?banked.filter(v=>v>0).length:0;if(fu.used<=0&&bankedRolls<=0)continue;const res=index.get(key);if(!restRestores("long",(_h=res==null?void 0:res.reset)!=null?_h:"long-rest"))continue;const rollsNote=bankedRolls>0?` \xB7 ${bankedRolls} roll${bankedRolls===1?"":"s"} cleared`:"";cats.push({id:`feature:${key}`,label:(_i=res==null?void 0:res.name)!=null?_i:key,preview:`${fu.used}/${fu.max} restored${rollsNote}`})}pushPartialRecoveries(cats,character,index,"long");character.equipment.forEach((entry,idx)=>{var _a2,_b2,_c2,_d2,_e2;const view=(_b2=(_a2=resolved.infusions)==null?void 0:_a2.views.get(idx))!=null?_b2:null;const rec=effectiveItemRecovery(entry,registry,view);const charges=effectiveItemCharges(entry,registry,view);if(!rec||!charges)return;if(charges.current>=charges.max)return;if(!restRestores("long",rec.reset))return;const label=(_e2=(_d2=(_c2=entry.overrides)==null?void 0:_c2.name)!=null?_d2:resolveItemName(entry,registry))!=null?_e2:entry.item;cats.push({id:`item:${idx}`,label,preview:`${charges.current} \u2192 ${charges.max}`,recharge:{amount:rec.amount,current:charges.current,max:charges.max}})})}if(type==="short"){for(const[key,fu]of Object.entries((_j=character.state.feature_uses)!=null?_j:{})){const banked=(_k=character.state.feature_rolls)==null?void 0:_k[key];const bankedRolls=banked?banked.filter(v=>v>0).length:0;if(fu.used<=0&&bankedRolls<=0)continue;const res=index.get(key);if(!restRestores("short",(_l=res==null?void 0:res.reset)!=null?_l:"long-rest"))continue;const rollsNote=bankedRolls>0?` \xB7 ${bankedRolls} roll${bankedRolls===1?"":"s"} cleared`:"";cats.push({id:`feature:${key}`,label:(_m=res==null?void 0:res.name)!=null?_m:key,preview:`${fu.used}/${fu.max} restored${rollsNote}`})}pushPartialRecoveries(cats,character,index,"short");character.equipment.forEach((entry,idx)=>{var _a2,_b2,_c2,_d2,_e2;const view=(_b2=(_a2=resolved.infusions)==null?void 0:_a2.views.get(idx))!=null?_b2:null;const rec=effectiveItemRecovery(entry,registry,view);const charges=effectiveItemCharges(entry,registry,view);if(!rec||!charges)return;if(charges.current>=charges.max)return;if(!restRestores("short",rec.reset))return;const label=(_e2=(_d2=(_c2=entry.overrides)==null?void 0:_c2.name)!=null?_d2:resolveItemName(entry,registry))!=null?_e2:entry.item;cats.push({id:`item:${idx}`,label,preview:`${charges.current} \u2192 ${charges.max}`,recharge:{amount:rec.amount,current:charges.current,max:charges.max}})})}pushBuffEnds(cats,character,resolved);const hdAvailable=type==="short"?Object.entries((_n=character.state.hit_dice)!=null?_n:{}).filter(([,hd])=>hd.used<hd.total).map(([die,hd])=>({die,remaining:hd.total-hd.used})):[];return{type,categories:cats,hdAvailable,hdRegainDist}}export{computeRestPlan,earliestRestoringRest,restRestores};
1
+ import{resolveResourceIndex}from"../chunk-2OVDSMPY.js";import"../chunk-PFQPP77Q.js";import{effectiveItemCharges,effectiveItemRecovery}from"../chunk-E4E6YEN6.js";import"../chunk-CMIEZQL4.js";import"../chunk-O776WL7O.js";import"../chunk-CSTAQQGX.js";import"../chunk-DVUXUIPV.js";import"../chunk-YGH7S5ZF.js";import"../chunk-4IAMSRHD.js";import"../chunk-DZITM5AG.js";import"../chunk-PZ4L2EEG.js";import"../chunk-QMEKQTUT.js";import"../chunk-EAARMPCW.js";import"../chunk-CAPYNIGK.js";import"../chunk-63YJPWTM.js";import"../chunk-BREHZNTL.js";import"../chunk-7FPQJDFD.js";import"../chunk-EVT7MGAC.js";function resolveItemName(entry,registry){var _a;if(!registry)return void 0;const ref=entry.item.match(/^\[\[(.+?)\]\]$/);const slug=ref?ref[1]:entry.item;return(_a=registry.getBySlug(slug))==null?void 0:_a.name}var RESTORED_BY={"short-rest":"short",either:"short",short:"short","long-rest":"long",long:"long",dawn:"long",dusk:"long",turn:null,round:null,custom:null,special:null};var REST_SPAN={short:1,long:2};function earliestRestoringRest(reset){return Object.prototype.hasOwnProperty.call(RESTORED_BY,reset)?RESTORED_BY[reset]:null}function restRestores(type,reset){const earliest=earliestRestoringRest(reset);return earliest!==null&&REST_SPAN[earliest]<=REST_SPAN[type]}function pushPartialRecoveries(cats,character,index,type){var _a,_b;for(const[key,fu]of Object.entries((_a=character.state.feature_uses)!=null?_a:{})){if(fu.used<=0)continue;const res=index.get(key);if(!((_b=res==null?void 0:res.recovery)==null?void 0:_b.length))continue;if(restRestores(type,res.reset))continue;const entry=res.recovery.find(r=>r.kind==="uses"&&r.flavour==="rest"&&restRestores(type,r.entry.reset));if(!entry)continue;const amount=entry.entry.amount;const restore=amount==="all"?"all":typeof amount==="number"?amount:Number(amount);if(restore!=="all"&&!Number.isFinite(restore))continue;const n=restore==="all"?fu.used:Math.min(fu.used,restore);cats.push({id:`feature:${key}`,label:res.name,preview:`${n} of ${fu.used} used restored`,restore})}}function pushBuffEnds(cats,character,resolved){var _a,_b,_c,_d,_e,_f,_g;const structured=d=>!!d&&typeof d==="object";for(const key of(_a=character.state.active_buffs)!=null?_a:[]){let found=false;let name=key;for(const rf of(_b=resolved.features)!=null?_b:[]){if(rf.feature.id===key&&structured(rf.feature.duration)){found=true;name=(_c=rf.feature.name)!=null?_c:key;break}}if(!found){for(const pool of(_d=resolved.pools)!=null?_d:[]){const entry=[...(_e=pool.selected)!=null?_e:[],...(_f=pool.grants)!=null?_f:[]].find(e=>e.slug===key);if(entry&&structured(entry.entity.duration)){found=true;name=(_g=entry.entity.name)!=null?_g:key;break}}}if(!found)continue;cats.push({id:`buff:${key}`,label:`End ${name}`,preview:"active \u2192 ended"})}}function computeRestPlan(character,resolved,derived,registry,type){var _a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n;const cats=[];let hdRegainDist;const index=resolveResourceIndex(resolved);const pact=character.state.spell_slots_pact;if(pact&&pact.used>0){cats.push({id:"pact-slots",label:"Pact Magic Slots",preview:"all reset"})}if(type==="long"){if(character.state.hp.current<derived.hp.max){cats.push({id:"hp-to-max",label:"Hit Points",preview:`${character.state.hp.current} \u2192 ${derived.hp.max}`})}if(character.state.exhaustion>0){cats.push({id:"exhaustion",label:"Exhaustion",preview:`${character.state.exhaustion} \u2192 ${character.state.exhaustion-1}`})}const hpModifier=(_b=(_a=character.overrides)==null?void 0:_a.hp)==null?void 0:_b.modifier;if(hpModifier!==void 0){const signed=hpModifier>0?`+${hpModifier}`:`${hpModifier}`;cats.push({id:"hp-modifier-reset",label:"Max HP Modifier",preview:`${signed} \u2192 cleared`})}const slotsUsed=Object.values((_c=character.state.spell_slots)!=null?_c:{}).reduce((s,slot)=>{var _a2;return s+((_a2=slot.used)!=null?_a2:0)},0);if(slotsUsed>0){cats.push({id:"spell-slots",label:"Spell Slots",preview:"all reset"})}const totalLevel=(_d=resolved.totalLevel)!=null?_d:0;const regainBudget=Math.max(1,Math.floor(totalLevel/2));const pools=Object.entries((_e=character.state.hit_dice)!=null?_e:{}).map(([die,hd])=>({die,used:hd.used,total:hd.total})).filter(p=>p.used>0).sort((a,b)=>b.used-a.used);if(pools.length>0){let left=regainBudget;const dist=[];for(const p of pools){if(left===0)break;const give=Math.min(p.used,left);if(give>0)dist.push({die:p.die,give,targetUsed:p.used-give});left-=give}const totalGive=dist.reduce((s,d)=>s+d.give,0);if(totalGive>0){const detail=dist.map(d=>`${d.die}: +${d.give}`).join(", ");cats.push({id:"hd-regain",label:"Hit Dice",preview:`+${totalGive} (${detail})`});hdRegainDist=dist.map(d=>({die:d.die,targetUsed:d.targetUsed}))}}for(const[key,fu]of Object.entries((_f=character.state.feature_uses)!=null?_f:{})){const banked=(_g=character.state.feature_rolls)==null?void 0:_g[key];const bankedRolls=banked?banked.filter(v=>v>0).length:0;if(fu.used<=0&&bankedRolls<=0)continue;const res=index.get(key);if(!restRestores("long",(_h=res==null?void 0:res.reset)!=null?_h:"long-rest"))continue;const rollsNote=bankedRolls>0?` \xB7 ${bankedRolls} roll${bankedRolls===1?"":"s"} cleared`:"";cats.push({id:`feature:${key}`,label:(_i=res==null?void 0:res.name)!=null?_i:key,preview:`${fu.used}/${fu.max} restored${rollsNote}`})}pushPartialRecoveries(cats,character,index,"long");character.equipment.forEach((entry,idx)=>{var _a2,_b2,_c2,_d2,_e2;const view=(_b2=(_a2=resolved.infusions)==null?void 0:_a2.views.get(idx))!=null?_b2:null;const rec=effectiveItemRecovery(entry,registry,view);const charges=effectiveItemCharges(entry,registry,view);if(!rec||!charges)return;if(charges.current>=charges.max)return;if(!restRestores("long",rec.reset))return;const label=(_e2=(_d2=(_c2=entry.overrides)==null?void 0:_c2.name)!=null?_d2:resolveItemName(entry,registry))!=null?_e2:entry.item;cats.push({id:`item:${idx}`,label,preview:`${charges.current} \u2192 ${charges.max}`,recharge:{amount:rec.amount,current:charges.current,max:charges.max}})})}if(type==="short"){for(const[key,fu]of Object.entries((_j=character.state.feature_uses)!=null?_j:{})){const banked=(_k=character.state.feature_rolls)==null?void 0:_k[key];const bankedRolls=banked?banked.filter(v=>v>0).length:0;if(fu.used<=0&&bankedRolls<=0)continue;const res=index.get(key);if(!restRestores("short",(_l=res==null?void 0:res.reset)!=null?_l:"long-rest"))continue;const rollsNote=bankedRolls>0?` \xB7 ${bankedRolls} roll${bankedRolls===1?"":"s"} cleared`:"";cats.push({id:`feature:${key}`,label:(_m=res==null?void 0:res.name)!=null?_m:key,preview:`${fu.used}/${fu.max} restored${rollsNote}`})}pushPartialRecoveries(cats,character,index,"short");character.equipment.forEach((entry,idx)=>{var _a2,_b2,_c2,_d2,_e2;const view=(_b2=(_a2=resolved.infusions)==null?void 0:_a2.views.get(idx))!=null?_b2:null;const rec=effectiveItemRecovery(entry,registry,view);const charges=effectiveItemCharges(entry,registry,view);if(!rec||!charges)return;if(charges.current>=charges.max)return;if(!restRestores("short",rec.reset))return;const label=(_e2=(_d2=(_c2=entry.overrides)==null?void 0:_c2.name)!=null?_d2:resolveItemName(entry,registry))!=null?_e2:entry.item;cats.push({id:`item:${idx}`,label,preview:`${charges.current} \u2192 ${charges.max}`,recharge:{amount:rec.amount,current:charges.current,max:charges.max}})})}pushBuffEnds(cats,character,resolved);const hdAvailable=type==="short"?Object.entries((_n=character.state.hit_dice)!=null?_n:{}).filter(([,hd])=>hd.used<hd.total).map(([die,hd])=>({die,remaining:hd.total-hd.used})):[];return{type,categories:cats,hdAvailable,hdRegainDist}}export{computeRestPlan,earliestRestoringRest,restRestores};
@@ -148,6 +148,7 @@ export declare const characterSchema: z.ZodObject<{
148
148
  "archivist-point-buy": "archivist-point-buy";
149
149
  manual: "manual";
150
150
  }>;
151
+ keep_species_ability_increases: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
151
152
  builder_rolls: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
152
153
  builder_equipment_mode: z.ZodOptional<z.ZodEnum<{
153
154
  gold: "gold";
@@ -1 +1 @@
1
- import{characterOverridesShape,characterSchema}from"../chunk-BWIEA5ZP.js";import"../chunk-KM75CC6Q.js";export{characterOverridesShape,characterSchema};
1
+ import{characterOverridesShape,characterSchema}from"../chunk-CYYVM6H3.js";import"../chunk-KM75CC6Q.js";export{characterOverridesShape,characterSchema};
@@ -0,0 +1,12 @@
1
+ import type { BackgroundEntity } from "@archivist-gg/dnd5e/background/background.types";
2
+ import type { RaceEntity } from "@archivist-gg/dnd5e/race/race.types";
3
+ import type { ResolvedCharacter } from "./pc.types.js";
4
+ export declare function backgroundGrantsAbilityIncreases(bg: BackgroundEntity | null | undefined): boolean;
5
+ export declare function speciesGrantsAbilityIncreases(race: RaceEntity | null | undefined): boolean;
6
+ export declare function isOlderSpecies(race: RaceEntity | null | undefined): boolean;
7
+ export interface SpeciesIncreaseRule {
8
+ applies: boolean;
9
+ kept: boolean;
10
+ suppressed: boolean;
11
+ }
12
+ export declare function speciesIncreaseRule(resolved: Pick<ResolvedCharacter, "race" | "background" | "definition">): SpeciesIncreaseRule;
@@ -0,0 +1 @@
1
+ import{backgroundGrantsAbilityIncreases,isOlderSpecies,speciesGrantsAbilityIncreases,speciesIncreaseRule}from"../chunk-6IPWTOLU.js";export{backgroundGrantsAbilityIncreases,isOlderSpecies,speciesGrantsAbilityIncreases,speciesIncreaseRule};
@@ -1,4 +1,5 @@
1
1
  import type { Ability, EntityFilter } from "../types/choice.js";
2
+ import type { ProficiencyReplacement } from "./pc.proficiency-replacements.js";
2
3
  import type { ArmorEntity } from "../armor/armor.types.js";
3
4
  import type { WeaponEntity } from "../weapon/weapon.types.js";
4
5
  import type { SpellScope, WeaponScope } from "../types/feature-effect.js";
@@ -250,6 +251,7 @@ export interface Character {
250
251
  origin_choices?: Record<string, ChoiceValue>;
251
252
  abilities: Record<Ability, number>;
252
253
  ability_method: AbilityMethod;
254
+ keep_species_ability_increases?: boolean;
253
255
  builder_rolls?: number[];
254
256
  builder_equipment_mode?: "starting" | "gold" | "empty";
255
257
  skills: {
@@ -341,6 +343,15 @@ export interface ResolvedFeature {
341
343
  description?: string;
342
344
  choices?: Choice[];
343
345
  }[];
346
+ poolMember?: true;
347
+ }
348
+ export interface ExtraAttackSource {
349
+ name: string;
350
+ source: FeatureSource;
351
+ level?: number;
352
+ poolMember?: true;
353
+ switched?: true;
354
+ scope?: WeaponScope[];
344
355
  }
345
356
  export interface ResolvedSpell {
346
357
  entity: Spell;
@@ -395,6 +406,7 @@ export interface ResolvedCharacter {
395
406
  background: BackgroundEntity | null;
396
407
  feats: FeatEntity[];
397
408
  originFeatSlug?: string;
409
+ proficiencyReplacements?: ProficiencyReplacement[];
398
410
  totalLevel: number;
399
411
  features: ResolvedFeature[];
400
412
  spells: ResolvedSpell[];
@@ -506,6 +518,7 @@ export interface AttackRow {
506
518
  damageRiders?: DamageRider[];
507
519
  weaponCategory?: "melee" | "ranged";
508
520
  attacksPerAction?: number;
521
+ extraAttackSource?: ExtraAttackSource;
509
522
  properties: string[];
510
523
  proficient: boolean;
511
524
  breakdown: {
@@ -536,10 +549,35 @@ export interface AttackRow {
536
549
  };
537
550
  grantedBy?: string;
538
551
  pactWeapon?: true;
552
+ naturalWeapon?: true;
553
+ }
554
+ export interface AbilityScoreTerm {
555
+ source: string;
556
+ amount: number;
557
+ notUsed?: true;
558
+ }
559
+ export interface AbilityScoreBreakdown {
560
+ total: number;
561
+ terms: AbilityScoreTerm[];
562
+ set?: {
563
+ source: string;
564
+ value: number;
565
+ };
566
+ override?: number;
539
567
  }
540
568
  export interface AppliedBonuses {
541
569
  ability_bonuses: Partial<Record<Ability, number>>;
542
570
  ability_statics: Partial<Record<Ability, number>>;
571
+ ability_terms?: {
572
+ ability: Ability;
573
+ source: string;
574
+ amount: number;
575
+ }[];
576
+ ability_static_terms?: {
577
+ ability: Ability;
578
+ source: string;
579
+ value: number;
580
+ }[];
543
581
  save_bonus: number;
544
582
  save_terms: {
545
583
  source: string;
@@ -653,6 +691,7 @@ export interface DerivedStats {
653
691
  source: string;
654
692
  amount: number;
655
693
  }[];
694
+ abilities?: Record<Ability, AbilityScoreBreakdown>;
656
695
  };
657
696
  passives: {
658
697
  perception: number;
@@ -700,6 +739,7 @@ export interface DerivedStats {
700
739
  spellcastingInformational: import("@archivist-gg/dnd5e/item/item.conditions.types").InformationalBonus[];
701
740
  speedInformational: import("@archivist-gg/dnd5e/item/item.conditions.types").InformationalBonus[];
702
741
  attacksPerAction: number;
742
+ extraAttackSource?: ExtraAttackSource;
703
743
  attacks: AttackRow[];
704
744
  spellDamageRiders?: SpellDamageRider[];
705
745
  equippedSlots: EquippedSlots;
@@ -1 +1 @@
1
- import{raceCodec}from"../chunk-TGK4OP7P.js";import"../chunk-JGCE4JVX.js";import"../chunk-XVXNBWK6.js";import"../chunk-S5UCI27C.js";import"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{raceCodec};
1
+ import{raceCodec}from"../chunk-XCF5R5XX.js";import"../chunk-KGZXAAFN.js";import"../chunk-D2BXAFOL.js";import"../chunk-S5UCI27C.js";import"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{raceCodec};
@@ -1 +1 @@
1
- import{parseRace}from"../chunk-JGCE4JVX.js";import"../chunk-XVXNBWK6.js";import"../chunk-S5UCI27C.js";import"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{parseRace};
1
+ import{parseRace}from"../chunk-KGZXAAFN.js";import"../chunk-D2BXAFOL.js";import"../chunk-S5UCI27C.js";import"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{parseRace};
@@ -1 +1 @@
1
- import{fixedAsiSchema,raceEntitySchema}from"../chunk-XVXNBWK6.js";import"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{fixedAsiSchema,raceEntitySchema};
1
+ import{fixedAsiSchema,raceEntitySchema}from"../chunk-D2BXAFOL.js";import"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{fixedAsiSchema,raceEntitySchema};
@@ -0,0 +1,12 @@
1
+ import type { RegisteredEntity } from "@archivist-gg/core";
2
+ import type { RaceEntity } from "./race.types.js";
3
+ export interface SubspeciesRegistry {
4
+ getByTypeAndSlug(entityType: string, slug: string): RegisteredEntity | undefined;
5
+ search(query: string, entityType: string, limit: number): RegisteredEntity[];
6
+ }
7
+ export declare function findSubspeciesParent(registry: SubspeciesRegistry, child: {
8
+ slug: string;
9
+ subspecies_of?: string | null;
10
+ }): RegisteredEntity | undefined;
11
+ export declare function mergeSubspecies(child: RaceEntity, parent: RaceEntity): RaceEntity;
12
+ export declare function withSubspeciesParent<T extends RaceEntity | null>(race: T, registry: SubspeciesRegistry): T;
@@ -0,0 +1 @@
1
+ import{findSubspeciesParent,mergeSubspecies,withSubspeciesParent}from"../chunk-4AJYEWFQ.js";import"../chunk-63YJPWTM.js";export{findSubspeciesParent,mergeSubspecies,withSubspeciesParent};
@@ -45,4 +45,5 @@ export declare const attackSchema: z.ZodObject<{
45
45
  martial: "martial";
46
46
  }>>;
47
47
  mastery: z.ZodOptional<z.ZodString>;
48
+ unarmed: z.ZodOptional<z.ZodBoolean>;
48
49
  }, z.core.$strip>;
@@ -1 +1 @@
1
- import{featureObjectSchema,featureSchema}from"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";export{featureObjectSchema,featureSchema};
1
+ import{featureObjectSchema,featureSchema}from"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";export{featureObjectSchema,featureSchema};
@@ -1 +1 @@
1
- import{subclassCodec}from"../chunk-LVKSX6EQ.js";import"../chunk-AHEL6LJ5.js";import"../chunk-3A4OSTC4.js";import"../chunk-S5UCI27C.js";import"../chunk-GCYUCIDN.js";import"../chunk-X22SISGM.js";import"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{subclassCodec};
1
+ import{subclassCodec}from"../chunk-NB4QWMF5.js";import"../chunk-J6FIBUI4.js";import"../chunk-NU6WP4P5.js";import"../chunk-S5UCI27C.js";import"../chunk-GCYUCIDN.js";import"../chunk-X22SISGM.js";import"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{subclassCodec};
@@ -1 +1 @@
1
- import{parseSubclass}from"../chunk-AHEL6LJ5.js";import"../chunk-3A4OSTC4.js";import"../chunk-S5UCI27C.js";import"../chunk-GCYUCIDN.js";import"../chunk-X22SISGM.js";import"../chunk-ZREOQMHM.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{parseSubclass};
1
+ import{parseSubclass}from"../chunk-J6FIBUI4.js";import"../chunk-NU6WP4P5.js";import"../chunk-S5UCI27C.js";import"../chunk-GCYUCIDN.js";import"../chunk-X22SISGM.js";import"../chunk-M2UA2FAK.js";import"../chunk-ZE46ADXS.js";import"../chunk-CCFIINBA.js";import"../chunk-VHIE2KYQ.js";import"../chunk-EON7T2SN.js";import"../chunk-I26FHSI6.js";export{parseSubclass};