using System.Collections.Generic; using Cielonos.MainGame.Interactions; using Cielonos.MainGame.Inventory.Collections; using Cielonos.MainGame.Map; using Cielonos.MainGame.UI; using UnityEngine; namespace Cielonos.MainGame.Rewards { /// /// 将 CombatRewardInstruction 转换为实际奖励效果。 /// Dispatcher 只负责“发放/生成”,奖励会话的生命周期仍由 RunManager.RunCombatRewardSubmodule 管理。 /// public static class CombatRewardDispatcher { private const string CombatRewardSpawnGroup = "CombatReward"; public static bool Dispatch(CombatRewardContext context, IReadOnlyList rewards) { bool hasPendingInteractable = false; if (rewards == null) { return false; } foreach (CombatRewardInstruction reward in rewards) { if (reward == null || reward.count <= 0) { continue; } switch (reward.type) { case CombatRewardInstructionType.RareMaterial: // 即时奖励:直接进入背包,不会阻塞玩家选择下一个节点。 GrantRareMaterial(reward, context.rng); break; case CombatRewardInstructionType.SupplyPack: case CombatRewardInstructionType.MechanicalTable: // 交互奖励:生成实体并登记 pending,玩家领取前不能离开当前节点。 hasPendingInteractable |= SpawnInteractableReward(reward, context.rng); break; } } return hasPendingInteractable; } private static void GrantRareMaterial(CombatRewardInstruction reward, System.Random rng) { int totalAmount = 0; for (int i = 0; i < reward.count; i++) { totalAmount += reward.RollRareMaterial(rng); } if (totalAmount <= 0) { return; } MainGameManager.Player.inventorySc.backpackSm.ObtainItem(totalAmount); PlayerCanvas.NotificationUIArea?.PushRareMaterial(totalAmount, "战斗奖励"); } private static bool SpawnInteractableReward(CombatRewardInstruction reward, System.Random rng) { int spawnCount = Mathf.Max(1, reward.count); bool spawnedAny = false; for (int i = 0; i < spawnCount; i++) { if (!TryCreateInteractableReward(reward, rng)) { continue; } spawnedAny = true; } return spawnedAny; } private static bool TryCreateInteractableReward(CombatRewardInstruction reward, System.Random rng) { string prefabId = reward.ResolveInteractablePrefabId(); GameObject instance = null; CombatRewardSession session = RunManager.Instance?.GetActiveCombatRewardSession(); int spawnIndex = session?.NextSpawnIndex() ?? 0; CombatRewardSpawnRequest spawnRequest = new( CombatRewardSpawnGroup, spawnIndex, 1.35f, session?.OccupiedSpawnPositions); if (ZoneManager.Instance != null) { ZoneManager.Instance.TrySpawnInteractable(prefabId, spawnRequest, out instance); } else { Debug.LogWarning("[CombatRewardDispatcher] ZoneManager.Instance 为空,无法生成 Combat 奖励。"); } if (instance == null) { Debug.LogWarning($"[CombatRewardDispatcher] 无法在 '{CombatRewardSpawnGroup}' 生成交互奖励 '{prefabId}'。"); return false; } ICombatRewardInteractable rewardInteractable = null; foreach (MonoBehaviour component in instance.GetComponents()) { if (component is ICombatRewardInteractable candidate) { rewardInteractable = candidate; break; } } if (rewardInteractable == null) { Debug.LogWarning($"[CombatRewardDispatcher] '{prefabId}' 没有实现 ICombatRewardInteractable。"); Object.Destroy(instance); return false; } rewardInteractable.SetupCombatReward(reward, rng); // 只有成功生成并完成 Setup 的交互奖励才登记 pending,避免阻塞 Run 流程。 RunManager.Instance?.RegisterPendingCombatReward(instance.transform.position); Debug.Log($"[CombatRewardDispatcher] 已在 '{CombatRewardSpawnGroup}' 生成 Combat 奖励 '{prefabId}'。"); return true; } } }