1
This commit is contained in:
@@ -18,11 +18,7 @@ import { lazy, Suspense, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { formatCurrency } from '../../data/economy';
|
||||
import { getEquipmentSlotFromItem } from '../../data/equipmentEffects';
|
||||
import {
|
||||
getFunctionDocumentationById,
|
||||
isContinueAdventureOption,
|
||||
NPC_CHAT_FUNCTION,
|
||||
} from '../../data/functionCatalog';
|
||||
import { isContinueAdventureOption } from '../../data/functionCatalog';
|
||||
import { getHostileNpcPresetById } from '../../data/hostileNpcPresets';
|
||||
import { resolveInventoryItemUseEffect } from '../../data/inventoryEffects';
|
||||
import { isQuestReadyToClaim } from '../../data/questFlow';
|
||||
@@ -136,22 +132,6 @@ function AdventurePanelOverlayLoadingFallback() {
|
||||
);
|
||||
}
|
||||
|
||||
function getCompactOptionDetailText(option: StoryOption) {
|
||||
if (option.functionId === NPC_CHAT_FUNCTION.id) {
|
||||
return (
|
||||
option.detailText ||
|
||||
getFunctionDocumentationById(option.functionId)?.runtime
|
||||
?.compactDetailText ||
|
||||
'聊聊并试探口风'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
getFunctionDocumentationById(option.functionId)?.runtime
|
||||
?.compactDetailText || option.detailText
|
||||
);
|
||||
}
|
||||
|
||||
function getOptionActionTextClass(option: StoryOption) {
|
||||
if ((option.priority ?? 1) >= 3)
|
||||
return 'text-fuchsia-200 group-hover:text-fuchsia-100';
|
||||
@@ -160,6 +140,67 @@ function getOptionActionTextClass(option: StoryOption) {
|
||||
return 'text-zinc-300 group-hover:text-white';
|
||||
}
|
||||
|
||||
function getOptionFunctionTagText(option: StoryOption) {
|
||||
const tagByFunctionId: Record<string, string> = {
|
||||
battle_all_in_crush: '战斗',
|
||||
battle_attack_basic: '战斗',
|
||||
battle_escape_breakout: '逃跑',
|
||||
battle_feint_step: '战斗',
|
||||
battle_finisher_window: '战斗',
|
||||
battle_guard_break: '战斗',
|
||||
battle_probe_pressure: '战斗',
|
||||
battle_recover_breath: '调息',
|
||||
battle_use_skill: '技能',
|
||||
camp_travel_home_scene: '场景',
|
||||
idle_call_out: '试探',
|
||||
idle_explore_forward: '探索',
|
||||
idle_follow_clue: '线索',
|
||||
idle_observe_signs: '观察',
|
||||
idle_rest_focus: '调息',
|
||||
idle_travel_next_scene: '场景',
|
||||
npc_chat: '聊天',
|
||||
npc_fight: '战斗',
|
||||
npc_gift: '送礼',
|
||||
npc_help: '求助',
|
||||
npc_leave: '离开',
|
||||
npc_preview_talk: '聊天',
|
||||
npc_quest_accept: '任务',
|
||||
npc_quest_turn_in: '任务',
|
||||
npc_recruit: '招募',
|
||||
npc_spar: '切磋',
|
||||
npc_trade: '交易',
|
||||
story_continue_adventure: '继续',
|
||||
treasure_inspect: '探查',
|
||||
treasure_leave: '离开',
|
||||
treasure_secure: '收取',
|
||||
};
|
||||
|
||||
if (option.functionId.startsWith('npc_chat_quest_offer_')) {
|
||||
return '任务';
|
||||
}
|
||||
|
||||
return tagByFunctionId[option.functionId] ?? null;
|
||||
}
|
||||
|
||||
function RpgOptionActionLabel({ option }: { option: StoryOption }) {
|
||||
const tagText = getOptionFunctionTagText(option);
|
||||
|
||||
return (
|
||||
<span className="flex min-w-0 flex-wrap items-center gap-1.5">
|
||||
{tagText ? (
|
||||
<span className="shrink-0 rounded border border-white/10 bg-white/10 px-1.5 py-0.5 text-[9px] leading-none text-zinc-300">
|
||||
{tagText}
|
||||
</span>
|
||||
) : null}
|
||||
<span
|
||||
className={`min-w-0 break-words text-sm sm:text-[15px] ${getOptionActionTextClass(option)}`}
|
||||
>
|
||||
{option.actionText}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function getDialogueTurnAlignmentClass(
|
||||
turn: NonNullable<StoryMoment['dialogue']>[number],
|
||||
) {
|
||||
@@ -798,29 +839,45 @@ function RpgAdventureChoiceSection(props: {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{isNpcChatMode ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onExitNpcChat?.()}
|
||||
aria-label="退出聊天"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 self-start rounded-md border border-rose-300/20 bg-rose-500/10 px-2 text-rose-100 transition-colors hover:bg-rose-500/15"
|
||||
>
|
||||
<span className="text-xs leading-none">退出聊天</span>
|
||||
</button>
|
||||
) : canRefreshOptions && !shouldHideChoiceUi ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onRefreshOptions}
|
||||
aria-label="换一换选项"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 self-start rounded-md border border-white/10 bg-black/20 px-2 text-zinc-300 transition-colors hover:text-white"
|
||||
>
|
||||
<PixelIcon
|
||||
src={CHROME_ICONS.refreshOptions}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<span className="text-xs leading-none">换一换</span>
|
||||
</button>
|
||||
) : null}
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
{isNpcChatMode && canRefreshOptions && !shouldHideChoiceUi ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onRefreshOptions}
|
||||
aria-label="换一换选项"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 self-start rounded-md border border-white/10 bg-black/20 px-2 text-zinc-300 transition-colors hover:text-white"
|
||||
>
|
||||
<PixelIcon
|
||||
src={CHROME_ICONS.refreshOptions}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<span className="text-xs leading-none">换一换</span>
|
||||
</button>
|
||||
) : !isNpcChatMode && canRefreshOptions && !shouldHideChoiceUi ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onRefreshOptions}
|
||||
aria-label="换一换选项"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 self-start rounded-md border border-white/10 bg-black/20 px-2 text-zinc-300 transition-colors hover:text-white"
|
||||
>
|
||||
<PixelIcon
|
||||
src={CHROME_ICONS.refreshOptions}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<span className="text-xs leading-none">换一换</span>
|
||||
</button>
|
||||
) : null}
|
||||
{isNpcChatMode ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onExitNpcChat?.()}
|
||||
aria-label="退出聊天"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1.5 self-start rounded-md border border-rose-300/20 bg-rose-500/10 px-2 text-rose-100 transition-colors hover:bg-rose-500/15"
|
||||
>
|
||||
<span className="text-xs leading-none">退出聊天</span>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
@@ -867,12 +924,8 @@ function RpgAdventureChoiceSection(props: {
|
||||
className="pixel-nine-slice pixel-pressable pixel-choice-button group w-full text-left"
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span
|
||||
className={`text-sm sm:text-[15px] ${getOptionActionTextClass(option)}`}
|
||||
>
|
||||
{option.actionText}
|
||||
</span>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<RpgOptionActionLabel option={option} />
|
||||
<PixelIcon
|
||||
src={CHROME_ICONS.optionArrow}
|
||||
className="h-3 w-3 opacity-70 transition-opacity group-hover:opacity-100"
|
||||
@@ -894,12 +947,8 @@ function RpgAdventureChoiceSection(props: {
|
||||
className={`pixel-nine-slice pixel-choice-button group w-full text-left ${optionDisabled ? 'cursor-not-allowed opacity-55' : 'pixel-pressable'}`}
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span
|
||||
className={`text-sm sm:text-[15px] ${getOptionActionTextClass(option)}`}
|
||||
>
|
||||
{option.actionText}
|
||||
</span>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<RpgOptionActionLabel option={option} />
|
||||
<PixelIcon
|
||||
src={CHROME_ICONS.optionArrow}
|
||||
className="h-3 w-3 opacity-70 transition-opacity group-hover:opacity-100"
|
||||
|
||||
Reference in New Issue
Block a user