@archivist-gg/dnd5e 0.3.11 → 0.3.13

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 (164) hide show
  1. package/LICENSES/SRD.md +38 -3
  2. package/dist/armor/armor.codec.js +3 -3
  3. package/dist/armor/armor.parser.js +2 -2
  4. package/dist/armor/armor.schema.d.ts +1 -0
  5. package/dist/armor/armor.schema.js +1 -1
  6. package/dist/armor/armor.types.d.ts +2 -0
  7. package/dist/background/background.codec.js +5 -5
  8. package/dist/background/background.parser.js +4 -4
  9. package/dist/background/background.schema.js +3 -3
  10. package/dist/chunk-2LULMQTF.js +14 -0
  11. package/dist/{chunk-CBEKVAX4.js → chunk-4BZ47YJ4.js} +10 -3
  12. package/dist/{chunk-T2SNEJOE.js → chunk-4SLOJXJ4.js} +1 -1
  13. package/dist/{chunk-2DFENQIJ.js → chunk-5GKJAUMX.js} +2 -0
  14. package/dist/{chunk-J77CKYV3.js → chunk-5KGV6TF7.js} +1 -1
  15. package/dist/{chunk-CHUALUIX.js → chunk-6ZY3U6BQ.js} +1 -1
  16. package/dist/{chunk-DNAJRMNN.js → chunk-A54HHCWW.js} +6 -7
  17. package/dist/{chunk-2M34FLAY.js → chunk-BRGLDWUP.js} +3 -1
  18. package/dist/chunk-CM5CWO4K.js +735 -0
  19. package/dist/{chunk-3HX5VLWP.js → chunk-DPM6V7YX.js} +1 -1
  20. package/dist/chunk-EJP263OP.js +186 -0
  21. package/dist/{chunk-G247QXWW.js → chunk-EL6QPF6I.js} +1 -1
  22. package/dist/{chunk-SMLXZUBH.js → chunk-EYX4JMAU.js} +4 -1
  23. package/dist/{chunk-AW3EHF3L.js → chunk-FC4IGH5Y.js} +1 -1
  24. package/dist/{chunk-PI4LLJG4.js → chunk-FPGXFD2M.js} +2 -2
  25. package/dist/{chunk-23LZLBJK.js → chunk-G6MHJDVT.js} +6 -2
  26. package/dist/{chunk-NWDF5HG3.js → chunk-G7ED5H2G.js} +1 -1
  27. package/dist/chunk-H5PTKYXL.js +101 -0
  28. package/dist/{chunk-LWFTHJIE.js → chunk-HHBD4SQ6.js} +1 -1
  29. package/dist/{chunk-PP2UHLBA.js → chunk-HJQNK3J5.js} +8 -0
  30. package/dist/{chunk-JC5UNIVM.js → chunk-HS6FIOLP.js} +2 -0
  31. package/dist/chunk-IHE6KVC3.js +13 -0
  32. package/dist/{chunk-BLRW2UU6.js → chunk-J53ERF6K.js} +2 -2
  33. package/dist/{chunk-MQ747UCR.js → chunk-JNNNBEUH.js} +65 -2
  34. package/dist/{chunk-LDDCNPHD.js → chunk-K5NJBTE2.js} +1 -1
  35. package/dist/{chunk-4ISR76DH.js → chunk-KSTV7J2U.js} +9 -3
  36. package/dist/chunk-LBEXLN6I.js +91 -0
  37. package/dist/{chunk-UBBKSYBY.js → chunk-LHZXYFBU.js} +30 -1
  38. package/dist/{chunk-U3BABVJF.js → chunk-LVX6TQ3R.js} +2 -2
  39. package/dist/{chunk-R747YKS7.js → chunk-M2OWVAZG.js} +1 -1
  40. package/dist/{chunk-7YU4NPKR.js → chunk-MC5YJ4PB.js} +1 -1
  41. package/dist/{chunk-JCEV7KYN.js → chunk-MUIU7RZ3.js} +1 -1
  42. package/dist/{chunk-R2ZV233X.js → chunk-MYY2C5MB.js} +3 -3
  43. package/dist/{chunk-S56D6B6C.js → chunk-PLOSP4XQ.js} +3 -3
  44. package/dist/{chunk-JANNRGJC.js → chunk-PX25R3DK.js} +1 -1
  45. package/dist/{chunk-V373TRJE.js → chunk-Q5XTEYHD.js} +191 -125
  46. package/dist/{chunk-MAH6DCRI.js → chunk-Q6UOHCCT.js} +1 -1
  47. package/dist/{chunk-2INMRR3Q.js → chunk-QEO7LYTG.js} +215 -94
  48. package/dist/{chunk-PJMG5XV3.js → chunk-QSBJ6NEM.js} +1 -1
  49. package/dist/{chunk-BL3VELKP.js → chunk-R2V5LN3I.js} +1 -1
  50. package/dist/{chunk-4DOMDEBZ.js → chunk-RQNJXADQ.js} +1 -1
  51. package/dist/{chunk-GFZ7PITJ.js → chunk-S3YUXDSC.js} +6 -1
  52. package/dist/chunk-T5GZBKIQ.js +927 -0
  53. package/dist/{chunk-PZCE7DJM.js → chunk-UE6LKRXQ.js} +15 -1
  54. package/dist/{chunk-5N2GW72F.js → chunk-UZXG6QSY.js} +2 -1
  55. package/dist/{chunk-QHMWA3SZ.js → chunk-VDPRBUU5.js} +1 -1
  56. package/dist/{chunk-4XTNPNQB.js → chunk-VPYBK2MG.js} +1 -1
  57. package/dist/{chunk-V6LJFP4R.js → chunk-X7VZY4ON.js} +2 -2
  58. package/dist/{chunk-HZA7OE7N.js → chunk-XCFC7LGF.js} +2 -1
  59. package/dist/{chunk-BIA32MQ5.js → chunk-XJRNEQPD.js} +1 -1
  60. package/dist/{chunk-UIRMA5KM.js → chunk-YDGMBMYI.js} +1 -1
  61. package/dist/{chunk-6X4KUDMU.js → chunk-ZCTUYGNV.js} +7 -2
  62. package/dist/{chunk-XTRDCSJB.js → chunk-ZMJQUZQH.js} +4 -1
  63. package/dist/chunk-ZUQW5VBZ.js +89 -0
  64. package/dist/class/class.codec.js +7 -7
  65. package/dist/class/class.parser.js +6 -6
  66. package/dist/class/class.schema.d.ts +10 -0
  67. package/dist/class/class.schema.js +5 -5
  68. package/dist/entities/base-item-resolver.js +2 -2
  69. package/dist/entities/slug.d.ts +18 -8
  70. package/dist/entities/slug.js +3 -1
  71. package/dist/feat/feat.codec.js +5 -5
  72. package/dist/feat/feat.parser.js +4 -4
  73. package/dist/feat/feat.schema.d.ts +16 -3
  74. package/dist/feat/feat.schema.js +3 -3
  75. package/dist/index.js +7190 -4116
  76. package/dist/item/item.actions-map.d.ts +40 -5
  77. package/dist/item/item.actions-map.js +5 -84
  78. package/dist/item/item.attunement.js +3 -9
  79. package/dist/item/item.bonuses.js +5 -2
  80. package/dist/item/item.codec.js +3 -3
  81. package/dist/item/item.conditions.js +4 -1
  82. package/dist/item/item.conditions.types.d.ts +4 -0
  83. package/dist/item/item.cost.d.ts +3 -0
  84. package/dist/item/item.cost.js +29 -0
  85. package/dist/item/item.icon.d.ts +15 -0
  86. package/dist/item/item.icon.js +211 -0
  87. package/dist/item/item.parser.js +2 -2
  88. package/dist/item/item.schema.d.ts +16 -1
  89. package/dist/item/item.schema.js +3 -1
  90. package/dist/item/item.types.d.ts +9 -2
  91. package/dist/monster/monster.parser.js +5 -5
  92. package/dist/monster/monster.schema.js +4 -4
  93. package/dist/optional-feature/optional-feature.codec.js +4 -4
  94. package/dist/optional-feature/optional-feature.parser.js +3 -3
  95. package/dist/optional-feature/optional-feature.schema.d.ts +229 -3
  96. package/dist/optional-feature/optional-feature.schema.js +6 -2
  97. package/dist/pc/pc.additional-spells.js +2 -2
  98. package/dist/pc/pc.asi-flatten.d.ts +62 -1
  99. package/dist/pc/pc.asi-flatten.js +16 -0
  100. package/dist/pc/pc.conditions.js +1 -1
  101. package/dist/pc/pc.containment.d.ts +45 -0
  102. package/dist/pc/pc.containment.js +24 -0
  103. package/dist/pc/pc.decision-engine.d.ts +21 -3
  104. package/dist/pc/pc.decision-engine.js +21 -12
  105. package/dist/pc/pc.entry-overrides.d.ts +79 -0
  106. package/dist/pc/pc.entry-overrides.js +40 -0
  107. package/dist/pc/pc.equipment.d.ts +2 -2
  108. package/dist/pc/pc.equipment.js +18 -7
  109. package/dist/pc/pc.feature-effects.js +2 -2
  110. package/dist/pc/pc.infusions.d.ts +220 -0
  111. package/dist/pc/pc.infusions.js +64 -0
  112. package/dist/pc/pc.parser.js +18 -1
  113. package/dist/pc/pc.pools.d.ts +1 -1
  114. package/dist/pc/pc.pools.js +11 -3
  115. package/dist/pc/pc.proficiencies.js +19 -12
  116. package/dist/pc/pc.recalc.d.ts +39 -36
  117. package/dist/pc/pc.recalc.js +58 -30
  118. package/dist/pc/pc.resolver.js +19 -12
  119. package/dist/pc/pc.resource-seed.js +1 -1
  120. package/dist/pc/pc.resources.d.ts +6 -1
  121. package/dist/pc/pc.resources.js +3 -1
  122. package/dist/pc/pc.rest.d.ts +21 -1
  123. package/dist/pc/pc.rest.js +52 -19
  124. package/dist/pc/pc.schema.d.ts +14 -0
  125. package/dist/pc/pc.schema.js +1 -1
  126. package/dist/pc/pc.slotting.d.ts +36 -3
  127. package/dist/pc/pc.slotting.js +13 -5
  128. package/dist/pc/pc.tool-picks.d.ts +51 -0
  129. package/dist/pc/pc.tool-picks.js +18 -0
  130. package/dist/pc/pc.types.d.ts +70 -12
  131. package/dist/pc/pool-layout.d.ts +14 -0
  132. package/dist/pc/pool-layout.js +7 -3
  133. package/dist/race/race.codec.js +6 -6
  134. package/dist/race/race.parser.js +5 -5
  135. package/dist/race/race.schema.js +4 -4
  136. package/dist/schemas/attack-schema.d.ts +1 -1
  137. package/dist/schemas/choice-schema.js +2 -2
  138. package/dist/schemas/feature-effect-schema.d.ts +16 -3
  139. package/dist/schemas/feature-effect-schema.js +1 -1
  140. package/dist/schemas/feature-schema.js +3 -3
  141. package/dist/schemas/selection-pool-schema.d.ts +10 -0
  142. package/dist/schemas/selection-pool-schema.js +1 -1
  143. package/dist/srd/retired-items.d.ts +14 -0
  144. package/dist/srd/retired-items.js +11 -0
  145. package/dist/subclass/subclass.codec.js +7 -7
  146. package/dist/subclass/subclass.parser.js +6 -6
  147. package/dist/subclass/subclass.schema.d.ts +10 -0
  148. package/dist/subclass/subclass.schema.js +5 -5
  149. package/dist/types/choice.d.ts +8 -0
  150. package/dist/types/equipment-grant.d.ts +18 -1
  151. package/dist/types/equipment-grant.js +12 -0
  152. package/dist/types/feature-effect.d.ts +6 -1
  153. package/dist/types/optional-feature.types.d.ts +79 -1
  154. package/dist/types/selection-pool.d.ts +16 -1
  155. package/dist/weapon/weapon.classify.d.ts +10 -8
  156. package/dist/weapon/weapon.classify.js +2 -2
  157. package/dist/weapon/weapon.codec.js +3 -3
  158. package/dist/weapon/weapon.parser.js +2 -2
  159. package/dist/weapon/weapon.schema.d.ts +1 -0
  160. package/dist/weapon/weapon.schema.js +1 -1
  161. package/dist/weapon/weapon.types.d.ts +2 -0
  162. package/package.json +1 -1
  163. package/dist/chunk-O4SRD3J5.js +0 -165
  164. package/dist/chunk-WXWPK3LI.js +0 -55
