fanren/src/System/InteractionSystem.php
2025-12-22 18:07:05 +08:00

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'));
}
}
}
}