This commit is contained in:
2026-04-19 20:33:18 +08:00
parent 692643136f
commit 67c584b4df
123 changed files with 11898 additions and 4082 deletions

View File

@@ -84,6 +84,7 @@ import {
import { flattenDirectedRuntimeRewardItems } from './runtimeItemNarrative';
import {
getStoryOptionPriority,
resolveFunctionOption,
sortStoryOptionsByPriority,
} from './stateFunctions';
@@ -1392,6 +1393,77 @@ function buildNpcOption(
} as StoryOption;
}
function buildHostileNpcDialogueText(
encounter: Encounter,
affinity: number,
) {
const hostilityText =
affinity <= -20
? '旧账就留到今天一起清。'
: affinity <= -10
? '我们之间已经没什么可谈的了。'
: '你再往前一步,我就当你是在挑衅。';
const contextText = encounter.context?.trim()
? `你居然还敢带着${encounter.context}的事来见我,`
: '';
return `${contextText}${hostilityText} 要么现在转身逃开,要么就拔刀。`;
}
function buildHostileNpcEscapeOption(params: {
state?: GameState | null;
worldType: WorldType | null;
playerCharacter: Character;
}) {
const functionContext =
params.worldType
? {
worldType: params.worldType,
playerCharacter: params.playerCharacter,
inBattle: false,
currentSceneId: params.state?.currentScenePreset?.id ?? null,
currentSceneName: params.state?.currentScenePreset?.name ?? null,
monsters: [],
playerHp: params.state?.playerHp ?? 1,
playerMaxHp: params.state?.playerMaxHp ?? 1,
playerMana: params.state?.playerMana ?? 0,
playerMaxMana: params.state?.playerMaxMana ?? 0,
}
: null;
const resolvedOption = functionContext
? resolveFunctionOption(
'battle_escape_breakout',
functionContext,
'逃跑',
)
: null;
if (resolvedOption) {
return {
...resolvedOption,
actionText: '逃跑',
text: '逃跑',
detailText: '',
} satisfies StoryOption;
}
return {
functionId: 'battle_escape_breakout',
actionText: '逃跑',
text: '逃跑',
detailText: '',
priority: getStoryOptionPriority('battle_escape_breakout'),
visuals: {
playerAnimation: AnimationState.RUN,
playerMoveMeters: -0.6,
playerOffsetY: 0,
playerFacing: 'left',
scrollWorld: true,
monsterChanges: [],
},
} satisfies StoryOption;
}
function buildQuestAcceptOpportunityDetail(params: {
issuerNpcId: string;
issuerNpcName: string;
@@ -2024,20 +2096,35 @@ export function buildNpcEncounterStoryMoment({
Boolean(encounter.monsterPresetId);
if (isHostileEncounter) {
const hostileDialogueText =
overrideText ?? buildHostileNpcDialogueText(encounter, npcState.affinity);
options.push(
buildHostileNpcEscapeOption({
state,
worldType,
playerCharacter,
}),
);
options.push(
buildNpcOption(
NPC_FIGHT_FUNCTION.id,
`迎战${encounter.npcName}`,
'对方敌意已明确,靠近后就会直接进入战斗。',
'与他对战',
'',
npcId,
'fight',
),
);
return {
text:
overrideText ??
`${scene?.name ?? '当前地界'}里,${encounter.npcName}已将你视为敌人。它一照面就摆出了进攻姿态,当前好感为 ${npcState.affinity}`,
text: hostileDialogueText,
displayMode: 'dialogue',
dialogue: [
{
speaker: 'npc',
speakerName: encounter.npcName,
text: hostileDialogueText,
},
],
options: sortStoryOptionsByPriority(options),
};
}