- 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.
208 lines
6.2 KiB
TypeScript
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),
|
|
});
|