import { z } from 'zod'; import { conditionSchema, hpSchema, int } from './common'; export const combatantKindSchema = z.enum(['pc', 'npc', 'monster']); export const combatantSchema = z.object({ id: z.string(), name: z.string().min(1).max(120), kind: combatantKindSchema, /** link to a Character, if this combatant is a tracked PC/NPC */ characterId: z.string().optional(), /** ref into the bestiary, if spawned from a monster */ monsterRef: z.string().optional(), initiative: int, /** modifier added when (re)rolling initiative */ initBonus: int.default(0), ac: int, hp: hpSchema, conditions: z.array(conditionSchema).default([]), notes: z.string().max(2000).default(''), /** 5e challenge rating (for difficulty budget), if known */ cr: z.number().finite().nonnegative().optional(), /** PF2e creature level (for difficulty budget), if known */ level: int.optional(), }); export type Combatant = z.infer; export const logEntrySchema = z.object({ round: int.nonnegative(), text: z.string(), }); export type LogEntry = z.infer; export const encounterStatusSchema = z.enum(['planning', 'active', 'ended']); export const encounterSchema = z.object({ id: z.string(), campaignId: z.string(), name: z.string().min(1).max(120), status: encounterStatusSchema.default('planning'), round: int.nonnegative().default(0), /** index into combatants of whose turn it is */ turnIndex: int.nonnegative().default(0), combatants: z.array(combatantSchema).default([]), /** newest-last event feed for the fight */ log: z.array(logEntrySchema).default([]), createdAt: z.string(), updatedAt: z.string(), }); export type Encounter = z.infer;