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

@@ -15,6 +15,7 @@ import {
NPC_RECRUIT_FUNCTION,
STATE_FUNCTION_DEFINITIONS as SPLIT_STATE_FUNCTION_DEFINITIONS,
STATE_FUNCTION_PROMPT_DESCRIPTIONS as SPLIT_STATE_FUNCTION_PROMPT_DESCRIPTIONS,
STATE_FUNCTION_RUNTIME_SOURCES,
} from './functionCatalog';
import {
getForwardScenePreset,
@@ -103,6 +104,12 @@ export function getFunctionPromptDescription(
const STATE_FUNCTION_OVERRIDES =
stateFunctionOverridesJson as StateFunctionOverrideMap;
const BASE_FUNCTIONS = [...SPLIT_STATE_FUNCTION_DEFINITIONS];
const STATE_FUNCTION_RUNTIME_SOURCE_MAP = new Map(
STATE_FUNCTION_RUNTIME_SOURCES.map((source) => [
source.definition.id,
source,
]),
);
function mergeStateFunctionDefinition(
definition: StateFunctionDefinition,
@@ -151,25 +158,9 @@ function applyRuntimeFunctionAdjustments(
return definitions
.filter((definition) => definition.id !== 'idle_follow_clue')
.map((definition) => {
if (definition.id === 'idle_explore_forward') {
return {
...definition,
text: '继续向前探索',
description:
'沿着当前场景继续深入,把前路真正探出来,下一刻就可能撞上新的危险或际遇。',
};
}
if (definition.id === 'idle_call_out') {
return {
...definition,
text: '主动出声试探',
description:
'主动朝前方喊话试探,可能把附近潜着的角色或怪物直接从远处引出来。',
};
}
return definition;
const runtime =
STATE_FUNCTION_RUNTIME_SOURCE_MAP.get(definition.id)?.runtime;
return runtime?.applyDefinitionAdjustments?.(definition) ?? definition;
});
}
@@ -211,15 +202,16 @@ function getMonsterHpRatio(context: FunctionAvailabilityContext) {
return monster.hp / Math.max(monster.maxHp, 1);
}
function buildSuggestedActionText(
definition: StateFunctionDefinition,
context: FunctionAvailabilityContext,
) {
function buildRuntimeMetrics(context: FunctionAvailabilityContext) {
return {
playerHpRatio: getPlayerHpRatio(context),
playerManaRatio: getPlayerManaRatio(context),
monsterHpRatio: getMonsterHpRatio(context),
};
}
function buildRuntimeEnvironment(context: FunctionAvailabilityContext) {
const monster = getPrimaryMonster(context);
const monsterName = monster?.name ?? '前方怪物';
const playerHpRatio = getPlayerHpRatio(context);
const playerManaRatio = getPlayerManaRatio(context);
const monsterHpRatio = getMonsterHpRatio(context);
const forwardScene = getForwardScenePreset(
context.worldType,
context.currentSceneId,
@@ -229,153 +221,51 @@ function buildSuggestedActionText(
context.currentSceneId,
);
const sceneName = context.currentSceneName ?? '前路';
return {
sceneName: context.currentSceneName ?? '前路',
monsterName: monster?.name ?? '前方怪物',
hasForwardScene: Boolean(forwardScene),
travelSceneName: travelScene?.name ?? null,
travelSceneDescription: travelScene?.description ?? null,
};
}
if (definition.id === 'idle_explore_forward') {
if (playerHpRatio <= 0.35)
return `按着伤口,沿着${sceneName}继续往深处摸去`;
if (forwardScene) return `顺着${sceneName}的路势,继续朝前方深处探去`;
return `拨开${sceneName}前的遮挡,继续朝更深处探去`;
}
if (definition.id === 'idle_call_out') {
return `冲着${sceneName}前方扬声试探,看是谁先被逼出来`;
}
switch (definition.id) {
case 'battle_finisher_window':
if (monsterHpRatio <= 0.25) return `完成对${monsterName}的残血收割`;
if (monsterHpRatio <= 0.45) return `抓住${monsterName}露出的破绽补上重击`;
return `盯住${monsterName}的空当准备终结一击`;
case 'battle_all_in_crush':
if (monsterHpRatio <= 0.25) return `压上去收掉${monsterName}最后一口气`;
if (playerHpRatio <= 0.35) return `顶着伤势强压${monsterName}赌一波强杀`;
return `正面强压${monsterName}不给喘息`;
case 'battle_guard_break':
if (monsterHpRatio <= 0.35) return `砸开${monsterName}的架势直接斩落`;
return `重击破开${monsterName}的招架`;
case 'battle_probe_pressure':
if (playerManaRatio <= 0.3)
return `稳住节奏试探${monsterName},先省下灵力`;
if (monsterHpRatio <= 0.3) return `稳步逼近,补掉${monsterName}残余血量`;
return `稳扎稳打继续试探${monsterName}`;
case 'battle_feint_step':
if (monsterHpRatio <= 0.35) return `虚晃切进去收掉${monsterName}`;
return `借假动作切进${monsterName}身前`;
case 'battle_recover_breath':
if (playerHpRatio <= 0.35) return '原地打坐恢复血量';
if (playerManaRatio <= 0.3) return '收势调息回一口灵力';
return '边守边调息稳住节奏';
case 'battle_escape_breakout':
if (playerHpRatio <= 0.35) return `撑着伤势先脱离${monsterName}的追杀`;
return `转身拉开距离,甩开${monsterName}`;
case 'idle_explore_forward':
if (forwardScene) return `继续向前探路`;
if (playerHpRatio <= 0.35) return '拖着伤势继续向前摸索';
return '继续向前探索前路';
case 'idle_travel_next_scene':
return travelScene ? `前往${travelScene.name}` : '前往其他场景';
case 'idle_rest_focus':
if (playerHpRatio <= 0.35) return '原地打坐恢复气血';
if (playerManaRatio <= 0.35) return '盘坐调息恢复灵力';
return '原地调息整理状态';
case 'idle_observe_signs':
return '停步观察附近的风吹草动';
case 'idle_follow_clue':
return '顺着可疑痕迹继续靠近';
case 'idle_call_out':
return '朝前方主动出声试探';
default:
return definition.text;
}
function buildSuggestedActionText(
definition: StateFunctionDefinition,
context: FunctionAvailabilityContext,
) {
const runtime = STATE_FUNCTION_RUNTIME_SOURCE_MAP.get(definition.id)?.runtime;
return (
runtime?.buildSuggestedActionText?.({
definition,
metrics: buildRuntimeMetrics(context),
environment: buildRuntimeEnvironment(context),
}) ?? definition.text
);
}
function buildOptionDetailText(
definition: StateFunctionDefinition,
context: FunctionAvailabilityContext,
) {
const forwardScene = getForwardScenePreset(
context.worldType,
context.currentSceneId,
);
const travelScene = getTravelScenePreset(
context.worldType,
context.currentSceneId,
);
const sceneName = context.currentSceneName ?? '当前区域';
if (definition.id === 'idle_explore_forward') {
return forwardScene
? `沿着${sceneName}继续往前压过去,真正把前方会遇到的人影、怪物或宝藏探出来。`
: `继续深入${sceneName}前方未探明的地带,下一刻就可能撞见新的动静。`;
}
if (definition.id === 'idle_call_out') {
return '主动打破寂静,把附近潜着的角色或怪物从屏幕外直接引到眼前。';
}
switch (definition.id) {
case 'idle_explore_forward':
return forwardScene
? `沿当前路径继续深入,可能会遇到角色、怪物、宝藏……`
: '继续向前试探这片区域,可能会遇到角色、怪物、宝藏……';
case 'idle_travel_next_scene':
return travelScene?.description ?? '离开当前区域,前往相邻场景继续冒险。';
case 'idle_observe_signs':
return '先确认附近是否潜伏着人影、怪物或其他值得靠近的东西。';
case 'idle_follow_clue':
return '沿着声音、脚印或灵气痕迹继续摸过去,可能更快接近前方目标。';
case 'idle_call_out':
return '主动打破寂静,看看附近是谁或什么东西先有反应。';
default:
return undefined;
}
const runtime = STATE_FUNCTION_RUNTIME_SOURCE_MAP.get(definition.id)?.runtime;
return runtime?.buildDetailText?.({
definition,
environment: buildRuntimeEnvironment(context),
});
}
function getFunctionPriority(
definition: StateFunctionDefinition,
context: FunctionAvailabilityContext,
) {
const playerHpRatio = getPlayerHpRatio(context);
const playerManaRatio = getPlayerManaRatio(context);
const monsterHpRatio = getMonsterHpRatio(context);
if (definition.id === 'idle_call_out') {
return 5;
}
switch (definition.id) {
case 'battle_recover_breath':
return (
(playerHpRatio <= 0.35 ? 10 : 0) + (playerManaRatio <= 0.3 ? 6 : 0)
);
case 'battle_finisher_window':
return monsterHpRatio <= 0.25 ? 10 : monsterHpRatio <= 0.45 ? 6 : 1;
case 'battle_all_in_crush':
return monsterHpRatio <= 0.25 ? 8 : playerHpRatio <= 0.35 ? 2 : 4;
case 'battle_guard_break':
return monsterHpRatio <= 0.4 ? 6 : 3;
case 'battle_probe_pressure':
return playerManaRatio <= 0.3 ? 8 : 4;
case 'battle_feint_step':
return monsterHpRatio <= 0.5 ? 5 : 3;
case 'battle_escape_breakout':
return playerHpRatio <= 0.2 ? 9 : playerHpRatio <= 0.35 ? 5 : 1;
case 'idle_rest_focus':
return playerHpRatio <= 0.35 || playerManaRatio <= 0.35 ? 8 : 2;
case 'idle_explore_forward':
return playerHpRatio > 0.45 ? 6 : 2;
case 'idle_travel_next_scene':
return playerHpRatio > 0.45 ? 5 : 3;
case 'idle_observe_signs':
return 4;
case 'idle_follow_clue':
return 5;
case 'idle_call_out':
return 3;
default:
return 0;
}
const runtime = STATE_FUNCTION_RUNTIME_SOURCE_MAP.get(definition.id)?.runtime;
return (
runtime?.getPriority?.({
definition,
metrics: buildRuntimeMetrics(context),
}) ?? 0
);
}
function matchesCategory(