From 80873e445e7748ca0e25fbec4756f56880227fab Mon Sep 17 00:00:00 2001 From: Lector Date: Mon, 1 Jun 2026 13:40:55 +0200 Subject: [PATCH 1/3] First sketch of Books Prereqs --- src/types/_Prerequisite.ts | 9 ++++++++ src/types/equipment/item/Book.ts | 8 ++++++- src/types/prerequisites/PrerequisiteGroups.ts | 10 +++++++++ .../single/LanguagePrerequisite.ts | 21 +++++++++++++++++++ .../single/ScriptPrerequisite.ts | 17 +++++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/types/prerequisites/single/LanguagePrerequisite.ts create mode 100644 src/types/prerequisites/single/ScriptPrerequisite.ts diff --git a/src/types/_Prerequisite.ts b/src/types/_Prerequisite.ts index 4276bb2f..1822209c 100644 --- a/src/types/_Prerequisite.ts +++ b/src/types/_Prerequisite.ts @@ -22,6 +22,7 @@ import { RulePrerequisiteGroup, SpellworkPrerequisiteGroup, TribePrerequisiteGroup, + LinguisticPrerequisiteGroup, } from "./prerequisites/PrerequisiteGroups.js" const PrerequisiteGroup = DB.GenTypeAlias(import.meta.url, { @@ -229,3 +230,11 @@ export const EnhancementPrerequisites = DB.TypeAlias(import.meta.url, { DB.IncludeIdentifier(EnhancementPrerequisiteGroup), ]), }) + +export const LinguisticPrerequisites = DB.TypeAlias(import.meta.url, { + name: "BookLinguisticPrerequisites", + type: () => + DB.GenIncludeIdentifier(PlainPrerequisites, [ + DB.IncludeIdentifier(LinguisticPrerequisiteGroup), + ]), +}) diff --git a/src/types/equipment/item/Book.ts b/src/types/equipment/item/Book.ts index 8bbcf520..93d6a282 100644 --- a/src/types/equipment/item/Book.ts +++ b/src/types/equipment/item/Book.ts @@ -4,6 +4,7 @@ import { NestedTranslationMap } from "../../Locale.js" import { Errata } from "../../source/_Erratum.js" import { src } from "../../source/_PublicationRef.js" import { Complexity, Cost, StructurePoints, Weight } from "./_Item.js" +import { LinguisticPrerequisites } from "../../_Prerequisite.js" export const Book = DB.Entity(import.meta.url, { name: "Book", @@ -35,6 +36,11 @@ export const Book = DB.Entity(import.meta.url, { comment: "The quality of the book’s content.", type: DB.IncludeIdentifier(BookContentQuality), }), + prerequisites: DB.Optional({ + comment: + "Which prerequisites must be met to buy the stat block? For example, a character might need the advantage Spellcaster or Blessed. Note: the AP cost for a profession package does not include these prerequisites.", + type: DB.IncludeIdentifier(LinguisticPrerequisites), + }), src, translations: NestedTranslationMap( DB.Required, @@ -309,4 +315,4 @@ const BookRulesOfEdition = DB.TypeAlias(import.meta.url, { type: DB.String({ minLength: 1, markdown: "block" }), }), }), -}) +}) \ No newline at end of file diff --git a/src/types/prerequisites/PrerequisiteGroups.ts b/src/types/prerequisites/PrerequisiteGroups.ts index 9e8617d1..010bba0f 100644 --- a/src/types/prerequisites/PrerequisiteGroups.ts +++ b/src/types/prerequisites/PrerequisiteGroups.ts @@ -20,6 +20,8 @@ import { SexualCharacteristicPrerequisite } from "./single/SexualCharacteristicP import { SocialStatusPrerequisite } from "./single/SocialStatusPrerequisite.js" import { StatePrerequisite } from "./single/StatePrerequisite.js" import { TextPrerequisite } from "./single/TextPrerequisite.js" +import { ScriptPrerequisite } from "./single/ScriptPrerequisite.js" +import { LanguagePrerequisite } from "./single/LanguagePrerequisite.js" import { BlessedTraditionPrerequisite, MagicalTraditionPrerequisite, @@ -199,3 +201,11 @@ export const PreconditionGroup = DB.Enum(import.meta.url, { }), }), }) + +export const LinguisticPrerequisiteGroup = DB.Enum(import.meta.url, { + name: "LinguisticPrerequisiteGroup", + values: () => ({ + Language: DB.EnumCase({ type: DB.IncludeIdentifier(LanguagePrerequisite) }), + Script: DB.EnumCase({ type: DB.IncludeIdentifier(ScriptPrerequisite) }), + }), +}) \ No newline at end of file diff --git a/src/types/prerequisites/single/LanguagePrerequisite.ts b/src/types/prerequisites/single/LanguagePrerequisite.ts new file mode 100644 index 00000000..ca749275 --- /dev/null +++ b/src/types/prerequisites/single/LanguagePrerequisite.ts @@ -0,0 +1,21 @@ +import * as DB from "tsondb/schema/dsl" +import { LanguageIdentifier } from "../../_Identifier.js" +//import { DisplayOption } from "../DisplayOption.js" + +export const LanguagePrerequisite = DB.TypeAlias(import.meta.url, { + name: "LanguagePrerequisite", + type: () => + DB.Object({ + id: DB.Required({ + comment: "The languages’s identifier.", + type: LanguageIdentifier(), + }), + value: DB.Required({ + comment: "The required minimum value.", + type: DB.Integer({ minimum: 0 }), + }), + //display_option: DB.Optional({ + // type: DB.IncludeIdentifier(DisplayOption), + //}), + }), +}) diff --git a/src/types/prerequisites/single/ScriptPrerequisite.ts b/src/types/prerequisites/single/ScriptPrerequisite.ts new file mode 100644 index 00000000..ff0dda8d --- /dev/null +++ b/src/types/prerequisites/single/ScriptPrerequisite.ts @@ -0,0 +1,17 @@ +import * as DB from "tsondb/schema/dsl" +import { ScriptIdentifier } from "../../_Identifier.js" +//import { DisplayOption } from "../DisplayOption.js" + +export const ScriptPrerequisite = DB.TypeAlias(import.meta.url, { + name: "ScriptPrerequisite", + type: () => + DB.Object({ + id: DB.Required({ + comment: "The scripts’s identifier.", + type: ScriptIdentifier(), + }), + //display_option: DB.Optional({ + // type: DB.IncludeIdentifier(DisplayOption), + //}), + }), +}) From 10e476b3e42b6a454c2ada2184409e0f1733b8af Mon Sep 17 00:00:00 2001 From: Lector Date: Wed, 10 Jun 2026 20:46:41 +0200 Subject: [PATCH 2/3] Reworked the books so it is possible to enter language prerequisites seperately to a version of a book To achieve this i separated the versioning from the translation and entered a lot of different translation-fields --- src/types/_Prerequisite.ts | 2 +- src/types/equipment/item/Book.ts | 136 +++++++++++++++++++------------ 2 files changed, 87 insertions(+), 51 deletions(-) diff --git a/src/types/_Prerequisite.ts b/src/types/_Prerequisite.ts index 1822209c..e01e1e76 100644 --- a/src/types/_Prerequisite.ts +++ b/src/types/_Prerequisite.ts @@ -232,7 +232,7 @@ export const EnhancementPrerequisites = DB.TypeAlias(import.meta.url, { }) export const LinguisticPrerequisites = DB.TypeAlias(import.meta.url, { - name: "BookLinguisticPrerequisites", + name: "LinguisticPrerequisites", type: () => DB.GenIncludeIdentifier(PlainPrerequisites, [ DB.IncludeIdentifier(LinguisticPrerequisiteGroup), diff --git a/src/types/equipment/item/Book.ts b/src/types/equipment/item/Book.ts index 93d6a282..cd4ecf31 100644 --- a/src/types/equipment/item/Book.ts +++ b/src/types/equipment/item/Book.ts @@ -39,7 +39,12 @@ export const Book = DB.Entity(import.meta.url, { prerequisites: DB.Optional({ comment: "Which prerequisites must be met to buy the stat block? For example, a character might need the advantage Spellcaster or Blessed. Note: the AP cost for a profession package does not include these prerequisites.", - type: DB.IncludeIdentifier(LinguisticPrerequisites), + type: DB.IncludeIdentifier(BookLinguisticPrerequisites), + }), + rules: DB.Required({ + comment: + "Skills and abilities you can learn by reading the book, as well as any other rules and effects concerning the book.", + type: DB.IncludeIdentifier(BookRules), }), src, translations: NestedTranslationMap( @@ -54,22 +59,10 @@ export const Book = DB.Entity(import.meta.url, { comment: "An auxiliary name or label of the item, if available.", type: DB.String({ minLength: 1 }), }), - language: DB.Optional({ - comment: "The language the book is written in, if specified.", - type: DB.String({ minLength: 1, markdown: "inline" }), - }), - script: DB.Optional({ - comment: "The script that was used for the book, if specified.", - type: DB.String({ minLength: 1, markdown: "inline" }), - }), note: DB.Optional({ comment: "Note text.", type: DB.String({ minLength: 1, markdown: "block" }), }), - rules: DB.Optional({ - comment: "Special rules text.", - type: DB.IncludeIdentifier(BookRules), - }), legality: DB.Optional({ comment: "The legality of the item, if specified.", type: DB.String({ minLength: 1, markdown: "inline" }), @@ -257,23 +250,29 @@ const PlainBookRules = DB.TypeAlias(import.meta.url, { comment: "The book’s rules without any special effects or conditions.", type: () => DB.Object({ - text: DB.Required({ - comment: "The (main) rules text.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), - reconstruction: DB.Optional({ - comment: "Rules for reconstructing certain skills or abilities from the book.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), - references: DB.Optional({ - comment: - "References to skills and abilities that, while mentioned in the book, cannot be learned from this book alone.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), - textAfter: DB.Optional({ - comment: "Additional rules text that comes after all other rules.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), + translation: NestedTranslationMap( + DB.Required, + "PlainBookRules", + DB.Object({ + text: DB.Required({ + comment: "The (main) rules text.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + reconstruction: DB.Optional({ + comment: "Rules for reconstructing certain skills or abilities from the book.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + references: DB.Optional({ + comment: + "References to skills and abilities that, while mentioned in the book, cannot be learned from this book alone.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + textAfter: DB.Optional({ + comment: "Additional rules text that comes after all other rules.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + }), + ), }), }) @@ -286,10 +285,16 @@ const BookRulesByEdition = DB.TypeAlias(import.meta.url, { editions: DB.Required({ type: DB.Array(DB.IncludeIdentifier(BookRulesOfEdition), { minItems: 1 }), }), - textAfter: DB.Optional({ - comment: "Additional rules text that comes after all other rules.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), + translation: NestedTranslationMap( + DB.Optional, + "BookRulesByEdition", + DB.Object({ + textAfter: DB.Optional({ + comment: "Additional rules text that comes after all other rules.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + }), + ), }), }) @@ -297,22 +302,53 @@ const BookRulesOfEdition = DB.TypeAlias(import.meta.url, { name: "BookRulesOfEdition", type: () => DB.Object({ - label: DB.Required({ - comment: "The edition(s) the rules apply to.", - type: DB.String({ minLength: 1 }), - }), - text: DB.Required({ - comment: "The rules text.", - type: DB.String({ minLength: 1, markdown: "block" }), + prerequisities: DB.Optional({ + comment: "The prerequisites for learning the rules of this edition.", + type: DB.IncludeIdentifier(BookLinguisticPrerequisites), }), - reconstruction: DB.Optional({ - comment: "Rules for reconstructing certain skills or abilities from the book.", - type: DB.String({ minLength: 1, markdown: "block" }), - }), - references: DB.Optional({ - comment: - "References to skills and abilities that, while mentioned in the book, cannot be learned from this book alone.", - type: DB.String({ minLength: 1, markdown: "block" }), + translation: NestedTranslationMap( + DB.Required, + "BookRulesOfEdition", + DB.Object({ + label: DB.Required({ + comment: "The edition(s) the rules apply to.", + type: DB.String({ minLength: 1 }), + }), + text: DB.Required({ + comment: "The rules text.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + reconstruction: DB.Optional({ + comment: "Rules for reconstructing certain skills or abilities from the book.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + references: DB.Optional({ + comment: + "References to skills and abilities that, while mentioned in the book, cannot be learned from this book alone.", + type: DB.String({ minLength: 1, markdown: "block" }), + }), + }), + ), + }), +}) + +const BookLinguisticPrerequisites = DB.TypeAlias(import.meta.url, { + name: "BookLinguisticPrerequisites", + type: () => + DB.Object({ + linguistic: DB.Required({ + comment: "The linguistic prerequisites for this book.", + type: DB.IncludeIdentifier(LinguisticPrerequisites), }), + translations: NestedTranslationMap( + DB.Optional, + "BookLinguisticPrerequisitesTranslation", + DB.Object({ + replacement: DB.Required({ + comment: "The label for this linguistic prerequisites.", + type: DB.String({ minLength: 1, markdown: "inline" }), + }), + }), + ), }), -}) \ No newline at end of file +}) From fa89e8636f99d001c35b8a1ba7f601e4b80840a5 Mon Sep 17 00:00:00 2001 From: Lector Date: Wed, 10 Jun 2026 20:50:24 +0200 Subject: [PATCH 3/3] prettier --- src/types/prerequisites/PrerequisiteGroups.ts | 2 +- .../single/LanguagePrerequisite.ts | 30 +++++++++---------- .../single/ScriptPrerequisite.ts | 22 +++++++------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/types/prerequisites/PrerequisiteGroups.ts b/src/types/prerequisites/PrerequisiteGroups.ts index 4e4d75e8..17f0ffaa 100644 --- a/src/types/prerequisites/PrerequisiteGroups.ts +++ b/src/types/prerequisites/PrerequisiteGroups.ts @@ -209,4 +209,4 @@ export const LinguisticPrerequisiteGroup = DB.Enum(import.meta.url, { Language: DB.EnumCase({ type: DB.IncludeIdentifier(LanguagePrerequisite) }), Script: DB.EnumCase({ type: DB.IncludeIdentifier(ScriptPrerequisite) }), }), -}) \ No newline at end of file +}) diff --git a/src/types/prerequisites/single/LanguagePrerequisite.ts b/src/types/prerequisites/single/LanguagePrerequisite.ts index ca749275..db654455 100644 --- a/src/types/prerequisites/single/LanguagePrerequisite.ts +++ b/src/types/prerequisites/single/LanguagePrerequisite.ts @@ -3,19 +3,19 @@ import { LanguageIdentifier } from "../../_Identifier.js" //import { DisplayOption } from "../DisplayOption.js" export const LanguagePrerequisite = DB.TypeAlias(import.meta.url, { - name: "LanguagePrerequisite", - type: () => - DB.Object({ - id: DB.Required({ - comment: "The languages’s identifier.", - type: LanguageIdentifier(), - }), - value: DB.Required({ - comment: "The required minimum value.", - type: DB.Integer({ minimum: 0 }), - }), - //display_option: DB.Optional({ - // type: DB.IncludeIdentifier(DisplayOption), - //}), - }), + name: "LanguagePrerequisite", + type: () => + DB.Object({ + id: DB.Required({ + comment: "The languages�s identifier.", + type: LanguageIdentifier(), + }), + value: DB.Required({ + comment: "The required minimum value.", + type: DB.Integer({ minimum: 0 }), + }), + //display_option: DB.Optional({ + // type: DB.IncludeIdentifier(DisplayOption), + //}), + }), }) diff --git a/src/types/prerequisites/single/ScriptPrerequisite.ts b/src/types/prerequisites/single/ScriptPrerequisite.ts index ff0dda8d..ce5354e7 100644 --- a/src/types/prerequisites/single/ScriptPrerequisite.ts +++ b/src/types/prerequisites/single/ScriptPrerequisite.ts @@ -3,15 +3,15 @@ import { ScriptIdentifier } from "../../_Identifier.js" //import { DisplayOption } from "../DisplayOption.js" export const ScriptPrerequisite = DB.TypeAlias(import.meta.url, { - name: "ScriptPrerequisite", - type: () => - DB.Object({ - id: DB.Required({ - comment: "The scripts’s identifier.", - type: ScriptIdentifier(), - }), - //display_option: DB.Optional({ - // type: DB.IncludeIdentifier(DisplayOption), - //}), - }), + name: "ScriptPrerequisite", + type: () => + DB.Object({ + id: DB.Required({ + comment: "The scripts�s identifier.", + type: ScriptIdentifier(), + }), + //display_option: DB.Optional({ + // type: DB.IncludeIdentifier(DisplayOption), + //}), + }), })