Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/AIVirtualCard.cs
gamer147 0d9d8acae0 feat(battle-engine): M1 auto-copy closure (782 battle-logic files)
Compile-driven bulk-copy loop (tools/engine-port/m1_copy_loop.py) pulled the precise reference closure of the battle-core roots, stopping at the classify god-object/View-VFX-UI boundary. 782 files; no re-explosion (M0 had estimated ~order 1000). Residual frontier = 52 shim-classified + 80 external (Unity/BCL) types to author next.
2026-06-05 16:57:20 -04:00

2654 lines
72 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Wizard;
public class AIVirtualCard
{
public class AIVirtualBanishInfo
{
public int Turn { get; private set; }
public bool IsCardOwnerTurn { get; private set; }
public BattleCardBase.BanishInfo.BanishPlace Place { get; private set; }
public AIVirtualBanishInfo(int turn, bool isCardOwnerTurn, BattleCardBase.BanishInfo.BanishPlace place)
{
Turn = turn;
IsCardOwnerTurn = isCardOwnerTurn;
Place = place;
}
}
protected AIVirtualField _field;
public bool IsFirstTurn;
public int BaseCost;
public int Cost;
public int RealCost;
public int PlayedCost = -1;
public List<int> EnhanceCostList;
public List<AIAccelerateInformation> AccelerateCostList;
public List<AICrystalizeInformation> CrystalizeCostList;
public List<AIChoiceTransformCostInformation> ChoiceTransformCostList;
public int LastHealAmount;
public int AttackableCount;
public bool IsSummonDrunkenness;
private bool IsDebuffCantEvolve;
public bool IsCantAttackAll;
public bool IsSkillCantAttackClass;
public bool IsSkillCantAttackUnit;
public bool IsSkillCantAtkUnitNotHasGuard;
private List<AICannotAttackInformation> _cannotAttackInfoList;
private bool _isCantUnderAttack;
public bool IsSkillCantUnderAnyAttack;
public bool IsUseEvo;
public bool IsGuard;
public bool IsIgnoreGuard;
public bool IsSkillLost;
public bool IsSelfTurn;
public bool IsNotAttackYet;
public bool IsMinimumBreakBonus;
public bool IsRobbedLastword;
public bool IsNotConsumeEp;
public bool IsSkillSummoned;
public bool HasAnySkill;
public bool HasSkillNecromance;
public bool IsPlayer;
public bool IsForceTargeting;
public bool IsUnbanishable;
public bool IsMetamorphosed;
private int UntouchableCount;
public AIBarrierInfoCollection BarrierInfoCollection;
public bool IsIndestructible;
public bool IsIndependent;
private int _destroyByBanishCount;
private int _bounceByBanishCount;
private int _banishByDestroyCount;
public int AttackByLifeCount;
public bool IsSneak;
private List<AIPlayTag> _giveSneakTagList;
public bool IsKiller;
public bool IsDrain;
public bool IsRush;
public bool IsQuick;
public bool IsDestroyWhenAttack;
public bool HasSpellboost;
public int SpellboostCount;
public int RealSpellboostCount;
private int _originalWhiteRitualCount;
public bool IsStackWhiteRitual;
public int TempAtkBuff;
public int TempLifeBuff;
public bool HasAfterAttackHeal;
public bool IsRecoveredAttackableCount;
public bool IsAmulet;
public bool IsCountdownAmulet;
public int ChantCount;
public bool IsSpell;
public bool IsUnit;
public bool IsLeader;
protected bool _isCompletedRemove;
public bool IsDead;
private AIHandPlayEstimator _handPlayEstimator;
protected List<CardBasePrm.TribeType> _tribeList;
public readonly AIVirtualAttackInfo AttackLeaderSituation;
public int GetOnCardId;
public AIVirtualCard GetOffCard;
public AIVirtualCard BeforeTransformedCardForSimulation;
public List<string> PermanentAITribeList;
public int ReferringSelfCount;
protected readonly ulong[] PRIME_NUMBERS_FOR_CLAN = new ulong[12]
{
282143uL, 282157uL, 282167uL, 282221uL, 282229uL, 282239uL, 282241uL, 282253uL, 282281uL, 282287uL,
282299uL, 282307uL
};
protected readonly ulong[] PRIME_NUMBERS_FOR_TRIBE = new ulong[13]
{
47521uL, 47527uL, 47533uL, 47543uL, 47563uL, 47569uL, 47581uL, 47591uL, 47599uL, 47609uL,
47623uL, 47629uL, 47639uL
};
public AIVirtualField SelfField => _field;
public AICardData AIData { get; private set; }
public BattlePlayerBase SelfBattlePlayer { get; protected set; }
public int BaseId
{
get
{
return CardParameter.BaseId;
}
protected set
{
CardParameter.BaseId = value;
}
}
public int CardIndex { get; protected set; }
public string CardName => CardParameter.CardName;
public int EvolutionAttack => CardParameter.Attack + CardParameter.EvoAttackPlus;
public int EvolutionLife => CardParameter.Life + CardParameter.EvoLifePlus;
public CardBasePrm.ClanType Clan { get; protected set; }
public bool IsEvolution { get; private set; }
public bool IsPreviousTurnAttacked { get; private set; }
public bool IsOnField { get; protected set; }
public bool IsInHand { get; protected set; }
public BattleCardBase BaseCard { get; protected set; }
public SkillCollectionBase BattleSkills { get; protected set; }
public List<string> BattleSkillHashList { get; protected set; }
public AIVirtualCardParameter BaseParameter { get; private set; }
public AIVirtualCardParameter OtherEvolveParameter { get; private set; }
public AIVirtualCardParameter CardParameter
{
get
{
if (OtherEvolveParameter != null)
{
return OtherEvolveParameter;
}
return BaseParameter;
}
}
public int Life
{
get
{
return CardParameter.Life;
}
set
{
CardParameter.Life = value;
}
}
public int MaxLife
{
get
{
return CardParameter.MaxLife;
}
set
{
CardParameter.MaxLife = value;
}
}
public int DefLife
{
get
{
return CardParameter.DefLife;
}
set
{
CardParameter.DefLife = value;
}
}
public int LastLife
{
get
{
return CardParameter.LastLife;
}
set
{
CardParameter.LastLife = value;
}
}
public int Attack
{
get
{
return CardParameter.Attack;
}
set
{
CardParameter.Attack = value;
}
}
public int MaxAttackableCount
{
get
{
return CardParameter.MaxAttackableCount;
}
set
{
CardParameter.MaxAttackableCount = value;
}
}
public int DefaultLife
{
get
{
return CardParameter.DefaultLife;
}
set
{
CardParameter.DefaultLife = value;
}
}
public int DefaultAttack
{
get
{
return CardParameter.DefaultAttack;
}
set
{
CardParameter.DefaultAttack = value;
}
}
public int DefaultMaxAttackableCount
{
get
{
return CardParameter.DefaultMaxAttackableCount;
}
set
{
CardParameter.DefaultMaxAttackableCount = value;
}
}
public bool IsAttacked => AttackableCount < MaxAttackableCount;
public bool IsUntouchable => UntouchableCount > 0;
public int DestroyedTurn { get; protected set; }
public int EvoAttackPlus
{
get
{
return CardParameter.EvoAttackPlus;
}
private set
{
CardParameter.EvoAttackPlus = value;
}
}
public int EvoLifePlus
{
get
{
return CardParameter.EvoLifePlus;
}
private set
{
CardParameter.EvoLifePlus = value;
}
}
public int BuffCount { get; private set; }
public AIBuffRecorderCollection BuffRecorderCollection { get; private set; }
public int SelfTurnDamagedCount { get; private set; }
public int OpponentTurnDamagedCount { get; private set; }
public int HealCount { get; private set; }
public bool IsAllShield
{
get
{
if (BarrierInfoCollection == null)
{
return false;
}
return BarrierInfoCollection.HasShieldAll;
}
}
public bool IsDestroyByBanish => _destroyByBanishCount > 0;
public bool IsBounceByBanish => _bounceByBanishCount > 0;
public bool IsBanishByDestroy => _banishByDestroyCount > 0;
public bool IsAttackByLife => AttackByLifeCount > 0;
public bool IsLastword { get; private set; }
public float Value { get; private set; }
public float DefaultValue { get; private set; }
public int WhiteRitualCount { get; protected set; }
public bool IsAlly { get; protected set; }
public bool DeadTurn { get; set; }
public AITagCollectionContainer TagCollectionContainer { get; protected set; }
public List<int> ChildrenIndexList { get; private set; }
public bool HasUnionBurst { get; private set; }
public int UnionBurstCount { get; private set; }
public bool HasSkyboundArt { get; private set; }
public int SkyboundArtCount { get; private set; }
public bool HasSuperSkyboundArt { get; private set; }
public int SuperSkyboundArtCount { get; private set; }
public bool IsFusionCard => TagCollectionContainer.HasTag(AIPlayTagType.Fusion);
public bool IsFusionable { get; private set; }
public AIVirtualFusionIngredientsInfo FusionIngredients { get; protected set; }
public BeforeTransformVirtualCard BeforeTransformCard { get; private set; }
public bool IsGetOn => GetOnCardId > 0;
public bool CantBeFocusedSkill
{
get
{
if (!IsSneak)
{
return IsUntouchable;
}
return true;
}
}
public AIVirtualBanishInfo BanishedInfo { get; private set; }
public bool IsTribe(CardBasePrm.TribeType tribe)
{
if (_tribeList == null)
{
return false;
}
for (int i = 0; i < _tribeList.Count; i++)
{
if (_tribeList[i] == tribe)
{
return true;
}
}
return false;
}
public bool HasAnyTribe()
{
if (_tribeList == null)
{
return false;
}
for (int i = 0; i < _tribeList.Count; i++)
{
if (_tribeList[i] != CardBasePrm.TribeType.ALL)
{
return true;
}
}
return false;
}
public AIVirtualCard()
{
}
public AIVirtualCard(BattleCardBase card, AIVirtualField field)
{
_field = field;
IsAlly = _field.AI.IsAllyCard(card);
TagCollectionContainer = new AITagCollectionContainer();
BarrierInfoCollection = new AIBarrierInfoCollection();
InitializeFromBattleCardBase(card);
InitializeAIParameter();
if (IsAlly && !IsLeader)
{
AttackLeaderSituation = new AIVirtualAttackInfo(this, _field.EnemyClass);
}
else
{
AttackLeaderSituation = null;
}
}
public AIVirtualCard(AIVirtualCard virtualCard, AIVirtualField field)
{
_field = field;
SelfBattlePlayer = virtualCard.SelfBattlePlayer;
AIData = virtualCard.AIData;
IsAlly = virtualCard.IsAlly;
BaseCost = virtualCard.BaseCost;
Cost = virtualCard.Cost;
RealCost = virtualCard.RealCost;
PlayedCost = virtualCard.PlayedCost;
IsDead = virtualCard.IsDead;
_isCompletedRemove = virtualCard._isCompletedRemove;
ChildrenIndexList = virtualCard.ChildrenIndexList;
IsPlayer = virtualCard.IsPlayer;
BaseCard = virtualCard.BaseCard;
CardIndex = virtualCard.CardIndex;
BattleSkills = virtualCard.BattleSkills;
BattleSkillHashList = virtualCard.BattleSkillHashList;
BaseParameter = virtualCard.BaseParameter.Clone();
OtherEvolveParameter = ((virtualCard.OtherEvolveParameter != null) ? virtualCard.OtherEvolveParameter.Clone() : null);
IsSpell = virtualCard.IsSpell;
IsUnit = virtualCard.IsUnit;
IsLeader = virtualCard.IsLeader;
Clan = virtualCard.Clan;
AttackableCount = virtualCard.AttackableCount;
IsCantAttackAll = virtualCard.IsCantAttackAll;
IsFirstTurn = virtualCard.IsFirstTurn;
IsSummonDrunkenness = virtualCard.IsSummonDrunkenness;
IsSkillCantAttackClass = virtualCard.IsSkillCantAttackClass;
IsSkillCantAttackUnit = virtualCard.IsSkillCantAttackUnit;
_cannotAttackInfoList = AIParamQuery.CloneList(virtualCard._cannotAttackInfoList);
_isCantUnderAttack = virtualCard._isCantUnderAttack;
IsSkillCantAtkUnitNotHasGuard = virtualCard.IsSkillCantAtkUnitNotHasGuard;
IsGuard = virtualCard.IsGuard;
IsSkillCantUnderAnyAttack = virtualCard.IsSkillCantUnderAnyAttack;
IsIgnoreGuard = virtualCard.IsIgnoreGuard;
IsSkillLost = virtualCard.IsSkillLost;
IsSelfTurn = virtualCard.IsSelfTurn;
IsNotAttackYet = virtualCard.IsNotAttackYet;
IsMinimumBreakBonus = virtualCard.IsMinimumBreakBonus;
IsRobbedLastword = virtualCard.IsRobbedLastword;
IsNotConsumeEp = virtualCard.IsNotConsumeEp;
IsSkillSummoned = virtualCard.IsSkillSummoned;
HasAnySkill = virtualCard.HasAnySkill;
IsOnField = virtualCard.IsOnField;
IsInHand = virtualCard.IsInHand;
IsUseEvo = virtualCard.IsUseEvo;
IsEvolution = virtualCard.IsEvolution;
IsPreviousTurnAttacked = virtualCard.IsPreviousTurnAttacked;
IsIndestructible = virtualCard.IsIndestructible;
IsIndependent = virtualCard.IsIndependent;
IsMetamorphosed = virtualCard.IsMetamorphosed;
IsLastword = virtualCard.IsLastword;
IsSneak = virtualCard.IsSneak;
_giveSneakTagList = AIParamQuery.CloneList(virtualCard._giveSneakTagList);
IsKiller = virtualCard.IsKiller;
IsDrain = virtualCard.IsDrain;
IsRush = virtualCard.IsRush;
IsQuick = virtualCard.IsQuick;
IsDestroyWhenAttack = virtualCard.IsDestroyWhenAttack;
IsRecoveredAttackableCount = virtualCard.IsRecoveredAttackableCount;
IsForceTargeting = virtualCard.IsForceTargeting;
IsUnbanishable = virtualCard.IsUnbanishable;
UntouchableCount = virtualCard.UntouchableCount;
IsDebuffCantEvolve = virtualCard.IsDebuffCantEvolve;
_destroyByBanishCount = virtualCard._destroyByBanishCount;
_bounceByBanishCount = virtualCard._bounceByBanishCount;
_banishByDestroyCount = virtualCard._banishByDestroyCount;
HasSpellboost = virtualCard.HasSpellboost;
SpellboostCount = virtualCard.SpellboostCount;
RealSpellboostCount = virtualCard.RealSpellboostCount;
WhiteRitualCount = virtualCard.WhiteRitualCount;
_originalWhiteRitualCount = virtualCard._originalWhiteRitualCount;
IsStackWhiteRitual = virtualCard.IsStackWhiteRitual;
AttackByLifeCount = virtualCard.AttackByLifeCount;
TempAtkBuff = virtualCard.TempAtkBuff;
TempLifeBuff = virtualCard.TempLifeBuff;
BuffCount = virtualCard.BuffCount;
if (virtualCard.BuffRecorderCollection != null)
{
BuffRecorderCollection = virtualCard.BuffRecorderCollection.Clone();
}
SelfTurnDamagedCount = virtualCard.SelfTurnDamagedCount;
OpponentTurnDamagedCount = virtualCard.OpponentTurnDamagedCount;
HealCount = virtualCard.HealCount;
HasAfterAttackHeal = virtualCard.HasAfterAttackHeal;
DestroyedTurn = virtualCard.DestroyedTurn;
ReferringSelfCount = virtualCard.ReferringSelfCount;
TagCollectionContainer = new AITagCollectionContainer(virtualCard.TagCollectionContainer, this);
BarrierInfoCollection = virtualCard.BarrierInfoCollection.Clone();
IsAmulet = virtualCard.IsAmulet;
IsCountdownAmulet = virtualCard.IsCountdownAmulet;
ChantCount = virtualCard.ChantCount;
Value = virtualCard.Value;
DefaultValue = virtualCard.DefaultValue;
if (virtualCard._tribeList != null)
{
_tribeList = new List<CardBasePrm.TribeType>(virtualCard._tribeList);
}
IsFusionable = virtualCard.IsFusionable;
if (virtualCard.FusionIngredients != null)
{
FusionIngredients = new AIVirtualFusionIngredientsInfo(virtualCard.FusionIngredients);
}
HasUnionBurst = virtualCard.HasUnionBurst;
UnionBurstCount = virtualCard.UnionBurstCount;
HasSkyboundArt = virtualCard.HasSkyboundArt;
SkyboundArtCount = virtualCard.SkyboundArtCount;
HasSuperSkyboundArt = virtualCard.HasSuperSkyboundArt;
SuperSkyboundArtCount = virtualCard.SuperSkyboundArtCount;
GetOnCardId = virtualCard.GetOnCardId;
GetOffCard = virtualCard.GetOffCard;
BeforeTransformCard = null;
if (virtualCard.BeforeTransformCard != null)
{
BeforeTransformCard = new BeforeTransformVirtualCard(virtualCard.BeforeTransformCard, _field);
}
if (IsAlly && !IsLeader)
{
AttackLeaderSituation = new AIVirtualAttackInfo(this, _field.EnemyClass);
}
else
{
AttackLeaderSituation = null;
}
BanishedInfo = virtualCard.BanishedInfo;
BeforeTransformedCardForSimulation = virtualCard.BeforeTransformedCardForSimulation;
PermanentAITribeList = virtualCard.PermanentAITribeList;
}
public AIVirtualCard(AIVirtualField field, AIVirtualCardParameter baseParameter, AIVirtualCard evalInstantAttackOwner, bool isEvalRush)
{
_field = field;
BaseParameter = baseParameter;
OtherEvolveParameter = null;
IsAlly = evalInstantAttackOwner.IsAlly;
IsPlayer = evalInstantAttackOwner.IsPlayer;
SelfBattlePlayer = evalInstantAttackOwner.SelfBattlePlayer;
AIData = evalInstantAttackOwner.AIData;
BaseCost = 0;
Cost = 0;
RealCost = 0;
PlayedCost = 0;
ChildrenIndexList = null;
BaseCard = evalInstantAttackOwner.BaseCard;
CardIndex = evalInstantAttackOwner.CardIndex;
BattleSkills = evalInstantAttackOwner.BattleSkills;
BattleSkillHashList = evalInstantAttackOwner.BattleSkillHashList;
IsUnit = true;
Clan = evalInstantAttackOwner.Clan;
AttackableCount = BaseParameter.MaxAttackableCount;
IsFirstTurn = true;
IsSummonDrunkenness = false;
IsSelfTurn = evalInstantAttackOwner.IsSelfTurn;
IsNotAttackYet = true;
IsMinimumBreakBonus = evalInstantAttackOwner.IsMinimumBreakBonus;
HasAnySkill = evalInstantAttackOwner.HasAnySkill;
IsOnField = true;
IsRush = isEvalRush;
IsQuick = !isEvalRush;
_destroyByBanishCount = 0;
_bounceByBanishCount = 0;
_banishByDestroyCount = 0;
SpellboostCount = 0;
RealSpellboostCount = 0;
WhiteRitualCount = 0;
_originalWhiteRitualCount = 0;
AttackByLifeCount = 0;
TempAtkBuff = 0;
TempLifeBuff = 0;
BuffCount = 0;
SelfTurnDamagedCount = 0;
OpponentTurnDamagedCount = 0;
HealCount = 0;
DestroyedTurn = evalInstantAttackOwner.DestroyedTurn;
ReferringSelfCount = 0;
ChantCount = 0;
UnionBurstCount = 0;
SkyboundArtCount = 0;
SuperSkyboundArtCount = 0;
TagCollectionContainer = new AITagCollectionContainer(evalInstantAttackOwner.TagCollectionContainer, this);
BarrierInfoCollection = new AIBarrierInfoCollection();
BuffRecorderCollection = null;
if (evalInstantAttackOwner._tribeList != null)
{
_tribeList = new List<CardBasePrm.TribeType>(evalInstantAttackOwner._tribeList);
}
if (IsAlly && !IsLeader)
{
AttackLeaderSituation = new AIVirtualAttackInfo(this, _field.EnemyClass);
}
else
{
AttackLeaderSituation = null;
}
}
protected virtual void InitializeFromBattleCardBase(BattleCardBase origin)
{
InitializeFromBattleCardBaseBasic(origin);
SelfBattlePlayer = origin.SelfBattlePlayer;
Value = 0f;
DefaultValue = 0f;
CardIndex = origin.Index;
IsDead = origin.IsDead;
IsPlayer = origin.IsPlayer;
BattleSkills = origin.Skills;
BattleSkillHashList = CardSkillHashUtility.GetSingleSkillHashStringList(BattleSkills);
IsSkillSummoned = origin.SelfBattlePlayer.SkillSummonedCards != null && origin.SelfBattlePlayer.SkillSummonedCards.Any((BattleCardBase c) => c.Index == origin.Index);
ISkillApplyInformation skillApplyInformation = origin.SkillApplyInformation;
Cost = origin.Cost;
RealCost = origin.Cost;
PlayedCost = origin.PlayedCost;
if (origin.Tribe != null && origin.Tribe.Count > 0)
{
for (int num = 0; num < origin.Tribe.Count; num++)
{
AppendTribe(origin.Tribe[num]);
}
}
IsOnField = origin.IsInplay;
IsInHand = origin.IsInHand;
IsSelfTurn = origin.IsSelfTurn;
IsFirstTurn = origin.IsFirstTurn;
IsSummonDrunkenness = origin.IsSummonDrunkenness;
IsCantAttackAll = origin.IsCantAttack;
IsSkillCantAttackClass = skillApplyInformation.IsSkillCantAtkClass;
IsSkillCantAttackUnit = skillApplyInformation.IsSkillCantAtkUnit;
IsSkillCantAtkUnitNotHasGuard = skillApplyInformation.IsSkillCantAtkUnitNotHasGuard;
IsSkillCantUnderAnyAttack = skillApplyInformation.NotBeAttackedInfoList.Count > 0;
_isCantUnderAttack = skillApplyInformation.IsSneak || IsSkillCantUnderAnyAttack;
IsIgnoreGuard = skillApplyInformation.IsIgnoreGuard;
IsNotConsumeEp = origin.SelfBattlePlayer.CheckNotConsumeEpCard(origin);
IsEvolution = IsUnit && origin.IsEvolution;
IsPreviousTurnAttacked = IsUnit && origin.IsPreviousTurnAttacked;
HasAnySkill = origin.HasAnySkill;
HasSkillNecromance = origin.HasSkillNecromance;
IsSkillLost = origin.IsSkillLost;
IsLastword = origin.Skills._skillTimingInfo.IsWhenDestroy;
IsSneak = IsUnit && skillApplyInformation.IsSneak;
IsKiller = IsUnit && skillApplyInformation.IsKiller;
IsDrain = IsUnit && skillApplyInformation.IsDrain;
IsRush = IsUnit && skillApplyInformation.IsRush;
IsQuick = skillApplyInformation.IsQuick;
IsGuard = IsUnit && skillApplyInformation.IsGuard;
IsIndestructible = skillApplyInformation.IndestructibleCount > 0;
IsIndependent = skillApplyInformation.IndependentCount > 0;
DestroyedTurn = origin.DestroyedTurn;
UntouchableCount = skillApplyInformation.UntouchableCount;
IsForceTargeting = skillApplyInformation.IsForceSkillTarget;
IsUnbanishable = false;
HasSpellboost = origin.HasSpellCharge;
SpellboostCount = origin.SpellChargeCount;
RealSpellboostCount = origin.SpellChargeCount;
WhiteRitualCount = (IsAmulet ? skillApplyInformation.WhiteRitualCount : 0);
_originalWhiteRitualCount = WhiteRitualCount;
IsStackWhiteRitual = origin.HasSkillStackWhiteRitual;
IsDebuffCantEvolve = skillApplyInformation.CantEvolutionList != null && skillApplyInformation.CantEvolutionList.Any((int f) => (f & Skill_cant_evolution.BIT_FLAG_EPUSE) != 0);
_banishByDestroyCount = skillApplyInformation.BanishByDestroyCount;
_destroyByBanishCount = skillApplyInformation.DestroyByBanishCount;
_bounceByBanishCount = skillApplyInformation.ReturnByBanishCount;
if (IsCountdownAmulet)
{
ChantCount = ((ChantFieldBattleCard)origin).ChantCount;
}
AttackableCount = (IsUnit ? origin.AttackableCount : 0);
BuffCount = (IsUnit ? skillApplyInformation.BuffCount : 0);
BuffRecorderCollection = (IsUnit ? new AIBuffRecorderCollection(skillApplyInformation.TurnBuffCountList) : null);
SelfTurnDamagedCount = ((!IsAmulet) ? origin.DamagedCounter.SelfTurnDamage : 0);
OpponentTurnDamagedCount = ((!IsAmulet) ? origin.DamagedCounter.OpponentTurnDamage : 0);
HealCount = ((!IsAmulet && skillApplyInformation.HealList != null) ? skillApplyInformation.HealList.Count : 0);
HasUnionBurst = origin.HasUnionBurst;
if (HasUnionBurst)
{
UnionBurstCount = skillApplyInformation.UnionBurstCount;
}
HasSkyboundArt = origin.HasSkyboundArt;
if (HasSkyboundArt)
{
SkyboundArtCount = skillApplyInformation.SkyboundArtCount;
}
HasSuperSkyboundArt = origin.HasSuperSkyboundArt;
if (HasSuperSkyboundArt)
{
SuperSkyboundArtCount = skillApplyInformation.SuperSkyboundArtCount;
}
BeforeTransformCard = null;
BattleCardBase.TransformInformation transformInfo = origin.TransformInfo;
if (transformInfo.Type != BattleCardBase.TransformType.Metamorphose && transformInfo.OriginalCard != null)
{
BeforeTransformCard = new BeforeTransformVirtualCard(transformInfo.OriginalCard, _field);
}
if (skillApplyInformation.GetOnCards != null && skillApplyInformation.GetOnCards.Count > 0)
{
GetOnCardId = skillApplyInformation.GetOnCards[0].BaseParameter.BaseCardId;
}
if (origin.GetOffCards != null && origin.GetOffCards.Count > 0)
{
GetOffCard = new AIVirtualCard(origin.GetOffCards[0], _field);
}
IsFusionable = origin.IsFusionable;
FusionIngredients = new AIVirtualFusionIngredientsInfo();
if (skillApplyInformation.FusionIngredients != null && skillApplyInformation.FusionIngredients.Count > 0)
{
FusionIngredients.CopyFusionIngredientsFromBattleCard(skillApplyInformation.FusionIngredients, _field);
}
ConvertBaseBanishInfo(origin.BanishedInfo);
BeforeTransformedCardForSimulation = null;
}
protected void InitializeFromBattleCardBaseBasic(BattleCardBase origin)
{
BaseCard = origin;
BaseCost = origin.BaseCost;
Clan = origin.Clan;
IsUnit = origin.IsUnit;
IsSpell = origin.IsSpell;
IsAmulet = origin.IsField;
IsCountdownAmulet = origin.IsChantField;
IsLeader = origin.IsClass;
IsRecoveredAttackableCount = false;
BaseParameter = new AIVirtualCardParameter(origin);
OtherEvolveParameter = null;
PermanentAITribeList = _field.GetReferenceTribe(BaseId);
int referenceId = _field.GetReferenceId(origin.CardId);
if (referenceId > 0)
{
BaseId = referenceId;
}
}
protected virtual void InitializeAIParameter()
{
IsUseEvo = false;
IsNotAttackYet = !IsAmulet;
IsMinimumBreakBonus = false;
IsRobbedLastword = false;
IsDestroyWhenAttack = false;
HasAfterAttackHeal = false;
IsMetamorphosed = false;
Value = 0f;
DefaultValue = 0f;
AttackByLifeCount = 0;
TempAtkBuff = 0;
TempLifeBuff = 0;
ChildrenIndexList = null;
}
public void InitializeEnemyHandParameter()
{
IsAlly = false;
IsInHand = true;
IsOnField = false;
}
private void InitializeFollowerTags(AIParamQuery query)
{
BattleCardBase baseCard = BaseCard;
if (IsSkillLost)
{
IsRobbedLastword = false;
IsDestroyWhenAttack = false;
HasAfterAttackHeal = false;
}
else
{
IsRobbedLastword = query.IsRobbedLastword(baseCard);
IsDestroyWhenAttack = query.IsDestroyBeforeAttack(baseCard);
TagCollectionContainer.InitTags(this, query);
HasAfterAttackHeal = TagCollectionContainer.HasTag(AIPlayTagType.AfterAttackHeal);
}
}
private void InitializeAmuletTags(AIParamQuery query)
{
if (!IsSkillLost)
{
TagCollectionContainer.InitTags(this, query);
}
}
public virtual void InitializeTags(AIParamQuery query, AIAttachedTagCollection attachedTagCollection, AIRemovedTagCollection removedTagCollection)
{
AIData = query.SearchAICardData(this);
if (IsAmulet)
{
InitializeAmuletTags(query);
}
else
{
InitializeFollowerTags(query);
}
attachedTagCollection?.AttachTagToReceiver(this);
removedTagCollection?.RemoveTagFromCard(this);
}
public void InitAtSummonToken(AIVirtualCard parent, AISituationInfo situation, bool isSkillSummon, bool isUpdateTokenIndex = true)
{
AIPreprocessSimulationUtility.SimulatePreprocess(this, situation, _field, AIScriptTokenArgType.WHEN_SUMMON, isPseudo: false);
IsOnField = true;
if (isUpdateTokenIndex)
{
if (_field.IsLatestActionField)
{
if (IsAlly)
{
CardIndex = _field.AllyCardTotalNum;
_field.AllyCardTotalNum++;
}
else
{
CardIndex = _field.EnemyCardTotalNum;
_field.EnemyCardTotalNum++;
}
}
else
{
CardIndex = _field.TokenIndex;
_field.TokenIndex--;
}
}
parent.AddChildren(CardIndex);
AttackableCount = MaxAttackableCount;
IsFirstTurn = true;
IsSkillSummoned = isSkillSummon;
if (IsUseEvo)
{
AttackableCount = 1;
AIAutoEvolutionSimulationUtility.AutoEvolveSingle(this, _field, situation);
}
}
public void PseudoInitAtSummonToken(AIVirtualCard parent, AISituationInfo situation, bool isSkillSummon)
{
IsOnField = true;
AttackableCount = MaxAttackableCount;
IsFirstTurn = true;
IsSkillSummoned = isSkillSummon;
if (IsUseEvo)
{
AttackableCount = ((AttackableCount <= 1) ? 1 : AttackableCount);
AIAutoEvolutionSimulationUtility.AutoEvolveSingle(this, _field, situation);
}
}
public void InitAtDrawToken(AIVirtualCard parent, AISituationInfo situation)
{
AIPreprocessSimulationUtility.SimulatePreprocess(this, situation, _field, AIScriptTokenArgType.TOKEN_DRAW, isPseudo: false);
IsOnField = false;
IsInHand = true;
if (_field.IsLatestActionField)
{
if (IsAlly)
{
CardIndex = _field.AllyCardTotalNum;
_field.AllyCardTotalNum++;
}
else
{
CardIndex = _field.EnemyCardTotalNum;
_field.EnemyCardTotalNum++;
}
}
else
{
CardIndex = _field.TokenIndex;
_field.TokenIndex--;
}
parent.AddChildren(CardIndex);
AddToHand();
}
public void InitAtMetamorphose(AIVirtualCard originCard, AIVirtualCard parent)
{
IsOnField = true;
CardIndex = originCard.CardIndex;
parent.AddChildren(CardIndex);
AttackableCount = MaxAttackableCount;
IsFirstTurn = true;
IsSkillSummoned = false;
}
public void InitAtHandMetamorphose(AIVirtualCard originCard, AIVirtualCard parent)
{
IsInHand = true;
CardIndex = originCard.CardIndex;
parent.AddChildren(CardIndex);
}
public void ReplaceSelfField(AIVirtualField field)
{
_field = field;
}
public void AddChildren(int index)
{
if (ChildrenIndexList == null)
{
ChildrenIndexList = new List<int>();
}
ChildrenIndexList.Add(index);
}
public virtual bool IsFollower(List<int> playPtn)
{
if (IsUnit)
{
if (!this.IsAccelerated(_field, playPtn))
{
return !this.IsCrystalize(_field, playPtn);
}
return false;
}
return false;
}
public virtual bool BasePlayable()
{
if (!IsAlly || !IsInHand)
{
return false;
}
return true;
}
public bool IsHoldKeywordSkill(AIScriptTokenArgType skill)
{
return skill switch
{
AIScriptTokenArgType.SNEAK => IsSneak,
AIScriptTokenArgType.KILLER => IsKiller,
AIScriptTokenArgType.GUARD => IsGuard,
AIScriptTokenArgType.RUSH => IsRush,
AIScriptTokenArgType.QUICK => IsQuick,
AIScriptTokenArgType.DRAIN => IsDrain,
AIScriptTokenArgType.UNTOUCHABLE => IsUntouchable,
AIScriptTokenArgType.FORCE_TARGETING => IsForceTargeting,
AIScriptTokenArgType.UNBANISHABLE => IsUnbanishable,
AIScriptTokenArgType.IGNORE_GUARD => IsIgnoreGuard,
_ => false,
};
}
public bool IsAttackable(List<int> playPtn)
{
bool flag = AttackableCount > 0 && !IsCantAttackAll && (!IsSummonDrunkenness || IsEvolution);
if (IsAlly && !flag && IsInHand && playPtn != null && playPtn.Count > 0)
{
for (int i = 0; i < playPtn.Count; i++)
{
if (_field.AllyHandCards[playPtn[i]].IsSameCard(this))
{
flag = AISkillSimulationUtility.HasSkill(this, AIScriptTokenArgType.QUICK, _field.AI, playPtn) || AISkillSimulationUtility.HasSkill(this, AIScriptTokenArgType.RUSH, _field.AI, playPtn);
break;
}
}
}
return flag;
}
public bool IsEvolDrunkenness()
{
if (IsFirstTurn && IsSummonDrunkenness)
{
return !IsQuick;
}
return false;
}
public bool IsCantAttackClass()
{
if (!IsSkillCantAttackClass && !IsEvolDrunkenness())
{
if (IsFirstTurn && IsRush)
{
return !IsQuick;
}
return false;
}
return true;
}
public void RecoverAttackableCount()
{
AttackableCount = MaxAttackableCount;
IsRecoveredAttackableCount = true;
}
public void ChangeClass(CardBasePrm.ClanType classType)
{
if (classType >= CardBasePrm.ClanType.ALL && classType < CardBasePrm.ClanType.MAX)
{
Clan = classType;
}
}
public bool IsTribe(AIScriptTokenArgType tribeType)
{
CardBasePrm.TribeType tribeType2 = AITribeSimulationUtility.ConvertTokenArgTypeToTribeType(tribeType);
if (tribeType2 >= CardBasePrm.TribeType.MAX)
{
return false;
}
return IsTribe(tribeType2);
}
public void AppendTribe(CardBasePrm.TribeType tribe)
{
if (_tribeList == null)
{
_tribeList = new List<CardBasePrm.TribeType>();
}
if (!_tribeList.Contains(tribe))
{
_tribeList.Add(tribe);
}
}
public void ChangeTribe(CardBasePrm.TribeType tribe)
{
if (_tribeList == null)
{
_tribeList = new List<CardBasePrm.TribeType>();
}
else
{
_tribeList.Clear();
}
_tribeList.Add(tribe);
}
public float UpdateValue(AIParamQuery paramQuery, AIStyleQuery styleQuery, List<int> playPtn, bool doesUseLostLife)
{
if (IsDead)
{
Value = 0f;
return Value;
}
if (IsUnit)
{
if (Life <= 0)
{
Value = 0f;
return Value;
}
Value = this.EvaluateValueOnField(playPtn, null, useStyle: true, doesUseLostLife, useOthersTag: true, useIgnoreInBattle: true);
Value += (this.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + this.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false)) * EnemyAI.BREAKBONUS_RATE_ON_FIELD;
}
else if (IsLeader)
{
Value = this.GetBattleBonus(playPtn);
}
else
{
Value = this.GetFieldBonus(playPtn);
}
return Value;
}
public void SetDefaultValue()
{
DefaultValue = Value;
}
public int SimulateAttackAmount(AISituationInfo situation)
{
return SimulateAttackAmount(Attack, situation);
}
public int SimulateAttackAmount(int attack, AISituationInfo situation)
{
return _field.DamageModifierCollection.CalcModifiedDamage(_field, EnemyAI.EmptyPlayPtn, situation, this, attack);
}
public int SimulateDamageAmount(int damageAmount, bool isSkillDamage = false, bool isSpellDamage = false)
{
damageAmount = BarrierInfoCollection.CalcDamageAmount(this, damageAmount, isSkillDamage, isSpellDamage);
return Math.Max(damageAmount, 0);
}
public int SimulateDamageShield(int damageAmount, bool isSkillDamage = false, bool isSpellDamage = false)
{
bool flag = !isSkillDamage && !isSpellDamage;
if ((isSkillDamage && BarrierInfoCollection.HasShieldSkill) || (isSpellDamage && BarrierInfoCollection.HasShieldSpell) || (flag && BarrierInfoCollection.HasShieldAttack))
{
return 0;
}
return damageAmount;
}
public int AddDamage(AISituationInfo situation, int baseDamage, bool isSkillDamage)
{
if (IsDead)
{
return 0;
}
bool isSpellDamage = situation.ActionType == AIOperationType.PLAY && situation.Actor.IsSpell;
int num = SimulateDamageAmount(baseDamage, isSkillDamage, isSpellDamage);
Life -= num;
if (Life > 0)
{
LastLife = Life;
SelfField.DamagedCardsByLastAction.Add(new Tuple<AIVirtualCard, int>(this, num));
}
else
{
IsDead = true;
}
_field.TagPreprocessContainer.SimulateAfterDamageInfo(this);
_field.ExecuteWhenDamageTags(this, baseDamage, SelfField.BestPlayPtn, situation);
_field.AllActivateCountHolderIncrement(situation, AIPlayTagType.DamagedActivateCount, this);
return num;
}
public void Heal(int healLife)
{
if (!IsDead)
{
int life = Life;
Life = Math.Min(Life + healLife, MaxLife);
LastHealAmount = Life - life;
LastLife = Life;
int turn = (IsAlly ? _field.AllyTurnCount : _field.EnemyTurnCount);
_field.HealRecorderCollection.AppendHealCount(turn, this, IsAlly);
}
}
private void ModifyAttack(int buff, bool isMultiply, bool isTemp)
{
int attack = Attack;
if (isMultiply)
{
Attack *= buff;
}
else
{
Attack += buff;
}
if (isTemp)
{
TempAtkBuff += Attack - attack;
}
}
private void ModifyLife(AISituationInfo situation, int buff, bool isMultiply, bool isTemp)
{
int life = Life;
if (isMultiply)
{
Life *= buff;
}
else
{
Life += buff;
}
if (Life <= 0)
{
RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
}
int newLife = (isMultiply ? (MaxLife * buff) : (MaxLife + buff));
SetMaxLife(situation, newLife);
if (isTemp && !IsDead)
{
TempLifeBuff += Life - life;
}
LastLife = Life;
}
public void GiveBuff(AISituationInfo situation, AIBuffExecutingInfo_old buff, bool isTemp)
{
int attack = Attack;
int life = Life;
ModifyAttack(buff.AttackValue, buff.IsMultiplyAttack, isTemp);
ModifyLife(situation, buff.LifeValue, buff.IsMultiplyLife, isTemp);
int turn = (IsAlly ? _field.AllyTurnCount : _field.EnemyTurnCount);
if (BuffRecorderCollection == null)
{
BuffRecorderCollection = new AIBuffRecorderCollection();
}
int atkBuff = Attack - attack;
int lifeBuff = Life - life;
BuffRecorderCollection.AddBuffRecord(turn, IsSelfTurn, atkBuff, lifeBuff);
if (isTemp)
{
AIBuffStopPreprocessOption option = new AIBuffStopPreprocessOption(this);
_field.TagPreprocessContainer.AppendAllyTurnEndStopInfo(option);
_field.TagPreprocessContainer.AppendOpponentTurnEndStopInfo(option);
}
}
public void MultiplyAttack(int rate)
{
Attack *= rate;
}
public void MultiplyLife(int rate)
{
Life *= rate;
}
public void SetAttack(int newAttack)
{
Attack = newAttack;
}
public void SetLife(int newLife, AISituationInfo situation)
{
Life = newLife;
MaxLife = newLife;
TempLifeBuff = 0;
if (Life <= 0)
{
RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
}
}
public void SetMaxLife(AISituationInfo situation, int newLife)
{
MaxLife = newLife;
if (Life > MaxLife)
{
Life = MaxLife;
}
if (Life <= 0)
{
RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
}
}
public void SetNewStatus(AISituationInfo situation, int newAttack, int newLife)
{
Attack = newAttack;
Life = newLife;
SetMaxLife(situation, newLife);
LastLife = Life;
TempAtkBuff = 0;
TempLifeBuff = 0;
}
public void ChantCountDown(AISituationInfo situation, int value)
{
ChantCount -= value;
if (ChantCount <= 0)
{
RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
}
}
public int EarthRite(int count, AISituationInfo situation, bool isPseudo)
{
int num = Math.Min(WhiteRitualCount, count);
WhiteRitualCount -= num;
if (!isPseudo)
{
_originalWhiteRitualCount -= num;
}
if (WhiteRitualCount <= 0)
{
if (isPseudo)
{
IsDead = true;
}
else
{
Destroy(situation, isFromSkill: true);
}
}
return num;
}
public void SetWhiteRitual(int count)
{
if (count <= 0)
{
AIConsoleUtility.LogError($"SetWhiteRitual : Ilegal add count Error [count={count}]");
}
else if (!IsDead && IsStackWhiteRitual && WhiteRitualCount > 0)
{
WhiteRitualCount = count;
}
}
public bool AddWhiteRitual(int count)
{
if (count <= 0)
{
AIConsoleUtility.LogError($"AddWhiteRitual : Ilegal add count Error [count={count}]");
return false;
}
if (IsDead || !IsStackWhiteRitual || WhiteRitualCount <= 0)
{
return false;
}
WhiteRitualCount += count;
return true;
}
public void ResetEarthRite(int resetCount)
{
if (WhiteRitualCount <= 0 && IsDead)
{
IsDead = false;
}
WhiteRitualCount += Mathf.Max(0, resetCount);
}
public void ResetAllEvaluationUpdatedParameter()
{
if (WhiteRitualCount <= 0 && IsDead)
{
IsDead = false;
}
WhiteRitualCount = _originalWhiteRitualCount;
}
public void ChangeIsCantUnderAttack(bool isCantUnderAttack)
{
_isCantUnderAttack = isCantUnderAttack;
}
public void RegisterGiveSneakTag(AIPlayTag tag)
{
_giveSneakTagList = AIParamQuery.AddElementToList(tag, _giveSneakTagList);
}
public void DepriveSneakWithGiveSneakTag()
{
IsSneak = false;
if (_giveSneakTagList != null && _giveSneakTagList.Count > 0)
{
for (int i = 0; i < _giveSneakTagList.Count; i++)
{
AIPlayTag removingTag = _giveSneakTagList[i];
TagCollectionContainer.RemoveOneTagWithUpdatingFieldCardList(this, removingTag, SelfField);
}
_giveSneakTagList.Clear();
}
}
public bool IsCantUnderAttack(AIParamQuery query, AIVirtualCard attacker, List<int> playPtn, AIVirtualField field)
{
if (TagCollectionContainer.HasTag(AIPlayTagType.CantBeAttacked) && TagCollectionContainer.CantBeAttackedTags.CantBeAttacked(this, attacker, playPtn, field))
{
return false;
}
return _isCantUnderAttack;
}
public bool IsCantUnderAnyAttack()
{
return _isCantUnderAttack;
}
public void AfterClash(AIVirtualCard clashTarget, int finalDamage, bool isAttacker, List<int> playPtn, AIVirtualAttackInfo situation)
{
if (!clashTarget.IsIndependent && IsKiller)
{
clashTarget.RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: true);
}
if (isAttacker)
{
if (IsSneak)
{
DepriveSneakWithGiveSneakTag();
}
DealDamageDrain(finalDamage, playPtn, situation);
}
if (Life <= 0 && !IsDead)
{
RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
}
}
public void DealDamageDrain(int damage, List<int> playPtn, AISituationInfo situation)
{
if (IsDrain && damage >= 0)
{
AISkillSimulationUtility.HealSingle(IsAlly ? _field.AllyClass : _field.EnemyClass, SelfField, damage, playPtn, situation);
}
}
public void RemoveTempBuff()
{
if (TempAtkBuff != 0)
{
Attack -= TempAtkBuff;
TempAtkBuff = 0;
}
if (TempLifeBuff != 0)
{
Life -= TempLifeBuff;
LastLife = Life;
TempLifeBuff = 0;
}
}
public bool IsEqual(BattleCardBase card)
{
if (card.Index == CardIndex && _field.AI.IsAllyCard(card) == IsAlly)
{
return card.BaseParameter.BaseCardId == BaseId;
}
return false;
}
public bool IsSameCard(AIVirtualCard card)
{
if (card.CardIndex == CardIndex && card.IsAlly == IsAlly)
{
return card.BaseParameter.BaseId == BaseParameter.BaseId;
}
return false;
}
public bool IsSameCardType(AIVirtualCard card)
{
if (card.IsUnit == IsUnit && card.IsSpell == IsSpell)
{
return (card.IsAmulet || card.IsCountdownAmulet) == (IsAmulet || IsCountdownAmulet);
}
return false;
}
public bool IsSameCardIncluded(List<AIVirtualCard> list)
{
if (list == null || list.Count <= 0)
{
return false;
}
for (int i = 0; i < list.Count; i++)
{
AIVirtualCard card = list[i];
if (IsSameCard(card))
{
return true;
}
}
return false;
}
public void NormalPlay()
{
IsOnField = true;
IsInHand = false;
IsFirstTurn = true;
AttackableCount = MaxAttackableCount;
IsSummonDrunkenness = !IsQuick && !IsRush;
}
public void ResetPosition(AIOperationType actionType)
{
if (actionType == AIOperationType.PLAY)
{
IsInHand = true;
IsOnField = false;
}
}
public void EvolveStatusUp()
{
Life += EvoLifePlus;
LastLife = Life;
MaxLife += EvoLifePlus;
Attack += EvoAttackPlus;
IsEvolution = true;
}
public void AddToHand()
{
IsInHand = true;
IsOnField = false;
if (IsAlly)
{
_field.AllyHandCards.Add(this);
}
else
{
_field.GetEnemyHandCardList().Add(this);
}
_field.CardListSet.AddHandCard(this);
}
private void LeaveFromField(AISituationInfo situation)
{
IsDead = true;
IsOnField = false;
_isCompletedRemove = true;
if (IsAlly)
{
_field.CardListSet.AddAllyLeftCard(this);
_field.CardListSet.AddAllyLeftCardThisTurn(this);
}
else
{
_field.CardListSet.AddEnemyLeftCard(this);
_field.CardListSet.AddEnemyLeftCardThisTurn(this);
}
_field.WhenCardLeaveFromField(this, situation);
GetOff(situation);
}
private void ExecuteLeaveSkills(AISituationInfo situation)
{
_field.SimulationExtraBonus += (float)(IsAlly ? 1 : (-1)) * this.GetAllLeaveBonus(_field.BestPlayPtn, useIgnoreInBattle: true);
if (TagCollectionContainer.HasTagCollection(TagCollectionType.WhenLeave))
{
TagCollectionContainer.LeaveTags.Execute(this, _field.BestPlayPtn, situation);
}
if (!_field.CardListSet.HasLeaveOtherTagHolders)
{
return;
}
for (int i = 0; i < _field.CardListSet.WhenLeaveOtherTagHolders.Count; i++)
{
AIVirtualCard aIVirtualCard = _field.CardListSet.WhenLeaveOtherTagHolders[i];
if (!aIVirtualCard.IsSameCard(this))
{
aIVirtualCard.TagCollectionContainer.OtherLeaveTags.RegisterPassedConditionTags(aIVirtualCard, SelfField, SelfField.BestPlayPtn, situation, this);
}
}
}
private void Destroy(AISituationInfo situation, bool isFromSkill)
{
if (_field == null || _isCompletedRemove || (isFromSkill && IsIndestructible))
{
return;
}
AISkillProcessInformation processInfo = situation.RegisterNewProcessInfo(this, AISituationTriggerInformation.TriggerType.Undefined);
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
situation.RegisterOwnDestroyedCard(this);
LeaveFromField(situation);
_field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
ExecuteLeaveSkills(situation);
if (IsLeader)
{
return;
}
_field.VirtualCemetery.AddCemetery(1, IsAlly);
if (TagCollectionContainer.HasTag(AIPlayTagType.RemoveSkill))
{
TagCollectionContainer.RemoveSkillTags.Execute(this, AIScriptTokenArgType.WHEN_DESTROY, null);
}
if (this.IsBreakBeforePlay(_field.BestPlayPtn))
{
_field.IsBreakBeforePlayKilled = true;
}
if (!IsSkillLost && (this.HasBreakBonus(_field) || TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword)))
{
if (IsAmulet)
{
_field.SimulationExtraBonus += (float)(IsAlly ? 1 : (-1)) * this.GetAllBreakBonus(_field.BestPlayPtn, useIgnoreInBattle: true);
ExecuteLastwordSkills(processInfo, situation);
}
else
{
AIVirtualCard aIVirtualCard = (IsAlly ? _field.AllyClass : _field.EnemyClass);
int num = 1;
if (aIVirtualCard.TagCollectionContainer.HasTag(AIPlayTagType.OneMoreLastword) && aIVirtualCard.TagCollectionContainer.OneMoreLastwordTags.CheckConditionAndRemovePassedTags(aIVirtualCard, _field, situation))
{
num++;
}
_field.SimulationExtraBonus += (float)(IsAlly ? 1 : (-1)) * this.GetBreakBonus(_field.BestPlayPtn, useIgnoreBreak: true) * (float)num;
_field.SimulationExtraBonus += (float)(IsAlly ? 1 : (-1)) * AIEvaluateBonusFromOhterUtility.GetOtherBreakBonus(this, _field, _field.BestPlayPtn, useIgnoreInBattle: true);
for (int i = 0; i < num; i++)
{
ExecuteLastwordSkills(processInfo, situation);
}
}
}
if (IsAlly)
{
_field.CardListSet.AddAllyDestroyedCard(this, isDestroyTurn: true);
}
else
{
_field.CardListSet.AddEnemyDestroyedCard(this);
}
if (SelfField.CardListSet.HasBreakTagHolder)
{
ApplyWhenDestroyTags(situation);
}
_field.AllActivateCountHolderIncrement(situation, AIPlayTagType.BreakActivateCount, this);
}
public void BurialRite()
{
if (IsInHand)
{
IsInHand = false;
_field.RemoveAllyHandCard(this);
_field.VirtualCemetery.AddCemetery(1, IsAlly);
}
}
private void ExecuteLastwordSkills(AISkillProcessInformation processInfo, AISituationInfo situation)
{
AIPreprocessSimulationUtility.SimulatePreprocess(this, situation, _field, AIScriptTokenArgType.WHEN_DESTROY, isPseudo: false);
if (TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword))
{
TagCollectionContainer.LastwordTags.RegisterExecutingTagActions(this, processInfo, situation);
}
situation.ProcessCollection.CombinePreprocessToProcessQueue();
}
private void Banish(AISituationInfo situation)
{
if (!_isCompletedRemove)
{
if (situation == null)
{
AIConsoleUtility.LogError("AIVirtualCard.Banish() error!! situation == null!!!!!");
}
situation.RegisterNewProcessInfo(this, AISituationTriggerInformation.TriggerType.Banish);
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
SetBanishedCardInfo();
situation.RegisterOwnBanishedCard(this);
LeaveFromField(situation);
_field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
ExecuteLeaveSkills(situation);
ApplyWhenBanishTags(situation);
_field.AllActivateCountHolderIncrement(situation, AIPlayTagType.BanishActivateCount, this);
_field.CardListSet.AddBanishedCard(this);
}
}
private void SetBanishedCardInfo()
{
if (_field == null)
{
AIConsoleUtility.LogError("SetBanishedCardInfo() Error : Field is Null");
return;
}
int currentTurnCount = _field.CurrentTurnCount;
BattleCardBase.BanishInfo.BanishPlace place = (IsOnField ? BattleCardBase.BanishInfo.BanishPlace.Field : (IsInHand ? BattleCardBase.BanishInfo.BanishPlace.Hand : BattleCardBase.BanishInfo.BanishPlace.Deck));
BanishedInfo = new AIVirtualBanishInfo(currentTurnCount, IsSelfTurn, place);
}
public bool IsBanishedTargetTurn(int turn)
{
if (BanishedInfo == null)
{
return false;
}
if (BanishedInfo.Place == BattleCardBase.BanishInfo.BanishPlace.None || BanishedInfo.Place == BattleCardBase.BanishInfo.BanishPlace.Deck)
{
return false;
}
if (BanishedInfo.Turn != turn || BanishedInfo.IsCardOwnerTurn != IsSelfTurn)
{
return false;
}
return true;
}
private void ConvertBaseBanishInfo(BattleCardBase.BanishInfo baseInfo)
{
if (baseInfo == null)
{
AIConsoleUtility.LogError("ConvertBaseBanishInfo() : convert target is Null");
return;
}
bool isSelfTurn = baseInfo.IsSelfTurn;
bool isCardOwnerTurn = (IsPlayer ? isSelfTurn : (!isSelfTurn));
BanishedInfo = new AIVirtualBanishInfo(baseInfo.Turn, isCardOwnerTurn, baseInfo.Place);
}
public void MetamorphoseLeave(AISituationInfo situation)
{
if (!_isCompletedRemove)
{
IsDead = true;
IsOnField = false;
LeaveFromField(situation);
}
}
private void Bounce(AISituationInfo situation)
{
if (!_isCompletedRemove)
{
_field.SimulationExtraBonus += (float)(IsAlly ? 1 : (-1)) * this.GetBounceBonus();
LeaveFromField(situation);
ExecuteLeaveSkills(situation);
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
situation.BounceCardList = AIParamQuery.AddElementToList(this, situation.BounceCardList);
this.ExecuteBounceSkills(this, _field, emptyPlayPtn, situation);
List<AIVirtualCard> list;
if (IsAlly)
{
list = _field.AllyHandCards;
_field.AllyInplayCards.Remove(this);
_field.CardListSet.RemoveAllyInplayCard(this);
}
else
{
list = _field.GetEnemyHandCardList();
_field.EnemyInplayCards.Remove(this);
_field.CardListSet.RemoveEnemyInplayCard(this);
}
if (list.Count >= 9)
{
_field.VirtualCemetery.AddCemetery(1, IsAlly);
}
else
{
AIVirtualCard aIVirtualCard = new AIVirtualCard(BaseCard, _field)
{
IsInHand = true
};
aIVirtualCard.InitializeTags(_field.ParamQuery, null, null);
list.Add(aIVirtualCard);
_field.CardListSet.AddHandCard(aIVirtualCard);
}
_field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
}
}
public void Reanimate(AISituationInfo situation)
{
if (this.IsReanimateEvo(_field.BestPlayPtn))
{
AttackableCount = 1;
AIAutoEvolutionSimulationUtility.AutoEvolveSingle(this, _field, situation);
}
}
public void GetOn(AIVirtualCard rideCard, AISituationInfo situation)
{
if (TagCollectionContainer.HasTag(AIPlayTagType.GetOn) && rideCard != null && rideCard.IsAlly == IsAlly && rideCard.IsUnit && !IsGetOn)
{
GetOnCardId = rideCard.BaseId;
rideCard.ToRide();
IsCantAttackAll = false;
IsSkillCantAttackUnit = false;
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
_field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
AIGetOnSimulationUtility.ExecuteGetOnTriggerTags(this, _field, situation);
}
}
public void GetOff(AISituationInfo situation)
{
if (IsGetOn)
{
GetOffCard = AIGetOnSimulationUtility.GetoffTokenOnVirtualField(GetOnCardId, this, _field, situation);
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
_field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
}
}
public void ToRide()
{
IsDead = true;
}
public void Spellboost(int count)
{
if (IsInHand && HasSpellboost)
{
SpellboostCount += count;
}
}
public void SetSpellboostCount(int count)
{
SpellboostCount = count;
}
public float EvaluateClashBonus()
{
if (!TagCollectionContainer.HasTagCollection(TagCollectionType.ClashBonus))
{
return 0f;
}
return TagCollectionContainer.ClashBonusTags.GetClashBonus(this, SelfField, SelfField.BestPlayPtn);
}
private void ApplyWhenDestroyTags(AISituationInfo situation)
{
for (int i = 0; i < SelfField.CardListSet.BreakTagHolders.Count; i++)
{
AIVirtualCard aIVirtualCard = SelfField.CardListSet.BreakTagHolders[i];
if (!aIVirtualCard.IsDead && (aIVirtualCard.CardIndex != CardIndex || aIVirtualCard.BaseId != BaseId) && aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenBreak))
{
aIVirtualCard.TagCollectionContainer.BreakTags.RegisterExecutingTagActions(SelfField, aIVirtualCard, this, SelfField.BestPlayPtn, situation);
}
}
}
private void ApplyWhenBanishTags(AISituationInfo situation)
{
if (TagCollectionContainer.HasTagCollection(TagCollectionType.WhenBanish))
{
TagCollectionContainer.BanishTags.RegisterExecutingTagActions(SelfField, this, SelfField.BestPlayPtn, situation);
}
if (!SelfField.CardListSet.HasBanishTagHolder)
{
return;
}
for (int i = 0; i < SelfField.CardListSet.BanishTagHolders.Count; i++)
{
AIVirtualCard aIVirtualCard = SelfField.CardListSet.BanishTagHolders[i];
if (!aIVirtualCard.IsDead && !aIVirtualCard.IsSameCard(this) && aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenOtherBanish))
{
aIVirtualCard.TagCollectionContainer.OtherBanishTags.RegisterExecutingTagActions(SelfField, aIVirtualCard, this, SelfField.BestPlayPtn, situation);
}
}
}
public void GiveAttackable()
{
IsCantAttackAll = false;
IsSkillCantAttackUnit = false;
IsSkillCantAttackClass = false;
}
public void GiveAttackableCount(int count)
{
int maxAttackableCount = MaxAttackableCount;
if (count > maxAttackableCount)
{
AttackableCount = Math.Min(AttackableCount + (count - maxAttackableCount), count);
}
else if (count < maxAttackableCount)
{
AttackableCount = Math.Min(count, AttackableCount);
}
MaxAttackableCount = count;
}
public void RemoveAllSkills(AISituationInfo situation)
{
DepriveSneakWithGiveSneakTag();
IsKiller = false;
IsDrain = false;
IsRush = false;
IsQuick = false;
IsDestroyWhenAttack = false;
HasSpellboost = false;
IsForceTargeting = false;
IsUnbanishable = false;
UntouchableCount = 0;
_bounceByBanishCount = 0;
_banishByDestroyCount = 0;
_destroyByBanishCount = 0;
TagCollectionContainer.RemoveAllTagWithUpdatingFieldCardList(this, SelfField, situation);
IsSkillLost = true;
}
public void CallOnAfterBattleSimulation(AIVirtualTurnEndInfo turnEndSituation)
{
turnEndSituation.ProcessCollection.ClearTempPreprocessList();
AIPreprocessSimulationUtility.SimulatePreprocess(this, turnEndSituation, _field, AIScriptTokenArgType.WHEN_TURNEND, isPseudo: false);
AISkillProcessInformation aISkillProcessInformation = turnEndSituation.RegisterNewProcessInfo(null, AISituationTriggerInformation.TriggerType.Undefined);
if (TagCollectionContainer.HasTagCollection(TagCollectionType.WhenTurnEnd))
{
TurnEndTagCollection turnEndTags = TagCollectionContainer.TurnEndTags;
if (turnEndTags.HasTagExecuteWhenAllyTurnEnd(turnEndSituation.Actor.IsAlly == IsAlly))
{
turnEndTags.RegisterConditionPassedTagActions(this, SelfField.BestPlayPtn, turnEndSituation, aISkillProcessInformation);
}
}
turnEndSituation.ProcessCollection.CombinePreprocessToProcessQueue();
aISkillProcessInformation.AddExecutingAction(delegate
{
if (!turnEndSituation.Actor.IsLeader)
{
AIConsoleUtility.LogError("turnEndSituation.Actor is not Leader!!");
}
else
{
this.Increment(turnEndSituation, AIPlayTagType.TurnEndActivateCount);
}
});
}
public bool IsAbleEvolution()
{
if (!IsUnit)
{
return false;
}
if (IsEvolution)
{
return false;
}
if (!_field.IsExceededWaitEvolveTurn)
{
return false;
}
if (!_field.IsLeftTurnEvol)
{
return false;
}
if (_field.AllyEvolutionCount <= 0 && !IsNotConsumeEp)
{
return false;
}
if (IsDebuffCantEvolve)
{
return false;
}
return true;
}
public bool IsAbleToPlay(List<int> playPtn, AIVirtualTargetSelectAction playSituation)
{
if (playSituation == null)
{
AIConsoleUtility.LogError("IsAbleToPlay() : situation is null");
return false;
}
return AIPlayCardSimulationUtility.IsAbleToPlayCard(playSituation, _field, playPtn);
}
public int GetUseCost(int restPp, List<int> playPtn, AISituationInfo situation, out PlaySimulationType playType)
{
int result = GetPlayEnhancedCost(restPp, out playType);
if (playType == PlaySimulationType.Undefined)
{
result = GetPlayChoiceTransformedCost(restPp, playPtn, situation, out playType);
}
if (playType == PlaySimulationType.Undefined)
{
result = GetPlayNormalCost(restPp, playPtn, situation, out playType);
}
if (playType == PlaySimulationType.Undefined)
{
result = GetPlayAcceleratedCost(restPp, playPtn, situation, out playType);
}
if (playType == PlaySimulationType.Undefined)
{
result = GetPlayCrystalizedCost(restPp, out playType);
}
if (situation is AIVirtualActionInfo aIVirtualActionInfo)
{
aIVirtualActionInfo.ReservedPlayType = playType;
}
return result;
}
public bool IsPlayingSimulationType(int restPp, List<int> playPtn, AISituationInfo situation, PlaySimulationType checkPlayType)
{
PlaySimulationType playType = PlaySimulationType.Undefined;
switch (checkPlayType)
{
case PlaySimulationType.Accelerate:
GetPlayNormalCost(restPp, playPtn, situation, out playType);
if (playType != PlaySimulationType.Normal)
{
GetPlayAcceleratedCost(restPp, playPtn, situation, out playType);
}
break;
case PlaySimulationType.ChoiceTransform:
GetPlayChoiceTransformedCost(restPp, playPtn, null, out playType);
break;
case PlaySimulationType.Crystalize:
GetPlayNormalCost(restPp, playPtn, situation, out playType);
if (playType != PlaySimulationType.Normal)
{
GetPlayCrystalizedCost(restPp, out playType);
}
break;
case PlaySimulationType.Enhance:
GetPlayEnhancedCost(restPp, out playType);
break;
case PlaySimulationType.Normal:
GetPlayNormalCost(restPp, playPtn, situation, out playType);
break;
default:
AIConsoleUtility.LogError("IsPlayingSimulationType() : Check Target is Undefined Play Type!");
break;
}
return playType == checkPlayType;
}
public int GetPlaySimulationTypeCost(int restPp, List<int> playPtn, AISituationInfo situation, PlaySimulationType checkPlayType)
{
PlaySimulationType playType = PlaySimulationType.Undefined;
int result = -1;
switch (checkPlayType)
{
case PlaySimulationType.Accelerate:
result = GetPlayNormalCost(restPp, playPtn, situation, out playType);
if (playType != PlaySimulationType.Normal)
{
result = GetPlayAcceleratedCost(restPp, playPtn, situation, out playType);
}
break;
case PlaySimulationType.ChoiceTransform:
result = GetPlayChoiceTransformedCost(restPp, playPtn, null, out playType);
break;
case PlaySimulationType.Crystalize:
result = GetPlayNormalCost(restPp, playPtn, situation, out playType);
if (playType != PlaySimulationType.Normal)
{
result = GetPlayCrystalizedCost(restPp, out playType);
}
break;
case PlaySimulationType.Enhance:
result = GetPlayEnhancedCost(restPp, out playType);
break;
case PlaySimulationType.Normal:
result = GetPlayNormalCost(restPp, playPtn, situation, out playType);
break;
default:
AIConsoleUtility.LogError("GetPlaySimulationTypeCost() : Check Target is Undefined Play Type!");
break;
}
if (playType != checkPlayType)
{
return -1;
}
return result;
}
public int GetPlayNormalCost(int restPp, List<int> playPtn, AISituationInfo situation, out PlaySimulationType playType)
{
playType = PlaySimulationType.Undefined;
int num = Mathf.Max(0, Cost - this.GetCostBonus(playPtn, situation));
if (restPp >= num)
{
playType = PlaySimulationType.Normal;
}
return num;
}
public int GetPlayEnhancedCost(int restPp, out PlaySimulationType playType)
{
playType = PlaySimulationType.Undefined;
int num = -1;
if (EnhanceCostList != null && EnhanceCostList.Count > 0)
{
for (int i = 0; i < EnhanceCostList.Count; i++)
{
int num2 = EnhanceCostList[i];
if (restPp >= num2 && num2 > num)
{
num = num2;
}
}
if (num >= 0)
{
playType = PlaySimulationType.Enhance;
}
}
return num;
}
public int GetPlayChoiceTransformedCost(int restPp, List<int> playPtn, AISituationInfo situation, out PlaySimulationType playType)
{
playType = PlaySimulationType.Undefined;
int num = -1;
if (ChoiceTransformCostList != null && ChoiceTransformCostList.Count > 0)
{
for (int i = 0; i < ChoiceTransformCostList.Count; i++)
{
AIChoiceTransformCostInformation aIChoiceTransformCostInformation = ChoiceTransformCostList[i];
if (aIChoiceTransformCostInformation.CheckCondition(this, _field, playPtn, situation))
{
int num2 = (int)aIChoiceTransformCostInformation.Cost.EvalArg(this, playPtn, _field, situation);
if (restPp >= num2 && num2 > num)
{
num = num2;
}
}
}
if (num >= 0)
{
playType = PlaySimulationType.ChoiceTransform;
}
}
return num;
}
public int GetPlayAcceleratedCost(int restPp, List<int> playPtn, AISituationInfo situation, out PlaySimulationType playType)
{
playType = PlaySimulationType.Undefined;
int num = -1;
if (AccelerateCostList != null && AccelerateCostList.Count > 0)
{
for (int i = 0; i < AccelerateCostList.Count; i++)
{
AIAccelerateInformation aIAccelerateInformation = AccelerateCostList[i];
if (aIAccelerateInformation.CheckCondition(this, _field, playPtn, situation))
{
int cost = aIAccelerateInformation.Cost;
if (restPp >= cost && cost > num)
{
num = cost;
}
}
}
if (num >= 0)
{
playType = PlaySimulationType.Accelerate;
}
}
return num;
}
public int GetPlayCrystalizedCost(int restPp, out PlaySimulationType playType)
{
playType = PlaySimulationType.Undefined;
int num = -1;
if (CrystalizeCostList != null && CrystalizeCostList.Count > 0)
{
for (int i = 0; i < CrystalizeCostList.Count; i++)
{
AICrystalizeInformation aICrystalizeInformation = CrystalizeCostList[i];
if (restPp >= aICrystalizeInformation.Cost && aICrystalizeInformation.Cost > num)
{
num = aICrystalizeInformation.Cost;
}
}
if (num >= 0)
{
playType = PlaySimulationType.Crystalize;
}
}
return num;
}
public void SetCurrentCost(int target_cost)
{
if (target_cost < 0)
{
AIConsoleUtility.LogError($"SetCurrentCost: Set ilegal values [{target_cost}]");
}
Cost = target_cost;
}
public void AddCurrentCost(int add_cost)
{
Cost = Mathf.Max(0, Cost + add_cost);
}
public void CreateHandPlayEstimator(AIParamQuery paramQuery, int handIndex, BattlePlayerPair sourcePair, EnemyAI ai)
{
_handPlayEstimator = new AIHandPlayEstimator(paramQuery, handIndex, this, sourcePair, ai);
}
public AIHandPlayEstimator GetHandPlayEstimator()
{
return _handPlayEstimator;
}
public int GetBaseSkillCount()
{
return BattleSkills.Count();
}
public bool IsHoldingBattleSkill(string hash)
{
if (BattleSkillHashList == null || BattleSkillHashList.Count <= 0)
{
return false;
}
for (int i = 0; i < BattleSkillHashList.Count; i++)
{
if (hash == BattleSkillHashList[i].ToString())
{
return true;
}
}
return false;
}
public void ResetParameterAfterPlayPtnEvaluation()
{
SpellboostCount = RealSpellboostCount;
Cost = RealCost;
if (_originalWhiteRitualCount != WhiteRitualCount)
{
if (IsDead && WhiteRitualCount <= 0 && _originalWhiteRitualCount > 0)
{
IsDead = false;
}
WhiteRitualCount = _originalWhiteRitualCount;
}
}
public void RollBackFromOneRecord(AIVirtualFieldRollBackRecord.CardParamRecord record)
{
Cost = record.Cost;
SpellboostCount = record.SpellBoost;
IsDead = record.IsDead;
WhiteRitualCount = record.WhiteRitualCount;
if (TagCollectionContainer.HasTagCollection(TagCollectionType.ActivateCount))
{
TagCollectionContainer.ActivateCountTags.UpdateCounterList(record.ActivateCounterList);
}
}
public void NotBeAttacked()
{
IsSkillCantUnderAnyAttack = true;
}
public float EvalKillerAttackValue(List<int> playPtn, AISituationInfo situation)
{
float num = (IsUnit ? (0f - this.EvaluateValueOnField(playPtn, situation, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true) + this.EvaluateBreakValue(playPtn, useIgnoreBreak: true) + this.EvaluateLeaveValue(playPtn, useIgnoreInBattle: true)) : 0f);
float num2 = float.MinValue;
AIVirtualCard aIVirtualCard = null;
bool flag = _field.EnemyInplayCards.Any((AIVirtualCard card) => card.IsGuard);
for (int num3 = 0; num3 < _field.EnemyInplayCards.Count; num3++)
{
float num4 = 0f;
AIVirtualCard aIVirtualCard2 = _field.EnemyInplayCards[num3];
if (!aIVirtualCard2.IsUnit || aIVirtualCard2.IsCantUnderAnyAttack() || (flag && !aIVirtualCard2.IsGuard && !IsIgnoreGuard) || new AIVirtualAttackInfo(this, aIVirtualCard2).WillTargetDestroyByAttackTags(_field, playPtn, this))
{
continue;
}
bool flag2 = true;
if (aIVirtualCard2.IsIndependent || aIVirtualCard2.IsIndestructible)
{
int damage = BaseCard.DamageCalculationAtkTypeAttack.Damage;
if (aIVirtualCard2.BaseCard.CalculateFinalDamageAmount(damage) < aIVirtualCard2.Life)
{
flag2 = false;
}
}
if (flag2)
{
float num5 = aIVirtualCard2.EvaluateValueOnField(EnemyAI.EmptyPlayPtn, null, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true) - aIVirtualCard2.EvaluateBreakValue(EnemyAI.EmptyPlayPtn, useIgnoreBreak: true) - aIVirtualCard2.EvaluateLeaveValue(EnemyAI.EmptyPlayPtn, useIgnoreInBattle: true);
num4 += num5;
}
int damage2 = aIVirtualCard2.BaseCard.DamageCalculationAtkTypeBeAttacked.Damage;
if (BaseCard.CalculateFinalDamageAmount(damage2) >= Life)
{
num4 += num;
}
if (num4 > num2)
{
num2 = num4;
aIVirtualCard = aIVirtualCard2;
}
}
if (aIVirtualCard != null)
{
return num2;
}
return 0f;
}
public void GiveRemoveByBanish()
{
_destroyByBanishCount++;
_bounceByBanishCount++;
}
public void DepriveRemoveByBanish()
{
if (_destroyByBanishCount > 0)
{
_destroyByBanishCount--;
}
if (_bounceByBanishCount > 0)
{
_bounceByBanishCount--;
}
}
public void GiveRemoveByDestroy()
{
_banishByDestroyCount++;
}
public void DepriveRemoveByDestroy()
{
if (_banishByDestroyCount > 0)
{
_banishByDestroyCount--;
}
}
public void AddUntouchableCount()
{
UntouchableCount++;
}
public void SubUntouchableCount()
{
UntouchableCount--;
if (UntouchableCount < 0)
{
UntouchableCount = 0;
}
}
public void RemoveCard(AISituationInfo situation, AIRemovalType type, bool isFromSkill)
{
switch (type)
{
case AIRemovalType.Destroy:
TryDestroyCard(situation, isFromSkill);
break;
case AIRemovalType.Banish:
TryBanishCard(situation);
break;
case AIRemovalType.Bounce:
TryBounceCard(situation);
break;
}
RemoveTempBuff();
}
private void TryDestroyCard(AISituationInfo situation, bool isFromSkill)
{
if (IsDestroyByBanish)
{
if (IsBanishByDestroy || this.IsRemoveByDestroy(EnemyAI.EmptyPlayPtn, situation))
{
Destroy(situation, isFromSkill);
}
else if (!isFromSkill || !IsIndestructible)
{
Banish(situation);
}
}
else
{
Destroy(situation, isFromSkill);
}
}
private void TryBanishCard(AISituationInfo situation)
{
if (IsBanishByDestroy || this.IsRemoveByDestroy(EnemyAI.EmptyPlayPtn, situation))
{
Destroy(situation, isFromSkill: true);
}
else
{
Banish(situation);
}
}
private void TryBounceCard(AISituationInfo situation)
{
if (IsBounceByBanish)
{
if (IsBanishByDestroy || this.IsRemoveByDestroy(EnemyAI.EmptyPlayPtn, situation))
{
if (IsIndestructible)
{
Bounce(situation);
}
else
{
Destroy(situation, isFromSkill: true);
}
}
else
{
Banish(situation);
}
}
else
{
Bounce(situation);
}
}
public bool CreateOtherEvolveParameterFromBattleCardBase(EnemyAI ai, BattleCardBase origin, BattleCardBase baseParamCard, AISituationInfo situation)
{
if (origin == null)
{
AIConsoleUtility.LogError("CreateOtherEvolvedCardParam() error!! param origin card is null");
return false;
}
if (baseParamCard == null)
{
AIConsoleUtility.LogError("CreateOtherEvolvedCardParam() error!! new param card is null!");
return false;
}
if (OtherEvolveParameter != null)
{
AIConsoleUtility.LogError("SetOtherEvolvedCardParam() error!! exist param data already!");
return false;
}
OtherEvolveParameter = new AIVirtualCardParameter(origin, baseParamCard, BuffRecorderCollection);
AIAttachedTagCollection attachedTags = TagCollectionContainer.AttachedTags;
AIRemovedTagCollection removedTagCollection = TagCollectionContainer.RemovedTagCollection;
TagCollectionContainer.RemoveAllTagWithUpdatingFieldCardList(this, SelfField, situation);
InitializeTags(ai.ParamQuery, attachedTags, removedTagCollection);
return true;
}
public void SetOtherEvolveParameterFromVirtualCard(AIVirtualCard source)
{
if (source.OtherEvolveParameter != null)
{
OtherEvolveParameter = source.OtherEvolveParameter;
BaseParameter = source.BaseParameter;
}
}
public void SetOtherEvolveParameterFromBuildParameter(ReferableVirtualCardBuildParameterCollection buildParameter)
{
if (buildParameter.OtherEvolveCardParameter != null)
{
OtherEvolveParameter = buildParameter.OtherEvolveCardParameter;
BaseParameter = buildParameter.BaseParameter;
}
}
public void AddCannotAttackInformation(AICannotAttackInformation info)
{
_cannotAttackInfoList = AIParamQuery.AddElementToList(info, _cannotAttackInfoList);
}
public void CopyCannotAttackInfoList(AIVirtualCard sourceCard)
{
_cannotAttackInfoList = AIParamQuery.CloneList(sourceCard._cannotAttackInfoList);
}
public void RemoveCannotAttackInformation(AICannotAttackInformation info)
{
if (_cannotAttackInfoList == null || _cannotAttackInfoList.Count <= 0)
{
return;
}
for (int num = _cannotAttackInfoList.Count - 1; num >= 0; num--)
{
if (_cannotAttackInfoList[num].IsEqual(info))
{
_cannotAttackInfoList.RemoveAt(num);
break;
}
}
}
public bool IsCannotAttackByTag(AIVirtualAttackInfo situation)
{
if (_cannotAttackInfoList == null || _cannotAttackInfoList.Count <= 0)
{
return false;
}
for (int i = 0; i < _cannotAttackInfoList.Count; i++)
{
if (_cannotAttackInfoList[i].IsCannotAttack(_field, situation))
{
return true;
}
}
return false;
}
public virtual ulong GetHash()
{
if (IsDead && !IsLeader)
{
return 0uL;
}
ulong num = 0uL;
num += (ulong)((long)Attack * 6337L);
num += (ulong)((long)Life * 11383L);
num += (ulong)((long)DefLife * 173L);
num += (ulong)((long)EvolutionAttack * 1488017L);
num += (ulong)((long)EvolutionLife * 937477L);
num += (ulong)((long)Cost * 14401L);
num += PRIME_NUMBERS_FOR_CLAN[(int)Clan % PRIME_NUMBERS_FOR_CLAN.Length];
num += (ulong)((long)SpellboostCount * 8389L);
num += (ulong)((long)WhiteRitualCount * 3571L);
if (_tribeList != null)
{
for (int i = 0; i < _tribeList.Count; i++)
{
num += PRIME_NUMBERS_FOR_TRIBE[(int)_tribeList[i] % PRIME_NUMBERS_FOR_TRIBE.Length];
}
}
num += TagCollectionContainer.GetHash(this) * 5237;
bool flag = false;
if (!IsLeader && AIData != null)
{
flag = true;
}
if (FusionIngredients != null)
{
num += FusionIngredients.GetHash();
}
if (IsOnField)
{
num += (ulong)((long)AttackableCount * 557L);
num += (ulong)((long)ChantCount * 5683L);
num += (ulong)((long)ReferringSelfCount * 558869L);
num += BarrierInfoCollection.GetHash();
if (flag)
{
num += (ulong)((long)AIData.BattleBonusExpr.Hash * 761L);
}
if (IsAlly)
{
num += (ulong)(IsFirstTurn ? 191 : 19);
if (IsAttackable(EnemyAI.EmptyPlayPtn))
{
num = ((!AIAttackSimulationUtility.IsAttackPossible(_field, AttackLeaderSituation)) ? (num * 37) : (num * 151));
}
num *= 11;
}
num *= (ulong)(IsUnit ? 103 : 1);
num *= (ulong)(IsEvolution ? 59 : 1);
num *= (ulong)(IsGetOn ? 577 : 1);
num *= (ulong)(IsPreviousTurnAttacked ? 9749 : 1);
num *= (ulong)(IsCantAttackAll ? 8089 : 1);
num *= (ulong)(IsNotConsumeEp ? 3527 : 1);
num *= (ulong)(IsLastword ? 809 : 1);
num *= (ulong)(IsSneak ? 811 : 1);
num *= (ulong)(IsKiller ? 821 : 1);
num *= (ulong)(IsDrain ? 823 : 1);
num *= (ulong)(IsRush ? 827 : 1);
num *= (ulong)(IsQuick ? 829 : 1);
num *= (ulong)(IsDestroyWhenAttack ? 839 : 1);
num *= (ulong)(IsGuard ? 853 : 1);
num *= (ulong)(IsIgnoreGuard ? 857 : 1);
num *= (ulong)(IsUntouchable ? 859 : 1);
num *= (ulong)(IsForceTargeting ? 863 : 1);
num *= (ulong)(IsUnbanishable ? 877 : 1);
}
if (IsInHand && flag)
{
num += (ulong)((long)AIData.PlayBonusExpr.Hash * 12007L);
num += (ulong)((long)AIData.BattleBonusExpr.Hash * 761L);
num += (ulong)((long)AIData.PriorityExpr.Hash * 101L);
}
return num;
}
}