import { AnimationState, type Encounter, type GameState, type StoryMoment, type StoryOption, type TreasureInteractionAction, } from '../types'; import { formatCurrency } from './economy'; import { TREASURE_INSPECT_FUNCTION, TREASURE_LEAVE_FUNCTION, TREASURE_SECURE_FUNCTION, } from './functionCatalog'; import { buildRuntimeItemGenerationContext } from './runtimeItemContext'; import { buildDirectedRuntimeReward } from './runtimeItemDirector'; import { flattenDirectedRuntimeRewardItems } from './runtimeItemNarrative'; export type TreasureReward = { items: ReturnType; hp: number; mana: number; currency: number; storyHint?: string; }; function buildTreasureOption( functionId: string, actionText: string, detailText: string, action: TreasureInteractionAction, ): StoryOption { return { functionId, actionText, detailText, visuals: { playerAnimation: AnimationState.IDLE, playerMoveMeters: 0, playerOffsetY: 0, playerFacing: 'right', scrollWorld: false, monsterChanges: [], }, interaction: { kind: 'treasure', action, }, } as StoryOption; } function buildTreasureReward( state: GameState, encounter: Encounter, action: TreasureInteractionAction, ): TreasureReward { const context = buildRuntimeItemGenerationContext({ state, generationChannel: 'treasure', encounter, }); const directed = buildDirectedRuntimeReward(context, { seedKey: `treasure:${encounter.id ?? encounter.npcName}:${action}`, variant: action, itemCount: action === 'inspect' ? 2 : 2, fixedKinds: action === 'inspect' ? ['relic', 'consumable'] : ['relic', 'material'], fixedPermanence: action === 'inspect' ? ['permanent', 'timed'] : ['permanent', 'resource'], baseHp: action === 'inspect' ? 10 : 0, baseMana: action === 'inspect' ? 12 : 0, baseCurrency: action === 'inspect' ? state.worldType === 'XIANXIA' ? 34 : 48 : state.worldType === 'XIANXIA' ? 22 : 30, storyHint: `${encounter.npcName}里藏着与你当前构筑和现场线索贴合的战利品。`, }); return { items: flattenDirectedRuntimeRewardItems(directed), hp: directed.hp ?? 0, mana: directed.mana ?? 0, currency: directed.currency ?? 0, storyHint: directed.storyHint, }; } export function buildTreasureEncounterStoryMoment({ state, encounter, overrideText, }: { state: GameState; encounter: Encounter; overrideText?: string; }): StoryMoment { const secureReward = buildTreasureReward(state, encounter, 'secure'); const inspectReward = buildTreasureReward(state, encounter, 'inspect'); return { text: overrideText ?? `你在 ${encounter.npcName} 前停下脚步。${encounter.npcDescription} 它看起来并非随意遗落,而像是被刻意留在这里。`, options: [ buildTreasureOption( TREASURE_SECURE_FUNCTION.id, TREASURE_SECURE_FUNCTION.title, `直接带走 ${secureReward.items.map((item) => item.name).join('、')},并获得 ${formatCurrency(secureReward.currency, state.worldType)}。`, 'secure', ), buildTreasureOption( TREASURE_INSPECT_FUNCTION.id, TREASURE_INSPECT_FUNCTION.title, `多花些时间搜查,可额外拿到 ${inspectReward.items.map((item) => item.name).join('、')}、${formatCurrency(inspectReward.currency, state.worldType)} 与恢复收益。`, 'inspect', ), buildTreasureOption( TREASURE_LEAVE_FUNCTION.id, TREASURE_LEAVE_FUNCTION.title, `先把 ${encounter.npcName} 的位置和迹象记住,暂时不动它。`, 'leave', ), ], }; } export function resolveTreasureReward( state: GameState, encounter: Encounter, action: TreasureInteractionAction, ) { return buildTreasureReward(state, encounter, action); } export function buildTreasureResultText( encounter: Encounter, action: TreasureInteractionAction, reward?: TreasureReward, ) { if (action === 'leave') { return `你暂时没有触碰 ${encounter.npcName},只是把它的异常位置和痕迹牢牢记下。`; } const itemText = reward?.items.length ? reward.items.map((item) => item.name).join('、') : '零散战利品'; const restoreParts = [ (reward?.hp ?? 0) > 0 ? `气血 +${reward?.hp ?? 0}` : null, (reward?.mana ?? 0) > 0 ? `灵力 +${reward?.mana ?? 0}` : null, ].filter(Boolean); const restoreText = restoreParts.length > 0 ? `,并恢复 ${restoreParts.join('、')}` : ''; const currencyText = reward ? `,另得 ${reward.currency} 钱币` : ''; const storyHint = reward?.storyHint ? ` ${reward.storyHint}` : ''; if (action === 'inspect') { return `你仔细检查了 ${encounter.npcName},顺着现场痕迹拆开机关与伪装,最终收回 ${itemText}${currencyText}${restoreText}。${storyHint}`; } return `你迅速收下了 ${encounter.npcName} 中最关键的收获:${itemText}${currencyText}。${storyHint}`; }