219 lines
4.5 KiB
TypeScript
219 lines
4.5 KiB
TypeScript
import type { ExitType, RoomClass } from "./content";
|
|
import type { LogEntry, RollResult, RuleEffect } from "./rules";
|
|
|
|
export type StatusDuration = "round" | "combat" | "room" | "run" | "permanent";
|
|
|
|
export type StatusInstance = {
|
|
id: string;
|
|
source?: string;
|
|
duration?: StatusDuration;
|
|
value?: number;
|
|
notes?: string;
|
|
};
|
|
|
|
export type InventoryEntry = {
|
|
definitionId: string;
|
|
quantity: number;
|
|
identified?: boolean;
|
|
charges?: number;
|
|
notes?: string;
|
|
};
|
|
|
|
export type InventoryState = {
|
|
carried: InventoryEntry[];
|
|
equipped: InventoryEntry[];
|
|
stored: InventoryEntry[];
|
|
currency: {
|
|
gold: number;
|
|
};
|
|
rationCount: number;
|
|
lightSources: InventoryEntry[];
|
|
};
|
|
|
|
export type AdventurerState = {
|
|
id: string;
|
|
name: string;
|
|
level: number;
|
|
xp: number;
|
|
hp: {
|
|
current: number;
|
|
max: number;
|
|
base: number;
|
|
};
|
|
stats: {
|
|
shift: number;
|
|
discipline: number;
|
|
precision: number;
|
|
};
|
|
weaponId: string;
|
|
manoeuvreIds: string[];
|
|
armourId?: string;
|
|
favour: Record<string, number>;
|
|
statuses: StatusInstance[];
|
|
inventory: InventoryState;
|
|
progressionFlags: string[];
|
|
};
|
|
|
|
export type TownState = {
|
|
visits: number;
|
|
knownServices: string[];
|
|
stash: InventoryEntry[];
|
|
pendingSales: InventoryEntry[];
|
|
serviceFlags: string[];
|
|
};
|
|
|
|
export type QuestState = {
|
|
id: string;
|
|
title: string;
|
|
status: "available" | "active" | "completed" | "failed";
|
|
progressFlags: string[];
|
|
rewardText?: string;
|
|
};
|
|
|
|
export type RunSummary = {
|
|
runId: string;
|
|
startedAt: string;
|
|
endedAt?: string;
|
|
deepestLevel: number;
|
|
roomsVisited: number;
|
|
creaturesDefeated: string[];
|
|
xpGained: number;
|
|
treasureValue: number;
|
|
outcome: "escaped" | "defeated" | "saved-in-progress";
|
|
};
|
|
|
|
export type CampaignState = {
|
|
id: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
rulesVersion: string;
|
|
contentVersion: string;
|
|
adventurer: AdventurerState;
|
|
unlockedLevels: number[];
|
|
completedLevels: number[];
|
|
townState: TownState;
|
|
questState: QuestState[];
|
|
campaignFlags: string[];
|
|
runHistory: RunSummary[];
|
|
};
|
|
|
|
export type RoomExitState = {
|
|
id: string;
|
|
direction: "north" | "east" | "south" | "west";
|
|
exitType: ExitType;
|
|
discovered: boolean;
|
|
traversable: boolean;
|
|
leadsToRoomId?: string;
|
|
destinationLevel?: number;
|
|
};
|
|
|
|
export type EncounterState = {
|
|
id: string;
|
|
sourceTableCode?: string;
|
|
creatureIds: string[];
|
|
resolved: boolean;
|
|
surprise?: boolean;
|
|
rewardPending?: boolean;
|
|
};
|
|
|
|
export type RoomObjectState = {
|
|
id: string;
|
|
objectType: "container" | "altar" | "corpse" | "hazard" | "feature" | "quest";
|
|
sourceTableCode?: string;
|
|
interacted: boolean;
|
|
hidden?: boolean;
|
|
effects?: RuleEffect[];
|
|
notes?: string;
|
|
};
|
|
|
|
export type RoomState = {
|
|
id: string;
|
|
level: number;
|
|
templateId?: string;
|
|
position: {
|
|
x: number;
|
|
y: number;
|
|
};
|
|
dimensions: {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
roomClass: RoomClass;
|
|
exits: RoomExitState[];
|
|
discovery: {
|
|
generated: boolean;
|
|
entered: boolean;
|
|
cleared: boolean;
|
|
searched: boolean;
|
|
};
|
|
encounter?: EncounterState;
|
|
objects: RoomObjectState[];
|
|
notes: string[];
|
|
flags: string[];
|
|
};
|
|
|
|
export type DungeonLevelState = {
|
|
level: number;
|
|
themeName?: string;
|
|
rooms: Record<string, RoomState>;
|
|
discoveredRoomOrder: string[];
|
|
stairsUpRoomId?: string;
|
|
stairsDownRoomId?: string;
|
|
secretDoorUsed?: boolean;
|
|
exhaustedExitSearch?: boolean;
|
|
};
|
|
|
|
export type DungeonState = {
|
|
levels: Record<number, DungeonLevelState>;
|
|
revealedPercentByLevel: Record<number, number>;
|
|
globalFlags: string[];
|
|
};
|
|
|
|
export type CombatantState = {
|
|
id: string;
|
|
name: string;
|
|
sourceDefinitionId?: string;
|
|
hpCurrent: number;
|
|
hpMax: number;
|
|
shift: number;
|
|
discipline: number;
|
|
precision: number;
|
|
armourValue?: number;
|
|
statuses: StatusInstance[];
|
|
traits: string[];
|
|
};
|
|
|
|
export type InterruptState = {
|
|
source: "player" | "enemy";
|
|
trigger: string;
|
|
effectText: string;
|
|
resolved: boolean;
|
|
};
|
|
|
|
export type CombatState = {
|
|
id: string;
|
|
round: number;
|
|
actingSide: "player" | "enemy";
|
|
fatigueDie?: number;
|
|
player: CombatantState;
|
|
enemies: CombatantState[];
|
|
selectedManoeuvreId?: string;
|
|
lastRoll?: RollResult;
|
|
pendingInterrupt?: InterruptState;
|
|
combatLog: LogEntry[];
|
|
};
|
|
|
|
export type RunState = {
|
|
id: string;
|
|
campaignId: string;
|
|
status: "active" | "paused" | "completed" | "failed";
|
|
startedAt: string;
|
|
currentLevel: number;
|
|
currentRoomId?: string;
|
|
dungeon: DungeonState;
|
|
adventurerSnapshot: AdventurerState;
|
|
activeCombat?: CombatState;
|
|
log: LogEntry[];
|
|
pendingEffects: RuleEffect[];
|
|
};
|