using System; using System.Collections; using Core; using Gameplay.Enemy; using Gameplay.Player; using Interface; using UnityEngine; namespace Gameplay { /// /// 战斗流程管理器(回合制、循环抽牌) /// 使用方法:在场景中挂载一个空物体并配置 player 与 enemy 的 Combatant 引用。 /// 该管理器通过事件回调让 UI 或其它系统接入“双方牌都打空时”的选择(继续/逃跑)。 /// public class CombatFlowManager : MonoSingleton { [Header("Participants")] public PlayerController player; public EnemyController enemy; [Header("Flow Settings")] [Tooltip("玩家是否先手(true=玩家先出一张)")] public bool playerStarts = true; [Tooltip("每出一张牌后的间隔(秒)")] public float turnDelay = 0.8f; // Events public event Action OnCombatStarted; public event Action OnCardPlayed; public event Action OnCombatEnded; // 参数为胜利方(null 表示平局或逃跑) public event Action OnBothEmpty; // 当双方都没有卡可以出时触发,UI 需要通过 ContinueAfterBothEmpty 或 EscapeFromCombat 响应 // internal state private Coroutine runningRoutine; private bool waitingForDecision = false; private bool decisionContinue = false; private bool decisionEscape = false; /// /// 启动战斗流程(也可以在 Inspector 中提前绑定 player/enemy,然后只调用 StartCombat()) /// public void StartCombat(PlayerController playerController = null, EnemyController enemyController = null) { if (playerController != null) player = playerController; if (enemyController != null) enemy = enemyController; if (player == null || enemy == null) { Debug.LogError("CombatFlowManager: player 或 enemy 未设置。"); return; } // 初始化双方状态 player.StartCombat(); enemy.StartCombat(); player.InitializeDeckCycle(); enemy.InitializeDeckCycle(); runningRoutine = StartCoroutine(CombatRoutine()); OnCombatStarted?.Invoke(); } public void StopCombat() { if (runningRoutine != null) StopCoroutine(runningRoutine); runningRoutine = null; } private IEnumerator CombatRoutine() { ICharacter current = playerStarts ? player : enemy; while (true) { // 结束检查 if (player.IsDead || enemy.IsDead) { ICharacter winner = player.IsDead ? enemy : player; OnCombatEnded?.Invoke(winner); runningRoutine = null; yield break; } bool playerHas = player.HasCardsLeft(); bool enemyHas = enemy.HasCardsLeft(); if (!playerHas && !enemyHas) { // 双方都打空,等待玩家选择(由 UI 调用 ContinueAfterBothEmpty 或 EscapeFromCombat) waitingForDecision = true; decisionContinue = false; decisionEscape = false; OnBothEmpty?.Invoke(); // 等待选择 while (waitingForDecision) yield return null; if (decisionEscape) { // 玩家选择逃跑 -> 结束战斗,胜者设为 null(或按需要设成敌人/玩家) OnCombatEnded?.Invoke(null); runningRoutine = null; yield break; } if (decisionContinue) { // 重新从卡册读取(重置抽牌队列),保持生命与其它状态不变 player.InitializeDeckCycle(); enemy.InitializeDeckCycle(); // 继续循环(当前先手不变) yield return null; continue; } } // 当前回合:如果当前方没有牌则跳过(空过) if (current.HasCardsLeft()) { var card = current.GetNextCard(); ICharacter target; if (current is PlayerController) { target = enemy; } else { target = player; } // 触发卡牌效果(当前仅支持直接伤害) if (card != null) { card.PlayCard(new CardContext(current, target)); OnCardPlayed?.Invoke(current, card); } // 检查死亡(将在下一循环顶部处理) yield return new WaitForSeconds(turnDelay); } else { // 跳过一轮,不延迟太久 yield return new WaitForSeconds(0.1f); } // 切换行动方 current = (current == player) ? enemy : player; } } /// /// 当双方都打空时,UI 调用此方法选择继续下一轮(重新从卡册读取卡牌) /// public void ContinueAfterBothEmpty() { if (!waitingForDecision) return; decisionContinue = true; waitingForDecision = false; } /// /// 当双方都打空时,UI 调用此方法选择逃跑 /// public void EscapeFromCombat() { if (!waitingForDecision) return; decisionEscape = true; waitingForDecision = false; } } }