144 lines
5.6 KiB
PHP
144 lines
5.6 KiB
PHP
<?php
|
|
namespace Game\System;
|
|
|
|
use Game\Database\NPCRepository;
|
|
use Game\Database\QuestRepository; // ⭐ Add Import
|
|
use Game\Event\Event;
|
|
use Game\Event\EventListenerInterface;
|
|
use Game\Event\EventDispatcher;
|
|
use Game\Model\NPC;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
|
use Symfony\Component\Console\Question\Question;
|
|
|
|
/**
|
|
* InteractionSystem: 负责处理玩家与 NPC 的对话和交互流程。
|
|
*/
|
|
class InteractionSystem implements EventListenerInterface {
|
|
|
|
private EventDispatcher $dispatcher;
|
|
private StateManager $stateManager;
|
|
private NPCRepository $npcRepository; // ⭐ 新增属性
|
|
private QuestRepository $questRepository; // ⭐ 新增
|
|
private DialogueService $dialogueService; // ⭐ 新增
|
|
// 输入依赖
|
|
private InputInterface $input;
|
|
private OutputInterface $output;
|
|
private QuestionHelper $helper;
|
|
|
|
// ⭐ 修正构造函数:注入 NPCRepository
|
|
public function __construct(
|
|
EventDispatcher $dispatcher,
|
|
StateManager $stateManager,
|
|
NPCRepository $npcRepository,
|
|
QuestRepository $questRepository, // ⭐ 参数
|
|
DialogueService $dialogueService, // ⭐ 参数
|
|
InputInterface $input,
|
|
OutputInterface $output,
|
|
QuestionHelper $helper
|
|
) {
|
|
$this->dispatcher = $dispatcher;
|
|
$this->stateManager = $stateManager;
|
|
$this->npcRepository = $npcRepository; // ⭐ 赋值
|
|
$this->questRepository = $questRepository; // ⭐ 赋值
|
|
$this->dialogueService = $dialogueService; // ⭐ 赋值
|
|
$this->input = $input;
|
|
$this->output = $output;
|
|
$this->helper = $helper;
|
|
}
|
|
|
|
public function handleEvent(Event $event): void {
|
|
switch ($event->getType()) {
|
|
case 'AttemptInteractEvent':
|
|
$npcId = $event->getPayload()['npcId'];
|
|
$this->startInteraction($npcId);
|
|
break;
|
|
// ⭐ 修正事件名称
|
|
case 'StartInteractionEvent':
|
|
$npcId = $event->getPayload()['npcId'];
|
|
$this->startInteraction($npcId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 初始化 NPC 交互
|
|
*/
|
|
private function startInteraction(string $npcId): void {
|
|
// ⭐ 修正:使用 Repository 加载 NPC
|
|
$npc = $this->npcRepository->createNPC($npcId);
|
|
|
|
if (!$npc) {
|
|
$this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "这里没有人可以交谈 ({$npcId} 不存在)。"]));
|
|
// ⭐ 切换回地图模式
|
|
$this->stateManager->setMode(StateManager::MODE_MAP);
|
|
return;
|
|
}
|
|
|
|
$this->dispatcher->dispatch(new Event('SystemMessage', [
|
|
'message' => "👤 你走近了 <fg=cyan;options=bold>{$npc->getName()}</>。"
|
|
]));
|
|
|
|
// ⭐ 直接尝试触发任务对话
|
|
$player = $this->stateManager->getPlayer();
|
|
$questIds = $this->questRepository->getQuestsByNpc($npc->id);
|
|
$foundQuest = false;
|
|
|
|
// ⭐ 优先检查是否有已完成的任务可以提交
|
|
foreach ($questIds as $questId) {
|
|
$activeQuests = $player->getActiveQuests();
|
|
if (isset($activeQuests[$questId]) && $activeQuests[$questId]->isCompleted()) {
|
|
// 找到已完成的任务,提示玩家交任务
|
|
$this->dispatcher->dispatch(new Event('QuestTurnInPrompt', [
|
|
'questId' => $questId,
|
|
'npcId' => $npc->id
|
|
]));
|
|
$foundQuest = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 如果没有已完成的任务,检查是否有新任务
|
|
if (!$foundQuest) {
|
|
foreach ($questIds as $questId) {
|
|
// 检查任务状态:未接受 或 进行中
|
|
if (!$player->isQuestCompleted($questId) && !isset($player->getActiveQuests()[$questId])) {
|
|
// 找到了一个新任务!
|
|
$questData = $this->questRepository->find($questId);
|
|
if ($questData && !empty($questData['dialogue'])) {
|
|
// ⭐ 使用新版对话系统
|
|
$this->dialogueService->startDialogue($questData['dialogue']);
|
|
$foundQuest = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$foundQuest) {
|
|
// 如果没有新任务,显示 NPC 默认闲聊
|
|
$defaultMsg = is_array($npc->dialogue) ? ($npc->dialogue['greeting'] ?? '...') : '...';
|
|
$this->dispatcher->dispatch(new Event('SystemMessage', [
|
|
'message' => "<fg=cyan>{$npc->getName()}</><fg=white>{$defaultMsg}</>"
|
|
]));
|
|
|
|
// ⭐ 检查NPC是否有商店
|
|
if ($npc->hasShop) {
|
|
$this->dispatcher->dispatch(new Event('SystemMessage', [
|
|
'message' => "\n🛍️ <fg=yellow>{$npc->getName()}</> 还经营着一家商店。"
|
|
]));
|
|
$this->dispatcher->dispatch(new Event('SystemMessage', [
|
|
'message' => "<fg=gray>输入 [S] 打开商店,[X] 离开</>"
|
|
]));
|
|
|
|
// 设置待处理的商店NPC
|
|
$this->stateManager->setPendingShopNpc($npc);
|
|
} else {
|
|
// ⭐ 没有任务也没有商店时切换回地图模式
|
|
$this->stateManager->setMode(StateManager::MODE_MAP);
|
|
$this->dispatcher->dispatch(new Event('ShowMenuEvent'));
|
|
}
|
|
}
|
|
}
|
|
} |