dispatcher = $dispatcher; $this->stateManager = $stateManager; $this->input = $input; $this->output = $output; $this->helper = $helper; $this->loadShopInventory(); } private function loadShopInventory(): void { // 模拟商店出售的物品配置 (ID 对应 LootService::loadItemData) $this->shopInventory = [ // 商店物品 ID => 价格倍数(如果价格不是 Item::value) 1 => ['stock' => 10, 'price' => 10], // 小药水 3 => ['stock' => 5, 'price' => 100], // 新物品:高级药水 ]; } public function handleEvent(Event $event): void { switch ($event->getType()) { case 'OpenShopEvent': // 响应 InteractionSystem 的请求 $this->startShopping(); break; } } /** * 启动商店界面和循环 */ private function startShopping(): void { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "\n欢迎光临!看看我有什么好东西。"])); $running = true; while ($running) { $player = $this->stateManager->getPlayer(); $this->displayShopMenu($player); $question = new Question("> 请选择操作 (B:购买 | S:出售 | X:退出):"); $choice = strtoupper($this->helper->ask($this->input, $this->output, $question) ?? ''); switch ($choice) { case 'B': $this->handlePurchase(); break; case 'S': $this->handleSelling(); break; case 'X': $running = false; $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '下次再来!'])); break; default: $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '无效的指令。'])); } } } // --- 购买逻辑 --- private function handlePurchase(): void { $this->displaySaleItems(); $player = $this->stateManager->getPlayer(); $question = new Question("> 输入要购买的物品编号 (或 X 退出):"); $choice = strtoupper($this->helper->ask($this->input, $this->output, $question) ?? ''); if ($choice === 'X') return; if (is_numeric($choice)) { $itemId = (int)$choice; if (isset($this->shopInventory[$itemId])) { $price = $this->shopInventory[$itemId]['price']; if ($player->spendGold($price)) { // ⭐ 触发事件请求 LootService 给予物品(重用 LootService 的逻辑) $this->dispatcher->dispatch(new Event('ShopPurchaseEvent', ['itemId' => $itemId])); $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "交易成功!花费 {$price} 💰,剩余 {$player->getGold()} 💰。" ])); } else { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "金币不足!你需要 {$price} 💰。"])); } } else { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '商店没有这个编号的物品。'])); } } } // --- 出售逻辑 --- private function handleSelling(): void { $player = $this->stateManager->getPlayer(); if (empty($player->getInventory())) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '你的背包是空的,没有什么可卖的。'])); return; } $this->displaySellableItems($player); $question = new Question("> 输入要出售的物品编号 (背包索引 | 或 X 退出):"); $choice = strtoupper($this->helper->ask($this->input, $this->output, $question) ?? ''); if ($choice === 'X') return; if (is_numeric($choice)) { $index = (int)$choice; $inventory = $player->getInventory(); if (isset($inventory[$index])) { $item = $inventory[$index]; // 简化:出售价格为 Item::value 的一半 $sellPrice = floor($item->value / 2); // 移除物品并获得金币 $player->removeItemByIndex($index); $player->gainGold($sellPrice); $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "💰 出售了 {$item->name},获得 {$sellPrice} 💰。剩余 {$player->getGold()} 💰。" ])); // 触发 UI 更新 $this->dispatcher->dispatch(new Event('InventoryUpdateEvent')); } else { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '无效的背包编号。'])); } } } // --- UI 辅助方法 --- private function displayShopMenu(Player $player): void { $this->output->writeln("\n--- 商店主页 ---"); $this->output->writeln("你的金币: {$player->getGold()} 💰"); $this->output->writeln("--------------------------"); } private function displaySaleItems(): void { $this->output->writeln("\n--- 🛒 商店出售 ---"); // 模拟获取 Item 数据的服务(实际应通过 ItemService/DB) $itemsData = [ 1 => ['name' => '小型治疗药水', 'value' => 10, 'type' => 'potion'], 3 => ['name' => '高级治疗药水', 'value' => 200, 'type' => 'potion'], // 假设 ID 3 ]; foreach ($this->shopInventory as $itemId => $data) { $name = $itemsData[$itemId]['name'] ?? "未知物品"; $price = $data['price']; $this->output->writeln("[{$itemId}] {$name} | 价格: {$price} 💰"); } $this->output->writeln("--------------------------"); } private function displaySellableItems(Player $player): void { $this->output->writeln("\n--- 📦 出售你的物品 ---"); $inventory = $player->getInventory(); if (empty($inventory)) return; foreach ($inventory as $index => $item) { $sellPrice = floor($item->value / 2); $this->output->writeln("[{$index}] {$item->name} | 售价: {$sellPrice} 💰"); } $this->output->writeln("--------------------------"); } }