@@ -1,7 +1,9 @@
1
1
  /** One thing a starting-equipment option grants. `item` is a BARE compendium
2
2
  * slug (e.g. "chain-mail"); the seeder resolves it to the full edition slug.
3
3
  * `category` is a player-picked class of item ("martial-weapon",
4
- * "simple-weapon", "martial-melee-weapon", "any-armor", "shield", …) resolved
4
+ * "simple-weapon", "martial-melee-weapon", "any-armor", "shield",
5
+ * "musical-instrument", "artisan's-tools", "gaming-set", a tool `X-or-Y` union;
6
+ * the vocabulary is `categoryToEntitySelect`'s in pc.decision-engine.ts) resolved
5
7
  * by a nested select-entity. `gold` is gp folded into the bundle. */
6
8
  export type EquipmentGrant =
7
9
  /** `contains_value` (COPPER; `1500` = 15 gp) is seeded as gold by the plugin's starting-equipment seeder
@@ -19,6 +21,21 @@ export type EquipmentGrant =
19
21
  } | {
20
22
  gold: number;
21
23
  };
24
+ /** THE rule for which grant is a player-picked CATEGORY: an object whose `category` is a non-empty string. Shared by
25
+ * the engine's nested-pick synthesis and the plugin's seeder, so the nth category grant of an option always
26
+ * consumes the nth pick key and the two can never count a malformed grant differently. */
27
+ export declare function isCategoryGrant(g: unknown): g is Extract<EquipmentGrant, {
28
+ category: string;
29
+ }>;
30
+ /** The persistence key of the nested pick for grant `k` of option `j` of starting-equipment entry `i`: the one
31
+ * spelling the engine emits and the plugin reads. `k` indexes the option's WHOLE grant list, not its category
32
+ * grants alone. */
33
+ export declare const equipmentCategoryKey: (i: number, j: number, k: number) => string;
34
+ /** The ORDERED pick keys of one option's category grants, the order `resolveGrants` consumes them in. */
35
+ export declare const equipmentCategoryKeys: (grants: readonly unknown[], i: number, j: number) => string[];
36
+ /** True for a starting-equipment decision key (`equipment-<i>` and its nested picks). The Equipment step owns
37
+ * these; every other step's decision strip leaves them out. */
38
+ export declare const isStartingEquipmentKey: (key: string) => boolean;
22
39
  /** One selectable option of a `kind:"choice"` starting-equipment entry. `label`
23
40
  * is the human display string (the `.pc-cb-eqopt` text); `grants` is what seeds. */
