using System; using System.Collections.Generic; using System.Linq; using Continentis.MainGame.Card; using Continentis.MainGame.Character; using Cysharp.Threading.Tasks; using DG.Tweening; using SLSUtilities.General; using UnityEngine; using Random = UnityEngine.Random; namespace Continentis.MainGame.Commands { public class Cmd_DrawCards : CommandBase { private readonly DeckSubmodule deck; private readonly int drawCount; private readonly float interval; private readonly List customDrawCards; private readonly bool isCustomDraw; private const float SingleCardAnimationDuration = 0.4f; public Cmd_DrawCards(DeckSubmodule deck, int drawCount, float interval = 0.1f) { this.deck = deck; this.drawCount = drawCount; this.interval = interval; isCustomDraw = false; customDrawCards = null; } public Cmd_DrawCards(DeckSubmodule deck, List customDrawCards, float interval = 0.1f) { this.deck = deck; this.drawCount = customDrawCards.Count; this.interval = interval; this.customDrawCards = customDrawCards; isCustomDraw = true; } protected override async UniTask ExecuteAsync(CommandContext outerContext) { if (!isCustomDraw) { int finalDrawCount = Mathf.Min(drawCount, deck.DrawPile.Count); if (finalDrawCount <= 0) { Debug.Log("[Cmd_DrawCards] 无牌可抽。"); outerContext.Set(CommandContextKeys.DrawnCards, new List()); return; } // 快照:在动画开始前记录将要抽的牌(顺序与 DrawPile 一致) var drawnCards = deck.DrawPile.Take(finalDrawCount).ToList(); outerContext.Set(CommandContextKeys.DrawnCards, drawnCards); Debug.Log($"[Cmd_DrawCards] 抽取 {finalDrawCount} 张牌。"); await DrawStaggeredAsync(finalDrawCount, drawnCards.Count); } else { outerContext.Set(CommandContextKeys.DrawnCards, customDrawCards); Debug.Log($"[Cmd_DrawCards] 抽取 {customDrawCards.Count} 张指定牌。"); await DrawCustomStaggeredAsync(customDrawCards); } } // 标准抽牌:每次从 DrawPile[0] 取牌,交错并行动画 private async UniTask DrawStaggeredAsync(int count, int totalCount) { var tasks = new UniTask[count]; for (int i = 0; i < count; i++) tasks[i] = DrawOneWithDelay(i, totalCount, i * interval); await UniTask.WhenAll(tasks); } private async UniTask DrawOneWithDelay(int index, int totalCount, float delay) { if (delay > 0f) await UniTask.Delay(TimeSpan.FromSeconds(delay)); var card = deck.DrawPile[0]; deck.TransferCard(deck.DrawPile, deck.HandPile, card); card.eventSubmodule.onDraw.Invoke(); card.handCardView.TransferCardView(CombatUIManager.Instance.combatMainPage.handPile); PlayDrawAnimation(card, index, totalCount); await UniTask.Delay(TimeSpan.FromSeconds(SingleCardAnimationDuration)); } // 指定牌抽牌:交错并行动画 private async UniTask DrawCustomStaggeredAsync(List cards) { var tasks = new UniTask[cards.Count]; for (int i = 0; i < cards.Count; i++) { CardInstance captured = cards[i]; int idx = i; tasks[i] = DrawCustomOneWithDelay(captured, idx, cards.Count, idx * interval); } await UniTask.WhenAll(tasks); } private async UniTask DrawCustomOneWithDelay(CardInstance card, int index, int totalCount, float delay) { if (delay > 0f) await UniTask.Delay(TimeSpan.FromSeconds(delay)); deck.TransferCard(card.cardLocation.pileName, "Hand", card); card.eventSubmodule.onDraw.Invoke(); card.handCardView.TransferCardView(CombatUIManager.Instance.combatMainPage.handPile); PlayDrawAnimation(card, index, totalCount); await UniTask.Delay(TimeSpan.FromSeconds(SingleCardAnimationDuration)); } private void PlayDrawAnimation(CardInstance card, int index, int totalCount) { var handPile = CombatUIManager.Instance.combatMainPage.handPile; var targetPosition = handPile.GetCardPosition(index, totalCount); var targetRotation = handPile.GetCardRotation(index, totalCount); var deltaMove = targetPosition - card.handCardView.cardTransform.localPosition; var randomLift = new Vector3(Random.Range(-200f, 200f), Random.Range(200f, 600f), 0f); card.handCardView.cardTransform.DOBlendableLocalMoveBy(deltaMove, SingleCardAnimationDuration).Play(); card.handCardView.cardTransform.DOBlendableLocalMoveBy(randomLift, SingleCardAnimationDuration * 0.5f) .SetLoops(2, LoopType.Yoyo).Play(); card.handCardView.cardTransform.DOLocalRotateQuaternion(targetRotation, SingleCardAnimationDuration).Play(); card.handCardView.cardTransform.DOScale(Vector3.one, SingleCardAnimationDuration).Play(); } } }