436 lines
9.8 KiB
TypeScript
436 lines
9.8 KiB
TypeScript
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<TWorldType extends string = string> = {
|
|
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<TIntent = JsonObject> = {
|
|
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<RuntimeStoryChoiceAction>;
|
|
|
|
export type RuntimeStoryActionResponse<
|
|
TSnapshotGameState = JsonObject,
|
|
TSnapshotCurrentStory = JsonObject,
|
|
> = RuntimeActionResponse<
|
|
RuntimeStoryViewModel,
|
|
RuntimeStoryPresentation,
|
|
RuntimeStoryPatch
|
|
> & {
|
|
snapshot: SavedGameSnapshot<
|
|
TSnapshotGameState,
|
|
string,
|
|
TSnapshotCurrentStory
|
|
>;
|
|
};
|