2025-11-15 12:17:34 -05:00
|
|
|
|
using System;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using Continentis.MainGame.Character;
|
2025-11-13 10:42:05 -05:00
|
|
|
|
using Continentis.MainGame.Combat;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
using Continentis.MainGame.UI;
|
|
|
|
|
|
using Lean.Pool;
|
2025-11-15 12:17:34 -05:00
|
|
|
|
using NaughtyAttributes;
|
|
|
|
|
|
using SLSFramework.General;
|
|
|
|
|
|
using UniRx;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Continentis.MainGame.Card
|
|
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
public partial class CardInstance : IGameElement
|
2025-10-03 00:02:43 -04:00
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
public Guid elementID { get; set; }
|
|
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
[Header("References")]
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public DeckSubmodule deck;
|
2025-11-15 12:17:34 -05:00
|
|
|
|
public CardLocation cardLocation;
|
|
|
|
|
|
public CardData cardData;
|
|
|
|
|
|
public CompositeDisposable disposables = new CompositeDisposable();
|
2025-11-15 09:08:36 -05:00
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public ICardOwner owner;
|
|
|
|
|
|
public CharacterBase user;
|
2025-11-15 09:08:36 -05:00
|
|
|
|
public CombatTeam usingTeam;
|
|
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public CardLogicBase cardLogic;
|
2025-11-15 12:17:34 -05:00
|
|
|
|
public int upgradeLevel;
|
|
|
|
|
|
|
|
|
|
|
|
[Header("Submodules")]
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public AttributeSubmodule attributeSubmodule { get; private set; }
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public WeightSubmodule weightSubmodule { get; private set; }
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public CombatBuffSubmodule combatBuffSubmodule { get; private set; }
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public EventSubmodule eventSubmodule { get; private set; }
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public ContentSubmodule contentSubmodule { get; private set; }
|
|
|
|
|
|
[ShowNativeProperty]
|
|
|
|
|
|
public PlaySubmodule playSubmodule { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public CardInstance(CardData data, ICardOwner owner, string initialPileName, int index = -1)
|
2025-10-03 00:02:43 -04:00
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
(this as IGameElement).Initialize();
|
|
|
|
|
|
|
|
|
|
|
|
this.cardData = data;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
this.owner = owner;
|
|
|
|
|
|
this.user = owner as CharacterBase;
|
2025-11-15 12:17:34 -05:00
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
if (this.owner is CombatTeam team)
|
|
|
|
|
|
{
|
2025-11-15 09:08:36 -05:00
|
|
|
|
this.usingTeam = team;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
}
|
|
|
|
|
|
else if (this.owner is CharacterBase character)
|
|
|
|
|
|
{
|
2025-11-15 09:08:36 -05:00
|
|
|
|
this.usingTeam = character.team;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
this.deck = owner.deckSubmodule;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
this.cardLocation = new CardLocation(initialPileName, index);
|
|
|
|
|
|
|
|
|
|
|
|
if (index < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.deck.Pile(cardLocation.pileName).Add(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.deck.Pile(cardLocation.pileName).Insert(index, this);
|
|
|
|
|
|
}
|
2025-11-15 12:17:34 -05:00
|
|
|
|
|
|
|
|
|
|
this.attributeSubmodule = new AttributeSubmodule(this);
|
|
|
|
|
|
this.weightSubmodule = new WeightSubmodule(this);
|
|
|
|
|
|
this.eventSubmodule = new EventSubmodule(this);
|
|
|
|
|
|
this.combatBuffSubmodule = new CombatBuffSubmodule(this);
|
|
|
|
|
|
this.contentSubmodule = new ContentSubmodule(this);
|
|
|
|
|
|
this.playSubmodule = new PlaySubmodule(this);
|
|
|
|
|
|
|
|
|
|
|
|
this.cardLogic = CardLogicBase.GenerateCardLogic(data);
|
|
|
|
|
|
this.cardLogic.Initialize(this);
|
|
|
|
|
|
this.cardLogic.SetUpLogicComponents();
|
2025-10-23 00:49:44 -04:00
|
|
|
|
}
|
2025-10-24 09:11:22 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据CardLogic生成卡牌实例
|
|
|
|
|
|
/// </summary>
|
2025-11-15 12:17:34 -05:00
|
|
|
|
/// <param name="template">卡牌实体实例</param>
|
2025-10-24 09:11:22 -04:00
|
|
|
|
/// <param name="owner">卡牌持有者</param>
|
|
|
|
|
|
/// <param name="pileName">初始卡堆名称"</param>
|
|
|
|
|
|
/// <param name="index">插入位置,默认为0</param>
|
2025-11-15 12:17:34 -05:00
|
|
|
|
public static CardInstance GenerateCardInstance(CardInstance template, ICardOwner owner, string pileName, int index = -1)
|
2025-10-24 09:11:22 -04:00
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
CardInstance cardInstance = new CardInstance(template.cardData, owner, pileName, index);
|
|
|
|
|
|
//TODO: 复制template的属性到cardInstance
|
2025-10-24 09:11:22 -04:00
|
|
|
|
return cardInstance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据CardData生成卡牌实例
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="data">卡牌数据</param>
|
|
|
|
|
|
/// <param name="owner">卡牌持有者</param>
|
|
|
|
|
|
/// <param name="pileName">初始卡堆名称"</param>
|
|
|
|
|
|
/// <param name="index">插入位置,默认为0</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static CardInstance GenerateCardInstance(CardData data, ICardOwner owner, string pileName, int index = -1)
|
|
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
CardInstance card = new CardInstance(data, owner, pileName, index);
|
2025-11-13 10:42:05 -05:00
|
|
|
|
|
|
|
|
|
|
if (owner == CombatMainManager.Instance.characterController.playerTeam)
|
|
|
|
|
|
{
|
2025-11-15 12:17:34 -05:00
|
|
|
|
CombatUIManager.Instance.combatMainPage.teamSwitchButton
|
|
|
|
|
|
.UpdateTeamPileText(CombatMainManager.Instance.characterController.playerTeam);
|
2025-11-13 10:42:05 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 12:17:34 -05:00
|
|
|
|
//下面的部分后续放入CardLogic的初始化函数中
|
|
|
|
|
|
card.RefreshCardAttributes();
|
|
|
|
|
|
|
|
|
|
|
|
if (card.HasKeyword("Instant")) //如果是“瞬发”牌,添加抽牌后立刻打出的事件
|
|
|
|
|
|
{
|
|
|
|
|
|
card.eventSubmodule.onDraw.InsertByPriority("Instant", new PrioritizedAction(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
card.DetectTargetsValidity(out List<CharacterBase> valid, out _, out _);
|
|
|
|
|
|
card.Play(card.SetRandomTargets(valid), card.user);
|
|
|
|
|
|
}, 99));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return card;
|
2025-10-24 09:11:22 -04:00
|
|
|
|
}
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
public HandCardView GenerateHandCardView(string pileName, int index = -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
PileBase pile = CombatUIManager.Instance.combatMainPage.Pile(pileName);
|
|
|
|
|
|
return GenerateHandCardView(pile, index);
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成手牌
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="pile">手牌生成位置</param>
|
|
|
|
|
|
/// <param name="index">插入位置,-1为末尾</param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public HandCardView GenerateHandCardView(PileBase pile, int index = -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject handCardObjectPrefab = MainGameManager.Instance.basePrefabs.handCardObject;
|
|
|
|
|
|
HandCardView handCardView = LeanPool.Spawn(handCardObjectPrefab, pile.rectTransform).GetComponent<HandCardView>();
|
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
pile.InsertCard(handCardView, index);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
pile.AddCard(handCardView);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 12:17:34 -05:00
|
|
|
|
handCardView.card = this;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
this.handCardView = handCardView;
|
|
|
|
|
|
|
|
|
|
|
|
handCardView.transform.localScale = pile is HandPile ? Vector3.one : Vector3.zero;
|
|
|
|
|
|
|
|
|
|
|
|
handCardView.Setup(this);
|
|
|
|
|
|
handCardView.currentPile = pile;
|
|
|
|
|
|
handCardView.cardOrb.gameObject.SetActive(false);
|
|
|
|
|
|
|
|
|
|
|
|
return handCardView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void DestroyHandCardView()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handCardView != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
handCardView.currentPile.RemoveCard(handCardView);
|
|
|
|
|
|
LeanPool.Despawn(handCardView.gameObject);
|
|
|
|
|
|
handCardView = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public IntentionCardView GenerateIntentionCardView()
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject intentionCardObjectPrefab = MainGameManager.Instance.basePrefabs.intentionCardObject;
|
|
|
|
|
|
HUD_Intention intention = user.characterView.hudContainer.enablingHUDs["Intention"] as HUD_Intention;
|
|
|
|
|
|
IntentionCardView intentionCardView = LeanPool.Spawn(intentionCardObjectPrefab, intention.hudTransform).GetComponent<IntentionCardView>();
|
|
|
|
|
|
intention.AddCard(intentionCardView);
|
2025-11-15 12:17:34 -05:00
|
|
|
|
intentionCardView.card = this;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
this.intentionCardView = intentionCardView;
|
|
|
|
|
|
intentionCardView.transform.localScale = Vector3.one;
|
|
|
|
|
|
intentionCardView.Setup(this);
|
2025-11-30 21:22:39 -05:00
|
|
|
|
|
|
|
|
|
|
string iconMarkKey = cardData.intentionIconKeys[0];
|
|
|
|
|
|
Sprite iconSprite = MainGameManager.Instance.basePrefabs.intentionMarkIcons[iconMarkKey];
|
|
|
|
|
|
if (string.IsNullOrEmpty(cardData.intentionTextOverride))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cardData.intentionValueNames.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
string intentionValue = attributeSubmodule.GetRoundCurrentAttribute(cardData.intentionValueNames[0]).ToString();
|
|
|
|
|
|
intentionCardView.intentionMark.SetMark(iconSprite, intentionValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
intentionCardView.intentionMark.SetMark(iconSprite);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
intentionCardView.intentionMark.SetMark(iconSprite, cardData.intentionTextOverride);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
return intentionCardView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void DestroyIntentionCardView()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (intentionCardView != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
HUD_Intention intention = user.characterView.hudContainer.enablingHUDs["Intention"] as HUD_Intention;
|
|
|
|
|
|
intention.RemoveCard(intentionCardView);
|
|
|
|
|
|
intentionCardView = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-15 12:17:34 -05:00
|
|
|
|
|
|
|
|
|
|
public partial class CardInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
public HandCardView handCardView;
|
|
|
|
|
|
public IntentionCardView intentionCardView;
|
|
|
|
|
|
}
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
public class CardLocation
|
|
|
|
|
|
{
|
|
|
|
|
|
public string pileName;
|
|
|
|
|
|
public int index;
|
|
|
|
|
|
|
|
|
|
|
|
public CardLocation(string pileName, int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.pileName = pileName;
|
|
|
|
|
|
this.index = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|