This commit is contained in:
2026-04-28 19:36:39 +08:00
parent a9febe7678
commit f0471a4f8d
206 changed files with 18456 additions and 10133 deletions

View File

@@ -77,39 +77,6 @@ type IncrementRuntimeStats = (
increments: RuntimeStatsIncrements,
) => GameState;
function isImmediateCombatChoice(option: StoryOption) {
return (
option.functionId.startsWith('battle_') ||
option.functionId === 'inventory_use'
);
}
function shouldResolveCombatChoiceLocally(
gameState: GameState,
currentStory: StoryMoment | null,
option: StoryOption,
) {
if (!isImmediateCombatChoice(option)) {
return false;
}
if (gameState.inBattle) {
return true;
}
const hasBattleMarkers =
Boolean(gameState.currentBattleNpcId || gameState.currentNpcBattleMode) ||
gameState.sceneHostileNpcs.some((hostileNpc) => hostileNpc.hp > 0);
const storyStillShowsBattleChoices = Boolean(
currentStory?.options.some(isImmediateCombatChoice),
);
// 中文注释:真实运行态里可能短暂出现“可见层仍在战斗,但逻辑态 inBattle
// 已经被提前切回 false”的窗口。如果这时玩家点击了还在面板上的 battle_* /
// inventory_use 选项,必须继续走本地逐帧战斗链,不能误分流到服务端直结算。
return hasBattleMarkers || storyStillShowsBattleChoices;
}
export function createStoryChoiceActions({
gameState,
currentStory,
@@ -213,9 +180,6 @@ export function createStoryChoiceActions({
currentScenePreset:
currentStory.deferredRuntimeState.currentScenePreset ??
gameState.currentScenePreset,
storyEngineMemory:
currentStory.deferredRuntimeState.storyEngineMemory ??
gameState.storyEngineMemory,
});
}
setCurrentStory({
@@ -252,10 +216,7 @@ export function createStoryChoiceActions({
return;
}
if (
isRpgRuntimeServerFunctionId(option.functionId) &&
!shouldResolveCombatChoiceLocally(gameState, currentStory, option)
) {
if (isRpgRuntimeServerFunctionId(option.functionId)) {
await runServerRuntimeChoiceAction({
gameState,
currentStory,