2025-10-03 00:02:43 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Continentis.MainGame.Character;
|
2025-10-24 09:11:22 -04:00
|
|
|
|
using Continentis.MainGame.Equipment;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
using SLSFramework.General;
|
2025-10-24 09:11:22 -04:00
|
|
|
|
using SLSFramework.UModAssistance;
|
2025-11-08 09:50:55 -05:00
|
|
|
|
using UniRx;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Continentis.MainGame.Card
|
|
|
|
|
|
{
|
|
|
|
|
|
public abstract partial class CardLogicBase
|
|
|
|
|
|
{
|
2025-10-24 09:11:22 -04:00
|
|
|
|
[Header("Reference")]
|
|
|
|
|
|
public CardData cardData;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public CardInstance cardInstance;
|
2025-11-08 09:50:55 -05:00
|
|
|
|
public CompositeDisposable disposables = new CompositeDisposable();
|
2025-10-03 00:02:43 -04:00
|
|
|
|
|
|
|
|
|
|
public ICardOwner owner => cardInstance.owner;
|
|
|
|
|
|
public CharacterBase user => cardInstance.user;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public CombatTeam team => cardInstance.team;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public HandCardView handCardView => cardInstance.handCardView;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public IntentionCardView intentionCardView => cardInstance.intentionCardView;
|
|
|
|
|
|
|
|
|
|
|
|
[Header("Card Base Info")]
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public Guid cardID;
|
|
|
|
|
|
public int upgradeLevel;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
[Header("Submodules")]
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public AttributeSubmodule attributeSubmodule { get; private set; }
|
|
|
|
|
|
public WeightSubmodule weightSubmodule { get; private set; }
|
|
|
|
|
|
public CombatBuffSubmodule combatBuffSubmodule { get; private set; }
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public EventSubmodule eventSubmodule { get; private set; }
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public ContentSubmodule contentSubmodule { get; private set; }
|
|
|
|
|
|
public PlaySubmodule playSubmodule { get; private set; }
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public HashSet<CardLogicComponentBase> logicComponents { get; private set; }
|
|
|
|
|
|
|
2025-10-24 09:11:22 -04:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成卡牌逻辑实例
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static CardLogicBase GenerateCardLogic(CardData data)
|
|
|
|
|
|
{
|
|
|
|
|
|
string typeID = ModManager.GetTypeID(data.modName, "Cards", data.className);
|
|
|
|
|
|
Type logicType = ModManager.GetType(typeID);
|
|
|
|
|
|
|
|
|
|
|
|
if(logicType == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"Card class '{typeID}' not found in assemblies.");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Activator.CreateInstance(logicType) is CardLogicBase cardLogic)
|
|
|
|
|
|
{
|
|
|
|
|
|
cardLogic.cardData = data;
|
|
|
|
|
|
cardLogic.Setup();
|
|
|
|
|
|
return cardLogic;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Debug.LogError($"Card class '{typeID}' not found or could not be instantiated.");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
public void Setup()
|
|
|
|
|
|
{
|
|
|
|
|
|
this.cardID = Guid.NewGuid();
|
2025-10-27 07:04:34 -04:00
|
|
|
|
|
2025-10-23 00:49:44 -04: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.logicComponents = new HashSet<CardLogicComponentBase>();
|
|
|
|
|
|
|
|
|
|
|
|
SetUpLogicComponents();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual void SetUpLogicComponents()
|
|
|
|
|
|
{
|
2025-10-03 00:02:43 -04:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public virtual void Initialize()
|
2025-10-03 00:02:43 -04:00
|
|
|
|
{
|
|
|
|
|
|
RefreshCardAttributes();
|
2025-11-08 09:50:55 -05:00
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
if (HasKeyword("Instant")) //如果是“瞬发”牌,添加抽牌后立刻打出的事件
|
|
|
|
|
|
{
|
2025-10-31 10:02:30 -04:00
|
|
|
|
eventSubmodule.onDraw.InsertByPriority("Instant", new PrioritizedAction(() =>
|
2025-10-23 00:49:44 -04:00
|
|
|
|
{
|
|
|
|
|
|
DetectTargetsValidity(out List<CharacterBase> valid, out _, out _);
|
|
|
|
|
|
Play(SetRandomTargets(valid), user);
|
|
|
|
|
|
}, 99));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public T AddLogicComponent<T>() where T : CardLogicComponentBase, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (logicComponents.Any(component => component is T))
|
|
|
|
|
|
{
|
2025-10-24 09:11:22 -04:00
|
|
|
|
Debug.LogWarning($"Card {cardData.className} already has component of type {typeof(T)}, cannot add duplicate.");
|
2025-10-23 00:49:44 -04:00
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
T component = new T();
|
|
|
|
|
|
component.Initialize(this);
|
|
|
|
|
|
logicComponents.Add(component);
|
|
|
|
|
|
return component;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public T LogicComponent<T>() where T : CardLogicComponentBase
|
|
|
|
|
|
{
|
|
|
|
|
|
return logicComponents.OfType<T>().FirstOrDefault();
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void UpgradeCard()
|
|
|
|
|
|
{
|
2025-10-23 00:49:44 -04:00
|
|
|
|
if (owner is not CombatTeam)
|
2025-10-03 00:02:43 -04:00
|
|
|
|
{
|
|
|
|
|
|
KeyValuePair<string, List<CardInstance>> currentPile = cardInstance.deck.GetCardLocation(cardInstance, out int index);
|
|
|
|
|
|
if (!cardData.upgradeNode.isTerminalNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
cardInstance.DestroyHandCardView();
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
CardData newData = cardData.upgradeNode.upgradeCards[0]; //后续可改为选择升级方向
|
2025-10-24 09:11:22 -04:00
|
|
|
|
CardLogicBase newLogic = CardLogicBase.GenerateCardLogic(newData);
|
2025-10-03 00:02:43 -04:00
|
|
|
|
cardInstance.cardLogic = newLogic;
|
|
|
|
|
|
newLogic.cardInstance = cardInstance;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
cardInstance.cardLogic.Initialize();
|
|
|
|
|
|
if (user is PlayerHero)
|
|
|
|
|
|
cardInstance.GenerateHandCardView(CombatUIManager.Instance.combatMainPage.Pile(currentPile.Key), index);
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-27 07:04:34 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取衍生卡牌数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CardData GetDerivativeCardData(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ModManager.GetData<CardData>(cardData.derivativeCardDataRefs[index]);
|
|
|
|
|
|
}
|
2025-10-30 12:07:59 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取衍生卡牌数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CardData GetDerivativeCardData(string dataName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cardData.derivativeCardDataRefs.Contains(dataName))
|
|
|
|
|
|
{
|
|
|
|
|
|
return ModManager.GetData<CardData>(dataName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Debug.LogError($"Card {cardData.className} does not contain derivative card data '{dataName}'.");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 卡牌逻辑组件基类接口
|
|
|
|
|
|
/// 注意,所有的子接口需要实现的函数:
|
|
|
|
|
|
/// ComponentTargetingEffect:此牌瞄准目标时调用
|
|
|
|
|
|
/// ComponentUntargetingEffect:此牌取消瞄准目标时调用
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public abstract class CardLogicComponentBase
|
2025-10-03 00:02:43 -04:00
|
|
|
|
{
|
2025-10-23 00:49:44 -04:00
|
|
|
|
protected CardLogicBase card;
|
|
|
|
|
|
protected CharacterBase user => card.user;
|
|
|
|
|
|
protected CombatTeam team => card.team;
|
2025-10-03 00:02:43 -04:00
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
public virtual void Initialize(CardLogicBase card)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.card = card;
|
|
|
|
|
|
card.eventSubmodule.onTargeting += TargetingEffect;
|
|
|
|
|
|
card.eventSubmodule.onUntargeting += UntargetingEffect;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual void TargetingEffect(CharacterBase target)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual void UntargetingEffect()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-10-03 00:02:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|