dispatcher = $dispatcher; $this->stateManager = $stateManager; $this->itemRepository = $itemRepository; $this->enemyRepository = $enemyRepository; } public function createEnemy(string $id): ?Enemy { // ⭐ 使用 Repository 获取数据 $data = $this->enemyRepository->find($id); if (!$data) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "❌ 错误:敌人ID '{$id}' 不存在。"])); return null; } // ⭐ 修正实例化 Enemy:传入 loot_table return new Enemy( $data['id'], $data['name'], $data['health'], $data['attack'], $data['defense'], $data['xp'], $data['loot'] ?? [] // 传递 loot_table ); } public function handleEvent(Event $event): void { switch ($event->getType()) { case 'LootDropEvent': $enemyId = $event->getPayload()['enemyId']; // LootDropEvent 应该由 BattleService 在敌人死亡时触发 $this->handleLootDrop($enemyId); break; case 'LootFoundEvent': // 响应 MapSystem 探索时发现的宝箱 $lootId = $event->getPayload()['lootId']; $this->handleLootFound($lootId); break; case 'ShopPurchaseEvent': // ⭐ 响应商店购买 $itemId = $event->getPayload()['itemId']; $this->giveItemToPlayer($itemId); break; // ⭐ 响应遇敌事件 case 'EncounterEnemyEvent': $enemyId = $event->getPayload()['enemyId']; $newEnemy = $this->createEnemy($enemyId); if ($newEnemy) { // 通知 BattleService 启动战斗 $this->dispatcher->dispatch(new Event('StartBattleEvent', ['enemy' => $newEnemy])); } break; } } /** * ⭐ 修正方法:处理敌人死亡时的掉落逻辑(从配置中加载数据) */ private function handleLootDrop(string $enemyId): void { // 1. 获取敌人配置数据 $enemyData = $this->enemyRepository->find($enemyId); if (!$enemyData) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "❌ 错误:无法找到敌人 {$enemyId} 的掉落配置。"])); return; } // --- 2. 掉落金币 (从配置中获取范围) --- $minGold = $enemyData['min_gold'] ?? 5; // 使用配置,默认 5 $maxGold = $enemyData['max_gold'] ?? 15; // 使用配置,默认 15 $goldAmount = rand($minGold, $maxGold); $player = $this->stateManager->getPlayer(); $player->gainGold($goldAmount); $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "💰 获得了 {$goldAmount} 金币。" ])); // --- 3. 掉落物品 (从配置的 loot_table 中获取) --- $lootTable = $enemyData['loot_table'] ?? []; if (!empty($lootTable)) { $droppedItemId = $this->getRandomItemIdFromLootTable($lootTable); if ($droppedItemId !== null) { // 成功掉落物品 $this->giveItemToPlayer($droppedItemId); } else { $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "战利品很少,只找到了一些零钱。" ])); } } else { $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "战利品很少,只找到了一些零钱。" ])); } } /** * ⭐ 新增方法:根据权重随机选择物品 ID */ private function getRandomItemIdFromLootTable(array $lootTable): ?int { $totalChance = array_sum(array_column($lootTable, 'chance')); // 随机数范围是 1 到 100 $randValue = rand(1, 100); // 如果随机值大于总几率,则表示未掉落任何物品 // 例如:总几率为 80,随机数是 85,则不掉落 if ($randValue > $totalChance) { return null; } $currentChance = 0; foreach ($lootTable as $item) { $currentChance += $item['chance']; if ($randValue <= $currentChance) { // 确保 item_id 是整数类型 return (int)$item['item_id']; } } return null; } /** * 处理探索时发现的宝箱/固定物品 (保持不变) */ private function handleLootFound($lootId): void { } /** * 核心逻辑:创建物品实例并添加到玩家背包 (保持不变) */ private function giveItemToPlayer($itemId): void { // ... $item = $this->itemRepository->createItem($itemId); if (!$item) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => "❌ 物品ID '{$itemId}' 不存在,无法获得。"])); return; } $player = $this->stateManager->getPlayer(); $player->addItem($item); $this->dispatcher->dispatch(new Event('SystemMessage', [ 'message' => "➕ 获得了物品:{$item->name}!" ])); // 触发 InventoryUpdateEvent (未来用于 UI 实时更新) $this->dispatcher->dispatch(new Event('InventoryUpdateEvent', ['playerInventory' => $player->getInventory()])); } }