@optolith/database-schema 0.107.1 → 0.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.109.0](https://github.com/Optolith/database-schema/compare/v0.108.1...v0.109.0) (2026-10-17)
6
+
7
+ ### ⚠ BREAKING CHANGES
8
+
9
+ * item component references special ammunition only
10
+
11
+ ### Features
12
+
13
+ * special ammunition entity ([0b149a9](https://github.com/Optolith/database-schema/commit/0b149a9073f02f425cb56c52c0b4e60b819b3024))
14
+
15
+ ### Bug Fixes
16
+
17
+ * derived trade secrets for special ammunition ([83b8d14](https://github.com/Optolith/database-schema/commit/83b8d1410886d87b6f790fa4bb96c100f5c04ee8))
18
+ * item component references special ammunition only ([a200ecd](https://github.com/Optolith/database-schema/commit/a200ecd5bd31e4d4bdc4cf1f13f11d73b22d88ce))
19
+
20
+ ## [0.108.1](https://github.com/Optolith/database-schema/compare/v0.108.0...v0.108.1) (2026-10-17)
21
+
22
+ ### Bug Fixes
23
+
24
+ * property specialization translation name ([4049f08](https://github.com/Optolith/database-schema/commit/4049f0841e53da33e83f92d541d54093f1514914))
25
+
26
+ ## [0.108.0](https://github.com/Optolith/database-schema/compare/v0.107.1...v0.108.0) (2026-10-17)
27
+
28
+ ### ⚠ BREAKING CHANGES
29
+
30
+ * gems with associated properties and optional color
31
+
32
+ ### Features
33
+
34
+ * gems with associated properties and optional color ([48a4a5e](https://github.com/Optolith/database-schema/commit/48a4a5eea0cc07336bb49aef02f5e9118664a34e))
35
+ * property specializations ([83b38df](https://github.com/Optolith/database-schema/commit/83b38df2f64a61c63062dca23d127080605ae9a0))
36
+
37
+ ### Bug Fixes
38
+
39
+ * **cache:** talisman trade secret prerequisites include associated tradition ([9935e24](https://github.com/Optolith/database-schema/commit/9935e24fbf4788a84b27a5f115f74d0d6a6990e0))
40
+
5
41
  ## [0.107.1](https://github.com/Optolith/database-schema/compare/v0.107.0...v0.107.1) (2026-10-16)
6
42
 
7
43
  ### Features
package/gen/types.d.ts CHANGED
@@ -145,6 +145,7 @@ export type EntityMap = {
145
145
  ProfessionVariant: ProfessionVariant
146
146
  ProfessionVersion: ProfessionVersion
147
147
  Property: Property
148
+ PropertySpecialization: PropertySpecialization
148
149
  ProtectiveWardingCircleSpecialAbility: ProtectiveWardingCircleSpecialAbility
149
150
  Publication: Publication
150
151
  Race: Race
@@ -170,6 +171,7 @@ export type EntityMap = {
170
171
  SkillStyleSpecialAbility: SkillStyleSpecialAbility
171
172
  SkillUse: SkillUse
172
173
  SocialStatus: SocialStatus
174
+ SpecialAmmunition: SpecialAmmunition
173
175
  Spell: Spell
174
176
  SpellSwordEnchantment: SpellSwordEnchantment
175
177
  StaffEnchantment: StaffEnchantment
@@ -217,6 +219,7 @@ export type ChildEntityMap = {
217
219
  ProfessionPackage: [ProfessionPackage, "profession_version", ProfessionPackage["profession_version"]]
218
220
  ProfessionVariant: [ProfessionVariant, "profession_package", ProfessionVariant["profession_package"]]
219
221
  ProfessionVersion: [ProfessionVersion, "profession", ProfessionVersion["profession"]]
222
+ PropertySpecialization: [PropertySpecialization, "parent", PropertySpecialization["parent"]]
220
223
  RaceVariant: [RaceVariant, "race", RaceVariant["race"]]
221
224
  SkillApplication: [SkillApplication, "parent", SkillApplication["parent"]]
222
225
  SkillUse: [SkillUse, "parent", SkillUse["parent"]]
@@ -247,6 +250,7 @@ export type EnumMap = {
247
250
  AnimistPowerImprovementCost: AnimistPowerImprovementCost
248
251
  AnimistPowerPerformanceParameters: AnimistPowerPerformanceParameters
249
252
  AnimistPowerPrerequisiteGroup: AnimistPowerPrerequisiteGroup
253
+ AnyPropertySpecializationIdentifier: AnyPropertySpecializationIdentifier
250
254
  ApplicableAmmunitionCategory: ApplicableAmmunitionCategory
251
255
  ApplicableArmorCategory: ApplicableArmorCategory
252
256
  ApplicableCombatTechniques: ApplicableCombatTechniques
@@ -321,6 +325,7 @@ export type EnumMap = {
321
325
  DerivedCharacteristicPrimaryAttributeValue: DerivedCharacteristicPrimaryAttributeValue
322
326
  DerivedCharacteristicSkillCheckPenalty: DerivedCharacteristicSkillCheckPenalty
323
327
  DerivedCharacteristicType: DerivedCharacteristicType
328
+ DerivedPropertySpecializations: DerivedPropertySpecializations
324
329
  DisplayOption: DisplayOption
325
330
  DominationRitualDuration: DominationRitualDuration
326
331
  DurationForOneTime: DurationForOneTime
@@ -724,6 +729,7 @@ export type TypeAliasMap = {
724
729
  FixedRange: FixedRange
725
730
  FixedSustainedAnimistPowerCost: FixedSustainedAnimistPowerCost
726
731
  FixedVolume: FixedVolume
732
+ GemOrPreviousStoneProperty: GemOrPreviousStoneProperty
727
733
  GeneralAnimalCare: GeneralAnimalCare
728
734
  GeneralPrerequisites: GeneralPrerequisites
729
735
  GenericSkillsSelectOptionCategoryCategory: GenericSkillsSelectOptionCategoryCategory<unknown>
@@ -5477,6 +5483,11 @@ export interface Property {
5477
5483
  */
5478
5484
  check?: SkillCheck
5479
5485
 
5486
+ /**
5487
+ * The property’s derived specializations.
5488
+ */
5489
+ derivedSpecializations?: DerivedPropertySpecializations
5490
+
5480
5491
  /**
5481
5492
  * All translations for the entry, identified by IETF language tag (BCP47).
5482
5493
  */
@@ -5497,6 +5508,37 @@ export interface PropertyTranslation {
5497
5508
  name: string
5498
5509
  }
5499
5510
 
5511
+ export interface PropertySpecialization {
5512
+ /**
5513
+ * The associated property.
5514
+ */
5515
+ parent: Property_ID
5516
+
5517
+ /**
5518
+ * All translations for the entry, identified by IETF language tag (BCP47).
5519
+ */
5520
+ translations: {
5521
+ [localeId: string]: PropertySpecializationTranslation
5522
+ }
5523
+ }
5524
+
5525
+ /**
5526
+ * The entity’s identifier. A UUID or a locale code if it is registered as the locale entity.
5527
+ */
5528
+ export type PropertySpecialization_ID = string
5529
+
5530
+ export interface PropertySpecializationTranslation {
5531
+ /**
5532
+ * The property’s name.
5533
+ */
5534
+ name: string
5535
+ }
5536
+
5537
+ export type DerivedPropertySpecializations =
5538
+ | {
5539
+ kind: "Elements"
5540
+ }
5541
+
5500
5542
  export interface Aspect {
5501
5543
  /**
5502
5544
  * All translations for the entry, identified by IETF language tag (BCP47).
@@ -8683,6 +8725,11 @@ export interface Spell {
8683
8725
  */
8684
8726
  property: Property_ID
8685
8727
 
8728
+ /**
8729
+ * The associated property specialization.
8730
+ */
8731
+ propertySpecialization?: AnyPropertySpecializationIdentifier
8732
+
8686
8733
  /**
8687
8734
  * The tradition(s) the spell is available for. It may be *generally* available to all traditions or it may be only familiar in specific traditions.
8688
8735
  */
@@ -8745,6 +8792,16 @@ export interface SpellTranslation {
8745
8792
  errata?: Errata
8746
8793
  }
8747
8794
 
8795
+ export type AnyPropertySpecializationIdentifier =
8796
+ | {
8797
+ kind: "General"
8798
+ General: PropertySpecialization_ID
8799
+ }
8800
+ | {
8801
+ kind: "Element"
8802
+ Element: Element_ID
8803
+ }
8804
+
8748
8805
  /**
8749
8806
  * The tradition(s) the spell or ritual is available for. It may be *generally* available to all traditions or it may be only familiar in specific traditions.
8750
8807
  */
@@ -9190,6 +9247,11 @@ export interface Ritual {
9190
9247
  */
9191
9248
  property: Property_ID
9192
9249
 
9250
+ /**
9251
+ * The associated property specialization.
9252
+ */
9253
+ propertySpecialization?: AnyPropertySpecializationIdentifier
9254
+
9193
9255
  /**
9194
9256
  * The tradition(s) the ritual is available for. It may be *generally* available to all traditions or it may be only familiar in specific traditions.
9195
9257
  */
@@ -26130,6 +26192,11 @@ export interface GemOrPreciousStone {
26130
26192
  */
26131
26193
  weight?: Weight
26132
26194
 
26195
+ /**
26196
+ * The associated property.
26197
+ */
26198
+ property?: GemOrPreviousStoneProperty
26199
+
26133
26200
  /**
26134
26201
  * The prerequisites of the item, if any. Note that this is fully separate from the prerequisites of the item’s trade secret, which are defined independently from this.
26135
26202
  */
@@ -26167,7 +26234,7 @@ export interface GemOrPreciousStoneTranslation {
26167
26234
  /**
26168
26235
  * The color of the gem or stone.
26169
26236
  */
26170
- color: string
26237
+ color?: string
26171
26238
 
26172
26239
  /**
26173
26240
  * Note text.
@@ -26182,6 +26249,18 @@ export interface GemOrPreciousStoneTranslation {
26182
26249
  errata?: Errata
26183
26250
  }
26184
26251
 
26252
+ export interface GemOrPreviousStoneProperty {
26253
+ /**
26254
+ * The associated property.
26255
+ */
26256
+ base: Property_ID
26257
+
26258
+ /**
26259
+ * The associated property specialization.
26260
+ */
26261
+ specialization?: AnyPropertySpecializationIdentifier
26262
+ }
26263
+
26185
26264
  export interface IlluminationLightSource {
26186
26265
  /**
26187
26266
  * The cost in silverthalers.
@@ -26650,7 +26729,7 @@ export interface ApplicableAmmunition {
26650
26729
  /**
26651
26730
  * Specific ammunition this component can be applied to.
26652
26731
  */
26653
- ammunition?: Ammunition_ID[]
26732
+ ammunition?: SpecialAmmunition_ID[]
26654
26733
 
26655
26734
  /**
26656
26735
  * Whether the list of ammunition is inverted, i.e. whether the component can be applied to all ammunition – or those of the specified category – except for the listed ammunition.
@@ -26663,6 +26742,69 @@ export interface ApplicableAmmunition {
26663
26742
  category?: ApplicableAmmunitionCategory
26664
26743
  }
26665
26744
 
26745
+ export interface SpecialAmmunition {
26746
+ /**
26747
+ * The base ammunition type that is affected by this specialization.
26748
+ */
26749
+ applicableTo: Ammunition_ID[]
26750
+
26751
+ /**
26752
+ * The cost modifier for the base price of affected ammunition.
26753
+ */
26754
+ costModifier: number
26755
+
26756
+ /**
26757
+ * The complexity of crafting the item.
26758
+ */
26759
+ complexity?: Complexity
26760
+
26761
+ /**
26762
+ * The prerequisites of the item, if any. Note that this is fully separate from the prerequisites of the item’s trade secret, which are defined independently from this.
26763
+ */
26764
+ prerequisites?: EquipmentPrerequisites
26765
+
26766
+ /**
26767
+ * References to where in which publications this entry has been defined. Entries may also be added or removed in later printings.
26768
+ */
26769
+ src: PublicationRefs
26770
+
26771
+ /**
26772
+ * All translations for the entry, identified by IETF language tag (BCP47).
26773
+ */
26774
+ translations: {
26775
+ [localeId: string]: SpecialAmmunitionTranslation
26776
+ }
26777
+ }
26778
+
26779
+ /**
26780
+ * The entity’s identifier. A UUID or a locale code if it is registered as the locale entity.
26781
+ */
26782
+ export type SpecialAmmunition_ID = string
26783
+
26784
+ export interface SpecialAmmunitionTranslation {
26785
+ /**
26786
+ * The item’s name.
26787
+ */
26788
+ name: string
26789
+
26790
+ /**
26791
+ * An auxiliary name or label of the item, if available.
26792
+ */
26793
+ secondary_name?: string
26794
+
26795
+ /**
26796
+ * Note text.
26797
+ */
26798
+ note?: string
26799
+
26800
+ /**
26801
+ * Special rules text.
26802
+ */
26803
+ rules?: string
26804
+
26805
+ errata?: Errata
26806
+ }
26807
+
26666
26808
  export type ApplicableAmmunitionCategory =
26667
26809
  | {
26668
26810
  kind: "ArrowOrBolt"
@@ -5,7 +5,7 @@ type EquipmentEntitiesWithComplexities = {
5
5
  [K in EquipmentIdentifier["kind"]]: EntityMap[K] extends {
6
6
  complexity?: Complexity | ArmorComplexity;
7
7
  } ? K : never;
8
- }[EquipmentIdentifier["kind"]];
8
+ }[EquipmentIdentifier["kind"]] | "SpecialAmmunition";
9
9
  type HerbaryEntitiesWithTradeSecrets = "Disease" | "Elixir" | "HerbalAid" | "Poison";
10
10
  export type DerivedTradeSecretsCache = {
11
11
  equipment: {
@@ -1,3 +1,5 @@
1
+ import { isNotEmpty } from "@elyukai/utils/array/nonEmpty";
2
+ import { nullableToArray } from "@elyukai/utils/nullable";
1
3
  import { assertExhaustive } from "@elyukai/utils/typeSafety";
2
4
  import { Case } from "tsondb/schema/gen";
3
5
  const emptyDerivedEquipmentTradeSecretsCache = {
@@ -20,6 +22,7 @@ const emptyDerivedEquipmentTradeSecretsCache = {
20
22
  MusicalInstrument: {},
21
23
  OrienteeringAid: {},
22
24
  RopeOrChain: {},
25
+ SpecialAmmunition: {},
23
26
  Stationery: {},
24
27
  ThievesTool: {},
25
28
  ToolOfTheTrade: {},
@@ -146,6 +149,19 @@ export const buildDerivedTradeSecretsCache = (database, settings) => {
146
149
  id: Case("FocusRule", settings.derivedTradeSecrets.requiredFocusRuleForTalismans),
147
150
  active: true,
148
151
  })),
152
+ ...nullableToArray(container.content.tradition === undefined || !isNotEmpty(container.content.tradition)
153
+ ? undefined
154
+ : container.content.tradition.length === 1
155
+ ? Case("Single", Case("Activatable", {
156
+ id: Case("BlessedTradition", container.content.tradition[0]),
157
+ active: true,
158
+ }))
159
+ : Case("Disjunction", {
160
+ list: container.content.tradition.map(tradition => Case("Activatable", {
161
+ id: Case("BlessedTradition", tradition),
162
+ active: true,
163
+ })),
164
+ })),
149
165
  ],
150
166
  src: container.content.src,
151
167
  translations: Object.fromEntries(Object.entries(container.content.translations).map(([lang, translation]) => [
package/lib/main.js CHANGED
@@ -153,6 +153,7 @@ export const schema = new Schema((await import("../package.json", { with: { type
153
153
  Types.SkillModificationLevel,
154
154
  Types.SkillStyleSpecialAbility,
155
155
  Types.SocialStatus,
156
+ Types.SpecialAmmunition,
156
157
  Types.Spell,
157
158
  Types.SpellSwordEnchantment,
158
159
  Types.StaffEnchantment,
@@ -1,7 +1,22 @@
1
1
  import * as DB from "tsondb/schema/dsl";
2
2
  export declare const Property: DB.Entity<"Property", {
3
3
  check: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"SkillCheck", DB.Array<DB.ReferenceIdentifier>, []>>, false>;
4
+ specializations: DB.MemberDecl<DB.ChildEntities<DB.Entity<"PropertySpecialization", {
5
+ parent: DB.MemberDecl<DB.ReferenceIdentifier, true>;
6
+ translations: DB.MemberDecl<DB.NestedEntityMap<"PropertySpecializationTranslation", {
7
+ name: DB.MemberDecl<DB.String, true>;
8
+ }>, true>;
9
+ }, "parent">>, true>;
10
+ derivedSpecializations: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"DerivedPropertySpecializations", {
11
+ Elements: DB.EnumCase<null>;
12
+ }, []>>, false>;
4
13
  translations: DB.MemberDecl<DB.NestedEntityMap<"PropertyTranslation", {
5
14
  name: DB.MemberDecl<DB.String, true>;
6
15
  }>, true>;
7
16
  }, undefined>;
17
+ export declare const PropertySpecialization: DB.Entity<"PropertySpecialization", {
18
+ parent: DB.MemberDecl<DB.ReferenceIdentifier, true>;
19
+ translations: DB.MemberDecl<DB.NestedEntityMap<"PropertySpecializationTranslation", {
20
+ name: DB.MemberDecl<DB.String, true>;
21
+ }>, true>;
22
+ }, "parent">;
@@ -1,4 +1,5 @@
1
1
  import * as DB from "tsondb/schema/dsl";
2
+ import { PropertyIdentifier } from "./_Identifier.js";
2
3
  import { SkillCheck } from "./_SkillCheck.js";
3
4
  import { NestedTranslationMap } from "./Locale.js";
4
5
  export const Property = DB.Entity(import.meta.url, {
@@ -9,6 +10,14 @@ export const Property = DB.Entity(import.meta.url, {
9
10
  comment: "The property check’s attributes. Only the properties from the Core Rules have defined property checks.",
10
11
  type: DB.IncludeIdentifier(SkillCheck),
11
12
  }),
13
+ specializations: DB.Required({
14
+ comment: "The property’s specializations.",
15
+ type: DB.ChildEntities(PropertySpecialization),
16
+ }),
17
+ derivedSpecializations: DB.Optional({
18
+ comment: "The property’s derived specializations.",
19
+ type: DB.IncludeIdentifier(DerivedPropertySpecializations),
20
+ }),
12
21
  translations: NestedTranslationMap(DB.Required, "Property", DB.Object({
13
22
  name: DB.Required({
14
23
  comment: "The property’s name.",
@@ -24,3 +33,33 @@ export const Property = DB.Entity(import.meta.url, {
24
33
  },
25
34
  ],
26
35
  });
36
+ const DerivedPropertySpecializations = DB.Enum(import.meta.url, {
37
+ name: "DerivedPropertySpecializations",
38
+ values: () => ({
39
+ Elements: DB.EnumCase({ type: null }),
40
+ }),
41
+ });
42
+ export const PropertySpecialization = DB.Entity(import.meta.url, {
43
+ name: "PropertySpecialization",
44
+ namePlural: "PropertySpecializations",
45
+ type: () => DB.Object({
46
+ parent: DB.Required({
47
+ comment: "The associated property.",
48
+ type: PropertyIdentifier(),
49
+ }),
50
+ translations: NestedTranslationMap(DB.Required, "PropertySpecialization", DB.Object({
51
+ name: DB.Required({
52
+ comment: "The property’s name.",
53
+ type: DB.String({ minLength: 1 }),
54
+ }),
55
+ })),
56
+ }),
57
+ parentReferenceKey: "parent",
58
+ instanceDisplayName: {},
59
+ uniqueConstraints: [
60
+ {
61
+ entityMapKeyPath: "translations",
62
+ keyPathInEntityMap: "name",
63
+ },
64
+ ],
65
+ });
@@ -560,6 +560,10 @@ export declare const Ritual: DB.Entity<"Ritual", {
560
560
  }>, false>;
561
561
  }>, []>>>, []>>, true>;
562
562
  property: DB.MemberDecl<DB.ReferenceIdentifier, true>;
563
+ propertySpecialization: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"AnyPropertySpecializationIdentifier", {
564
+ General: DB.EnumCase<DB.ReferenceIdentifier>;
565
+ Element: DB.EnumCase<DB.ReferenceIdentifier>;
566
+ }, []>>, false>;
563
567
  traditions: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"SpellworkTraditions", {
564
568
  General: DB.EnumCase<null>;
565
569
  Specific: DB.EnumCase<DB.Array<DB.ReferenceIdentifier>>;
@@ -4,6 +4,7 @@ import { ActivatableSkillEffect } from "./_ActivatableSkillEffect.js";
4
4
  import { AffectedTargetCategories } from "./_ActivatableSkillTargetCategory.js";
5
5
  import { Enhancement } from "./_Enhancements.js";
6
6
  import { PropertyIdentifier } from "./_Identifier.js";
7
+ import { AnyPropertySpecializationIdentifier } from "./_IdentifierGroup.js";
7
8
  import { ImprovementCost } from "./_ImprovementCost.js";
8
9
  import { SpellworkPrerequisites } from "./_Prerequisite.js";
9
10
  import { SkillCheck, SkillCheckPenalty } from "./_SkillCheck.js";
@@ -35,6 +36,10 @@ export const Ritual = DB.Entity(import.meta.url, {
35
36
  comment: "The associated property.",
36
37
  type: PropertyIdentifier(),
37
38
  }),
39
+ propertySpecialization: DB.Optional({
40
+ comment: "The associated property specialization.",
41
+ type: DB.IncludeIdentifier(AnyPropertySpecializationIdentifier),
42
+ }),
38
43
  traditions: DB.Required({
39
44
  comment: "The tradition(s) the ritual is available for. It may be *generally* available to all traditions or it may be only familiar in specific traditions.",
40
45
  type: DB.IncludeIdentifier(SpellworkTraditions),
@@ -560,6 +560,10 @@ export declare const Spell: DB.Entity<"Spell", {
560
560
  }>, false>;
561
561
  }>, []>>>, []>>, true>;
562
562
  property: DB.MemberDecl<DB.ReferenceIdentifier, true>;
563
+ propertySpecialization: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"AnyPropertySpecializationIdentifier", {
564
+ General: DB.EnumCase<DB.ReferenceIdentifier>;
565
+ Element: DB.EnumCase<DB.ReferenceIdentifier>;
566
+ }, []>>, false>;
563
567
  traditions: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"SpellworkTraditions", {
564
568
  General: DB.EnumCase<null>;
565
569
  Specific: DB.EnumCase<DB.Array<DB.ReferenceIdentifier>>;
@@ -4,6 +4,7 @@ import { ActivatableSkillEffect } from "./_ActivatableSkillEffect.js";
4
4
  import { AffectedTargetCategories } from "./_ActivatableSkillTargetCategory.js";
5
5
  import { Enhancement } from "./_Enhancements.js";
6
6
  import { PropertyIdentifier } from "./_Identifier.js";
7
+ import { AnyPropertySpecializationIdentifier } from "./_IdentifierGroup.js";
7
8
  import { ImprovementCost } from "./_ImprovementCost.js";
8
9
  import { SpellworkPrerequisites } from "./_Prerequisite.js";
9
10
  import { SkillCheck, SkillCheckPenalty } from "./_SkillCheck.js";
@@ -35,6 +36,10 @@ export const Spell = DB.Entity(import.meta.url, {
35
36
  comment: "The associated property.",
36
37
  type: PropertyIdentifier(),
37
38
  }),
39
+ propertySpecialization: DB.Optional({
40
+ comment: "The associated property specialization.",
41
+ type: DB.IncludeIdentifier(AnyPropertySpecializationIdentifier),
42
+ }),
38
43
  traditions: DB.Required({
39
44
  comment: "The tradition(s) the spell is available for. It may be *generally* available to all traditions or it may be only familiar in specific traditions.",
40
45
  type: DB.IncludeIdentifier(SpellworkTraditions),
@@ -135,6 +135,7 @@ export declare const ProfessionPackageIdentifier: () => R;
135
135
  export declare const ProfessionVersionIdentifier: () => R;
136
136
  export declare const ProfessionVariantIdentifier: () => R;
137
137
  export declare const PropertyIdentifier: () => R;
138
+ export declare const PropertySpecializationIdentifier: () => R;
138
139
  export declare const ProtectiveWardingCircleSpecialAbilityIdentifier: () => R;
139
140
  export declare const PublicationIdentifier: () => R;
140
141
  export declare const RaceIdentifier: () => R;
@@ -160,6 +161,7 @@ export declare const SkillIdentifier: () => R;
160
161
  export declare const SkillModificationLevelIdentifier: () => R;
161
162
  export declare const SkillStyleSpecialAbilityIdentifier: () => R;
162
163
  export declare const SocialStatusIdentifier: () => R;
164
+ export declare const SpecialAmmunitionIdentifier: () => R;
163
165
  export declare const SpellIdentifier: () => R;
164
166
  export declare const SpellSwordEnchantmentIdentifier: () => R;
165
167
  export declare const StaffEnchantmentIdentifier: () => R;
@@ -51,6 +51,7 @@ import { OrienteeringAid } from "./equipment/item/OrienteeringAid.js";
51
51
  import { Plant } from "./equipment/item/Plant.js";
52
52
  import { Poison } from "./equipment/item/Poison.js";
53
53
  import { RopeOrChain } from "./equipment/item/RopeOrChain.js";
54
+ import { SpecialAmmunition } from "./equipment/item/SpecialAmmunition.js";
54
55
  import { Stationery } from "./equipment/item/Stationery.js";
55
56
  import { Biome } from "./equipment/item/sub/Biome.js";
56
57
  import { BotanicRegion } from "./equipment/item/sub/BotanicRegion.js";
@@ -87,7 +88,7 @@ import { Patron } from "./Patron.js";
87
88
  import { PatronCategory } from "./PatronCategory.js";
88
89
  import { PersonalityTrait } from "./PersonalityTrait.js";
89
90
  import { Profession, ProfessionPackage, ProfessionVariant, ProfessionVersion, } from "./Profession.js";
90
- import { Property } from "./Property.js";
91
+ import { Property, PropertySpecialization } from "./Property.js";
91
92
  import { Race, RaceVariant } from "./Race.js";
92
93
  import { Ritual } from "./Ritual.js";
93
94
  import { AlternativeRule } from "./rule/AlternativeRule.js";
@@ -305,6 +306,7 @@ export const ProfessionPackageIdentifier = () => R(ProfessionPackage);
305
306
  export const ProfessionVersionIdentifier = () => R(ProfessionVersion);
306
307
  export const ProfessionVariantIdentifier = () => R(ProfessionVariant);
307
308
  export const PropertyIdentifier = () => R(Property);
309
+ export const PropertySpecializationIdentifier = () => R(PropertySpecialization);
308
310
  export const ProtectiveWardingCircleSpecialAbilityIdentifier = () => R(PWCSpecialAbility);
309
311
  export const PublicationIdentifier = () => R(Publication);
310
312
  export const RaceIdentifier = () => R(Race);
@@ -330,6 +332,7 @@ export const SkillIdentifier = () => R(Skill);
330
332
  export const SkillModificationLevelIdentifier = () => R(SkillModificationLevel);
331
333
  export const SkillStyleSpecialAbilityIdentifier = () => R(SkillStyleSpecialAbility);
332
334
  export const SocialStatusIdentifier = () => R(SocialStatus);
335
+ export const SpecialAmmunitionIdentifier = () => R(SpecialAmmunition);
333
336
  export const SpellIdentifier = () => R(Spell);
334
337
  export const SpellSwordEnchantmentIdentifier = () => R(SpellSwordEnchantment);
335
338
  export const StaffEnchantmentIdentifier = () => R(StaffEnchantment);
@@ -480,3 +480,7 @@ export declare const TinyActivatableIdentifier: DB.Enum<"TinyActivatableIdentifi
480
480
  Blessing: DB.EnumCase<DB.ReferenceIdentifier>;
481
481
  Cantrip: DB.EnumCase<DB.ReferenceIdentifier>;
482
482
  }, []>;
483
+ export declare const AnyPropertySpecializationIdentifier: DB.Enum<"AnyPropertySpecializationIdentifier", {
484
+ General: DB.EnumCase<DB.ReferenceIdentifier>;
485
+ Element: DB.EnumCase<DB.ReferenceIdentifier>;
486
+ }, []>;
@@ -1,6 +1,6 @@
1
1
  import { sortObjectKeys } from "@elyukai/utils/object";
2
2
  import * as DB from "tsondb/schema/dsl";
3
- import { AdvancedCombatSpecialAbilityIdentifier, AdvancedKarmaSpecialAbilityIdentifier, AdvancedMagicalSpecialAbilityIdentifier, AdvancedSkillSpecialAbilityIdentifier, AdvantageIdentifier, AmmunitionIdentifier, AncestorGlyphIdentifier, AnimalCareIdentifier, AnimalIdentifier, AnimalShapeIdentifier, AnimalShapeSizeIdentifier, AnimistPowerIdentifier, ArcaneBardTraditionIdentifier, ArcaneDancerTraditionIdentifier, ArcaneOrbEnchantmentIdentifier, ArmorAccessoryIdentifier, ArmorIdentifier, AspectIdentifier, AttireEnchantmentIdentifier, AttributeIdentifier, BandageOrRemedyIdentifier, BannzeichenIdentifier, BeutelzauberIdentifier, BlessedTraditionIdentifier, BlessingIdentifier, BookIdentifier, BowlEnchantmentIdentifier, BrawlingSpecialAbilityIdentifier, CantripIdentifier, CauldronEnchantmentIdentifier, CeremonialItemIdentifier, CeremonialItemSpecialAbilityIdentifier, CeremonyIdentifier, ChronicleEnchantmentIdentifier, CloseCombatTechniqueIdentifier, ClothesIdentifier, ClothingPackageIdentifier, CombatSpecialAbilityIdentifier, CombatStyleSpecialAbilityIdentifier, CommandSpecialAbilityIdentifier, ContainerIdentifier, CultureIdentifier, CurseIdentifier, DaggerRitualIdentifier, DisadvantageIdentifier, DiseaseIdentifier, DominationRitualIdentifier, ElementIdentifier, ElixirIdentifier, ElvenMagicalSongIdentifier, EnhancementIdentifier, EquipmentOfBlessedOnesIdentifier, FamiliarSpecialAbilityIdentifier, FatePointSexSpecialAbilityIdentifier, FatePointSpecialAbilityIdentifier, FocusRuleIdentifier, FoolsHatEnchantmentIdentifier, GemOrPreciousStoneIdentifier, GeneralIdentifier, GeneralSpecialAbilityIdentifier, GeodeRitualIdentifier, GoblinRitualIdentifier, HaubenzauberIdentifier, HauerkettenzauberIdentifier, IlluminationLightSourceIdentifier, IlluminationRefillOrSupplyIdentifier, InstrumentEnchantmentIdentifier, ItemComponentIdentifier, JesterTrickIdentifier, JewelryIdentifier, KarmaSpecialAbilityIdentifier, KeulenzauberIdentifier, KrallenkettenzauberIdentifier, KristallkugelzauberIdentifier, LaboratoryIdentifier, LanguageIdentifier, LiebesspielzeugIdentifier, LiturgicalChantIdentifier, LiturgicalStyleSpecialAbilityIdentifier, LuxuryGoodIdentifier, LycantropicGiftIdentifier, MagicalArtifactIdentifier, MagicalDanceIdentifier, MagicalMelodyIdentifier, MagicalRuneIdentifier, MagicalSignIdentifier, MagicalSpecialAbilityIdentifier, MagicalTraditionIdentifier, MagicStyleSpecialAbilityIdentifier, MusicalInstrumentIdentifier, NewspaperIdentifier, OptionalRuleIdentifier, OrbEnchantmentIdentifier, OrienteeringAidIdentifier, PactGiftIdentifier, PatronIdentifier, PoisonIdentifier, PropertyIdentifier, ProtectiveWardingCircleSpecialAbilityIdentifier, RaceIdentifier, RangedCombatTechniqueIdentifier, RingEnchantmentIdentifier, RitualIdentifier, RopeOrChainIdentifier, SchweinetrommelzauberIdentifier, ScriptIdentifier, SermonIdentifier, SexPracticeIdentifier, SexSpecialAbilityIdentifier, SickleRitualIdentifier, SikaryanDrainSpecialAbilityIdentifier, SkillApplicationIdentifier, SkillGroupIdentifier, SkillIdentifier, SkillStyleSpecialAbilityIdentifier, SpellIdentifier, SpellSwordEnchantmentIdentifier, StaffEnchantmentIdentifier, StationeryIdentifier, TargetCategoryIdentifier, ThievesToolIdentifier, ToolOfTheTradeIdentifier, ToyEnchantmentIdentifier, TradeSecretIdentifier, TravelGearOrToolIdentifier, TrinkhornzauberIdentifier, VampiricGiftIdentifier, VehicleIdentifier, VisionIdentifier, WandEnchantmentIdentifier, WeaponAccessoryIdentifier, WeaponEnchantmentIdentifier, WeaponIdentifier, WorkingSupernaturalCreatureIdentifier, ZibiljaRitualIdentifier, } from "./_Identifier.js";
3
+ import { AdvancedCombatSpecialAbilityIdentifier, AdvancedKarmaSpecialAbilityIdentifier, AdvancedMagicalSpecialAbilityIdentifier, AdvancedSkillSpecialAbilityIdentifier, AdvantageIdentifier, AmmunitionIdentifier, AncestorGlyphIdentifier, AnimalCareIdentifier, AnimalIdentifier, AnimalShapeIdentifier, AnimalShapeSizeIdentifier, AnimistPowerIdentifier, ArcaneBardTraditionIdentifier, ArcaneDancerTraditionIdentifier, ArcaneOrbEnchantmentIdentifier, ArmorAccessoryIdentifier, ArmorIdentifier, AspectIdentifier, AttireEnchantmentIdentifier, AttributeIdentifier, BandageOrRemedyIdentifier, BannzeichenIdentifier, BeutelzauberIdentifier, BlessedTraditionIdentifier, BlessingIdentifier, BookIdentifier, BowlEnchantmentIdentifier, BrawlingSpecialAbilityIdentifier, CantripIdentifier, CauldronEnchantmentIdentifier, CeremonialItemIdentifier, CeremonialItemSpecialAbilityIdentifier, CeremonyIdentifier, ChronicleEnchantmentIdentifier, CloseCombatTechniqueIdentifier, ClothesIdentifier, ClothingPackageIdentifier, CombatSpecialAbilityIdentifier, CombatStyleSpecialAbilityIdentifier, CommandSpecialAbilityIdentifier, ContainerIdentifier, CultureIdentifier, CurseIdentifier, DaggerRitualIdentifier, DisadvantageIdentifier, DiseaseIdentifier, DominationRitualIdentifier, ElementIdentifier, ElixirIdentifier, ElvenMagicalSongIdentifier, EnhancementIdentifier, EquipmentOfBlessedOnesIdentifier, FamiliarSpecialAbilityIdentifier, FatePointSexSpecialAbilityIdentifier, FatePointSpecialAbilityIdentifier, FocusRuleIdentifier, FoolsHatEnchantmentIdentifier, GemOrPreciousStoneIdentifier, GeneralIdentifier, GeneralSpecialAbilityIdentifier, GeodeRitualIdentifier, GoblinRitualIdentifier, HaubenzauberIdentifier, HauerkettenzauberIdentifier, IlluminationLightSourceIdentifier, IlluminationRefillOrSupplyIdentifier, InstrumentEnchantmentIdentifier, ItemComponentIdentifier, JesterTrickIdentifier, JewelryIdentifier, KarmaSpecialAbilityIdentifier, KeulenzauberIdentifier, KrallenkettenzauberIdentifier, KristallkugelzauberIdentifier, LaboratoryIdentifier, LanguageIdentifier, LiebesspielzeugIdentifier, LiturgicalChantIdentifier, LiturgicalStyleSpecialAbilityIdentifier, LuxuryGoodIdentifier, LycantropicGiftIdentifier, MagicalArtifactIdentifier, MagicalDanceIdentifier, MagicalMelodyIdentifier, MagicalRuneIdentifier, MagicalSignIdentifier, MagicalSpecialAbilityIdentifier, MagicalTraditionIdentifier, MagicStyleSpecialAbilityIdentifier, MusicalInstrumentIdentifier, NewspaperIdentifier, OptionalRuleIdentifier, OrbEnchantmentIdentifier, OrienteeringAidIdentifier, PactGiftIdentifier, PatronIdentifier, PoisonIdentifier, PropertyIdentifier, PropertySpecializationIdentifier, ProtectiveWardingCircleSpecialAbilityIdentifier, RaceIdentifier, RangedCombatTechniqueIdentifier, RingEnchantmentIdentifier, RitualIdentifier, RopeOrChainIdentifier, SchweinetrommelzauberIdentifier, ScriptIdentifier, SermonIdentifier, SexPracticeIdentifier, SexSpecialAbilityIdentifier, SickleRitualIdentifier, SikaryanDrainSpecialAbilityIdentifier, SkillApplicationIdentifier, SkillGroupIdentifier, SkillIdentifier, SkillStyleSpecialAbilityIdentifier, SpellIdentifier, SpellSwordEnchantmentIdentifier, StaffEnchantmentIdentifier, StationeryIdentifier, TargetCategoryIdentifier, ThievesToolIdentifier, ToolOfTheTradeIdentifier, ToyEnchantmentIdentifier, TradeSecretIdentifier, TravelGearOrToolIdentifier, TrinkhornzauberIdentifier, VampiricGiftIdentifier, VehicleIdentifier, VisionIdentifier, WandEnchantmentIdentifier, WeaponAccessoryIdentifier, WeaponEnchantmentIdentifier, WeaponIdentifier, WorkingSupernaturalCreatureIdentifier, ZibiljaRitualIdentifier, } from "./_Identifier.js";
4
4
  export const ActivatableIdentifier = DB.Enum(import.meta.url, {
5
5
  name: "ActivatableIdentifier",
6
6
  values: () => ({
@@ -364,3 +364,10 @@ export const TinyActivatableIdentifier = DB.Enum(import.meta.url, {
364
364
  Cantrip: DB.EnumCase({ type: CantripIdentifier() }),
365
365
  }),
366
366
  });
367
+ export const AnyPropertySpecializationIdentifier = DB.Enum(import.meta.url, {
368
+ name: "AnyPropertySpecializationIdentifier",
369
+ values: () => ({
370
+ General: DB.EnumCase({ type: PropertySpecializationIdentifier() }),
371
+ Element: DB.EnumCase({ type: ElementIdentifier() }),
372
+ }),
373
+ });
@@ -23,6 +23,13 @@ export declare const GemOrPreciousStone: DB.Entity<"GemOrPreciousStone", {
23
23
  }>, []>>>;
24
24
  }, []>>, true>;
25
25
  weight: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"Weight", DB.Float, []>>, false>;
26
+ property: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"GemOrPreviousStoneProperty", DB.Object<{
27
+ base: DB.MemberDecl<DB.ReferenceIdentifier, true>;
28
+ specialization: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"AnyPropertySpecializationIdentifier", {
29
+ General: DB.EnumCase<DB.ReferenceIdentifier>;
30
+ Element: DB.EnumCase<DB.ReferenceIdentifier>;
31
+ }, []>>, false>;
32
+ }>, []>>, false>;
26
33
  prerequisites: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"EquipmentPrerequisites", DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PlainPrerequisites", DB.Array<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.Enum<"PrerequisitesElement", {
27
34
  Single: DB.EnumCase<DB.TypeArgument<DB.Param<"T", DB.Type>>>;
28
35
  Disjunction: DB.EnumCase<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PrerequisitesDisjunction", DB.Object<{
@@ -91,7 +98,7 @@ export declare const GemOrPreciousStone: DB.Entity<"GemOrPreciousStone", {
91
98
  translations: DB.MemberDecl<DB.NestedEntityMap<"GemOrPreciousStoneTranslation", {
92
99
  name: DB.MemberDecl<DB.String, true>;
93
100
  secondary_name: DB.MemberDecl<DB.String, false>;
94
- color: DB.MemberDecl<DB.String, true>;
101
+ color: DB.MemberDecl<DB.String, false>;
95
102
  note: DB.MemberDecl<DB.String, false>;
96
103
  rules: DB.MemberDecl<DB.String, false>;
97
104
  errata: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"Errata", DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"Erratum", DB.Object<{
@@ -1,4 +1,6 @@
1
1
  import * as DB from "tsondb/schema/dsl";
2
+ import { PropertyIdentifier } from "../../_Identifier.js";
3
+ import { AnyPropertySpecializationIdentifier } from "../../_IdentifierGroup.js";
2
4
  import { EquipmentPrerequisites } from "../../_Prerequisite.js";
3
5
  import { NestedTranslationMap } from "../../Locale.js";
4
6
  import { Errata } from "../../source/_Erratum.js";
@@ -16,6 +18,10 @@ export const GemOrPreciousStone = DB.Entity(import.meta.url, {
16
18
  comment: "The weight in kg.",
17
19
  type: DB.IncludeIdentifier(Weight),
18
20
  }),
21
+ property: DB.Optional({
22
+ comment: "The associated property.",
23
+ type: DB.IncludeIdentifier(GemOrPreviousStoneProperty),
24
+ }),
19
25
  prerequisites: DB.Optional({
20
26
  comment: "The prerequisites of the item, if any. Note that this is fully separate from the prerequisites of the item’s trade secret, which are defined independently from this.",
21
27
  type: DB.IncludeIdentifier(EquipmentPrerequisites),
@@ -30,7 +36,7 @@ export const GemOrPreciousStone = DB.Entity(import.meta.url, {
30
36
  comment: "An auxiliary name or label of the item, if available.",
31
37
  type: DB.String({ minLength: 1 }),
32
38
  }),
33
- color: DB.Required({
39
+ color: DB.Optional({
34
40
  comment: "The color of the gem or stone.",
35
41
  type: DB.String({ minLength: 1 }),
36
42
  }),
@@ -55,3 +61,16 @@ export const GemOrPreciousStone = DB.Entity(import.meta.url, {
55
61
  },
56
62
  ],
57
63
  });
64
+ const GemOrPreviousStoneProperty = DB.TypeAlias(import.meta.url, {
65
+ name: "GemOrPreviousStoneProperty",
66
+ type: () => DB.Object({
67
+ base: DB.Required({
68
+ comment: "The associated property.",
69
+ type: PropertyIdentifier(),
70
+ }),
71
+ specialization: DB.Optional({
72
+ comment: "The associated property specialization.",
73
+ type: DB.IncludeIdentifier(AnyPropertySpecializationIdentifier),
74
+ }),
75
+ }),
76
+ });
@@ -1,5 +1,5 @@
1
1
  import * as DB from "tsondb/schema/dsl";
2
- import { AmmunitionIdentifier, ArmorIdentifier, CloseCombatTechniqueIdentifier, ItemComponentIdentifier, RangedCombatTechniqueIdentifier, WeaponIdentifier, } from "../../_Identifier.js";
2
+ import { ArmorIdentifier, CloseCombatTechniqueIdentifier, ItemComponentIdentifier, RangedCombatTechniqueIdentifier, SpecialAmmunitionIdentifier, WeaponIdentifier, } from "../../_Identifier.js";
3
3
  import { EquipmentPrerequisites } from "../../_Prerequisite.js";
4
4
  import { CloseCombatTechnique, RangedCombatTechnique } from "../../CombatTechnique.js";
5
5
  import { NestedTranslationMap } from "../../Locale.js";
@@ -258,7 +258,7 @@ const ApplicableAmmunition = DB.TypeAlias(import.meta.url, {
258
258
  type: () => DB.Object({
259
259
  ammunition: DB.Optional({
260
260
  comment: "Specific ammunition this component can be applied to.",
261
- type: DB.Array(AmmunitionIdentifier(), {
261
+ type: DB.Array(SpecialAmmunitionIdentifier(), {
262
262
  minItems: 1,
263
263
  uniqueItems: true,
264
264
  }),
@@ -0,0 +1,152 @@
1
+ import * as DB from "tsondb/schema/dsl";
2
+ export declare const SpecialAmmunition: DB.Entity<"SpecialAmmunition", {
3
+ applicableTo: DB.MemberDecl<DB.Array<DB.ReferenceIdentifier>, true>;
4
+ costModifier: DB.MemberDecl<DB.Integer, true>;
5
+ complexity: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Complexity", {
6
+ Primitive: DB.EnumCase<null>;
7
+ Simple: DB.EnumCase<null>;
8
+ Complex: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"ComplexComplexity", DB.Object<{
9
+ ap_value: DB.MemberDecl<DB.Integer, true>;
10
+ prerequisites: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"PlainGeneralPrerequisites", DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PlainPrerequisites", DB.Array<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.Enum<"PrerequisitesElement", {
11
+ Single: DB.EnumCase<DB.TypeArgument<DB.Param<"T", DB.Type>>>;
12
+ Disjunction: DB.EnumCase<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PrerequisitesDisjunction", DB.Object<{
13
+ list: DB.MemberDecl<DB.Array<DB.TypeArgument<DB.Param<"T", DB.Type>>>, true>;
14
+ display_option: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"DisplayOption", {
15
+ Hide: DB.EnumCase<null>;
16
+ ReplaceWith: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"ReplacementDisplayOption", DB.Object<{
17
+ sentence_type: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"SentenceType", {
18
+ Standalone: DB.EnumCase<null>;
19
+ Connected: DB.EnumCase<null>;
20
+ }, []>>, false>;
21
+ translations: DB.MemberDecl<DB.NestedEntityMap<"ReplacementDisplayOptionTranslation", {
22
+ replacement: DB.MemberDecl<DB.String, true>;
23
+ }>, true>;
24
+ }>, []>>>;
25
+ }, []>>, false>;
26
+ }>, [T: DB.Param<"T", DB.Type>]>>>;
27
+ Group: DB.EnumCase<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PrerequisiteGroup", DB.Object<{
28
+ list: DB.MemberDecl<DB.Array<DB.TypeArgument<DB.Param<"T", DB.Type>>>, true>;
29
+ translations: DB.MemberDecl<DB.NestedEntityMap<"PrerequisiteGroupTranslation", {
30
+ text: DB.MemberDecl<DB.String, true>;
31
+ }>, true>;
32
+ }>, [T: DB.Param<"T", DB.Type>]>>>;
33
+ }, [T: DB.Param<"T", DB.Type>]>>>, [T: DB.Param<"T", DB.Type>]>>, []>>, false>;
34
+ src: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"PublicationRefs", DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PublicationRef", DB.Object<{
35
+ id: DB.MemberDecl<DB.ReferenceIdentifier, true>;
36
+ occurrences: DB.MemberDecl<DB.NestedEntityMap<string, {
37
+ initial: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"InitialOccurrence", DB.Object<{
38
+ printing: DB.MemberDecl<DB.Integer, false>;
39
+ pages: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PageRange", DB.Object<{
40
+ first_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
41
+ InsideCoverFront: DB.EnumCase<null>;
42
+ InsideCoverBack: DB.EnumCase<null>;
43
+ Numbered: DB.EnumCase<DB.Integer>;
44
+ }, []>>, true>;
45
+ last_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
46
+ InsideCoverFront: DB.EnumCase<null>;
47
+ InsideCoverBack: DB.EnumCase<null>;
48
+ Numbered: DB.EnumCase<DB.Integer>;
49
+ }, []>>, false>;
50
+ }>, []>>>, true>;
51
+ isRemoved: DB.MemberDecl<DB.Boolean, false>;
52
+ }>, []>>, true>;
53
+ revisions: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.Enum<"Revision", {
54
+ Since: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"Since", DB.Object<{
55
+ printing: DB.MemberDecl<DB.Integer, true>;
56
+ pages: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PageRange", DB.Object<{
57
+ first_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
58
+ InsideCoverFront: DB.EnumCase<null>;
59
+ InsideCoverBack: DB.EnumCase<null>;
60
+ Numbered: DB.EnumCase<DB.Integer>;
61
+ }, []>>, true>;
62
+ last_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
63
+ InsideCoverFront: DB.EnumCase<null>;
64
+ InsideCoverBack: DB.EnumCase<null>;
65
+ Numbered: DB.EnumCase<DB.Integer>;
66
+ }, []>>, false>;
67
+ }>, []>>>, true>;
68
+ }>, []>>>;
69
+ Deprecated: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"Deprecation", DB.Object<{
70
+ printing: DB.MemberDecl<DB.Integer, true>;
71
+ }>, []>>>;
72
+ }, []>>>, false>;
73
+ }>, true>;
74
+ }>, []>>>, []>>, false>;
75
+ }>, []>>>;
76
+ }, []>>, false>;
77
+ prerequisites: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"EquipmentPrerequisites", DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PlainPrerequisites", DB.Array<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.Enum<"PrerequisitesElement", {
78
+ Single: DB.EnumCase<DB.TypeArgument<DB.Param<"T", DB.Type>>>;
79
+ Disjunction: DB.EnumCase<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PrerequisitesDisjunction", DB.Object<{
80
+ list: DB.MemberDecl<DB.Array<DB.TypeArgument<DB.Param<"T", DB.Type>>>, true>;
81
+ display_option: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"DisplayOption", {
82
+ Hide: DB.EnumCase<null>;
83
+ ReplaceWith: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"ReplacementDisplayOption", DB.Object<{
84
+ sentence_type: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"SentenceType", {
85
+ Standalone: DB.EnumCase<null>;
86
+ Connected: DB.EnumCase<null>;
87
+ }, []>>, false>;
88
+ translations: DB.MemberDecl<DB.NestedEntityMap<"ReplacementDisplayOptionTranslation", {
89
+ replacement: DB.MemberDecl<DB.String, true>;
90
+ }>, true>;
91
+ }>, []>>>;
92
+ }, []>>, false>;
93
+ }>, [T: DB.Param<"T", DB.Type>]>>>;
94
+ Group: DB.EnumCase<DB.IncludeIdentifier<DB.Param<string, DB.Type>[], DB.TypeAlias<"PrerequisiteGroup", DB.Object<{
95
+ list: DB.MemberDecl<DB.Array<DB.TypeArgument<DB.Param<"T", DB.Type>>>, true>;
96
+ translations: DB.MemberDecl<DB.NestedEntityMap<"PrerequisiteGroupTranslation", {
97
+ text: DB.MemberDecl<DB.String, true>;
98
+ }>, true>;
99
+ }>, [T: DB.Param<"T", DB.Type>]>>>;
100
+ }, [T: DB.Param<"T", DB.Type>]>>>, [T: DB.Param<"T", DB.Type>]>>, []>>, false>;
101
+ src: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"PublicationRefs", DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PublicationRef", DB.Object<{
102
+ id: DB.MemberDecl<DB.ReferenceIdentifier, true>;
103
+ occurrences: DB.MemberDecl<DB.NestedEntityMap<string, {
104
+ initial: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"InitialOccurrence", DB.Object<{
105
+ printing: DB.MemberDecl<DB.Integer, false>;
106
+ pages: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PageRange", DB.Object<{
107
+ first_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
108
+ InsideCoverFront: DB.EnumCase<null>;
109
+ InsideCoverBack: DB.EnumCase<null>;
110
+ Numbered: DB.EnumCase<DB.Integer>;
111
+ }, []>>, true>;
112
+ last_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
113
+ InsideCoverFront: DB.EnumCase<null>;
114
+ InsideCoverBack: DB.EnumCase<null>;
115
+ Numbered: DB.EnumCase<DB.Integer>;
116
+ }, []>>, false>;
117
+ }>, []>>>, true>;
118
+ isRemoved: DB.MemberDecl<DB.Boolean, false>;
119
+ }>, []>>, true>;
120
+ revisions: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.Enum<"Revision", {
121
+ Since: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"Since", DB.Object<{
122
+ printing: DB.MemberDecl<DB.Integer, true>;
123
+ pages: DB.MemberDecl<DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"PageRange", DB.Object<{
124
+ first_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
125
+ InsideCoverFront: DB.EnumCase<null>;
126
+ InsideCoverBack: DB.EnumCase<null>;
127
+ Numbered: DB.EnumCase<DB.Integer>;
128
+ }, []>>, true>;
129
+ last_page: DB.MemberDecl<DB.IncludeIdentifier<[], DB.Enum<"Page", {
130
+ InsideCoverFront: DB.EnumCase<null>;
131
+ InsideCoverBack: DB.EnumCase<null>;
132
+ Numbered: DB.EnumCase<DB.Integer>;
133
+ }, []>>, false>;
134
+ }>, []>>>, true>;
135
+ }>, []>>>;
136
+ Deprecated: DB.EnumCase<DB.IncludeIdentifier<[], DB.TypeAlias<"Deprecation", DB.Object<{
137
+ printing: DB.MemberDecl<DB.Integer, true>;
138
+ }>, []>>>;
139
+ }, []>>>, false>;
140
+ }>, true>;
141
+ }>, []>>>, []>>, true>;
142
+ translations: DB.MemberDecl<DB.NestedEntityMap<"SpecialAmmunitionTranslation", {
143
+ name: DB.MemberDecl<DB.String, true>;
144
+ secondary_name: DB.MemberDecl<DB.String, false>;
145
+ note: DB.MemberDecl<DB.String, false>;
146
+ rules: DB.MemberDecl<DB.String, false>;
147
+ errata: DB.MemberDecl<DB.IncludeIdentifier<[], DB.TypeAlias<"Errata", DB.Array<DB.IncludeIdentifier<[], DB.TypeAlias<"Erratum", DB.Object<{
148
+ date: DB.MemberDecl<DB.Date, true>;
149
+ description: DB.MemberDecl<DB.String, true>;
150
+ }>, []>>>, []>>, false>;
151
+ }>, true>;
152
+ }, undefined>;
@@ -0,0 +1,58 @@
1
+ import * as DB from "tsondb/schema/dsl";
2
+ import { AmmunitionIdentifier } from "../../_Identifier.js";
3
+ import { EquipmentPrerequisites } from "../../_Prerequisite.js";
4
+ import { NestedTranslationMap } from "../../Locale.js";
5
+ import { Errata } from "../../source/_Erratum.js";
6
+ import { src } from "../../source/_PublicationRef.js";
7
+ import { Complexity } from "./_Item.js";
8
+ export const SpecialAmmunition = DB.Entity(import.meta.url, {
9
+ name: "SpecialAmmunition",
10
+ namePlural: "SpecialAmmunition",
11
+ type: () => DB.Object({
12
+ applicableTo: DB.Required({
13
+ comment: "The base ammunition type that is affected by this specialization.",
14
+ type: DB.Array(AmmunitionIdentifier(), { minItems: 1 }),
15
+ }),
16
+ costModifier: DB.Required({
17
+ comment: "The cost modifier for the base price of affected ammunition.",
18
+ type: DB.Integer({ minimum: 1 }),
19
+ }),
20
+ complexity: DB.Optional({
21
+ comment: "The complexity of crafting the item.",
22
+ type: DB.IncludeIdentifier(Complexity),
23
+ }),
24
+ prerequisites: DB.Optional({
25
+ comment: "The prerequisites of the item, if any. Note that this is fully separate from the prerequisites of the item’s trade secret, which are defined independently from this.",
26
+ type: DB.IncludeIdentifier(EquipmentPrerequisites),
27
+ }),
28
+ src,
29
+ translations: NestedTranslationMap(DB.Required, "SpecialAmmunition", DB.Object({
30
+ name: DB.Required({
31
+ comment: "The item’s name.",
32
+ type: DB.String({ minLength: 1 }),
33
+ }),
34
+ secondary_name: DB.Optional({
35
+ comment: "An auxiliary name or label of the item, if available.",
36
+ type: DB.String({ minLength: 1 }),
37
+ }),
38
+ note: DB.Optional({
39
+ comment: "Note text.",
40
+ type: DB.String({ minLength: 1, markdown: "block" }),
41
+ }),
42
+ rules: DB.Optional({
43
+ comment: "Special rules text.",
44
+ type: DB.String({ minLength: 1, markdown: "block" }),
45
+ }),
46
+ errata: DB.Optional({
47
+ type: DB.IncludeIdentifier(Errata),
48
+ }),
49
+ })),
50
+ }),
51
+ instanceDisplayName: {},
52
+ uniqueConstraints: [
53
+ {
54
+ entityMapKeyPath: "translations",
55
+ keyPathInEntityMap: "name",
56
+ },
57
+ ],
58
+ });
@@ -49,6 +49,7 @@ export { OrienteeringAid } from "./equipment/item/OrienteeringAid.js";
49
49
  export { Plant } from "./equipment/item/Plant.js";
50
50
  export { Poison } from "./equipment/item/Poison.js";
51
51
  export { RopeOrChain } from "./equipment/item/RopeOrChain.js";
52
+ export { SpecialAmmunition } from "./equipment/item/SpecialAmmunition.js";
52
53
  export { Stationery } from "./equipment/item/Stationery.js";
53
54
  export { Biome } from "./equipment/item/sub/Biome.js";
54
55
  export { BotanicRegion } from "./equipment/item/sub/BotanicRegion.js";
@@ -49,6 +49,7 @@ export { OrienteeringAid } from "./equipment/item/OrienteeringAid.js";
49
49
  export { Plant } from "./equipment/item/Plant.js";
50
50
  export { Poison } from "./equipment/item/Poison.js";
51
51
  export { RopeOrChain } from "./equipment/item/RopeOrChain.js";
52
+ export { SpecialAmmunition } from "./equipment/item/SpecialAmmunition.js";
52
53
  export { Stationery } from "./equipment/item/Stationery.js";
53
54
  export { Biome } from "./equipment/item/sub/Biome.js";
54
55
  export { BotanicRegion } from "./equipment/item/sub/BotanicRegion.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optolith/database-schema",
3
- "version": "0.107.1",
3
+ "version": "0.109.0",
4
4
  "description": "Definitions and utilities for the flat-file database of Optolith, a character creation tool for the Pen and Paper RPG “The Dark Eye 5”, and its external integrations into other software.",
5
5
  "keywords": [
6
6
  "tde",