@@ -28,7 +28,11 @@ import { resolveInventoryItemUseEffect } from '../data/inventoryEffects';
|
||||
import { isQuestReadyToClaim } from '../data/questFlow';
|
||||
import { getScenePresetById } from '../data/scenePresets';
|
||||
import { getOptionImpactSummary } from '../hooks/combatStoryUtils';
|
||||
import type { BattleRewardUi, QuestFlowUi } from '../hooks/useStoryGeneration';
|
||||
import type {
|
||||
BattleRewardUi,
|
||||
NpcChatQuestOfferUi,
|
||||
QuestFlowUi,
|
||||
} from '../hooks/useStoryGeneration';
|
||||
import type {
|
||||
ChapterState,
|
||||
Character,
|
||||
@@ -70,6 +74,7 @@ interface AdventurePanelProps {
|
||||
worldType: WorldType | null;
|
||||
quests: QuestLogEntry[];
|
||||
questUi: QuestFlowUi;
|
||||
npcChatQuestOfferUi: NpcChatQuestOfferUi;
|
||||
goalStack: GoalStackState;
|
||||
goalPulse: GoalPulseEvent | null;
|
||||
onDismissGoalPulse: () => void;
|
||||
@@ -625,6 +630,7 @@ export function AdventurePanel({
|
||||
worldType,
|
||||
quests,
|
||||
questUi,
|
||||
npcChatQuestOfferUi,
|
||||
goalStack,
|
||||
goalPulse,
|
||||
onDismissGoalPulse,
|
||||
@@ -646,6 +652,8 @@ export function AdventurePanel({
|
||||
const dialogueTurns = currentStory.dialogue ?? [];
|
||||
const npcChatState = currentStory.npcChatState ?? null;
|
||||
const isNpcChatMode = Boolean(npcChatState);
|
||||
const pendingNpcQuestOffer = npcChatState?.pendingQuestOffer?.quest ?? null;
|
||||
const isNpcQuestOfferMode = Boolean(pendingNpcQuestOffer);
|
||||
const isStoryStreaming = Boolean(currentStory.streaming);
|
||||
const shouldHideChoiceUi = hideOptions;
|
||||
const storyScrollContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
@@ -689,8 +697,10 @@ export function AdventurePanel({
|
||||
[quests],
|
||||
);
|
||||
const selectedQuest = useMemo(
|
||||
() => quests.find((quest) => quest.id === selectedQuestId) ?? null,
|
||||
[quests, selectedQuestId],
|
||||
() =>
|
||||
quests.find((quest) => quest.id === selectedQuestId) ??
|
||||
(pendingNpcQuestOffer?.id === selectedQuestId ? pendingNpcQuestOffer : null),
|
||||
[pendingNpcQuestOffer, quests, selectedQuestId],
|
||||
);
|
||||
const rewardQuest = useMemo(
|
||||
() => quests.find((quest) => quest.id === rewardQuestId) ?? null,
|
||||
@@ -901,6 +911,27 @@ export function AdventurePanel({
|
||||
Boolean(selectedRewardItem);
|
||||
|
||||
const handleOptionChoice = (option: StoryOption) => {
|
||||
const pendingQuestAction =
|
||||
typeof option.runtimePayload?.npcChatQuestOfferAction === 'string'
|
||||
? option.runtimePayload.npcChatQuestOfferAction
|
||||
: null;
|
||||
if (pendingQuestAction && pendingNpcQuestOffer) {
|
||||
if (pendingQuestAction === 'view') {
|
||||
setSelectedQuestId(pendingNpcQuestOffer.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingQuestAction === 'replace') {
|
||||
void npcChatQuestOfferUi.replacePendingOffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingQuestAction === 'abandon') {
|
||||
npcChatQuestOfferUi.abandonPendingOffer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
option.interaction?.kind === 'npc' &&
|
||||
option.interaction.action === 'quest_accept'
|
||||
@@ -1179,7 +1210,7 @@ export function AdventurePanel({
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
{isNpcChatMode ? (
|
||||
{isNpcChatMode && !isNpcQuestOfferMode ? (
|
||||
<div className="pixel-nine-slice pixel-panel mt-0.5 border border-white/10 bg-black/25 p-1.5">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<input
|
||||
@@ -1263,6 +1294,13 @@ export function AdventurePanel({
|
||||
selectedRewardEquipSlot={selectedRewardEquipSlot}
|
||||
selectedQuestSceneName={selectedQuestSceneName}
|
||||
getQuestStatusLabel={getQuestStatusLabel}
|
||||
pendingNpcQuestOffer={pendingNpcQuestOffer}
|
||||
onAcceptPendingNpcQuestOffer={() => {
|
||||
const acceptedQuestId = npcChatQuestOfferUi.acceptPendingOffer();
|
||||
if (!acceptedQuestId) return null;
|
||||
setSelectedQuestId(null);
|
||||
return acceptedQuestId;
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user