24
41
  export interface EquipmentOption {
@@ -0,0 +1,12 @@
1
+ import {
2
+ equipmentCategoryKey,
3
+ equipmentCategoryKeys,
4
+ isCategoryGrant,
5
+ isStartingEquipmentKey
6
+ } from "../chunk-2LULMQTF.js";
7
+ export {
8
+ equipmentCategoryKey,
9
+ equipmentCategoryKeys,
10
+ isCategoryGrant,
11
+ isStartingEquipmentKey
12
+ };
@@ -1,5 +1,10 @@
1
1
  import type { Ability } from "./choice.js";
2
2
  export type SenseType = "darkvision" | "blindsight" | "tremorsense" | "truesight";
3
+ /** A damage rider's weapon scope, the `damage-bonus` arm's structured `applies_to` words (ART-c1 Task 9b, controller
4
+ * ruling 8): `melee` and `ranged` are the weapon's CATEGORY (a thrown melee weapon stays melee), `unarmed` the engine's
5
+ * Unarmed Strike row, `finesse` and `thrown` the row's properties, and `weapon` every attack row (today's reach, the
6
+ * Unarmed Strike row included). A list reaches a row when ANY word matches it. */
7
+ export type WeaponScope = "weapon" | "melee" | "ranged" | "unarmed" | "finesse" | "thrown";
3
8
  /** Present on every arm: whose numbers the effect changes. Absent === "self". The engine's fold readers skip
4
9
  * every effect whose subject is present and not "self" (`foldsOnSelf` in pc.feature-effects.ts). */
5
10
  type Subject = {
@@ -69,7 +74,7 @@ export type FeatureEffect = ({
69
74
  kind: "damage-bonus";
70
75
  damage_type: string;
71
76
  amount: string;
72
- applies_to?: "weapon" | "spell" | "all";
77
+ applies_to?: "spell" | "all" | WeaponScope | WeaponScope[];
73
78
  } & Qualified) | ({
74
79
  kind: "proficiency";
75
80
  proficiency_type: "skill" | "tool" | "language" | "saving-throw" | "armor" | "weapon";
@@ -8,7 +8,7 @@ import type { AdditionalSpellsEntry, ProgressionEntry } from "../schemas/entity-
8
8
  * `feature_type` field is now an open string (see {@link OptionalFeatureEntity})
9
9
  * so homebrew categories parse; this union is kept purely as a reference list.
10
10
  */
11
- export type OptionalFeatureKind = "invocation" | "fighting_style" | "metamagic" | "maneuver" | "infusion";
11
+ export type OptionalFeatureKind = "invocation" | "fighting_style" | "metamagic" | "maneuver" | "infusion" | "artificer_plan";
12
12
  /** A class/subclass named reference carried by a level prerequisite; mirrors namedRefSchema. */
13
13
  export type OptionalFeatureNamedRef = {
14
14
  name: string;
@@ -45,6 +45,76 @@ export type OptionalFeaturePrerequisite = {
45
45
  entry?: string;
46
46
  entry_summary?: string;
47
47
  };
48
+ /** ART-a (spec §4.2). */
49
+ export interface FilterSpec {
50
+ rarity: string[];
51
+ types?: string[];
52
+ exclude_types?: string[];
53
+ cursed?: false;
54
+ }
55
+ export interface OptionCreates {
56
+ item?: string;
57
+ variant?: {
58
+ candidates: string[];
59
+ };
60
+ filter?: FilterSpec;
61
+ }
62
+ export interface OptionRow {
63
+ key: string;
64
+ name: string;
65
+ min_level: number;
66
+ attunement?: boolean;
67
+ creates: OptionCreates;
68
+ }
69
+ export interface InfuseItem {
70
+ bonuses?: {
71
+ ac?: number;
72
+ weapon_attack?: number;
73
+ weapon_damage?: number;
74
+ spell_attack?: number;
75
+ saving_throws?: number;
76
+ speed?: {
77
+ walk?: number;
78
+ fly?: number;
79
+ swim?: number;
80
+ climb?: number;
81
+ };
82
+ };
83
+ resist?: string[];
84
+ charges?: {
85
+ max: number;
86
+ dice?: string;
87
+ recharge?: string;
88
+ recharge_amount?: string;
89
+ };
90
+ action?: ActionCost;
91
+ /** ART-c1 (R-3 a): the Actions row's range ("Self"); absent draws no range. */
92
+ range?: string;
93
+ }
94
+ export interface InfuseTarget {
95
+ kind: "armor" | "shield" | "weapon" | "gear";
96
+ category?: string[];
97
+ property?: string;
98
+ name_any?: string[];
99
+ }
100
+ export interface InfuseBlock {
101
+ targets: InfuseTarget[];
102
+ targets_label?: string;
103
+ new_object?: string;
104
+ rarity?: string;
105
+ attunement?: {
106
+ required: true;
107
+ };
108
+ choice?: {
109
+ kind: "damage-type";
110
+ options?: string[];
111
+ };
112
+ item?: InfuseItem;
113
+ scales_at?: Array<{
114
+ level: number;
115
+ item: InfuseItem;
116
+ }>;
117
+ }
48
118
  export interface OptionalFeatureEntity {
49
119
  slug: string;
50
120
  name: string;
@@ -87,4 +157,12 @@ export interface OptionalFeatureEntity {
87
157
  optionalfeature_progression?: ProgressionEntry[];
88
158
  /** One wikilink, or an array of them for the multi-fluff-image emit. */
89
159
  image?: string | string[];
160
+ /** ART-a (spec §4.1): a pick is a COPY `<note slug>#<param>`; needs `options` and `item_choice`. */
161
+ repeatable?: true;
162
+ /** `learn`: the param is the item's FULL slug (TCE); `create`: the param is a row key, the item chosen at Create (EFA). */
163
+ item_choice?: "learn" | "create";
164
+ /** The table a copy's param must satisfy (spec §4.2). */
165
+ options?: OptionRow[];
166
+ /** This member infuses an existing object; its effect is an item-vocabulary overlay (spec §4.2). */
167
+ infuse?: InfuseBlock;
90
168
  }
@@ -1,3 +1,12 @@
1
+ /** ART-a (spec §4.5): the at-once counter of an item-bound pool; its defaults are applied at read (`poolActiveWords`). */
2
+ export interface PoolActive {
3
+ column: string;
4
+ label: string;
5
+ verb: string;
6
+ counter_label?: string;
7
+ create_label?: string;
8
+ create_verb?: string;
9
+ }
1
10
  /** A (sub)class-declared selectable pool (e.g. Interdict Boons). The engine is
2
11
  * generic: every game-specific string lives here in data, never in code. */
3
12
  export interface SelectionPool {
@@ -10,11 +19,17 @@ export interface SelectionPool {
10
19
  available_to: "self";
11
20
  };
12
21
  };
13
- /** Pick count read from the owning class table column at the current level. */
22
+ /** Pick count read from the owning class table column at the current level. `label` is the known-counter word,
23
+ * read through `poolCountLabel` (absent reads "Known", ART-a spec §4.5). */
14
24
  count: {
15
25
  column: string;
26
+ label?: string;
16
27
  };
17
28
  replaceable?: boolean;
29
+ /** ART-a (spec §4.5): the at-once counter (Infused Items, Magic Items). */
30
+ active?: PoolActive;
31
+ /** ART-a (spec §4.5): a resource id the tab head shows when the pool spends none of its own. */
32
+ head_resource?: string;
18
33
  }
19
34
  /** Subclass auto-grants that extend a named pool and do NOT count toward picks. */
20
35
  export interface PoolGrant {
@@ -1,13 +1,15 @@
1
1
  import type { WeaponEntity } from "./weapon.types.js";
2
2
  /** The two attack modes a weapon supports, derived from data the SRD pipeline
3
- * actually preserves. The SRD runtime data miscategorizes throwable MELEE
4
- * weapons (dagger/spear/handaxe/javelin/light hammer/trident) as `*-ranged`,
5
- * so the melee/ranged split is reconstructed here instead of trusted:
6
- * a category-ranged weapon is PURE ranged only when it needs ammunition or
7
- * loading, or is one of the two genuinely-ranged thrown weapons (dart, net —
8
- * a closed SRD set; a homebrew weapon whose bare slug is exactly "dart"/"net"
9
- * is force-classified pure ranged). Everything else category-ranged is a
10
- * throwable melee weapon. `reach` is 5 ft, +5 with the reach property. */
3
+ * actually preserves. Since dnd5e 0.3.13 the SRD data files the throwable
4
+ * MELEE weapons (dagger/spear/handaxe/javelin/light hammer/trident) as
5
+ * `*-melee`, but older SRD data, imported records and homebrew can still file
6
+ * them as `*-ranged` (by their thrown range), so the melee/ranged split is
7
+ * reconstructed here instead of trusted: a category-ranged weapon is PURE
8
+ * ranged only when it needs ammunition or loading, or is one of the two
9
+ * genuinely-ranged thrown weapons (dart, net: a closed SRD set; a homebrew
10
+ * weapon whose bare slug is exactly "dart"/"net" is force-classified pure
11
+ * ranged). Everything else category-ranged is a throwable melee weapon.
12
+ * `reach` is 5 ft., +5 with the reach property. */
11
13
  export interface WeaponRangeModes {
12
14
  melee: {
13
15
  reach: number;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  classifyWeaponRange
3
- } from "../chunk-UIRMA5KM.js";
4
- import "../chunk-6X4KUDMU.js";
3
+ } from "../chunk-YDGMBMYI.js";
4
+ import "../chunk-ZCTUYGNV.js";
5
5
  export {
6
6
  classifyWeaponRange
7
7
  };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  weaponCodec
3
- } from "../chunk-LDDCNPHD.js";
4
- import "../chunk-HZA7OE7N.js";
5
- import "../chunk-2DFENQIJ.js";
3
+ } from "../chunk-K5NJBTE2.js";
4
+ import "../chunk-XCFC7LGF.js";
5
+ import "../chunk-5GKJAUMX.js";
6
6
  import "../chunk-UA5KS2PL.js";
7
7
  export {
8
8
  weaponCodec
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parseWeapon
3
- } from "../chunk-HZA7OE7N.js";
4
- import "../chunk-2DFENQIJ.js";
3
+ } from "../chunk-XCFC7LGF.js";
4
+ import "../chunk-5GKJAUMX.js";
5
5
  import "../chunk-UA5KS2PL.js";
6
6
  export {
7
7
  parseWeapon
@@ -31,6 +31,7 @@ export declare const weaponEntitySchema: z.ZodObject<{
31
31
  }>;
32
32
  entries: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
33
33
  rendering_hint: z.ZodOptional<z.ZodString>;
34
+ icon: z.ZodOptional<z.ZodString>;
34
35
  has_fluff: z.ZodOptional<z.ZodBoolean>;
35
36
  has_fluff_images: z.ZodOptional<z.ZodBoolean>;
36
37
  image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  weaponEntitySchema
3
- } from "../chunk-2DFENQIJ.js";
3
+ } from "../chunk-5GKJAUMX.js";
4
4
  import "../chunk-UA5KS2PL.js";
5
5
  export {
6
6
  weaponEntitySchema
@@ -36,6 +36,8 @@ export interface WeaponEntity {
36
36
  entries?: unknown[];
37
37
  /** Carried as the empty string on every converter weapon carrier today (98). */
38
38
  rendering_hint?: string;
39
+ /** The icon key (I3): a key of the renderer's icon set or a Lucide name. */
40
+ icon?: string;
39
41
  has_fluff?: boolean;
40
42
  has_fluff_images?: boolean;
41
43
  /** One wikilink, or an array for >= 2 fluff images (images-ON emit). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archivist-gg/dnd5e",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "license": "MIT AND CC-BY-4.0",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,165 +0,0 @@
1
- import {
2
- derivePoolLayout
3
- } from "./chunk-PP2UHLBA.js";
4
- import {
5
- readTableColumn
6
- } from "./chunk-IUAAXXNO.js";
7
- import {
8
- warnOnce
9
- } from "./chunk-LVQLWRCU.js";
10
- import {
11
- bareEntitySlug,
12
- wikilinkTailSlug
13
- } from "./chunk-6X4KUDMU.js";
14
-
15
- // src/pc/pc.pools.ts
16
- function levelPrereqMax(d) {
17
- var _a;
18
- return ((_a = d.prerequisites) != null ? _a : []).filter((p) => p.kind === "level").reduce((m, p) => Math.max(m, p.min), 0);
19
- }
20
- function resolvePool(rc, classIndex, pool, registry, index) {
21
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
22
- const entity = rc.entity;
23
- const level = rc.level;
24
- const ownerBare = bareEntitySlug(entity.slug);
25
- const ownerPrefix = entity.slug.split("_")[0];
26
- const col = pool.count.column;
27
- const count = (_a = readTableColumn(entity.table, level, [col])) != null ? _a : 0;
28
- let anchorLevel = 1;
29
- let columnSeen = false;
30
- for (let l = 1; l <= 20; l++) {
31
- const c = readTableColumn(entity.table, l, [col]);
32
- if (c != null) columnSeen = true;
33
- if (c != null && c >= 1) {
34
- anchorLevel = l;
35
- break;
36
- }
37
- }
38
- if (!columnSeen) {
39
- warnOnce(
40
- `pool-column:${pool.id}`,
41
- `Archivist: pool "${pool.id}" declares count column "${col}", which "${entity.slug}"'s class table carries at no level; the pool resolves count 0 at anchor level 1`
42
- );
43
- }
44
- const ft = pool.source.where.feature_type;
45
- const all = registry.search("", "optional-feature", Number.POSITIVE_INFINITY).slice().sort((a, b) => a.name.localeCompare(b.name) || a.slug.localeCompare(b.slug));
46
- const byBare = /* @__PURE__ */ new Map();
47
- const candidates = /* @__PURE__ */ new Map();
48
- for (const e of all) {
49
- const d = e.data;
50
- const entry = { slug: e.slug, entity: d, ...e.compendium ? { compendium: e.compendium } : {} };
51
- const bare = bareEntitySlug(e.slug);
52
- byBare.set(bare, entry);
53
- if (d.feature_type !== ft) continue;
54
- if (!((_b = d.available_to) != null ? _b : []).some((l) => wikilinkTailSlug(l) === ownerBare)) continue;
55
- if (levelPrereqMax(d) > level) continue;
56
- const group = candidates.get(bare);
57
- if (group) group.push(entry);
58
- else candidates.set(bare, [entry]);
59
- }
60
- const available = [];
61
- for (const [bare, group] of candidates) {
62
- if (group.length === 1) {
63
- available.push(group[0]);
64
- continue;
65
- }
66
- const owned = group.find((e) => e.slug.split("_")[0] === ownerPrefix);
67
- if (!owned) {
68
- warnOnce(
69
- `pool-collapse:${bare}`,
70
- `Archivist: pool "${pool.id}" holds ${group.length} cross-edition entries for "${bare}" and none shares the owner's compendium prefix "${ownerPrefix}"; keeping "${group[0].slug}"`
71
- );
72
- }
73
- available.push(owned != null ? owned : group[0]);
74
- }
75
- const grantDecls = [
76
- ...(_d = (_c = rc.entity) == null ? void 0 : _c.pool_grants) != null ? _d : [],
77
- ...(_f = (_e = rc.subclass) == null ? void 0 : _e.pool_grants) != null ? _f : []
78
- ];
79
- const grantsRaw = grantDecls.filter((g) => g.pool === pool.id).flatMap((g) => g.grants).filter((g) => g.at_level <= level).map((g) => byBare.get(wikilinkTailSlug(g.feature))).filter((e) => e != null);
80
- const grantedBare = /* @__PURE__ */ new Set();
81
- const grants = grantsRaw.filter((e) => {
82
- const key = bareEntitySlug(e.slug);
83
- if (grantedBare.has(key)) return false;
84
- grantedBare.add(key);
85
- return true;
86
- });
87
- const bySlugAvailable = new Map(available.map((e) => [e.slug, e]));
88
- const byBareAvailable = new Map(available.map((e) => [bareEntitySlug(e.slug), e]));
89
- const resolveStored = (s) => {
90
- const exact = bySlugAvailable.get(s);
91
- if (exact) return exact;
92
- const survivor = byBareAvailable.get(bareEntitySlug(s));
93
- if (survivor) return survivor;
94
- const full = registry.getByTypeAndSlug("optional-feature", s);
95
- if (full) {
96
- const d = full.data;
97
- return { slug: full.slug, entity: d, ...full.compendium ? { compendium: full.compendium } : {} };
98
- }
99
- return byBare.get(bareEntitySlug(s));
100
- };
101
- const raw = (_g = rc.choices[anchorLevel]) == null ? void 0 : _g[pool.id];
102
- const selectedSlugs = Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
103
- const selected = [];
104
- const seenBare = /* @__PURE__ */ new Set();
105
- for (const s of selectedSlugs) {
106
- const entry = resolveStored(s);
107
- if (!entry) continue;
108
- const bare = bareEntitySlug(entry.slug);
109
- if (grantedBare.has(bare) || seenBare.has(bare)) continue;
110
- seenBare.add(bare);
111
- selected.push(entry);
112
- }
113
- const members = [...available, ...grants];
114
- const layout = derivePoolLayout(members);
115
- const votes = /* @__PURE__ */ new Map();
116
- for (const e of members) {
117
- const id = (_h = e.entity.consumes) == null ? void 0 : _h.resource;
118
- if (!id || !index.has(id)) continue;
119
- votes.set(id, ((_i = votes.get(id)) != null ? _i : 0) + 1);
120
- }
121
- let resource;
122
- let bestN = 0;
123
- for (const [id, n] of votes) if (n > bestN) {
124
- resource = id;
125
- bestN = n;
126
- }
127
- return {
128
- id: pool.id,
129
- label: pool.label,
130
- classIndex,
131
- count,
132
- anchorLevel,
133
- selected,
134
- available,
135
- grants,
136
- ...layout ? { layout } : {},
137
- ...resource ? { resource } : {}
138
- };
139
- }
140
- function resolveAllPools(resolved, registry, index) {
141
- const out = [];
142
- resolved.classes.forEach((rc, classIndex) => {
143
- var _a, _b, _c;
144
- if (!rc.entity) return;
145
- const decls = [...(_a = rc.entity.selection_pools) != null ? _a : [], ...(_c = (_b = rc.subclass) == null ? void 0 : _b.selection_pools) != null ? _c : []];
146
- const seen = /* @__PURE__ */ new Set();
147
- for (const pool of decls) {
148
- if (seen.has(pool.id)) continue;
149
- seen.add(pool.id);
150
- out.push(resolvePool(rc, classIndex, pool, registry, index));
151
- }
152
- });
153
- return out;
154
- }
155
- function strandedPicks(pool) {
156
- const inAvailable = new Set(pool.available.map((e) => e.slug));
157
- return pool.selected.filter((e) => !inAvailable.has(e.slug));
158
- }
159
-
160
- export {
161
- levelPrereqMax,
162
- resolvePool,
163
- resolveAllPools,
164
- strandedPicks
165
- };
@@ -1,55 +0,0 @@
1
- import {
2
- slugify
3
- } from "./chunk-6X4KUDMU.js";
4
-
5
- // src/entities/base-item-resolver.ts
6
- function unwrapWikilink(input) {
7
- const m = /^\[\[([^\]]+)\]\]$/.exec(input.trim());
8
- if (!m) return null;
9
- const inner = m[1];
10
- const pipe = inner.indexOf("|");
11
- return pipe === -1 ? inner : inner.slice(0, pipe);
12
- }
13
- var FOLDER_TO_TYPE = {
14
- Weapons: "weapon",
15
- Armor: "armor",
16
- "Magic Items": "item"
17
- };
18
- function vaultPathToSlug(target) {
19
- const segments = target.split("/").map((s) => s.trim()).filter((s) => s.length > 0);
20
- if (segments.length === 0) return "";
21
- if (segments.length === 1) {
22
- return slugify(segments[0]);
23
- }
24
- const compendiumName = segments[0];
25
- const typeFolder = segments[segments.length - 2];
26
- const basename = segments[segments.length - 1];
27
- const prefix = slugify(compendiumName);
28
- const nameSlug = slugify(basename);
29
- if (!prefix || !nameSlug) return nameSlug;
30
- const type = FOLDER_TO_TYPE[typeFolder];
31
- return type ? `${prefix}_${type}_${nameSlug}` : `${prefix}_${nameSlug}`;
32
- }
33
- function resolveBaseItem(baseItem, registry) {
34
- var _a, _b;
35
- if (typeof baseItem !== "string" || baseItem.length === 0) return null;
36
- const target = (_a = unwrapWikilink(baseItem)) != null ? _a : baseItem.trim();
37
- if (target.length === 0) return null;
38
- if (!target.includes("/")) {
39
- const direct = registry.getBySlug(target);
40
- if (direct) return direct;
41
- }
42
- const slug = vaultPathToSlug(target);
43
- if (!slug) return null;
44
- return (_b = registry.getBySlug(slug)) != null ? _b : null;
45
- }
46
- function resolveBaseItemOfType(baseItem, entityType, registry) {
47
- const found = resolveBaseItem(baseItem, registry);
48
- return found && found.entityType === entityType ? found : null;
49
- }
50
-
51
- export {
52
- vaultPathToSlug,
53
- resolveBaseItem,
54
- resolveBaseItemOfType
55
- };