import type { JsonObject } from './common'; import type { SavedGameSnapshot } from './runtime'; export const QUEST_NARRATIVE_TYPES = [ 'bounty', 'escort', 'investigation', 'retrieval', 'relationship', 'trial', ] as const; export type SharedQuestNarrativeType = (typeof QUEST_NARRATIVE_TYPES)[number]; export const QUEST_OBJECTIVE_KINDS = [ 'defeat_hostile_npc', 'inspect_treasure', 'spar_with_npc', 'talk_to_npc', 'reach_scene', 'deliver_item', ] as const; export type SharedQuestObjectiveKind = (typeof QUEST_OBJECTIVE_KINDS)[number]; export const QUEST_URGENCY_LEVELS = ['low', 'medium', 'high'] as const; export type SharedQuestUrgency = (typeof QUEST_URGENCY_LEVELS)[number]; export const QUEST_INTIMACY_LEVELS = [ 'transactional', 'cooperative', 'trust_based', ] as const; export type SharedQuestIntimacy = (typeof QUEST_INTIMACY_LEVELS)[number]; export const QUEST_REWARD_THEMES = [ 'currency', 'resource', 'relationship', 'intel', 'rare_item', ] as const; export type SharedQuestRewardTheme = (typeof QUEST_REWARD_THEMES)[number]; export const RUNTIME_ITEM_FUNCTIONAL_BIAS_VALUES = [ 'heal', 'mana', 'cooldown', 'guard', 'damage', ] as const; export type SharedRuntimeItemFunctionalBias = (typeof RUNTIME_ITEM_FUNCTIONAL_BIAS_VALUES)[number]; export const RUNTIME_ITEM_TONE_VALUES = [ 'grim', 'mysterious', 'martial', 'ritual', 'survival', ] as const; export type SharedRuntimeItemTone = (typeof RUNTIME_ITEM_TONE_VALUES)[number]; export type StoryRequestOptionsPayload = { availableOptions?: JsonObject[]; optionCatalog?: JsonObject[]; }; export type StoryRequestPayload = { worldType: TWorldType; character: JsonObject; monsters?: JsonObject[]; history?: JsonObject[]; choice?: string; context: JsonObject; requestOptions?: StoryRequestOptionsPayload; }; export type PlainTextPromptRequest = { systemPrompt: string; userPrompt: string; }; export type PlainTextResponse = { text: string; }; export type CharacterChatReplyRequest< TCharacter = unknown, TStoryMoment = unknown, TContext = unknown, TConversationTurn = unknown, TTargetStatus = unknown, > = { worldType: string; playerCharacter: TCharacter; targetCharacter: TCharacter; storyHistory: TStoryMoment[]; context: TContext; conversationHistory: TConversationTurn[]; conversationSummary: string; playerMessage: string; targetStatus: TTargetStatus; }; export type CharacterChatSuggestionsRequest< TCharacter = unknown, TStoryMoment = unknown, TContext = unknown, TConversationTurn = unknown, TTargetStatus = unknown, > = { worldType: string; playerCharacter: TCharacter; targetCharacter: TCharacter; storyHistory: TStoryMoment[]; context: TContext; conversationHistory: TConversationTurn[]; conversationSummary: string; targetStatus: TTargetStatus; }; export type CharacterChatSummaryRequest< TCharacter = unknown, TStoryMoment = unknown, TContext = unknown, TConversationTurn = unknown, TTargetStatus = unknown, > = { worldType: string; playerCharacter: TCharacter; targetCharacter: TCharacter; storyHistory: TStoryMoment[]; context: TContext; conversationHistory: TConversationTurn[]; previousSummary: string; targetStatus: TTargetStatus; }; export type NpcChatDialogueRequest< TCharacter = unknown, TEncounter = unknown, TMonster = unknown, TStoryMoment = unknown, TContext = unknown, > = { worldType: string; character: TCharacter; encounter: TEncounter; monsters: TMonster[]; history: TStoryMoment[]; context: TContext; topic: string; resultSummary: string; }; export type NpcChatTurnRequest< TCharacter = unknown, TEncounter = unknown, TMonster = unknown, TStoryMoment = unknown, TContext = unknown, TConversationTurn = unknown, TNpcState = unknown, > = { worldType: string; character: TCharacter; encounter: TEncounter; monsters: TMonster[]; history: TStoryMoment[]; context: TContext; conversationHistory: TConversationTurn[]; playerMessage: string; npcState: TNpcState; }; export type NpcChatTurnResult = { npcReply: string; affinityDelta: number; affinityText: string; suggestions: string[]; }; export type NpcRecruitDialogueRequest< TCharacter = unknown, TEncounter = unknown, TMonster = unknown, TStoryMoment = unknown, TContext = unknown, > = { worldType: string; character: TCharacter; encounter: TEncounter; monsters: TMonster[]; history: TStoryMoment[]; context: TContext; invitationText: string; recruitSummary: string; }; export type RuntimeItemIntentRequest< TContext = JsonObject, TPlan = JsonObject, > = { context: TContext; plans: TPlan[]; }; export type RuntimeItemIntentResponse = { intents: TIntent[]; }; export type QuestGenerationRequest< TState = JsonObject, TEncounter = JsonObject, > = { state: TState; encounter: TEncounter; }; export type RuntimeAction< TType extends string = string, TPayload = JsonObject, > = { type: TType; functionId?: string; targetId?: string; payload?: TPayload; }; export type RuntimeActionRequest< TAction extends RuntimeAction = RuntimeAction, > = { sessionId: string; clientVersion?: number; action: TAction; }; export type RuntimeActionResponse< TViewModel = JsonObject, TPresentation = JsonObject, TPatch = JsonObject, > = { sessionId: string; serverVersion: number; viewModel: TViewModel; presentation: TPresentation; patches: TPatch[]; }; export const TASK5_RUNTIME_FUNCTION_IDS = [ 'story_continue_adventure', 'story_opening_camp_dialogue', 'camp_travel_home_scene', 'idle_call_out', 'idle_explore_forward', 'idle_observe_signs', 'idle_rest_focus', 'idle_travel_next_scene', 'battle_all_in_crush', 'battle_escape_breakout', 'battle_feint_step', 'battle_finisher_window', 'battle_guard_break', 'battle_probe_pressure', 'battle_recover_breath', 'npc_chat', 'npc_fight', 'npc_help', 'npc_leave', 'npc_preview_talk', 'npc_recruit', 'npc_spar', ] as const; export type Task5RuntimeFunctionId = (typeof TASK5_RUNTIME_FUNCTION_IDS)[number]; export const TASK6_RUNTIME_FUNCTION_IDS = [ 'equipment_equip', 'equipment_unequip', 'forge_craft', 'forge_dismantle', 'forge_reforge', 'inventory_use', 'npc_gift', 'npc_quest_accept', 'npc_quest_turn_in', 'npc_trade', 'treasure_inspect', 'treasure_leave', 'treasure_secure', ] as const; export type Task6RuntimeFunctionId = (typeof TASK6_RUNTIME_FUNCTION_IDS)[number]; export const SERVER_RUNTIME_FUNCTION_IDS = [ ...TASK5_RUNTIME_FUNCTION_IDS, ...TASK6_RUNTIME_FUNCTION_IDS, ] as const; export type ServerRuntimeFunctionId = (typeof SERVER_RUNTIME_FUNCTION_IDS)[number]; export const TASK5_RUNTIME_OPTION_SCOPES = ['story', 'combat', 'npc'] as const; export type Task5RuntimeOptionScope = (typeof TASK5_RUNTIME_OPTION_SCOPES)[number]; export type RuntimeStoryChoicePayload = JsonObject & { optionText?: string; note?: string; }; export type RuntimeStoryChoiceAction = RuntimeAction< 'story_choice', RuntimeStoryChoicePayload > & { functionId: string; targetId?: string; }; export type RuntimeStoryOptionView = { functionId: string; actionText: string; detailText?: string; scope: Task5RuntimeOptionScope; disabled?: boolean; reason?: string; }; export type RuntimeStoryPlayerViewModel = { hp: number; maxHp: number; mana: number; maxMana: number; }; export type RuntimeStoryCompanionViewModel = { npcId: string; characterId?: string; joinedAtAffinity: number; }; export type RuntimeStoryEncounterViewModel = { id: string; kind: 'npc' | 'treasure'; npcName: string; hostile: boolean; affinity?: number; recruited?: boolean; interactionActive: boolean; battleMode?: 'fight' | 'spar' | null; }; export type RuntimeStoryStatusViewModel = { inBattle: boolean; npcInteractionActive: boolean; currentNpcBattleMode: 'fight' | 'spar' | null; currentNpcBattleOutcome: 'fight_victory' | 'spar_complete' | null; }; export type RuntimeBattlePresentation = { targetId?: string; targetName?: string; damageDealt?: number; damageTaken?: number; outcome?: 'ongoing' | 'victory' | 'spar_complete' | 'escaped'; }; export type RuntimeStoryViewModel = { player: RuntimeStoryPlayerViewModel; encounter: RuntimeStoryEncounterViewModel | null; companions: RuntimeStoryCompanionViewModel[]; availableOptions: RuntimeStoryOptionView[]; status: RuntimeStoryStatusViewModel; }; export type RuntimeStoryPresentation = { actionText: string; resultText: string; storyText: string; options: RuntimeStoryOptionView[]; toast?: string | null; battle?: RuntimeBattlePresentation | null; }; export type RuntimeStoryPatch = | { type: 'story_history_append'; actionText: string; resultText: string; } | { type: 'npc_affinity_changed'; npcId: string; previousAffinity: number; nextAffinity: number; } | { type: 'battle_resolved'; functionId: string; targetId?: string; damageDealt?: number; damageTaken?: number; outcome: 'ongoing' | 'victory' | 'spar_complete' | 'escaped'; } | { type: 'status_changed'; inBattle: boolean; npcInteractionActive: boolean; currentNpcBattleMode: 'fight' | 'spar' | null; currentNpcBattleOutcome: 'fight_victory' | 'spar_complete' | null; } | { type: 'encounter_changed'; encounterId: string | null; }; export type RuntimeStoryActionRequest = RuntimeActionRequest; export type RuntimeStoryActionResponse< TSnapshotGameState = JsonObject, TSnapshotCurrentStory = JsonObject, > = RuntimeActionResponse< RuntimeStoryViewModel, RuntimeStoryPresentation, RuntimeStoryPatch > & { snapshot: SavedGameSnapshot< TSnapshotGameState, string, TSnapshotCurrentStory >; };