Files
2D6-Dungeon/src/schemas/content.ts
Keith Solomon 120e144b3f Feature: add level 1 content including room templates, encounter tables, and room generation logic
- Introduced contentHelpers for table and room template lookups.
- Created level1Rooms.ts with various room templates for level 1.
- Added level1Tables.ts containing encounter tables for animals, martial, dogs, people, fungal, guards, workers, and room types.
- Implemented room generation functions in rooms.ts to create rooms based on templates and tables.
- Added tests for room generation logic in rooms.test.ts to ensure correct functionality.
2026-03-15 12:54:46 -05:00

208 lines
6.2 KiB
TypeScript

import { z } from "zod";
import {
contentReferenceSchema,
diceKindSchema,
ruleEffectSchema,
} from "./rules";
export const tableEntrySchema = z.object({
key: z.string().min(1),
min: z.number().int().optional(),
max: z.number().int().optional(),
exact: z.number().int().optional(),
d66: z.number().int().optional(),
label: z.string().min(1),
text: z.string().optional(),
effects: z.array(ruleEffectSchema).optional(),
references: z.array(contentReferenceSchema).optional(),
});
export const tableDefinitionSchema = z.object({
id: z.string().min(1),
code: z.string().min(1),
name: z.string().min(1),
category: z.enum(["generic", "random-list", "loot", "level", "optional", "town", "room"]),
level: z.number().int().positive().optional(),
page: z.number().int().positive(),
diceKind: diceKindSchema,
usesModifiedRangesRule: z.boolean().optional(),
entries: z.array(tableEntrySchema),
notes: z.array(z.string()).optional(),
mvp: z.boolean(),
});
export const weaponDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
category: z.enum(["melee", "ranged"]),
handedness: z.enum(["one-handed", "two-handed"]),
baseDamage: z.number().int(),
allowedManoeuvreIds: z.array(z.string()),
tags: z.array(z.string()),
startingOption: z.boolean(),
});
export const manoeuvreDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
weaponCategories: z.array(z.enum(["melee", "ranged"])),
shiftCost: z.number().int().optional(),
disciplineModifier: z.number().int().optional(),
precisionModifier: z.number().int().optional(),
damageModifier: z.number().int().optional(),
exactStrikeBonus: z.boolean().optional(),
interruptRule: z.string().optional(),
effectText: z.string().optional(),
mvp: z.boolean(),
});
export const armourDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
armourValue: z.number().int(),
penalties: z
.object({
shift: z.number().int().optional(),
discipline: z.number().int().optional(),
precision: z.number().int().optional(),
})
.optional(),
deflectionRule: z.string().optional(),
startingOption: z.boolean(),
valueGp: z.number().int().optional(),
mvp: z.boolean(),
});
export const itemDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
itemType: z.enum([
"gear",
"treasure",
"quest",
"herb",
"rune",
"misc",
"ration",
"light-source",
]),
stackable: z.boolean(),
consumable: z.boolean(),
valueGp: z.number().int().optional(),
weight: z.number().optional(),
rulesText: z.string().optional(),
effects: z.array(ruleEffectSchema).optional(),
mvp: z.boolean(),
});
export const potionDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
tableSource: z.string().min(1),
useTiming: z.enum(["combat", "exploration", "town", "any"]),
effects: z.array(ruleEffectSchema),
valueGp: z.number().int().optional(),
mvp: z.boolean(),
});
export const scrollDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
tableSource: z.string().min(1),
castCheck: z
.object({
diceKind: z.enum(["d6", "2d6"]),
successMin: z.number().int().optional(),
successMax: z.number().int().optional(),
})
.optional(),
onSuccess: z.array(ruleEffectSchema),
onFailureTableCode: z.string().optional(),
valueGp: z.number().int().optional(),
startingOption: z.boolean(),
mvp: z.boolean(),
});
export const creatureDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
level: z.number().int().positive(),
category: z.string().min(1),
hp: z.number().int().positive(),
attackProfile: z.object({
discipline: z.number().int(),
precision: z.number().int(),
damage: z.number().int(),
numberAppearing: z.string().optional(),
}),
defenceProfile: z
.object({
armour: z.number().int().optional(),
specialRules: z.array(z.string()).optional(),
})
.optional(),
xpReward: z.number().int().optional(),
lootTableCodes: z.array(z.string()).optional(),
interruptRules: z.array(z.string()).optional(),
traits: z.array(z.string()).optional(),
sourcePage: z.number().int().positive(),
mvp: z.boolean(),
});
export const exitTemplateSchema = z.object({
direction: z.enum(["north", "east", "south", "west"]).optional(),
exitType: z.enum(["open", "door", "locked", "secret", "shaft", "stairs"]),
destinationLevel: z.number().int().optional(),
});
export const roomTemplateSchema = z.object({
id: z.string().min(1),
level: z.number().int().positive(),
sourcePage: z.number().int().positive().optional(),
roomClass: z.enum(["normal", "small", "large", "special", "start", "stairs"]),
tableCode: z.string().min(1),
tableEntryKey: z.string().min(1),
title: z.string().min(1),
text: z.string().optional(),
encounterText: z.string().optional(),
exitHint: z.string().optional(),
unique: z.boolean().optional(),
dimensions: z
.object({
width: z.number().int().positive(),
height: z.number().int().positive(),
})
.optional(),
exits: z.array(exitTemplateSchema).optional(),
encounterRefs: z.array(contentReferenceSchema).optional(),
objectRefs: z.array(contentReferenceSchema).optional(),
tags: z.array(z.string()),
mvp: z.boolean(),
});
export const townServiceDefinitionSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
serviceType: z.enum(["market", "temple", "tavern", "healer", "smith", "quest"]),
tableCodes: z.array(z.string()).optional(),
costRules: z.array(z.string()).optional(),
effects: z.array(ruleEffectSchema).optional(),
mvp: z.boolean(),
});
export const contentPackSchema = z.object({
version: z.string().min(1),
sourceBooks: z.array(z.string()),
tables: z.array(tableDefinitionSchema),
weapons: z.array(weaponDefinitionSchema),
manoeuvres: z.array(manoeuvreDefinitionSchema),
armour: z.array(armourDefinitionSchema),
items: z.array(itemDefinitionSchema),
potions: z.array(potionDefinitionSchema),
scrolls: z.array(scrollDefinitionSchema),
creatures: z.array(creatureDefinitionSchema),
roomTemplates: z.array(roomTemplateSchema),
townServices: z.array(townServiceDefinitionSchema),
});