Files
SoulliesOfficial ac98ec3aef 更新
2026-04-17 12:01:50 -04:00

135 lines
5.5 KiB
C#

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<CardInstance> 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<CardInstance> 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<CardLogicBase>());
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<CardInstance> 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();
}
}
}