1
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import type {
|
||||
RuntimeStoryActionRequest,
|
||||
RuntimeStoryPatch,
|
||||
} from '../../../../packages/shared/src/contracts/story.js';
|
||||
import { conflict, invalidRequest } from '../../errors.js';
|
||||
import {
|
||||
addInventoryItems,
|
||||
appendStoryEngineCarrierMemory,
|
||||
} from '../../bridges/legacyNpcTask6Bridge.js';
|
||||
import {
|
||||
buildTreasureResultText,
|
||||
resolveTreasureReward,
|
||||
} from '../../bridges/legacyTreasureRuntimeBridge.js';
|
||||
import { buildBuildToast } from '../inventory/inventoryStoryActionService.js';
|
||||
import {
|
||||
replaceRuntimeSessionRawGameState,
|
||||
type RuntimeSession,
|
||||
} from '../story/runtimeSession.js';
|
||||
|
||||
const SUPPORTED_TREASURE_STORY_FUNCTION_IDS = new Set<string>([
|
||||
'treasure_inspect',
|
||||
'treasure_leave',
|
||||
'treasure_secure',
|
||||
]);
|
||||
|
||||
type TreasureStoryResolution = {
|
||||
actionText: string;
|
||||
resultText: string;
|
||||
patches: RuntimeStoryPatch[];
|
||||
toast?: string | null;
|
||||
};
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
type RuntimeGameState = Parameters<typeof resolveTreasureReward>[0];
|
||||
type RuntimeEncounter = Parameters<typeof resolveTreasureReward>[1];
|
||||
|
||||
function resolveTreasureAction(functionId: string) {
|
||||
switch (functionId) {
|
||||
case 'treasure_secure':
|
||||
return 'secure';
|
||||
case 'treasure_inspect':
|
||||
return 'inspect';
|
||||
case 'treasure_leave':
|
||||
return 'leave';
|
||||
default:
|
||||
throw invalidRequest(`暂不支持的 Treasure 动作:${functionId}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getTreasureEncounter(
|
||||
session: RuntimeSession,
|
||||
state: RuntimeGameState,
|
||||
): RuntimeEncounter | null {
|
||||
const rawEncounter = state.currentEncounter;
|
||||
if (!rawEncounter || rawEncounter.kind !== 'treasure') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
npcAvatar: '',
|
||||
hostile: false,
|
||||
...rawEncounter,
|
||||
id: rawEncounter.id ?? session.currentEncounter?.id ?? rawEncounter.npcName,
|
||||
} satisfies RuntimeEncounter;
|
||||
}
|
||||
|
||||
export function isSupportedTreasureStoryFunctionId(functionId: string) {
|
||||
return SUPPORTED_TREASURE_STORY_FUNCTION_IDS.has(functionId);
|
||||
}
|
||||
|
||||
export function resolveTreasureStoryAction(
|
||||
session: RuntimeSession,
|
||||
request: RuntimeStoryActionRequest,
|
||||
): TreasureStoryResolution {
|
||||
const state = session.rawGameState as unknown as RuntimeGameState;
|
||||
const encounter = getTreasureEncounter(session, state);
|
||||
if (!encounter) {
|
||||
throw conflict('当前没有可结算的宝藏遭遇。');
|
||||
}
|
||||
|
||||
const action = resolveTreasureAction(request.action.functionId);
|
||||
const reward =
|
||||
action === 'leave' ? null : resolveTreasureReward(state, encounter, action);
|
||||
|
||||
let nextState = {
|
||||
...state,
|
||||
currentEncounter: null,
|
||||
npcInteractionActive: false,
|
||||
sceneHostileNpcs: [],
|
||||
playerX: 0,
|
||||
playerFacing: 'right' as const,
|
||||
animationState: state.animationState,
|
||||
scrollWorld: false,
|
||||
inBattle: false,
|
||||
playerHp: reward
|
||||
? Math.min(state.playerMaxHp, state.playerHp + reward.hp)
|
||||
: state.playerHp,
|
||||
playerMana: reward
|
||||
? Math.min(state.playerMaxMana, state.playerMana + reward.mana)
|
||||
: state.playerMana,
|
||||
playerCurrency: reward
|
||||
? state.playerCurrency + reward.currency
|
||||
: state.playerCurrency,
|
||||
playerInventory: reward
|
||||
? addInventoryItems(state.playerInventory, reward.items)
|
||||
: state.playerInventory,
|
||||
currentBattleNpcId: null,
|
||||
currentNpcBattleMode: null,
|
||||
currentNpcBattleOutcome: null,
|
||||
sparReturnEncounter: null,
|
||||
sparPlayerHpBefore: null,
|
||||
sparPlayerMaxHpBefore: null,
|
||||
sparStoryHistoryBefore: null,
|
||||
} satisfies RuntimeGameState;
|
||||
if (reward) {
|
||||
nextState = appendStoryEngineCarrierMemory(nextState, reward.items);
|
||||
}
|
||||
|
||||
replaceRuntimeSessionRawGameState(
|
||||
session,
|
||||
nextState as unknown as JsonRecord,
|
||||
);
|
||||
|
||||
return {
|
||||
actionText:
|
||||
action === 'leave'
|
||||
? '先记下位置'
|
||||
: action === 'inspect'
|
||||
? '仔细检查'
|
||||
: '直接收取',
|
||||
resultText: buildTreasureResultText(
|
||||
encounter,
|
||||
action,
|
||||
reward ?? undefined,
|
||||
state.worldType,
|
||||
),
|
||||
patches: [],
|
||||
toast: reward ? buildBuildToast(nextState) : null,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user