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