Files
Continentis/Assets/Scripts/MainGame/Commands/Cmd_DiscardCards.cs

101 lines
4.6 KiB
C#
Raw Normal View History

2025-10-03 00:02:43 -04:00
using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.Card;
using Continentis.MainGame.Character;
using DG.Tweening;
2025-10-23 00:49:44 -04:00
using SLSFramework.General;
2025-10-03 00:02:43 -04:00
using UniRx;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Continentis.MainGame.Commands
{
public class Cmd_DiscardCards : CommandBase
{
private readonly DeckSubmodule deck;
private readonly List<CardInstance> cardsToDiscard;
private readonly float interval;
private readonly float singleCardAnimationDuration = 0.5f; // 单张卡牌的动画时长
2025-10-31 10:02:30 -04:00
private readonly bool isInitiative;
2025-10-03 00:02:43 -04:00
2025-10-31 10:02:30 -04:00
public Cmd_DiscardCards(DeckSubmodule deck, List<CardInstance> cards, bool isInitiative, float interval)
2025-10-03 00:02:43 -04:00
{
this.deck = deck;
this.cardsToDiscard = cards;
2025-10-31 10:02:30 -04:00
this.isInitiative = isInitiative;
2025-10-03 00:02:43 -04:00
this.interval = interval;
}
2025-10-23 00:49:44 -04:00
protected override IObservable<Unit> OnExecute(CommandContext outerContext)
2025-10-03 00:02:43 -04:00
{
if (cardsToDiscard == null || cardsToDiscard.Count == 0)
{
return Observable.Return(Unit.Default);
}
// --- 情况1并行丢弃 (所有卡牌动画同时开始) ---
if (interval <= 0f)
{
// 为每张卡牌创建一个“懒加载”的丢弃动画流。
var allDiscardAnimations = cardsToDiscard.Select(card =>
Observable.Defer(() => DiscardCard(card))
);
// 使用 WhenAll 等待所有的并行任务都完成。
// 只有当最后一个动画结束时WhenAll 才会发出完成信号。
return Observable.WhenAll(allDiscardAnimations).AsUnitObservable();
}
// --- 情况2交错丢弃 (按固定间隔开始动画) ---
else
{
var cardStream = cardsToDiscard.ToObservable();
var timerStream = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(interval));
return timerStream
.Zip(cardStream, (_, card) => card)
// 核心:不再使用 .Do(..).Subscribe(),而是使用 Select 将每个 card 转换为
// 其对应的动画流。这样主流程就“知道”了每个动画的存在。
.Select(card => DiscardCard(card))
// 使用 Merge 将所有交错开始的动画流合并为一个流。
// Merge 会同时运行所有这些动画,并在最后一个动画也完成时,它才会完成。
.Merge()
// 使用 Last 来确保我们只在整个 Merge 流全部结束后,才发出最终的完成信号。
.Last()
.AsUnitObservable();
}
}
private IObservable<Unit> DiscardCard(CardInstance card)
{
2025-10-31 10:02:30 -04:00
if (isInitiative)
{
if (card.cardLogic.eventSubmodule.onInitiativeDiscard.GetChecks().Any()) // 如果主动弃牌后,有触发条件,则打断弃牌,直接触发效果
{
CommandQueueManager.Instance.AddCommand(new Cmd_Function(() =>
{
card.cardLogic.eventSubmodule.onInitiativeDiscard.GetEffects().ForEach(effect => effect.Invoke());
}));
return Observable.Return(Unit.Default);
}
}
2025-10-03 00:02:43 -04:00
2025-10-31 10:02:30 -04:00
deck.TransferCard(deck.Pile(card.cardLocation.pileName), deck.DiscardPile, card);
2025-10-23 00:49:44 -04:00
card.handCardView.TransferCardView(CombatUIManager.Instance.combatMainPage.discardPile);
2025-10-03 00:02:43 -04:00
RectTransform cardTransform = card.handCardView.cardTransform;
Vector3 deltaMove = Vector3.zero - card.handCardView.cardTransform.localPosition;
Vector3 randomLift = new Vector3(Random.Range(-200f, 200f), Random.Range(200f, 600f), 0);
cardTransform.DOBlendableLocalMoveBy(deltaMove, singleCardAnimationDuration).Play();
cardTransform.DOBlendableLocalMoveBy(randomLift, singleCardAnimationDuration * 0.5f).SetLoops(2, LoopType.Yoyo).Play();
cardTransform.DOLocalRotate(new Vector3(0, 0, 720f), singleCardAnimationDuration, RotateMode.FastBeyond360).Play();
cardTransform.DOScale(Vector3.zero, singleCardAnimationDuration).SetEase(Ease.Linear).Play();
return Observable.Timer(TimeSpan.FromSeconds(singleCardAnimationDuration)).AsUnitObservable();
}
}
}