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.
This commit is contained in:
26
SVSim.BattleEngine/Engine/Wizard/AIAccelerateInformation.cs
Normal file
26
SVSim.BattleEngine/Engine/Wizard/AIAccelerateInformation.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAccelerateInformation
|
||||
{
|
||||
public int Cost;
|
||||
|
||||
public int CardId;
|
||||
|
||||
public AIConditionExpressions Condition { get; private set; }
|
||||
|
||||
public void SetCondition(AIConditionExpressions cond)
|
||||
{
|
||||
Condition = cond;
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard owner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (Condition == null || Condition.IsEmpty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return Condition.CheckCondition(owner, playPtn, field, situation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIActivateCountTagArgument : AIScriptArgumentExpressions
|
||||
{
|
||||
private static readonly AIScriptTokenArgType[] LegalResetSideTypes = new AIScriptTokenArgType[4]
|
||||
{
|
||||
AIScriptTokenArgType.ALLY,
|
||||
AIScriptTokenArgType.OPPONENT,
|
||||
AIScriptTokenArgType.BOTH,
|
||||
AIScriptTokenArgType.NONE
|
||||
};
|
||||
|
||||
protected const int RESET_SIDE_TYPE_OFFSET = 3;
|
||||
|
||||
protected const int SKILL_OWNER_ID_OFFSET = 2;
|
||||
|
||||
protected const int SKILL_INDEX_OFFSET = 1;
|
||||
|
||||
public AIScriptTokenArgType ResetSideType { get; protected set; }
|
||||
|
||||
public int SkillOwnerId { get; protected set; }
|
||||
|
||||
public int SkillIndex { get; protected set; }
|
||||
|
||||
public int TurnMaxActivateCount { get; protected set; }
|
||||
|
||||
public AIActivateCountTagArgument(string text)
|
||||
: base(text)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitExpressions(string text)
|
||||
{
|
||||
base.InitExpressions(text);
|
||||
TurnMaxActivateCount = -1;
|
||||
if (_exprList[_exprList.Count - 1].TokenList[0] is AIScriptNumericToken aIScriptNumericToken)
|
||||
{
|
||||
SkillIndex = (int)aIScriptNumericToken.Value;
|
||||
ResetSideType = AIPlayTagInitializingUtility.CreateSingleArgType(_exprList[_exprList.Count - 3], LegalResetSideTypes);
|
||||
if (_exprList[_exprList.Count - 2].TokenList[0] is AIScriptIDToken aIScriptIDToken)
|
||||
{
|
||||
SkillOwnerId = aIScriptIDToken.ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
SkillOwnerId = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SkillIndex = 0;
|
||||
SkillOwnerId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
151
SVSim.BattleEngine/Engine/Wizard/AIActivateCounter.cs
Normal file
151
SVSim.BattleEngine/Engine/Wizard/AIActivateCounter.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIActivateCounter
|
||||
{
|
||||
private AIPlayTag _sourceTag;
|
||||
|
||||
private AIActivateCountTagArgument _sourceTagArgument;
|
||||
|
||||
public int ActivateCount { get; private set; }
|
||||
|
||||
public int TurnMaxActivateCount => _sourceTagArgument.TurnMaxActivateCount;
|
||||
|
||||
public AIScriptTokenArgType ResetSideType => _sourceTagArgument.ResetSideType;
|
||||
|
||||
public int SourceCardId => _sourceTagArgument.SkillOwnerId;
|
||||
|
||||
public int CounterIndex => _sourceTagArgument.SkillIndex;
|
||||
|
||||
public AIPlayTagType CounterType => _sourceTag.Type;
|
||||
|
||||
public AIActivateCounter(AIPlayTag tag, int count = 0)
|
||||
{
|
||||
ActivateCount = count;
|
||||
_sourceTag = tag;
|
||||
_sourceTagArgument = tag.ArgumentExpressions as AIActivateCountTagArgument;
|
||||
if (_sourceTagArgument == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIActivateCounter error!! _sourceTagArgument == null!!!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
public AIActivateCounter Clone()
|
||||
{
|
||||
return new AIActivateCounter(_sourceTag, ActivateCount);
|
||||
}
|
||||
|
||||
public void CheckConditionAndIncrement(AIVirtualCard owner, AISituationInfo situation, AIVirtualCard triggerCard)
|
||||
{
|
||||
AIVirtualField selfField = owner.SelfField;
|
||||
List<int> bestPlayPtn = selfField.BestPlayPtn;
|
||||
if (CanIncrement() && _sourceTag.CheckCondition(owner, bestPlayPtn, selfField, situation) && (!(_sourceTagArgument is AIFilteringActivateCountArgument aIFilteringActivateCountArgument) || (triggerCard != null && AIFilteringUtility.CheckMatchTargetFiltering(triggerCard, null, aIFilteringActivateCountArgument.Filters, bestPlayPtn, owner, situation))))
|
||||
{
|
||||
ActivateCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckConditionAndIncrement(AIVirtualCard owner, AISituationInfo situation, List<AIVirtualCard> triggerCardList)
|
||||
{
|
||||
AIVirtualField selfField = owner.SelfField;
|
||||
List<int> bestPlayPtn = selfField.BestPlayPtn;
|
||||
if (!CanIncrement() || !_sourceTag.CheckCondition(owner, bestPlayPtn, selfField, situation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool flag = false;
|
||||
if (_sourceTagArgument is AIFilteringActivateCountArgument aIFilteringActivateCountArgument)
|
||||
{
|
||||
if (triggerCardList == null || triggerCardList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < triggerCardList.Count; i++)
|
||||
{
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(triggerCardList[i], null, aIFilteringActivateCountArgument.Filters, bestPlayPtn, owner, situation))
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
ActivateCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanIncrement()
|
||||
{
|
||||
if (TurnMaxActivateCount == -1 || ActivateCount < TurnMaxActivateCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetCountIfMatched(int sourceCardId, int index)
|
||||
{
|
||||
if (SourceCardId == sourceCardId && CounterIndex == index)
|
||||
{
|
||||
return ActivateCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool IsSkillOccurred()
|
||||
{
|
||||
if (TurnMaxActivateCount == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ActivateCount >= TurnMaxActivateCount;
|
||||
}
|
||||
|
||||
public void Reset(bool isOwnerTurn)
|
||||
{
|
||||
switch (ResetSideType)
|
||||
{
|
||||
case AIScriptTokenArgType.BOTH:
|
||||
ActivateCount = 0;
|
||||
break;
|
||||
case AIScriptTokenArgType.ALLY:
|
||||
if (isOwnerTurn)
|
||||
{
|
||||
ActivateCount = 0;
|
||||
}
|
||||
break;
|
||||
case AIScriptTokenArgType.OPPONENT:
|
||||
if (!isOwnerTurn)
|
||||
{
|
||||
ActivateCount = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDuplicate(AIPlayTag tag)
|
||||
{
|
||||
return tag.Hash == _sourceTag.Hash;
|
||||
}
|
||||
|
||||
public bool InheritFromOtherCounter(AIActivateCounter counter)
|
||||
{
|
||||
if (IsDuplicate(counter))
|
||||
{
|
||||
ActivateCount = counter.ActivateCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsDuplicate(AIActivateCounter counter)
|
||||
{
|
||||
return counter.IsDuplicate(_sourceTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAfterDamageStopCollection : AITagPreprocessCollectionBase
|
||||
{
|
||||
public AIAfterDamageStopCollection Clone(List<AIVirtualCard> overrideCardList)
|
||||
{
|
||||
AIAfterDamageStopCollection aIAfterDamageStopCollection = new AIAfterDamageStopCollection();
|
||||
aIAfterDamageStopCollection.CopyInfoListWithReplaceCardReference(overrideCardList, base.InfoList);
|
||||
return aIAfterDamageStopCollection;
|
||||
}
|
||||
|
||||
public void SimulateActionAll(AIVirtualCard damagedCard)
|
||||
{
|
||||
List<AITagPreprocessInformationBase> list = null;
|
||||
for (int i = 0; i < base.InfoList.Count; i++)
|
||||
{
|
||||
if (base.InfoList[i] is AIAfterDamageStopInformation aIAfterDamageStopInformation && aIAfterDamageStopInformation.ExecuteReservedAction(damagedCard))
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIAfterDamageStopInformation, list);
|
||||
}
|
||||
}
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
base.InfoList.Remove(list[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AppendInfo(AITagPreprocessCreationOptionBase option)
|
||||
{
|
||||
AIAfterDamageStopInformation aIAfterDamageStopInformation = CreateInfo(option);
|
||||
if (aIAfterDamageStopInformation != null)
|
||||
{
|
||||
base.InfoList.Add(aIAfterDamageStopInformation);
|
||||
}
|
||||
}
|
||||
|
||||
private AIAfterDamageStopInformation CreateInfo(AITagPreprocessCreationOptionBase option)
|
||||
{
|
||||
if (option.PreprocessInfoType == AITagPreprocessInfoType.BARRIER_STOP)
|
||||
{
|
||||
return new AIBarrierAfterDamageStopInformation(option as AIBarrierStopPreprocessOption);
|
||||
}
|
||||
AIConsoleUtility.LogError("AITurnEndStopInfoContainer-CreateInfo(): Missing TurnEndInfo type");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void GetOverrideCardAndAppendCopyInfo(List<AIVirtualCard> overrideCardList, AITagPreprocessInformationBase originalInfo)
|
||||
{
|
||||
if (overrideCardList != null && overrideCardList.Count > 0)
|
||||
{
|
||||
AIVirtualCard overrideTargetCard = originalInfo.GetOverrideTargetCard(overrideCardList);
|
||||
if (overrideTargetCard != null)
|
||||
{
|
||||
AITagPreprocessCreationOptionBase option = originalInfo.CreateOptionInfoForOverride(overrideTargetCard);
|
||||
AppendInfo(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAfterDamageStopInformation : AITagPreprocessInformationBase
|
||||
{
|
||||
public AIAfterDamageStopInformation(AIVirtualCard card)
|
||||
: base(card)
|
||||
{
|
||||
}
|
||||
|
||||
public bool ExecuteReservedAction(AIVirtualCard damagedCard)
|
||||
{
|
||||
if (damagedCard.IsSameCard(base.TargetCard))
|
||||
{
|
||||
StopMethod();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void StopMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttachOperateMgrBattleEventCache
|
||||
{
|
||||
public Action<BattleCardBase, BattleCardBase, IEnumerable<BattleCardBase>> OnSetCardSuccessEvent;
|
||||
|
||||
public Func<BattleCardBase, VfxBase> OnSetCardExecutedEvent;
|
||||
|
||||
public Action<BattleCardBase, BattleCardBase, IEnumerable<BattleCardBase>> OnEvolveSuccessEvent;
|
||||
|
||||
public Func<BattleCardBase, VfxBase> OnEvolveCompleteEvent;
|
||||
|
||||
public Func<BattleCardBase, BattleCardBase, SkillProcessor, VfxBase> OnBeforeAttackEvent;
|
||||
|
||||
public Func<BattleCardBase, BattleCardBase, bool, VfxBase> OnAttackExecutedEvent;
|
||||
|
||||
public Action<BattleCardBase, IEnumerable<BattleCardBase>> OnBeforeFusionEvent;
|
||||
|
||||
public Func<BattleCardBase, VfxBase> OnAfterFusionEvent;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttachPlayerBattleEventCache
|
||||
{
|
||||
public Action<BattleCardBase, BattlePlayerBase.CEMETERY_TYPE, bool, SkillBase> AllyAddCemeteryEvent;
|
||||
|
||||
public Action<BattleCardBase, BattlePlayerBase.CEMETERY_TYPE, bool, SkillBase> OpponentAddCemeteryEvent;
|
||||
|
||||
public Action OpponentTurnStartCompleteEvent;
|
||||
|
||||
public Action AllyTurnStartCompleteEvent;
|
||||
|
||||
public Action AllySelfTurnEndEvent;
|
||||
|
||||
public Action OpponentSelfTurnEndEvent;
|
||||
}
|
||||
124
SVSim.BattleEngine/Engine/Wizard/AIAttachedTagCollection.cs
Normal file
124
SVSim.BattleEngine/Engine/Wizard/AIAttachedTagCollection.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttachedTagCollection
|
||||
{
|
||||
public List<AIAttachedTagInformation> AllList;
|
||||
|
||||
public List<AIPlayTag> RemovedTagCacheList { get; private set; }
|
||||
|
||||
public bool HasAnyTag
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AllList != null)
|
||||
{
|
||||
return AllList.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasRemovedInfoCaches
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RemovedTagCacheList != null)
|
||||
{
|
||||
return RemovedTagCacheList.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AIAttachedTagCollection()
|
||||
{
|
||||
AllList = null;
|
||||
}
|
||||
|
||||
public AIAttachedTagCollection Clone()
|
||||
{
|
||||
return new AIAttachedTagCollection
|
||||
{
|
||||
AllList = AIParamQuery.CloneList(AllList)
|
||||
};
|
||||
}
|
||||
|
||||
public void AddAttachedTagInformation(AIAttachedTagInformation info)
|
||||
{
|
||||
AllList = AIParamQuery.AddElementToList(info, AllList);
|
||||
}
|
||||
|
||||
public void RemoveMatchedAttachedTagInformation(bool ownerIsAlly, int ownerCardIndex, AIPlayTag removeingTag, bool needsInheritRemovedTags)
|
||||
{
|
||||
if (AllList == null || AllList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < AllList.Count; i++)
|
||||
{
|
||||
AIAttachedTagInformation aIAttachedTagInformation = AllList[i];
|
||||
if (aIAttachedTagInformation.IsReceiverAlly == ownerIsAlly && aIAttachedTagInformation.ReceiverIndex == ownerCardIndex && aIAttachedTagInformation.Tag.Hash == removeingTag.Hash)
|
||||
{
|
||||
AllList.RemoveAt(i);
|
||||
if (needsInheritRemovedTags)
|
||||
{
|
||||
RemovedTagCacheList = AIParamQuery.AddElementToList(removeingTag, RemovedTagCacheList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAllAttachedTagInformation(AISituationInfo situation)
|
||||
{
|
||||
if (AllList == null || AllList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool flag = situation?.IsLatestAction ?? false;
|
||||
while (AllList.Count > 0)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
AIAttachedTagInformation aIAttachedTagInformation = AllList[0];
|
||||
RemovedTagCacheList = AIParamQuery.AddElementToList(aIAttachedTagInformation.Tag, RemovedTagCacheList);
|
||||
}
|
||||
AllList.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void AttachTagToReceiver(AIVirtualCard receiver)
|
||||
{
|
||||
if (AllList == null || AllList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < AllList.Count; i++)
|
||||
{
|
||||
AIAttachedTagInformation aIAttachedTagInformation = AllList[i];
|
||||
if (aIAttachedTagInformation.IsReceiverAlly == receiver.IsAlly && aIAttachedTagInformation.ReceiverIndex == receiver.CardIndex)
|
||||
{
|
||||
receiver.TagCollectionContainer.AttachTag(aIAttachedTagInformation, receiver, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetAttachedTagCountFromId(int id)
|
||||
{
|
||||
if (!HasAnyTag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < AllList.Count; i++)
|
||||
{
|
||||
if (AllList[i].ProviderCardId == id)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
49
SVSim.BattleEngine/Engine/Wizard/AIAttachedTagInformation.cs
Normal file
49
SVSim.BattleEngine/Engine/Wizard/AIAttachedTagInformation.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttachedTagInformation
|
||||
{
|
||||
public AIPlayTag Tag { get; private set; }
|
||||
|
||||
public AIScriptTokenArgType RemoveTiming { get; private set; }
|
||||
|
||||
public int ProviderIndex { get; private set; }
|
||||
|
||||
public bool IsProviderAlly { get; private set; }
|
||||
|
||||
public int ProviderCardId { get; private set; }
|
||||
|
||||
public int ReceiverIndex { get; private set; }
|
||||
|
||||
public bool IsReceiverAlly { get; private set; }
|
||||
|
||||
public ulong Hash { get; private set; }
|
||||
|
||||
public AIAttachedTagInformation(AIPlayTag attachTag, AIScriptTokenArgType removeTiming, AIVirtualCard provider, AIVirtualCard receiver)
|
||||
{
|
||||
Tag = attachTag;
|
||||
RemoveTiming = removeTiming;
|
||||
ProviderIndex = provider.CardIndex;
|
||||
IsProviderAlly = provider.IsAlly;
|
||||
ProviderCardId = provider.BaseId;
|
||||
ReceiverIndex = receiver.CardIndex;
|
||||
IsReceiverAlly = receiver.IsAlly;
|
||||
Hash = GetHash();
|
||||
}
|
||||
|
||||
public AIAttachedTagInformation(AIPlayTag attachTag, AIScriptTokenArgType removeTiming, int providerCardId, int providerIndex, bool providerIsAlly, int receiverIndex, bool receiverIsAlly)
|
||||
{
|
||||
Tag = attachTag;
|
||||
RemoveTiming = removeTiming;
|
||||
ProviderIndex = providerIndex;
|
||||
IsProviderAlly = providerIsAlly;
|
||||
ProviderCardId = providerCardId;
|
||||
ReceiverIndex = receiverIndex;
|
||||
IsReceiverAlly = receiverIsAlly;
|
||||
Hash = GetHash();
|
||||
}
|
||||
|
||||
public ulong GetHash()
|
||||
{
|
||||
return (ulong)(((long)(Tag.Hash * 6323) + (long)RemoveTiming.GetHashCode() * 15187L + (long)ProviderIndex * 682009L + (long)ProviderCardId * 733L + (long)ReceiverIndex * 192149L) * (IsProviderAlly ? 641 : 43) * (IsReceiverAlly ? 503 : 4211));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttackPreCheckInformation
|
||||
{
|
||||
public float AttackBonus { get; private set; }
|
||||
|
||||
public AISimulationBuffInfoCollection BuffInfo { get; private set; }
|
||||
|
||||
public bool HasBuffInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BuffInfo != null)
|
||||
{
|
||||
return BuffInfo.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AIAttackPreCheckInformation(float attackBonus, AISimulationBuffInfoCollection buffInfo)
|
||||
{
|
||||
AttackBonus = attackBonus;
|
||||
BuffInfo = buffInfo;
|
||||
}
|
||||
|
||||
public void ApplyBuff(ulong tagHash, AIVirtualField field, List<int> playPtn, AIVirtualAttackInfo situation)
|
||||
{
|
||||
BuffInfo.ApplySingleBuff(tagHash, field, playPtn, situation);
|
||||
}
|
||||
|
||||
public bool HasPreCheckBuffInfo(AIPlayTag tag)
|
||||
{
|
||||
if (BuffInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return BuffInfo.HasBuffInfo(tag.Hash);
|
||||
}
|
||||
}
|
||||
103
SVSim.BattleEngine/Engine/Wizard/AIBarrierInfoBase.cs
Normal file
103
SVSim.BattleEngine/Engine/Wizard/AIBarrierInfoBase.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public abstract class AIBarrierInfoBase
|
||||
{
|
||||
public int BarrierAmount { get; protected set; }
|
||||
|
||||
public AIDamageType DamageType { get; protected set; }
|
||||
|
||||
public List<AIBarrierStopTiming> StopTimingList { get; protected set; }
|
||||
|
||||
public abstract AIBarrierType BarrierType { get; }
|
||||
|
||||
public ulong Hash { get; protected set; }
|
||||
|
||||
public AIBarrierInfoBase(int amount, AIDamageType damageType, AIBarrierStopTiming stopTiming = AIBarrierStopTiming.None)
|
||||
{
|
||||
BarrierAmount = amount;
|
||||
DamageType = damageType;
|
||||
if (stopTiming != AIBarrierStopTiming.None)
|
||||
{
|
||||
StopTimingList = new List<AIBarrierStopTiming> { stopTiming };
|
||||
}
|
||||
else
|
||||
{
|
||||
StopTimingList = null;
|
||||
}
|
||||
}
|
||||
|
||||
public AIBarrierInfoBase(int amount, AIDamageType damageType, List<AIBarrierStopTiming> stopTimingList)
|
||||
{
|
||||
BarrierAmount = amount;
|
||||
DamageType = damageType;
|
||||
StopTimingList = stopTimingList;
|
||||
}
|
||||
|
||||
public int GetDamageAmount(AIVirtualCard owner, int damage, bool isSkillDamage, bool isSpellDamage)
|
||||
{
|
||||
if (IsDamageType(isSkillDamage, isSpellDamage))
|
||||
{
|
||||
return CalcDamage(owner, damage);
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
||||
public bool IsDamageType(bool isSkillDamage, bool isSpellDamage)
|
||||
{
|
||||
if (DamageType == AIDamageType.All)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (DamageType == AIDamageType.Skill && (isSkillDamage || isSpellDamage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (DamageType == AIDamageType.Spell && isSpellDamage)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (DamageType == AIDamageType.Attack && !isSkillDamage && !isSpellDamage)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsMatchingStopTiming(AIBarrierStopTiming timing)
|
||||
{
|
||||
if (StopTimingList == null || StopTimingList.Count <= 0)
|
||||
{
|
||||
return timing == AIBarrierStopTiming.None;
|
||||
}
|
||||
for (int i = 0; i < StopTimingList.Count; i++)
|
||||
{
|
||||
if (timing == StopTimingList[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void UpdateHash()
|
||||
{
|
||||
Hash = AIBarrierSimulationUtility.CalculateBarrierInfoBaseHash(DamageType, BarrierType, StopTimingList);
|
||||
}
|
||||
|
||||
public bool IsDuplicate(AIBarrierType barrierType, AIDamageType damageType, int barrierAmount)
|
||||
{
|
||||
if ((long)BarrierAmount * (long)AIBarrierSimulationUtility.BARRIER_AMOUNT_HASH_COEFFICIENT + (long)DamageType * (long)AIBarrierSimulationUtility.DAMAGE_TYPE_HASH_COEFFICIENT + (long)BarrierType * (long)AIBarrierSimulationUtility.BARRIER_TYPE_HASH_COEFFICIENT == (long)Hash)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract AIBarrierInfoBase Clone();
|
||||
|
||||
public abstract bool IsShield();
|
||||
|
||||
protected abstract int CalcDamage(AIVirtualCard owner, int damage);
|
||||
}
|
||||
224
SVSim.BattleEngine/Engine/Wizard/AIBarrierInfoCollection.cs
Normal file
224
SVSim.BattleEngine/Engine/Wizard/AIBarrierInfoCollection.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBarrierInfoCollection
|
||||
{
|
||||
private int _shieldAllCount;
|
||||
|
||||
private int _shieldAttackCount;
|
||||
|
||||
private int _shieldSpellCount;
|
||||
|
||||
private int _shieldSkillCount;
|
||||
|
||||
public List<AIBarrierInfoBase> BarrierList { get; private set; }
|
||||
|
||||
public bool HasBarrier
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BarrierList != null)
|
||||
{
|
||||
return BarrierList.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int BarrierCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BarrierList == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return BarrierList.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasShieldAll => _shieldAllCount > 0;
|
||||
|
||||
public bool HasShieldAttack => _shieldAttackCount > 0;
|
||||
|
||||
public bool HasShieldSpell
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_shieldSpellCount <= 0)
|
||||
{
|
||||
return HasShieldSkill;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasShieldSkill => _shieldSkillCount > 0;
|
||||
|
||||
public AIBarrierInfoCollection Clone()
|
||||
{
|
||||
AIBarrierInfoCollection aIBarrierInfoCollection = new AIBarrierInfoCollection();
|
||||
if (HasBarrier)
|
||||
{
|
||||
for (int i = 0; i < BarrierList.Count; i++)
|
||||
{
|
||||
aIBarrierInfoCollection.AddBarrierInfo(BarrierList[i].Clone());
|
||||
}
|
||||
}
|
||||
return aIBarrierInfoCollection;
|
||||
}
|
||||
|
||||
public AIBarrierInfoCollection GetInheritanceForNewVirtualField()
|
||||
{
|
||||
AIBarrierInfoCollection aIBarrierInfoCollection = new AIBarrierInfoCollection();
|
||||
if (HasBarrier)
|
||||
{
|
||||
for (int i = 0; i < BarrierList.Count; i++)
|
||||
{
|
||||
AIBarrierInfoBase barrierInfo = BarrierList[i];
|
||||
aIBarrierInfoCollection.AddBarrierInfo(barrierInfo);
|
||||
}
|
||||
}
|
||||
return aIBarrierInfoCollection;
|
||||
}
|
||||
|
||||
public void GetBarrierInfoFromPreviousField(AIBarrierInfoCollection previousBarrierCollection)
|
||||
{
|
||||
if (HasBarrier)
|
||||
{
|
||||
for (int num = BarrierList.Count - 1; num >= 0; num--)
|
||||
{
|
||||
_ = BarrierList[num];
|
||||
BarrierList.RemoveAt(num);
|
||||
}
|
||||
}
|
||||
if (previousBarrierCollection.HasBarrier)
|
||||
{
|
||||
for (int i = 0; i < previousBarrierCollection.BarrierList.Count; i++)
|
||||
{
|
||||
AddBarrierInfo(previousBarrierCollection.BarrierList[i].Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetHash()
|
||||
{
|
||||
ulong num = 0uL;
|
||||
if (!HasBarrier)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
for (int i = 0; i < BarrierList.Count; i++)
|
||||
{
|
||||
num += BarrierList[i].Hash;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public void AddBarrierInfo(AIBarrierInfoBase barrierInfo)
|
||||
{
|
||||
BarrierList = AIParamQuery.AddElementToList(barrierInfo, BarrierList);
|
||||
IncrementHasShieldCount(barrierInfo);
|
||||
}
|
||||
|
||||
public void DepriveAllBarrierOfOneTiming(AIBarrierStopTiming timing)
|
||||
{
|
||||
if (!HasBarrier)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int num = BarrierList.Count - 1; num >= 0; num--)
|
||||
{
|
||||
AIBarrierInfoBase aIBarrierInfoBase = BarrierList[num];
|
||||
if (aIBarrierInfoBase.IsMatchingStopTiming(timing))
|
||||
{
|
||||
BarrierList.RemoveAt(num);
|
||||
DecrementHasShieldCount(aIBarrierInfoBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DepriveCertainBarrier(ulong depriveShieldHash, AIBarrierStopTiming timing)
|
||||
{
|
||||
if (!HasBarrier)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int num = BarrierList.Count - 1; num >= 0; num--)
|
||||
{
|
||||
AIBarrierInfoBase aIBarrierInfoBase = BarrierList[num];
|
||||
if (aIBarrierInfoBase.Hash == depriveShieldHash && aIBarrierInfoBase.IsMatchingStopTiming(timing))
|
||||
{
|
||||
BarrierList.RemoveAt(num);
|
||||
DecrementHasShieldCount(aIBarrierInfoBase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasDuplicateBarrier(AIBarrierType barrierType, AIDamageType damageType, int barrierAmount)
|
||||
{
|
||||
if (BarrierList == null || BarrierList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < BarrierList.Count; i++)
|
||||
{
|
||||
if (BarrierList[i].IsDuplicate(barrierType, damageType, barrierAmount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int CalcDamageAmount(AIVirtualCard owner, int damage, bool isSkillDamage, bool isSpellDamage)
|
||||
{
|
||||
if (BarrierList == null || BarrierList.Count <= 0)
|
||||
{
|
||||
return damage;
|
||||
}
|
||||
int num = damage;
|
||||
for (int i = 0; i < BarrierList.Count; i++)
|
||||
{
|
||||
num = BarrierList[i].GetDamageAmount(owner, num, isSkillDamage, isSpellDamage);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private void IncrementHasShieldCount(AIBarrierInfoBase appendInfo)
|
||||
{
|
||||
if (appendInfo != null && appendInfo.IsShield())
|
||||
{
|
||||
AppendShieldCount(appendInfo.DamageType, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void DecrementHasShieldCount(AIBarrierInfoBase removedInfo)
|
||||
{
|
||||
if (removedInfo != null && removedInfo.IsShield())
|
||||
{
|
||||
AppendShieldCount(removedInfo.DamageType, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendShieldCount(AIDamageType type, int appendValue)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AIDamageType.All:
|
||||
_shieldAllCount += appendValue;
|
||||
break;
|
||||
case AIDamageType.Attack:
|
||||
_shieldAttackCount += appendValue;
|
||||
break;
|
||||
case AIDamageType.Spell:
|
||||
_shieldSpellCount += appendValue;
|
||||
break;
|
||||
case AIDamageType.Skill:
|
||||
_shieldSkillCount += appendValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBarrierPseudoSimulationInfo
|
||||
{
|
||||
private AIBarrierInfoCollection _barrierCollection;
|
||||
|
||||
public AIVirtualCard Owner { get; private set; }
|
||||
|
||||
public AIBarrierPseudoSimulationInfo(AIVirtualCard owner)
|
||||
{
|
||||
Owner = owner;
|
||||
_barrierCollection = ((owner.BarrierInfoCollection != null) ? owner.BarrierInfoCollection.Clone() : new AIBarrierInfoCollection());
|
||||
}
|
||||
|
||||
public AIBarrierPseudoSimulationInfo(AIBarrierPseudoSimulationInfo info)
|
||||
{
|
||||
Owner = info.Owner;
|
||||
_barrierCollection = info._barrierCollection.Clone();
|
||||
}
|
||||
|
||||
public void AddBarrierInfo(AIBarrierInfoBase barrier)
|
||||
{
|
||||
_barrierCollection.AddBarrierInfo(barrier);
|
||||
}
|
||||
|
||||
public void DepriveBarrier(AIBarrierStopTiming timing)
|
||||
{
|
||||
_barrierCollection.DepriveAllBarrierOfOneTiming(timing);
|
||||
}
|
||||
|
||||
public void DepriveCertainBarrier(AIBarrierStopTiming timing, ulong barrierHash)
|
||||
{
|
||||
_barrierCollection.DepriveCertainBarrier(barrierHash, timing);
|
||||
}
|
||||
|
||||
public int SimulateDamageAmount(int damage, bool isSpellDamage, bool isSkillDamage = true)
|
||||
{
|
||||
int b = _barrierCollection.CalcDamageAmount(Owner, damage, isSkillDamage, isSpellDamage);
|
||||
return Mathf.Max(0, b);
|
||||
}
|
||||
}
|
||||
12
SVSim.BattleEngine/Engine/Wizard/AIBarrierStopTiming.cs
Normal file
12
SVSim.BattleEngine/Engine/Wizard/AIBarrierStopTiming.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIBarrierStopTiming
|
||||
{
|
||||
None,
|
||||
AllyTurnEnd,
|
||||
OpponentTurnEnd,
|
||||
WhenLeaveStop,
|
||||
AfterDamage,
|
||||
AllyTurnStart,
|
||||
OpponentTurnStart
|
||||
}
|
||||
10
SVSim.BattleEngine/Engine/Wizard/AIBarrierType.cs
Normal file
10
SVSim.BattleEngine/Engine/Wizard/AIBarrierType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIBarrierType
|
||||
{
|
||||
None,
|
||||
DamageCut,
|
||||
DamageClipping,
|
||||
DamageClippingLifeLowerLimit,
|
||||
Shield
|
||||
}
|
||||
16
SVSim.BattleEngine/Engine/Wizard/AIBattleInfoReceivedData.cs
Normal file
16
SVSim.BattleEngine/Engine/Wizard/AIBattleInfoReceivedData.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBattleInfoReceivedData
|
||||
{
|
||||
public AttachedSkillInfoReceiveDataCollection AttachedInfoReceiveCollection { get; private set; }
|
||||
|
||||
public AIBattleInfoReceivedData()
|
||||
{
|
||||
AttachedInfoReceiveCollection = new AttachedSkillInfoReceiveDataCollection();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
AttachedInfoReceiveCollection.Clear();
|
||||
}
|
||||
}
|
||||
56
SVSim.BattleEngine/Engine/Wizard/AIBuffExecutingInfo_old.cs
Normal file
56
SVSim.BattleEngine/Engine/Wizard/AIBuffExecutingInfo_old.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBuffExecutingInfo_old
|
||||
{
|
||||
public int AttackValue;
|
||||
|
||||
public int LifeValue;
|
||||
|
||||
public bool IsMultiplyAttack;
|
||||
|
||||
public bool IsMultiplyLife;
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
if (AttackValue == 0 && LifeValue == 0 && !IsMultiplyAttack)
|
||||
{
|
||||
return !IsMultiplyLife;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsBuff()
|
||||
{
|
||||
bool flag = ((!IsMultiplyAttack) ? (AttackValue >= 0) : (AttackValue >= 1));
|
||||
bool flag2 = ((!IsMultiplyLife) ? (LifeValue >= 0) : (LifeValue >= 1));
|
||||
return flag && flag2;
|
||||
}
|
||||
|
||||
public int GetExpectedAttackBuffValue(AIVirtualCard target)
|
||||
{
|
||||
return GetExpectedAttackBuffValue(target.Attack);
|
||||
}
|
||||
|
||||
public int GetExpectedAttackBuffValue(int attack)
|
||||
{
|
||||
if (IsMultiplyAttack)
|
||||
{
|
||||
return attack * AttackValue - attack;
|
||||
}
|
||||
return AttackValue;
|
||||
}
|
||||
|
||||
public int GetExpectedLifeBuffValue(AIVirtualCard target)
|
||||
{
|
||||
return GetExpectedLifeBuffValue(target.Life);
|
||||
}
|
||||
|
||||
public int GetExpectedLifeBuffValue(int life)
|
||||
{
|
||||
if (IsMultiplyLife)
|
||||
{
|
||||
return life * LifeValue - life;
|
||||
}
|
||||
return LifeValue;
|
||||
}
|
||||
}
|
||||
115
SVSim.BattleEngine/Engine/Wizard/AIBuffRecorderCollection.cs
Normal file
115
SVSim.BattleEngine/Engine/Wizard/AIBuffRecorderCollection.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBuffRecorderCollection
|
||||
{
|
||||
public class AIBuffRecorder : BuffCountInfo
|
||||
{
|
||||
public int SimulateAtkBuffValue;
|
||||
|
||||
public int SimulateLifeBuffValue;
|
||||
|
||||
public AIBuffRecorder(int turn, bool isSelfTurn, int atkBuff = 0, int lifeBuff = 0)
|
||||
: base(turn, isSelfTurn)
|
||||
{
|
||||
SimulateAtkBuffValue = atkBuff;
|
||||
SimulateLifeBuffValue = lifeBuff;
|
||||
}
|
||||
}
|
||||
|
||||
public List<AIBuffRecorder> RecorderList { get; private set; }
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RecorderList != null)
|
||||
{
|
||||
return RecorderList.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public AIBuffRecorderCollection()
|
||||
{
|
||||
RecorderList = null;
|
||||
}
|
||||
|
||||
public AIBuffRecorderCollection(List<BuffCountInfo> turnBuffCountList)
|
||||
{
|
||||
RecorderList = null;
|
||||
CreateRecorderListFromTurnBuffCountList(turnBuffCountList);
|
||||
}
|
||||
|
||||
private AIBuffRecorderCollection(AIBuffRecorderCollection original)
|
||||
{
|
||||
RecorderList = AIParamQuery.CloneList(original.RecorderList);
|
||||
}
|
||||
|
||||
public AIBuffRecorderCollection Clone()
|
||||
{
|
||||
return new AIBuffRecorderCollection(this);
|
||||
}
|
||||
|
||||
public void AddBuffRecord(int turn, bool isSelfTurn, int atkBuff = 0, int lifeBuff = 0)
|
||||
{
|
||||
AIBuffRecorder element = new AIBuffRecorder(turn, isSelfTurn, atkBuff, lifeBuff);
|
||||
RecorderList = AIParamQuery.AddElementToList(element, RecorderList);
|
||||
}
|
||||
|
||||
public int GetTurnBuffCount(int turn, bool isSelfTurn)
|
||||
{
|
||||
if (Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < RecorderList.Count; i++)
|
||||
{
|
||||
AIBuffRecorder aIBuffRecorder = RecorderList[i];
|
||||
if (aIBuffRecorder.Turn == turn && aIBuffRecorder.IsSelfTurn == isSelfTurn)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public (int atkSum, int lifeSum) GetSimulateBuff()
|
||||
{
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
if (0 < Count)
|
||||
{
|
||||
for (int i = 0; i < RecorderList.Count; i++)
|
||||
{
|
||||
AIBuffRecorder aIBuffRecorder = RecorderList[i];
|
||||
num += aIBuffRecorder.SimulateAtkBuffValue;
|
||||
num2 += aIBuffRecorder.SimulateLifeBuffValue;
|
||||
}
|
||||
}
|
||||
return (atkSum: num, lifeSum: num2);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
RecorderList.Clear();
|
||||
RecorderList = null;
|
||||
}
|
||||
|
||||
public void CreateRecorderListFromTurnBuffCountList(List<BuffCountInfo> turnBuffCountList)
|
||||
{
|
||||
if (turnBuffCountList != null && turnBuffCountList.Count > 0)
|
||||
{
|
||||
RecorderList = new List<AIBuffRecorder>();
|
||||
for (int i = 0; i < turnBuffCountList.Count; i++)
|
||||
{
|
||||
BuffCountInfo buffCountInfo = turnBuffCountList[i];
|
||||
AIBuffRecorder item = new AIBuffRecorder(buffCountInfo.Turn, !buffCountInfo.IsSelfTurn);
|
||||
RecorderList.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBuffWithTargetsInformation
|
||||
{
|
||||
private ulong _tagHash;
|
||||
|
||||
public List<AIVirtualCard> TargetList { get; private set; }
|
||||
|
||||
public AISimulationBuffInfo BuffInfo { get; private set; }
|
||||
|
||||
public AIBuffWithTargetsInformation(List<AIVirtualCard> targets, AISimulationBuffInfo buff, ulong hash)
|
||||
{
|
||||
TargetList = targets;
|
||||
BuffInfo = buff;
|
||||
_tagHash = hash;
|
||||
}
|
||||
|
||||
public void PseudoApplyBuffForSimpleAttack(AIVirtualCard currentAttacker, List<AIVirtualCard> attackerList, Tuple<int, int>[] statusArray)
|
||||
{
|
||||
if (TargetList == null || TargetList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < TargetList.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = TargetList[i];
|
||||
if (aIVirtualCard.IsAlly == currentAttacker.IsAlly)
|
||||
{
|
||||
int num = attackerList.IndexOf(aIVirtualCard);
|
||||
statusArray[num].first += BuffInfo.TotalAttackBuff;
|
||||
statusArray[num].second += BuffInfo.TotalLifeBuff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool VerifyArgumentAndApply(ulong hash, AIVirtualField field, List<int> playPtn, AIVirtualAttackInfo situation)
|
||||
{
|
||||
if (hash != _tagHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Apply(field, playPtn, situation);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Apply(AIVirtualField field, List<int> playPtn, AIVirtualAttackInfo situation)
|
||||
{
|
||||
int totalAttackBuff = BuffInfo.TotalAttackBuff;
|
||||
int totalLifeBuff = BuffInfo.TotalLifeBuff;
|
||||
AIBuffExecutingInfo_old buffInfo = new AIBuffExecutingInfo_old
|
||||
{
|
||||
AttackValue = totalAttackBuff,
|
||||
LifeValue = totalLifeBuff,
|
||||
IsMultiplyAttack = false,
|
||||
IsMultiplyLife = false
|
||||
};
|
||||
bool isTemp = BuffInfo.TempAttackBuff > 0 || BuffInfo.TempLifeBuff > 0;
|
||||
AIBuffSimulationUtility.BuffAll_old(TargetList, field, buffInfo, isTemp, playPtn, situation);
|
||||
}
|
||||
|
||||
public bool ContainsTarget(AIVirtualCard target)
|
||||
{
|
||||
if (TargetList == null || TargetList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < TargetList.Count; i++)
|
||||
{
|
||||
if (target.IsSameCard(TargetList[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsHashEqual(ulong hash)
|
||||
{
|
||||
return _tagHash == hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AICannotAttackInformation
|
||||
{
|
||||
private List<AIScriptTokenBase> _filters;
|
||||
|
||||
public AICannotAttackInformation(List<AIScriptTokenBase> filters)
|
||||
{
|
||||
_filters = filters;
|
||||
}
|
||||
|
||||
public bool IsEqual(AICannotAttackInformation info)
|
||||
{
|
||||
return IsSameFilterList(info._filters);
|
||||
}
|
||||
|
||||
private bool IsSameFilterList(List<AIScriptTokenBase> compare)
|
||||
{
|
||||
if (_filters == null || _filters.Count <= 0)
|
||||
{
|
||||
if (compare != null)
|
||||
{
|
||||
return compare.Count <= 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (_filters.Count != compare.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _filters.Count; i++)
|
||||
{
|
||||
if (!_filters[i].IsEqual(compare[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsCannotAttack(AIVirtualField field, AIVirtualAttackInfo situation)
|
||||
{
|
||||
if (situation.ActionType != AIOperationType.ATTACK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<AIVirtualCard> candidates = (situation.Actor.IsAlly ? field.CardListSet.EnemyClassAndInplayCards : field.CardListSet.AllyClassAndInplayCards);
|
||||
return AIFilteringUtility.CheckMatchTargetFiltering(situation.AttackTarget, candidates, _filters, field.BestPlayPtn, situation.Actor, situation);
|
||||
}
|
||||
}
|
||||
53
SVSim.BattleEngine/Engine/Wizard/AICannotPlayInformation.cs
Normal file
53
SVSim.BattleEngine/Engine/Wizard/AICannotPlayInformation.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AICannotPlayInformation
|
||||
{
|
||||
public AIVirtualCard Owner;
|
||||
|
||||
public List<AIScriptTokenBase> Filters;
|
||||
|
||||
public AICannotPlayInformation(AIVirtualCard owner, List<AIScriptTokenBase> filters)
|
||||
{
|
||||
Owner = owner;
|
||||
Filters = filters;
|
||||
}
|
||||
|
||||
public bool IsEqual(AIVirtualCard card, List<AIScriptTokenBase> filters)
|
||||
{
|
||||
if (!Owner.IsSameCard(card))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!IsSameFilterList(filters))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsSameFilterList(List<AIScriptTokenBase> compare)
|
||||
{
|
||||
if (Filters == null || Filters.Count <= 0)
|
||||
{
|
||||
if (compare != null)
|
||||
{
|
||||
return compare.Count <= 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (Filters.Count != compare.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < Filters.Count; i++)
|
||||
{
|
||||
if (!Filters[i].IsEqual(compare[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
70
SVSim.BattleEngine/Engine/Wizard/AICardData.cs
Normal file
70
SVSim.BattleEngine/Engine/Wizard/AICardData.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AICardData
|
||||
{
|
||||
private List<AIPlayTag> tagList;
|
||||
|
||||
public int CardID { get; private set; }
|
||||
|
||||
public int CardNum { get; private set; }
|
||||
|
||||
public List<AIPlayTag> TagList => tagList;
|
||||
|
||||
public AIPolishConvertedExpression BattleBonusExpr { get; set; }
|
||||
|
||||
public AIPolishConvertedExpression PlayBonusExpr { get; set; }
|
||||
|
||||
public AIPolishConvertedExpression PriorityExpr { get; set; }
|
||||
|
||||
private string BattleBonus { get; set; }
|
||||
|
||||
private string PlayBonus { get; set; }
|
||||
|
||||
private string Priority { get; set; }
|
||||
|
||||
public AICardData(AICardDataAsset asset)
|
||||
{
|
||||
CardID = asset.CardID;
|
||||
CardNum = asset.CardNum;
|
||||
BattleBonus = asset.BattleBonus;
|
||||
PlayBonus = asset.PlayBonus;
|
||||
Priority = asset.Priority;
|
||||
tagList = new List<AIPlayTag>();
|
||||
foreach (AIPlayTagAsset tag in asset.TagList)
|
||||
{
|
||||
AIPlayTag aIPlayTag = new AIPlayTag();
|
||||
if (aIPlayTag.InitFromTextAsset(tag))
|
||||
{
|
||||
tagList.Add(aIPlayTag);
|
||||
}
|
||||
else
|
||||
{
|
||||
aIPlayTag = null;
|
||||
}
|
||||
}
|
||||
BattleBonusExpr = new AIPolishConvertedExpression(asset.BattleBonus);
|
||||
PlayBonusExpr = new AIPolishConvertedExpression(asset.PlayBonus);
|
||||
PriorityExpr = new AIPolishConvertedExpression(asset.Priority);
|
||||
}
|
||||
|
||||
public void MergeCardData(AICardData data)
|
||||
{
|
||||
BattleBonus = data.BattleBonus;
|
||||
PlayBonus = data.PlayBonus;
|
||||
BattleBonusExpr = data.BattleBonusExpr;
|
||||
PlayBonusExpr = data.PlayBonusExpr;
|
||||
if (Priority == null || Priority == "")
|
||||
{
|
||||
Priority = data.Priority;
|
||||
PriorityExpr = data.PriorityExpr;
|
||||
}
|
||||
MergeTagFromAnotherData(data);
|
||||
}
|
||||
|
||||
public void MergeTagFromAnotherData(AICardData data)
|
||||
{
|
||||
tagList.InsertRange(0, data.TagList);
|
||||
}
|
||||
}
|
||||
58
SVSim.BattleEngine/Engine/Wizard/AICardDataAsset.cs
Normal file
58
SVSim.BattleEngine/Engine/Wizard/AICardDataAsset.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AICardDataAsset
|
||||
{
|
||||
public List<AIPlayTagAsset> TagList;
|
||||
|
||||
public int CardID { get; private set; }
|
||||
|
||||
public int CardNum { get; private set; }
|
||||
|
||||
public bool UseCommon { get; private set; }
|
||||
|
||||
public string CardName { get; private set; }
|
||||
|
||||
public string BattleBonus { get; private set; }
|
||||
|
||||
public string PlayBonus { get; private set; }
|
||||
|
||||
public string Priority { get; private set; }
|
||||
|
||||
public AICardDataAsset(string[] columns)
|
||||
{
|
||||
int num = 0;
|
||||
CardID = AIScriptParser.ParseInt(columns[num++]);
|
||||
if (columns[num++] == "〇")
|
||||
{
|
||||
UseCommon = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UseCommon = false;
|
||||
}
|
||||
CardName = columns[num++];
|
||||
CardNum = AIScriptParser.ParseInt(columns[num++]);
|
||||
BattleBonus = columns[num++];
|
||||
PlayBonus = columns[num++];
|
||||
Priority = columns[num++];
|
||||
TagList = new List<AIPlayTagAsset>();
|
||||
int num2 = (columns.Length - num - 1) / 3;
|
||||
for (int i = 0; i < num2; i++)
|
||||
{
|
||||
AIPlayTagAsset item = new AIPlayTagAsset
|
||||
{
|
||||
Type = columns[num++],
|
||||
Arg = columns[num++],
|
||||
Condition = columns[num++]
|
||||
};
|
||||
TagList.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSameCard(AICardDataAsset data)
|
||||
{
|
||||
return CardID == data.CardID;
|
||||
}
|
||||
}
|
||||
88
SVSim.BattleEngine/Engine/Wizard/AICardDataAssetSet.cs
Normal file
88
SVSim.BattleEngine/Engine/Wizard/AICardDataAssetSet.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AICardDataAssetSet
|
||||
{
|
||||
private class AICardDataAssetTemporaryRecord
|
||||
{
|
||||
public string[] Data { get; set; }
|
||||
|
||||
public int DiffFromLatestRotationPack { get; set; }
|
||||
}
|
||||
|
||||
public List<AICardDataAsset> Set { get; private set; }
|
||||
|
||||
public AICardDataAssetSet()
|
||||
{
|
||||
Set = new List<AICardDataAsset>();
|
||||
}
|
||||
|
||||
public void ConvertCsvTextToAsset(List<string[]> csv)
|
||||
{
|
||||
int latestRotationCardPack = GetRotationLatestCardPackNumber();
|
||||
Dictionary<int, AICardDataAssetTemporaryRecord> latestCardCandidateDic = new Dictionary<int, AICardDataAssetTemporaryRecord>();
|
||||
foreach (string[] item in csv)
|
||||
{
|
||||
if (IsRegister(item))
|
||||
{
|
||||
Set.Add(new AICardDataAsset(item));
|
||||
}
|
||||
}
|
||||
foreach (AICardDataAssetTemporaryRecord value2 in latestCardCandidateDic.Values)
|
||||
{
|
||||
Set.Add(new AICardDataAsset(value2.Data));
|
||||
}
|
||||
bool IsRegister(string[] cardData)
|
||||
{
|
||||
string text = cardData[0];
|
||||
int num;
|
||||
int key;
|
||||
if (text.Length > 9)
|
||||
{
|
||||
num = int.Parse(text.Substring(text.Length - 2));
|
||||
key = int.Parse(text.Substring(0, text.Length - 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
key = int.Parse(text);
|
||||
num = 0;
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (num < latestRotationCardPack)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cardData[0] = key.ToString();
|
||||
if (latestCardCandidateDic.TryGetValue(key, out var value))
|
||||
{
|
||||
int num2 = num - latestRotationCardPack;
|
||||
if (num2 < value.DiffFromLatestRotationPack)
|
||||
{
|
||||
latestCardCandidateDic[key] = new AICardDataAssetTemporaryRecord
|
||||
{
|
||||
Data = cardData,
|
||||
DiffFromLatestRotationPack = num2
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
latestCardCandidateDic.Add(key, new AICardDataAssetTemporaryRecord
|
||||
{
|
||||
Data = cardData,
|
||||
DiffFromLatestRotationPack = num - latestRotationCardPack
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetRotationLatestCardPackNumber()
|
||||
{
|
||||
return Data.Load.data.RotationLatestCardPackId % 100;
|
||||
}
|
||||
}
|
||||
14
SVSim.BattleEngine/Engine/Wizard/AICategory.cs
Normal file
14
SVSim.BattleEngine/Engine/Wizard/AICategory.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AICategory
|
||||
{
|
||||
ALL,
|
||||
ELF,
|
||||
ROYAL,
|
||||
WITCH,
|
||||
DRAGON,
|
||||
NECROMANCE,
|
||||
VAMPIRE,
|
||||
BISHOP,
|
||||
NEMESIS
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIChoiceTransformCostInformation
|
||||
{
|
||||
public AIPolishConvertedExpression Cost;
|
||||
|
||||
public AIConditionExpressions Condition { get; private set; }
|
||||
|
||||
public void SetCondition(AIConditionExpressions cond)
|
||||
{
|
||||
Condition = cond;
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard owner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (Condition == null || Condition.IsEmpty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return Condition.CheckCondition(owner, playPtn, field, situation);
|
||||
}
|
||||
}
|
||||
43
SVSim.BattleEngine/Engine/Wizard/AIConditionExpressions.cs
Normal file
43
SVSim.BattleEngine/Engine/Wizard/AIConditionExpressions.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIConditionExpressions
|
||||
{
|
||||
private AIPolishConvertedExpression _expr;
|
||||
|
||||
public List<int> ReferringIds { get; private set; }
|
||||
|
||||
public bool IsEmpty => _expr == null;
|
||||
|
||||
public AIConditionExpressions(string text)
|
||||
{
|
||||
if (!(text == ""))
|
||||
{
|
||||
_expr = new AIPolishConvertedExpression(text);
|
||||
ReferringIds = _expr.GetReferringIDLists();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
if (_expr == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!_expr.CheckCondition(tagOwner, playPtn, field, situation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsHoldingEVAL()
|
||||
{
|
||||
if (_expr != null)
|
||||
{
|
||||
return _expr.IsHoldingEVAL();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AICrystalizeInformation
|
||||
{
|
||||
public int Cost;
|
||||
|
||||
public int CardId;
|
||||
}
|
||||
17
SVSim.BattleEngine/Engine/Wizard/AICsvLoadingInfo.cs
Normal file
17
SVSim.BattleEngine/Engine/Wizard/AICsvLoadingInfo.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AICsvLoadingInfo
|
||||
{
|
||||
public int DeckId { get; private set; }
|
||||
|
||||
public int StyleId { get; private set; }
|
||||
|
||||
public int EmoteId { get; private set; }
|
||||
|
||||
public AICsvLoadingInfo(int deckId, int styleId, int emoteId)
|
||||
{
|
||||
DeckId = deckId;
|
||||
StyleId = styleId;
|
||||
EmoteId = emoteId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDamageModifierCollection
|
||||
{
|
||||
private List<AIDamageModifierInfo> _modifierList;
|
||||
|
||||
public AIDamageModifierCollection Clone(AIVirtualField field)
|
||||
{
|
||||
AIDamageModifierCollection aIDamageModifierCollection = new AIDamageModifierCollection();
|
||||
if (_modifierList != null)
|
||||
{
|
||||
for (int i = 0; i < _modifierList.Count; i++)
|
||||
{
|
||||
AIDamageModifierInfo aIDamageModifierInfo = _modifierList[i];
|
||||
AIVirtualCard aIVirtualCard = aIDamageModifierInfo.FindCloneTarget(field);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
aIDamageModifierCollection.AddDamageModifierInfo(aIDamageModifierInfo.Clone(field, aIVirtualCard));
|
||||
}
|
||||
}
|
||||
}
|
||||
return aIDamageModifierCollection;
|
||||
}
|
||||
|
||||
public int CalcModifiedDamage(AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIVirtualCard damageOwner, int baseDamage)
|
||||
{
|
||||
if (_modifierList == null || _modifierList.Count <= 0)
|
||||
{
|
||||
return baseDamage;
|
||||
}
|
||||
int num = baseDamage;
|
||||
for (int i = 0; i < _modifierList.Count; i++)
|
||||
{
|
||||
AIDamageModifierInfo aIDamageModifierInfo = _modifierList[i];
|
||||
if (aIDamageModifierInfo.IsLegalDamageOwner(damageOwner, playPtn, situation))
|
||||
{
|
||||
num = aIDamageModifierInfo.GetModifiedDamage(field, playPtn, situation, num);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public void AddDamageModifierInfo(AIDamageModifierInfo info)
|
||||
{
|
||||
_modifierList = AIParamQuery.AddElementToList(info, _modifierList);
|
||||
}
|
||||
|
||||
public void DepriveDamageModifierInfo(AIVirtualCard owner, int textHash)
|
||||
{
|
||||
if (_modifierList == null || _modifierList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < _modifierList.Count; i++)
|
||||
{
|
||||
if (_modifierList[i].IsMatch(owner, textHash))
|
||||
{
|
||||
_modifierList.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
SVSim.BattleEngine/Engine/Wizard/AIDamageModifierInfo.cs
Normal file
73
SVSim.BattleEngine/Engine/Wizard/AIDamageModifierInfo.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDamageModifierInfo
|
||||
{
|
||||
private int _textHash;
|
||||
|
||||
private AIVirtualCard _owner;
|
||||
|
||||
private List<AIScriptTokenBase> _damageOwnerFilter;
|
||||
|
||||
private AIScriptTokenArgType _calcType;
|
||||
|
||||
private AIPolishConvertedExpression _optionalDamageValue;
|
||||
|
||||
private static AIVirtualField.AIVirtualFieldSearchCardOption _searchOptionForClone = new AIVirtualField.AIVirtualFieldSearchCardOption
|
||||
{
|
||||
IsSearchFromDeck = false,
|
||||
IsOutputCannotFindError = false,
|
||||
IsSearchFromBeforeLatestActionDeck = false,
|
||||
OptionalSearchRange = BattleCardRealTargetInformation.TargetRange.Default
|
||||
};
|
||||
|
||||
public AIDamageModifierInfo(AIVirtualCard owner, List<AIScriptTokenBase> filters, AIScriptTokenArgType calcType, AIPolishConvertedExpression optionalDamage, int textHash)
|
||||
{
|
||||
_textHash = textHash;
|
||||
_owner = owner;
|
||||
_damageOwnerFilter = filters;
|
||||
_calcType = calcType;
|
||||
_optionalDamageValue = optionalDamage;
|
||||
}
|
||||
|
||||
public AIDamageModifierInfo Clone(AIVirtualField field, AIVirtualCard newOwner)
|
||||
{
|
||||
return new AIDamageModifierInfo(newOwner, _damageOwnerFilter, _calcType, _optionalDamageValue, _textHash);
|
||||
}
|
||||
|
||||
public bool IsLegalDamageOwner(AIVirtualCard damageOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return AIFilteringUtility.CheckMatchTargetFiltering(damageOwner, null, _damageOwnerFilter, playPtn, _owner, situation);
|
||||
}
|
||||
|
||||
public int GetModifiedDamage(AIVirtualField field, List<int> playPtn, AISituationInfo situation, int baseDamage)
|
||||
{
|
||||
int num = baseDamage;
|
||||
int num2 = (int)_optionalDamageValue.EvalArg(_owner, playPtn, field, situation);
|
||||
switch (_calcType)
|
||||
{
|
||||
case AIScriptTokenArgType.ADD:
|
||||
num += num2;
|
||||
break;
|
||||
case AIScriptTokenArgType.SET:
|
||||
num = num2;
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public bool IsMatch(AIVirtualCard owner, int textHash)
|
||||
{
|
||||
if (_owner.IsSameCard(owner))
|
||||
{
|
||||
return _textHash == textHash;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AIVirtualCard FindCloneTarget(AIVirtualField field)
|
||||
{
|
||||
return field.SearchVirtualCard(_owner, _searchOptionForClone);
|
||||
}
|
||||
}
|
||||
9
SVSim.BattleEngine/Engine/Wizard/AIDamageType.cs
Normal file
9
SVSim.BattleEngine/Engine/Wizard/AIDamageType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIDamageType
|
||||
{
|
||||
All,
|
||||
Attack,
|
||||
Skill,
|
||||
Spell
|
||||
}
|
||||
184
SVSim.BattleEngine/Engine/Wizard/AIDataLibrary.cs
Normal file
184
SVSim.BattleEngine/Engine/Wizard/AIDataLibrary.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDataLibrary
|
||||
{
|
||||
private readonly AIDeckData _basicDic;
|
||||
|
||||
private readonly AIDeckData _commonDic;
|
||||
|
||||
private readonly AIDeckData _allyCommonDic;
|
||||
|
||||
private readonly Dictionary<string, AIDeckData> _deckDic;
|
||||
|
||||
private readonly AIStyleData _commonStyle;
|
||||
|
||||
private readonly Dictionary<string, AIStyleData> _deckStyleDic;
|
||||
|
||||
private AISetUpData setupInfoBuf;
|
||||
|
||||
private readonly Dictionary<string, AIEmoteSet> emoteDic;
|
||||
|
||||
public AISetUpData SetupInfoBuf => setupInfoBuf;
|
||||
|
||||
public AIDataLibrary()
|
||||
{
|
||||
_basicDic = new AIDeckData();
|
||||
_commonDic = new AIDeckData();
|
||||
_allyCommonDic = new AIDeckData();
|
||||
_commonStyle = new AIStyleData();
|
||||
_deckStyleDic = new Dictionary<string, AIStyleData>();
|
||||
_deckDic = new Dictionary<string, AIDeckData>();
|
||||
emoteDic = new Dictionary<string, AIEmoteSet>();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_basicDic.Clear();
|
||||
_commonDic.Clear();
|
||||
_allyCommonDic.Clear();
|
||||
_deckDic.Clear();
|
||||
_commonStyle.Clear();
|
||||
_deckStyleDic.Clear();
|
||||
emoteDic.Clear();
|
||||
}
|
||||
|
||||
public void SaveBattleSetUpInfo(int classID, AI_LOGIC_LV logicLv, string deckName, string styleName, string emoteName, bool useEmote, bool useInnerEmote, int enemyAiID, List<int> specialAbilityList)
|
||||
{
|
||||
setupInfoBuf = new AISetUpData(classID, logicLv, deckName, styleName, emoteName, useEmote, useInnerEmote, enemyAiID, specialAbilityList);
|
||||
}
|
||||
|
||||
public AIStyleData CreateStyle(int enemyClassID, AIStyleData deckStyle)
|
||||
{
|
||||
AIStyleData aIStyleData = new AIStyleData(new List<AICategory>
|
||||
{
|
||||
AICategory.ALL,
|
||||
AIPolicyData.ConvertClassIDToCategory(enemyClassID)
|
||||
});
|
||||
aIStyleData.MixInStyle(_commonStyle);
|
||||
if (deckStyle != null)
|
||||
{
|
||||
aIStyleData.MixInStyle(deckStyle);
|
||||
}
|
||||
return aIStyleData;
|
||||
}
|
||||
|
||||
public void RegisterBasicData(AICardDataAsset asset)
|
||||
{
|
||||
_basicDic.RegisterCardData(asset);
|
||||
}
|
||||
|
||||
public bool RegisterCommonData(AICardDataAsset asset)
|
||||
{
|
||||
AICardData mergeData = _basicDic.SearchCardData(asset.CardID);
|
||||
return _commonDic.RegisterCardData(asset, mergeData);
|
||||
}
|
||||
|
||||
public bool RegisterAllyCommonData(AICardDataAsset asset)
|
||||
{
|
||||
AICardData mergeData = _basicDic.SearchCardData(asset.CardID);
|
||||
return _allyCommonDic.RegisterCardData(asset, mergeData);
|
||||
}
|
||||
|
||||
public void RegisterDeckToDeckDic(string deckName, List<AICardDataAsset> cardDataAssetList)
|
||||
{
|
||||
AIDeckData aIDeckData = new AIDeckData();
|
||||
for (int i = 0; i < cardDataAssetList.Count; i++)
|
||||
{
|
||||
AICardDataAsset aICardDataAsset = cardDataAssetList[i];
|
||||
int cardID = aICardDataAsset.CardID;
|
||||
bool useCommon = aICardDataAsset.UseCommon;
|
||||
AICardData mergeData = ((!useCommon) ? _basicDic.SearchCardData(cardID) : _allyCommonDic.SearchCardData(cardID));
|
||||
aIDeckData.RegisterCardData(aICardDataAsset, mergeData, useCommon);
|
||||
}
|
||||
RegisterDeck(deckName, aIDeckData);
|
||||
}
|
||||
|
||||
public bool RegisterDeck(string deckName, AIDeckData deck)
|
||||
{
|
||||
if (_deckDic.ContainsKey(deckName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_deckDic.Add(deckName, deck);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RegisterEmoteSet(string emoteSetName, AIEmoteSet emoteSet)
|
||||
{
|
||||
if (emoteDic.ContainsKey(emoteSetName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
emoteDic.Add(emoteSetName, emoteSet);
|
||||
return true;
|
||||
}
|
||||
|
||||
public AIDeckData SearchDeckData(string name)
|
||||
{
|
||||
if (!_deckDic.ContainsKey(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _deckDic[name];
|
||||
}
|
||||
|
||||
public AIStyleData SearchDeckStyle(string name)
|
||||
{
|
||||
if (!_deckStyleDic.ContainsKey(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _deckStyleDic[name];
|
||||
}
|
||||
|
||||
public AIEmoteSet SearchEmoteSet(string name)
|
||||
{
|
||||
if (!emoteDic.ContainsKey(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return emoteDic[name];
|
||||
}
|
||||
|
||||
public AIDeckData GetCommonDic()
|
||||
{
|
||||
return _commonDic;
|
||||
}
|
||||
|
||||
public AIDeckData GetAllyCommonDic()
|
||||
{
|
||||
return _allyCommonDic;
|
||||
}
|
||||
|
||||
public void RegisterCommonStyle(List<AIPolicyDataAsset> assetList)
|
||||
{
|
||||
_commonStyle.CreateFromAsset(assetList);
|
||||
}
|
||||
|
||||
public bool RegisterDeckStyle(string styleName, List<AIPolicyDataAsset> assetList)
|
||||
{
|
||||
if (_deckStyleDic.ContainsKey(styleName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AIStyleData aIStyleData = new AIStyleData();
|
||||
aIStyleData.CreateFromAsset(assetList);
|
||||
_deckStyleDic.Add(styleName, aIStyleData);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<int> GetAIDeckCardList(string deckname)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
foreach (AICardData value in GameMgr.GetIns().GetDataMgr().m_AIDataLibrary.SearchDeckData(deckname).CardDic.Values)
|
||||
{
|
||||
for (int i = 0; i < value.CardNum; i++)
|
||||
{
|
||||
list.Add(value.CardID);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
41
SVSim.BattleEngine/Engine/Wizard/AIDeckAcccessor.cs
Normal file
41
SVSim.BattleEngine/Engine/Wizard/AIDeckAcccessor.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDeckAcccessor
|
||||
{
|
||||
private AIDeckData commonDic;
|
||||
|
||||
private AIDeckData allyCommonDic;
|
||||
|
||||
private AIDeckData curDic;
|
||||
|
||||
public AIDeckAcccessor(AIDeckData _curDic, AIDeckData _commonDic, AIDeckData _allyCommonDic)
|
||||
{
|
||||
curDic = _curDic;
|
||||
commonDic = _commonDic;
|
||||
allyCommonDic = _allyCommonDic;
|
||||
}
|
||||
|
||||
private AICardData SearchAllyCardData(int card_id)
|
||||
{
|
||||
AICardData aICardData = null;
|
||||
if (curDic != null)
|
||||
{
|
||||
aICardData = curDic.SearchCardData(card_id);
|
||||
}
|
||||
if (aICardData == null)
|
||||
{
|
||||
aICardData = allyCommonDic.SearchCardData(card_id);
|
||||
}
|
||||
return aICardData;
|
||||
}
|
||||
|
||||
public AICardData SearchCardData(int cardId, bool isAlly)
|
||||
{
|
||||
AICardData aICardData = null;
|
||||
if (isAlly)
|
||||
{
|
||||
return SearchAllyCardData(cardId);
|
||||
}
|
||||
return commonDic.SearchCardData(cardId);
|
||||
}
|
||||
}
|
||||
52
SVSim.BattleEngine/Engine/Wizard/AIDeckData.cs
Normal file
52
SVSim.BattleEngine/Engine/Wizard/AIDeckData.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDeckData
|
||||
{
|
||||
private Dictionary<int, AICardData> cardDic;
|
||||
|
||||
public Dictionary<int, AICardData> CardDic => cardDic;
|
||||
|
||||
public AIDeckData()
|
||||
{
|
||||
cardDic = new Dictionary<int, AICardData>();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
cardDic.Clear();
|
||||
}
|
||||
|
||||
public bool RegisterCardData(AICardDataAsset asset, AICardData mergeData = null, bool isMergeDefaultParameter = false)
|
||||
{
|
||||
if (cardDic.ContainsKey(asset.CardID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AICardData aICardData = new AICardData(asset);
|
||||
if (mergeData != null)
|
||||
{
|
||||
if (isMergeDefaultParameter)
|
||||
{
|
||||
aICardData.MergeCardData(mergeData);
|
||||
}
|
||||
else
|
||||
{
|
||||
aICardData.MergeTagFromAnotherData(mergeData);
|
||||
}
|
||||
}
|
||||
cardDic.Add(asset.CardID, aICardData);
|
||||
return true;
|
||||
}
|
||||
|
||||
public AICardData SearchCardData(int card_id)
|
||||
{
|
||||
AICardData value = null;
|
||||
if (CardDic.TryGetValue(card_id, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
33
SVSim.BattleEngine/Engine/Wizard/AIDeckFileNameList.cs
Normal file
33
SVSim.BattleEngine/Engine/Wizard/AIDeckFileNameList.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDeckFileNameList
|
||||
{
|
||||
private const int DECK_ID_INDEX = 0;
|
||||
|
||||
private const int FILE_NAME_INDEX = 1;
|
||||
|
||||
private readonly Dictionary<int, string> _dataTable = new Dictionary<int, string>();
|
||||
|
||||
public AIDeckFileNameList(List<string[]> csvData)
|
||||
{
|
||||
foreach (string[] csvDatum in csvData)
|
||||
{
|
||||
int key = int.Parse(csvDatum[0]);
|
||||
string value = csvDatum[1];
|
||||
_dataTable.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFileName(int id)
|
||||
{
|
||||
return _dataTable[id];
|
||||
}
|
||||
|
||||
public List<string> GetFileNameList()
|
||||
{
|
||||
return _dataTable.Values.ToList();
|
||||
}
|
||||
}
|
||||
39
SVSim.BattleEngine/Engine/Wizard/AIDiscardInfo.cs
Normal file
39
SVSim.BattleEngine/Engine/Wizard/AIDiscardInfo.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDiscardInfo
|
||||
{
|
||||
public AIVirtualCard Owner;
|
||||
|
||||
public List<AIVirtualCard> TargetList;
|
||||
|
||||
public bool IsSuccess;
|
||||
|
||||
public bool IsNGByAI;
|
||||
|
||||
public bool IsValuable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsSuccess && !IsNGByAI && TargetList != null)
|
||||
{
|
||||
return TargetList.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AIDiscardInfo(AIVirtualCard owner, bool isSuccess, List<AIVirtualCard> targets)
|
||||
{
|
||||
Owner = owner;
|
||||
IsSuccess = isSuccess;
|
||||
TargetList = targets;
|
||||
IsNGByAI = false;
|
||||
}
|
||||
|
||||
public void MarkAsNG()
|
||||
{
|
||||
IsNGByAI = true;
|
||||
}
|
||||
}
|
||||
50
SVSim.BattleEngine/Engine/Wizard/AIDummyDeckContainer.cs
Normal file
50
SVSim.BattleEngine/Engine/Wizard/AIDummyDeckContainer.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDummyDeckContainer
|
||||
{
|
||||
private List<DeckVirtualCard> _allyDummyDeck;
|
||||
|
||||
private List<DeckVirtualCard> _enemyDummyDeck;
|
||||
|
||||
public AIDummyDeckContainer()
|
||||
{
|
||||
_allyDummyDeck = new List<DeckVirtualCard>();
|
||||
_enemyDummyDeck = new List<DeckVirtualCard>();
|
||||
}
|
||||
|
||||
public AIDummyDeckContainer Clone(AIVirtualField field)
|
||||
{
|
||||
AIDummyDeckContainer aIDummyDeckContainer = new AIDummyDeckContainer();
|
||||
CopyDeck(_allyDummyDeck, aIDummyDeckContainer._allyDummyDeck, field);
|
||||
CopyDeck(_enemyDummyDeck, aIDummyDeckContainer._enemyDummyDeck, field);
|
||||
return aIDummyDeckContainer;
|
||||
}
|
||||
|
||||
private void CopyDeck(List<DeckVirtualCard> srcDeck, List<DeckVirtualCard> dstDeck, AIVirtualField field)
|
||||
{
|
||||
for (int i = 0; i < srcDeck.Count; i++)
|
||||
{
|
||||
dstDeck.Add(new DeckVirtualCard(srcDeck[i], field));
|
||||
}
|
||||
}
|
||||
|
||||
public List<DeckVirtualCard> GetDeck(bool isAlly)
|
||||
{
|
||||
if (!isAlly)
|
||||
{
|
||||
return _enemyDummyDeck;
|
||||
}
|
||||
return _allyDummyDeck;
|
||||
}
|
||||
|
||||
public void AppendDummyCard(DeckVirtualCard card, bool isAlly)
|
||||
{
|
||||
List<DeckVirtualCard> deck = GetDeck(isAlly);
|
||||
if (!deck.Contains(card))
|
||||
{
|
||||
deck.Add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
SVSim.BattleEngine/Engine/Wizard/AIEmoteCmd.cs
Normal file
55
SVSim.BattleEngine/Engine/Wizard/AIEmoteCmd.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteCmd
|
||||
{
|
||||
public ClassCharaPrm.EmotionType emoteType { get; set; }
|
||||
|
||||
public int ID { get; set; }
|
||||
|
||||
public int CategoryKey { get; set; }
|
||||
|
||||
public int faceID { get; set; }
|
||||
|
||||
public int motionID { get; set; }
|
||||
|
||||
public string voiceID { get; set; }
|
||||
|
||||
public string textID { get; set; }
|
||||
|
||||
public bool isAI { get; set; }
|
||||
|
||||
public AIEmoteCmd()
|
||||
{
|
||||
emoteType = ClassCharaPrm.EmotionType.GREET;
|
||||
ID = 0;
|
||||
CategoryKey = 0;
|
||||
faceID = 0;
|
||||
motionID = 0;
|
||||
voiceID = "";
|
||||
textID = "";
|
||||
isAI = true;
|
||||
}
|
||||
|
||||
public AIEmoteCmd(AIEmoteDataAsset asset)
|
||||
{
|
||||
ID = asset.ID;
|
||||
CategoryKey = asset.Category;
|
||||
faceID = asset.FaceID;
|
||||
motionID = asset.MotionID;
|
||||
voiceID = asset.VoiceID;
|
||||
textID = asset.TextID;
|
||||
isAI = true;
|
||||
}
|
||||
|
||||
public AIEmoteCmd(ClassCharaPrm.EmotionType _emoteType)
|
||||
{
|
||||
emoteType = _emoteType;
|
||||
ID = 0;
|
||||
CategoryKey = 0;
|
||||
faceID = 0;
|
||||
motionID = 0;
|
||||
voiceID = "";
|
||||
textID = "";
|
||||
isAI = true;
|
||||
}
|
||||
}
|
||||
22
SVSim.BattleEngine/Engine/Wizard/AIEmoteCmdType.cs
Normal file
22
SVSim.BattleEngine/Engine/Wizard/AIEmoteCmdType.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIEmoteCmdType
|
||||
{
|
||||
ON_FIRST_TURN,
|
||||
ON_ITERATION_START,
|
||||
ON_ALLY_TURN_START,
|
||||
ON_OPPONENT_TURN_START,
|
||||
ON_ALLY_TURN_END,
|
||||
ON_OPPONENT_TURN_END,
|
||||
ON_ALLY_ATTACK,
|
||||
ON_OPPONENT_ATTACK,
|
||||
ON_ALLY_EVOLUTION,
|
||||
ON_RECEIVE,
|
||||
ON_CARD_DESTROY,
|
||||
ON_CARD_PLAY_ALLY,
|
||||
ON_CARD_PLAY_OPPONENT,
|
||||
ON_DEBUG_SEARCH_ID,
|
||||
ON_DEBUG_SEARCH_CATEGORY,
|
||||
ON_LEADER_DAMAGED,
|
||||
ON_PLAYER_LEADER_DAMAGED
|
||||
}
|
||||
507
SVSim.BattleEngine/Engine/Wizard/AIEmoteCtrl.cs
Normal file
507
SVSim.BattleEngine/Engine/Wizard/AIEmoteCtrl.cs
Normal file
@@ -0,0 +1,507 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Wizard.Battle.Card;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteCtrl : IAIEmoteCtrl
|
||||
{
|
||||
public static AIPlayTagType[] EMOTE_TAG_TYPES = new AIPlayTagType[6]
|
||||
{
|
||||
AIPlayTagType.EmoteOnPlay,
|
||||
AIPlayTagType.EmoteOnAtk,
|
||||
AIPlayTagType.EmoteOnEvo,
|
||||
AIPlayTagType.EmoteOnDestroy,
|
||||
AIPlayTagType.ForceEmoteOnDestroy,
|
||||
AIPlayTagType.EmoteOnTurnEnd
|
||||
};
|
||||
|
||||
private EnemyAI AI;
|
||||
|
||||
private bool _isEmoOnDestroyPlayed;
|
||||
|
||||
public AIEmoteCtrl(EnemyAI ai)
|
||||
{
|
||||
AI = ai;
|
||||
}
|
||||
|
||||
public void SetUpEmoteEvent(BattlePlayerBase self, BattlePlayerBase opponent, OperateMgr operateManager)
|
||||
{
|
||||
opponent.OnTurnStartBeforeDraw += (SkillProcessor arg) => GetEmoteWithTurnStartSimulate(isAllyTurnStart: false);
|
||||
self.OnTurnStartBeforeDraw += delegate
|
||||
{
|
||||
AI.EmoteMng.ResetOpponentTurnEmoteFlag();
|
||||
return GetEmoteWithTurnStartSimulate(isAllyTurnStart: true);
|
||||
};
|
||||
Func<SkillProcessor, VfxBase> func = null;
|
||||
func = delegate
|
||||
{
|
||||
VfxBase emote = AI.GetEmote(AIEmoteCmdType.ON_OPPONENT_TURN_END);
|
||||
ImmediateVfxMgr.GetInstance().Register(emote);
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
opponent.OnTurnEnd += func;
|
||||
self.OnAddCemeteryEvent += delegate(BattleCardBase card, BattlePlayerBase.CEMETERY_TYPE cemeteryType, bool isOpen, SkillBase skill)
|
||||
{
|
||||
if (cemeteryType == BattlePlayerBase.CEMETERY_TYPE.NORMAL && !(card is NullBattleCard) && !(card is IVirtualBattleCard) && card.SelfBattlePlayer.ClassAndInPlayCardList.Contains(card))
|
||||
{
|
||||
AIUnknownAction situation = new AIUnknownAction(AI.CurrentVirtualField.SearchVirtualCard(card));
|
||||
SequentialVfxPlayer sequential = SequentialVfxPlayer.Create();
|
||||
VfxBase emote = AI.GetEmote(AIEmoteCmdType.ON_CARD_DESTROY, situation);
|
||||
sequential.Register(emote);
|
||||
if (emote != NullVfx.GetInstance())
|
||||
{
|
||||
_isEmoOnDestroyPlayed = true;
|
||||
card.OnDestroy += (BattleCardBase destroyCard, SkillProcessor skillProcessor) => sequential;
|
||||
}
|
||||
}
|
||||
};
|
||||
self.Class.OnDamageAfter += (SkillProcessor skillProcessorOneTime) => (self.Class.Life <= 0) ? NullVfx.GetInstance() : AI.GetEmote(AIEmoteCmdType.ON_LEADER_DAMAGED);
|
||||
opponent.Class.OnDamageAfter += (SkillProcessor skillProcessorOneTime) => (opponent.Class.Life <= 0) ? NullVfx.GetInstance() : AI.GetEmote(AIEmoteCmdType.ON_PLAYER_LEADER_DAMAGED);
|
||||
operateManager.OnBeforeSetCard += delegate
|
||||
{
|
||||
AI.EmoteMng.EvalFieldOnBeforeSetCard();
|
||||
};
|
||||
operateManager.OnSetCardExecuted += delegate(BattleCardBase card)
|
||||
{
|
||||
AIUnknownAction situation = new AIUnknownAction(new AIVirtualCard(card, AI.CurrentVirtualField));
|
||||
return AI.GetEmote(AIEmoteCmdType.ON_CARD_PLAY_OPPONENT, situation);
|
||||
};
|
||||
operateManager.OnBeforeAttack += delegate
|
||||
{
|
||||
AI.EmoteMng.EvalFieldOnBeforeAttack();
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
operateManager.OnAttackExecuted += (BattleCardBase attacker, BattleCardBase target, bool needAttack) => AI.GetEmote(AIEmoteCmdType.ON_OPPONENT_ATTACK);
|
||||
}
|
||||
|
||||
private VfxBase GetEmoteWithTurnStartSimulate(bool isAllyTurnStart)
|
||||
{
|
||||
AIVirtualField aIVirtualField = new AIVirtualField((AI.BeforeLatestActionField != null) ? AI.BeforeLatestActionField : AI.CurrentVirtualField);
|
||||
if (aIVirtualField.AllyTurnCount > 0 || aIVirtualField.EnemyTurnCount > 0)
|
||||
{
|
||||
AIVirtualTurnEndSimulator.TurnEnd(new AIVirtualTurnEndInfo(isAllyTurnStart ? aIVirtualField.EnemyClass : aIVirtualField.AllyClass), aIVirtualField);
|
||||
}
|
||||
AIVirtualTurnStartInfo situation = new AIVirtualTurnStartInfo(isAllyTurnStart ? aIVirtualField.AllyClass : aIVirtualField.EnemyClass);
|
||||
aIVirtualField.TurnStartFieldProcess(situation);
|
||||
return AI.GetEmote(isAllyTurnStart ? AIEmoteCmdType.ON_ALLY_TURN_START : AIEmoteCmdType.ON_OPPONENT_TURN_START, situation);
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentEmotion(ClassCharaPrm.EmotionType emoteType)
|
||||
{
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (AI.IsThisTurnEmotePlayed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!AI.EmoteQuery.UseInnerEmote)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ClassCharaPrm.EmotionType replyEmote = ClassCharaPrm.EmotionType.NULL;
|
||||
if (AI.EmoteMng.IsReplyAllowed(emoteType, ref replyEmote))
|
||||
{
|
||||
return new AIEmoteCmd(replyEmote);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyTurnStart(AISituationInfo situation)
|
||||
{
|
||||
AI.EmoteMng.SetUpOnAllyTurnStart();
|
||||
AI.EmoteMng.EvalFieldOnTurnStart();
|
||||
_isEmoOnDestroyPlayed = false;
|
||||
int emoteOnTurnStart = AI.StyleQuery.GetEmoteOnTurnStart(isAllyTurn: true, situation.Actor.SelfField);
|
||||
if (emoteOnTurnStart >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnStart);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentTurnStart(AISituationInfo situation)
|
||||
{
|
||||
AI.EmoteMng.EvalFieldOnOpponentTurnStart();
|
||||
_isEmoOnDestroyPlayed = false;
|
||||
AIVirtualField selfField = situation.Actor.SelfField;
|
||||
int emoteOnTurnStart = AI.StyleQuery.GetEmoteOnTurnStart(isAllyTurn: false, selfField);
|
||||
if (emoteOnTurnStart >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnStart);
|
||||
}
|
||||
emoteOnTurnStart = AI.StyleQuery.GetPlayerEmoteOnTurnStart(selfField);
|
||||
if (emoteOnTurnStart >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnStart, isAlly: false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyTurnEnd()
|
||||
{
|
||||
if (AI.IsTurnEndLethal)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(22);
|
||||
}
|
||||
for (int i = 0; i < AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards.Count; i++)
|
||||
{
|
||||
int emoteOnTurnEndCategory = AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards[i].GetEmoteOnTurnEndCategory(isAllyTurnEnd: true);
|
||||
if (emoteOnTurnEndCategory >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEndCategory);
|
||||
}
|
||||
}
|
||||
int emoteOnTurnEnd = AI.StyleQuery.GetEmoteOnTurnEnd(isAllyTurn: true);
|
||||
if (emoteOnTurnEnd >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEnd);
|
||||
}
|
||||
emoteOnTurnEnd = AI.StyleQuery.GetPlayerEmoteOnTurnEnd(isPlayerTurn: false);
|
||||
if (emoteOnTurnEnd >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEnd, isAlly: false);
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(13);
|
||||
}
|
||||
if (AI.EmoteMng.IsHuntDown())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(14);
|
||||
}
|
||||
if (AI.IsRoyal() && AI.EmoteMng.IsEnoughUnit())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(102);
|
||||
}
|
||||
if (AI.IsNecromancer() && AI.EmoteMng.IsEnoughGrave())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(501);
|
||||
}
|
||||
if (AI.EmoteMng.IsAwaking(1))
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(401);
|
||||
}
|
||||
if (AI.EmoteMng.IsUnexpectedBattle())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(11);
|
||||
}
|
||||
if (AI.ALLY.InPlayCards.Count() < 5 && AI.EmoteMng.IsRemainTooPP())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(15);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentTurnEnd()
|
||||
{
|
||||
if (AI.EmoteMng.IsOpponentTurnEmoteOccured)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards.Count; i++)
|
||||
{
|
||||
int emoteOnTurnEndCategory = AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards[i].GetEmoteOnTurnEndCategory(isAllyTurnEnd: false);
|
||||
if (emoteOnTurnEndCategory >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEndCategory);
|
||||
}
|
||||
}
|
||||
int emoteOnTurnEnd = AI.StyleQuery.GetEmoteOnTurnEnd(isAllyTurn: false);
|
||||
if (emoteOnTurnEnd >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEnd);
|
||||
}
|
||||
emoteOnTurnEnd = AI.StyleQuery.GetPlayerEmoteOnTurnEnd(isPlayerTurn: true);
|
||||
if (emoteOnTurnEnd >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnTurnEnd, isAlly: false);
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (AI.EmoteMng.IsOpponentEarnGreatMerit())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(33);
|
||||
}
|
||||
if (AI.OPPONENT.InPlayCards.Count() < 5 && AI.EmoteMng.IsOpponentRemainTooPP())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(31);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnIterationStart()
|
||||
{
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
float num = AI.EmoteMng.EvalDisplacement_PlayedValue();
|
||||
AI.EmoteMng.ResetLastOpr();
|
||||
if (num < -4f)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (num > 4f)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnCardPlay(AISituationInfo situation)
|
||||
{
|
||||
if (situation == null || situation.Actor == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int num = AI.CurrentVirtualField.AllyHandCards.FindIndex((AIVirtualCard c) => c.IsSameCard(situation.Actor));
|
||||
if (num < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualField aIVirtualField = new AIVirtualField(AI.CurrentVirtualField)
|
||||
{
|
||||
BestPlayPtn = new List<int> { num }
|
||||
};
|
||||
AIVirtualCard aIVirtualCard = aIVirtualField.SearchVirtualCard(situation.Actor);
|
||||
AISelectedTargetInfoSet aISelectedTargetInfoSet = new AISelectedTargetInfoSet();
|
||||
if (situation.SelectedTargets != null)
|
||||
{
|
||||
for (int num2 = 0; num2 < AISelectedTargetInfoSet.LENGTH; num2++)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo = situation.SelectedTargets.Get(num2);
|
||||
if (aISelectedTargetInfo == null || !aISelectedTargetInfo.HasTarget)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AISelectedTargetInfo aISelectedTargetInfo2 = new AISelectedTargetInfo(aISelectedTargetInfo.Type);
|
||||
int count = aISelectedTargetInfo.Targets.Count;
|
||||
for (int num3 = 0; num3 < count; num3++)
|
||||
{
|
||||
if (aISelectedTargetInfo.Type == TargetSelectType.Choice)
|
||||
{
|
||||
aISelectedTargetInfo2.AddTarget(aISelectedTargetInfo.Targets[num3]);
|
||||
continue;
|
||||
}
|
||||
AIVirtualCard target = aIVirtualField.SearchVirtualCard(aISelectedTargetInfo.Targets[num3]);
|
||||
aISelectedTargetInfo2.AddTarget(target);
|
||||
}
|
||||
aISelectedTargetInfoSet.Set(aISelectedTargetInfo2, num2);
|
||||
}
|
||||
if (situation.SelectedTargets.HasChoiceTarget)
|
||||
{
|
||||
aISelectedTargetInfoSet.SetChoiceTarget(situation.SelectedTargets.ChoiceTarget);
|
||||
}
|
||||
}
|
||||
AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(aIVirtualCard, aIVirtualCard, situation.ActionType, aISelectedTargetInfoSet);
|
||||
PlaySimulationInfo playSimulationInfo = AIPlayCardSimulationUtility.CreatePlaySimulationInfo(aIVirtualCard, aIVirtualTargetSelectAction, aIVirtualField);
|
||||
if (playSimulationInfo == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIEmoteCtrl:OnCardPlay() playSimulationInfo is null. CardName:" + ((aIVirtualCard != null) ? aIVirtualCard.CardName : ""));
|
||||
return null;
|
||||
}
|
||||
if (playSimulationInfo.Type == PlaySimulationType.Accelerate || playSimulationInfo.Type == PlaySimulationType.Crystalize)
|
||||
{
|
||||
AISinglePlayptnRecord playptnRecord = AI.PlayPtnRecorder.FindMatchedPlayPtnRecord(aIVirtualField.BestPlayPtn, aIVirtualField);
|
||||
aIVirtualTargetSelectAction.SetActor(aIVirtualCard.FindRealActor(playptnRecord));
|
||||
}
|
||||
AIVirtualPlaySimulator.PlayCard(aIVirtualTargetSelectAction, aIVirtualField, playSimulationInfo);
|
||||
if (aIVirtualField.EnemyClass.Life <= 0 || aIVirtualField.EnemyClass.IsDead)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(22);
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIRealBattleCardSearcher.SearchBattleCardFromSituation(AI.PlayerPair, situation, out var actor, out var targetList);
|
||||
if (actor == null || (situation.ActionTarget != null && (targetList == null || targetList.Count < 1 || targetList[0] == null)) || (situation.SecondActionTarget != null && (targetList == null || targetList.Count < 2 || targetList[1] == null)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (AI.ALLY.IsSelfTurn && AI.IsAllyCard(actor))
|
||||
{
|
||||
AIVirtualCard actor2 = situation.Actor;
|
||||
int emoteCategory = actor2.GetEmoteCategory(AIPlayTagType.EmoteOnPlay);
|
||||
if (emoteCategory >= 0)
|
||||
{
|
||||
AIEmoteCmd result = AI.EmoteQuery.SearchEmoteAtRandom(emoteCategory);
|
||||
AI.EmoteQuery.OnCardPlayEmotion();
|
||||
return result;
|
||||
}
|
||||
new BattlePlayerPair(actor.SelfBattlePlayer, actor.OpponentBattlePlayer);
|
||||
int num4 = actor2.BattleSkills.Count();
|
||||
for (int num5 = 0; num5 < num4; num5++)
|
||||
{
|
||||
SkillBase skill = actor2.BattleSkills.ElementAt(num5);
|
||||
if (AI.ParamQuery.IsBanishSkill(skill))
|
||||
{
|
||||
return OnBanishSkill(actor, aIVirtualField);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyAttack(AISituationInfo situation)
|
||||
{
|
||||
if (!(situation is AIVirtualAttackInfo { Actor: not null, AttackTarget: not null }))
|
||||
{
|
||||
AIConsoleUtility.LogError("OnAllyAttack() error!!! situation is not valid attackSituation");
|
||||
return null;
|
||||
}
|
||||
AI.EmoteMng.EvalFieldOnAttack();
|
||||
AIVirtualField aIVirtualField = new AIVirtualField(AI.CurrentVirtualField);
|
||||
AIVirtualAttackInfo aIVirtualAttackInfo2 = AISimulationUtility.CreateActionInfoOnFieldFromSituation(aIVirtualField, situation) as AIVirtualAttackInfo;
|
||||
if (!situation.IsSameSituation(aIVirtualAttackInfo2))
|
||||
{
|
||||
AIConsoleUtility.LogError("OnAllyAttack() error!!! Failed situation clone");
|
||||
return null;
|
||||
}
|
||||
AIVirtualAttackSimulator.Attack(aIVirtualAttackInfo2, aIVirtualField);
|
||||
if (aIVirtualField.EnemyClass.IsDead)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(22);
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int emoteCategory = aIVirtualAttackInfo2.Actor.GetEmoteCategory(AIPlayTagType.EmoteOnAtk);
|
||||
if (emoteCategory >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteCategory);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyEvolution(AISituationInfo situation)
|
||||
{
|
||||
if (situation == null || situation.Actor == null || situation.ActionType != AIOperationType.EVOLVE)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualField aIVirtualField = new AIVirtualField(AI.CurrentVirtualField);
|
||||
AIVirtualActionInfo aIVirtualActionInfo = AISimulationUtility.CreateActionInfoOnFieldFromSituation(aIVirtualField, situation);
|
||||
if (!situation.IsSameSituation(aIVirtualActionInfo))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualEvolutionSimulator.ManualEvolve(aIVirtualActionInfo, aIVirtualField);
|
||||
if (aIVirtualField.EnemyClass.IsDead)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(22);
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int emoteCategory = aIVirtualActionInfo.Actor.GetEmoteCategory(AIPlayTagType.EmoteOnEvo);
|
||||
if (emoteCategory >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteCategory);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnBanishSkill(BattleCardBase actCard, AIVirtualField fieldAfterPlayed)
|
||||
{
|
||||
if (AI.EmoteMng.IsBanishOverExpected(actCard, fieldAfterPlayed))
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(21);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentPlayCardExecuted(AISituationInfo situation)
|
||||
{
|
||||
if (AI.EmoteMng.IsCheckmated() || situation == null || situation.Actor == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
if (AI.EmoteMng.IsOpponentBanishSplendid(actor))
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(35);
|
||||
}
|
||||
if (AI.EmoteMng.IsOpponentBanishBad(actor))
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(36);
|
||||
}
|
||||
if (!actor.IsAlly && AI.EmoteMng.IsGiantPlayed())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(34);
|
||||
}
|
||||
if (AI.EmoteMng.IsOpponentHealClassLifeLargeOnCardPlay())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(37);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentAttackExecuted()
|
||||
{
|
||||
if (AI.EmoteMng.IsCheckmated())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (AI.EmoteMng.IsOpponentHealClassLifeLargeOnAttack())
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(37);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnCardDestroy(AISituationInfo situation)
|
||||
{
|
||||
if (situation == null || situation.Actor == null || situation.ActionType != AIOperationType.UNKNOWN)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
if (actor.IsAlly)
|
||||
{
|
||||
int emoteCategory = actor.GetEmoteCategory(AIPlayTagType.ForceEmoteOnDestroy);
|
||||
if (emoteCategory >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteCategory);
|
||||
}
|
||||
}
|
||||
if (AI.EmoteMng.IsCheckmated() || _isEmoOnDestroyPlayed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (actor.IsAlly)
|
||||
{
|
||||
int emoteCategory2 = actor.GetEmoteCategory(AIPlayTagType.EmoteOnDestroy);
|
||||
if (emoteCategory2 >= 0)
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteCategory2);
|
||||
}
|
||||
if (AI.OPPONENT.IsSelfTurn && AI.EmoteMng.IsEliminatedAllyLegion(situation.Actor))
|
||||
{
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(101);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnLeaderDamaged(AIVirtualField field)
|
||||
{
|
||||
int emoteOnLeaderDamaged = AI.StyleQuery.GetEmoteOnLeaderDamaged(field);
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(emoteOnLeaderDamaged);
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnPlayerLeaderDamaged(AIVirtualField field)
|
||||
{
|
||||
int playerEmoteOnLeaderDamaged = AI.StyleQuery.GetPlayerEmoteOnLeaderDamaged(field);
|
||||
return AI.EmoteQuery.SearchEmoteAtRandom(playerEmoteOnLeaderDamaged, isAlly: false);
|
||||
}
|
||||
}
|
||||
36
SVSim.BattleEngine/Engine/Wizard/AIEmoteDataAsset.cs
Normal file
36
SVSim.BattleEngine/Engine/Wizard/AIEmoteDataAsset.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteDataAsset
|
||||
{
|
||||
public int ID;
|
||||
|
||||
public int Category;
|
||||
|
||||
public int FaceID;
|
||||
|
||||
public int MotionID;
|
||||
|
||||
public string VoiceID;
|
||||
|
||||
public string TextID;
|
||||
|
||||
public AIEmoteDataAsset(string[] columns)
|
||||
{
|
||||
int num = 0;
|
||||
ID = AIScriptParser.ParseInt(columns[num++]);
|
||||
Category = AIScriptParser.ParseInt(columns[num++]);
|
||||
FaceID = AIScriptParser.ParseInt(columns[num++]);
|
||||
MotionID = AIScriptParser.ParseInt(columns[num++]);
|
||||
VoiceID = columns[num++];
|
||||
TextID = ConvEmoteMasterText(columns[num++]);
|
||||
}
|
||||
|
||||
private string ConvEmoteMasterText(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return Data.Master.GetEmoteWordText(id);
|
||||
}
|
||||
}
|
||||
37
SVSim.BattleEngine/Engine/Wizard/AIEmoteFileNameList.cs
Normal file
37
SVSim.BattleEngine/Engine/Wizard/AIEmoteFileNameList.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteFileNameList
|
||||
{
|
||||
private const int EMOTE_ID_INDEX = 0;
|
||||
|
||||
private const int FILE_NAME_INDEX = 1;
|
||||
|
||||
private readonly Dictionary<int, string> _dataTable = new Dictionary<int, string>();
|
||||
|
||||
public AIEmoteFileNameList(List<string[]> csvData)
|
||||
{
|
||||
foreach (string[] csvDatum in csvData)
|
||||
{
|
||||
int key = int.Parse(csvDatum[0]);
|
||||
string value = csvDatum[1];
|
||||
_dataTable.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFileName(int emoteId)
|
||||
{
|
||||
if (_dataTable.ContainsKey(emoteId))
|
||||
{
|
||||
return _dataTable[emoteId];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public List<string> GetFileNameList()
|
||||
{
|
||||
return _dataTable.Values.ToList();
|
||||
}
|
||||
}
|
||||
417
SVSim.BattleEngine/Engine/Wizard/AIEmoteMng.cs
Normal file
417
SVSim.BattleEngine/Engine/Wizard/AIEmoteMng.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteMng
|
||||
{
|
||||
private EnemyAI AI;
|
||||
|
||||
private float _allyAdvOnTurnStart;
|
||||
|
||||
private float _opponentAdvOnTurnStart;
|
||||
|
||||
private int _allyLegionNumOnTurnStart;
|
||||
|
||||
private float _allyAdvOnFirstAttack;
|
||||
|
||||
private float _advOnBeforeSetCard;
|
||||
|
||||
private int _opponentLifeOnBeforeSetCard;
|
||||
|
||||
private int _opponentLifeOnBeforeAttack;
|
||||
|
||||
private bool _isLastOpr_CardPlay;
|
||||
|
||||
private float _playedCardValue;
|
||||
|
||||
private float _allyAdvOnCardPlay;
|
||||
|
||||
private bool _isFirstAttacked;
|
||||
|
||||
private bool _isOpponentTurnEmoteOccured;
|
||||
|
||||
private bool _isAIGreeted;
|
||||
|
||||
private bool _isAIThanked;
|
||||
|
||||
private readonly Stopwatch _stopwatch;
|
||||
|
||||
private bool _isThinkingEmoteOccured;
|
||||
|
||||
public Dictionary<int, int> EmoteCategoryPlayedCounter { get; private set; }
|
||||
|
||||
public bool IsOpponentTurnEmoteOccured => _isOpponentTurnEmoteOccured;
|
||||
|
||||
public Stopwatch Stopwatch => _stopwatch;
|
||||
|
||||
public int EmoteRandomSeed { get; private set; }
|
||||
|
||||
public AIEmoteMng(EnemyAI ai)
|
||||
{
|
||||
AI = ai;
|
||||
EmoteRandomSeed = new Random().Next();
|
||||
_stopwatch = new Stopwatch();
|
||||
_isAIGreeted = false;
|
||||
_isAIThanked = false;
|
||||
EmoteCategoryPlayedCounter = new Dictionary<int, int>();
|
||||
}
|
||||
|
||||
public float EvalDisplacement_PlayedValue()
|
||||
{
|
||||
if (!_isLastOpr_CardPlay)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() - (_allyAdvOnCardPlay + _playedCardValue);
|
||||
}
|
||||
|
||||
public void ResetLastOpr()
|
||||
{
|
||||
_isLastOpr_CardPlay = false;
|
||||
}
|
||||
|
||||
public void SetUpOnAllyTurnStart()
|
||||
{
|
||||
_isFirstAttacked = false;
|
||||
ResetLastOpr();
|
||||
AI.EmoteQuery.UpdateCategoryInterval();
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_isThinkingEmoteOccured = false;
|
||||
}
|
||||
|
||||
public void EvalFieldOnTurnStart()
|
||||
{
|
||||
_allyAdvOnTurnStart = AI.CalcFieldAdvantage();
|
||||
_allyLegionNumOnTurnStart = AI.ALLY.InPlayCards.Count((BattleCardBase c) => c.IsTribe(CardBasePrm.TribeType.LEGION));
|
||||
}
|
||||
|
||||
public void EvalFieldOnOpponentTurnStart()
|
||||
{
|
||||
_opponentAdvOnTurnStart = AI.CalcFieldAdvantage();
|
||||
}
|
||||
|
||||
public void EvalFieldOnAttack()
|
||||
{
|
||||
if (!_isFirstAttacked)
|
||||
{
|
||||
_allyAdvOnFirstAttack = AI.CalcFieldAdvantage();
|
||||
_isFirstAttacked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void EvalFieldOnBeforeSetCard()
|
||||
{
|
||||
_advOnBeforeSetCard = AI.CalcFieldAdvantage();
|
||||
_opponentLifeOnBeforeSetCard = AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public void EvalFieldOnBeforeAttack()
|
||||
{
|
||||
_opponentLifeOnBeforeAttack = AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public void EvalAllyOnCardPlay(AIVirtualCard playCard, AISinglePlayptnRecord playptnRecord)
|
||||
{
|
||||
if (playptnRecord != null && playptnRecord.PlayPtn != null && playptnRecord.PlayPtn.Count > 0)
|
||||
{
|
||||
_isLastOpr_CardPlay = true;
|
||||
_allyAdvOnCardPlay = AI.CalcFieldAdvantage();
|
||||
AIVirtualTargetSelectAction play = new AIVirtualTargetSelectAction(playCard, playCard, AIOperationType.PLAY);
|
||||
_playedCardValue = AI.EnemyAIPlay.EvaluateHandValue(playCard, playptnRecord.PlayPtn, play, isOnBattleSimulate: false, playptnRecord);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOpponentTurnEmote()
|
||||
{
|
||||
_isOpponentTurnEmoteOccured = true;
|
||||
}
|
||||
|
||||
public void ResetOpponentTurnEmoteFlag()
|
||||
{
|
||||
_isOpponentTurnEmoteOccured = false;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyCardDestroy()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsReverseDisAdv()
|
||||
{
|
||||
if (_allyAdvOnTurnStart >= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() >= 0f;
|
||||
}
|
||||
|
||||
public bool IsOpponentEarnGreatMerit()
|
||||
{
|
||||
float num = AI.CalcFieldAdvantage();
|
||||
int ppTotal = AI.OPPONENT.PpTotal;
|
||||
return _opponentAdvOnTurnStart - num > (float)ppTotal * 2f;
|
||||
}
|
||||
|
||||
public bool IsFailedReverseDisAdv()
|
||||
{
|
||||
if (_allyAdvOnTurnStart >= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() < 0f;
|
||||
}
|
||||
|
||||
public bool IsOpponentFailedReverseDisAdv()
|
||||
{
|
||||
if (_opponentAdvOnTurnStart <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() > 0f;
|
||||
}
|
||||
|
||||
public bool IsRemainTooPP()
|
||||
{
|
||||
return AI.ALLY.Pp >= 2;
|
||||
}
|
||||
|
||||
public bool IsOpponentRemainTooPP()
|
||||
{
|
||||
return AI.OPPONENT.Pp > AI.OPPONENT.PpTotal / 2;
|
||||
}
|
||||
|
||||
public bool IsGiantPlayed()
|
||||
{
|
||||
float num = 10f;
|
||||
return AI.FieldInplayValueDifference >= num;
|
||||
}
|
||||
|
||||
public bool IsEnoughUnit()
|
||||
{
|
||||
return AI.ALLY.InPlayCards.Count() >= 3;
|
||||
}
|
||||
|
||||
public bool IsEnoughGrave()
|
||||
{
|
||||
return AI.ALLY.CemeteryList.Count >= 6;
|
||||
}
|
||||
|
||||
public bool IsCheckmated()
|
||||
{
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in AI.OPPONENT.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.IsUnit)
|
||||
{
|
||||
num += inPlayCard.Atk;
|
||||
}
|
||||
}
|
||||
if (AI.OPPONENT.IsEvolve && AI.OPPONENT.InPlayCards.Any((BattleCardBase card) => card.IsUnit && !card.IsEvolution))
|
||||
{
|
||||
num += AI.OPPONENT.InPlayCards.Max((BattleCardBase card) => (!card.IsEvolution) ? (card.BaseParameter.EvoAtk - card.BaseParameter.Atk) : 0);
|
||||
}
|
||||
int num2 = 0;
|
||||
List<AIVirtualCard> bothClassAndInplayCards = AI.CurrentVirtualField.CardListSet.BothClassAndInplayCards;
|
||||
for (int num3 = 0; num3 < bothClassAndInplayCards.Count; num3++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = bothClassAndInplayCards[num3];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTag(AIPlayTagType.TurnEndDamage))
|
||||
{
|
||||
num2 += aIVirtualCard.TagCollectionContainer.TurnEndTags.GetTurnEndDamageToAllyLeader(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
return num + num2 >= AI.ALLY.Class.Life;
|
||||
}
|
||||
|
||||
public bool IsHuntDown()
|
||||
{
|
||||
if (AI.OPPONENT.InPlayCards.Any((BattleCardBase c) => c.SkillApplyInformation.IsGuard))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in AI.ALLY.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.IsUnit)
|
||||
{
|
||||
num += inPlayCard.Atk;
|
||||
}
|
||||
}
|
||||
if (AI.ALLY.CurrentEpCount > 0)
|
||||
{
|
||||
num += 2;
|
||||
}
|
||||
return num >= AI.OPPONENT.Class.Life;
|
||||
}
|
||||
|
||||
public bool IsEliminatedAllyLegion(AIVirtualCard destroyingCard)
|
||||
{
|
||||
if (_allyLegionNumOnTurnStart < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (AI.CurrentVirtualField.AllyInplayCards.Count((AIVirtualCard c) => c.IsTribe(CardBasePrm.TribeType.LEGION) && c.IsSameCard(destroyingCard)) > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsAwaking(int turnOffset)
|
||||
{
|
||||
if (AI.ALLY.Pp + turnOffset == 7)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsUnexpectedBattle()
|
||||
{
|
||||
if (!_isFirstAttacked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return AI.CalcFieldAdvantage() < _allyAdvOnFirstAttack;
|
||||
}
|
||||
|
||||
public bool IsBanishOverExpected(BattleCardBase actCard, AIVirtualField fieldAfterPlayed)
|
||||
{
|
||||
if (!actCard.IsSpell)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = (float)actCard.Cost * 2f + 4f;
|
||||
float num2 = AI.ParamQuery.EvaluateBattlePlayerPair(AI.CurrentVirtualField);
|
||||
if (AI.ParamQuery.EvaluateBattlePlayerPair(fieldAfterPlayed) - num2 >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentBanishSplendid(AIVirtualCard actCard)
|
||||
{
|
||||
if (actCard.IsAlly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = (float)actCard.Cost * 2f + 4f;
|
||||
float num2 = AI.CalcFieldAdvantage();
|
||||
if (_advOnBeforeSetCard - num2 >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentBanishBad(AIVirtualCard actCard)
|
||||
{
|
||||
if (actCard.IsAlly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float num = actCard.Cost;
|
||||
float num2 = AI.CalcFieldAdvantage();
|
||||
if (_advOnBeforeSetCard - num2 < num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentHealClassLifeLargeOnCardPlay()
|
||||
{
|
||||
int num = 4;
|
||||
if (AI.OPPONENT.Class.Life - _opponentLifeOnBeforeSetCard >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOpponentHealClassLifeLargeOnAttack()
|
||||
{
|
||||
int num = 4;
|
||||
if (AI.OPPONENT.Class.Life - _opponentLifeOnBeforeAttack >= num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsThinkingLong()
|
||||
{
|
||||
float num = 20000f;
|
||||
if (!_isThinkingEmoteOccured)
|
||||
{
|
||||
return (float)_stopwatch.ElapsedMilliseconds > num;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnThinkingEmote()
|
||||
{
|
||||
_isThinkingEmoteOccured = true;
|
||||
_stopwatch.Reset();
|
||||
}
|
||||
|
||||
public void OnOperationRequest()
|
||||
{
|
||||
if (!_isThinkingEmoteOccured)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReplyAllowed(ClassCharaPrm.EmotionType emoteType, ref ClassCharaPrm.EmotionType replyEmote)
|
||||
{
|
||||
switch (emoteType)
|
||||
{
|
||||
case ClassCharaPrm.EmotionType.GREET:
|
||||
if (_isAIGreeted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
replyEmote = ClassCharaPrm.EmotionType.GREET;
|
||||
_isAIGreeted = true;
|
||||
return true;
|
||||
case ClassCharaPrm.EmotionType.THANK:
|
||||
if (_isAIThanked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
replyEmote = ClassCharaPrm.EmotionType.THANK;
|
||||
_isAIThanked = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPlayedCountOnEmotePlaying(int category)
|
||||
{
|
||||
if (EmoteCategoryPlayedCounter.ContainsKey(category))
|
||||
{
|
||||
EmoteCategoryPlayedCounter[category]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmoteCategoryPlayedCounter.Add(category, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetEmotePlayCount(int category)
|
||||
{
|
||||
if (EmoteCategoryPlayedCounter.ContainsKey(category))
|
||||
{
|
||||
return EmoteCategoryPlayedCounter[category];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
214
SVSim.BattleEngine/Engine/Wizard/AIEmoteQuery.cs
Normal file
214
SVSim.BattleEngine/Engine/Wizard/AIEmoteQuery.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteQuery
|
||||
{
|
||||
public enum Category
|
||||
{
|
||||
UnexpectedPlayResult_Good = 1,
|
||||
UnexpectedPlayResult_Bad = 2,
|
||||
LongThinking = 3,
|
||||
UnexpectedBattleResult = 11,
|
||||
ReverseDisAdv = 12,
|
||||
CheckMated = 13,
|
||||
HuntDown = 14,
|
||||
RemainTooPP = 15,
|
||||
SpellBanishOverExpected = 21,
|
||||
FatalAttack = 22,
|
||||
OpponentRemainTooPP = 31,
|
||||
OpponentReverseDisAdvFail = 32,
|
||||
OpponentGetGreatMerit = 33,
|
||||
OpponentPlayGiant = 34,
|
||||
OpponentBanishSpell_Good = 35,
|
||||
OpponentBanishSpell_Bad = 36,
|
||||
OpponentWellHealing = 37,
|
||||
EliminatedAllyLegion = 101,
|
||||
EnoughUnit = 102,
|
||||
Awake = 401,
|
||||
EnoughGrave = 501
|
||||
}
|
||||
|
||||
private EnemyAI enemyAI;
|
||||
|
||||
private bool _isActivate = true;
|
||||
|
||||
private AIEmoteSet _curEmoteSet;
|
||||
|
||||
private bool _emotePermission;
|
||||
|
||||
private bool _useInnerEmote;
|
||||
|
||||
private Queue<int> _previousEmoteQueue;
|
||||
|
||||
private Queue<int> _previousPlayerEmoteQueue;
|
||||
|
||||
private Dictionary<int, int> _categoryIntervalDic;
|
||||
|
||||
private const int EMOTE_QUEUE_LENGTH = 3;
|
||||
|
||||
public bool UseInnerEmote => _useInnerEmote;
|
||||
|
||||
public AIEmoteQuery(EnemyAI ai)
|
||||
{
|
||||
enemyAI = ai;
|
||||
_emotePermission = true;
|
||||
_useInnerEmote = false;
|
||||
_previousEmoteQueue = new Queue<int>(3);
|
||||
_previousPlayerEmoteQueue = new Queue<int>(3);
|
||||
_categoryIntervalDic = new Dictionary<int, int>();
|
||||
}
|
||||
|
||||
public void SetOnOffEmote(bool isActivate, bool useInnerEmote)
|
||||
{
|
||||
_isActivate = isActivate;
|
||||
_useInnerEmote = useInnerEmote;
|
||||
}
|
||||
|
||||
public void SetEmoteSet(AIEmoteSet emoteSet)
|
||||
{
|
||||
_curEmoteSet = emoteSet;
|
||||
}
|
||||
|
||||
public void UpdateCategoryInterval()
|
||||
{
|
||||
foreach (int item in new List<int>(_categoryIntervalDic.Keys))
|
||||
{
|
||||
int num = _categoryIntervalDic[item];
|
||||
if (num > 0)
|
||||
{
|
||||
_categoryIntervalDic[item] = num - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetInterval(int emoteKey, int turnCount)
|
||||
{
|
||||
if (_categoryIntervalDic.ContainsKey(emoteKey))
|
||||
{
|
||||
_categoryIntervalDic[emoteKey] = turnCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
_categoryIntervalDic.Add(emoteKey, turnCount);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetCategoryInterval(int emoteKey)
|
||||
{
|
||||
if (!_categoryIntervalDic.ContainsKey(emoteKey))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return _categoryIntervalDic[emoteKey];
|
||||
}
|
||||
|
||||
public AIEmoteCmd SearchEmoteAtRandom(int emoteKey, bool isAlly = true)
|
||||
{
|
||||
if (!_isActivate)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (_curEmoteSet == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.CategoryKey == emoteKey))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!_emotePermission)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!_useInnerEmote && emoteKey <= 1000)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIEmoteCmd aIEmoteCmd = null;
|
||||
IList<AIEmoteCmd> list = FilterEmoteByPreviousPlayed(_curEmoteSet.EmoteCmds.Where((AIEmoteCmd c) => c.CategoryKey == emoteKey), isAlly);
|
||||
int count = list.Count;
|
||||
if (count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (count > 1)
|
||||
{
|
||||
int index = enemyAI.AIStableRandom() % count;
|
||||
aIEmoteCmd = list[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
aIEmoteCmd = list[0];
|
||||
}
|
||||
if (aIEmoteCmd != null)
|
||||
{
|
||||
Queue<int> queue = (isAlly ? _previousEmoteQueue : _previousPlayerEmoteQueue);
|
||||
if (queue.Count == 3)
|
||||
{
|
||||
queue.Dequeue();
|
||||
}
|
||||
queue.Enqueue(aIEmoteCmd.ID);
|
||||
aIEmoteCmd.isAI = isAlly;
|
||||
}
|
||||
return aIEmoteCmd;
|
||||
}
|
||||
|
||||
public AIEmoteCmd SearchEmoteByID(int emoteID)
|
||||
{
|
||||
if (_curEmoteSet == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.ID == emoteID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _curEmoteSet.EmoteCmds.First((AIEmoteCmd c) => c.ID == emoteID);
|
||||
}
|
||||
|
||||
public IEnumerable<AIEmoteCmd> SearchEmoteByCategory(int emoteCategory)
|
||||
{
|
||||
if (_curEmoteSet == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.CategoryKey == emoteCategory))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _curEmoteSet.EmoteCmds.Where((AIEmoteCmd c) => c.CategoryKey == emoteCategory);
|
||||
}
|
||||
|
||||
public void OnOperation()
|
||||
{
|
||||
_emotePermission = true;
|
||||
}
|
||||
|
||||
public void OnCardPlayEmotion()
|
||||
{
|
||||
_emotePermission = false;
|
||||
}
|
||||
|
||||
private IList<AIEmoteCmd> FilterEmoteByPreviousPlayed(IEnumerable<AIEmoteCmd> emoteCmds, bool isAlly)
|
||||
{
|
||||
IList<AIEmoteCmd> list = new List<AIEmoteCmd>();
|
||||
Queue<int> queue = (isAlly ? _previousEmoteQueue : _previousPlayerEmoteQueue);
|
||||
foreach (AIEmoteCmd emoteCmd in emoteCmds)
|
||||
{
|
||||
if (queue.Contains(emoteCmd.ID))
|
||||
{
|
||||
if (enemyAI.AIStableRandom() % 4 == 0)
|
||||
{
|
||||
list.Add(emoteCmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(emoteCmd);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
19
SVSim.BattleEngine/Engine/Wizard/AIEmoteSet.cs
Normal file
19
SVSim.BattleEngine/Engine/Wizard/AIEmoteSet.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteSet
|
||||
{
|
||||
private List<AIEmoteCmd> cmdList = new List<AIEmoteCmd>();
|
||||
|
||||
public IEnumerable<AIEmoteCmd> EmoteCmds => cmdList;
|
||||
|
||||
public void CreateFromAsset(List<AIEmoteDataAsset> assetList)
|
||||
{
|
||||
cmdList.Clear();
|
||||
foreach (AIEmoteDataAsset asset in assetList)
|
||||
{
|
||||
cmdList.Add(new AIEmoteCmd(asset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIFunctionResultContainer
|
||||
{
|
||||
private Dictionary<AIScriptTokenFuncType, Dictionary<ulong, float>> _functionResultDic;
|
||||
|
||||
public AIFunctionResultContainer()
|
||||
{
|
||||
_functionResultDic = new Dictionary<AIScriptTokenFuncType, Dictionary<ulong, float>>();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (AIScriptTokenFuncType key in _functionResultDic.Keys)
|
||||
{
|
||||
_functionResultDic[key].Clear();
|
||||
}
|
||||
_functionResultDic.Clear();
|
||||
}
|
||||
|
||||
public void AddRecord(AIScriptTokenFuncType funcType, ulong hash, float result)
|
||||
{
|
||||
if (!_functionResultDic.TryGetValue(funcType, out var value))
|
||||
{
|
||||
value = new Dictionary<ulong, float>();
|
||||
_functionResultDic.Add(funcType, value);
|
||||
}
|
||||
if (value.ContainsKey(hash))
|
||||
{
|
||||
AIConsoleUtility.LogError($"AIFunctionResultContainer.AddRecord() error!! conflict key = {hash}");
|
||||
}
|
||||
else
|
||||
{
|
||||
value.Add(hash, result);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetContainsResultValue(AIScriptTokenFuncType funcType, ulong hash, out float getResult)
|
||||
{
|
||||
if (_functionResultDic.TryGetValue(funcType, out var value))
|
||||
{
|
||||
return value.TryGetValue(hash, out getResult);
|
||||
}
|
||||
getResult = 0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
48
SVSim.BattleEngine/Engine/Wizard/AIFusionSituationInfo.cs
Normal file
48
SVSim.BattleEngine/Engine/Wizard/AIFusionSituationInfo.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIFusionSituationInfo : AISituationInfo
|
||||
{
|
||||
public List<AIVirtualCard> Targets;
|
||||
|
||||
public float Priority { get; private set; }
|
||||
|
||||
public List<AIScriptTokenBase> Range { get; private set; }
|
||||
|
||||
public AIPolishConvertedExpression PriorityExpression { get; private set; }
|
||||
|
||||
public bool HasTargets
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Targets != null)
|
||||
{
|
||||
return Targets.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AIFusionSituationInfo(AIVirtualCard actor, List<AIVirtualCard> targets)
|
||||
: base(actor, null, null, AIOperationType.FUSION)
|
||||
{
|
||||
Targets = targets;
|
||||
}
|
||||
|
||||
public void UpdatePriority(List<int> playPtn)
|
||||
{
|
||||
Priority = PriorityExpression.EvalArg(base.Actor, playPtn, base.Actor.SelfField, this);
|
||||
}
|
||||
|
||||
public bool InitializeFusionParameter(AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
return base.Actor.TagCollectionContainer.FusionTags.InitializeFusionSituationParameter(base.Actor, field, playPtn, this);
|
||||
}
|
||||
|
||||
public void SetParameter(List<AIScriptTokenBase> range, AIPolishConvertedExpression priority)
|
||||
{
|
||||
Range = range;
|
||||
PriorityExpression = priority;
|
||||
}
|
||||
}
|
||||
126
SVSim.BattleEngine/Engine/Wizard/AIGenerateTagOwnerTable.cs
Normal file
126
SVSim.BattleEngine/Engine/Wizard/AIGenerateTagOwnerTable.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIGenerateTagOwnerTable
|
||||
{
|
||||
public class GenerateTagOwnerInfo
|
||||
{
|
||||
public int OwnerBaseCardId { get; private set; }
|
||||
|
||||
public int OwnerCardIndex { get; private set; }
|
||||
|
||||
public bool OwnerIsPlayer { get; private set; }
|
||||
|
||||
public List<AIPlayTag> GenerateTagList { get; private set; }
|
||||
|
||||
public GenerateTagOwnerInfo(int baseCardId, int cardIndex, bool isPlayer)
|
||||
{
|
||||
OwnerBaseCardId = baseCardId;
|
||||
OwnerCardIndex = cardIndex;
|
||||
OwnerIsPlayer = isPlayer;
|
||||
GenerateTagList = new List<AIPlayTag>();
|
||||
}
|
||||
|
||||
public bool IsOwner(int baseCardId, int cardIndex, bool isPlayer)
|
||||
{
|
||||
if (OwnerBaseCardId == baseCardId && OwnerCardIndex == cardIndex)
|
||||
{
|
||||
return OwnerIsPlayer == isPlayer;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RegisterNewGenerateTag(List<AIPlayTag> tagList)
|
||||
{
|
||||
List<AIPlayTag> list = null;
|
||||
for (int i = 0; i < tagList.Count; i++)
|
||||
{
|
||||
AIPlayTag aIPlayTag = tagList[i];
|
||||
if (aIPlayTag.Type == AIPlayTagType.GenerateTag && !GenerateTagList.Contains(aIPlayTag))
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIPlayTag, list);
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
{
|
||||
GenerateTagList.AddRange(list);
|
||||
}
|
||||
}
|
||||
|
||||
public GenerateTagOwnerInfo Clone()
|
||||
{
|
||||
return new GenerateTagOwnerInfo(OwnerBaseCardId, OwnerCardIndex, OwnerIsPlayer)
|
||||
{
|
||||
GenerateTagList = new List<AIPlayTag>(GenerateTagList)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private List<GenerateTagOwnerInfo> _ownerInfoList;
|
||||
|
||||
public AIGenerateTagOwnerTable()
|
||||
{
|
||||
_ownerInfoList = new List<GenerateTagOwnerInfo>();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
_ownerInfoList.Clear();
|
||||
}
|
||||
|
||||
public AIGenerateTagOwnerTable Clone()
|
||||
{
|
||||
AIGenerateTagOwnerTable aIGenerateTagOwnerTable = new AIGenerateTagOwnerTable();
|
||||
for (int i = 0; i < _ownerInfoList.Count; i++)
|
||||
{
|
||||
aIGenerateTagOwnerTable._ownerInfoList.Add(_ownerInfoList[i].Clone());
|
||||
}
|
||||
return aIGenerateTagOwnerTable;
|
||||
}
|
||||
|
||||
public void RegisterAllGenerateTagOwner(AIVirtualField field)
|
||||
{
|
||||
BattlePlayerPair playerPair = new BattlePlayerPair(field.AllyBattlePlayer, field.EnemyBattlePlayer);
|
||||
List<AIVirtualCard> allReferableCards = field.CardListSet.AllReferableCards;
|
||||
for (int i = 0; i < allReferableCards.Count; i++)
|
||||
{
|
||||
if (allReferableCards[i].TagCollectionContainer.HasTag(AIPlayTagType.GenerateTag))
|
||||
{
|
||||
RegisterGenerateTagOwnerOneCard(playerPair, allReferableCards[i]);
|
||||
}
|
||||
}
|
||||
List<AIVirtualCard> enemyHandCardList = field.GetEnemyHandCardList();
|
||||
for (int j = 0; j < enemyHandCardList.Count; j++)
|
||||
{
|
||||
if (enemyHandCardList[j].TagCollectionContainer.HasTag(AIPlayTagType.GenerateTag))
|
||||
{
|
||||
RegisterGenerateTagOwnerOneCard(playerPair, enemyHandCardList[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterGenerateTagOwnerOneCard(BattlePlayerPair playerPair, AIVirtualCard card)
|
||||
{
|
||||
BattleCardBase battleCard = AIRealBattleCardSearcher.SearchBattleCardFromVirtualCard(playerPair, card);
|
||||
if (battleCard != null)
|
||||
{
|
||||
GenerateTagOwnerInfo generateTagOwnerInfo = _ownerInfoList.FirstOrDefault((GenerateTagOwnerInfo o) => o.IsOwner(battleCard.BaseParameter.BaseCardId, battleCard.Index, battleCard.IsPlayer));
|
||||
if (generateTagOwnerInfo == null)
|
||||
{
|
||||
generateTagOwnerInfo = new GenerateTagOwnerInfo(battleCard.BaseParameter.BaseCardId, battleCard.Index, battleCard.IsPlayer);
|
||||
_ownerInfoList.Add(generateTagOwnerInfo);
|
||||
}
|
||||
if (card.TagCollectionContainer.HasTag(AIPlayTagType.GenerateTag))
|
||||
{
|
||||
generateTagOwnerInfo.RegisterNewGenerateTag(card.TagCollectionContainer.GenerateTags.TagList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GenerateTagOwnerInfo GetGenerateTagOwnerInfo(int baseCardId, int ownerIndex, bool ownerIsPlayer)
|
||||
{
|
||||
return _ownerInfoList.FirstOrDefault((GenerateTagOwnerInfo o) => o.IsOwner(baseCardId, ownerIndex, ownerIsPlayer));
|
||||
}
|
||||
}
|
||||
52
SVSim.BattleEngine/Engine/Wizard/AIHandPlayEstimator.cs
Normal file
52
SVSim.BattleEngine/Engine/Wizard/AIHandPlayEstimator.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIHandPlayEstimator
|
||||
{
|
||||
public List<AIVirtualCard> InplayEstimations { get; private set; }
|
||||
|
||||
public AIHandPlayEstimator(AIParamQuery paramQuery, int handIndex, AIVirtualCard handOriginal, BattlePlayerPair sourcePair, EnemyAI ai)
|
||||
{
|
||||
BattleCardBase baseCard = handOriginal.BaseCard;
|
||||
int num = ai.CurrentVirtualField.AllyInplayCards.Count;
|
||||
if (baseCard.IsUnit || baseCard.IsField)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
List<int> playPtn = new List<int> { handOriginal.SelfField.AllyHandCards.FindIndex((AIVirtualCard c) => c.CardIndex == handOriginal.CardIndex) };
|
||||
AISinglePlayptnRecord playptnRecord = ai.PlayPtnRecorder.FindMatchedPlayPtnRecord(playPtn, ai.CurrentVirtualField);
|
||||
AIVirtualCard aIVirtualCard = handOriginal.FindRealActor(playptnRecord);
|
||||
if (!aIVirtualCard.IsSameCard(handOriginal))
|
||||
{
|
||||
ai.tokenManager.AddTokenFromCard(aIVirtualCard);
|
||||
}
|
||||
AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(aIVirtualCard, handOriginal, AIOperationType.PLAY);
|
||||
if (aIVirtualCard.BaseCard.Movable())
|
||||
{
|
||||
List<AITokenInformation> allySideTokenIdsOfPlaySituation = AIPlayTokenSimulationUtility.GetAllySideTokenIdsOfPlaySituation(ai.CurrentVirtualField, new List<int> { handOriginal.SelfField.AllyHandCards.FindIndex((AIVirtualCard c) => c.CardIndex == handOriginal.CardIndex) }, situation);
|
||||
if (allySideTokenIdsOfPlaySituation == null || allySideTokenIdsOfPlaySituation.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int num2 = 0; num2 < allySideTokenIdsOfPlaySituation.Count; num2++)
|
||||
{
|
||||
AIVirtualCard tokenFromId = ai.tokenManager.GetTokenFromId(allySideTokenIdsOfPlaySituation[num2].TokenId, isAlly: true, ai.CurrentVirtualField, needsClone: true);
|
||||
if (InplayEstimations == null)
|
||||
{
|
||||
InplayEstimations = new List<AIVirtualCard>();
|
||||
}
|
||||
InplayEstimations.Add(tokenFromId);
|
||||
num++;
|
||||
if (num >= 6)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InplayEstimations = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
74
SVSim.BattleEngine/Engine/Wizard/AIHealRecorderCollection.cs
Normal file
74
SVSim.BattleEngine/Engine/Wizard/AIHealRecorderCollection.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIHealRecorderCollection
|
||||
{
|
||||
public class AIHealRecorder
|
||||
{
|
||||
public int TurnCount { get; private set; }
|
||||
|
||||
public AIVirtualCard Card { get; private set; }
|
||||
|
||||
public AIHealRecorder(int turnCount, AIVirtualCard healedCard)
|
||||
{
|
||||
TurnCount = turnCount;
|
||||
Card = healedCard;
|
||||
}
|
||||
}
|
||||
|
||||
public List<AIHealRecorder> AllyHealRecorderList { get; private set; }
|
||||
|
||||
public List<AIHealRecorder> EnemyHealRecorderList { get; private set; }
|
||||
|
||||
public AIHealRecorderCollection()
|
||||
{
|
||||
AllyHealRecorderList = new List<AIHealRecorder>();
|
||||
EnemyHealRecorderList = new List<AIHealRecorder>();
|
||||
}
|
||||
|
||||
private AIHealRecorderCollection(AIHealRecorderCollection original)
|
||||
{
|
||||
AllyHealRecorderList = new List<AIHealRecorder>(original.AllyHealRecorderList);
|
||||
EnemyHealRecorderList = new List<AIHealRecorder>(original.EnemyHealRecorderList);
|
||||
}
|
||||
|
||||
public AIHealRecorderCollection Clone()
|
||||
{
|
||||
return new AIHealRecorderCollection(this);
|
||||
}
|
||||
|
||||
public int GetTurnHealCount(int turn, List<AIVirtualCard> checkTargets, bool isAlly)
|
||||
{
|
||||
List<AIHealRecorder> list = (isAlly ? AllyHealRecorderList : EnemyHealRecorderList);
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIHealRecorder aIHealRecorder = list[i];
|
||||
if (aIHealRecorder.TurnCount != turn)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < checkTargets.Count; j++)
|
||||
{
|
||||
if (aIHealRecorder.Card.IsSameCard(checkTargets[j]))
|
||||
{
|
||||
num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public void AppendHealCount(int turn, AIVirtualCard healedCard, bool isAlly)
|
||||
{
|
||||
(isAlly ? AllyHealRecorderList : EnemyHealRecorderList).Add(new AIHealRecorder(turn, healedCard));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
AllyHealRecorderList.Clear();
|
||||
EnemyHealRecorderList.Clear();
|
||||
}
|
||||
}
|
||||
82
SVSim.BattleEngine/Engine/Wizard/AILeaveStopCollection.cs
Normal file
82
SVSim.BattleEngine/Engine/Wizard/AILeaveStopCollection.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AILeaveStopCollection : AITagPreprocessCollectionBase
|
||||
{
|
||||
public AILeaveStopCollection Clone(List<AIVirtualCard> overrideCardList)
|
||||
{
|
||||
AILeaveStopCollection aILeaveStopCollection = new AILeaveStopCollection();
|
||||
aILeaveStopCollection.CopyInfoListWithReplaceCardReference(overrideCardList, base.InfoList);
|
||||
return aILeaveStopCollection;
|
||||
}
|
||||
|
||||
public void SimulateActionAll(AIVirtualCard leaveCard, AISituationInfo situation)
|
||||
{
|
||||
List<AITagPreprocessInformationBase> list = null;
|
||||
for (int i = 0; i < base.InfoList.Count; i++)
|
||||
{
|
||||
if (base.InfoList[i] is AILeaveStopInformation aILeaveStopInformation && aILeaveStopInformation.ExecuteReservedAction(leaveCard, situation))
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aILeaveStopInformation, list);
|
||||
}
|
||||
}
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
base.InfoList.Remove(list[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PseudoSimulateForEvalRandomMultiDamage(List<AIBarrierPseudoSimulationInfo> barrierInfoList, AIVirtualCard leaveCard)
|
||||
{
|
||||
for (int i = 0; i < base.InfoList.Count; i++)
|
||||
{
|
||||
if (base.InfoList[i] is AILeaveStopInformation aILeaveStopInformation)
|
||||
{
|
||||
aILeaveStopInformation.PseudoExecuteForEvalRandomMultiDamage(leaveCard, barrierInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AppendInfo(AITagPreprocessCreationOptionBase option, AIVirtualCard provider)
|
||||
{
|
||||
AILeaveStopInformation aILeaveStopInformation = CreateInfo(option, provider);
|
||||
if (aILeaveStopInformation != null)
|
||||
{
|
||||
base.InfoList.Add(aILeaveStopInformation);
|
||||
}
|
||||
}
|
||||
|
||||
private AILeaveStopInformation CreateInfo(AITagPreprocessCreationOptionBase option, AIVirtualCard provider)
|
||||
{
|
||||
switch (option.PreprocessInfoType)
|
||||
{
|
||||
case AITagPreprocessInfoType.BARRIER_STOP:
|
||||
return new AIBarrierLeaveStopInformation(option as AIBarrierStopPreprocessOption, provider);
|
||||
case AITagPreprocessInfoType.REMOVE_ATTACHED_TAG:
|
||||
return new AIAttachedTagLeaveStopInformation(option as AIAttachedTagStopPreprocessOption, provider);
|
||||
case AITagPreprocessInfoType.UNTOUCHABLE_STOP:
|
||||
return new AIUntouchableLeaveStopInformation(option, provider);
|
||||
default:
|
||||
AIConsoleUtility.LogError("AITurnEndStopInfoContainer-CreateInfo(): Missing TurnEndInfo type");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void GetOverrideCardAndAppendCopyInfo(List<AIVirtualCard> overrideCardList, AITagPreprocessInformationBase originalInfo)
|
||||
{
|
||||
if (overrideCardList != null && overrideCardList.Count > 0 && originalInfo is AILeaveStopInformation aILeaveStopInformation)
|
||||
{
|
||||
AIVirtualCard overrideTargetCard = aILeaveStopInformation.GetOverrideTargetCard(overrideCardList);
|
||||
AIVirtualCard overrideProviderCard = aILeaveStopInformation.GetOverrideProviderCard(overrideCardList);
|
||||
if (overrideTargetCard != null && overrideProviderCard != null)
|
||||
{
|
||||
AITagPreprocessCreationOptionBase option = originalInfo.CreateOptionInfoForOverride(overrideTargetCard);
|
||||
AppendInfo(option, overrideProviderCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
SVSim.BattleEngine/Engine/Wizard/AILeaveStopInformation.cs
Normal file
53
SVSim.BattleEngine/Engine/Wizard/AILeaveStopInformation.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AILeaveStopInformation : AITagPreprocessInformationBase
|
||||
{
|
||||
private AIVirtualCard _provider;
|
||||
|
||||
public AILeaveStopInformation(AIVirtualCard target, AIVirtualCard provider)
|
||||
: base(target)
|
||||
{
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
public bool ExecuteReservedAction(AIVirtualCard leaveCard, AISituationInfo situation)
|
||||
{
|
||||
if (leaveCard.IsSameCard(_provider))
|
||||
{
|
||||
StopMethod(situation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void StopMethod(AISituationInfo situation)
|
||||
{
|
||||
}
|
||||
|
||||
public void PseudoExecuteForEvalRandomMultiDamage(AIVirtualCard leaveCard, List<AIBarrierPseudoSimulationInfo> barrierInfoList)
|
||||
{
|
||||
if (leaveCard.IsSameCard(_provider))
|
||||
{
|
||||
PseudoStopMethodForEvalRandomMultiDamage(barrierInfoList);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PseudoStopMethodForEvalRandomMultiDamage(List<AIBarrierPseudoSimulationInfo> barrierInfoList)
|
||||
{
|
||||
}
|
||||
|
||||
public AIVirtualCard GetOverrideProviderCard(List<AIVirtualCard> overrideCardList)
|
||||
{
|
||||
for (int i = 0; i < overrideCardList.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = overrideCardList[i];
|
||||
if (aIVirtualCard.IsSameCard(_provider))
|
||||
{
|
||||
return aIVirtualCard;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
29
SVSim.BattleEngine/Engine/Wizard/AILethalPlan.cs
Normal file
29
SVSim.BattleEngine/Engine/Wizard/AILethalPlan.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AILethalPlan
|
||||
{
|
||||
public bool IsSuccess;
|
||||
|
||||
public List<AISituationInfo> ActionSequence;
|
||||
|
||||
public AILethalPlan()
|
||||
{
|
||||
IsSuccess = false;
|
||||
ActionSequence = null;
|
||||
}
|
||||
|
||||
public void AddAction(AISituationInfo action)
|
||||
{
|
||||
ActionSequence = AIParamQuery.AddElementToList(action, ActionSequence);
|
||||
}
|
||||
|
||||
public AILethalPlan Clone()
|
||||
{
|
||||
AILethalPlan aILethalPlan = new AILethalPlan();
|
||||
aILethalPlan.IsSuccess = IsSuccess;
|
||||
aILethalPlan.ActionSequence = AIParamQuery.AddRangeToList(ActionSequence, aILethalPlan.ActionSequence);
|
||||
return aILethalPlan;
|
||||
}
|
||||
}
|
||||
295
SVSim.BattleEngine/Engine/Wizard/AIOperationProcessor.cs
Normal file
295
SVSim.BattleEngine/Engine/Wizard/AIOperationProcessor.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
using Wizard.Battle.Card;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIOperationProcessor
|
||||
{
|
||||
private BattleManagerBase _battleMgr;
|
||||
|
||||
private EnemyAI _ai;
|
||||
|
||||
public AIOperationProcessor(BattleManagerBase mgr, EnemyAI ai)
|
||||
{
|
||||
_battleMgr = mgr;
|
||||
_ai = ai;
|
||||
}
|
||||
|
||||
public VfxBase AIPlayCard(AISituationInfo situation)
|
||||
{
|
||||
_ai.BestPlayPtnRecord = null;
|
||||
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
||||
VfxBase emote = _ai.GetEmote(AIEmoteCmdType.ON_CARD_PLAY_ALLY, situation);
|
||||
sequentialVfxPlayer.Register(emote);
|
||||
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
||||
AISelectedTargetInfoSet selectedTargets = situation.SelectedTargets;
|
||||
if (targetList.IsNotNullOrEmpty() && !selectedTargets.HasChoiceTarget)
|
||||
{
|
||||
SequentialVfxPlayer sequentialVfxPlayer2 = SequentialVfxPlayer.Create();
|
||||
for (int i = 0; i < targetList.Count; i++)
|
||||
{
|
||||
BattleCardBase battleCardBase = targetList[i];
|
||||
if (!battleCardBase.IsClass && !battleCardBase.BattleCardView.IsLoadResorces)
|
||||
{
|
||||
sequentialVfxPlayer2.Register(WaitVfx.Create(0.07f));
|
||||
sequentialVfxPlayer2.Register(battleCardBase.LoadResource());
|
||||
sequentialVfxPlayer2.Register(WaitVfx.Create(0.2f));
|
||||
}
|
||||
}
|
||||
sequentialVfxPlayer.Register(sequentialVfxPlayer2);
|
||||
}
|
||||
BattleCardBase battleCardBase2 = actor;
|
||||
int num = 0;
|
||||
if (actor.HasSkillAccelerate || actor.HasSkillCrystallize)
|
||||
{
|
||||
int num2 = CalcFixedUseCostTransformId(actor, actor.SelfBattlePlayer.Pp);
|
||||
if (num2 > 0)
|
||||
{
|
||||
battleCardBase2 = BattleManagerBase.GetIns().CreateTransformCardRegisterVfx(actor, num2, actor.IsPlayer);
|
||||
}
|
||||
}
|
||||
else if (actor.Skills.CheckWhenPlayChoice && actor.Skills.Count() > 1)
|
||||
{
|
||||
SkillBase skillBase = actor.Skills.Get(0);
|
||||
SkillBase skillBase2 = actor.Skills.Get(1);
|
||||
if (skillBase.IsChoiceType && skillBase2 is Skill_transform)
|
||||
{
|
||||
battleCardBase2 = targetList[0];
|
||||
num = 1;
|
||||
}
|
||||
}
|
||||
BattlePlayerPair battlePlayerPair = _ai.PlayerPair.VirtualClone(CloneActualFlags.All);
|
||||
battlePlayerPair.Self.AddCurrentTrunPlayCount(1);
|
||||
BattleCardBase battleCardBase3 = battlePlayerPair.Self.HandCardList.Where((BattleCardBase c) => c.Index == actor.Index && c.CardId == actor.CardId && c.IsPlayer == actor.IsPlayer).FirstOrDefault();
|
||||
if (battleCardBase3 != null)
|
||||
{
|
||||
battlePlayerPair.Self.HandCardList.Remove(battleCardBase3);
|
||||
}
|
||||
List<SkillBase> checkSkillList = GetCheckSkillList(battleCardBase2.Skills, battlePlayerPair);
|
||||
if (CheckSelectTypeSkillTargetCount(actor, checkSkillList, targetList, num, "[PlayCard]") || targetList != null)
|
||||
{
|
||||
CheckSelectTypeSkillTarget(actor, battlePlayerPair, checkSkillList, targetList, num, "[PlayCard]");
|
||||
}
|
||||
if (!targetList.IsNotNullOrEmpty() || !targetList.Any((BattleCardBase c) => c is IVirtualBattleCard) || !actor.Skills.HaveChoiceTransformSkill())
|
||||
{
|
||||
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.InitSetCard(actor, actor.IsPlayer, targetList.IsNotNullOrEmpty()));
|
||||
}
|
||||
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.PlayCard(actor, actor.IsPlayer, targetList));
|
||||
return sequentialVfxPlayer;
|
||||
}
|
||||
|
||||
public VfxBase AIEvolutionCard(AISituationInfo situation)
|
||||
{
|
||||
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
||||
if (!actor.CanEvolution(isSkill: false, isSelfBattlePlayer: true))
|
||||
{
|
||||
AIConsoleUtility.LogError("Evolution Condition Error!!!");
|
||||
}
|
||||
if (actor.EvolutionSkills.HasEvolutionSkillWithSelection)
|
||||
{
|
||||
List<SkillBase> checkSkillList = GetCheckSkillList(actor.EvolutionSkills, _ai.PlayerPair);
|
||||
CheckSelectTypeSkillTarget(actor, _ai.PlayerPair, checkSkillList, targetList, 0, "[Evolution]");
|
||||
}
|
||||
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
||||
VfxBase emote = _ai.GetEmote(AIEmoteCmdType.ON_ALLY_EVOLUTION, situation);
|
||||
sequentialVfxPlayer.Register(emote);
|
||||
if (emote != NullVfx.GetInstance())
|
||||
{
|
||||
_ai.EmoteQuery.OnCardPlayEmotion();
|
||||
}
|
||||
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.EvolutionCard(actor, actor.IsPlayer, targetList));
|
||||
return sequentialVfxPlayer;
|
||||
}
|
||||
|
||||
public VfxBase AIFusionCard(AISituationInfo situation)
|
||||
{
|
||||
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
||||
SkillBase item = actor.Skills.FirstOrDefault((SkillBase s) => s is Skill_fusion);
|
||||
CheckSelectTypeSkillTarget(actor, _ai.PlayerPair, new List<SkillBase> { item }, targetList, 0, "[Fusion]");
|
||||
return _battleMgr.OperateMgr.FusionCard(actor, actor.IsPlayer, targetList);
|
||||
}
|
||||
|
||||
private List<SkillBase> GetCheckSkillList(SkillCollectionBase skillCollection, BattlePlayerPair playerPair)
|
||||
{
|
||||
List<SkillBase> list = new List<SkillBase>();
|
||||
IEnumerable<SkillBase> selectTypeSkill = skillCollection.GetSelectTypeSkill(isEvolve: true, isFusion: false, isActivateFanfare: false, playerPair);
|
||||
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
||||
foreach (SkillBase item in skillCollection.Where((SkillBase s) => s.IsChoiceType && s.CheckCondition(playerPair, option, isPrePlay: true)))
|
||||
{
|
||||
if (!list.Contains(item))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
foreach (SkillBase item2 in selectTypeSkill)
|
||||
{
|
||||
if (!list.Contains(item2))
|
||||
{
|
||||
list.Add(item2);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void CheckSelectTypeSkillTarget(BattleCardBase actor, BattlePlayerPair playerPair, IEnumerable<SkillBase> skills, List<BattleCardBase> targetList, int selectTargetNumber, string checkTimingName)
|
||||
{
|
||||
int num = selectTargetNumber;
|
||||
bool flag = false;
|
||||
foreach (SkillBase skill in skills)
|
||||
{
|
||||
if (skill.IsBurialRite)
|
||||
{
|
||||
BattleCardBase card = targetList[num];
|
||||
if (!actor.SelfBattlePlayer.HandCardList.Any((BattleCardBase c) => c.Index == card.Index && c.IsPlayer == card.IsPlayer))
|
||||
{
|
||||
string message = actor.BaseParameter.CardName + checkTimingName + "BURIAL_RITE Target not in Hand list Error!!!";
|
||||
ThrowErrorMessage(message);
|
||||
}
|
||||
else if (!card.IsInHand || !card.IsUnit)
|
||||
{
|
||||
string message2 = actor.BaseParameter.CardName + checkTimingName + "BURIAL_RITE Wrong targeted selection criteria Error!!!";
|
||||
ThrowErrorMessage(message2);
|
||||
}
|
||||
flag = true;
|
||||
num++;
|
||||
}
|
||||
if (skill.ApplySelectFilter is SkillRandomSelectFilter || skill.ApplySelectFilter is SkillSelectAllFilter || (!skill.IsChoiceType && skill.ApplySelectFilter is SkillSelectNullFilter))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
IEnumerable<BattleCardBase> selectableCards = skill.GetSelectableCards(playerPair, new SkillConditionCheckerOption());
|
||||
int skillSelectCount = skill.GetSkillSelectCount();
|
||||
int num2 = targetList.Count - num;
|
||||
skillSelectCount = ((skillSelectCount > num2) ? num2 : skillSelectCount);
|
||||
List<BattleCardBase> list = new List<BattleCardBase>(targetList.GetRange(num, skillSelectCount));
|
||||
num += skillSelectCount;
|
||||
if (list.Count > 1)
|
||||
{
|
||||
for (int num3 = 0; num3 < list.Count; num3++)
|
||||
{
|
||||
BattleCardBase card2 = list[num3];
|
||||
List<BattleCardBase> list2 = list.Where((BattleCardBase c) => c.Index == card2.Index && c.IsPlayer == card2.IsPlayer).ToList();
|
||||
if (list2.Count > 1)
|
||||
{
|
||||
string message3 = $"{actor.BaseParameter.CardName}{checkTimingName}Duplicate {list2.Count} selected card Error!!!";
|
||||
ThrowErrorMessage(message3);
|
||||
}
|
||||
}
|
||||
}
|
||||
int num4 = 0;
|
||||
for (int num5 = 0; num5 < list.Count; num5++)
|
||||
{
|
||||
BattleCardBase card3 = list[num5];
|
||||
if (!selectableCards.Any((BattleCardBase c) => c.Index == card3.Index && c.IsPlayer == card3.IsPlayer))
|
||||
{
|
||||
if (num4 < selectableCards.Count() && !flag)
|
||||
{
|
||||
targetList[num5] = selectableCards.ElementAt(num4);
|
||||
num4++;
|
||||
}
|
||||
string message4 = actor.BaseParameter.CardName + checkTimingName + "Target not in selection list Error!!!";
|
||||
ThrowErrorMessage(message4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckSelectTypeSkillTargetCount(BattleCardBase actor, IEnumerable<SkillBase> skills, List<BattleCardBase> targetList, int selectCardCount, string checkTimingName)
|
||||
{
|
||||
string text = checkTimingName + actor.BaseParameter.CardName + "\n";
|
||||
int num = selectCardCount;
|
||||
foreach (SkillBase skill in skills)
|
||||
{
|
||||
if (skill.IsBurialRite)
|
||||
{
|
||||
selectCardCount++;
|
||||
num++;
|
||||
text += "BurialRite1回";
|
||||
if (skill is Skill_none)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!(skill.ApplySelectFilter is SkillRandomSelectFilter) && !(skill.ApplySelectFilter is SkillSelectAllFilter) && (!skill.IsBurialRite || skill.ApplySelectFilter is SkillUserSelectFilter) && (skill.IsChoiceType || !(skill.ApplySelectFilter is SkillSelectNullFilter)))
|
||||
{
|
||||
BattlePlayerReadOnlyInfoPair playerInfoPair = new BattlePlayerReadOnlyInfoPair(actor.SelfBattlePlayer, actor.OpponentBattlePlayer);
|
||||
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
||||
if (skill.CheckCondition(playerInfoPair, option, isPrePlay: true))
|
||||
{
|
||||
int skillSelectCount = skill.GetSkillSelectCount();
|
||||
selectCardCount += skillSelectCount;
|
||||
num += ((!actor.IsUnit && !actor.IsField) ? 1 : 0);
|
||||
text += $"{skill}{skillSelectCount}回";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectCardCount <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool flag = false;
|
||||
if (targetList == null || targetList.Count <= 0)
|
||||
{
|
||||
if (num <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
text += "\n選択されていません";
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = targetList.Count;
|
||||
int num2 = count - selectCardCount;
|
||||
if (num2 < 0 && count < num)
|
||||
{
|
||||
text += "\n少なく選択されています";
|
||||
flag = true;
|
||||
}
|
||||
if (num2 > 0)
|
||||
{
|
||||
text += $"\n{num2}回多く選択されています";
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
ThrowErrorMessage(text);
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
public int CalcFixedUseCostTransformId(BattleCardBase actor, int currentPp)
|
||||
{
|
||||
int num = -1;
|
||||
int cost = actor.Cost;
|
||||
int result = -1;
|
||||
for (int i = 0; i < actor.Skills.Count(); i++)
|
||||
{
|
||||
if (!(actor.Skills.ElementAt(i) is Skill_pp_fixeduse skill_pp_fixeduse) || currentPp < skill_pp_fixeduse._fixedUsePP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool num2 = skill_pp_fixeduse.CheckCondition(_ai.PlayerPair, new SkillConditionCheckerOption(), isPrePlay: true);
|
||||
bool flag = num2 && num < skill_pp_fixeduse._fixedUsePP;
|
||||
bool flag2 = num2 && skill_pp_fixeduse._fixedUsePP < cost && currentPp < cost;
|
||||
if (flag || flag2)
|
||||
{
|
||||
if (actor.Skills.ElementAt(i + 1) is Skill_transform skill_transform)
|
||||
{
|
||||
result = skill_transform.TransformId;
|
||||
}
|
||||
num = skill_pp_fixeduse._fixedUsePP;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ThrowErrorMessage(string message)
|
||||
{
|
||||
AIConsoleUtility.LogError(message);
|
||||
}
|
||||
}
|
||||
122
SVSim.BattleEngine/Engine/Wizard/AIOperationSimulatorAccessor.cs
Normal file
122
SVSim.BattleEngine/Engine/Wizard/AIOperationSimulatorAccessor.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Wizard.Battle.Operation;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIOperationSimulatorAccessor
|
||||
{
|
||||
private EnemyAI _ai;
|
||||
|
||||
private List<BattleCardBase> _selectedSkillTargetList = new List<BattleCardBase>();
|
||||
|
||||
public AIVirtualField CurrentField { get; private set; }
|
||||
|
||||
public AIGenerateTagOwnerTable GenerateTagOwnerTable { get; private set; }
|
||||
|
||||
public AIBattleInfoReceivedData BattleInfoReceiveDate { get; private set; } = new AIBattleInfoReceivedData();
|
||||
|
||||
public AIOperationSimulatorAccessor(EnemyAI ai)
|
||||
{
|
||||
CurrentField = null;
|
||||
Initialize(ai);
|
||||
}
|
||||
|
||||
public AIOperationSimulatorAccessor(EnemyAI ai, AIVirtualField field)
|
||||
{
|
||||
CurrentField = field;
|
||||
Initialize(ai);
|
||||
}
|
||||
|
||||
private void Initialize(EnemyAI ai)
|
||||
{
|
||||
_ai = ai;
|
||||
GenerateTagOwnerTable = ai.GenerateTagOwnerTable.Clone();
|
||||
}
|
||||
|
||||
public BattlePlayerPair CallAttack(BattlePlayerPair sourcePair, BattleCardBase attackCardId, BattleCardBase targetCardId, List<int> playPtn)
|
||||
{
|
||||
UpdateCurrentField(sourcePair, playPtn);
|
||||
SetUpBattleInfoReceiver();
|
||||
BattlePlayerPair battlePlayerPair = OperationSimulator.Attack(sourcePair, attackCardId, targetCardId, isPrediction: false, SetVirtualPairEvent);
|
||||
CleanUpBattleInfoReceiver();
|
||||
UpdateCurrentField(battlePlayerPair, playPtn);
|
||||
return battlePlayerPair;
|
||||
}
|
||||
|
||||
public BattlePlayerPair CallPlay(BattlePlayerPair sourcePair, BattleCardBase playCardId, List<BattleCardBase> skillTargets, List<int> playPtn)
|
||||
{
|
||||
UpdateCurrentField(sourcePair, playPtn);
|
||||
Action<BattleCardBase> playCardSkillEvent = delegate(BattleCardBase card)
|
||||
{
|
||||
BattlePlayerPair pair = new BattlePlayerPair(card.SelfBattlePlayer, card.OpponentBattlePlayer);
|
||||
EnemyAIUtil.SetupPlayCardSkillOptionValue(card, pair);
|
||||
};
|
||||
SetUpBattleInfoReceiver();
|
||||
BattlePlayerPair battlePlayerPair = OperationSimulator.Play(sourcePair, playCardId, skillTargets, SetVirtualPairEvent, playCardSkillEvent);
|
||||
CleanUpBattleInfoReceiver();
|
||||
List<int> list = new List<int>();
|
||||
for (int num = 1; num < playPtn.Count; num++)
|
||||
{
|
||||
BattleCardBase oldCard = sourcePair.Self.HandCardList[playPtn[num]];
|
||||
BattleCardBase battleCardBase = battlePlayerPair.Self.HandCardList.FirstOrDefault((BattleCardBase c) => c.Index == oldCard.Index || c.BaseParameter.BaseCardId == oldCard.BaseParameter.BaseCardId);
|
||||
if (battleCardBase != null)
|
||||
{
|
||||
list.Add(battlePlayerPair.Self.HandCardList.IndexOf(battleCardBase));
|
||||
}
|
||||
}
|
||||
UpdateCurrentField(battlePlayerPair, list);
|
||||
return battlePlayerPair;
|
||||
}
|
||||
|
||||
public BattlePlayerPair CallEvolve(BattlePlayerPair sourcePair, BattleCardBase evolutionCardId, List<BattleCardBase> skillTargets, List<int> playPtn)
|
||||
{
|
||||
UpdateCurrentField(sourcePair, playPtn);
|
||||
SetUpBattleInfoReceiver();
|
||||
BattlePlayerPair battlePlayerPair = OperationSimulator.Evolve(sourcePair, evolutionCardId, skillTargets, SetVirtualPairEvent);
|
||||
CleanUpBattleInfoReceiver();
|
||||
UpdateCurrentField(battlePlayerPair, playPtn);
|
||||
return battlePlayerPair;
|
||||
}
|
||||
|
||||
public BattlePlayerPair CallTurnEnd(BattlePlayerPair sourcePair)
|
||||
{
|
||||
SetUpBattleInfoReceiver();
|
||||
BattlePlayerPair result = OperationSimulator.TurnEnd(sourcePair);
|
||||
CleanUpBattleInfoReceiver();
|
||||
return result;
|
||||
}
|
||||
|
||||
public BattlePlayerPair CallOpponentTurnStart(BattlePlayerPair sourcePair)
|
||||
{
|
||||
BattlePlayerPair sourcePair2 = new BattlePlayerPair(sourcePair.Opponent, sourcePair.Self);
|
||||
SetUpBattleInfoReceiver();
|
||||
BattlePlayerPair battlePlayerPair = OperationSimulator.TurnStart(sourcePair2);
|
||||
CleanUpBattleInfoReceiver();
|
||||
return new BattlePlayerPair(battlePlayerPair.Opponent, battlePlayerPair.Self);
|
||||
}
|
||||
|
||||
public void UpdateCurrentField(BattlePlayerPair sourcePair, List<int> playPtn)
|
||||
{
|
||||
AIVirtualFieldBuildParameterCollction buildParameters = new AIVirtualFieldBuildParameterCollction(CurrentField);
|
||||
CurrentField = AIVirtualField.CreateTemporaryVirtualField(_ai, _ai.ParamQuery, _ai.StyleQuery, sourcePair, playPtn, buildParameters);
|
||||
GenerateTagOwnerTable.RegisterAllGenerateTagOwner(CurrentField);
|
||||
_selectedSkillTargetList.Clear();
|
||||
}
|
||||
|
||||
public void SetVirtualPairEvent(BattlePlayerPair virtualPair)
|
||||
{
|
||||
AIAttachEventToBattleModuleUtility.SetupVirtualPairEventForOperationSimulator(virtualPair, this);
|
||||
}
|
||||
|
||||
private void SetUpBattleInfoReceiver()
|
||||
{
|
||||
AIBattleInfoReceiver.GetInstance()?.SetUpOprSimAccessor(this);
|
||||
}
|
||||
|
||||
private void CleanUpBattleInfoReceiver()
|
||||
{
|
||||
AIBattleInfoReceiver.GetInstance()?.CleanUpOprSimAccessor();
|
||||
}
|
||||
}
|
||||
12
SVSim.BattleEngine/Engine/Wizard/AIOperationType.cs
Normal file
12
SVSim.BattleEngine/Engine/Wizard/AIOperationType.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIOperationType
|
||||
{
|
||||
ATTACK,
|
||||
EVOLVE,
|
||||
PLAY,
|
||||
FUSION,
|
||||
TURNEND,
|
||||
TURNSTART,
|
||||
UNKNOWN
|
||||
}
|
||||
64
SVSim.BattleEngine/Engine/Wizard/AIOwnSkillProcessRecord.cs
Normal file
64
SVSim.BattleEngine/Engine/Wizard/AIOwnSkillProcessRecord.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIOwnSkillProcessRecord
|
||||
{
|
||||
public List<AIVirtualCard> OwnDestroyedCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> OwnBanishedCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> OwnSummonedCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> OwnLatestSummonedCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> OwnLatestDrewCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> LatestTargets { get; private set; }
|
||||
|
||||
public int DefaultDamage { get; private set; } = -1;
|
||||
|
||||
public void AddOwnDestroyedCard(AIVirtualCard card)
|
||||
{
|
||||
OwnDestroyedCards = AIParamQuery.AddElementToList(card, OwnDestroyedCards);
|
||||
}
|
||||
|
||||
public void AddOwnBanishedCard(AIVirtualCard card)
|
||||
{
|
||||
OwnBanishedCards = AIParamQuery.AddElementToList(card, OwnBanishedCards);
|
||||
}
|
||||
|
||||
public void AddOwnSummonedCards(List<AIVirtualCard> list)
|
||||
{
|
||||
OwnSummonedCards = AIParamQuery.AddRangeToList(list, OwnSummonedCards);
|
||||
OwnLatestSummonedCards = list;
|
||||
}
|
||||
|
||||
public void AddOwnDrewCards(List<AIVirtualCard> list)
|
||||
{
|
||||
OwnLatestDrewCards = list;
|
||||
}
|
||||
|
||||
public void RegisterSingleLatestTarget(AIVirtualCard card)
|
||||
{
|
||||
if (LatestTargets != null)
|
||||
{
|
||||
LatestTargets.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
LatestTargets = new List<AIVirtualCard>();
|
||||
}
|
||||
LatestTargets.Add(card);
|
||||
}
|
||||
|
||||
public void RegisterLatestTargetList(List<AIVirtualCard> list)
|
||||
{
|
||||
LatestTargets = list;
|
||||
}
|
||||
|
||||
public void RegisterDefaultDamage(int damage)
|
||||
{
|
||||
DefaultDamage = damage;
|
||||
}
|
||||
}
|
||||
420
SVSim.BattleEngine/Engine/Wizard/AIParamQuery.cs
Normal file
420
SVSim.BattleEngine/Engine/Wizard/AIParamQuery.cs
Normal file
@@ -0,0 +1,420 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
using Wizard.Battle;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIParamQuery
|
||||
{
|
||||
private const float MAX_ADVANTAGE = 1000f;
|
||||
|
||||
public EnemyAI enemyAI;
|
||||
|
||||
public AIStyleQuery styleQuery;
|
||||
|
||||
private int classID;
|
||||
|
||||
private AI_LOGIC_LV logicLv = AI_LOGIC_LV.STRONG;
|
||||
|
||||
private AIDeckAcccessor deck;
|
||||
|
||||
public AIParamQuery(EnemyAI ai)
|
||||
{
|
||||
enemyAI = ai;
|
||||
}
|
||||
|
||||
public void SetUp(AIStyleQuery _styleQuery)
|
||||
{
|
||||
styleQuery = _styleQuery;
|
||||
}
|
||||
|
||||
public void SetDeck(int _classID, AI_LOGIC_LV _logicLv, AIDeckData _curDeck, AIDeckData _commonDic, AIDeckData _allyCommonDic)
|
||||
{
|
||||
classID = _classID;
|
||||
logicLv = _logicLv;
|
||||
deck = new AIDeckAcccessor(_curDeck, _commonDic, _allyCommonDic);
|
||||
}
|
||||
|
||||
public AICardData SearchAICardData(AIVirtualCard card)
|
||||
{
|
||||
if (!card.IsLeader && deck != null)
|
||||
{
|
||||
return deck.SearchCardData(card.BaseId, card.IsAlly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetClassID()
|
||||
{
|
||||
return classID;
|
||||
}
|
||||
|
||||
public AI_LOGIC_LV GetLogicLv()
|
||||
{
|
||||
return logicLv;
|
||||
}
|
||||
|
||||
public bool IsEnabledTag(AIVirtualCard card, AIVirtualField field, AIPlayTagType type, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
int tagCount = GetTagCount(card);
|
||||
if (tagCount <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
{
|
||||
AIPlayTag tag = GetTag(card, i);
|
||||
if (tag.Type == type && tag.CheckCondition(card, playPtn, card.SelfField, situation))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetTagCount(AIVirtualCard owner, AICardData data = null)
|
||||
{
|
||||
if (deck == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AICardData aICardData = null;
|
||||
if (!owner.IsLeader)
|
||||
{
|
||||
aICardData = ((data == null) ? deck.SearchCardData(owner.BaseId, enemyAI.IsAllyCard(owner)) : data);
|
||||
}
|
||||
int num = 0;
|
||||
if (aICardData != null && aICardData.TagList != null && !owner.IsSkillLost)
|
||||
{
|
||||
if (owner.IsRobbedLastword)
|
||||
{
|
||||
for (int i = 0; i < aICardData.TagList.Count; i++)
|
||||
{
|
||||
if (!aICardData.TagList[i].IsLastwordTag())
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num += aICardData.TagList.Count;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public AIPlayTag GetTag(AIVirtualCard owner, int index, AICardData data = null)
|
||||
{
|
||||
AICardData aICardData = null;
|
||||
if (!owner.IsLeader)
|
||||
{
|
||||
aICardData = ((data == null) ? deck.SearchCardData(owner.BaseId, enemyAI.IsAllyCard(owner)) : data);
|
||||
}
|
||||
int num = 0;
|
||||
if (aICardData != null && aICardData.TagList != null && !owner.IsSkillLost)
|
||||
{
|
||||
if (owner.IsRobbedLastword)
|
||||
{
|
||||
for (int i = 0; i < aICardData.TagList.Count; i++)
|
||||
{
|
||||
if (!aICardData.TagList[i].IsLastwordTag())
|
||||
{
|
||||
if (num == index)
|
||||
{
|
||||
return aICardData.TagList[i];
|
||||
}
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num = aICardData.TagList.Count;
|
||||
if (aICardData.TagList.Count > index)
|
||||
{
|
||||
return aICardData.TagList[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsRobbedLastword(BattleCardBase card)
|
||||
{
|
||||
for (int i = 0; i < card.BuffInfoList.Count; i++)
|
||||
{
|
||||
BuffInfo buffInfo = card.BuffInfoList[i];
|
||||
if (buffInfo.PreviousOwner == null && buffInfo.SkillFrom is Skill_rob_skill)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float EvaluateBattlePlayerPair(AIVirtualField field, bool useStyle = true)
|
||||
{
|
||||
float num = 0f;
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyInplayCards[i];
|
||||
if (!aIVirtualCard.IsDead && aIVirtualCard.IsOnField)
|
||||
{
|
||||
float num2 = aIVirtualCard.EvaluateValueOnField(EnemyAI.EmptyPlayPtn, null, useStyle);
|
||||
num += num2;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < field.EnemyInplayCards.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = field.EnemyInplayCards[j];
|
||||
if (!aIVirtualCard2.IsDead && aIVirtualCard2.IsOnField)
|
||||
{
|
||||
float num3 = aIVirtualCard2.EvaluateValueOnField(EnemyAI.EmptyPlayPtn, null, useStyle);
|
||||
num -= num3;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public IEnumerable<BattleCardBase> RemoveDuplicatedCards(IEnumerable<BattleCardBase> targetCards, IEnumerable<BattleCardBase> filterCards)
|
||||
{
|
||||
if (!targetCards.IsNotNullOrEmpty() || !filterCards.IsNotNullOrEmpty())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach (BattleCardBase targetCard in targetCards)
|
||||
{
|
||||
bool flag = false;
|
||||
foreach (BattleCardBase filterCard in filterCards)
|
||||
{
|
||||
if (filterCard != null && targetCard.IsPlayer == filterCard.IsPlayer && targetCard.Index == filterCard.Index)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
yield return targetCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBanishSkill(SkillBase skill)
|
||||
{
|
||||
if (!(skill is Skill_banish) && !(skill is Skill_destroy) && !(skill is Skill_damage) && !(skill is Skill_return_card))
|
||||
{
|
||||
return skill is Skill_metamorphose;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public float CalcHandCardOverflowPenalty(AIVirtualField field, List<int> playPtn, float penalty, ref int dstHandCount)
|
||||
{
|
||||
float num = 0f;
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
int index = playPtn[i];
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[index];
|
||||
int handPlusCount = aIVirtualCard.GetHandPlusCount(playPtn);
|
||||
_ = aIVirtualCard.IsSpell;
|
||||
dstHandCount--;
|
||||
dstHandCount += handPlusCount;
|
||||
if (dstHandCount > 9)
|
||||
{
|
||||
num += penalty * (float)(dstHandCount - 9);
|
||||
dstHandCount = 9;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < field.AllyInplayCards.Count; j++)
|
||||
{
|
||||
AIVirtualCard tagOwner = field.AllyInplayCards[j];
|
||||
dstHandCount += tagOwner.GetHandPlusCount(playPtn);
|
||||
}
|
||||
if (dstHandCount > 8)
|
||||
{
|
||||
num += penalty * (float)(dstHandCount - 8);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public List<BattleCardBase> GetEvoSelectCandidates(BattleCardBase evoCard, BattlePlayerPair pair)
|
||||
{
|
||||
List<SkillBase> list = evoCard.GetSelectTypeSkill(isEvolve: true).ToList();
|
||||
if (list.IsNotNullOrEmpty())
|
||||
{
|
||||
return GetSkillTargetsForEstimator(evoCard, list, pair);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<BattleCardBase> GetSkillTargetsForEstimator(BattleCardBase actCard, List<SkillBase> selectSkills, BattlePlayerPair pair)
|
||||
{
|
||||
List<BattleCardBase> list = new List<BattleCardBase>();
|
||||
for (int i = 0; i < selectSkills.Count; i++)
|
||||
{
|
||||
SkillBase skillBase = selectSkills[i];
|
||||
IEnumerable<BattleCardBase> burialSelectableCards = AIBurialRiteSimulationUtility.GetBurialSelectableCards(skillBase, actCard);
|
||||
if (burialSelectableCards.IsNotNullOrEmpty())
|
||||
{
|
||||
List<BattleCardBase> list2 = burialSelectableCards.ToList();
|
||||
for (int j = 0; j < list2.Count; j++)
|
||||
{
|
||||
BattleCardBase item = list2[j];
|
||||
if (!list.Contains(item))
|
||||
{
|
||||
list.Add(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
IEnumerable<BattleCardBase> selectableCards = GetSelectableCards(skillBase, pair);
|
||||
if (!selectableCards.IsNotNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<BattleCardBase> list3 = selectableCards.ToList();
|
||||
list3.AddRange(from c in GetSelectableCards(skillBase, pair, isSkipForceSelect: true)
|
||||
where !selectableCards.Contains(c)
|
||||
select c);
|
||||
int num = Mathf.Min(skillBase.GetSkillSelectCount(), list3.Count());
|
||||
for (int num2 = 0; num2 < num; num2++)
|
||||
{
|
||||
if (list3.Contains(pair.Opponent.Class) && !list.Contains(pair.Opponent.Class))
|
||||
{
|
||||
list.Add(pair.Opponent.Class);
|
||||
continue;
|
||||
}
|
||||
for (int num3 = 0; num3 < list3.Count; num3++)
|
||||
{
|
||||
BattleCardBase item2 = list3[num3];
|
||||
if (!list.Contains(item2))
|
||||
{
|
||||
list.Add(item2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public int CalcAllyUnitTotalDamage()
|
||||
{
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in enemyAI.ALLY.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.IsUnit)
|
||||
{
|
||||
int num2 = inPlayCard.MaxLife - inPlayCard.Life;
|
||||
num += num2;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public int GetEnemyGuardiansCount()
|
||||
{
|
||||
int num = 0;
|
||||
foreach (BattleCardBase inPlayCard in enemyAI.OPPONENT.InPlayCards)
|
||||
{
|
||||
if (inPlayCard.SkillApplyInformation.IsGuard)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public IEnumerable<BattleCardBase> GetSelectSkillTargetCandidates(BattleCardBase card, BattlePlayerReadOnlyInfoPair pair)
|
||||
{
|
||||
SkillBase actSkill = null;
|
||||
return ActionProcessor.GetSkillUserSelectableTargets(card.Skills, pair, ref actSkill);
|
||||
}
|
||||
|
||||
public bool IsDestroyBeforeAttack(BattleCardBase card)
|
||||
{
|
||||
if (card.IsUnit)
|
||||
{
|
||||
return card.Skills.Any((SkillBase skill) => skill is Skill_destroy && skill.IsBeforAttackSkill);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<IReadOnlyBattleCardInfo> GetBrokenAll(BattleCardBase card)
|
||||
{
|
||||
SkillTargetDestroyedCardListFilter skillTargetDestroyedCardListFilter = new SkillTargetDestroyedCardListFilter();
|
||||
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
||||
IBattlePlayerReadOnlyInfo[] battlePlayerInfos = new IBattlePlayerReadOnlyInfo[1] { card.SelfBattlePlayer };
|
||||
return skillTargetDestroyedCardListFilter.Filtering(battlePlayerInfos, option);
|
||||
}
|
||||
|
||||
public IEnumerable<BattleCardBase> GetSelectableCards(SkillBase skill, BattlePlayerPair pair, bool isSkipForceSelect = false)
|
||||
{
|
||||
if (skill.IsUserSelectType || skill.IsChoiceType)
|
||||
{
|
||||
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
||||
return skill.GetSelectableCards(pair, option, isSkipForceSelect);
|
||||
}
|
||||
return new List<BattleCardBase>();
|
||||
}
|
||||
|
||||
public static List<T> AddElementToList<T>(T element, List<T> container, bool isBlockDuplicate = false)
|
||||
{
|
||||
if (container == null)
|
||||
{
|
||||
container = new List<T>();
|
||||
}
|
||||
if (!isBlockDuplicate || !container.Contains(element))
|
||||
{
|
||||
container.Add(element);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
public static List<T> AddRangeToList<T>(List<T> elements, List<T> container, bool isBlockDuplicate = false)
|
||||
{
|
||||
if (elements == null || elements.Count <= 0)
|
||||
{
|
||||
return container;
|
||||
}
|
||||
if (container == null)
|
||||
{
|
||||
container = new List<T>();
|
||||
}
|
||||
for (int i = 0; i < elements.Count; i++)
|
||||
{
|
||||
T item = elements[i];
|
||||
if (!isBlockDuplicate || !container.Contains(item))
|
||||
{
|
||||
container.Add(item);
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
public static List<T> CloneList<T>(List<T> src)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new List<T>(src);
|
||||
}
|
||||
|
||||
public static AIVirtualCard FindSameCardFromList<T>(AIVirtualCard origin, List<T> list) where T : AIVirtualCard
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (aIVirtualCard.IsSameCard(origin))
|
||||
{
|
||||
return aIVirtualCard;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
30
SVSim.BattleEngine/Engine/Wizard/AIPlayOutAction.cs
Normal file
30
SVSim.BattleEngine/Engine/Wizard/AIPlayOutAction.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayOutAction
|
||||
{
|
||||
public int UseCardIndex { get; private set; }
|
||||
|
||||
public AIOperationType Command { get; private set; }
|
||||
|
||||
public List<BattleCardBase> TargetCardList { get; private set; }
|
||||
|
||||
public AIPlayOutAction(AIOperationType command, BattleCardBase useCard, List<BattleCardBase> targetCards)
|
||||
{
|
||||
Command = command;
|
||||
if (useCard != null)
|
||||
{
|
||||
UseCardIndex = useCard.Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
UseCardIndex = -1;
|
||||
}
|
||||
TargetCardList = new List<BattleCardBase>();
|
||||
if (targetCards != null && targetCards.Count > 0)
|
||||
{
|
||||
TargetCardList.AddRange(targetCards);
|
||||
}
|
||||
}
|
||||
}
|
||||
960
SVSim.BattleEngine/Engine/Wizard/AIPlayTag.cs
Normal file
960
SVSim.BattleEngine/Engine/Wizard/AIPlayTag.cs
Normal file
@@ -0,0 +1,960 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayTag
|
||||
{
|
||||
public static readonly int TAG_WORDS_LENTGH = 3;
|
||||
|
||||
private string _typeText;
|
||||
|
||||
private string _argText;
|
||||
|
||||
private string _conditionText;
|
||||
|
||||
private AIScriptArgumentExpressions argExpr;
|
||||
|
||||
private AIConditionExpressions condExpr;
|
||||
|
||||
public AIPlayTagType Type { get; private set; }
|
||||
|
||||
public string Arg => _argText;
|
||||
|
||||
public string Condition => _conditionText;
|
||||
|
||||
public ulong Hash { get; private set; }
|
||||
|
||||
public AIScriptArgumentExpressions ArgumentExpressions => argExpr;
|
||||
|
||||
public AIConditionExpressions ConditionExpressions => condExpr;
|
||||
|
||||
public bool InitFromTextAsset(AIPlayTagAsset asset)
|
||||
{
|
||||
Type = AIScriptParser.ConvertWordToTagType(asset.Type);
|
||||
if (Type == AIPlayTagType.None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (CheckInvalidTagPattern(asset, out var _))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_typeText = asset.Type;
|
||||
_argText = asset.Arg;
|
||||
_conditionText = asset.Condition;
|
||||
Hash = GetHash();
|
||||
argExpr = CreateArgument(_argText);
|
||||
condExpr = new AIConditionExpressions(_conditionText);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckInvalidTagPattern(AIPlayTagAsset asset, out string errorLog)
|
||||
{
|
||||
errorLog = "";
|
||||
bool flag = false;
|
||||
switch (Type)
|
||||
{
|
||||
case AIPlayTagType.FanfareToken:
|
||||
case AIPlayTagType.PlayToken:
|
||||
flag = asset.Arg.IndexOf("PLAY_TOKEN_COUNT") >= 0 || asset.Condition.IndexOf("PLAY_TOKEN_COUNT") >= 0;
|
||||
if (flag)
|
||||
{
|
||||
errorLog = "タグ " + asset.Type + " のArgに PLAY_TOKEN_COUNT が使用されています。\n";
|
||||
}
|
||||
break;
|
||||
case AIPlayTagType.TurnEndActivateCount:
|
||||
flag = asset.Condition.IndexOf("IS_IN_HAND") < 0 && asset.Condition.IndexOf("IS_ON_FIELD") < 0;
|
||||
if (flag)
|
||||
{
|
||||
errorLog = "タグ " + asset.Type + " のCondに IS_IN_HAND,IS_ON_FIELD のどちらも指定されていません。\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
AIPlayTagType type = Type;
|
||||
if ((uint)(type - 23) > 2u && (uint)(type - 27) > 1u && asset.Condition.IndexOf("NEXT_PLAY_PRIORITY ") > 0)
|
||||
{
|
||||
flag = true;
|
||||
errorLog = "PlaySkip系以外のタグ " + asset.Type + " のCondには NEXT_PLAY_PRIORITY を使用することを許可されていません。\n";
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
errorLog = errorLog + "tag:" + asset.Type + ", arg:" + asset.Arg + ", cond:" + asset.Condition;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
private AIScriptArgumentExpressions CreateArgument(string arg)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case AIPlayTagType.AllyPlayBonus:
|
||||
case AIPlayTagType.EnemyPlayBonus:
|
||||
return new AIOtherPlayBonus(arg);
|
||||
case AIPlayTagType.MemberBattleBonusRate:
|
||||
case AIPlayTagType.EnemyBattleBonusRate:
|
||||
return new AIOtherBattleBonusRate(arg);
|
||||
case AIPlayTagType.MemberEvoBonus:
|
||||
case AIPlayTagType.EnemyEvoBonus:
|
||||
return new AIOtherEvoBonus(arg);
|
||||
case AIPlayTagType.PlayAttachTag:
|
||||
case AIPlayTagType.FanfareAttachTag:
|
||||
return new AIWhenPlayAttachTag(arg);
|
||||
case AIPlayTagType.PlayCopyTag:
|
||||
case AIPlayTagType.FanfareCopyTag:
|
||||
return new AIWhenPlayCopyTag(arg);
|
||||
case AIPlayTagType.AttackAttachTag:
|
||||
return new AIAttackAttachTag(arg);
|
||||
case AIPlayTagType.LastwordAttachTag:
|
||||
return new AILastwordAttachTag(arg);
|
||||
case AIPlayTagType.EvoAttachTag:
|
||||
return new AIEvoAttachTag(arg);
|
||||
case AIPlayTagType.SummonAttachTag:
|
||||
return new AISummonAttachTag(arg);
|
||||
case AIPlayTagType.OtherSummonAttachTag:
|
||||
return new AIOtherSummonAttachTag(arg);
|
||||
case AIPlayTagType.FanfareAttachStyle:
|
||||
return new AIWhenPlayAttachStyle(arg);
|
||||
case AIPlayTagType.FanfareToken:
|
||||
case AIPlayTagType.PlayToken:
|
||||
return new AIWhenPlaySummonToken(arg);
|
||||
case AIPlayTagType.BreakAttachTag:
|
||||
return new AIBreakAttachTag(arg);
|
||||
case AIPlayTagType.NecromanceAttachTag:
|
||||
return new AINecromanceAttachTag(arg);
|
||||
case AIPlayTagType.NecromanceAddCemetery:
|
||||
return new AINecromanceAddCemetery(arg);
|
||||
case AIPlayTagType.TurnStartAttachTag:
|
||||
return new AITurnStartAttachTag(arg);
|
||||
case AIPlayTagType.TurnStartSubtractCountdown:
|
||||
return new AITurnStartSubtractCountdown(arg);
|
||||
case AIPlayTagType.TurnStartDamageCut:
|
||||
return new AITurnStartDamageCut(arg);
|
||||
case AIPlayTagType.TurnStartShield:
|
||||
return new AITurnStartShield(arg);
|
||||
case AIPlayTagType.TurnStartDamage:
|
||||
return new AITurnStartDamage(arg);
|
||||
case AIPlayTagType.TurnEndAttachTag:
|
||||
return new AITurnEndAttachTag(arg);
|
||||
case AIPlayTagType.HealAttachTag:
|
||||
return new AIHealAttachTag(arg);
|
||||
case AIPlayTagType.DiscardedToken:
|
||||
return new AIDiscardedToken(arg);
|
||||
case AIPlayTagType.LeaveToken:
|
||||
return new AILeaveToken(arg);
|
||||
case AIPlayTagType.DamagedToken:
|
||||
return new AIDamagedToken(arg);
|
||||
case AIPlayTagType.PlayDamage:
|
||||
case AIPlayTagType.FanfareDamage:
|
||||
return new AIWhenPlayDamage(arg);
|
||||
case AIPlayTagType.PlayBuff:
|
||||
case AIPlayTagType.FanfareBuff:
|
||||
return new AIWhenPlayBuff(arg);
|
||||
case AIPlayTagType.PlaySetMaxStatus:
|
||||
case AIPlayTagType.FanfareSetMaxStatus:
|
||||
return new AIWhenPlaySetMaxStatus(arg);
|
||||
case AIPlayTagType.PlaySetLeaderMaxLife:
|
||||
return new AIWhenPlaySetLeaderMaxLife(arg);
|
||||
case AIPlayTagType.PlayDestroy:
|
||||
case AIPlayTagType.FanfareDestroy:
|
||||
return new AIWhenPlayDestroy(arg);
|
||||
case AIPlayTagType.PlayBanish:
|
||||
case AIPlayTagType.FanfareBanish:
|
||||
return new AIWhenPlayBanish(arg);
|
||||
case AIPlayTagType.PlayBounce:
|
||||
case AIPlayTagType.FanfareBounce:
|
||||
return new AIWhenPlayBounce(arg);
|
||||
case AIPlayTagType.PlayMetamorphose:
|
||||
case AIPlayTagType.FanfareMetamorphose:
|
||||
return new AIWhenPlayMetamorphose(arg);
|
||||
case AIPlayTagType.PlayHandMetamorphose:
|
||||
case AIPlayTagType.FanfareHandMetamorphose:
|
||||
return new AIWhenPlayHandMetamorphose(arg);
|
||||
case AIPlayTagType.FanfareSpellboost:
|
||||
case AIPlayTagType.PlaySpellboost:
|
||||
return new AIWhenPlaySpellboost(arg);
|
||||
case AIPlayTagType.FanfareAddCemetery:
|
||||
case AIPlayTagType.PlayAddCemetery:
|
||||
return new AIWhenPlayAddCemetery(arg);
|
||||
case AIPlayTagType.PlayReanimate:
|
||||
case AIPlayTagType.FanfareReanimate:
|
||||
return new AIWhenPlayReanimate(arg);
|
||||
case AIPlayTagType.PlayBanAttack:
|
||||
case AIPlayTagType.FanfareBanAttack:
|
||||
return new AIWhenPlayBanAttack(arg);
|
||||
case AIPlayTagType.FanfareHandBuff:
|
||||
case AIPlayTagType.PlayHandBuff:
|
||||
return new AIWhenPlayHandBuff(arg);
|
||||
case AIPlayTagType.PlayChangeCost:
|
||||
case AIPlayTagType.FanfareChangeCost:
|
||||
return new AIWhenPlayChangeCost(arg);
|
||||
case AIPlayTagType.FanfareBonusInSimulation:
|
||||
case AIPlayTagType.PlayBonusInSimulation:
|
||||
return new AIWhenPlayBonusInSimulation(arg);
|
||||
case AIPlayTagType.Target:
|
||||
case AIPlayTagType.IgnoreTarget:
|
||||
case AIPlayTagType.AttackByLife:
|
||||
case AIPlayTagType.FirstEvo:
|
||||
return new AIFiltersArgument(arg);
|
||||
case AIPlayTagType.PlaySkip:
|
||||
return new AIPlaySkipTagArgument(arg);
|
||||
case AIPlayTagType.PlaySkipWithEvo:
|
||||
return new AIPlaySkipWithEvo(arg);
|
||||
case AIPlayTagType.PlaySkipIfEvo:
|
||||
return new AIPlaySkipIfEvo(arg);
|
||||
case AIPlayTagType.PlaySkipWithAction:
|
||||
return new AIPlaySkipWithAction(arg);
|
||||
case AIPlayTagType.PlaySkipWithActionIfEvo:
|
||||
return new AIPlaySkipWithActionIfEvo(arg);
|
||||
case AIPlayTagType.AttackDamage:
|
||||
return new AIAttackDamage(arg);
|
||||
case AIPlayTagType.AttackDestroy:
|
||||
return new AIAttackDestroy(arg);
|
||||
case AIPlayTagType.ClashBanish:
|
||||
case AIPlayTagType.AttackBanish:
|
||||
return new AIAttackOrClashBanish(arg);
|
||||
case AIPlayTagType.ClashHeal:
|
||||
case AIPlayTagType.AttackHeal:
|
||||
return new AIAttackOrClashHeal(arg);
|
||||
case AIPlayTagType.AttackEvo:
|
||||
return new AIAttackEvo(arg);
|
||||
case AIPlayTagType.AttackBreakDamage:
|
||||
return new AIAttackBreakDamage(arg);
|
||||
case AIPlayTagType.AttackBreakEvo:
|
||||
return new AIAttackBreakEvo(arg);
|
||||
case AIPlayTagType.AttackBreakRecoverPp:
|
||||
return new AIAttackBreakRecoverPp(arg);
|
||||
case AIPlayTagType.AttackBreakAttackTwice:
|
||||
return new AIAttackBreakAttackTwice(arg);
|
||||
case AIPlayTagType.ClashToken:
|
||||
case AIPlayTagType.AttackToken:
|
||||
return new AIAttackOrClashToken(arg);
|
||||
case AIPlayTagType.AttackAttackableCount:
|
||||
return new AIAttackAttackableCount(arg);
|
||||
case AIPlayTagType.AttackQuick:
|
||||
return new AIAttackOrClashKeywordSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.PlayHeal:
|
||||
case AIPlayTagType.FanfareHeal:
|
||||
return new AIWhenPlayHeal(arg);
|
||||
case AIPlayTagType.AttackBuff:
|
||||
return new AIAttackBuff(arg);
|
||||
case AIPlayTagType.AttackHandBuff:
|
||||
return new AIAttackHandBuff(arg);
|
||||
case AIPlayTagType.SummonBuff:
|
||||
return new AISummonBuff(arg);
|
||||
case AIPlayTagType.SummonDestroy:
|
||||
return new AISummonDestroy(arg);
|
||||
case AIPlayTagType.SummonBanAttack:
|
||||
return new AISummonBanAttack(arg);
|
||||
case AIPlayTagType.BreakDamage:
|
||||
return new AIBreakDamage(arg);
|
||||
case AIPlayTagType.BreakRecoverAttackableCount:
|
||||
return new AIBreakRecoverAttackableCount(arg);
|
||||
case AIPlayTagType.LastwordDestroy:
|
||||
return new AILastwordDestroy(arg);
|
||||
case AIPlayTagType.DamagedBonus:
|
||||
return new AIDamagedBonus(arg);
|
||||
case AIPlayTagType.DamagedBuff:
|
||||
return new AIDamagedBuff(arg);
|
||||
case AIPlayTagType.DamagedDamage:
|
||||
return new AIDamagedDamage(arg);
|
||||
case AIPlayTagType.DamagedHeal:
|
||||
return new AIDamagedHeal(arg);
|
||||
case AIPlayTagType.DamagedCantUnderAttack:
|
||||
return new AIDamagedCantUnderAttack(arg);
|
||||
case AIPlayTagType.OtherDamagedDamage:
|
||||
return new AIOtherDamagedDamage(arg);
|
||||
case AIPlayTagType.OtherDamagedHeal:
|
||||
return new AIOtherDamagedHeal(arg);
|
||||
case AIPlayTagType.OtherDamagedSetLeaderMaxLife:
|
||||
return new AIOtherDamagedSetLeaderMaxLife(arg);
|
||||
case AIPlayTagType.OtherDamagedSubtractCountdown:
|
||||
return new AIOtherDamagedSubtractCountdown(arg);
|
||||
case AIPlayTagType.OtherDamagedBanish:
|
||||
return new AIOtherDamagedBanish(arg);
|
||||
case AIPlayTagType.SummonEvo:
|
||||
return new AISummonEvo(arg);
|
||||
case AIPlayTagType.EvoToken:
|
||||
return new AIEvoToken(arg);
|
||||
case AIPlayTagType.LastwordToken:
|
||||
return new AILastwordToken(arg);
|
||||
case AIPlayTagType.SummonRush:
|
||||
return new AISummonKeywordSkill(arg, AIScriptTokenArgType.RUSH);
|
||||
case AIPlayTagType.SummonQuick:
|
||||
return new AISummonKeywordSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.OtherSummonRush:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.RUSH);
|
||||
case AIPlayTagType.SummonDamage:
|
||||
return new AISummonDamage(arg);
|
||||
case AIPlayTagType.SummonBanish:
|
||||
return new AISummonBanish(arg);
|
||||
case AIPlayTagType.SummonHeal:
|
||||
return new AISummonHeal(arg);
|
||||
case AIPlayTagType.OtherSummonDamage:
|
||||
return new AIOtherSummonDamage(arg);
|
||||
case AIPlayTagType.OtherSummonGuard:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.GUARD);
|
||||
case AIPlayTagType.OtherSummonQuick:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.OtherSummonKiller:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.KILLER);
|
||||
case AIPlayTagType.OtherSummonDrain:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.DRAIN);
|
||||
case AIPlayTagType.OtherSummonBanish:
|
||||
return new AIOtherSummonBanish(arg);
|
||||
case AIPlayTagType.OtherSummonHeal:
|
||||
return new AIOtherSummonHeal(arg);
|
||||
case AIPlayTagType.OtherSummonBuff:
|
||||
return new AIOtherSummonBuff(arg);
|
||||
case AIPlayTagType.OtherSummonEvo:
|
||||
return new AIOtherSummonEvo(arg);
|
||||
case AIPlayTagType.OtherSummonDamageCut:
|
||||
return new AIOtherSummonDamageCut(arg);
|
||||
case AIPlayTagType.OtherSummonDamageClip:
|
||||
return new AIOtherSummonDamageClip(arg);
|
||||
case AIPlayTagType.OtherSummonSubtractCountdown:
|
||||
return new AIOtherSummonSubtractCountdown(arg);
|
||||
case AIPlayTagType.OtherSummonAddCemetery:
|
||||
return new AIOtherSummonAddCemetery(arg);
|
||||
case AIPlayTagType.OtherSummonUntouchable:
|
||||
return new AIOtherSummonKeywordSkill(arg, AIScriptTokenArgType.UNTOUCHABLE);
|
||||
case AIPlayTagType.OtherSummonDestory:
|
||||
return new AIOtherSummonDestroy(arg);
|
||||
case AIPlayTagType.OtherSummonDraw:
|
||||
return new AIOtherSummonDraw(arg);
|
||||
case AIPlayTagType.Necromance:
|
||||
return new AINecromance(arg);
|
||||
case AIPlayTagType.EarthRite:
|
||||
return new AIEarthRite(arg);
|
||||
case AIPlayTagType.BurialRite:
|
||||
return new AIBurialRite(arg);
|
||||
case AIPlayTagType.LastwordDamage:
|
||||
return new AILastwordDamage(arg);
|
||||
case AIPlayTagType.LastwordHeal:
|
||||
return new AILastwordHeal(arg);
|
||||
case AIPlayTagType.LastwordMetamorphose:
|
||||
return new AILastwordMetamorphose(arg);
|
||||
case AIPlayTagType.LastwordBanish:
|
||||
return new AILastwordBanish(arg);
|
||||
case AIPlayTagType.LastwordDraw:
|
||||
return new AILastwordDraw(arg);
|
||||
case AIPlayTagType.LastwordAddDeck:
|
||||
return new AILastwordAddDeck(arg);
|
||||
case AIPlayTagType.LastwordSetStatus:
|
||||
return new AILastwordSetStatus(arg);
|
||||
case AIPlayTagType.TurnEndDamage:
|
||||
return new AITurnEndDamage(arg);
|
||||
case AIPlayTagType.ClashDamage:
|
||||
return new AIClashDamage(arg);
|
||||
case AIPlayTagType.AfterClashDamage:
|
||||
return new AIAfterClashDamage(arg);
|
||||
case AIPlayTagType.ClashDestroy:
|
||||
return new AIClashDestroy(arg);
|
||||
case AIPlayTagType.ClashBuff:
|
||||
return new AIClashBuff(arg);
|
||||
case AIPlayTagType.ClashKiller:
|
||||
case AIPlayTagType.AttackKiller:
|
||||
return new AIAttackOrClashKeywordSkill(arg, AIScriptTokenArgType.KILLER);
|
||||
case AIPlayTagType.AttackRemoveTag:
|
||||
case AIPlayTagType.ClashRemoveTag:
|
||||
return new AIAttackOrClashRemoveTag(arg);
|
||||
case AIPlayTagType.ClashRemoveSkill:
|
||||
case AIPlayTagType.AttackRemoveSkill:
|
||||
return new AIAttackOrClashRemoveSkill(arg);
|
||||
case AIPlayTagType.ClashSpellboost:
|
||||
return new AIAttackOrClashSpellboost(arg);
|
||||
case AIPlayTagType.AfterClashHeal:
|
||||
return new AIAfterClashHeal(arg);
|
||||
case AIPlayTagType.RemoveSkill:
|
||||
return new AIRemoveSkill(arg);
|
||||
case AIPlayTagType.HealDamage:
|
||||
return new AIHealDamage(arg);
|
||||
case AIPlayTagType.HealBuff:
|
||||
return new AIHealBuff(arg);
|
||||
case AIPlayTagType.HealToken:
|
||||
return new AIHealToken(arg);
|
||||
case AIPlayTagType.HealHeal:
|
||||
return new AIHealHeal(arg);
|
||||
case AIPlayTagType.HealEvo:
|
||||
return new AIHealEvo(arg);
|
||||
case AIPlayTagType.TurnEndMetamorphose:
|
||||
return new AITurnEndMetamorphose(arg);
|
||||
case AIPlayTagType.BreakBuff:
|
||||
return new AIBreakBuff(arg);
|
||||
case AIPlayTagType.BreakSetLeaderMaxLife:
|
||||
return new AIBreakSetLeaderMaxLife(arg);
|
||||
case AIPlayTagType.LastwordBuff:
|
||||
return new AILastwordBuff(arg);
|
||||
case AIPlayTagType.EvoBuff:
|
||||
return new AIEvoBuff(arg);
|
||||
case AIPlayTagType.EvoHeal:
|
||||
return new AIEvoHeal(arg);
|
||||
case AIPlayTagType.EvoBanish:
|
||||
return new AIEvoBanish(arg);
|
||||
case AIPlayTagType.EvoSubtractCountdown:
|
||||
return new AIEvoSubtractCountdown(arg);
|
||||
case AIPlayTagType.EvoEvo:
|
||||
return new AIEvoEvo(arg);
|
||||
case AIPlayTagType.EvoDamage:
|
||||
return new AIEvoDamage(arg);
|
||||
case AIPlayTagType.EvoDestroy:
|
||||
return new AIEvoDestroy(arg);
|
||||
case AIPlayTagType.EvoMetamorphose:
|
||||
return new AIEvoMetamorphose(arg);
|
||||
case AIPlayTagType.EvoHandMetamorphose:
|
||||
return new AIEvoHandMetamorphose(arg);
|
||||
case AIPlayTagType.EvoBounce:
|
||||
return new AIEvoBounce(arg);
|
||||
case AIPlayTagType.EvoRush:
|
||||
return new AIEvoGiveBasicSkill(arg, AIScriptTokenArgType.RUSH);
|
||||
case AIPlayTagType.EvoQuick:
|
||||
return new AIEvoGiveBasicSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.EvoGuard:
|
||||
return new AIEvoGiveBasicSkill(arg, AIScriptTokenArgType.GUARD);
|
||||
case AIPlayTagType.EvoKiller:
|
||||
return new AIEvoGiveBasicSkill(arg, AIScriptTokenArgType.KILLER);
|
||||
case AIPlayTagType.EvoDrain:
|
||||
return new AIEvoGiveBasicSkill(arg, AIScriptTokenArgType.DRAIN);
|
||||
case AIPlayTagType.EvoAttackableCount:
|
||||
return new AIEvoAttackableCount(arg);
|
||||
case AIPlayTagType.EvoChangeCost:
|
||||
return new AIEvoChangeCost(arg);
|
||||
case AIPlayTagType.EvoHandSelect:
|
||||
return new AIEvoHandSelect(arg);
|
||||
case AIPlayTagType.EvoTokenDraw:
|
||||
return new AIEvoTokenDraw(arg);
|
||||
case AIPlayTagType.EvoShield:
|
||||
return new AIEvoShield(arg);
|
||||
case AIPlayTagType.EvoDamageCut:
|
||||
return new AIEvoDamageCut(arg);
|
||||
case AIPlayTagType.EvoReanimate:
|
||||
return new AIEvoReanimate(arg);
|
||||
case AIPlayTagType.EvoAddDeck:
|
||||
return new AIEvoAddDeck(arg);
|
||||
case AIPlayTagType.TurnEndDestroy:
|
||||
return new AITurnEndDestroy(arg);
|
||||
case AIPlayTagType.TurnEndHeal:
|
||||
return new AITurnEndHeal(arg);
|
||||
case AIPlayTagType.TurnEndBanish:
|
||||
return new AITurnEndBanish(arg);
|
||||
case AIPlayTagType.TurnEndSetLeaderMaxLife:
|
||||
return new AITurnEndSetLeaderMaxLife(arg);
|
||||
case AIPlayTagType.TurnEndDiscard:
|
||||
return new AITurnEndDiscard(arg);
|
||||
case AIPlayTagType.TurnEndBuff:
|
||||
return new AITurnEndBuff(arg);
|
||||
case AIPlayTagType.TurnEndSubtractCountdown:
|
||||
return new AITurnEndSubtractCountdown(arg);
|
||||
case AIPlayTagType.TurnEndToken:
|
||||
return new AITurnEndToken(arg);
|
||||
case AIPlayTagType.TurnEndBounce:
|
||||
return new AITurnEndBounce(arg);
|
||||
case AIPlayTagType.TurnEndAddDeck:
|
||||
return new AITurnEndAddDeck(arg);
|
||||
case AIPlayTagType.TurnEndEvo:
|
||||
return new AITurnEndEvo(arg);
|
||||
case AIPlayTagType.TurnEndDraw:
|
||||
return new AITurnEndDraw(arg);
|
||||
case AIPlayTagType.TurnEndRemoveTag:
|
||||
return new AITurnEndRemoveTag(arg);
|
||||
case AIPlayTagType.TurnEndShield:
|
||||
return new AITurnEndShield(arg);
|
||||
case AIPlayTagType.TurnEndDamageClip:
|
||||
return new AITurnEndDamageClip(arg);
|
||||
case AIPlayTagType.TurnEndDamageCut:
|
||||
return new AITurnEndDamageCut(arg);
|
||||
case AIPlayTagType.TurnEndGuard:
|
||||
return new AITurnEndKeywordSkill(arg, AIScriptTokenArgType.GUARD);
|
||||
case AIPlayTagType.TurnEndBanAttack:
|
||||
return new AITurnEndBanAttack(arg);
|
||||
case AIPlayTagType.EvoSetLeaderMaxLife:
|
||||
return new AIEvoSetLeaderMaxLife(arg);
|
||||
case AIPlayTagType.EvolvedAttackableCount:
|
||||
return new AIEvolvedAttackableCount(arg);
|
||||
case AIPlayTagType.EvolvedAttackable:
|
||||
return new AIEvolvedAttackable(arg);
|
||||
case AIPlayTagType.EvolvedSkill:
|
||||
return new AIEvolvedSkill(arg);
|
||||
case AIPlayTagType.AfterAttackEvo:
|
||||
return new AIAfterAttackEvo(arg);
|
||||
case AIPlayTagType.AfterAttackDraw:
|
||||
return new AIAfterAttackDraw(arg);
|
||||
case AIPlayTagType.AfterAttackBanish:
|
||||
return new AIAfterAttackBanish(arg);
|
||||
case AIPlayTagType.BreakDestroy:
|
||||
return new AIBreakDestroy(arg);
|
||||
case AIPlayTagType.PlayRecoverPP:
|
||||
case AIPlayTagType.FanfareRecoverPp:
|
||||
return new AIWhenPlayRecoverPp(arg);
|
||||
case AIPlayTagType.BuffRecoverPP:
|
||||
return new AIBuffRecoverPp(arg);
|
||||
case AIPlayTagType.BreakRecoverPp:
|
||||
return new AIBreakRecoverPp(arg);
|
||||
case AIPlayTagType.Fusion:
|
||||
return new AIFusion(arg);
|
||||
case AIPlayTagType.FusionDraw:
|
||||
return new AIFusionDraw(arg);
|
||||
case AIPlayTagType.HandBonus:
|
||||
return new AIBonusArgumentWithIgnoreInBattle(arg);
|
||||
case AIPlayTagType.EvoRecoverPp:
|
||||
return new AIEvoRecoverPp(arg);
|
||||
case AIPlayTagType.PlayptnBaseStatsRate:
|
||||
return new AIPlayptnBaseStatsRate(arg);
|
||||
case AIPlayTagType.GiveSkill:
|
||||
return new AIGiveSkill(arg);
|
||||
case AIPlayTagType.PlayDiscard:
|
||||
case AIPlayTagType.FanfareDiscard:
|
||||
return new AIWhenPlayDiscard(arg);
|
||||
case AIPlayTagType.AttackDiscard:
|
||||
return new AIAttackDiscard(arg);
|
||||
case AIPlayTagType.DiscardDamage:
|
||||
return new AIDiscardDamage(arg);
|
||||
case AIPlayTagType.BreakHeal:
|
||||
return new AIBreakHeal(arg);
|
||||
case AIPlayTagType.BuffDamage:
|
||||
return new AIBuffDamage(arg);
|
||||
case AIPlayTagType.BuffDestroy:
|
||||
return new AIBuffDestroy(arg);
|
||||
case AIPlayTagType.BuffToken:
|
||||
return new AIBuffToken(arg);
|
||||
case AIPlayTagType.BuffEvo:
|
||||
return new AIBuffEvo(arg);
|
||||
case AIPlayTagType.BuffDraw:
|
||||
return new AIBuffDraw(arg);
|
||||
case AIPlayTagType.BuffShield:
|
||||
return new AIBuffShield(arg);
|
||||
case AIPlayTagType.EvoDiscard:
|
||||
return new AIEvoDiscard(arg);
|
||||
case AIPlayTagType.BounceDamage:
|
||||
return new AIBounceDamage(arg);
|
||||
case AIPlayTagType.ResonanceDamage:
|
||||
return new AIResonanceDamage(arg);
|
||||
case AIPlayTagType.ResonanceHeal:
|
||||
return new AIResonanceHeal(arg);
|
||||
case AIPlayTagType.ResonanceKiller:
|
||||
return new AIResonanceGiveBasicSkill(arg, AIScriptTokenArgType.KILLER);
|
||||
case AIPlayTagType.DiscardHeal:
|
||||
return new AIDiscardHeal(arg);
|
||||
case AIPlayTagType.AllyDiscardBonus:
|
||||
return new AIAllyDiscardBonus(arg);
|
||||
case AIPlayTagType.BanishAttachTag:
|
||||
return new AIBanishAttachTag(arg);
|
||||
case AIPlayTagType.OtherBanishToken:
|
||||
return new AIOtherBanishToken(arg);
|
||||
case AIPlayTagType.OtherBanishAddCemetery:
|
||||
return new AIOtherBanishAddCemetery(arg);
|
||||
case AIPlayTagType.EvoChoice:
|
||||
case AIPlayTagType.PlayChoice:
|
||||
case AIPlayTagType.FanfareChoice:
|
||||
return new AIChoiceTagArgument(arg);
|
||||
case AIPlayTagType.ChoiceBrave:
|
||||
return new AIChoiceBrave();
|
||||
case AIPlayTagType.Enhance:
|
||||
return new AIEnhance(arg);
|
||||
case AIPlayTagType.Accelerate:
|
||||
return new AIAccelerate(arg);
|
||||
case AIPlayTagType.Crystalize:
|
||||
return new AICrystalize(arg);
|
||||
case AIPlayTagType.ChoiceTransform:
|
||||
return new AIChoiceTransform(arg);
|
||||
case AIPlayTagType.PlaySubtractCountdown:
|
||||
case AIPlayTagType.FanfareSubtractCountdown:
|
||||
return new AIWhenPlaySubtractCountdown(arg);
|
||||
case AIPlayTagType.FanfareRecoverAttackableCount:
|
||||
return new AIWhenPlayRecoverAttackableCount(arg);
|
||||
case AIPlayTagType.FanfareSneak:
|
||||
case AIPlayTagType.PlaySneak:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.SNEAK);
|
||||
case AIPlayTagType.FanfareQuick:
|
||||
case AIPlayTagType.PlayQuick:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.FanfareRush:
|
||||
case AIPlayTagType.PlayRush:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.RUSH);
|
||||
case AIPlayTagType.FanfareGuard:
|
||||
case AIPlayTagType.PlayGuard:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.GUARD);
|
||||
case AIPlayTagType.FanfareKiller:
|
||||
case AIPlayTagType.PlayKiller:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.KILLER);
|
||||
case AIPlayTagType.FanfareDrain:
|
||||
case AIPlayTagType.PlayDrain:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.DRAIN);
|
||||
case AIPlayTagType.FanfareUntouchable:
|
||||
case AIPlayTagType.PlayUntouchable:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.UNTOUCHABLE);
|
||||
case AIPlayTagType.FanfareForceTargeting:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.FORCE_TARGETING);
|
||||
case AIPlayTagType.PlayIgnoreGuard:
|
||||
case AIPlayTagType.FanfareIgnoreGuard:
|
||||
return new AIWhenPlayKeywordSkill(arg, AIScriptTokenArgType.IGNORE_GUARD);
|
||||
case AIPlayTagType.PlaySummonHandCard:
|
||||
case AIPlayTagType.FanfareSummonHandCard:
|
||||
return new AIWhenPlaySummonHandCard(arg);
|
||||
case AIPlayTagType.PlaySelect:
|
||||
case AIPlayTagType.FanfareSelect:
|
||||
return new AIWhenPlaySelect(arg);
|
||||
case AIPlayTagType.PlayHandSelect:
|
||||
case AIPlayTagType.FanfareHandSelect:
|
||||
return new AIWhenPlayHandSelect(arg);
|
||||
case AIPlayTagType.EmoteOnTurnEnd:
|
||||
return new AIEmoteOnTurnTransition(arg);
|
||||
case AIPlayTagType.LastwordReanimate:
|
||||
return new AILastwordReanimate(arg);
|
||||
case AIPlayTagType.ModifyHeal:
|
||||
return new AIModifyValue(arg);
|
||||
case AIPlayTagType.LeaveBonus:
|
||||
case AIPlayTagType.DiscardedBonus:
|
||||
return new AIBonusArgumentWithIgnoreInBattle(arg);
|
||||
case AIPlayTagType.LeaveHeal:
|
||||
return new AILeaveHeal(arg);
|
||||
case AIPlayTagType.LeaveDamage:
|
||||
return new AILeaveDamage(arg);
|
||||
case AIPlayTagType.LeaveAttachTag:
|
||||
return new AILeaveAttachTag(arg);
|
||||
case AIPlayTagType.LeaveBanish:
|
||||
return new AILeaveBanish(arg);
|
||||
case AIPlayTagType.OtherLeaveDamage:
|
||||
return new AIOtherLeaveDamage(arg);
|
||||
case AIPlayTagType.OtherLeaveToken:
|
||||
return new AIOtherLeaveToken(arg);
|
||||
case AIPlayTagType.AllyPlayoutDamageBonus:
|
||||
return new AIOtherPlayoutDamageBonus(arg);
|
||||
case AIPlayTagType.OtherBreakBonus:
|
||||
case AIPlayTagType.OtherBanishBonus:
|
||||
case AIPlayTagType.OtherLeaveBonus:
|
||||
return new AIOtherBreakBonus(arg);
|
||||
case AIPlayTagType.BuffRush:
|
||||
return new AIBuffRush(arg);
|
||||
case AIPlayTagType.BuffHeal:
|
||||
return new AIBuffHeal(arg);
|
||||
case AIPlayTagType.BuffBuff:
|
||||
return new AIBuffBuff(arg);
|
||||
case AIPlayTagType.GetOn:
|
||||
return new AIGetOn(arg);
|
||||
case AIPlayTagType.GetOnBanish:
|
||||
return new AIGetOnBanish(arg);
|
||||
case AIPlayTagType.GetOnDamage:
|
||||
return new AIGetOnDamage(arg);
|
||||
case AIPlayTagType.GetOnEvo:
|
||||
return new AIGetOnEvo(arg);
|
||||
case AIPlayTagType.GetOffMetamorphose:
|
||||
return new AIGetOffMetamorphose(arg);
|
||||
case AIPlayTagType.GetOffEvo:
|
||||
return new AIGetOffEvo(arg);
|
||||
case AIPlayTagType.AfterAttackHeal:
|
||||
return new AIAfterAttackHeal(arg);
|
||||
case AIPlayTagType.OtherAttackBuff:
|
||||
return new AIOtherAttackBuff(arg);
|
||||
case AIPlayTagType.OtherAttackDamage:
|
||||
return new AIOtherAttackDamage(arg);
|
||||
case AIPlayTagType.OtherAttackHeal:
|
||||
return new AIOtherAttackHeal(arg);
|
||||
case AIPlayTagType.OtherAttackToken:
|
||||
return new AIOtherAttackToken(arg);
|
||||
case AIPlayTagType.OtherAttackAttachTag:
|
||||
return new AIOtherAttackAttachTag(arg);
|
||||
case AIPlayTagType.OtherAttackRemoveTag:
|
||||
return new AIOtherAttackRemoveTag(arg);
|
||||
case AIPlayTagType.OtherEvoBuff:
|
||||
return new AIOtherEvoBuff(arg);
|
||||
case AIPlayTagType.OtherEvoDamage:
|
||||
case AIPlayTagType.SelfAndOtherEvoDamage:
|
||||
return new AIOtherEvoDamage(arg);
|
||||
case AIPlayTagType.OtherEvoBanish:
|
||||
return new AIOtherEvoBanish(arg);
|
||||
case AIPlayTagType.OtherEvoSubtractCountdown:
|
||||
return new AIOtherEvoSubtractCountdown(arg);
|
||||
case AIPlayTagType.OtherEvoEvo:
|
||||
return new AIOtherEvoEvo(arg);
|
||||
case AIPlayTagType.OtherEvoToken:
|
||||
case AIPlayTagType.SelfAndOtherEvoToken:
|
||||
return new AIOtherEvoToken(arg);
|
||||
case AIPlayTagType.OtherEvoShield:
|
||||
case AIPlayTagType.SelfAndOtherEvoShield:
|
||||
return new AIOtherEvoShield(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoAttachTag:
|
||||
return new AIOtherEvoAttachTag(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoDestroy:
|
||||
return new AIOtherEvoDestroy(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoBounce:
|
||||
return new AIOtherEvoBounce(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoDraw:
|
||||
return new AIOtherEvoDraw(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoAddCemetery:
|
||||
return new AIOtherEvoAddCemetery(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoHeal:
|
||||
return new AIOtherEvoHeal(arg);
|
||||
case AIPlayTagType.SelfAndOtherEvoTokenDraw:
|
||||
return new AIOtherEvoTokenDraw(arg);
|
||||
case AIPlayTagType.RallyCountPlus:
|
||||
return new AIFiltersArgument(arg);
|
||||
case AIPlayTagType.TurnEndActivateCount:
|
||||
return new AIActivateCountTagArgument(arg);
|
||||
case AIPlayTagType.PlayActivateCount:
|
||||
case AIPlayTagType.AttackActivateCount:
|
||||
case AIPlayTagType.BreakActivateCount:
|
||||
case AIPlayTagType.BanishActivateCount:
|
||||
case AIPlayTagType.DamagedActivateCount:
|
||||
case AIPlayTagType.BuffActivateCounnt:
|
||||
case AIPlayTagType.HealActivateCount:
|
||||
case AIPlayTagType.NecromanceActivateCount:
|
||||
case AIPlayTagType.EvoActivateCount:
|
||||
case AIPlayTagType.SummonActivateCount:
|
||||
return new AIFilteringActivateCountArgument(arg);
|
||||
case AIPlayTagType.SetAITribe:
|
||||
return new AISetTribe(arg);
|
||||
case AIPlayTagType.GenerateTag:
|
||||
return new AIGenerateTag(arg);
|
||||
case AIPlayTagType.PlayTokenDraw:
|
||||
case AIPlayTagType.FanfareTokenDraw:
|
||||
return new AIWhenPlayTokenDraw(arg);
|
||||
case AIPlayTagType.PlayChangeClass:
|
||||
case AIPlayTagType.FanfareChangeClass:
|
||||
return new AIWhenPlayChangeClass(arg);
|
||||
case AIPlayTagType.PlayChangeTribe:
|
||||
case AIPlayTagType.FanfareChangeTribe:
|
||||
return new AIWhenPlayChangeTribe(arg);
|
||||
case AIPlayTagType.RemoveByDestroy:
|
||||
return new AIRemoveByDestroy(arg);
|
||||
case AIPlayTagType.EvoHandBuff:
|
||||
return new AIEvoHandBuff(arg);
|
||||
case AIPlayTagType.PlayNotBeAttacked:
|
||||
case AIPlayTagType.FanfareNotBeAttacked:
|
||||
return new AIWhenPlayNotBeAttacked(arg);
|
||||
case AIPlayTagType.PlayAttackableCount:
|
||||
case AIPlayTagType.FanfareAttackableCount:
|
||||
return new AIWhenPlayAttackableCount(arg);
|
||||
case AIPlayTagType.PlayRemoveSkill:
|
||||
case AIPlayTagType.FanfareRemoveSkill:
|
||||
return new AIWhenPlayRemoveSkill(arg);
|
||||
case AIPlayTagType.BreakAddStack:
|
||||
return new AIBreakAddStack(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateRemoveByBanish:
|
||||
return new AIChangeInplayFixRemoveType(arg, FixedRemoveType.RemoveByBanish, isImmediate: true);
|
||||
case AIPlayTagType.ChangeInplayImmediateRemoveByDestroy:
|
||||
return new AIChangeInplayFixRemoveType(arg, FixedRemoveType.RemoveByDestroy, isImmediate: true);
|
||||
case AIPlayTagType.ChangeInplayCannotPlay:
|
||||
return new AIChangeInplayCannotPlay(arg, isImmediate: false);
|
||||
case AIPlayTagType.ChangeInplayCannotAttack:
|
||||
return new AIChangeInplayCannotAttack(arg, isImmediate: false);
|
||||
case AIPlayTagType.ChangeInplayAttachTag:
|
||||
return new AIChangeInplayAttachTag(arg, isImmediate: false);
|
||||
case AIPlayTagType.ChangeInplayImmediateShield:
|
||||
return new AIChangeInplayImmediateShield(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateDamageCut:
|
||||
return new AIChangeInplayImmediateDamageCut(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateDamageClip:
|
||||
return new AIChangeInplayImmediateDamageClip(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateLifeLowerLimit:
|
||||
return new AIChangeInplayImmediateLifeLowerLimit(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateDamageModifier:
|
||||
return new AIChangeInplayImmediateDamageModifier(arg);
|
||||
case AIPlayTagType.ChangeInplayImmediateUntouchable:
|
||||
return new AIChangeInplayImmediateKeywordSkill(arg, AIScriptTokenArgType.UNTOUCHABLE);
|
||||
case AIPlayTagType.ChangeInplayImmediateIndestructible:
|
||||
return new AIChangeInplayImmediateIndestructible(arg);
|
||||
case AIPlayTagType.ChangePpTotalBuff:
|
||||
return new AIChangePpTotalBuff(arg, isImmediate: false);
|
||||
case AIPlayTagType.EvoSetStatus:
|
||||
return new AIEvoSetStatus(arg);
|
||||
case AIPlayTagType.PlayModifyConsumeEp:
|
||||
case AIPlayTagType.FanfareModifyConsumeEp:
|
||||
return new AIWhenPlayModifyConsumeEp(arg);
|
||||
case AIPlayTagType.PlayEvo:
|
||||
case AIPlayTagType.FanfareEvo:
|
||||
return new AIWhenPlayEvo(arg);
|
||||
case AIPlayTagType.OtherPlayEvo:
|
||||
return new AIOtherWhenPlayEvo(arg, PlaySimulationType.Undefined);
|
||||
case AIPlayTagType.OtherEnhanceEvo:
|
||||
return new AIOtherWhenPlayEvo(arg, PlaySimulationType.Enhance);
|
||||
case AIPlayTagType.OtherPlayDamage:
|
||||
return new AIOtherWhenPlayDamage(arg);
|
||||
case AIPlayTagType.OtherPlayRecoverPp:
|
||||
return new AIOtherWhenPlayRecoverPp(arg);
|
||||
case AIPlayTagType.OtherPlayDestroy:
|
||||
return new AIOtherWhenPlayDestroy(arg);
|
||||
case AIPlayTagType.OtherPlayBounce:
|
||||
return new AIOtherWhenPlayBounce(arg);
|
||||
case AIPlayTagType.OtherPlayBuff:
|
||||
return new AIOtherWhenPlayBuff(arg);
|
||||
case AIPlayTagType.OtherPlayToken:
|
||||
return new AIOtherWhenPlayToken(arg);
|
||||
case AIPlayTagType.OtherPlayRemoveTag:
|
||||
return new AIOtherWhenPlayRemoveTag(arg);
|
||||
case AIPlayTagType.OtherPlayQuick:
|
||||
return new AIOtherWhenPlayKeywordSkill(arg, AIScriptTokenArgType.QUICK);
|
||||
case AIPlayTagType.AttackSubtractCountdown:
|
||||
return new AIAttackSubtractCountdown(arg);
|
||||
case AIPlayTagType.EvolveToOther:
|
||||
return new AIEvolveToOtherTagArgument(arg);
|
||||
case AIPlayTagType.LastwordEvo:
|
||||
return new AILastwordEvo(arg);
|
||||
case AIPlayTagType.LastwordRemoveSkill:
|
||||
return new AILastwordRemoveSkill(arg);
|
||||
case AIPlayTagType.LastwordAddCemetery:
|
||||
return new AILastwordAddCemetery(arg);
|
||||
case AIPlayTagType.LastwordDamageClip:
|
||||
return new AILastwordDamageClip(arg);
|
||||
case AIPlayTagType.LastwordShield:
|
||||
return new AILastwordShield(arg);
|
||||
case AIPlayTagType.PlayShield:
|
||||
case AIPlayTagType.FanfareShield:
|
||||
return new AIWhenPlayShield(arg);
|
||||
case AIPlayTagType.PlayDamageCut:
|
||||
case AIPlayTagType.FanfareDamageCut:
|
||||
return new AIWhenPlayDamageCut(arg);
|
||||
case AIPlayTagType.PlayDamageClip:
|
||||
case AIPlayTagType.FanfareDamageClip:
|
||||
return new AIWhenPlayDamageClip(arg);
|
||||
case AIPlayTagType.OtherPlayAttachTag:
|
||||
return new AIOtherWhenPlayAttachTag(arg);
|
||||
case AIPlayTagType.AttackShield:
|
||||
case AIPlayTagType.ClashShield:
|
||||
return new AIAttackOrClashShield(arg);
|
||||
case AIPlayTagType.AttackDamageClip:
|
||||
case AIPlayTagType.ClashDamageClip:
|
||||
return new AIAttackOrClashDamageClip(arg);
|
||||
case AIPlayTagType.NecromanceDamage:
|
||||
return new AINecromanceDamage(arg);
|
||||
case AIPlayTagType.NecromanceHeal:
|
||||
return new AINecromanceHeal(arg);
|
||||
case AIPlayTagType.FanfareRemoveGuard:
|
||||
return new AIWhenPlayRemoveKeywordSkill(arg, AIScriptTokenArgType.GUARD);
|
||||
case AIPlayTagType.Stack:
|
||||
return new AIStack(arg);
|
||||
case AIPlayTagType.EvoAddStack:
|
||||
return new AIEvoAddStack(arg);
|
||||
case AIPlayTagType.FusionMetamorphose:
|
||||
return new AIFusionMetamorphose(arg);
|
||||
case AIPlayTagType.LastwordSubtractCountdown:
|
||||
return new AILastwordSubtractCountdown(arg);
|
||||
case AIPlayTagType.AttackSetStatus:
|
||||
return new AIAttackSetStatus(arg);
|
||||
case AIPlayTagType.PlayAddDeck:
|
||||
case AIPlayTagType.FanfareAddDeck:
|
||||
return new AIWhenPlayAddDeck(arg);
|
||||
case AIPlayTagType.AttackAddDeck:
|
||||
return new AIAttackAddDeck(arg);
|
||||
default:
|
||||
return new AIScriptArgumentExpressions(arg);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
return condExpr.CheckCondition(tagOwner, playPtn, field, situation);
|
||||
}
|
||||
|
||||
public float EvalArg(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation, int index = 0)
|
||||
{
|
||||
return argExpr.EvalArg(index, tagOwner, playPtn, field, situation);
|
||||
}
|
||||
|
||||
public int EvalID(int index = 0)
|
||||
{
|
||||
return argExpr.EvalID(index);
|
||||
}
|
||||
|
||||
public bool IsArgID(int index)
|
||||
{
|
||||
return argExpr.IsArgID(index);
|
||||
}
|
||||
|
||||
public bool IsHoldingEVAL()
|
||||
{
|
||||
if (!ArgumentExpressions.IsHoldingEVAL())
|
||||
{
|
||||
return condExpr.IsHoldingEVAL();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsAttachTagType(AIPlayTagType type)
|
||||
{
|
||||
if (type > AIPlayTagType.AttachTag_Start)
|
||||
{
|
||||
return type < AIPlayTagType.AttachTag_End;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsRemoveTagType(AIPlayTagType tagType)
|
||||
{
|
||||
if (tagType == AIPlayTagType.AttackRemoveTag || tagType == AIPlayTagType.ClashRemoveTag || tagType == AIPlayTagType.TurnEndRemoveTag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsClashTagType()
|
||||
{
|
||||
if (Type != AIPlayTagType.ClashDestroy && Type != AIPlayTagType.ClashBanish && Type != AIPlayTagType.ClashDamage && Type != AIPlayTagType.ClashHeal && Type != AIPlayTagType.ClashKiller && Type != AIPlayTagType.ClashBuff && Type != AIPlayTagType.ClashRemoveSkill && Type != AIPlayTagType.ClashToken && Type != AIPlayTagType.ClashShield && Type != AIPlayTagType.ClashDamageClip && Type != AIPlayTagType.ClashRemoveTag)
|
||||
{
|
||||
return Type == AIPlayTagType.ClashSpellboost;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsAttackTagType()
|
||||
{
|
||||
if (Type != AIPlayTagType.AttackBuff && Type != AIPlayTagType.AttackDamage && Type != AIPlayTagType.AttackHeal && Type != AIPlayTagType.AttackDestroy && Type != AIPlayTagType.AttackBanish && Type != AIPlayTagType.AttackToken && Type != AIPlayTagType.AttackDiscard && Type != AIPlayTagType.AttackAttackableCount && Type != AIPlayTagType.AttackAttachTag && Type != AIPlayTagType.AttackEvo && Type != AIPlayTagType.AttackSubtractCountdown && Type != AIPlayTagType.AttackKiller && Type != AIPlayTagType.AttackShield && Type != AIPlayTagType.AttackDamageClip && Type != AIPlayTagType.AttackRemoveTag && Type != AIPlayTagType.AttackRemoveSkill && Type != AIPlayTagType.AttackSetStatus && Type != AIPlayTagType.AttackAddDeck)
|
||||
{
|
||||
return Type == AIPlayTagType.AttackHandBuff;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsLastwordTag()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case AIPlayTagType.IgnoreBreak:
|
||||
case AIPlayTagType.LastwordToken:
|
||||
case AIPlayTagType.LastwordBuff:
|
||||
case AIPlayTagType.LastwordDestroy:
|
||||
case AIPlayTagType.LastwordDamage:
|
||||
case AIPlayTagType.LastwordHeal:
|
||||
case AIPlayTagType.LastwordMetamorphose:
|
||||
case AIPlayTagType.LastwordBanish:
|
||||
case AIPlayTagType.LastwordDraw:
|
||||
case AIPlayTagType.LastwordSetStatus:
|
||||
case AIPlayTagType.Break:
|
||||
case AIPlayTagType.LastwordReanimate:
|
||||
case AIPlayTagType.LastwordAttachTag:
|
||||
case AIPlayTagType.LastwordEvo:
|
||||
case AIPlayTagType.LastwordRemoveSkill:
|
||||
case AIPlayTagType.LastwordAddCemetery:
|
||||
case AIPlayTagType.LastwordDamageClip:
|
||||
case AIPlayTagType.LastwordShield:
|
||||
case AIPlayTagType.LastwordSubtractCountdown:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTokenTag()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case AIPlayTagType.FanfareToken:
|
||||
case AIPlayTagType.PlayToken:
|
||||
case AIPlayTagType.LastwordToken:
|
||||
case AIPlayTagType.AttackToken:
|
||||
case AIPlayTagType.EvoToken:
|
||||
case AIPlayTagType.HealToken:
|
||||
case AIPlayTagType.BuffToken:
|
||||
case AIPlayTagType.OtherAttackToken:
|
||||
case AIPlayTagType.OtherBanishToken:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetHash()
|
||||
{
|
||||
return (ulong)(_argText.GetHashCode() * 79 + _conditionText.GetHashCode() * 167 + Type.GetHashCode() * 2851);
|
||||
}
|
||||
}
|
||||
10
SVSim.BattleEngine/Engine/Wizard/AIPlayTagAsset.cs
Normal file
10
SVSim.BattleEngine/Engine/Wizard/AIPlayTagAsset.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayTagAsset
|
||||
{
|
||||
public string Type { get; set; }
|
||||
|
||||
public string Arg { get; set; }
|
||||
|
||||
public string Condition { get; set; }
|
||||
}
|
||||
478
SVSim.BattleEngine/Engine/Wizard/AIPlayTagType.cs
Normal file
478
SVSim.BattleEngine/Engine/Wizard/AIPlayTagType.cs
Normal file
@@ -0,0 +1,478 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIPlayTagType
|
||||
{
|
||||
PlayBonus,
|
||||
PlayBonusRate,
|
||||
FanfareBonus,
|
||||
IgnoreFanfareBonus,
|
||||
IgnoreBreak,
|
||||
PlayptnBonus,
|
||||
Priority,
|
||||
PlayoutDamageBonus,
|
||||
AllyPlayoutDamageBonus,
|
||||
PlayoutNextTurn,
|
||||
CostBonus,
|
||||
PlayLimit,
|
||||
PlayPlus,
|
||||
Target,
|
||||
IgnoreTarget,
|
||||
AllyPlayBonus,
|
||||
EnemyPlayBonus,
|
||||
FanfareToken,
|
||||
PlayToken,
|
||||
AddCardToPlayoutPlayPtn,
|
||||
PlayDraw,
|
||||
HandBonus,
|
||||
NoInstantAttack,
|
||||
PlaySkip,
|
||||
PlaySkipWithEvo,
|
||||
PlaySkipIfEvo,
|
||||
BreakBeforePlay,
|
||||
PlaySkipWithAction,
|
||||
PlaySkipWithActionIfEvo,
|
||||
EvoBonus,
|
||||
MemberEvoBonus,
|
||||
EnemyEvoBonus,
|
||||
EvoHandPlus,
|
||||
NoNormalEvo,
|
||||
EvoEvo,
|
||||
EvoDamage,
|
||||
EvoHandBuff,
|
||||
ClashBonus,
|
||||
AttackBonus,
|
||||
ClashDestroy,
|
||||
ClashHeal,
|
||||
ClashToken,
|
||||
ClashBanish,
|
||||
ClashSpellboost,
|
||||
AfterClashHeal,
|
||||
AttackBuff,
|
||||
AttackHandBuff,
|
||||
AttackDestroy,
|
||||
AttackBanish,
|
||||
AttackHeal,
|
||||
AttackDiscard,
|
||||
AttackAttackableCount,
|
||||
AttackQuick,
|
||||
AttackRemoveTag,
|
||||
AttackSetStatus,
|
||||
AfterAttackEvo,
|
||||
AfterAttackDraw,
|
||||
AfterAttackBanish,
|
||||
SummonBuff,
|
||||
BreakBuff,
|
||||
BreakSetLeaderMaxLife,
|
||||
SummonEvo,
|
||||
SummonRush,
|
||||
SummonQuick,
|
||||
SummonDamage,
|
||||
SummonBanish,
|
||||
SummonRecoverPp,
|
||||
SummonHeal,
|
||||
SummonDestroy,
|
||||
SummonBanAttack,
|
||||
OtherSummonDamage,
|
||||
OtherSummonRush,
|
||||
OtherSummonGuard,
|
||||
OtherSummonQuick,
|
||||
OtherSummonKiller,
|
||||
OtherSummonDrain,
|
||||
OtherSummonBanish,
|
||||
OtherSummonHeal,
|
||||
OtherSummonBuff,
|
||||
OtherSummonEvo,
|
||||
OtherSummonDamageCut,
|
||||
OtherSummonDamageClip,
|
||||
OtherSummonSubtractCountdown,
|
||||
OtherSummonAddCemetery,
|
||||
OtherSummonUntouchable,
|
||||
OtherSummonDestory,
|
||||
OtherSummonDraw,
|
||||
PlayoutAttackBonus,
|
||||
TurnEndDestroy,
|
||||
TurnEndBanish,
|
||||
TurnEndDamage,
|
||||
TurnEndHeal,
|
||||
TurnEndSetLeaderMaxLife,
|
||||
TurnEndDiscard,
|
||||
TurnEndBuff,
|
||||
TurnEndSubtractCountdown,
|
||||
TurnEndToken,
|
||||
TurnEndBounce,
|
||||
TurnEndAddDeck,
|
||||
TurnEndEvo,
|
||||
TurnEndDraw,
|
||||
TurnEndShield,
|
||||
TurnEndDamageClip,
|
||||
TurnEndDamageCut,
|
||||
TurnEndGuard,
|
||||
TurnEndBanAttack,
|
||||
ReincarnationSimulation,
|
||||
PlayDestroy,
|
||||
PlayDamage,
|
||||
PlayHeal,
|
||||
FanfareHeal,
|
||||
PlayBanish,
|
||||
FanfareBanish,
|
||||
PlayBounce,
|
||||
PlaySubtractCountdown,
|
||||
FanfareSubtractCountdown,
|
||||
AllyClashDamage,
|
||||
CantBeAttacked,
|
||||
AttackableClass,
|
||||
ClashBuff,
|
||||
PlayptnBaseStatsRate,
|
||||
LastwordToken,
|
||||
AttackByLife,
|
||||
AttackToken,
|
||||
PuppetAttack,
|
||||
NoSkipAttack,
|
||||
EvoToken,
|
||||
HealDamage,
|
||||
HealBuff,
|
||||
HealToken,
|
||||
HealHeal,
|
||||
HealEvo,
|
||||
TurnEndMetamorphose,
|
||||
LastwordBuff,
|
||||
FirstEvo,
|
||||
LeaveHeal,
|
||||
LeaveDamage,
|
||||
LeaveBanish,
|
||||
GiveSkill,
|
||||
BreakHeal,
|
||||
BuffDamage,
|
||||
BuffDestroy,
|
||||
BuffShield,
|
||||
BounceDamage,
|
||||
FanfareDamage,
|
||||
PlayBuff,
|
||||
FanfareBuff,
|
||||
FanfareDestroy,
|
||||
FanfareBounce,
|
||||
FanfareRecoverAttackableCount,
|
||||
FanfareSneak,
|
||||
PlaySneak,
|
||||
FanfareQuick,
|
||||
PlayQuick,
|
||||
FanfareRush,
|
||||
PlayRush,
|
||||
FanfareGuard,
|
||||
PlayGuard,
|
||||
FanfareDrain,
|
||||
PlayDrain,
|
||||
FanfareKiller,
|
||||
PlayKiller,
|
||||
FanfareHandBuff,
|
||||
PlayHandBuff,
|
||||
FanfareUntouchable,
|
||||
PlayUntouchable,
|
||||
FanfareForceTargeting,
|
||||
ResonanceDamage,
|
||||
ResonanceHeal,
|
||||
ResonanceKiller,
|
||||
BuffToken,
|
||||
PlaySelect,
|
||||
FanfareSelect,
|
||||
PlayHandSelect,
|
||||
FanfareHandSelect,
|
||||
PlayRemoveSkill,
|
||||
FanfareRemoveSkill,
|
||||
PlayReanimate,
|
||||
FanfareReanimate,
|
||||
PlayMetamorphose,
|
||||
FanfareMetamorphose,
|
||||
PlayHandMetamorphose,
|
||||
FanfareHandMetamorphose,
|
||||
PlaySetMaxStatus,
|
||||
FanfareSetMaxStatus,
|
||||
PlaySetLeaderMaxLife,
|
||||
FanfareBonusInSimulation,
|
||||
PlayBonusInSimulation,
|
||||
DamagedBonus,
|
||||
DamagedBuff,
|
||||
DamagedDamage,
|
||||
DamagedToken,
|
||||
DamagedHeal,
|
||||
DamagedCantUnderAttack,
|
||||
OtherDamagedDamage,
|
||||
OtherDamagedHeal,
|
||||
OtherDamagedSetLeaderMaxLife,
|
||||
OtherDamagedSubtractCountdown,
|
||||
OtherDamagedBanish,
|
||||
LastwordDestroy,
|
||||
BreakDamage,
|
||||
LastwordDamage,
|
||||
LastwordHeal,
|
||||
LastwordMetamorphose,
|
||||
LastwordBanish,
|
||||
LastwordDraw,
|
||||
LastwordAddDeck,
|
||||
LastwordSetStatus,
|
||||
AttackDamage,
|
||||
AttackEvo,
|
||||
AttackBreakDamage,
|
||||
AttackBreakEvo,
|
||||
AttackBreakRecoverPp,
|
||||
AttackBreakAttackTwice,
|
||||
AfterAttackHeal,
|
||||
ClashDamage,
|
||||
AfterClashDamage,
|
||||
BreakFirst,
|
||||
BreakLast,
|
||||
BreakRecoverAttackableCount,
|
||||
ClashKiller,
|
||||
AttackKiller,
|
||||
EvolvedAttackable,
|
||||
EvolvedAttackableCount,
|
||||
EvolvedSkill,
|
||||
EvoDestroy,
|
||||
EvoBuff,
|
||||
EvoHeal,
|
||||
EvoBanish,
|
||||
EvoSubtractCountdown,
|
||||
EvoRecoverPp,
|
||||
EvoSetLeaderMaxLife,
|
||||
EvoDiscard,
|
||||
EvoMetamorphose,
|
||||
EvoHandMetamorphose,
|
||||
EvoBounce,
|
||||
EvoRush,
|
||||
EvoQuick,
|
||||
EvoGuard,
|
||||
EvoKiller,
|
||||
EvoDrain,
|
||||
EvoAttackableCount,
|
||||
EvoChangeCost,
|
||||
EvoHandSelect,
|
||||
EvoShield,
|
||||
EvoDamageCut,
|
||||
EvoReanimate,
|
||||
EvoAddDeck,
|
||||
ClashRemoveSkill,
|
||||
ClashRemoveTag,
|
||||
AttackRemoveSkill,
|
||||
CantAttack,
|
||||
ForceAttackUnit,
|
||||
OtherAttackBuff,
|
||||
OtherAttackDamage,
|
||||
OtherAttackHeal,
|
||||
OtherAttackToken,
|
||||
OtherAttackAttachTag,
|
||||
OtherAttackRemoveTag,
|
||||
OtherEvoBuff,
|
||||
OtherEvoDamage,
|
||||
OtherEvoBanish,
|
||||
OtherEvoSubtractCountdown,
|
||||
OtherEvoEvo,
|
||||
OtherEvoToken,
|
||||
OtherEvoShield,
|
||||
SelfAndOtherEvoDamage,
|
||||
SelfAndOtherEvoAttachTag,
|
||||
SelfAndOtherEvoShield,
|
||||
SelfAndOtherEvoDestroy,
|
||||
SelfAndOtherEvoBounce,
|
||||
SelfAndOtherEvoToken,
|
||||
SelfAndOtherEvoDraw,
|
||||
SelfAndOtherEvoAddCemetery,
|
||||
SelfAndOtherEvoHeal,
|
||||
SelfAndOtherEvoTokenDraw,
|
||||
BattleBonus,
|
||||
BattleBonusRate,
|
||||
HandPlus,
|
||||
Break,
|
||||
OtherBreakBonus,
|
||||
OtherBanishBonus,
|
||||
OtherLeaveBonus,
|
||||
MemberBattleBonus,
|
||||
MemberBattleBonusRate,
|
||||
EnemyBattleBonus,
|
||||
EnemyBattleBonusRate,
|
||||
BounceBonus,
|
||||
BanishBonus,
|
||||
RemoveSkill,
|
||||
OneMoreLastword,
|
||||
BreakDestroy,
|
||||
ModifyHeal,
|
||||
LeaveBonus,
|
||||
ForceBerserk,
|
||||
BanishAttachTag,
|
||||
OtherBanishToken,
|
||||
OtherBanishAddCemetery,
|
||||
MulliganKeep,
|
||||
MulliganChange,
|
||||
Necromance,
|
||||
EarthRite,
|
||||
BurialRite,
|
||||
Enhance,
|
||||
Accelerate,
|
||||
Crystalize,
|
||||
ChoiceTransform,
|
||||
LastwordReanimate,
|
||||
ReanimateBonus,
|
||||
ReanimateEvo,
|
||||
PlayRecoverPP,
|
||||
FanfareRecoverPp,
|
||||
BuffRecoverPP,
|
||||
BreakRecoverPp,
|
||||
CondChoice,
|
||||
EvoChoice,
|
||||
PlayChoice,
|
||||
FanfareChoice,
|
||||
ChoiceBrave,
|
||||
AttachTag_Start,
|
||||
AttackAttachTag,
|
||||
LastwordAttachTag,
|
||||
EvoAttachTag,
|
||||
SummonAttachTag,
|
||||
OtherSummonAttachTag,
|
||||
BreakAttachTag,
|
||||
NecromanceAttachTag,
|
||||
TurnStartAttachTag,
|
||||
TurnEndAttachTag,
|
||||
HealAttachTag,
|
||||
FusionAttachTag,
|
||||
PlayAttachTag,
|
||||
OtherPlayAttachTag,
|
||||
FanfareAttachTag,
|
||||
ChangeInplayAttachTag,
|
||||
FanfareAttachStyle,
|
||||
AttachTag_End,
|
||||
TurnEndRemoveTag,
|
||||
PlayCopyTag,
|
||||
FanfareCopyTag,
|
||||
LeaveToken,
|
||||
EvoTokenDraw,
|
||||
PlayTokenDraw,
|
||||
FanfareTokenDraw,
|
||||
PlaySummonHandCard,
|
||||
FanfareSummonHandCard,
|
||||
PlayDiscard,
|
||||
FanfareDiscard,
|
||||
DiscardedBonus,
|
||||
DiscardedToken,
|
||||
DiscardDamage,
|
||||
DiscardHeal,
|
||||
AllyDiscardBonus,
|
||||
EmoteOnPlay,
|
||||
EmoteOnEvo,
|
||||
EmoteOnAtk,
|
||||
EmoteOnDestroy,
|
||||
ForceEmoteOnDestroy,
|
||||
EmoteOnTurnEnd,
|
||||
PlagueCity,
|
||||
Fusion,
|
||||
FusionBonus,
|
||||
FusionDraw,
|
||||
BuffRush,
|
||||
BuffHeal,
|
||||
BuffBuff,
|
||||
BuffEvo,
|
||||
BuffDraw,
|
||||
GetOn,
|
||||
GetOnBanish,
|
||||
GetOnDamage,
|
||||
GetOnEvo,
|
||||
GetOffMetamorphose,
|
||||
GetOffEvo,
|
||||
RallyCountPlus,
|
||||
PlayActivateCount,
|
||||
AttackActivateCount,
|
||||
BreakActivateCount,
|
||||
BanishActivateCount,
|
||||
DamagedActivateCount,
|
||||
BuffActivateCounnt,
|
||||
TurnEndActivateCount,
|
||||
HealActivateCount,
|
||||
NecromanceActivateCount,
|
||||
EvoActivateCount,
|
||||
SummonActivateCount,
|
||||
SetAITribe,
|
||||
FanfareSpellboost,
|
||||
PlaySpellboost,
|
||||
FanfareAddCemetery,
|
||||
PlayAddCemetery,
|
||||
NecromanceAddCemetery,
|
||||
NecromanceDamage,
|
||||
NecromanceHeal,
|
||||
PlayBanAttack,
|
||||
FanfareBanAttack,
|
||||
PlayIgnoreGuard,
|
||||
FanfareIgnoreGuard,
|
||||
GenerateTag,
|
||||
PlayChangeClass,
|
||||
FanfareChangeClass,
|
||||
PlayChangeTribe,
|
||||
FanfareChangeTribe,
|
||||
PlayChangeCost,
|
||||
FanfareChangeCost,
|
||||
RemoveByDestroy,
|
||||
PlayNotBeAttacked,
|
||||
FanfareNotBeAttacked,
|
||||
PlayAttackableCount,
|
||||
FanfareAttackableCount,
|
||||
Stack,
|
||||
BreakAddStack,
|
||||
EvoAddStack,
|
||||
ChangeInplayImmediateRemoveByBanish,
|
||||
ChangeInplayImmediateRemoveByDestroy,
|
||||
ChangeInplayCannotPlay,
|
||||
ChangeInplayCannotAttack,
|
||||
ChangeInplayImmediateShield,
|
||||
ChangeInplayImmediateDamageCut,
|
||||
ChangeInplayImmediateDamageClip,
|
||||
ChangeInplayImmediateLifeLowerLimit,
|
||||
ChangeInplayImmediateDamageModifier,
|
||||
ChangeInplayImmediateUntouchable,
|
||||
ChangeInplayImmediateIndestructible,
|
||||
ChangePpTotalBuff,
|
||||
EvoSetStatus,
|
||||
PlayModifyConsumeEp,
|
||||
FanfareModifyConsumeEp,
|
||||
PlayEvo,
|
||||
FanfareEvo,
|
||||
OtherPlayEvo,
|
||||
OtherEnhanceEvo,
|
||||
OtherPlayDamage,
|
||||
OtherPlayRecoverPp,
|
||||
OtherPlayDestroy,
|
||||
OtherPlayBuff,
|
||||
OtherPlayToken,
|
||||
OtherPlayRemoveTag,
|
||||
OtherPlayBounce,
|
||||
OtherPlayQuick,
|
||||
OtherLeaveDamage,
|
||||
OtherLeaveToken,
|
||||
AttackSubtractCountdown,
|
||||
EvolveToOther,
|
||||
LastwordEvo,
|
||||
LastwordRemoveSkill,
|
||||
LastwordAddCemetery,
|
||||
LastwordDamageClip,
|
||||
LastwordShield,
|
||||
TurnStartSubtractCountdown,
|
||||
TurnStartDamageCut,
|
||||
TurnStartShield,
|
||||
TurnStartDamage,
|
||||
PlayShield,
|
||||
FanfareShield,
|
||||
AttackShield,
|
||||
ClashShield,
|
||||
PlayDamageCut,
|
||||
FanfareDamageCut,
|
||||
PlayDamageClip,
|
||||
FanfareDamageClip,
|
||||
AttackDamageClip,
|
||||
ClashDamageClip,
|
||||
BuffBonus,
|
||||
FanfareRemoveGuard,
|
||||
ForceImmediateAttack,
|
||||
FusionMetamorphose,
|
||||
LastwordSubtractCountdown,
|
||||
LeaveAttachTag,
|
||||
PlayAddDeck,
|
||||
FanfareAddDeck,
|
||||
AttackAddDeck,
|
||||
None
|
||||
}
|
||||
192
SVSim.BattleEngine/Engine/Wizard/AIPlayedCardContainer.cs
Normal file
192
SVSim.BattleEngine/Engine/Wizard/AIPlayedCardContainer.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayedCardContainer
|
||||
{
|
||||
private List<AIVirtualCard> _allyTurnPlayedCardList;
|
||||
|
||||
private List<AIVirtualCard> _allyInGamePlayedCardList;
|
||||
|
||||
private List<AIVirtualCard> _allyPreviousTurnPlayedCardList;
|
||||
|
||||
private List<AIVirtualCard> _enemyTurnPlayedCardList;
|
||||
|
||||
private List<AIVirtualCard> _enemyInGamePlayedCardList;
|
||||
|
||||
private List<AIVirtualCard> _enemyPreviousTurnPlayedCardList;
|
||||
|
||||
public int AllyTurnPlayedCardCount => _allyTurnPlayedCardList.Count;
|
||||
|
||||
public int AllyInGamePlayedCardCount => _allyInGamePlayedCardList.Count;
|
||||
|
||||
public AIPlayedCardContainer()
|
||||
{
|
||||
_allyTurnPlayedCardList = new List<AIVirtualCard>();
|
||||
_allyInGamePlayedCardList = new List<AIVirtualCard>();
|
||||
_allyPreviousTurnPlayedCardList = new List<AIVirtualCard>();
|
||||
_enemyTurnPlayedCardList = new List<AIVirtualCard>();
|
||||
_enemyInGamePlayedCardList = new List<AIVirtualCard>();
|
||||
_enemyPreviousTurnPlayedCardList = new List<AIVirtualCard>();
|
||||
}
|
||||
|
||||
public AIPlayedCardContainer(AIPlayedCardContainer source)
|
||||
{
|
||||
_allyTurnPlayedCardList = new List<AIVirtualCard>(source._allyTurnPlayedCardList);
|
||||
_allyInGamePlayedCardList = new List<AIVirtualCard>(source._allyInGamePlayedCardList);
|
||||
_allyPreviousTurnPlayedCardList = new List<AIVirtualCard>(source._allyPreviousTurnPlayedCardList);
|
||||
_enemyTurnPlayedCardList = new List<AIVirtualCard>(source._enemyTurnPlayedCardList);
|
||||
_enemyInGamePlayedCardList = new List<AIVirtualCard>(source._enemyInGamePlayedCardList);
|
||||
_enemyPreviousTurnPlayedCardList = new List<AIVirtualCard>(source._enemyPreviousTurnPlayedCardList);
|
||||
}
|
||||
|
||||
public AIPlayedCardContainer Clone()
|
||||
{
|
||||
return new AIPlayedCardContainer(this);
|
||||
}
|
||||
|
||||
public void Validate(AIPlayedCardContainer source)
|
||||
{
|
||||
}
|
||||
|
||||
private void CopyPreviousPlayCardOnTurnShift(AIVirtualTurnStartInfo turnStartSituation)
|
||||
{
|
||||
if (turnStartSituation != null)
|
||||
{
|
||||
if (turnStartSituation.Actor.IsAlly)
|
||||
{
|
||||
_enemyPreviousTurnPlayedCardList = new List<AIVirtualCard>(_enemyTurnPlayedCardList);
|
||||
}
|
||||
else
|
||||
{
|
||||
_allyPreviousTurnPlayedCardList = new List<AIVirtualCard>(_allyTurnPlayedCardList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearInTurn(AIVirtualTurnStartInfo turnStartSituation = null)
|
||||
{
|
||||
CopyPreviousPlayCardOnTurnShift(turnStartSituation);
|
||||
_allyTurnPlayedCardList.Clear();
|
||||
_enemyTurnPlayedCardList.Clear();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
ClearInTurn();
|
||||
_allyInGamePlayedCardList.Clear();
|
||||
_enemyInGamePlayedCardList.Clear();
|
||||
_allyPreviousTurnPlayedCardList.Clear();
|
||||
_enemyPreviousTurnPlayedCardList.Clear();
|
||||
}
|
||||
|
||||
public int GetPlayedCountInTurn(List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return AIFilteringUtility.MultipleFiltering(tagOwner.IsAlly ? _allyTurnPlayedCardList : _enemyTurnPlayedCardList, filters, tagOwner, playPtn, situation, isBlockDeadCard: false)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public int GetPlayedCountInPreviousTurn(bool isAllyList, List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return AIFilteringUtility.MultipleFiltering(isAllyList ? _allyPreviousTurnPlayedCardList : _enemyPreviousTurnPlayedCardList, filters, tagOwner, playPtn, situation, isBlockDeadCard: false)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public int GetAllPlayedCountInTurn(bool isAITurn)
|
||||
{
|
||||
return (isAITurn ? _allyTurnPlayedCardList : _enemyTurnPlayedCardList)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public int GetPlayedCountInGame(List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
int num = 0;
|
||||
num = ((!AIPlayPtnUtility.IsInPlayPtn(tagOwner, playPtn)) ? (num + AIPlayPtnUtility.GetPlayPtnCardCount(filters, tagOwner, playPtn, situation)) : (num + AIPlayPtnUtility.GetBeforePlayPtnCount(filters, tagOwner, playPtn, situation)));
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.IsAlly ? _allyInGamePlayedCardList : _enemyInGamePlayedCardList, filters, tagOwner, playPtn, situation, isBlockDeadCard: false);
|
||||
if (list != null)
|
||||
{
|
||||
num += list.Count;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public int GetPlayedNameCount(List<AIScriptTokenBase> filters, AIScriptTokenArgType turnOrGame, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = null;
|
||||
switch (turnOrGame)
|
||||
{
|
||||
case AIScriptTokenArgType.TURN:
|
||||
list = (tagOwner.IsAlly ? _allyTurnPlayedCardList : _enemyTurnPlayedCardList);
|
||||
break;
|
||||
case AIScriptTokenArgType.GAME:
|
||||
list = (tagOwner.IsAlly ? _allyInGamePlayedCardList : _enemyInGamePlayedCardList);
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError($"GetPlayedNameCount() error!! turnOrGame == {turnOrGame}");
|
||||
return 0;
|
||||
}
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return AIFilteringUtility.GetCardNameCountFromList(list, filters, tagOwner, playPtn, situation);
|
||||
}
|
||||
|
||||
public bool IsPlayedAsAccelerate(AIVirtualCard card)
|
||||
{
|
||||
CardParameter baseParameter = card.BaseCard.BaseParameter;
|
||||
if (!card.IsSpell || baseParameter.BaseCardId == baseParameter.ResourceCardId || !IsPlayedCard(card))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CardParameter cardParameterFromId = CardMaster.GetInstanceForBattle().GetCardParameterFromId(baseParameter.ResourceCardId);
|
||||
if (cardParameterFromId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (cardParameterFromId.Cost > baseParameter.Cost && cardParameterFromId.CharType == CardBasePrm.CharaType.NORMAL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsPlayedAsCrystalize(AIVirtualCard card)
|
||||
{
|
||||
if (!IsPlayedCard(card) || !card.IsAmulet)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (card.BaseCard.TransformInfo.Type != BattleCardBase.TransformType.Crystallize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPlayedCard(AIVirtualCard card)
|
||||
{
|
||||
return (card.IsAlly ? _allyInGamePlayedCardList : _enemyInGamePlayedCardList).Any((AIVirtualCard c) => c.IsSameCard(card));
|
||||
}
|
||||
|
||||
public void AddPlayedCard(AIVirtualCard card)
|
||||
{
|
||||
if (!IsPlayedCard(card))
|
||||
{
|
||||
List<AIVirtualCard> container = (card.IsAlly ? _allyTurnPlayedCardList : _enemyTurnPlayedCardList);
|
||||
AIParamQuery.AddElementToList(card, container);
|
||||
List<AIVirtualCard> container2 = (card.IsAlly ? _allyInGamePlayedCardList : _enemyInGamePlayedCardList);
|
||||
AIParamQuery.AddElementToList(card, container2);
|
||||
}
|
||||
}
|
||||
|
||||
public void RollBackFromOneRecord(AIVirtualFieldRollBackRecord.PlayedCardContainerRecord rollBackRecord)
|
||||
{
|
||||
for (int num = _allyTurnPlayedCardList.Count - 1; num >= rollBackRecord.AllyTurnPlayedCardCount; num--)
|
||||
{
|
||||
_allyTurnPlayedCardList.RemoveAt(num);
|
||||
}
|
||||
for (int num2 = _allyInGamePlayedCardList.Count - 1; num2 >= rollBackRecord.AllyInGamePlayedCardCount; num2--)
|
||||
{
|
||||
_allyInGamePlayedCardList.RemoveAt(num2);
|
||||
}
|
||||
}
|
||||
}
|
||||
433
SVSim.BattleEngine/Engine/Wizard/AIPlayptnRecorder.cs
Normal file
433
SVSim.BattleEngine/Engine/Wizard/AIPlayptnRecorder.cs
Normal file
@@ -0,0 +1,433 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayptnRecorder
|
||||
{
|
||||
private List<AISinglePlayptnRecord> _allPlayPtnList;
|
||||
|
||||
private List<AIVirtualField> _referenceFieldList;
|
||||
|
||||
private bool _isRegisteringPlayPtn;
|
||||
|
||||
private bool _isCalculatingPriority;
|
||||
|
||||
public List<AISinglePlayptnRecord> ValidPlayPtnList { get; private set; }
|
||||
|
||||
public AIPlayptnRecorder()
|
||||
{
|
||||
ValidPlayPtnList = new List<AISinglePlayptnRecord>();
|
||||
_allPlayPtnList = new List<AISinglePlayptnRecord>();
|
||||
_referenceFieldList = new List<AIVirtualField>();
|
||||
_isRegisteringPlayPtn = false;
|
||||
}
|
||||
|
||||
public static void BuildSinglePlayptnRecord(List<int> playPtn, AISinglePlayptnRecord currentRecord, AIVirtualField field, AIVirtualFieldRollBackBasicProcessor rollBackProcessor)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
int num = 0;
|
||||
for (int i = 0; i < currentRecord.PlayedCardList.Count; i++)
|
||||
{
|
||||
if (!currentRecord.PlayedCardList[i].IsProcessed)
|
||||
{
|
||||
num = i;
|
||||
break;
|
||||
}
|
||||
list.Add(playPtn[i]);
|
||||
}
|
||||
for (int j = num; j < playPtn.Count; j++)
|
||||
{
|
||||
int num2 = playPtn[j];
|
||||
list.Add(num2);
|
||||
PlayedCardInfo playedCardInfo = currentRecord.PlayedCardList[j];
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[num2];
|
||||
AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(aIVirtualCard, aIVirtualCard, AIOperationType.PLAY);
|
||||
PlaySimulationType playType;
|
||||
int num3 = (playedCardInfo.UsedCost = aIVirtualCard.GetUseCost(currentRecord.LastRestPp, list, aIVirtualTargetSelectAction, out playType));
|
||||
if (num3 >= 0)
|
||||
{
|
||||
int num4 = currentRecord.LastRestPp - num3;
|
||||
playedCardInfo.PlayType = playType;
|
||||
num4 += AIEvaluateBonusFromOhterUtility.GetTotalRecoverPp(aIVirtualCard, playPtn, aIVirtualTargetSelectAction);
|
||||
playedCardInfo.RestPp = num4;
|
||||
playedCardInfo.DrawCount = aIVirtualCard.GetPlayDrawCount(list, aIVirtualTargetSelectAction);
|
||||
SetTransformCardToPlayedInfo(playedCardInfo, aIVirtualCard, field, list, aIVirtualTargetSelectAction, num3, playType);
|
||||
}
|
||||
else
|
||||
{
|
||||
playedCardInfo.RestPp = -1;
|
||||
playedCardInfo.PlayType = PlaySimulationType.Undefined;
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
playedCardInfo.IsPassedPlayCondition = aIVirtualCard.BaseCard.BaseMovable;
|
||||
}
|
||||
else
|
||||
{
|
||||
playedCardInfo.IsPassedPlayCondition = true;
|
||||
}
|
||||
currentRecord.UpdatePlayPtnRecord(playedCardInfo);
|
||||
if (!currentRecord.IsValid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
AIPreprocessSimulationUtility.SimulatePreprocess(aIVirtualTargetSelectAction.Actor, aIVirtualTargetSelectAction, field, AIScriptTokenArgType.WHEN_PLAY, isPseudo: true);
|
||||
currentRecord.RegisterPreprocess(playedCardInfo, aIVirtualTargetSelectAction, field);
|
||||
PseudoExecuteCardPlayProcess(field, currentRecord, playedCardInfo, aIVirtualTargetSelectAction);
|
||||
}
|
||||
rollBackProcessor.ResetVirtualFieldToStart();
|
||||
}
|
||||
|
||||
public void CreateValidPlayPtnList(AIVirtualField field)
|
||||
{
|
||||
AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(field);
|
||||
int fieldIndex = RegisterFieldAndGetFieldIndex(field);
|
||||
List<Tuple<int, List<int>>> list = AIHandPtnCalculator.CreateSortedPlayPtnList(field.AI);
|
||||
_isRegisteringPlayPtn = true;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = new AISinglePlayptnRecord(list[i].second, field, fieldIndex);
|
||||
_allPlayPtnList.Add(aISinglePlayptnRecord);
|
||||
ProcessPlayPtnRecord(aISinglePlayptnRecord, field, rollBackProcessor);
|
||||
}
|
||||
_isRegisteringPlayPtn = false;
|
||||
}
|
||||
|
||||
private void ProcessPlayPtnRecord(AISinglePlayptnRecord currentRecord, AIVirtualField field, AIVirtualFieldRollBackBasicProcessor rollBackProcessor)
|
||||
{
|
||||
List<int> playPtn = currentRecord.PlayPtn;
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = FindMostlyMatchedPlayPtn(currentRecord);
|
||||
if (aISinglePlayptnRecord != null)
|
||||
{
|
||||
if (!aISinglePlayptnRecord.IsValid)
|
||||
{
|
||||
_allPlayPtnList.Remove(currentRecord);
|
||||
return;
|
||||
}
|
||||
currentRecord = RegisterMatchedRecordToNewRecord(aISinglePlayptnRecord, field, currentRecord);
|
||||
}
|
||||
if (!currentRecord.IsValid)
|
||||
{
|
||||
rollBackProcessor.ResetVirtualFieldToStart();
|
||||
return;
|
||||
}
|
||||
BuildSinglePlayptnRecord(playPtn, currentRecord, field, rollBackProcessor);
|
||||
if (currentRecord.IsToBeRegister() && currentRecord.IsValid && !CheckSimilarValidPlayPtnRecord(currentRecord.PlayPtnHash))
|
||||
{
|
||||
ValidPlayPtnList.Add(currentRecord);
|
||||
}
|
||||
}
|
||||
|
||||
public AISinglePlayptnRecord FindMatchedPlayPtnRecord(List<int> playPtn, AIVirtualField playPtnField)
|
||||
{
|
||||
ulong hash = playPtnField.GetHash();
|
||||
int num = GetFieldIndex(hash);
|
||||
for (int i = 0; i < _allPlayPtnList.Count; i++)
|
||||
{
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = _allPlayPtnList[i];
|
||||
if (aISinglePlayptnRecord.PlayPtn.Count != playPtn.Count || num != aISinglePlayptnRecord.ReferenceFieldIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = true;
|
||||
for (int j = 0; j < playPtn.Count; j++)
|
||||
{
|
||||
if (!playPtnField.AllyHandCards[playPtn[j]].IsSameCard(aISinglePlayptnRecord.PlayedCardList[j].Card))
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
return aISinglePlayptnRecord;
|
||||
}
|
||||
}
|
||||
if (_isRegisteringPlayPtn)
|
||||
{
|
||||
AIConsoleUtility.LogError("FindMatchedPlayPtnRecordで無限ループが発生しそうです!!!!!");
|
||||
return null;
|
||||
}
|
||||
_isRegisteringPlayPtn = true;
|
||||
if (num < 0)
|
||||
{
|
||||
_referenceFieldList.Add(playPtnField);
|
||||
num = _referenceFieldList.Count - 1;
|
||||
}
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord2 = new AISinglePlayptnRecord(playPtn, playPtnField, num);
|
||||
_allPlayPtnList.Add(aISinglePlayptnRecord2);
|
||||
AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(playPtnField);
|
||||
ProcessPlayPtnRecord(aISinglePlayptnRecord2, playPtnField, rollBackProcessor);
|
||||
_isRegisteringPlayPtn = false;
|
||||
return aISinglePlayptnRecord2;
|
||||
}
|
||||
|
||||
public void StartCalculatingPriority()
|
||||
{
|
||||
_isCalculatingPriority = true;
|
||||
}
|
||||
|
||||
public void StopCalculatingPriority()
|
||||
{
|
||||
_isCalculatingPriority = false;
|
||||
}
|
||||
|
||||
public int GetRestPp(List<int> playPtn, AIVirtualField field)
|
||||
{
|
||||
if (_isCalculatingPriority)
|
||||
{
|
||||
AIConsoleUtility.LogWarning("AIPlayptnRecorder.GetRestPp() warning!! Calling GetRestPp() during calculating priority!!!!!");
|
||||
return 0;
|
||||
}
|
||||
int allyPp = field.AllyPp;
|
||||
if (playPtn == null || playPtn.Count <= 0)
|
||||
{
|
||||
return allyPp;
|
||||
}
|
||||
AISinglePlayptnRecord playptnRecordOnSim = field.GetPlayptnRecordOnSim(playPtn);
|
||||
if (playptnRecordOnSim == null)
|
||||
{
|
||||
return allyPp;
|
||||
}
|
||||
allyPp = playptnRecordOnSim.LastRestPp;
|
||||
return Mathf.Max(0, allyPp);
|
||||
}
|
||||
|
||||
public int GetFixedCostWithCheckingPlayType(AIVirtualCard card, AIVirtualField field, List<int> playPtn, out PlaySimulationType playType)
|
||||
{
|
||||
int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp);
|
||||
if (playPtn == null || playPtn.Count <= 0 || !card.IsAlly)
|
||||
{
|
||||
return card.GetUseCost(restPp, playPtn, null, out playType);
|
||||
}
|
||||
int cardPlayPtnIndex = GetCardPlayPtnIndex(card, field, playPtn);
|
||||
if (cardPlayPtnIndex == -1)
|
||||
{
|
||||
return card.GetUseCost(restPp, playPtn, null, out playType);
|
||||
}
|
||||
return GetCardCostAndTypeFromPlayPtnRecord(card, cardPlayPtnIndex, field, playPtn, out playType);
|
||||
}
|
||||
|
||||
public bool IsCardPlayingSimulationType(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation, PlaySimulationType targetPlayType)
|
||||
{
|
||||
List<int> list = (card.IsAlly ? playPtn : null);
|
||||
int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp);
|
||||
int num = -1;
|
||||
if (card.IsAlly && list != null && list.Count > 0)
|
||||
{
|
||||
num = field.AI.PlayPtnRecorder.GetCardPlayPtnIndex(card, field, list);
|
||||
}
|
||||
if (num != -1)
|
||||
{
|
||||
field.AI.PlayPtnRecorder.GetCardCostAndTypeFromPlayPtnRecord(card, num, field, list, out var playType);
|
||||
return playType == targetPlayType;
|
||||
}
|
||||
return card.IsPlayingSimulationType(restPp, playPtn, situation, targetPlayType);
|
||||
}
|
||||
|
||||
public int GetCardPlaySimulationTypeCost(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation, PlaySimulationType targetPlayType)
|
||||
{
|
||||
List<int> list = (card.IsAlly ? playPtn : null);
|
||||
int restPp = (card.IsAlly ? field.AllyPp : field.EnemyPp);
|
||||
int num = -1;
|
||||
if (card.IsAlly && list != null && list.Count > 0)
|
||||
{
|
||||
num = field.AI.PlayPtnRecorder.GetCardPlayPtnIndex(card, field, list);
|
||||
}
|
||||
if (num != -1)
|
||||
{
|
||||
PlaySimulationType playType;
|
||||
int cardCostAndTypeFromPlayPtnRecord = field.AI.PlayPtnRecorder.GetCardCostAndTypeFromPlayPtnRecord(card, num, field, list, out playType);
|
||||
if (playType != targetPlayType)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return cardCostAndTypeFromPlayPtnRecord;
|
||||
}
|
||||
return card.GetPlaySimulationTypeCost(restPp, playPtn, situation, targetPlayType);
|
||||
}
|
||||
|
||||
public int GetCardPlayPtnIndex(AIVirtualCard card, AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
int item = -1;
|
||||
for (int i = 0; i < field.AllyHandCards.Count; i++)
|
||||
{
|
||||
if (field.AllyHandCards[i].IsSameCard(card))
|
||||
{
|
||||
item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int num = playPtn.IndexOf(item);
|
||||
if (num < 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIPlayPtnRecorder.GetFixedCostWithCheckingPlayType() error!! card is not in playPtn!!!!!");
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public int GetCardCostAndTypeFromPlayPtnRecord(AIVirtualCard card, int playPtnIndex, AIVirtualField field, List<int> playPtn, out PlaySimulationType playType)
|
||||
{
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = FindMatchedPlayPtnRecord(playPtn, field);
|
||||
playType = PlaySimulationType.Undefined;
|
||||
if (aISinglePlayptnRecord != null)
|
||||
{
|
||||
PlayedCardInfo playedCardInfo = aISinglePlayptnRecord.PlayedCardList[playPtnIndex];
|
||||
if (playedCardInfo.Card.IsSameCard(card))
|
||||
{
|
||||
playType = playedCardInfo.PlayType;
|
||||
return playedCardInfo.UsedCost;
|
||||
}
|
||||
AIConsoleUtility.LogError("AIPlayPtnRecorder.GetCardCostAndTypeInPlayPtnRecord() error!! Cannot find same card from matched playPtn record!!!!!");
|
||||
return -1;
|
||||
}
|
||||
AIConsoleUtility.LogError("AIPlayPtnRecorder.GetCardCostAndTypeInPlayPtnRecord() error!! Cannot find record!!!!!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private AISinglePlayptnRecord RegisterMatchedRecordToNewRecord(AISinglePlayptnRecord matched, AIVirtualField field, AISinglePlayptnRecord newRecord)
|
||||
{
|
||||
for (int i = 0; i < matched.PlayedCardList.Count; i++)
|
||||
{
|
||||
PlayedCardInfo playedCardInfo = newRecord.PlayedCardList[i];
|
||||
playedCardInfo.CloneFromPartlyMatchedInfo(matched.PlayedCardList[i]);
|
||||
AIVirtualCard card = playedCardInfo.Card;
|
||||
AIVirtualCard obj = ((playedCardInfo.TransformCard == null) ? card : playedCardInfo.TransformCard);
|
||||
AIVirtualTargetSelectAction situation = new AIVirtualTargetSelectAction(obj, card, AIOperationType.PLAY);
|
||||
AIPreprocessSimulationUtility.SimulatePreprocess(obj, situation, field, AIScriptTokenArgType.WHEN_PLAY, isPseudo: true);
|
||||
newRecord.RegisterPreprocess(playedCardInfo, situation, field);
|
||||
newRecord.UpdatePlayPtnRecord(playedCardInfo);
|
||||
PseudoExecuteCardPlayProcess(field, newRecord, playedCardInfo, situation);
|
||||
if (!newRecord.IsValid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newRecord;
|
||||
}
|
||||
|
||||
private AISinglePlayptnRecord FindMostlyMatchedPlayPtn(AISinglePlayptnRecord record)
|
||||
{
|
||||
AISinglePlayptnRecord result = null;
|
||||
int num = 0;
|
||||
List<int> playPtn = record.PlayPtn;
|
||||
for (int i = 0; i < _allPlayPtnList.Count; i++)
|
||||
{
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = _allPlayPtnList[i];
|
||||
int count = aISinglePlayptnRecord.PlayPtn.Count;
|
||||
if (record.ReferenceFieldIndex == aISinglePlayptnRecord.ReferenceFieldIndex && playPtn.Count > count && aISinglePlayptnRecord.IsMatchedPattern(playPtn) && count > num)
|
||||
{
|
||||
num = count;
|
||||
result = aISinglePlayptnRecord;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void SetTransformCardToPlayedInfo(PlayedCardInfo info, AIVirtualCard playedCard, AIVirtualField field, List<int> playPtn, AIVirtualTargetSelectAction situation, int usedCost, PlaySimulationType type)
|
||||
{
|
||||
if (AIPlayCardSimulationUtility.SetRealActorToPlaySituation(situation, field, usedCost, type))
|
||||
{
|
||||
info.SetTransformCard(situation.Actor);
|
||||
}
|
||||
}
|
||||
|
||||
private static void PseudoExecuteCardPlayProcess(AIVirtualField field, AISinglePlayptnRecord record, PlayedCardInfo playedCardInfo, AIVirtualTargetSelectAction situation)
|
||||
{
|
||||
AIVirtualCard card = playedCardInfo.Card;
|
||||
if (card.IsSpell || card.IsAccelerated(field, null, situation))
|
||||
{
|
||||
AIPlayCardSimulationUtility.UpdateFieldWhenEvaluateSpellCard(card, field);
|
||||
}
|
||||
if (card.IsUnit)
|
||||
{
|
||||
record.FirstSummonedAllyFollower = card;
|
||||
}
|
||||
field.PlayedCardContainer.AddPlayedCard(card);
|
||||
card.PseudoExecuteWhenPlayTags(field, record, playedCardInfo, situation);
|
||||
field.AllActivateCountHolderIncrement(situation, AIPlayTagType.PlayActivateCount, card);
|
||||
field.IsNoInstantAttackRecheck();
|
||||
}
|
||||
|
||||
private bool CheckSimilarValidPlayPtnRecord(ulong currentRecordHash)
|
||||
{
|
||||
for (int i = 0; i < ValidPlayPtnList.Count; i++)
|
||||
{
|
||||
if (ValidPlayPtnList[i].PlayPtnHash == currentRecordHash)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int RegisterFieldAndGetFieldIndex(AIVirtualField field)
|
||||
{
|
||||
ulong hash = field.GetHash();
|
||||
for (int i = 0; i < _referenceFieldList.Count; i++)
|
||||
{
|
||||
if (_referenceFieldList[i].GetHash() == hash)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
_referenceFieldList.Add(field);
|
||||
return _referenceFieldList.Count - 1;
|
||||
}
|
||||
|
||||
private int GetFieldIndex(ulong fieldHash)
|
||||
{
|
||||
for (int i = 0; i < _referenceFieldList.Count; i++)
|
||||
{
|
||||
if (fieldHash == _referenceFieldList[i].GetHash())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public AISinglePlayptnRecord GetEmptyPlayPtnRecord()
|
||||
{
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = ValidPlayPtnList[0];
|
||||
if (aISinglePlayptnRecord.PlayedCardList.Count > 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIPlayPtnRecorder.GetEmptyPlayPtnRecord() error!! first record is not empty!!!!!");
|
||||
}
|
||||
return aISinglePlayptnRecord;
|
||||
}
|
||||
|
||||
public AISinglePlayptnRecord CreateRecordForNextPlayTargetSelectSimulation(AIVirtualTargetSelectAction action, AISinglePlayptnRecord previousRecord, AIVirtualField field)
|
||||
{
|
||||
bool num = action.ActionType == AIOperationType.PLAY;
|
||||
int fieldIndex = RegisterFieldAndGetFieldIndex(field);
|
||||
List<int> list = new List<int>();
|
||||
for (int i = (num ? 1 : 0); i < previousRecord.PlayedCardList.Count; i++)
|
||||
{
|
||||
AIVirtualCard card = previousRecord.PlayedCardList[i].Card;
|
||||
AIVirtualCard aIVirtualCard = field.SearchVirtualCard(card);
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIPlayptnRecorder.CreateRecordForNextPlayTargetSelectSimulation() error!! Cannot find play card!!!!!");
|
||||
}
|
||||
else if (aIVirtualCard.IsInHand)
|
||||
{
|
||||
int num2 = field.AllyHandCards.IndexOf(aIVirtualCard);
|
||||
if (num2 < 0 || field.AllyHandCards.Count <= num2)
|
||||
{
|
||||
AIConsoleUtility.LogError($"CreateRecordForNextPlayTargetSelectSimulation() error!! handIndex: {num2}, CardName: {aIVirtualCard.CardName}");
|
||||
return null;
|
||||
}
|
||||
list.Add(num2);
|
||||
}
|
||||
}
|
||||
AISinglePlayptnRecord aISinglePlayptnRecord = new AISinglePlayptnRecord(list, field, fieldIndex);
|
||||
_isRegisteringPlayPtn = true;
|
||||
_allPlayPtnList.Add(aISinglePlayptnRecord);
|
||||
AIVirtualFieldRollBackBasicProcessor rollBackProcessor = new AIVirtualFieldRollBackBasicProcessor(field);
|
||||
ProcessPlayPtnRecord(aISinglePlayptnRecord, field, rollBackProcessor);
|
||||
_isRegisteringPlayPtn = false;
|
||||
return aISinglePlayptnRecord;
|
||||
}
|
||||
}
|
||||
42
SVSim.BattleEngine/Engine/Wizard/AIPolicyCollection.cs
Normal file
42
SVSim.BattleEngine/Engine/Wizard/AIPolicyCollection.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPolicyCollection
|
||||
{
|
||||
public List<AIPolicyData> PolicyList { get; protected set; }
|
||||
|
||||
public bool HasPolicy
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PolicyList != null)
|
||||
{
|
||||
return 0 < PolicyList.Count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AIPolicyCollection()
|
||||
{
|
||||
PolicyList = null;
|
||||
}
|
||||
|
||||
public void AddPolicy(AIPolicyData policy)
|
||||
{
|
||||
if (PolicyList == null)
|
||||
{
|
||||
PolicyList = new List<AIPolicyData>();
|
||||
}
|
||||
PolicyList.Add(policy);
|
||||
}
|
||||
|
||||
public void RemovePolicy(AIPolicyData policy)
|
||||
{
|
||||
if (PolicyList.Contains(policy))
|
||||
{
|
||||
PolicyList.Remove(policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
113
SVSim.BattleEngine/Engine/Wizard/AIPolicyCollectionContainer.cs
Normal file
113
SVSim.BattleEngine/Engine/Wizard/AIPolicyCollectionContainer.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPolicyCollectionContainer
|
||||
{
|
||||
private List<AIPolicyType> _holdingPolicyTypes;
|
||||
|
||||
private List<PolicyCollectionWithTypeBase> _policyCollectionTable;
|
||||
|
||||
public AIPolicyCollectionContainer()
|
||||
{
|
||||
_holdingPolicyTypes = null;
|
||||
_policyCollectionTable = null;
|
||||
}
|
||||
|
||||
public bool HasPolicy(AIPolicyType policyType)
|
||||
{
|
||||
if (_holdingPolicyTypes != null)
|
||||
{
|
||||
return _holdingPolicyTypes.Contains(policyType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AIPolicyCollection GetPolicyCollection(AIPolicyType policyType)
|
||||
{
|
||||
if (_policyCollectionTable != null)
|
||||
{
|
||||
for (int i = 0; i < _policyCollectionTable.Count; i++)
|
||||
{
|
||||
PolicyCollectionWithTypeBase policyCollectionWithTypeBase = _policyCollectionTable[i];
|
||||
if (policyCollectionWithTypeBase.HasTag(policyType))
|
||||
{
|
||||
return policyCollectionWithTypeBase.PolicyCollection;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void InitializeAllCollections(List<AIPolicyData> policyList)
|
||||
{
|
||||
for (int i = 0; i < policyList.Count; i++)
|
||||
{
|
||||
AIPolicyData policy = policyList[i];
|
||||
RegisterNewPolicy(policy);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterNewPolicy(AIPolicyData policy)
|
||||
{
|
||||
PolicyCollectionWithTypeBase policyCollectionWithTypeBase = FindPolicyCollectionWityType(policy.PolicyType);
|
||||
if (policyCollectionWithTypeBase != null)
|
||||
{
|
||||
policyCollectionWithTypeBase.AddPolicy(policy);
|
||||
if (_holdingPolicyTypes == null)
|
||||
{
|
||||
_holdingPolicyTypes = new List<AIPolicyType>();
|
||||
}
|
||||
if (!_holdingPolicyTypes.Contains(policy.PolicyType))
|
||||
{
|
||||
_holdingPolicyTypes.Add(policy.PolicyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAttachedPolicies(List<AIPolicyData> attachedPolicies)
|
||||
{
|
||||
for (int i = 0; i < attachedPolicies.Count; i++)
|
||||
{
|
||||
AIPolicyData aIPolicyData = attachedPolicies[i];
|
||||
PolicyCollectionWithTypeBase policyCollectionWithTypeBase = FindPolicyCollectionWityType(aIPolicyData.PolicyType, isCreateNewCollection: false);
|
||||
if (policyCollectionWithTypeBase != null && policyCollectionWithTypeBase.RemovePolicyAndCheckIsNoLongerHoldThisType(aIPolicyData))
|
||||
{
|
||||
_holdingPolicyTypes.Remove(aIPolicyData.PolicyType);
|
||||
if (policyCollectionWithTypeBase is PolicyCollectionWithSingleType)
|
||||
{
|
||||
_policyCollectionTable.Remove(policyCollectionWithTypeBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PolicyCollectionWithTypeBase FindPolicyCollectionWityType(AIPolicyType policyType, bool isCreateNewCollection = true)
|
||||
{
|
||||
if (_policyCollectionTable != null)
|
||||
{
|
||||
for (int i = 0; i < _policyCollectionTable.Count; i++)
|
||||
{
|
||||
PolicyCollectionWithTypeBase policyCollectionWithTypeBase = _policyCollectionTable[i];
|
||||
if (policyCollectionWithTypeBase.IsUnderManagement(policyType))
|
||||
{
|
||||
return policyCollectionWithTypeBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isCreateNewCollection)
|
||||
{
|
||||
PolicyCollectionWithTypeBase policyCollectionWithTypeBase2 = PolicyCollectionWithTypeCreator.Create(policyType);
|
||||
if (policyCollectionWithTypeBase2 != null)
|
||||
{
|
||||
if (_policyCollectionTable == null)
|
||||
{
|
||||
_policyCollectionTable = new List<PolicyCollectionWithTypeBase>();
|
||||
}
|
||||
_policyCollectionTable.Add(policyCollectionWithTypeBase2);
|
||||
}
|
||||
return policyCollectionWithTypeBase2;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
145
SVSim.BattleEngine/Engine/Wizard/AIPolicyData.cs
Normal file
145
SVSim.BattleEngine/Engine/Wizard/AIPolicyData.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPolicyData
|
||||
{
|
||||
private AIConditionExpressions _conditionExpr;
|
||||
|
||||
public int ID { get; private set; }
|
||||
|
||||
public AICategory Category { get; private set; }
|
||||
|
||||
public int Priority { get; private set; }
|
||||
|
||||
public AIPolicyType PolicyType { get; private set; }
|
||||
|
||||
public string ARG { get; private set; }
|
||||
|
||||
public string CONDITION { get; private set; }
|
||||
|
||||
public AIScriptArgumentExpressions Argument { get; private set; }
|
||||
|
||||
public AIPolicyData(AIPolicyDataAsset asset)
|
||||
{
|
||||
ID = asset.ID;
|
||||
Category = ConvertStringToCategory(asset.Category);
|
||||
Priority = asset.Priority;
|
||||
PolicyType = ConvertStringToPolicyType(asset.Type);
|
||||
ARG = asset.Arg;
|
||||
CONDITION = asset.Cond;
|
||||
Argument = CreateArgument(asset.Arg);
|
||||
_conditionExpr = new AIConditionExpressions(asset.Cond);
|
||||
}
|
||||
|
||||
private AIScriptArgumentExpressions CreateArgument(string arg)
|
||||
{
|
||||
switch (PolicyType)
|
||||
{
|
||||
case AIPolicyType.PlayBreak:
|
||||
return new AIPlayBreak(arg);
|
||||
case AIPolicyType.EmoOnTurnEnd:
|
||||
case AIPolicyType.EmoOnTurnStart:
|
||||
case AIPolicyType.PlayerEmoOnTurnEnd:
|
||||
return new AIEmoteOnTurnTransition(arg);
|
||||
case AIPolicyType.AllyPlayBonus:
|
||||
return new AIOtherPlayBonus(arg);
|
||||
case AIPolicyType.AllyPlayBonusRate:
|
||||
return new AIOtherPlayBonusRate(arg);
|
||||
case AIPolicyType.DelayTurnEndTime:
|
||||
return new AIDelayTurnEndTime(arg);
|
||||
case AIPolicyType.MoveFirstBonus:
|
||||
return new AIFirstMoveBonus(arg);
|
||||
case AIPolicyType.GameStartAttachTag:
|
||||
return new AIGameStartAttachTag(arg);
|
||||
default:
|
||||
return new AIScriptArgumentExpressions(arg);
|
||||
}
|
||||
}
|
||||
|
||||
public static AICategory ConvertStringToCategory(string str)
|
||||
{
|
||||
return str switch
|
||||
{
|
||||
"All" => AICategory.ALL,
|
||||
"Elf" => AICategory.ELF,
|
||||
"Royal" => AICategory.ROYAL,
|
||||
"Witch" => AICategory.WITCH,
|
||||
"Dragon" => AICategory.DRAGON,
|
||||
"Necromance" => AICategory.NECROMANCE,
|
||||
"Vampire" => AICategory.VAMPIRE,
|
||||
"Bishop" => AICategory.BISHOP,
|
||||
"Nemesis" => AICategory.NEMESIS,
|
||||
_ => AICategory.ALL,
|
||||
};
|
||||
}
|
||||
|
||||
public static AIPolicyType ConvertStringToPolicyType(string str)
|
||||
{
|
||||
return str switch
|
||||
{
|
||||
"epValue" => AIPolicyType.EpValue,
|
||||
"modUnitRate" => AIPolicyType.ModUnitRate,
|
||||
"unitBonus" => AIPolicyType.UnitBonus,
|
||||
"emoOnTurnEnd" => AIPolicyType.EmoOnTurnEnd,
|
||||
"emoOnTurnStart" => AIPolicyType.EmoOnTurnStart,
|
||||
"playptnBonus" => AIPolicyType.PlayptnBonus,
|
||||
"playBreak" => AIPolicyType.PlayBreak,
|
||||
"barrierBonus" => AIPolicyType.BarrierBonus,
|
||||
"allyPlayB" => AIPolicyType.AllyPlayBonus,
|
||||
"allyPlayBonusRate" => AIPolicyType.AllyPlayBonusRate,
|
||||
"disableLethalCheck" => AIPolicyType.DisableLethalCheck,
|
||||
"delayTurnEndTime" => AIPolicyType.DelayTurnEndTime,
|
||||
"emoOnLeaderDamaged" => AIPolicyType.EmoOnLeaderDamaged,
|
||||
"setReferenceId" => AIPolicyType.SetReferenceId,
|
||||
"setReferenceTribe" => AIPolicyType.SetReferenceTribe,
|
||||
"playerEmoOnTurnEnd" => AIPolicyType.PlayerEmoOnTurnEnd,
|
||||
"playerEmoOnTurnStart" => AIPolicyType.PlayerEmoOnTurnStart,
|
||||
"playerEmoOnLeaderDamaged" => AIPolicyType.PlayerEmoOnLeaderDamaged,
|
||||
"moveFirstBonus" => AIPolicyType.MoveFirstBonus,
|
||||
"gameStartAttachTag" => AIPolicyType.GameStartAttachTag,
|
||||
_ => AIPolicyType.None,
|
||||
};
|
||||
}
|
||||
|
||||
public static AICategory ConvertClassIDToCategory(int id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
1 => AICategory.ELF,
|
||||
2 => AICategory.ROYAL,
|
||||
3 => AICategory.WITCH,
|
||||
4 => AICategory.DRAGON,
|
||||
5 => AICategory.NECROMANCE,
|
||||
6 => AICategory.VAMPIRE,
|
||||
7 => AICategory.BISHOP,
|
||||
8 => AICategory.NEMESIS,
|
||||
_ => AICategory.ALL,
|
||||
};
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard owner, List<int> playPtn, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
return _conditionExpr.CheckCondition(owner, playPtn, field, situation);
|
||||
}
|
||||
|
||||
public float EvalArg(AIVirtualCard owner, List<int> playPtn, AIVirtualField field, AISituationInfo situation = null)
|
||||
{
|
||||
return Argument.EvalArg(0, owner, playPtn, field, situation);
|
||||
}
|
||||
|
||||
public int EvalId(int index = 0)
|
||||
{
|
||||
return Argument.EvalID(index);
|
||||
}
|
||||
|
||||
public List<int> EvalIdList(int startindex = 0)
|
||||
{
|
||||
return Argument.EvalIDList(startindex);
|
||||
}
|
||||
|
||||
public string EvalText(int index = 0)
|
||||
{
|
||||
return Argument.EvalText(index);
|
||||
}
|
||||
}
|
||||
37
SVSim.BattleEngine/Engine/Wizard/AIPolicyDataAsset.cs
Normal file
37
SVSim.BattleEngine/Engine/Wizard/AIPolicyDataAsset.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPolicyDataAsset
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
public string Category { get; set; }
|
||||
|
||||
public int Priority { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public string Arg { get; set; }
|
||||
|
||||
public string Cond { get; set; }
|
||||
|
||||
public AIPolicyDataAsset()
|
||||
{
|
||||
ID = -1;
|
||||
Category = "";
|
||||
Priority = 0;
|
||||
Type = "";
|
||||
Arg = "";
|
||||
Cond = "";
|
||||
}
|
||||
|
||||
public AIPolicyDataAsset(string[] columns)
|
||||
{
|
||||
int num = 0;
|
||||
ID = AIScriptParser.ParseInt(columns[num++]);
|
||||
Category = columns[num++];
|
||||
Priority = AIScriptParser.ParseInt(columns[num++]);
|
||||
Type = columns[num++];
|
||||
Arg = columns[num++];
|
||||
Cond = columns[num++];
|
||||
}
|
||||
}
|
||||
26
SVSim.BattleEngine/Engine/Wizard/AIPolicyType.cs
Normal file
26
SVSim.BattleEngine/Engine/Wizard/AIPolicyType.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIPolicyType
|
||||
{
|
||||
None,
|
||||
EpValue,
|
||||
ModUnitRate,
|
||||
UnitBonus,
|
||||
PlayptnBonus,
|
||||
PlayBreak,
|
||||
BarrierBonus,
|
||||
AllyPlayBonus,
|
||||
AllyPlayBonusRate,
|
||||
DisableLethalCheck,
|
||||
DelayTurnEndTime,
|
||||
SetReferenceId,
|
||||
SetReferenceTribe,
|
||||
EmoOnTurnEnd,
|
||||
EmoOnTurnStart,
|
||||
EmoOnLeaderDamaged,
|
||||
PlayerEmoOnTurnEnd,
|
||||
PlayerEmoOnTurnStart,
|
||||
PlayerEmoOnLeaderDamaged,
|
||||
MoveFirstBonus,
|
||||
GameStartAttachTag
|
||||
}
|
||||
324
SVSim.BattleEngine/Engine/Wizard/AIPolishConvertedExpression.cs
Normal file
324
SVSim.BattleEngine/Engine/Wizard/AIPolishConvertedExpression.cs
Normal file
@@ -0,0 +1,324 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPolishConvertedExpression
|
||||
{
|
||||
private readonly AIScriptTokenFuncType[] EvalFuncList = new AIScriptTokenFuncType[22]
|
||||
{
|
||||
AIScriptTokenFuncType.EVAL_ALL_DAMAGE,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_DAMAGE,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_AND_RANDOM_MULTI_DAMAGE,
|
||||
AIScriptTokenFuncType.EVAL_ALL_DESTROY,
|
||||
AIScriptTokenFuncType.EVAL_ALL_BOUNCE,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_BOUNCE,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_BANISH,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_BANISH,
|
||||
AIScriptTokenFuncType.EVAL_ALL_BANISH,
|
||||
AIScriptTokenFuncType.EVAL_ALL_METAMORPHOSE,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_METAMORPHOSE,
|
||||
AIScriptTokenFuncType.EVAL_ALL_BUFF,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_BUFF,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_DESTROY,
|
||||
AIScriptTokenFuncType.EVAL_TARGETING_HEAL,
|
||||
AIScriptTokenFuncType.EVAL_ALL_HEAL,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_BOUNCE,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_DESTROY,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_METAMORPHOSE,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_MULTI_DAMAGE,
|
||||
AIScriptTokenFuncType.EVAL_RANDOM_MULTI_SELECT_DAMAGE,
|
||||
AIScriptTokenFuncType.EVAL_DIVIDED_DAMAGE
|
||||
};
|
||||
|
||||
public List<AIScriptTokenBase> TokenList { get; private set; }
|
||||
|
||||
public int Hash { get; private set; }
|
||||
|
||||
public bool IsMultiplyMarked { get; private set; }
|
||||
|
||||
public AIPolishConvertedExpression(string text, bool isMultiplyMarked = false)
|
||||
{
|
||||
IsMultiplyMarked = isMultiplyMarked;
|
||||
TokenList = CreateExpression(text);
|
||||
Hash = text.GetHashCode();
|
||||
}
|
||||
|
||||
public int EvalID()
|
||||
{
|
||||
if (TokenList == null || TokenList.Count != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!(TokenList[0] is AIScriptIDToken))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (TokenList[0] as AIScriptIDToken).ID;
|
||||
}
|
||||
|
||||
public bool IsID()
|
||||
{
|
||||
return TokenList[0] is AIScriptIDToken;
|
||||
}
|
||||
|
||||
public List<int> GetReferringIDLists()
|
||||
{
|
||||
List<int> list = null;
|
||||
for (int i = 0; i < TokenList.Count; i++)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = TokenList[i];
|
||||
if (aIScriptTokenBase is AIScriptIDToken)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = new List<int>();
|
||||
}
|
||||
list.Add(((AIScriptIDToken)aIScriptTokenBase).ID);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public string EvalText()
|
||||
{
|
||||
if (TokenList == null || TokenList.Count != 1)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (TokenList[0] is AIScriptTextToken aIScriptTextToken)
|
||||
{
|
||||
return aIScriptTextToken.Text;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public float EvalArg(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation = null)
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return GetFloatValue(tagOwner, situation, playPtn, field);
|
||||
}
|
||||
|
||||
public bool CheckCondition(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return GetFloatValue(tagOwner, situation, playPtn, field) > 0f;
|
||||
}
|
||||
|
||||
public bool IsZeroOrNone()
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TokenList.Count > 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AIScriptTokenBase aIScriptTokenBase = TokenList[0];
|
||||
if (aIScriptTokenBase is AIScriptArgumentToken { ArgumentType: AIScriptTokenArgType.NONE } || aIScriptTokenBase is AIScriptNumericToken { Value: 0f })
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsMathematicExpress()
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TokenList.Count > 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
AIScriptTokenBase aIScriptTokenBase = TokenList[0];
|
||||
if (!(aIScriptTokenBase is AIScriptNumericToken))
|
||||
{
|
||||
return aIScriptTokenBase is AIScriptVariableToken;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsCertainArgumentTypeExpress(AIScriptTokenArgType argType)
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0 || TokenList.Count > 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TokenList[0] is AIScriptArgumentToken aIScriptArgumentToken && aIScriptArgumentToken.ArgumentType == argType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private float GetFloatValue(AIVirtualCard tagOwner, AISituationInfo situation, List<int> playPtn, AIVirtualField field)
|
||||
{
|
||||
if (TokenList == null || TokenList.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return AIScriptExpressionCalculator.CalculateExpression(TokenList, playPtn, field, tagOwner, situation);
|
||||
}
|
||||
|
||||
private List<AIScriptTokenBase> CreateExpression(string expression)
|
||||
{
|
||||
if (expression == "")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIScriptTokenBase> list = CreateScriptTokenList(expression);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (list.Count == 1 && list[0] is AIScriptNumericToken)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return _ConvertExprToIPolish(list);
|
||||
}
|
||||
|
||||
private List<AIScriptTokenBase> CreateScriptTokenList(string text)
|
||||
{
|
||||
List<AIScriptTokenBase> list = new List<AIScriptTokenBase>();
|
||||
string[] array = text.Split(' ');
|
||||
bool flag = false;
|
||||
string[] array2 = array;
|
||||
foreach (string text2 in array2)
|
||||
{
|
||||
if (!(text2 == ""))
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = AIScriptParser.ConvertWordToToken(text2);
|
||||
if (aIScriptTokenBase != null)
|
||||
{
|
||||
list.Add(aIScriptTokenBase);
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<AIScriptTokenBase> _ConvertExprToIPolish(List<AIScriptTokenBase> expression)
|
||||
{
|
||||
List<AIScriptTokenBase> list = new List<AIScriptTokenBase>();
|
||||
Stack<AIScriptTokenBase> stack = new Stack<AIScriptTokenBase>();
|
||||
AIScriptFunctionToken aIScriptFunctionToken = null;
|
||||
for (int i = 0; i < expression.Count; i++)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = expression[i];
|
||||
if (aIScriptTokenBase is AIScriptNumericToken || aIScriptTokenBase is AIScriptArgumentToken || aIScriptTokenBase is AIScriptVariableToken || aIScriptTokenBase is AIScriptIDToken)
|
||||
{
|
||||
list.Add(aIScriptTokenBase);
|
||||
continue;
|
||||
}
|
||||
if (aIScriptTokenBase is AIScriptOperatorSymbolToken)
|
||||
{
|
||||
if (aIScriptTokenBase.Type == AIScriptTokenType.COMMA)
|
||||
{
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase2 = stack.Pop();
|
||||
if (aIScriptTokenBase2 is AIScriptOperatorSymbolToken && aIScriptTokenBase2.Type == AIScriptTokenType.LEFT_BLACKET)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIScriptTokenBase2 == aIScriptFunctionToken)
|
||||
{
|
||||
aIScriptFunctionToken = stack.LastOrDefault((AIScriptTokenBase t) => t is AIScriptFunctionToken) as AIScriptFunctionToken;
|
||||
}
|
||||
list.Add(aIScriptTokenBase2);
|
||||
}
|
||||
aIScriptFunctionToken.ArgCount++;
|
||||
stack.Push(new AIScriptOperatorSymbolToken(AIScriptTokenType.LEFT_BLACKET));
|
||||
continue;
|
||||
}
|
||||
if (aIScriptTokenBase.Type == AIScriptTokenType.LEFT_BLACKET)
|
||||
{
|
||||
stack.Push(aIScriptTokenBase);
|
||||
continue;
|
||||
}
|
||||
if (aIScriptTokenBase.Type == AIScriptTokenType.RIGHT_BLACKET)
|
||||
{
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase3 = stack.Pop();
|
||||
if (aIScriptTokenBase3 is AIScriptOperatorSymbolToken && aIScriptTokenBase3.Type == AIScriptTokenType.LEFT_BLACKET)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIScriptTokenBase3 == aIScriptFunctionToken)
|
||||
{
|
||||
aIScriptFunctionToken = stack.LastOrDefault((AIScriptTokenBase t) => t is AIScriptFunctionToken) as AIScriptFunctionToken;
|
||||
}
|
||||
list.Add(aIScriptTokenBase3);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (aIScriptTokenBase is AIScriptFunctionToken)
|
||||
{
|
||||
aIScriptFunctionToken = aIScriptTokenBase as AIScriptFunctionToken;
|
||||
aIScriptFunctionToken.ArgCount = 1;
|
||||
}
|
||||
if (stack.Count <= 0)
|
||||
{
|
||||
stack.Push(aIScriptTokenBase);
|
||||
continue;
|
||||
}
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase4 = stack.Peek();
|
||||
if (aIScriptTokenBase4.Type == AIScriptTokenType.LEFT_BLACKET || aIScriptTokenBase4.Priority < aIScriptTokenBase.Priority)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIScriptTokenBase4 == aIScriptFunctionToken)
|
||||
{
|
||||
aIScriptFunctionToken = stack.LastOrDefault((AIScriptTokenBase t) => t is AIScriptFunctionToken) as AIScriptFunctionToken;
|
||||
}
|
||||
list.Add(stack.Pop());
|
||||
}
|
||||
stack.Push(aIScriptTokenBase);
|
||||
}
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
list.Add(stack.Pop());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public AIScriptCalculationToken CreateCalculationToken()
|
||||
{
|
||||
return new AIScriptCalculationToken(TokenList);
|
||||
}
|
||||
|
||||
public bool IsHoldingEVAL()
|
||||
{
|
||||
if (TokenList == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < TokenList.Count; i++)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = TokenList[i];
|
||||
if (aIScriptTokenBase is AIScriptFunctionToken && EvalFuncList.Contains(((AIScriptFunctionToken)aIScriptTokenBase).FuncType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
208
SVSim.BattleEngine/Engine/Wizard/AIRealActionInformation.cs
Normal file
208
SVSim.BattleEngine/Engine/Wizard/AIRealActionInformation.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIRealActionInformation
|
||||
{
|
||||
public BattleCardBase OriginalActor;
|
||||
|
||||
public BattleCardBase Actor;
|
||||
|
||||
public List<BattleCardBase> SelectedTargetCardSet;
|
||||
|
||||
public List<BattleCardRealTargetInformation> RealTargetInformationList;
|
||||
|
||||
public AIOperationType OperationType;
|
||||
|
||||
private AIVirtualField.AIVirtualFieldSearchCardOption _searchTargetOption;
|
||||
|
||||
public AIRealActionInformation(AIOperationType type, BattleCardBase actCard, BattleCardBase originalCard, IEnumerable<BattleCardBase> targetCards)
|
||||
{
|
||||
OperationType = type;
|
||||
OriginalActor = originalCard;
|
||||
if (actCard == null)
|
||||
{
|
||||
Actor = OriginalActor;
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor = actCard;
|
||||
}
|
||||
SelectedTargetCardSet = targetCards?.ToList();
|
||||
_searchTargetOption = new AIVirtualField.AIVirtualFieldSearchCardOption
|
||||
{
|
||||
IsSearchFromDeck = false,
|
||||
IsOutputCannotFindError = false
|
||||
};
|
||||
RealTargetInformationList = null;
|
||||
}
|
||||
|
||||
public AISituationInfo CreateSituationInfo(AIVirtualField field)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.SearchVirtualCard(OriginalActor);
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIRealActionInformation.CreateSituationInfo() error!! virtualActor is not found");
|
||||
return null;
|
||||
}
|
||||
if (!aIVirtualCard.IsAlly && aIVirtualCard is EnemyHandVirtualCard)
|
||||
{
|
||||
aIVirtualCard = new AIVirtualCard(aIVirtualCard, field);
|
||||
}
|
||||
AIVirtualCard aIVirtualCard2 = aIVirtualCard;
|
||||
if (OriginalActor != Actor)
|
||||
{
|
||||
aIVirtualCard2 = new AIVirtualCard(Actor, field);
|
||||
aIVirtualCard2.InitializeTags(field.ParamQuery, null, null);
|
||||
}
|
||||
AISituationInfo aISituationInfo;
|
||||
switch (OperationType)
|
||||
{
|
||||
case AIOperationType.TURNEND:
|
||||
aISituationInfo = new AIVirtualTurnEndInfo(aIVirtualCard);
|
||||
break;
|
||||
case AIOperationType.ATTACK:
|
||||
aISituationInfo = GetTargetRegisteredAttackSituation(aIVirtualCard, field);
|
||||
break;
|
||||
case AIOperationType.EVOLVE:
|
||||
case AIOperationType.PLAY:
|
||||
case AIOperationType.FUSION:
|
||||
aISituationInfo = GetTargetRegisteredTargetSelectSituation(aIVirtualCard2, aIVirtualCard, field);
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError("AIRealActionInformation.CreateSituationInfo() error!! OperationType " + OperationType.ToString() + " is illegal");
|
||||
return null;
|
||||
}
|
||||
if (aISituationInfo != null && RealTargetInformationList != null)
|
||||
{
|
||||
aISituationInfo.RegisterRealTargetInfo(RealTargetInformationList);
|
||||
}
|
||||
return aISituationInfo;
|
||||
}
|
||||
|
||||
private AIVirtualAttackInfo GetTargetRegisteredAttackSituation(AIVirtualCard attacker, AIVirtualField field)
|
||||
{
|
||||
if (SelectedTargetCardSet == null || SelectedTargetCardSet.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIRealActionInformation.GetTargetRegisteredAttackSituation error!! Attack situation cannot find target!!!!!");
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard target = field.SearchVirtualCard(SelectedTargetCardSet.First());
|
||||
return new AIVirtualAttackInfo(attacker, target);
|
||||
}
|
||||
|
||||
private AIVirtualTargetSelectAction GetTargetRegisteredTargetSelectSituation(AIVirtualCard playActor, AIVirtualCard originalCard, AIVirtualField field)
|
||||
{
|
||||
AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(playActor, originalCard, OperationType, (AISelectedTargetInfoSet)null);
|
||||
if (SelectedTargetCardSet == null || SelectedTargetCardSet.Count <= 0)
|
||||
{
|
||||
return aIVirtualTargetSelectAction;
|
||||
}
|
||||
AIVirtualCard owner = playActor;
|
||||
if (!playActor.IsSameCard(originalCard) && aIVirtualTargetSelectAction.IsChoiceAndChangeActor(field))
|
||||
{
|
||||
owner = originalCard;
|
||||
}
|
||||
List<AIVirtualTargetSelectInfo> list = owner.CreateAIVirtualSelectInfo(field, aIVirtualTargetSelectAction);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIRealActionInformation.CreateSituationInfo error!! Target selection is required while TargetCardSet is empty!!!!! Card ID == " + originalCard.BaseId);
|
||||
return aIVirtualTargetSelectAction;
|
||||
}
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualTargetSelectInfo aIVirtualTargetSelectInfo = list[i];
|
||||
int num3;
|
||||
if (aIVirtualTargetSelectAction.ActionType == AIOperationType.FUSION)
|
||||
{
|
||||
num3 = SelectedTargetCardSet.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
AIPlayTag selectRule = aIVirtualTargetSelectInfo.SelectRule;
|
||||
num3 = ((selectRule != null && selectRule.Type == AIPlayTagType.ChoiceBrave) ? 1 : Math.Min(aIVirtualTargetSelectInfo.Candidates.Count, aIVirtualTargetSelectInfo.Count));
|
||||
}
|
||||
List<AIVirtualCard> list2 = new List<AIVirtualCard>();
|
||||
if (SelectedTargetCardSet.Count - num < num3)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIRealActionInformation.CreateSituationInfo error!! Targets are not enough!!!!!");
|
||||
break;
|
||||
}
|
||||
for (int j = 0; j < num3; j++)
|
||||
{
|
||||
BattleCardBase battleCardBase = SelectedTargetCardSet[num];
|
||||
AIVirtualCard aIVirtualCard = field.SearchVirtualCard(battleCardBase, _searchTargetOption);
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
aIVirtualCard = new AIVirtualCard(battleCardBase, field);
|
||||
aIVirtualCard.InitializeTags(field.ParamQuery, null, null);
|
||||
}
|
||||
list2.Add(aIVirtualCard);
|
||||
num++;
|
||||
}
|
||||
if (aIVirtualTargetSelectInfo.Type == TargetSelectType.Choice)
|
||||
{
|
||||
aIVirtualTargetSelectAction.SetChoicedMultipleTargetInInfo(list2);
|
||||
continue;
|
||||
}
|
||||
AIScriptTokenArgType whichTarget = ((num2 != 0) ? AIScriptTokenArgType.SECOND_TARGET_SELECT : AIScriptTokenArgType.TARGET_SELECT);
|
||||
aIVirtualTargetSelectAction.SetMultipleTargetsInInfo(list2, aIVirtualTargetSelectInfo.Type, aIVirtualTargetSelectInfo.RemovalType, whichTarget);
|
||||
num2++;
|
||||
}
|
||||
return aIVirtualTargetSelectAction;
|
||||
}
|
||||
|
||||
public void CreateRandomTargetInformation(BattleCardBase actor, Func<SkillBase, bool> skillCheckFunc, bool forceCheckEvolveSkills = false)
|
||||
{
|
||||
BattleCardRealTargetInformation information = GetRealRandomTargetInformation(actor);
|
||||
SkillCollectionBase skillCollectionBase = (forceCheckEvolveSkills ? actor.EvolutionSkills : actor.Skills);
|
||||
int num = skillCollectionBase.Count();
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
SkillBase skillBase = skillCollectionBase.Get(i);
|
||||
if (skillCheckFunc(skillBase))
|
||||
{
|
||||
skillBase.OnSkillEnd += OnSkillEndRegistTargets;
|
||||
}
|
||||
}
|
||||
VfxBase OnSkillEndRegistTargets(SkillBase currentSkill, List<BattleCardBase> skillTargets, SkillConditionCheckerOption option, SkillProcessor skillProcessor)
|
||||
{
|
||||
if (skillTargets != null && skillTargets.Count > 0)
|
||||
{
|
||||
information.AddTargetList(skillTargets, currentSkill.ApplyingTargetFilter);
|
||||
}
|
||||
currentSkill.OnSkillEnd -= OnSkillEndRegistTargets;
|
||||
return NullVfx.GetInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private BattleCardRealTargetInformation GetRealRandomTargetInformation(BattleCardBase skillOwner)
|
||||
{
|
||||
if (RealTargetInformationList == null)
|
||||
{
|
||||
RealTargetInformationList = new List<BattleCardRealTargetInformation>();
|
||||
}
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation = null;
|
||||
for (int i = 0; i < RealTargetInformationList.Count; i++)
|
||||
{
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation2 = RealTargetInformationList[i];
|
||||
BattleCardBase skillOwner2 = battleCardRealTargetInformation2.SkillOwner;
|
||||
if (skillOwner.IsPlayer == skillOwner2.IsPlayer && skillOwner.Index == skillOwner2.Index && skillOwner.BaseParameter.BaseCardId == skillOwner2.BaseParameter.BaseCardId)
|
||||
{
|
||||
battleCardRealTargetInformation = battleCardRealTargetInformation2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (battleCardRealTargetInformation == null)
|
||||
{
|
||||
battleCardRealTargetInformation = new BattleCardRealTargetInformation(skillOwner);
|
||||
RealTargetInformationList.Add(battleCardRealTargetInformation);
|
||||
}
|
||||
return battleCardRealTargetInformation;
|
||||
}
|
||||
}
|
||||
11
SVSim.BattleEngine/Engine/Wizard/AIRemovalType.cs
Normal file
11
SVSim.BattleEngine/Engine/Wizard/AIRemovalType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIRemovalType
|
||||
{
|
||||
None,
|
||||
Damage,
|
||||
Destroy,
|
||||
Banish,
|
||||
Bounce,
|
||||
Metamorphose
|
||||
}
|
||||
55
SVSim.BattleEngine/Engine/Wizard/AIRemovedTagCollection.cs
Normal file
55
SVSim.BattleEngine/Engine/Wizard/AIRemovedTagCollection.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIRemovedTagCollection
|
||||
{
|
||||
public List<AIRemovedTagInformation> AllList;
|
||||
|
||||
public AIRemovedTagCollection()
|
||||
{
|
||||
AllList = null;
|
||||
}
|
||||
|
||||
public AIRemovedTagCollection Clone()
|
||||
{
|
||||
AIRemovedTagCollection aIRemovedTagCollection = new AIRemovedTagCollection();
|
||||
if (AllList != null)
|
||||
{
|
||||
aIRemovedTagCollection.AllList = new List<AIRemovedTagInformation>(AllList);
|
||||
}
|
||||
return aIRemovedTagCollection;
|
||||
}
|
||||
|
||||
public void Add(AIRemovedTagInformation info)
|
||||
{
|
||||
AllList = AIParamQuery.AddElementToList(info, AllList);
|
||||
}
|
||||
|
||||
public void RemoveTagFromCard(AIVirtualCard card)
|
||||
{
|
||||
if (AllList == null || AllList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AIVirtualField selfField = card.SelfField;
|
||||
for (int i = 0; i < AllList.Count; i++)
|
||||
{
|
||||
AIRemovedTagInformation aIRemovedTagInformation = AllList[i];
|
||||
if (aIRemovedTagInformation.IsAlly == card.IsAlly && aIRemovedTagInformation.CardIndex == card.CardIndex)
|
||||
{
|
||||
card.TagCollectionContainer.RemoveOneTagWithUpdatingFieldCardList(card, aIRemovedTagInformation.Tag, selfField);
|
||||
card.TagCollectionContainer.RemovedTagCollection.Add(aIRemovedTagInformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
if (AllList != null)
|
||||
{
|
||||
AllList.Clear();
|
||||
AllList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
SVSim.BattleEngine/Engine/Wizard/AIRemovedTagInformation.cs
Normal file
17
SVSim.BattleEngine/Engine/Wizard/AIRemovedTagInformation.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIRemovedTagInformation
|
||||
{
|
||||
public AIPlayTag Tag;
|
||||
|
||||
public int CardIndex { get; private set; }
|
||||
|
||||
public bool IsAlly { get; private set; }
|
||||
|
||||
public AIRemovedTagInformation(AIVirtualCard remover, AIPlayTag tag)
|
||||
{
|
||||
CardIndex = remover.CardIndex;
|
||||
IsAlly = remover.IsAlly;
|
||||
Tag = tag;
|
||||
}
|
||||
}
|
||||
269
SVSim.BattleEngine/Engine/Wizard/AIScriptArgumentExpressions.cs
Normal file
269
SVSim.BattleEngine/Engine/Wizard/AIScriptArgumentExpressions.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIScriptArgumentExpressions
|
||||
{
|
||||
protected List<AIPolishConvertedExpression> _exprList;
|
||||
|
||||
private List<int> _referringIds;
|
||||
|
||||
protected AIScriptTokenArgType[] LegalSelectTypes { get; set; }
|
||||
|
||||
public AIScriptArgumentExpressions(string text)
|
||||
{
|
||||
CreateLegalSelectTypes();
|
||||
if (!(text == ""))
|
||||
{
|
||||
InitExpressions(text);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void InitExpressions(string text)
|
||||
{
|
||||
InitExprList(text);
|
||||
}
|
||||
|
||||
protected void InitExprList(string text)
|
||||
{
|
||||
string[] array = text.Split(';');
|
||||
_exprList = new List<AIPolishConvertedExpression>();
|
||||
foreach (string expression in array)
|
||||
{
|
||||
AIPolishConvertedExpression aIPolishConvertedExpression = CreateArgumentExpression(expression);
|
||||
_exprList.Add(aIPolishConvertedExpression);
|
||||
List<int> referringIDLists = aIPolishConvertedExpression.GetReferringIDLists();
|
||||
if (referringIDLists != null)
|
||||
{
|
||||
if (_referringIds == null)
|
||||
{
|
||||
_referringIds = new List<int>();
|
||||
}
|
||||
_referringIds.AddRange(referringIDLists);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AIPolishConvertedExpression CreateArgumentExpression(string expression)
|
||||
{
|
||||
string text = expression.TrimStart();
|
||||
if (text[0] == '*')
|
||||
{
|
||||
return new AIPolishConvertedExpression(text.Substring(1), isMultiplyMarked: true);
|
||||
}
|
||||
return new AIPolishConvertedExpression(expression);
|
||||
}
|
||||
|
||||
public bool IsArgID(int index)
|
||||
{
|
||||
return _exprList[index].IsID();
|
||||
}
|
||||
|
||||
public int EvalID(int index)
|
||||
{
|
||||
if (_exprList == null || index >= _exprList.Count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return _exprList[index].EvalID();
|
||||
}
|
||||
|
||||
public List<int> EvalIDList(int startIndex)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
if (_exprList != null && startIndex < _exprList.Count)
|
||||
{
|
||||
for (int i = startIndex; i < _exprList.Count; i++)
|
||||
{
|
||||
list.Add(_exprList[i].EvalID());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public string EvalText(int index)
|
||||
{
|
||||
if (_exprList == null || index >= _exprList.Count)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return _exprList[index].EvalText();
|
||||
}
|
||||
|
||||
public virtual List<int> GetReferringOtherInplayIds()
|
||||
{
|
||||
return _referringIds;
|
||||
}
|
||||
|
||||
public float EvalArg(int index, AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
if (_exprList == null || index >= _exprList.Count)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return _exprList[index].EvalArg(tagOwner, playPtn, field, situation);
|
||||
}
|
||||
|
||||
public bool IsHoldingEVAL()
|
||||
{
|
||||
if (_exprList != null)
|
||||
{
|
||||
return _exprList.Any((AIPolishConvertedExpression expr) => expr.IsHoldingEVAL());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected string[] SplitTextToWords(string text)
|
||||
{
|
||||
string pattern = "\\s\\;\\s(?=\\{)";
|
||||
return Regex.Split(text, pattern);
|
||||
}
|
||||
|
||||
protected List<AIScriptTokenBase> GetFilters(List<AIPolishConvertedExpression> exprs)
|
||||
{
|
||||
List<AIScriptTokenBase> list = new List<AIScriptTokenBase>();
|
||||
for (int i = 0; i < exprs.Count; i++)
|
||||
{
|
||||
AIPolishConvertedExpression aIPolishConvertedExpression = exprs[i];
|
||||
if (aIPolishConvertedExpression.TokenList == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (aIPolishConvertedExpression.TokenList.Count > 1)
|
||||
{
|
||||
list.Add(aIPolishConvertedExpression.CreateCalculationToken());
|
||||
continue;
|
||||
}
|
||||
AIScriptTokenBase aIScriptTokenBase = aIPolishConvertedExpression.TokenList[0];
|
||||
if (!(aIScriptTokenBase is AIScriptArgumentToken { ArgumentType: AIScriptTokenArgType.FILTER_END }))
|
||||
{
|
||||
list.Add(aIScriptTokenBase);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public virtual void Execute(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation = null)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ExecuteWhenRemove(AIVirtualCard tagOwner, AIVirtualField field, AIPlayTag removingTag)
|
||||
{
|
||||
}
|
||||
|
||||
protected AIScriptTokenArgType GetFirstTokenArgType(AIPolishConvertedExpression arg)
|
||||
{
|
||||
AIScriptTokenArgType result = AIScriptTokenArgType.NONE;
|
||||
if (arg.TokenList != null && arg.TokenList.Count > 0)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = arg.TokenList[0];
|
||||
if (aIScriptTokenBase is AIScriptArgumentToken)
|
||||
{
|
||||
result = ((AIScriptArgumentToken)aIScriptTokenBase).ArgumentType;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual AITokenIdCollection GetAllRegisterTokenPoolInfo(AIVirtualCard owner)
|
||||
{
|
||||
if (_exprList == null || _exprList.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<int> list = null;
|
||||
for (int i = 0; i < _exprList.Count; i++)
|
||||
{
|
||||
List<AIScriptTokenBase> tokenList = _exprList[i].TokenList;
|
||||
if (tokenList != null && tokenList.Count > 0 && tokenList.Count == 1 && tokenList[0] is AIScriptIDToken aIScriptIDToken)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIScriptIDToken.ID, list);
|
||||
}
|
||||
}
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return CreateRegisterTokenPoolInfo(owner, list);
|
||||
}
|
||||
|
||||
protected virtual AITokenIdCollection CreateRegisterTokenPoolInfo(AIVirtualCard owner, List<int> idList)
|
||||
{
|
||||
return AISummonTokenUtility.CreateTokenIdCollectionFromIdList(owner, AIScriptTokenArgType.ALLY, idList, AITokenType.Default);
|
||||
}
|
||||
|
||||
protected bool IsFirstFiltersEnd(AIPolishConvertedExpression arg, AIScriptTokenArgType[] InitFilters, out AIScriptTokenArgType dstType)
|
||||
{
|
||||
dstType = AIScriptTokenArgType.NONE;
|
||||
if (arg.TokenList != null && arg.TokenList.Count > 0)
|
||||
{
|
||||
AIScriptTokenBase aIScriptTokenBase = arg.TokenList[0];
|
||||
if (aIScriptTokenBase is AIScriptArgumentToken)
|
||||
{
|
||||
dstType = ((AIScriptArgumentToken)aIScriptTokenBase).ArgumentType;
|
||||
if (InitFilters.Contains(dstType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected bool IsTimingTokenArgType(AIPolishConvertedExpression arg, out AIScriptTokenArgType dstTokenArgType)
|
||||
{
|
||||
dstTokenArgType = GetFirstTokenArgType(arg);
|
||||
switch (dstTokenArgType)
|
||||
{
|
||||
case AIScriptTokenArgType.WHEN_PLAY:
|
||||
case AIScriptTokenArgType.WHEN_DESTROY:
|
||||
case AIScriptTokenArgType.WHEN_ATTACK:
|
||||
case AIScriptTokenArgType.WHEN_CLASH:
|
||||
case AIScriptTokenArgType.WHEN_DAMAGED:
|
||||
case AIScriptTokenArgType.WHEN_EVO:
|
||||
case AIScriptTokenArgType.WHEN_TURNEND:
|
||||
case AIScriptTokenArgType.WHEN_ALLY_TURNEND:
|
||||
case AIScriptTokenArgType.WHEN_OPPONENT_TURNEND:
|
||||
case AIScriptTokenArgType.WHEN_ALLY_TURNSTART:
|
||||
case AIScriptTokenArgType.WHEN_OPPONENT_TURNSTART:
|
||||
case AIScriptTokenArgType.WHEN_FUSION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsSideTokenArgType(AIPolishConvertedExpression arg, out AIScriptTokenArgType dstTokenARgType)
|
||||
{
|
||||
dstTokenARgType = GetFirstTokenArgType(arg);
|
||||
AIScriptTokenArgType aIScriptTokenArgType = dstTokenARgType;
|
||||
if ((uint)(aIScriptTokenArgType - 84) <= 2u)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected bool IsLegalSelectType(AIPolishConvertedExpression arg, out AIScriptTokenArgType selectType)
|
||||
{
|
||||
selectType = AIScriptTokenArgType.NONE;
|
||||
if (arg.TokenList != null && arg.TokenList.Count > 0 && arg.TokenList[0] is AIScriptArgumentToken { ArgumentType: var argumentType } && Array.IndexOf(LegalSelectTypes, argumentType) >= 0)
|
||||
{
|
||||
selectType = argumentType;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void CreateLegalSelectTypes()
|
||||
{
|
||||
LegalSelectTypes = new AIScriptTokenArgType[2]
|
||||
{
|
||||
AIScriptTokenArgType.ALL_SELECT,
|
||||
AIScriptTokenArgType.RANDOM_SELECT
|
||||
};
|
||||
}
|
||||
}
|
||||
121
SVSim.BattleEngine/Engine/Wizard/AIScriptCalculationToken.cs
Normal file
121
SVSim.BattleEngine/Engine/Wizard/AIScriptCalculationToken.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIScriptCalculationToken : AIScriptTokenBase
|
||||
{
|
||||
public Func<AIVirtualCard, AIVirtualCard, AIVirtualField, List<int>, AISituationInfo, float> Expression;
|
||||
|
||||
public AIScriptCalculationToken(List<AIScriptTokenBase> tokens)
|
||||
: base(AIScriptTokenType.FUNC, 0f)
|
||||
{
|
||||
CreateExpression(tokens);
|
||||
}
|
||||
|
||||
public AIScriptCalculationToken(Func<AIVirtualCard, AIVirtualCard, AIVirtualField, List<int>, AISituationInfo, float> expression)
|
||||
: base(AIScriptTokenType.FUNC, 0f)
|
||||
{
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
private void CreateExpression(List<AIScriptTokenBase> tokens)
|
||||
{
|
||||
Stack<AIScriptTokenBase> stack = new Stack<AIScriptTokenBase>();
|
||||
for (int i = 0; i < tokens.Count; i++)
|
||||
{
|
||||
AIScriptTokenBase token = tokens[i];
|
||||
if (token is AIScriptNumericToken || token is AIScriptIDToken)
|
||||
{
|
||||
stack.Push(token);
|
||||
continue;
|
||||
}
|
||||
AIScriptArgumentToken argument = token as AIScriptArgumentToken;
|
||||
if (argument != null)
|
||||
{
|
||||
AIScriptCalculationToken item = new AIScriptCalculationToken(delegate(AIVirtualCard owner, AIVirtualCard candidate, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
AIFilteringUtility.FilteringParameter filter = new AIFilteringUtility.FilteringParameter
|
||||
{
|
||||
Type = argument.ArgumentType,
|
||||
IsNot = argument.IsNot,
|
||||
IsSkipNextToken = false,
|
||||
FilteringThreshold = -1
|
||||
};
|
||||
if (argument is AIScriptTextToken aIScriptTextToken)
|
||||
{
|
||||
filter.SubParameter = aIScriptTextToken.Text;
|
||||
}
|
||||
situation.SetCurrentCheckCard(candidate);
|
||||
float result = (AIFilteringUtility.CheckFilterPassOrNot(candidate, filter, owner, playPtn, situation) ? 1f : 0f);
|
||||
situation.ResetCurrentCheckCard();
|
||||
return result;
|
||||
});
|
||||
stack.Push(item);
|
||||
}
|
||||
if (token is AIScriptVariableToken)
|
||||
{
|
||||
AIScriptCalculationToken item2 = new AIScriptCalculationToken(delegate(AIVirtualCard owner, AIVirtualCard candidate, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
situation.SetCurrentCheckCard(candidate);
|
||||
AIScriptTokenBase aIScriptTokenBase = AIScriptExpressionCalculator.CalculateVariableToken(token, playPtn, field, owner, situation);
|
||||
situation.ResetCurrentCheckCard();
|
||||
return aIScriptTokenBase.Value;
|
||||
});
|
||||
stack.Push(item2);
|
||||
}
|
||||
AIScriptFunctionToken funcToken = token as AIScriptFunctionToken;
|
||||
if (funcToken != null)
|
||||
{
|
||||
int argCount = ((AIScriptFunctionToken)token).ArgCount;
|
||||
List<AIScriptTokenBase> argList = new List<AIScriptTokenBase>();
|
||||
for (int num = 0; num < argCount; num++)
|
||||
{
|
||||
AIScriptTokenBase item3 = stack.Pop();
|
||||
argList.Add(item3);
|
||||
}
|
||||
AIScriptCalculationToken item4 = new AIScriptCalculationToken(delegate(AIVirtualCard owner, AIVirtualCard candidate, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
situation.SetCurrentCheckCard(candidate);
|
||||
AIScriptTokenBase aIScriptTokenBase = AIScriptExpressionCalculator.CalculateFunctionToken(argList, funcToken, field, playPtn, owner, situation);
|
||||
situation.ResetCurrentCheckCard();
|
||||
return aIScriptTokenBase.Value;
|
||||
});
|
||||
stack.Push(item4);
|
||||
}
|
||||
if (token is AIScriptOperatorSymbolToken)
|
||||
{
|
||||
AIScriptTokenBase right = stack.Pop();
|
||||
AIScriptTokenBase left = stack.Pop();
|
||||
AIScriptCalculationToken item5 = new AIScriptCalculationToken(delegate(AIVirtualCard owner, AIVirtualCard candidate, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float tokenValue = GetTokenValue(left, owner, candidate, field, playPtn, situation);
|
||||
float tokenValue2 = GetTokenValue(right, owner, candidate, field, playPtn, situation);
|
||||
return AIScriptExpressionCalculator.CalculateByOperatorSymbol(token.Type, tokenValue, tokenValue2);
|
||||
});
|
||||
stack.Push(item5);
|
||||
}
|
||||
}
|
||||
if (stack.Count <= 1 && stack.Count > 0 && stack.Pop() is AIScriptCalculationToken aIScriptCalculationToken)
|
||||
{
|
||||
Expression = aIScriptCalculationToken.Expression;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetTokenValue(AIScriptTokenBase token, AIVirtualCard owner, AIVirtualCard candidate, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (token is AIScriptCalculationToken aIScriptCalculationToken)
|
||||
{
|
||||
return aIScriptCalculationToken.Expression(owner, candidate, field, playPtn, situation);
|
||||
}
|
||||
if (token is AIScriptIDToken aIScriptIDToken)
|
||||
{
|
||||
if (!((aIScriptIDToken.ID == candidate.BaseId) ^ aIScriptIDToken.IsNot))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return 1f;
|
||||
}
|
||||
return token.Value;
|
||||
}
|
||||
}
|
||||
198
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenArgType.cs
Normal file
198
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenArgType.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIScriptTokenArgType
|
||||
{
|
||||
NONE = 0,
|
||||
LEGION = 1,
|
||||
LORD = 2,
|
||||
WHITE_RITUAL = 3,
|
||||
ARTIFACT = 4,
|
||||
MANARIA = 5,
|
||||
MACHINE = 6,
|
||||
FOOD = 7,
|
||||
LEVIN = 8,
|
||||
NATURE = 9,
|
||||
LOOT = 10,
|
||||
BANQUET = 11,
|
||||
HERO = 12,
|
||||
ARMED = 13,
|
||||
HELLBOUND = 14,
|
||||
SCHOOL = 15,
|
||||
CHESS = 16,
|
||||
ANY_TRIBE = 17,
|
||||
ALL = 18,
|
||||
CLASS = 19,
|
||||
SPELL = 20,
|
||||
SPELL_CARD_TYPE = 21,
|
||||
ALL_SPELLBOOST = 22,
|
||||
FIELD = 23,
|
||||
CHANT_FIELD = 24,
|
||||
ALLY_CLASS = 25,
|
||||
ENEMY_CLASS = 26,
|
||||
ACCELERATE = 27,
|
||||
CRYSTALIZE = 28,
|
||||
LASTWORD = 29,
|
||||
KILLER = 30,
|
||||
SNEAK = 31,
|
||||
MEDUSA = 32,
|
||||
QUICK = 33,
|
||||
RUSH = 34,
|
||||
DRAIN = 35,
|
||||
GUARD = 36,
|
||||
NOT_BE_ATTACKED = 37,
|
||||
UNION_BURST = 38,
|
||||
CRYSTALIZE_HOLDER = 39,
|
||||
DESTRUCTIBLE = 40,
|
||||
UNTOUCHABLE = 41,
|
||||
FORCE_TARGETING = 42,
|
||||
UNBANISHABLE = 43,
|
||||
NO_SKILL = 44,
|
||||
IGNORE_GUARD = 45,
|
||||
DAMAGE_CLIP = 46,
|
||||
DAMAGE_CUT = 47,
|
||||
ALL_DAMAGE = 48,
|
||||
ATTACK_DAMAGE = 49,
|
||||
SPELL_DAMAGE = 50,
|
||||
SKILL_DAMAGE = 51,
|
||||
ELF = 52,
|
||||
ROYAL = 53,
|
||||
WITCH = 54,
|
||||
DRAGON = 55,
|
||||
NECROMANCER = 56,
|
||||
VAMPIRE = 57,
|
||||
BISHOP = 58,
|
||||
NEMESIS = 59,
|
||||
WHEN_PLAY = 60,
|
||||
WHEN_DESTROY = 61,
|
||||
WHEN_ATTACK = 62,
|
||||
WHEN_CLASH = 63,
|
||||
WHEN_DAMAGED = 64,
|
||||
WHEN_EVO = 65,
|
||||
WHEN_TURNEND = 66,
|
||||
WHEN_SUMMON = 67,
|
||||
WHEN_HEAL = 68,
|
||||
WHEN_LEAVE = 69,
|
||||
WHEN_ALLY_TURNEND = 70,
|
||||
WHEN_OPPONENT_TURNEND = 71,
|
||||
WHEN_ALLY_TURNSTART = 72,
|
||||
WHEN_OPPONENT_TURNSTART = 73,
|
||||
WHEN_NEXT_TURNEND = 74,
|
||||
WHEN_FUSION = 75,
|
||||
FIRST_TURN = 76,
|
||||
EVOLVED = 77,
|
||||
ATTACKABLE = 78,
|
||||
CANT_ATTACK = 79,
|
||||
PREVIOUS_TURN_ATTACKED = 80,
|
||||
ATTACKED = 81,
|
||||
CONSUME_EP_ZERO = 82,
|
||||
AI_FILTER_INITIAL_START = 83,
|
||||
ALLY = 84,
|
||||
OPPONENT = 85,
|
||||
BOTH = 86,
|
||||
SELF = 87,
|
||||
SUMMON_FOLLOWER = 88,
|
||||
LATEST_SUMMON_CARD = 89,
|
||||
LATEST_DRAW_CARD = 90,
|
||||
ROMELIA_TARGET = 91,
|
||||
SUMMON_AMULET = 92,
|
||||
CLASH_TARGET = 93,
|
||||
ATTACKER = 94,
|
||||
EVOLVER = 95,
|
||||
PLAYED_CARD = 96,
|
||||
CHOICED_TARGET = 97,
|
||||
SELECTED_TARGET = 98,
|
||||
SECOND_SELECTED_TARGET = 99,
|
||||
SELECTED_TARGET_SIDE = 100,
|
||||
TRIGGER = 101,
|
||||
REAL_SKILL_TARGET = 102,
|
||||
FILTER_END = 103,
|
||||
BANISHED_TARGET = 104,
|
||||
GETOFF_CARD = 105,
|
||||
AI_FILTER_INITIAL_END = 106,
|
||||
OTHER_FOLLOWER = 107,
|
||||
MIN_ATTACK = 108,
|
||||
MAX_ATTACK = 109,
|
||||
MIN_COST = 110,
|
||||
MAX_COST = 111,
|
||||
ALLY_AMULET = 112,
|
||||
FOLLOWER = 113,
|
||||
FOLLOWER_CARD_TYPE = 114,
|
||||
AMULET = 115,
|
||||
NOT_COUNTDOWN_AMULET = 116,
|
||||
DAMAGED_FOLLOWER = 117,
|
||||
NO_DAMAGED_FOLLOWER = 118,
|
||||
EVOLVED_FOLLOWER = 119,
|
||||
BUFFED_FOLLOWER = 120,
|
||||
BUFFED_FOLLOWER_CARD_TYPE = 121,
|
||||
NEUTRAL = 122,
|
||||
SELECTED_TARGET_ID = 123,
|
||||
DESTROYED_CARD = 124,
|
||||
DESTROYED_IN_CURRENT_TURN = 125,
|
||||
RANDOM_SELECT = 126,
|
||||
ALL_SELECT = 127,
|
||||
TARGET_SELECT = 128,
|
||||
RANDOM_MULTI_SELECT = 129,
|
||||
SECOND_TARGET_SELECT = 130,
|
||||
REVERSE_TARGET = 131,
|
||||
FIRST_SELECT = 132,
|
||||
DIVIDED_SELECT = 133,
|
||||
OLDEST_SELECT = 134,
|
||||
DESTROY = 135,
|
||||
BANISH = 136,
|
||||
TOKEN_DRAW = 137,
|
||||
TEMP = 138,
|
||||
PERM = 139,
|
||||
ADD = 140,
|
||||
SET = 141,
|
||||
TURN = 142,
|
||||
GAME = 143,
|
||||
TARGET_ID = 144,
|
||||
USE_MIN = 145,
|
||||
IGNORE_IN_BATTLE = 146,
|
||||
IGNORE_IN_FUSION = 147,
|
||||
IN_HAND = 148,
|
||||
IN_PLAY = 149,
|
||||
LAST_DRAW_CARD = 150,
|
||||
NEWER = 151,
|
||||
OLDEST_FOLLOWER = 152,
|
||||
OTHER_OLDEST_HAND_CARD_TYPE = 153,
|
||||
PLAYED = 154,
|
||||
PLAYPTN = 155,
|
||||
BEFORE_PLAYPTN = 156,
|
||||
NOW = 157,
|
||||
AI_TRIBE = 158,
|
||||
CANDIDATE = 159,
|
||||
ENHANCED = 160,
|
||||
LEAST_VALUE = 161,
|
||||
ALLY_ATTACK_FOLLOWER = 162,
|
||||
NEXT_PLAY = 163,
|
||||
WHEN_PLAY_DAMAGE = 164,
|
||||
WHEN_PLAY_DESTROY = 165,
|
||||
FIRST_SUMMON_FOLLOWER_IN_PLAYPTN = 166,
|
||||
SELECT_LOGIC_TYPE_BEGIN = 167,
|
||||
DEFAULT_LOGIC = 168,
|
||||
DESTROY_LOGIC = 169,
|
||||
DAMAGE_LOGIC = 170,
|
||||
BANISH_LOGIC = 171,
|
||||
BOUNCE_LOGIC = 172,
|
||||
METAMORPHOSE_LOGIC = 173,
|
||||
MAX_ATTACK_LOGIC = 174,
|
||||
TYRANT_ORDER_LOGIC = 175,
|
||||
REVERSE_DISCARD_LOGIC = 176,
|
||||
WHITEFROST_WHISPER_LOGIC = 177,
|
||||
SELECT_LOGIC_TYPE_END = 178,
|
||||
LIFE_INF = 1001,
|
||||
ATK_INF = 1002,
|
||||
COST_INF = 1003,
|
||||
BASE_COST_INF = 1004,
|
||||
LIFE_SUP = 1005,
|
||||
ATK_SUP = 1006,
|
||||
COST_SUP = 1007,
|
||||
BASE_COST_SUP = 1008,
|
||||
ATK_EQL = 1009,
|
||||
LIFE_EQL = 1010,
|
||||
COST_EQL = 1011,
|
||||
BASE_COST_EQL = 1012,
|
||||
COUNTDOWN_EQL = 1013,
|
||||
PLAY_COUNT_EQL = 1014
|
||||
}
|
||||
48
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenBase.cs
Normal file
48
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenBase.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIScriptTokenBase
|
||||
{
|
||||
public AIScriptTokenType Type { get; private set; }
|
||||
|
||||
public virtual float Value { get; private set; }
|
||||
|
||||
public int Priority => Type switch
|
||||
{
|
||||
AIScriptTokenType.OR => -3,
|
||||
AIScriptTokenType.AND => -2,
|
||||
AIScriptTokenType.PLUS => 0,
|
||||
AIScriptTokenType.MINUS => 0,
|
||||
AIScriptTokenType.MULTI => 2,
|
||||
AIScriptTokenType.DIV => 2,
|
||||
AIScriptTokenType.REMAIN => 2,
|
||||
AIScriptTokenType.MORE_THAN => -1,
|
||||
AIScriptTokenType.LESS_THAN => -1,
|
||||
AIScriptTokenType.MORE_EQUAL => -1,
|
||||
AIScriptTokenType.LESS_EQUAL => -1,
|
||||
AIScriptTokenType.EQUAL => -1,
|
||||
AIScriptTokenType.MAX => 3,
|
||||
AIScriptTokenType.MIN => 3,
|
||||
AIScriptTokenType.FUNC => 6,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
protected AIScriptTokenBase(AIScriptTokenType type, float value)
|
||||
{
|
||||
Type = type;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public virtual AIScriptTokenBase Clone()
|
||||
{
|
||||
return new AIScriptTokenBase(Type, Value);
|
||||
}
|
||||
|
||||
public virtual bool IsEqual(AIScriptTokenBase token)
|
||||
{
|
||||
if (Type == token.Type)
|
||||
{
|
||||
return Value == token.Value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
119
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenFuncType.cs
Normal file
119
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenFuncType.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIScriptTokenFuncType
|
||||
{
|
||||
MEMBER_COUNT,
|
||||
HAND_COUNT,
|
||||
HAND_NAME_COUNT,
|
||||
DECK_COUNT,
|
||||
INPLAY_COUNT,
|
||||
PLAYOUT_ATTACKER_COUNT,
|
||||
BEFORE_PLAYPTN_COUNT,
|
||||
PLAY_TOKEN_COUNT,
|
||||
EVO_COUNT_IN_GAME,
|
||||
EVO_COUNT_IN_PREVIOUS_TURN,
|
||||
EVAL_TARGETING_DAMAGE,
|
||||
EVAL_TARGETING_AND_RANDOM_MULTI_DAMAGE,
|
||||
EVAL_TARGETING_DESTROY,
|
||||
EVAL_TARGETING_OTHER_DESTROY,
|
||||
EVAL_TARGETING_MULTI_DESTROY,
|
||||
EVAL_TARGETING_BOUNCE,
|
||||
EVAL_TARGETING_BANISH,
|
||||
EVAL_TARGETING_HEAL,
|
||||
EVAL_TARGETING_METAMORPHOSE,
|
||||
EVAL_TARGETING_BUFF,
|
||||
EVAL_ECHO_DAMAGE,
|
||||
EVAL_ALL_DAMAGE,
|
||||
EVAL_ALL_DESTROY,
|
||||
EVAL_ALL_BOUNCE,
|
||||
EVAL_ALL_METAMORPHOSE,
|
||||
EVAL_ALL_BUFF,
|
||||
EVAL_RANDOM_BUFF,
|
||||
EVAL_ALL_HEAL,
|
||||
EVAL_ALL_BANISH,
|
||||
EVAL_RANDOM_DESTROY,
|
||||
EVAL_RANDOM_BANISH,
|
||||
EVAL_RANDOM_METAMORPHOSE,
|
||||
EVAL_LEADER_DAMAGE,
|
||||
EVAL_RANDOM_BOUNCE,
|
||||
EVAL_LEADER_HEAL,
|
||||
EVAL_RANDOM_MULTI_DAMAGE,
|
||||
EVAL_RANDOM_MULTI_SELECT_DAMAGE,
|
||||
EVAL_RANDOM_MULTI_DAMAGE_MAX,
|
||||
EVAL_INSTANT_ATTACK,
|
||||
EVAL_RUSH,
|
||||
EVAL_REANIMATE,
|
||||
EVAL_DIVIDED_DAMAGE,
|
||||
EVAL_ALL_MULTI_DAMAGE,
|
||||
EVAL_ATTACK_REMOVE,
|
||||
FORCED_EXCHANGE,
|
||||
LIFE,
|
||||
ATTACK,
|
||||
POW,
|
||||
CEILING,
|
||||
FLOOR,
|
||||
EVAL_CHANT_COUNT_CHANGE,
|
||||
EVAL_CHANT_COUNT_CHANGE_ALL,
|
||||
IS_CLASH_TARGET,
|
||||
IS_ATTACK_TARGET,
|
||||
IS_SELECTED_TARGET,
|
||||
IS_NEXT_PLAY,
|
||||
DECK_NAME_COUNT,
|
||||
BROKEN_COUNT,
|
||||
BROKEN_NAME_COUNT,
|
||||
BROKEN_COST_SUM,
|
||||
LEAVE_NAME_COUNT,
|
||||
DESTROYED_COUNT,
|
||||
IS_TRIBE,
|
||||
SKILL_COUNT_FROM_ID,
|
||||
TAG_COUNT_FROM_ID,
|
||||
PLAYED_COUNT,
|
||||
PLAYED_COUNT_IN_GAME,
|
||||
PLAYED_COUNT_IN_PREVIOUS_TURN,
|
||||
PLAYED_NAME_COUNT,
|
||||
RANDOM,
|
||||
IS_REANIMATE,
|
||||
DAMAGE_COUNT,
|
||||
HEAL_COUNT,
|
||||
TOTAL_DAMAGE,
|
||||
FUSION_COUNT,
|
||||
NOW_FUSION_COUNT,
|
||||
FUSION_COUNT_AT_ONCE,
|
||||
FUSION_NAME_COUNT,
|
||||
IS_SKILL_OCCURRED,
|
||||
SKILL_ACTIVATE_COUNT,
|
||||
HAND_MAX_ATTACK,
|
||||
DECK_MAX_COST,
|
||||
INPLAY_LARGEST_LIFE,
|
||||
LEADER_MAX_LIFE,
|
||||
IS_DISCARD_TARGET,
|
||||
DISCARD_COUNT,
|
||||
BOUNCE_COUNT,
|
||||
EMOTE_PLAY_COUNT,
|
||||
DRAW_COUNT,
|
||||
MEMBER_MAX_ATK,
|
||||
IS_BURIAL_RITE,
|
||||
BURIAL_COUNT,
|
||||
RESONANCE_START_COUNT,
|
||||
SUMMON_COUNT,
|
||||
BUFF_COUNT,
|
||||
IS_HOLDING_BATTLE_SKILL,
|
||||
IS_LEADER_HOLDING_BATTLE_SKILL,
|
||||
STACK_COUNT,
|
||||
LEAVE_COUNT,
|
||||
OWN_DESTROY_COUNT,
|
||||
IS_SELECTABLE,
|
||||
IS_ENEMY_AI_ID,
|
||||
ADD_HAND_COUNT,
|
||||
BASE_COST,
|
||||
RECEIVED_DAMAGE_SUM,
|
||||
FUSION_COUNT_IN_GAME,
|
||||
FUSION_NAME_COUNT_IN_GAME,
|
||||
BANISH_COUNT,
|
||||
HAND_BANISH_COUNT,
|
||||
ADDED_DECK_COUNT_IN_GAME,
|
||||
IS_PLAYER_CHARA_ID,
|
||||
IS_PLAYER_ABILITY_ID,
|
||||
IS_BOTH_CLASS,
|
||||
NONE
|
||||
}
|
||||
27
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenType.cs
Normal file
27
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenType.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIScriptTokenType
|
||||
{
|
||||
NUMERIC,
|
||||
PLUS,
|
||||
MINUS,
|
||||
MULTI,
|
||||
DIV,
|
||||
REMAIN,
|
||||
LEFT_BLACKET,
|
||||
RIGHT_BLACKET,
|
||||
COMMA,
|
||||
MORE_THAN,
|
||||
LESS_THAN,
|
||||
MORE_EQUAL,
|
||||
LESS_EQUAL,
|
||||
EQUAL,
|
||||
MAX,
|
||||
MIN,
|
||||
FUNC,
|
||||
ARG,
|
||||
ID,
|
||||
VARIABLE,
|
||||
OR,
|
||||
AND
|
||||
}
|
||||
118
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenVariableType.cs
Normal file
118
SVSim.BattleEngine/Engine/Wizard/AIScriptTokenVariableType.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIScriptTokenVariableType
|
||||
{
|
||||
NONE,
|
||||
NOW_TURN,
|
||||
COUNTDOWN,
|
||||
REINCARNATION_MAX,
|
||||
SPELLBOOST,
|
||||
FIELD_SPACE,
|
||||
ALLY_UNIT_MIN,
|
||||
ALLY_UNIT_MAX,
|
||||
ALLY_ATTACKABLE_ATK_MAX,
|
||||
ALLY_NON_ATTACKABLE_ATK_MAX,
|
||||
ALLY_MAX_ATTACKABLE_LIFE,
|
||||
ENEMY_UNIT_MIN,
|
||||
ENEMY_UNIT_MAX,
|
||||
HAND_COUNT_E,
|
||||
DECK_COUNT_E,
|
||||
PLAYPTN_COUNT,
|
||||
MEMBER_MAX_LIFE,
|
||||
MEMBER_ATK_SUM,
|
||||
MEMBER_LIFE_SUM,
|
||||
INPLAY_ATTACK_SUM_TO_LEADER,
|
||||
ATTACK_TARGET_ATK_MAX,
|
||||
SUMMON_DRUNKEN_ATK_MAX,
|
||||
ENEMY_MIN_ATK,
|
||||
ENEMY_MAX_ATK,
|
||||
ENEMY_ATK_SUM,
|
||||
ALLY_INPLAY_MAX_ATK,
|
||||
GRAVE_COUNT,
|
||||
ALLY_MAX_PP,
|
||||
ENEMY_MAX_PP,
|
||||
REST_PP,
|
||||
NOW_REST_PP,
|
||||
ALLY_EP,
|
||||
ENEMY_EP,
|
||||
OWN_ATK,
|
||||
OWN_LIFE,
|
||||
OWN_COST,
|
||||
OWN_BASE_ATK,
|
||||
OWN_BASE_LIFE,
|
||||
KILLER_ATTACK_VALUE,
|
||||
ENHANCE_COST,
|
||||
PLAY_ACTOR_ENHANCE_COST,
|
||||
ACCELERATE_COST,
|
||||
CHOICE_TRANSFORM_COST,
|
||||
BASE_SKILL_COUNT,
|
||||
LAST_LIFE,
|
||||
LEADER_DEF_LIFE,
|
||||
LEADER_CURRENT_LIFE,
|
||||
MAX_ATTACKABLE_COUNT,
|
||||
HAND_MIN_COST,
|
||||
HAND_MAX_COST,
|
||||
UNION_BURST_COUNT,
|
||||
CONSUME_EP,
|
||||
LAST_HEAL_AMOUNT,
|
||||
JUST_BEFORE_TURN_DAMAGE,
|
||||
RALLY_COUNT,
|
||||
SKYBOUND_ART_COUNT,
|
||||
SUPER_SKYBOUND_ART_COUNT,
|
||||
USED_EP_COUNT,
|
||||
USED_PP_COUNT,
|
||||
EARTH_RITE_COUNT,
|
||||
NECROMANCE_COUNT,
|
||||
USED_STACK_COUNT,
|
||||
DEFAULT_DAMAGE,
|
||||
NEXT_PLAY_PRIORITY,
|
||||
NECROMANCED_COUNT_IN_GAME,
|
||||
IS_EVO_TURN,
|
||||
IS_ABLE_EVO,
|
||||
IS_F_ADV,
|
||||
IS_F_DISADV,
|
||||
IS_AWAKE,
|
||||
IS_BERSERK,
|
||||
IS_TO_BE_BERSERK,
|
||||
IS_ON_FIELD,
|
||||
IS_IN_HAND,
|
||||
IS_IN_PLAYPTN,
|
||||
IS_OWNER_TURN,
|
||||
IS_ALLY,
|
||||
IS_ENEMY,
|
||||
IS_ALLY_FIRST,
|
||||
IS_SNEAK,
|
||||
IS_MEDUSA,
|
||||
IS_KILLER,
|
||||
IS_EVOLVED,
|
||||
IS_GUARD,
|
||||
IS_RUSH,
|
||||
IS_PLAYOUT_ATTACKER,
|
||||
IS_ENHANCED,
|
||||
IS_ACCELERATE,
|
||||
IS_CRYSTALIZE,
|
||||
IS_ATTACK_LEADER,
|
||||
IS_FANFARE,
|
||||
IS_SKILL_REMOVED,
|
||||
IS_BARBAROSSA,
|
||||
IS_RESONANCE,
|
||||
IS_LETHAL,
|
||||
IS_USED_EVO,
|
||||
IS_FIRST_TURN,
|
||||
IS_DAMAGED,
|
||||
IS_DELAY_HEAL,
|
||||
IS_NOT_ATTACK_YET,
|
||||
IS_EVOLVING,
|
||||
IS_LEADER,
|
||||
IS_GET_ON,
|
||||
IS_SKILL_SUMMONED,
|
||||
IS_UNTOUCHABLE,
|
||||
IS_FORCE_TARGETING,
|
||||
IS_QUICK,
|
||||
IS_NOT_BE_ATTACKED,
|
||||
IS_IN_SIMULATION,
|
||||
IS_IGNORE_GUARD,
|
||||
IS_ATTACKED,
|
||||
IS_ONEMORELASTWORD_TAGGED,
|
||||
IS_DRAIN
|
||||
}
|
||||
150
SVSim.BattleEngine/Engine/Wizard/AISelectedTargetInfo.cs
Normal file
150
SVSim.BattleEngine/Engine/Wizard/AISelectedTargetInfo.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISelectedTargetInfo
|
||||
{
|
||||
public TargetSelectType Type;
|
||||
|
||||
public AIRemovalType RemovalType;
|
||||
|
||||
public List<AIVirtualCard> Targets { get; private set; }
|
||||
|
||||
public AIVirtualCard FirstTarget => Targets[0];
|
||||
|
||||
public bool HasTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Targets != null)
|
||||
{
|
||||
return Targets.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo(TargetSelectType type, AIRemovalType removalType = AIRemovalType.None)
|
||||
{
|
||||
Type = type;
|
||||
RemovalType = removalType;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo(AIVirtualCard target, TargetSelectType type, AIRemovalType removalType = AIRemovalType.None)
|
||||
{
|
||||
AddTarget(target);
|
||||
Type = type;
|
||||
RemovalType = removalType;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo(List<AIVirtualCard> targets, TargetSelectType type, AIRemovalType removalType = AIRemovalType.None)
|
||||
{
|
||||
Type = type;
|
||||
RemovalType = removalType;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AddTarget(targets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTarget(AIVirtualCard target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AISelectedTargetInfo.AddTarget error!! Trying to add null into target list!!!!!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Targets = AIParamQuery.AddElementToList(target, Targets);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsTarget(AIVirtualCard card)
|
||||
{
|
||||
if (Targets == null || Targets.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
if (Targets[i].IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo GetSimilarTargetInfo(AIVirtualField field)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo = new AISelectedTargetInfo(Type, RemovalType);
|
||||
if (Targets == null || Targets.Count <= 0)
|
||||
{
|
||||
return aISelectedTargetInfo;
|
||||
}
|
||||
for (int i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = Targets[i];
|
||||
AIVirtualCard target = ((Type == TargetSelectType.Choice) ? aIVirtualCard : field.SearchVirtualCard(aIVirtualCard));
|
||||
aISelectedTargetInfo.AddTarget(target);
|
||||
}
|
||||
return aISelectedTargetInfo;
|
||||
}
|
||||
|
||||
public bool IsDuplicate(AISelectedTargetInfo compare)
|
||||
{
|
||||
if (Type != compare.Type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (HasTarget)
|
||||
{
|
||||
if (!compare.HasTarget || compare.Targets.Count != Targets.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
if (!Targets[i].IsSameCard(compare.Targets[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (compare.HasTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsSelectedSameTarget(AISelectedTargetInfo otherTargetInfo)
|
||||
{
|
||||
if (!HasTarget || otherTargetInfo == null || !otherTargetInfo.HasTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
if (otherTargetInfo.ContainsTarget(Targets[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<int> GetTargetIdList()
|
||||
{
|
||||
if (!HasTarget)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<int> list = new List<int>();
|
||||
for (int i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
list.Add(Targets[i].BaseId);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
232
SVSim.BattleEngine/Engine/Wizard/AISelectedTargetInfoSet.cs
Normal file
232
SVSim.BattleEngine/Engine/Wizard/AISelectedTargetInfoSet.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISelectedTargetInfoSet
|
||||
{
|
||||
public static readonly int LENGTH = 2;
|
||||
|
||||
private AISelectedTargetInfo[] _set;
|
||||
|
||||
public AISelectedTargetInfo PreprocessTarget { get; private set; }
|
||||
|
||||
public AISelectedTargetInfo ChoiceTarget { get; private set; }
|
||||
|
||||
public bool HasChoiceTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ChoiceTarget != null)
|
||||
{
|
||||
return ChoiceTarget.HasTarget;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AISelectedTargetInfoSet()
|
||||
{
|
||||
_set = new AISelectedTargetInfo[LENGTH];
|
||||
}
|
||||
|
||||
public AISelectedTargetInfoSet Clone()
|
||||
{
|
||||
return new AISelectedTargetInfoSet(this);
|
||||
}
|
||||
|
||||
private AISelectedTargetInfoSet(AISelectedTargetInfoSet set)
|
||||
{
|
||||
_set = new AISelectedTargetInfo[LENGTH];
|
||||
for (int i = 0; i < LENGTH; i++)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo = set.Get(i);
|
||||
_set[i] = aISelectedTargetInfo;
|
||||
}
|
||||
PreprocessTarget = set.PreprocessTarget;
|
||||
ChoiceTarget = set.ChoiceTarget;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo Get(int index)
|
||||
{
|
||||
if (index < 0 || index > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _set[index];
|
||||
}
|
||||
|
||||
public void Set(AISelectedTargetInfo info, int index)
|
||||
{
|
||||
if (index >= 0 && index <= 1)
|
||||
{
|
||||
_set[index] = info;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPreprocessTarget(AISelectedTargetInfo info)
|
||||
{
|
||||
PreprocessTarget = info;
|
||||
}
|
||||
|
||||
public void SetChoiceTarget(AISelectedTargetInfo info)
|
||||
{
|
||||
ChoiceTarget = info;
|
||||
}
|
||||
|
||||
public bool IsTargetExist(int index)
|
||||
{
|
||||
if (index < 0 || index > 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _set[index]?.HasTarget ?? false;
|
||||
}
|
||||
|
||||
public bool IsAnyTargetExists()
|
||||
{
|
||||
if (PreprocessTarget != null && PreprocessTarget.HasTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (HasChoiceTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
AISelectedTargetInfo[] set = _set;
|
||||
foreach (AISelectedTargetInfo aISelectedTargetInfo in set)
|
||||
{
|
||||
if (aISelectedTargetInfo != null && aISelectedTargetInfo.HasTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo GetChoiceInfo()
|
||||
{
|
||||
if (HasChoiceTarget)
|
||||
{
|
||||
return ChoiceTarget;
|
||||
}
|
||||
AISelectedTargetInfo[] set = _set;
|
||||
foreach (AISelectedTargetInfo aISelectedTargetInfo in set)
|
||||
{
|
||||
if (aISelectedTargetInfo != null && aISelectedTargetInfo.Type == TargetSelectType.Choice)
|
||||
{
|
||||
return aISelectedTargetInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfoSet GetSimilarTargetInfoSet(AIVirtualField field)
|
||||
{
|
||||
AISelectedTargetInfoSet aISelectedTargetInfoSet = new AISelectedTargetInfoSet();
|
||||
if (PreprocessTarget != null)
|
||||
{
|
||||
AISelectedTargetInfo similarTargetInfo = PreprocessTarget.GetSimilarTargetInfo(field);
|
||||
aISelectedTargetInfoSet.SetPreprocessTarget(similarTargetInfo);
|
||||
}
|
||||
if (ChoiceTarget != null)
|
||||
{
|
||||
AISelectedTargetInfo similarTargetInfo2 = ChoiceTarget.GetSimilarTargetInfo(field);
|
||||
aISelectedTargetInfoSet.SetChoiceTarget(similarTargetInfo2);
|
||||
}
|
||||
for (int i = 0; i < _set.Length; i++)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo = _set[i];
|
||||
AISelectedTargetInfo info = null;
|
||||
if (aISelectedTargetInfo != null)
|
||||
{
|
||||
info = aISelectedTargetInfo.GetSimilarTargetInfo(field);
|
||||
}
|
||||
aISelectedTargetInfoSet.Set(info, i);
|
||||
}
|
||||
return aISelectedTargetInfoSet;
|
||||
}
|
||||
|
||||
public bool IsDuplicate(AISelectedTargetInfoSet compare)
|
||||
{
|
||||
if (compare == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (PreprocessTarget == null)
|
||||
{
|
||||
if (compare.PreprocessTarget != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!PreprocessTarget.IsDuplicate(compare.PreprocessTarget))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ChoiceTarget == null)
|
||||
{
|
||||
if (compare.ChoiceTarget != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!ChoiceTarget.IsDuplicate(compare.ChoiceTarget))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < LENGTH; i++)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo = _set[i];
|
||||
AISelectedTargetInfo aISelectedTargetInfo2 = compare.Get(i);
|
||||
if (aISelectedTargetInfo == null)
|
||||
{
|
||||
if (aISelectedTargetInfo2 != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!aISelectedTargetInfo.IsDuplicate(aISelectedTargetInfo2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<int> GetTargetIdList(AIScriptTokenArgType selectType)
|
||||
{
|
||||
AISelectedTargetInfo aISelectedTargetInfo;
|
||||
switch (selectType)
|
||||
{
|
||||
case AIScriptTokenArgType.CHOICED_TARGET:
|
||||
aISelectedTargetInfo = ChoiceTarget;
|
||||
break;
|
||||
case AIScriptTokenArgType.SELECTED_TARGET:
|
||||
aISelectedTargetInfo = _set[0];
|
||||
break;
|
||||
case AIScriptTokenArgType.SECOND_SELECTED_TARGET:
|
||||
aISelectedTargetInfo = _set[1];
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError("AISelectedTargetInfoSet.GetTargetIdList() error!! selectType = " + selectType);
|
||||
aISelectedTargetInfo = null;
|
||||
break;
|
||||
}
|
||||
return aISelectedTargetInfo?.GetTargetIdList();
|
||||
}
|
||||
|
||||
public void UpdateRemovalType(AIScriptTokenArgType whichTarget, AIRemovalType removalType)
|
||||
{
|
||||
if (whichTarget != AIScriptTokenArgType.TARGET_SELECT && whichTarget != AIScriptTokenArgType.SECOND_TARGET_SELECT)
|
||||
{
|
||||
AIConsoleUtility.LogError($"whichTarget=={whichTarget} is invalid!!");
|
||||
return;
|
||||
}
|
||||
int num = ((whichTarget != AIScriptTokenArgType.TARGET_SELECT) ? 1 : 0);
|
||||
AISelectedTargetInfo aISelectedTargetInfo = _set[num];
|
||||
if (aISelectedTargetInfo != null)
|
||||
{
|
||||
aISelectedTargetInfo.RemovalType = removalType;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
SVSim.BattleEngine/Engine/Wizard/AISetUpData.cs
Normal file
37
SVSim.BattleEngine/Engine/Wizard/AISetUpData.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISetUpData
|
||||
{
|
||||
public int classID;
|
||||
|
||||
public AI_LOGIC_LV logicLv;
|
||||
|
||||
public string deckName;
|
||||
|
||||
public string styleName;
|
||||
|
||||
public string emoteName;
|
||||
|
||||
public bool doesUseEmote;
|
||||
|
||||
public bool useInnerEmote;
|
||||
|
||||
public int enemyAiID;
|
||||
|
||||
public List<int> specialAbilityList;
|
||||
|
||||
public AISetUpData(int _classID, AI_LOGIC_LV _logicLv, string _deckName, string _styleName, string _emoteName, bool _doesUseEmote, bool _useInnerEmote, int _enemyAiID, List<int> _specialAbilityList = null)
|
||||
{
|
||||
classID = _classID;
|
||||
logicLv = _logicLv;
|
||||
deckName = _deckName;
|
||||
styleName = _styleName;
|
||||
emoteName = _emoteName;
|
||||
doesUseEmote = _doesUseEmote;
|
||||
useInnerEmote = _useInnerEmote;
|
||||
enemyAiID = _enemyAiID;
|
||||
specialAbilityList = _specialAbilityList;
|
||||
}
|
||||
}
|
||||
25
SVSim.BattleEngine/Engine/Wizard/AISimulationBuffInfo.cs
Normal file
25
SVSim.BattleEngine/Engine/Wizard/AISimulationBuffInfo.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AISimulationBuffInfo
|
||||
{
|
||||
public int TempAttackBuff;
|
||||
|
||||
public int TempLifeBuff;
|
||||
|
||||
public int TotalAttackBuff;
|
||||
|
||||
public int TotalLifeBuff;
|
||||
|
||||
public AISimulationBuffInfo(int tempAttack, int tempLife, int totalAttack, int totalLife)
|
||||
{
|
||||
TempAttackBuff = tempAttack;
|
||||
TempLifeBuff = tempLife;
|
||||
TotalAttackBuff = totalAttack;
|
||||
TotalLifeBuff = totalLife;
|
||||
}
|
||||
|
||||
public static AISimulationBuffInfo operator +(AISimulationBuffInfo a, AISimulationBuffInfo b)
|
||||
{
|
||||
return new AISimulationBuffInfo(a.TempAttackBuff + b.TempAttackBuff, a.TempLifeBuff + b.TempLifeBuff, a.TotalAttackBuff + b.TotalAttackBuff, a.TotalLifeBuff + b.TotalLifeBuff);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISimulationBuffInfoCollection
|
||||
{
|
||||
public List<AIBuffWithTargetsInformation> BuffInfoList { get; private set; }
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BuffInfoList != null)
|
||||
{
|
||||
return BuffInfoList.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public AISimulationBuffInfoCollection()
|
||||
{
|
||||
BuffInfoList = null;
|
||||
}
|
||||
|
||||
public void Add(ulong tagHash, List<AIVirtualCard> target, AISimulationBuffInfo buffInfo)
|
||||
{
|
||||
AIBuffWithTargetsInformation element = new AIBuffWithTargetsInformation(target, buffInfo, tagHash);
|
||||
BuffInfoList = AIParamQuery.AddElementToList(element, BuffInfoList);
|
||||
}
|
||||
|
||||
public void PseudoApplyBuffForSimpleAttack(AIVirtualCard currentAttacker, List<AIVirtualCard> attackerList, Tuple<int, int>[] statusArray)
|
||||
{
|
||||
if (BuffInfoList != null && BuffInfoList.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < BuffInfoList.Count; i++)
|
||||
{
|
||||
BuffInfoList[i].PseudoApplyBuffForSimpleAttack(currentAttacker, attackerList, statusArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplySingleBuff(ulong tagHash, AIVirtualField field, List<int> playPtn, AIVirtualAttackInfo situation)
|
||||
{
|
||||
if (BuffInfoList != null && BuffInfoList.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < BuffInfoList.Count && !BuffInfoList[i].VerifyArgumentAndApply(tagHash, field, playPtn, situation); i++)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AISimulationBuffInfo GetBuffInfoToCertainCard(AIVirtualCard card)
|
||||
{
|
||||
AISimulationBuffInfo result = null;
|
||||
if (BuffInfoList != null && BuffInfoList.Count > 0)
|
||||
{
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
int num3 = 0;
|
||||
int num4 = 0;
|
||||
for (int i = 0; i < BuffInfoList.Count; i++)
|
||||
{
|
||||
AIBuffWithTargetsInformation aIBuffWithTargetsInformation = BuffInfoList[i];
|
||||
if (aIBuffWithTargetsInformation.ContainsTarget(card))
|
||||
{
|
||||
num += aIBuffWithTargetsInformation.BuffInfo.TempAttackBuff;
|
||||
num2 += aIBuffWithTargetsInformation.BuffInfo.TempLifeBuff;
|
||||
num3 += aIBuffWithTargetsInformation.BuffInfo.TotalAttackBuff;
|
||||
num4 += aIBuffWithTargetsInformation.BuffInfo.TotalLifeBuff;
|
||||
}
|
||||
}
|
||||
if (num != 0 || num2 != 0 || num3 != 0 || num4 != 0)
|
||||
{
|
||||
result = new AISimulationBuffInfo(num, num2, num3, num4);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool HasBuffInfo(ulong hash)
|
||||
{
|
||||
if (BuffInfoList == null || BuffInfoList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < BuffInfoList.Count; i++)
|
||||
{
|
||||
if (BuffInfoList[i].IsHashEqual(hash))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISimulationPreprocessRecorder
|
||||
{
|
||||
public List<AISinglePreprocessRecord> RecordList;
|
||||
|
||||
public int TotalBurialCount { get; private set; }
|
||||
|
||||
public bool HasRecord
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RecordList != null)
|
||||
{
|
||||
return RecordList.Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public AISimulationPreprocessRecorder()
|
||||
{
|
||||
TotalBurialCount = 0;
|
||||
}
|
||||
|
||||
public void AddRecord(AISinglePreprocessRecord record)
|
||||
{
|
||||
RecordList = AIParamQuery.AddElementToList(record, RecordList);
|
||||
if (record.BurialRiteCount > 0)
|
||||
{
|
||||
TotalBurialCount += record.BurialRiteCount;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAll()
|
||||
{
|
||||
if (RecordList != null)
|
||||
{
|
||||
RecordList.Clear();
|
||||
RecordList = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearBurialCount()
|
||||
{
|
||||
TotalBurialCount = 0;
|
||||
}
|
||||
}
|
||||
246
SVSim.BattleEngine/Engine/Wizard/AISinglePlayptnRecord.cs
Normal file
246
SVSim.BattleEngine/Engine/Wizard/AISinglePlayptnRecord.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISinglePlayptnRecord
|
||||
{
|
||||
public List<int> PlayPtn;
|
||||
|
||||
public ulong PlayPtnHash;
|
||||
|
||||
public List<PlayedCardInfo> PlayedCardList;
|
||||
|
||||
public bool IsValid;
|
||||
|
||||
public int LastRestPp;
|
||||
|
||||
public int TotalDrawCount;
|
||||
|
||||
public float FirstPlayCardPriority;
|
||||
|
||||
public AIVirtualCard FirstSummonedAllyFollower;
|
||||
|
||||
public int ReferenceFieldIndex { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> UsableHandCardList { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> RestHandCardList { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> AllDiscardedCardList { get; private set; }
|
||||
|
||||
public int DiscardCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AllDiscardedCardList != null)
|
||||
{
|
||||
return AllDiscardedCardList.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int PlayPtnCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PlayPtn != null)
|
||||
{
|
||||
return PlayPtn.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public AISinglePlayptnRecord(List<int> playPtn, AIVirtualField field, int fieldIndex)
|
||||
{
|
||||
PlayPtn = playPtn;
|
||||
PlayPtnHash = AIHandPtnCalculator.CalculatePlayPtnHash(field, playPtn);
|
||||
IsValid = true;
|
||||
LastRestPp = field.AllyPp;
|
||||
ReferenceFieldIndex = fieldIndex;
|
||||
TotalDrawCount = 0;
|
||||
InitializeHandCardList(field);
|
||||
AllDiscardedCardList = null;
|
||||
PlayedCardList = new List<PlayedCardInfo>();
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
int num = playPtn[i];
|
||||
AIVirtualCard card = field.AllyHandCards[num];
|
||||
PlayedCardList.Add(new PlayedCardInfo(num, card));
|
||||
if (i == 0)
|
||||
{
|
||||
FirstPlayCardPriority = card.GetPriority(playPtn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdatePlayPtnRecord(PlayedCardInfo info)
|
||||
{
|
||||
TotalDrawCount += info.DrawCount;
|
||||
LastRestPp = info.RestPp;
|
||||
if (!info.IsPlayable)
|
||||
{
|
||||
IsValid = false;
|
||||
}
|
||||
RestHandCardList.Remove(info.Card);
|
||||
info.IsProcessed = true;
|
||||
}
|
||||
|
||||
public bool IsToBeRegister()
|
||||
{
|
||||
return PlayPtn.Count == PlayedCardList.Count;
|
||||
}
|
||||
|
||||
public AIVirtualCard FindRealActor(AIVirtualCard originalCard)
|
||||
{
|
||||
List<PlayedCardInfo> playedCardList = PlayedCardList;
|
||||
for (int i = 0; i < playedCardList.Count; i++)
|
||||
{
|
||||
PlayedCardInfo playedCardInfo = playedCardList[i];
|
||||
if (originalCard.IsSameCard(playedCardInfo.Card) && playedCardInfo.TransformCard != null)
|
||||
{
|
||||
return playedCardInfo.TransformCard;
|
||||
}
|
||||
}
|
||||
return originalCard;
|
||||
}
|
||||
|
||||
public bool IsMatchedPattern(List<int> playPtn)
|
||||
{
|
||||
for (int i = 0; i < PlayPtn.Count; i++)
|
||||
{
|
||||
int num = PlayPtn[i];
|
||||
int num2 = playPtn[i];
|
||||
if (num != num2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializeHandCardList(AIVirtualField field)
|
||||
{
|
||||
UsableHandCardList = new List<AIVirtualCard>();
|
||||
RestHandCardList = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < field.AllyHandCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard item = field.AllyHandCards[i];
|
||||
RestHandCardList.Add(item);
|
||||
if (!PlayPtn.Contains(i))
|
||||
{
|
||||
UsableHandCardList.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAllTargetsUsableHandCard(List<AIVirtualCard> targets)
|
||||
{
|
||||
if (UsableHandCardList == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard item = targets[i];
|
||||
if (!UsableHandCardList.Contains(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsUsableHandCard(AIVirtualCard card)
|
||||
{
|
||||
if (UsableHandCardList == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < UsableHandCardList.Count; i++)
|
||||
{
|
||||
if (UsableHandCardList[i].IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CheckRegisteredDiscardInfo(AIDiscardInfo discardInfo)
|
||||
{
|
||||
if (discardInfo.IsNGByAI)
|
||||
{
|
||||
IsValid = false;
|
||||
}
|
||||
else if (discardInfo.IsSuccess)
|
||||
{
|
||||
List<AIVirtualCard> targetList = discardInfo.TargetList;
|
||||
UpdateHandCardList(targetList);
|
||||
AllDiscardedCardList = AIParamQuery.AddRangeToList(targetList, AllDiscardedCardList);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateHandCardList(List<AIVirtualCard> usedHandCardList)
|
||||
{
|
||||
if (usedHandCardList != null && usedHandCardList.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < usedHandCardList.Count; i++)
|
||||
{
|
||||
AIVirtualCard item = usedHandCardList[i];
|
||||
UsableHandCardList.Remove(item);
|
||||
RestHandCardList.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterPreprocess(PlayedCardInfo info, AIVirtualTargetSelectAction situation, AIVirtualField field)
|
||||
{
|
||||
AISimulationPreprocessRecorder preprocessRecorder = situation.PreprocessRecorder;
|
||||
info.RegisterPreprocess(preprocessRecorder);
|
||||
AIVirtualCard card = info.Card;
|
||||
if (preprocessRecorder.TotalBurialCount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AIVirtualTargetSelectInfo burialSelectInfo = card.GetBurialSelectInfo(field, situation);
|
||||
bool flag = false;
|
||||
bool isBreakPlayptn = false;
|
||||
if (burialSelectInfo != null)
|
||||
{
|
||||
AISelectedTargetInfo burialSelectTargets = burialSelectInfo.GetBurialSelectTargets(situation, field, burialSelectInfo, this, out isBreakPlayptn);
|
||||
if (burialSelectTargets != null)
|
||||
{
|
||||
info.RegisterPreDecidedPreprocessTarget(burialSelectTargets);
|
||||
UpdateHandCardList(burialSelectTargets.Targets);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
IsValid = !isBreakPlayptn;
|
||||
}
|
||||
else
|
||||
{
|
||||
preprocessRecorder.ClearBurialCount();
|
||||
}
|
||||
}
|
||||
|
||||
public PlayedCardInfo FindPlayedCardInfo(AIVirtualCard actor)
|
||||
{
|
||||
if (PlayedCardList == null || PlayedCardList.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < PlayedCardList.Count; i++)
|
||||
{
|
||||
PlayedCardInfo playedCardInfo = PlayedCardList[i];
|
||||
if (actor.IsSameCard(playedCardInfo.Card))
|
||||
{
|
||||
return playedCardInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
92
SVSim.BattleEngine/Engine/Wizard/AISinglePreprocessRecord.cs
Normal file
92
SVSim.BattleEngine/Engine/Wizard/AISinglePreprocessRecord.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISinglePreprocessRecord
|
||||
{
|
||||
public int NecromanceCount;
|
||||
|
||||
public int BurialRiteCount;
|
||||
|
||||
public AIVirtualCard RealActor { get; private set; }
|
||||
|
||||
public AIVirtualCard OriginalCard { get; private set; }
|
||||
|
||||
public AIScriptTokenArgType Timing { get; private set; }
|
||||
|
||||
public int EarthRiteCount { get; private set; }
|
||||
|
||||
public List<EarthRiteRecordContainer> EarthRiteContainer { get; private set; }
|
||||
|
||||
public AISinglePreprocessRecord(AIVirtualCard realActor, AIVirtualCard originalCard, AIScriptTokenArgType timing)
|
||||
{
|
||||
RealActor = realActor;
|
||||
OriginalCard = originalCard;
|
||||
Timing = timing;
|
||||
NecromanceCount = 0;
|
||||
BurialRiteCount = 0;
|
||||
EarthRiteCount = 0;
|
||||
EarthRiteContainer = new List<EarthRiteRecordContainer>();
|
||||
}
|
||||
|
||||
public void AddConsumedEarthRite(AIVirtualCard consumedTarget, int consumedStack)
|
||||
{
|
||||
if (consumedTarget == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AISinglePreprocessRecord.AddConsumedEarthRite(): Consumed stack target is null.");
|
||||
return;
|
||||
}
|
||||
if (consumedStack <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AISinglePreprocessRecord.AddConsumedEarthRite(): Consumed stack count is less than 1");
|
||||
return;
|
||||
}
|
||||
EarthRiteCount += consumedStack;
|
||||
EarthRiteContainer.Add(new EarthRiteRecordContainer(consumedTarget, consumedStack));
|
||||
}
|
||||
|
||||
public void RestoreAllEarthRiteCount(AIVirtualField field)
|
||||
{
|
||||
if (field == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("RestoreAllEarthRiteCount(): field is null.");
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> list = (RealActor.IsAlly ? field.AllyInplayCards : field.EnemyInplayCards);
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (RestoreEarthRiteCount(list[i]))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
if (EarthRiteContainer.Count != num)
|
||||
{
|
||||
AIConsoleUtility.LogError("RestoreAllEarthRiteCount(): Failed to restore all stacks!!!! ");
|
||||
}
|
||||
}
|
||||
|
||||
private bool RestoreEarthRiteCount(AIVirtualCard card)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("RestoreEarthRiteCount(): card is null.");
|
||||
return false;
|
||||
}
|
||||
if (!card.IsTribe(CardBasePrm.TribeType.WHITE_RITUAL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < EarthRiteContainer.Count; i++)
|
||||
{
|
||||
EarthRiteRecordContainer earthRiteRecordContainer = EarthRiteContainer[i];
|
||||
if (card.IsSameCard(earthRiteRecordContainer.ConsumedTarget))
|
||||
{
|
||||
card.ResetEarthRite(earthRiteRecordContainer.ConsumedStack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
333
SVSim.BattleEngine/Engine/Wizard/AISituationInfo.cs
Normal file
333
SVSim.BattleEngine/Engine/Wizard/AISituationInfo.cs
Normal file
@@ -0,0 +1,333 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public abstract class AISituationInfo
|
||||
{
|
||||
public AISelectedTargetInfoSet SelectedTargets;
|
||||
|
||||
public List<AIVirtualCard> BounceCardList;
|
||||
|
||||
public AISimulationPreprocessRecorder PreprocessRecorder;
|
||||
|
||||
public List<BattleCardRealTargetInformation> RealTargetInformationList;
|
||||
|
||||
public AIVirtualCard Actor { get; protected set; }
|
||||
|
||||
public AIVirtualCard OriginalCard { get; protected set; }
|
||||
|
||||
public AIVirtualCard ActionTarget => SelectedTargets.Get(0)?.FirstTarget;
|
||||
|
||||
public AIVirtualCard SecondActionTarget => SelectedTargets.Get(1)?.FirstTarget;
|
||||
|
||||
public AIOperationType ActionType { get; private set; }
|
||||
|
||||
public AIVirtualCard CurrentCheckCard { get; private set; }
|
||||
|
||||
public AIDiscardInfo DiscardInfo { get; private set; }
|
||||
|
||||
public AISkillProcessInfoCollection ProcessCollection { get; private set; }
|
||||
|
||||
public AISkillProcessInformation CurrentSkillProcessInfo { get; private set; }
|
||||
|
||||
public bool IsLatestAction { get; private set; }
|
||||
|
||||
public AISituationInfo(AIVirtualCard actor, AIVirtualCard target, AIVirtualCard secondTarget = null, AIOperationType type = AIOperationType.ATTACK)
|
||||
{
|
||||
Actor = actor;
|
||||
OriginalCard = actor;
|
||||
ActionType = type;
|
||||
SelectedTargets = new AISelectedTargetInfoSet();
|
||||
ProcessCollection = new AISkillProcessInfoCollection();
|
||||
if (target != null)
|
||||
{
|
||||
SelectedTargets.Set(new AISelectedTargetInfo(target, TargetSelectType.Default), 0);
|
||||
}
|
||||
if (secondTarget != null)
|
||||
{
|
||||
SelectedTargets.Set(new AISelectedTargetInfo(secondTarget, TargetSelectType.Default), 1);
|
||||
}
|
||||
PreprocessRecorder = new AISimulationPreprocessRecorder();
|
||||
IsLatestAction = false;
|
||||
RealTargetInformationList = null;
|
||||
}
|
||||
|
||||
public AISituationInfo(AIVirtualCard actor, AIOperationType type, AISelectedTargetInfoSet selectedTargetInfoSet)
|
||||
{
|
||||
Actor = actor;
|
||||
OriginalCard = actor;
|
||||
ActionType = type;
|
||||
ProcessCollection = new AISkillProcessInfoCollection();
|
||||
if (selectedTargetInfoSet == null)
|
||||
{
|
||||
SelectedTargets = new AISelectedTargetInfoSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedTargets = selectedTargetInfoSet;
|
||||
}
|
||||
PreprocessRecorder = new AISimulationPreprocessRecorder();
|
||||
IsLatestAction = false;
|
||||
RealTargetInformationList = null;
|
||||
}
|
||||
|
||||
public void SetActor(AIVirtualCard newActor)
|
||||
{
|
||||
Actor = newActor;
|
||||
}
|
||||
|
||||
public void SetOriginalCard(AIVirtualCard card)
|
||||
{
|
||||
OriginalCard = card;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo GetSituationTarget(AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
switch (whichTarget)
|
||||
{
|
||||
case AIScriptTokenArgType.SELECTED_TARGET:
|
||||
case AIScriptTokenArgType.TARGET_SELECT:
|
||||
return SelectedTargets.Get(0);
|
||||
case AIScriptTokenArgType.SECOND_SELECTED_TARGET:
|
||||
case AIScriptTokenArgType.SECOND_TARGET_SELECT:
|
||||
return SelectedTargets.Get(1);
|
||||
case AIScriptTokenArgType.CHOICED_TARGET:
|
||||
return SelectedTargets.GetChoiceInfo();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo GetBurialRiteTarget()
|
||||
{
|
||||
if (SelectedTargets != null && SelectedTargets.PreprocessTarget != null && SelectedTargets.PreprocessTarget.Type == TargetSelectType.BurialRite)
|
||||
{
|
||||
return SelectedTargets.PreprocessTarget;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AISelectedTargetInfo GetChoiceTarget()
|
||||
{
|
||||
if (SelectedTargets != null && SelectedTargets.HasChoiceTarget)
|
||||
{
|
||||
return SelectedTargets.ChoiceTarget;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsFirstTarget(AIVirtualCard card)
|
||||
{
|
||||
if (ActionTarget != null && ActionTarget.IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsSecondTarget(AIVirtualCard card)
|
||||
{
|
||||
if (SecondActionTarget != null && SecondActionTarget.IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsTargetExists(AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
return whichTarget switch
|
||||
{
|
||||
AIScriptTokenArgType.TARGET_SELECT => SelectedTargets.IsTargetExist(0),
|
||||
AIScriptTokenArgType.SECOND_TARGET_SELECT => SelectedTargets.IsTargetExist(1),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public void SetTarget(AISelectedTargetInfo info, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
switch (whichTarget)
|
||||
{
|
||||
case AIScriptTokenArgType.TARGET_SELECT:
|
||||
SelectedTargets.Set(info, 0);
|
||||
break;
|
||||
case AIScriptTokenArgType.SECOND_TARGET_SELECT:
|
||||
SelectedTargets.Set(info, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMultipleTargetsInInfo(List<AIVirtualCard> targets, TargetSelectType type, AIRemovalType removalType, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo info = new AISelectedTargetInfo(targets, type, removalType);
|
||||
SetTarget(info, whichTarget);
|
||||
}
|
||||
|
||||
public void SetSingleTargetInInfo(AIVirtualCard target, TargetSelectType type, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo info = ((target != null) ? new AISelectedTargetInfo(target, type) : null);
|
||||
SetTarget(info, whichTarget);
|
||||
}
|
||||
|
||||
public void SetChoicedTargetInInfo(AIVirtualCard target)
|
||||
{
|
||||
AISelectedTargetInfo choiceTarget = ((target != null) ? new AISelectedTargetInfo(target, TargetSelectType.Choice) : null);
|
||||
SelectedTargets.SetChoiceTarget(choiceTarget);
|
||||
}
|
||||
|
||||
public void SetChoicedMultipleTargetInInfo(List<AIVirtualCard> targets)
|
||||
{
|
||||
AISelectedTargetInfo choiceTarget = ((targets != null) ? new AISelectedTargetInfo(targets, TargetSelectType.Choice) : null);
|
||||
SelectedTargets.SetChoiceTarget(choiceTarget);
|
||||
}
|
||||
|
||||
public void SetDiscardInfo(AIDiscardInfo info)
|
||||
{
|
||||
DiscardInfo = info;
|
||||
}
|
||||
|
||||
public bool IsSameSituation(AISituationInfo situation)
|
||||
{
|
||||
if (ActionType != situation.ActionType || !Actor.IsSameCard(situation.Actor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!SelectedTargets.IsDuplicate(situation.SelectedTargets))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<int> GetTargetIdList(AIScriptTokenArgType selectType)
|
||||
{
|
||||
if (SelectedTargets == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SelectedTargets.GetTargetIdList(selectType);
|
||||
}
|
||||
|
||||
public void SetExecutingSkillProcess(AISkillProcessInformation processInfo)
|
||||
{
|
||||
CurrentSkillProcessInfo = processInfo;
|
||||
}
|
||||
|
||||
public AISkillProcessInformation RegisterNewProcessInfo(AIVirtualCard triggerCard, AISituationTriggerInformation.TriggerType triggerType)
|
||||
{
|
||||
AISkillProcessInformation aISkillProcessInformation = new AISkillProcessInformation(new AISituationTriggerInformation(triggerCard, triggerType));
|
||||
ProcessCollection.RegisterProcess(aISkillProcessInformation);
|
||||
return aISkillProcessInformation;
|
||||
}
|
||||
|
||||
public AISkillProcessInformation RegisterNewPreprocessProcessInfo(AIVirtualCard triggerCard, AISituationTriggerInformation.TriggerType triggerType)
|
||||
{
|
||||
AISkillProcessInformation aISkillProcessInformation = new AISkillProcessInformation(new AISituationTriggerInformation(triggerCard, triggerType));
|
||||
ProcessCollection.RegisterPreprocessProcessInfo(aISkillProcessInformation);
|
||||
return aISkillProcessInformation;
|
||||
}
|
||||
|
||||
public void AddProcessInfos(List<AISkillProcessInformation> processInfo)
|
||||
{
|
||||
ProcessCollection.RegisterProcess(processInfo);
|
||||
}
|
||||
|
||||
public void ExecuteAllSkillProcess()
|
||||
{
|
||||
ProcessCollection.ExecuteAllProcess(this);
|
||||
}
|
||||
|
||||
public void SetCurrentCheckCard(AIVirtualCard card)
|
||||
{
|
||||
CurrentCheckCard = card;
|
||||
}
|
||||
|
||||
public void ResetCurrentCheckCard()
|
||||
{
|
||||
CurrentCheckCard = null;
|
||||
}
|
||||
|
||||
public void RegisterRealTargetInfo(List<BattleCardRealTargetInformation> info)
|
||||
{
|
||||
RealTargetInformationList = info;
|
||||
}
|
||||
|
||||
public bool IsRealSkillTarget(AIVirtualCard target, AIVirtualCard owner)
|
||||
{
|
||||
if (RealTargetInformationList == null || RealTargetInformationList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < RealTargetInformationList.Count; i++)
|
||||
{
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation = RealTargetInformationList[i];
|
||||
if (owner.IsEqual(battleCardRealTargetInformation.SkillOwner) && battleCardRealTargetInformation.IsTarget(target))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AIVirtualCardRealTargetInformation DequeueRealTargetInfo(AIVirtualCard owner, AIVirtualField field)
|
||||
{
|
||||
if (RealTargetInformationList == null || RealTargetInformationList.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualField.AIVirtualFieldSearchCardOption searchOption = new AIVirtualField.AIVirtualFieldSearchCardOption
|
||||
{
|
||||
IsOutputCannotFindError = true,
|
||||
IsSearchFromDeck = true,
|
||||
IsSearchFromBeforeLatestActionDeck = true
|
||||
};
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation = null;
|
||||
for (int i = 0; i < RealTargetInformationList.Count; i++)
|
||||
{
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation2 = RealTargetInformationList[i];
|
||||
if (owner.IsEqual(battleCardRealTargetInformation2.SkillOwner))
|
||||
{
|
||||
battleCardRealTargetInformation = battleCardRealTargetInformation2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (battleCardRealTargetInformation != null)
|
||||
{
|
||||
RealTargetInformationList.Remove(battleCardRealTargetInformation);
|
||||
return battleCardRealTargetInformation.CreateAIVirtualTargetInformation(field, owner, searchOption);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<int> GetTokenIdListFromDequeuedRealTargetInfo(AIVirtualCard owner, AITokenType tokenType)
|
||||
{
|
||||
if (RealTargetInformationList == null || RealTargetInformationList.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < RealTargetInformationList.Count; i++)
|
||||
{
|
||||
BattleCardRealTargetInformation battleCardRealTargetInformation = RealTargetInformationList[i];
|
||||
if (owner.IsEqual(battleCardRealTargetInformation.SkillOwner))
|
||||
{
|
||||
List<int> result = battleCardRealTargetInformation.DequeueFirstTargetInfoAndCreateTokenIdList(owner, tokenType);
|
||||
if (!battleCardRealTargetInformation.HasAnyTarget)
|
||||
{
|
||||
RealTargetInformationList.Remove(battleCardRealTargetInformation);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetLatestActionSimulationParameter()
|
||||
{
|
||||
IsLatestAction = true;
|
||||
}
|
||||
|
||||
public void SetLatestActionSimulationParameterFromPreAction(AISituationInfo preAction)
|
||||
{
|
||||
IsLatestAction = preAction.IsLatestAction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AISituationTriggerInformation
|
||||
{
|
||||
public enum TriggerType
|
||||
{
|
||||
Evolver,
|
||||
Damage,
|
||||
Banish,
|
||||
Bounce,
|
||||
Leave,
|
||||
Summon,
|
||||
WhenPlay,
|
||||
Undefined
|
||||
}
|
||||
|
||||
public AIVirtualCard TriggerCard { get; private set; }
|
||||
|
||||
public TriggerType Type { get; private set; }
|
||||
|
||||
public AISituationTriggerInformation()
|
||||
{
|
||||
Type = TriggerType.Undefined;
|
||||
}
|
||||
|
||||
public AISituationTriggerInformation(AIVirtualCard trigger, TriggerType type)
|
||||
{
|
||||
Type = type;
|
||||
TriggerCard = trigger;
|
||||
}
|
||||
|
||||
public bool IsTriggerCard(AIVirtualCard card)
|
||||
{
|
||||
if (TriggerCard == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return TriggerCard.IsSameCard(card);
|
||||
}
|
||||
|
||||
public bool IsTriggerCardAndTriggerType(AIVirtualCard card, TriggerType type)
|
||||
{
|
||||
if (type != Type || TriggerCard == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return TriggerCard.IsSameCard(card);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISkillProcessInfoCollection
|
||||
{
|
||||
private Queue<AISkillProcessInformation> _processQueue;
|
||||
|
||||
private List<AISkillProcessInformation> _tempPreprocessList;
|
||||
|
||||
public AISkillProcessInfoCollection()
|
||||
{
|
||||
_processQueue = new Queue<AISkillProcessInformation>();
|
||||
}
|
||||
|
||||
public void RegisterProcess(AISkillProcessInformation process)
|
||||
{
|
||||
_processQueue.Enqueue(process);
|
||||
}
|
||||
|
||||
public void RegisterProcess(List<AISkillProcessInformation> processList)
|
||||
{
|
||||
if (processList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < processList.Count; i++)
|
||||
{
|
||||
if (processList[i] != null)
|
||||
{
|
||||
_processQueue.Enqueue(processList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterPreprocessProcessInfo(AISkillProcessInformation process)
|
||||
{
|
||||
_tempPreprocessList = AIParamQuery.AddElementToList(process, _tempPreprocessList, isBlockDuplicate: true);
|
||||
}
|
||||
|
||||
public void CombinePreprocessToProcessQueue()
|
||||
{
|
||||
if (_tempPreprocessList != null && _tempPreprocessList.Count > 0)
|
||||
{
|
||||
RegisterProcess(_tempPreprocessList);
|
||||
_tempPreprocessList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearTempPreprocessList()
|
||||
{
|
||||
if (_tempPreprocessList != null)
|
||||
{
|
||||
_tempPreprocessList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void ExecuteAllProcess(AISituationInfo situation)
|
||||
{
|
||||
while (_processQueue.Count > 0)
|
||||
{
|
||||
_processQueue.Dequeue().ExecuteAllAction(situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cute;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISkillProcessInformation
|
||||
{
|
||||
private List<Action> _executingAction;
|
||||
|
||||
public AISituationTriggerInformation TriggerInfo { get; private set; }
|
||||
|
||||
public AIOwnSkillProcessRecord OwnProcessRecord { get; private set; }
|
||||
|
||||
public AISkillProcessInformation(AISituationTriggerInformation triggerInfo)
|
||||
{
|
||||
TriggerInfo = triggerInfo;
|
||||
OwnProcessRecord = new AIOwnSkillProcessRecord();
|
||||
}
|
||||
|
||||
public void AddExecutingAction(Action action)
|
||||
{
|
||||
_executingAction = AIParamQuery.AddElementToList(action, _executingAction);
|
||||
}
|
||||
|
||||
public void ExecuteAllAction(AISituationInfo situation)
|
||||
{
|
||||
if (_executingAction != null && _executingAction.Count > 0)
|
||||
{
|
||||
situation.SetExecutingSkillProcess(this);
|
||||
for (int i = 0; i < _executingAction.Count; i++)
|
||||
{
|
||||
_executingAction[i].Call();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
SVSim.BattleEngine/Engine/Wizard/AIStyleData.cs
Normal file
99
SVSim.BattleEngine/Engine/Wizard/AIStyleData.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIStyleData
|
||||
{
|
||||
private List<AICategory> categoryFilter;
|
||||
|
||||
private Dictionary<AIStyleKey, List<AIPolicyData>> policyDic = new Dictionary<AIStyleKey, List<AIPolicyData>>();
|
||||
|
||||
public AIStyleData()
|
||||
{
|
||||
}
|
||||
|
||||
public AIStyleData(List<AICategory> filter)
|
||||
{
|
||||
categoryFilter = filter;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
categoryFilter = null;
|
||||
policyDic.Clear();
|
||||
}
|
||||
|
||||
public void CreateFromAsset(List<AIPolicyDataAsset> assetList)
|
||||
{
|
||||
foreach (AIPolicyDataAsset asset in assetList)
|
||||
{
|
||||
AIPolicyData aIPolicyData = new AIPolicyData(asset);
|
||||
AIStyleKey key = new AIStyleKey(aIPolicyData.Category, aIPolicyData.PolicyType);
|
||||
MixInPolicy(key, aIPolicyData);
|
||||
}
|
||||
}
|
||||
|
||||
public List<AIPolicyData> ConvertToPolicyList()
|
||||
{
|
||||
List<AIPolicyData> list = new List<AIPolicyData>();
|
||||
foreach (KeyValuePair<AIStyleKey, List<AIPolicyData>> item in policyDic)
|
||||
{
|
||||
foreach (AIPolicyData item2 in item.Value)
|
||||
{
|
||||
list.Add(item2);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool MixInPolicy(AIStyleKey key, AIPolicyData value)
|
||||
{
|
||||
if (categoryFilter != null && !categoryFilter.Any((AICategory c) => c == key.category))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (policyDic.ContainsKey(key))
|
||||
{
|
||||
List<AIPolicyData> list = policyDic[key];
|
||||
if (list == null)
|
||||
{
|
||||
list = new List<AIPolicyData>();
|
||||
list.Add(value);
|
||||
return true;
|
||||
}
|
||||
int priority = list[0].Priority;
|
||||
if (value.Priority > priority)
|
||||
{
|
||||
list.Clear();
|
||||
list.Add(value);
|
||||
return true;
|
||||
}
|
||||
if (value.Priority == priority)
|
||||
{
|
||||
list.Add(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
List<AIPolicyData> list2 = new List<AIPolicyData>();
|
||||
list2.Add(value);
|
||||
policyDic.Add(key, list2);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void MixInStyle(AIStyleData addStyle)
|
||||
{
|
||||
foreach (KeyValuePair<AIStyleKey, List<AIPolicyData>> pair in addStyle.policyDic)
|
||||
{
|
||||
if (pair.Value == null || (categoryFilter != null && !categoryFilter.Any((AICategory c) => c == pair.Key.category)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (AIPolicyData item in pair.Value)
|
||||
{
|
||||
MixInPolicy(pair.Key, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
SVSim.BattleEngine/Engine/Wizard/AIStyleFileNameList.cs
Normal file
37
SVSim.BattleEngine/Engine/Wizard/AIStyleFileNameList.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIStyleFileNameList
|
||||
{
|
||||
private const int STYLE_ID_INDEX = 0;
|
||||
|
||||
private const int FILE_NAME_INDEX = 1;
|
||||
|
||||
private readonly Dictionary<int, string> _dataTable = new Dictionary<int, string>();
|
||||
|
||||
public AIStyleFileNameList(List<string[]> csvData)
|
||||
{
|
||||
foreach (string[] csvDatum in csvData)
|
||||
{
|
||||
int key = int.Parse(csvDatum[0]);
|
||||
string value = csvDatum[1];
|
||||
_dataTable.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFileName(int id)
|
||||
{
|
||||
if (_dataTable.ContainsKey(id))
|
||||
{
|
||||
return _dataTable[id];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public List<string> GetFileNameList()
|
||||
{
|
||||
return _dataTable.Values.ToList();
|
||||
}
|
||||
}
|
||||
38
SVSim.BattleEngine/Engine/Wizard/AIStyleKey.cs
Normal file
38
SVSim.BattleEngine/Engine/Wizard/AIStyleKey.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIStyleKey
|
||||
{
|
||||
public AICategory category;
|
||||
|
||||
public AIPolicyType policy;
|
||||
|
||||
public AIStyleKey(AICategory _category, AIPolicyType _policy)
|
||||
{
|
||||
category = _category;
|
||||
policy = _policy;
|
||||
}
|
||||
|
||||
public static bool operator ==(AIStyleKey lhs, AIStyleKey rhs)
|
||||
{
|
||||
if (lhs.category == rhs.category)
|
||||
{
|
||||
return lhs.policy == rhs.policy;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator !=(AIStyleKey lhs, AIStyleKey rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
248
SVSim.BattleEngine/Engine/Wizard/AIStyleQuery.cs
Normal file
248
SVSim.BattleEngine/Engine/Wizard/AIStyleQuery.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIStyleQuery
|
||||
{
|
||||
private EnemyAI _enemyAI;
|
||||
|
||||
private AIStyleData _deckStyle;
|
||||
|
||||
private AIStyleData _curStyle;
|
||||
|
||||
private List<AIPolicyData> _curPolicies;
|
||||
|
||||
private List<AIPolicyData> _attachedPolicies;
|
||||
|
||||
private AIPolicyCollectionContainer _policyCollections;
|
||||
|
||||
public AIStyleQuery(EnemyAI ai, AIParamQuery _paramQuery)
|
||||
{
|
||||
_enemyAI = ai;
|
||||
_curStyle = new AIStyleData();
|
||||
_curPolicies = new List<AIPolicyData>();
|
||||
}
|
||||
|
||||
public void SetDeckStyle(AIStyleData _style)
|
||||
{
|
||||
_deckStyle = _style;
|
||||
}
|
||||
|
||||
public void UpdateStyle()
|
||||
{
|
||||
AIDataLibrary aIDataLibrary = GameMgr.GetIns().GetDataMgr().m_AIDataLibrary;
|
||||
_curStyle = aIDataLibrary.CreateStyle(GameMgr.GetIns().GetDataMgr().GetPlayerClassId(), _deckStyle);
|
||||
_curPolicies = _curStyle.ConvertToPolicyList();
|
||||
_policyCollections = new AIPolicyCollectionContainer();
|
||||
_policyCollections.InitializeAllCollections(_curPolicies);
|
||||
if (_attachedPolicies != null)
|
||||
{
|
||||
_policyCollections.InitializeAllCollections(_attachedPolicies);
|
||||
}
|
||||
InitializeReferenceIdTable();
|
||||
InitializeReferenceTribeTable();
|
||||
}
|
||||
|
||||
public void ExecuteAttachStyle(AIPolicyData data)
|
||||
{
|
||||
if (_attachedPolicies == null)
|
||||
{
|
||||
_attachedPolicies = new List<AIPolicyData>();
|
||||
}
|
||||
_attachedPolicies.Add(data);
|
||||
_policyCollections.RegisterNewPolicy(data);
|
||||
}
|
||||
|
||||
public void RemoveAllAttachedStyle()
|
||||
{
|
||||
if (_attachedPolicies != null)
|
||||
{
|
||||
_policyCollections.RemoveAttachedPolicies(_attachedPolicies);
|
||||
_attachedPolicies.Clear();
|
||||
_attachedPolicies = null;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetEpValue(AISituationInfo situation, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.EpValue))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.EpValue) as EpValuePolicyCollection).GetEpValue(situation, playPtn);
|
||||
}
|
||||
|
||||
public float GetUnitRate(AIVirtualField field, AIVirtualCard card, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.ModUnitRate))
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.ModUnitRate) as ModUnitRatePolicyCollection).GetUnitRate(card, field, playPtn);
|
||||
}
|
||||
|
||||
public float GetUnitBonus(AIVirtualField field, AIVirtualCard card, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.UnitBonus))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.UnitBonus) as UnitBonusPolicyCollection).GetUnitBonus(card, field, playPtn);
|
||||
}
|
||||
|
||||
public float GetPlayptnBonus(AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.PlayptnBonus))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.PlayptnBonus) as PlayptnBonusPolicyCollection).GetPlayptnBonus(field, playPtn);
|
||||
}
|
||||
|
||||
public float GetAllyPlayBonus(AIVirtualCard playCard, List<int> playPtn, AISituationInfo situation, ref float currentUseMinValue)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.AllyPlayBonus))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.AllyPlayBonus) as AllyPlayBonusPolicyCollection).GetAllyPlayBonus(playCard, playPtn, situation, ref currentUseMinValue);
|
||||
}
|
||||
|
||||
public float GetAllyPlayBonusRate(AIVirtualCard playCard, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.AllyPlayBonusRate))
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.AllyPlayBonusRate) as AllyPlayBonusRatePolicyCollection).GetAllyPlayBonusRate(playCard, playPtn, situation);
|
||||
}
|
||||
|
||||
public bool IsPlayBreak(AIVirtualCard card, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.PlayBreak))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.PlayBreak) as PlayBreakPolicyCollection).IsPlayBreak(card, playPtn, situation);
|
||||
}
|
||||
|
||||
public float GetBarrierBonus(AIVirtualCard card)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.BarrierBonus))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.BarrierBonus) as BarrierBonusPolicyCollection).GetBarrierBonus(card);
|
||||
}
|
||||
|
||||
public bool IsDisableLethalCheck(AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.DisableLethalCheck))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.DisableLethalCheck) as DisableLethalCheckPolicyCollection).IsDisableLethalCheck(field, playPtn);
|
||||
}
|
||||
|
||||
public float GetDelayTurnEndTime(AIVirtualCard owner, List<int> playPtn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.DelayTurnEndTime))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.DelayTurnEndTime) as AIDelayTurnEndTimePolicyCollection).GetDelayTime(owner, playPtn);
|
||||
}
|
||||
|
||||
public int GetEmoteOnTurnEnd(bool isAllyTurn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.EmoOnTurnEnd))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.EmoOnTurnEnd) as EmoOnTurnEndPolicyCollection).GetEmoOnTurnEnd(_enemyAI.CurrentVirtualField, isAllyTurn);
|
||||
}
|
||||
|
||||
public int GetEmoteOnTurnStart(bool isAllyTurn, AIVirtualField field)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.EmoOnTurnStart))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.EmoOnTurnStart) as EmoOnTurnStartPolicyCollection).GetEmoOnTurnStart(field, isAllyTurn);
|
||||
}
|
||||
|
||||
public int GetEmoteOnLeaderDamaged(AIVirtualField field)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.EmoOnLeaderDamaged))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.EmoOnLeaderDamaged) as EmoOnLeaderDamagedPolicyCollection).GetEmoOnLeaderDamaged(field);
|
||||
}
|
||||
|
||||
public int GetPlayerEmoteOnTurnEnd(bool isPlayerTurn)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.PlayerEmoOnTurnEnd))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.PlayerEmoOnTurnEnd) as PlayerEmoOnTurnEndPolicyCollection).GetPlayerEmoOnTurnEnd(_enemyAI.CurrentVirtualField, isPlayerTurn);
|
||||
}
|
||||
|
||||
public int GetPlayerEmoteOnTurnStart(AIVirtualField field)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.PlayerEmoOnTurnStart))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.PlayerEmoOnTurnStart) as PlayerEmoOnTurnStartPolicyCollection).GetPlayerEmoOnTurnStart(field);
|
||||
}
|
||||
|
||||
public int GetPlayerEmoteOnLeaderDamaged(AIVirtualField field)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.PlayerEmoOnLeaderDamaged))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.PlayerEmoOnLeaderDamaged) as PlayerEmoOnLeaderDamagedPolicyCollection).GetPlayerEmoOnLeaderDamaged(field);
|
||||
}
|
||||
|
||||
private void InitializeReferenceIdTable()
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.SetReferenceId))
|
||||
{
|
||||
_enemyAI.ReferenceIdTable = new Dictionary<int, int>();
|
||||
return;
|
||||
}
|
||||
SetReferenceIdPolicyCollection setReferenceIdPolicyCollection = _policyCollections.GetPolicyCollection(AIPolicyType.SetReferenceId) as SetReferenceIdPolicyCollection;
|
||||
_enemyAI.ReferenceIdTable = setReferenceIdPolicyCollection.CreateReferenceIdTable();
|
||||
}
|
||||
|
||||
private void InitializeReferenceTribeTable()
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.SetReferenceTribe))
|
||||
{
|
||||
_enemyAI.ReferenceTribeTable = new Dictionary<string, List<int>>();
|
||||
return;
|
||||
}
|
||||
SetReferenceTribePolicyCollection setReferenceTribePolicyCollection = _policyCollections.GetPolicyCollection(AIPolicyType.SetReferenceTribe) as SetReferenceTribePolicyCollection;
|
||||
_enemyAI.ReferenceTribeTable = setReferenceTribePolicyCollection.CreateReferenceTribeTable();
|
||||
}
|
||||
|
||||
public float GetFirstMoveBonus(AIVirtualCard playCard, List<AIVirtualActionInfo> moves)
|
||||
{
|
||||
if (!_policyCollections.HasPolicy(AIPolicyType.MoveFirstBonus))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return (_policyCollections.GetPolicyCollection(AIPolicyType.MoveFirstBonus) as MoveFirstBonusPolicyCollection).GetMoveFirstBonus(playCard, playCard.SelfField, moves);
|
||||
}
|
||||
|
||||
public void ExecuteGameStartAttachTag(AIVirtualField field)
|
||||
{
|
||||
if (_policyCollections.HasPolicy(AIPolicyType.GameStartAttachTag))
|
||||
{
|
||||
(_policyCollections.GetPolicyCollection(AIPolicyType.GameStartAttachTag) as GameStartAttachTagPolicyCollection).ExecuteAttachTag(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
SVSim.BattleEngine/Engine/Wizard/AISummonedCardContainer.cs
Normal file
115
SVSim.BattleEngine/Engine/Wizard/AISummonedCardContainer.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AISummonedCardContainer
|
||||
{
|
||||
private class SummonedCardListSet
|
||||
{
|
||||
public List<AIVirtualCard> TurnSummonedCards { get; private set; }
|
||||
|
||||
public List<AIVirtualCard> GameSummonedCards { get; private set; }
|
||||
|
||||
public SummonedCardListSet()
|
||||
{
|
||||
TurnSummonedCards = new List<AIVirtualCard>();
|
||||
GameSummonedCards = new List<AIVirtualCard>();
|
||||
}
|
||||
|
||||
private SummonedCardListSet(SummonedCardListSet clone)
|
||||
{
|
||||
TurnSummonedCards = new List<AIVirtualCard>(clone.TurnSummonedCards);
|
||||
GameSummonedCards = new List<AIVirtualCard>(clone.GameSummonedCards);
|
||||
}
|
||||
|
||||
public SummonedCardListSet Clone()
|
||||
{
|
||||
return new SummonedCardListSet(this);
|
||||
}
|
||||
|
||||
public void AddSummonedCard(AIVirtualCard card)
|
||||
{
|
||||
AddTurnSummonedCard(card);
|
||||
AddGameSummonedCard(card);
|
||||
}
|
||||
|
||||
public void AddTurnSummonedCard(AIVirtualCard card)
|
||||
{
|
||||
TurnSummonedCards.Add(card);
|
||||
}
|
||||
|
||||
private void AddGameSummonedCard(AIVirtualCard card)
|
||||
{
|
||||
GameSummonedCards.Add(card);
|
||||
}
|
||||
|
||||
public void LoadListSet(AIVirtualField field, BattlePlayerBase player)
|
||||
{
|
||||
BattleManagerBase ins = BattleManagerBase.GetIns();
|
||||
int currentTurn = ins.CurrentTurn;
|
||||
bool isSelfTurn = ins.BattlePlayer.IsSelfTurn;
|
||||
for (int i = 0; i < player.GameSummonCards.Count; i++)
|
||||
{
|
||||
BattlePlayerBase.TurnAndCard turnAndCard = player.GameSummonCards[i];
|
||||
SummonedVirtualCard card = new SummonedVirtualCard(turnAndCard.Card as BattleCardBase, field);
|
||||
AddGameSummonedCard(card);
|
||||
if (turnAndCard.Turn == currentTurn && turnAndCard.IsSelfTurn == isSelfTurn)
|
||||
{
|
||||
AddTurnSummonedCard(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SummonedCardListSet _allySummonedListSet = new SummonedCardListSet();
|
||||
|
||||
private SummonedCardListSet _enemySummonedListSet = new SummonedCardListSet();
|
||||
|
||||
public int AllyTurnSummonedListCount => _allySummonedListSet.TurnSummonedCards.Count;
|
||||
|
||||
public AISummonedCardContainer()
|
||||
{
|
||||
}
|
||||
|
||||
private AISummonedCardContainer(AISummonedCardContainer clone)
|
||||
{
|
||||
_allySummonedListSet = clone._allySummonedListSet.Clone();
|
||||
_enemySummonedListSet = clone._enemySummonedListSet.Clone();
|
||||
}
|
||||
|
||||
public AISummonedCardContainer Clone()
|
||||
{
|
||||
return new AISummonedCardContainer(this);
|
||||
}
|
||||
|
||||
public void LoadSummonedCardList(AIVirtualField field, BattlePlayerBase ally, BattlePlayerBase enemy)
|
||||
{
|
||||
_allySummonedListSet.LoadListSet(field, ally);
|
||||
_enemySummonedListSet.LoadListSet(field, enemy);
|
||||
}
|
||||
|
||||
public List<AIVirtualCard> GetSummonedList(bool isAlly, bool isTurnList)
|
||||
{
|
||||
SummonedCardListSet summonedCardListSet = (isAlly ? _allySummonedListSet : _enemySummonedListSet);
|
||||
if (!isTurnList)
|
||||
{
|
||||
return summonedCardListSet.GameSummonedCards;
|
||||
}
|
||||
return summonedCardListSet.TurnSummonedCards;
|
||||
}
|
||||
|
||||
public void AddSummonedCard(AIVirtualCard card)
|
||||
{
|
||||
(card.IsAlly ? _allySummonedListSet : _enemySummonedListSet).AddSummonedCard(card);
|
||||
}
|
||||
|
||||
public void RollBackSummonedCard(int beforeTurnSummonedCount)
|
||||
{
|
||||
int num = _allySummonedListSet.TurnSummonedCards.Count - beforeTurnSummonedCount;
|
||||
if (0 < num)
|
||||
{
|
||||
_allySummonedListSet.TurnSummonedCards.RemoveRange(beforeTurnSummonedCount, num);
|
||||
_allySummonedListSet.GameSummonedCards.RemoveRange(beforeTurnSummonedCount, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
665
SVSim.BattleEngine/Engine/Wizard/AITagCollectionContainer.cs
Normal file
665
SVSim.BattleEngine/Engine/Wizard/AITagCollectionContainer.cs
Normal file
@@ -0,0 +1,665 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AITagCollectionContainer
|
||||
{
|
||||
protected List<AIPlayTagType> _holdingTagTypes;
|
||||
|
||||
protected List<TagCollectionType> _holdingTagCollectionTypes;
|
||||
|
||||
private static ulong[] PRIME_NUMBERS_FOR_HASH_CALCULATION = new ulong[20]
|
||||
{
|
||||
23uL, 479uL, 811uL, 1447uL, 3541uL, 383uL, 281uL, 733uL, 71uL, 1201uL,
|
||||
2293uL, 991uL, 59uL, 1931uL, 251uL, 673uL, 1613uL, 12491uL, 5uL, 2699uL
|
||||
};
|
||||
|
||||
private readonly AIPlayTagType[] DISABLED_TAG_TYPES_INPLAY = new AIPlayTagType[96]
|
||||
{
|
||||
AIPlayTagType.HandPlus,
|
||||
AIPlayTagType.CostBonus,
|
||||
AIPlayTagType.Priority,
|
||||
AIPlayTagType.PlayLimit,
|
||||
AIPlayTagType.PlayPlus,
|
||||
AIPlayTagType.PlayBonus,
|
||||
AIPlayTagType.FanfareBonus,
|
||||
AIPlayTagType.EmoteOnPlay,
|
||||
AIPlayTagType.MulliganKeep,
|
||||
AIPlayTagType.MulliganChange,
|
||||
AIPlayTagType.FanfareToken,
|
||||
AIPlayTagType.PlayToken,
|
||||
AIPlayTagType.AddCardToPlayoutPlayPtn,
|
||||
AIPlayTagType.PlayoutNextTurn,
|
||||
AIPlayTagType.PlayDraw,
|
||||
AIPlayTagType.PlayReanimate,
|
||||
AIPlayTagType.Fusion,
|
||||
AIPlayTagType.HandBonus,
|
||||
AIPlayTagType.FusionBonus,
|
||||
AIPlayTagType.FusionDraw,
|
||||
AIPlayTagType.CondChoice,
|
||||
AIPlayTagType.PlayDestroy,
|
||||
AIPlayTagType.PlayDamage,
|
||||
AIPlayTagType.PlayHeal,
|
||||
AIPlayTagType.PlayBounce,
|
||||
AIPlayTagType.PlayBanish,
|
||||
AIPlayTagType.FanfareBanish,
|
||||
AIPlayTagType.FanfareBounce,
|
||||
AIPlayTagType.FanfareDamage,
|
||||
AIPlayTagType.PlayBuff,
|
||||
AIPlayTagType.FanfareBuff,
|
||||
AIPlayTagType.PlaySetMaxStatus,
|
||||
AIPlayTagType.FanfareSetMaxStatus,
|
||||
AIPlayTagType.PlaySetLeaderMaxLife,
|
||||
AIPlayTagType.FanfareDestroy,
|
||||
AIPlayTagType.FanfareSpellboost,
|
||||
AIPlayTagType.PlaySpellboost,
|
||||
AIPlayTagType.FanfareAddCemetery,
|
||||
AIPlayTagType.PlayAddCemetery,
|
||||
AIPlayTagType.FanfareHeal,
|
||||
AIPlayTagType.PlaySubtractCountdown,
|
||||
AIPlayTagType.FanfareSubtractCountdown,
|
||||
AIPlayTagType.PlayBanAttack,
|
||||
AIPlayTagType.FanfareBanAttack,
|
||||
AIPlayTagType.PlayIgnoreGuard,
|
||||
AIPlayTagType.FanfareIgnoreGuard,
|
||||
AIPlayTagType.PlayMetamorphose,
|
||||
AIPlayTagType.FanfareMetamorphose,
|
||||
AIPlayTagType.PlayHandMetamorphose,
|
||||
AIPlayTagType.FanfareHandMetamorphose,
|
||||
AIPlayTagType.FanfareRecoverAttackableCount,
|
||||
AIPlayTagType.FanfareSneak,
|
||||
AIPlayTagType.PlaySneak,
|
||||
AIPlayTagType.FanfareQuick,
|
||||
AIPlayTagType.PlayQuick,
|
||||
AIPlayTagType.FanfareRush,
|
||||
AIPlayTagType.PlayRush,
|
||||
AIPlayTagType.FanfareGuard,
|
||||
AIPlayTagType.PlayGuard,
|
||||
AIPlayTagType.FanfareKiller,
|
||||
AIPlayTagType.PlayKiller,
|
||||
AIPlayTagType.FanfareDrain,
|
||||
AIPlayTagType.PlayDrain,
|
||||
AIPlayTagType.FanfareChangeClass,
|
||||
AIPlayTagType.PlayChangeClass,
|
||||
AIPlayTagType.FanfareChangeTribe,
|
||||
AIPlayTagType.PlayChangeTribe,
|
||||
AIPlayTagType.FanfareUntouchable,
|
||||
AIPlayTagType.PlayUntouchable,
|
||||
AIPlayTagType.FanfareSummonHandCard,
|
||||
AIPlayTagType.PlaySummonHandCard,
|
||||
AIPlayTagType.FanfareHandBuff,
|
||||
AIPlayTagType.PlayHandBuff,
|
||||
AIPlayTagType.FanfareForceTargeting,
|
||||
AIPlayTagType.PlayChangeCost,
|
||||
AIPlayTagType.FanfareChangeCost,
|
||||
AIPlayTagType.PlaySelect,
|
||||
AIPlayTagType.FanfareSelect,
|
||||
AIPlayTagType.PlayHandSelect,
|
||||
AIPlayTagType.FanfareHandSelect,
|
||||
AIPlayTagType.PlayNotBeAttacked,
|
||||
AIPlayTagType.FanfareNotBeAttacked,
|
||||
AIPlayTagType.PlayAttackableCount,
|
||||
AIPlayTagType.FanfareAttackableCount,
|
||||
AIPlayTagType.PlayRemoveSkill,
|
||||
AIPlayTagType.FanfareRemoveSkill,
|
||||
AIPlayTagType.PlayModifyConsumeEp,
|
||||
AIPlayTagType.FanfareModifyConsumeEp,
|
||||
AIPlayTagType.PlayEvo,
|
||||
AIPlayTagType.FanfareEvo,
|
||||
AIPlayTagType.PlayBonusInSimulation,
|
||||
AIPlayTagType.FanfareBonusInSimulation,
|
||||
AIPlayTagType.FanfareRemoveGuard,
|
||||
AIPlayTagType.FusionMetamorphose,
|
||||
AIPlayTagType.PlayAddDeck,
|
||||
AIPlayTagType.FanfareAddDeck
|
||||
};
|
||||
|
||||
public List<TagCollectionWithTypeBase> TagDictionary { get; protected set; }
|
||||
|
||||
public AIAttachedTagCollection AttachedTags { get; private set; }
|
||||
|
||||
public AIRemovedTagCollection RemovedTagCollection { get; private set; }
|
||||
|
||||
public List<int> ReferringOtherInplayIds { get; private set; }
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TagDictionary != null)
|
||||
{
|
||||
return TagDictionary.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public PuppetAttackTagCollection PuppetAttackTags => GetTagCollection<PuppetAttackTagCollection>(TagCollectionType.PuppetAttack);
|
||||
|
||||
public DamagedTagCollection DamagedTags => GetTagCollection<DamagedTagCollection>(TagCollectionType.WhenDamaged);
|
||||
|
||||
public OtherDamagedTagCollection OtherDamagedTags => GetTagCollection<OtherDamagedTagCollection>(TagCollectionType.WhenOtherDamaged);
|
||||
|
||||
public AttackTagCollection AttackTags => GetTagCollection<AttackTagCollection>(TagCollectionType.WhenAttack);
|
||||
|
||||
public OtherAttackTagCollection OtherAttackTags => GetTagCollection<OtherAttackTagCollection>(TagCollectionType.WhenOtherAttack);
|
||||
|
||||
public BreakTagCollection BreakTags => GetTagCollection<BreakTagCollection>(TagCollectionType.WhenBreak);
|
||||
|
||||
public AfterAttackTagCollection AfterAttackTags => GetTagCollection<AfterAttackTagCollection>(TagCollectionType.WhenAfterAttack);
|
||||
|
||||
public SummonTagCollection SummonTags => GetTagCollection<SummonTagCollection>(TagCollectionType.WhenSummon);
|
||||
|
||||
public OtherSummonTagCollection OtherSummonTags => GetTagCollection<OtherSummonTagCollection>(TagCollectionType.WhenOtherSummon);
|
||||
|
||||
public FanfareTagCollection FanfareTags => GetTagCollection<FanfareTagCollection>(TagCollectionType.Fanfare);
|
||||
|
||||
public PlayTagCollection PlayTags => GetTagCollection<PlayTagCollection>(TagCollectionType.Play);
|
||||
|
||||
public LastwordTagCollection LastwordTags => GetTagCollection<LastwordTagCollection>(TagCollectionType.Lastword);
|
||||
|
||||
public LeaveTagCollection LeaveTags => GetTagCollection<LeaveTagCollection>(TagCollectionType.WhenLeave);
|
||||
|
||||
public OtherLeaveTagCollection OtherLeaveTags => GetTagCollection<OtherLeaveTagCollection>(TagCollectionType.WhenOtherLeave);
|
||||
|
||||
public BounceTagCollection BounceTags => GetTagCollection<BounceTagCollection>(TagCollectionType.WhenBounce);
|
||||
|
||||
public TurnStartTagCollection TurnStartTags => GetTagCollection<TurnStartTagCollection>(TagCollectionType.WhenTurnStart);
|
||||
|
||||
public TurnEndTagCollection TurnEndTags => GetTagCollection<TurnEndTagCollection>(TagCollectionType.WhenTurnEnd);
|
||||
|
||||
public AfterClashTagCollection AfterClashTags => GetTagCollection<AfterClashTagCollection>(TagCollectionType.WhenAfterClash);
|
||||
|
||||
public EvoTagCollection EvoTags => GetTagCollection<EvoTagCollection>(TagCollectionType.WhenEvo);
|
||||
|
||||
public OtherEvoTagCollection OtherEvoTags => GetTagCollection<OtherEvoTagCollection>(TagCollectionType.WhenOtherEvo);
|
||||
|
||||
public SelfAndOtherEvoTagCollection SelfAndOtherEvoTags => GetTagCollection<SelfAndOtherEvoTagCollection>(TagCollectionType.WhenSelfAndOtherEvo);
|
||||
|
||||
public HealTagCollection HealTags => GetTagCollection<HealTagCollection>(TagCollectionType.WhenHeal);
|
||||
|
||||
public DiscardedTagCollection DiscardedTags => GetTagCollection<DiscardedTagCollection>(TagCollectionType.WhenDiscarded);
|
||||
|
||||
public AfterDiscardTagCollection AfterDiscardTags => GetTagCollection<AfterDiscardTagCollection>(TagCollectionType.WhenAfterDiscard);
|
||||
|
||||
public BuffTriggerTagCollection BuffTriggerTags => GetTagCollection<BuffTriggerTagCollection>(TagCollectionType.WhenBuff);
|
||||
|
||||
public BanishTagCollection BanishTags => GetTagCollection<BanishTagCollection>(TagCollectionType.WhenBanish);
|
||||
|
||||
public OtherBanishTagCollection OtherBanishTags => GetTagCollection<OtherBanishTagCollection>(TagCollectionType.WhenOtherBanish);
|
||||
|
||||
public GetOnTriggerTagCollection GetOnTriggerTags => GetTagCollection<GetOnTriggerTagCollection>(TagCollectionType.WhenGetOn);
|
||||
|
||||
public WhenGetOffTagCollection WhenGetOffTags => GetTagCollection<WhenGetOffTagCollection>(TagCollectionType.WhenGetOff);
|
||||
|
||||
public ActivateCountTagCollection ActivateCountTags => GetTagCollection<ActivateCountTagCollection>(TagCollectionType.ActivateCount);
|
||||
|
||||
public ClashBonusTagCollection ClashBonusTags => GetTagCollection<ClashBonusTagCollection>(TagCollectionType.ClashBonus);
|
||||
|
||||
public ReincarnationSimulationTagCollection ReincarnationSimulationTags => GetTagCollection<ReincarnationSimulationTagCollection>(TagCollectionType.Reincarnation);
|
||||
|
||||
public CantBeAttackedTagCollection CantBeAttackedTags => GetTagCollection<CantBeAttackedTagCollection>(TagCollectionType.CantBeAttacked);
|
||||
|
||||
public ChoiceTagCollection ChoiceTags => GetTagCollection<ChoiceTagCollection>(TagCollectionType.Choice);
|
||||
|
||||
public ChangeInplayTagCollection ChangeInplayTags => GetTagCollection<ChangeInplayTagCollection>(TagCollectionType.WhenChangeInplay);
|
||||
|
||||
public EvolveToOtherTagCollection EvolveToOtherTags => GetTagCollection<EvolveToOtherTagCollection>(TagCollectionType.EvolveToOther);
|
||||
|
||||
public OtherPlayTagCollection OtherPlayTags => GetTagCollection<OtherPlayTagCollection>(TagCollectionType.WhenOtherPlay);
|
||||
|
||||
public BuffBonusTagCollection BuffBonusTags => GetTagCollection<BuffBonusTagCollection>(TagCollectionType.BuffBonus);
|
||||
|
||||
public EvolvedResidentTagCollection EvolvedResidentTags => GetTagCollection<EvolvedResidentTagCollection>(TagCollectionType.EvolvedResident);
|
||||
|
||||
public GenerateTagCollection GenerateTags => GetTagCollection<GenerateTagCollection>(TagCollectionType.GenerateTag);
|
||||
|
||||
public BounceBonusTagCollection BounceBonusTags => GetTagCollection<BounceBonusTagCollection>(TagCollectionType.BounceBonus);
|
||||
|
||||
public PriorityTagCollection PriorityTags => GetTagCollection<PriorityTagCollection>(TagCollectionType.Priority);
|
||||
|
||||
public PlayBonusTagCollection PlayBonusTags => GetTagCollection<PlayBonusTagCollection>(TagCollectionType.PlayBonus);
|
||||
|
||||
public PlayBonusRateTagCollection PlayBonusRateTags => GetTagCollection<PlayBonusRateTagCollection>(TagCollectionType.PlayBonusRate);
|
||||
|
||||
public FanfareBonusTagCollection FanfareBonusTags => GetTagCollection<FanfareBonusTagCollection>(TagCollectionType.FanfareBonus);
|
||||
|
||||
public IgnoreFanfareBonusTagCollection IgnoreFanfareBonusTags => GetTagCollection<IgnoreFanfareBonusTagCollection>(TagCollectionType.IgnoreFanfareBonus);
|
||||
|
||||
public HandPlusTagCollection HandPlusTags => GetTagCollection<HandPlusTagCollection>(TagCollectionType.HandPlus);
|
||||
|
||||
public AllyPlayBonusTagCollection AllyPlayBonusTags => GetTagCollection<AllyPlayBonusTagCollection>(TagCollectionType.AllyPlayBonus);
|
||||
|
||||
public EnemyPlayBonusTagCollection EnemyPlayBonusTags => GetTagCollection<EnemyPlayBonusTagCollection>(TagCollectionType.EnemyPlayBonus);
|
||||
|
||||
public CostBonusTagCollection CostBonusTags => GetTagCollection<CostBonusTagCollection>(TagCollectionType.CostBonus);
|
||||
|
||||
public PlayDrawTagCollection PlayDrawTags => GetTagCollection<PlayDrawTagCollection>(TagCollectionType.PlayDraw);
|
||||
|
||||
public PlayLimitTagCollection PlayLimitTags => GetTagCollection<PlayLimitTagCollection>(TagCollectionType.PlayLimit);
|
||||
|
||||
public PlayPtnBonusTagCollection PlayptnBonusTags => GetTagCollection<PlayPtnBonusTagCollection>(TagCollectionType.PlayptnBonus);
|
||||
|
||||
public AttackBonusTagCollection AttackBonusTags => GetTagCollection<AttackBonusTagCollection>(TagCollectionType.AttackBonus);
|
||||
|
||||
public BattleBonusTagCollection BattleBonusTags => GetTagCollection<BattleBonusTagCollection>(TagCollectionType.BattleBonus);
|
||||
|
||||
public MemberBattleBonusTagCollection MemberBattleBonusTags => GetTagCollection<MemberBattleBonusTagCollection>(TagCollectionType.MemberBattleBonus);
|
||||
|
||||
public EnemyBattleBonusTagCollection EnemyBattleBonusTags => GetTagCollection<EnemyBattleBonusTagCollection>(TagCollectionType.EnemyBattleBonus);
|
||||
|
||||
public BattleBonusRateTagCollection BattleBonusRateTags => GetTagCollection<BattleBonusRateTagCollection>(TagCollectionType.BattleBonusRate);
|
||||
|
||||
public MemberBattleBonusRateTagCollection MemberBattleBonusRateTags => GetTagCollection<MemberBattleBonusRateTagCollection>(TagCollectionType.MemberBattleBonusRate);
|
||||
|
||||
public EnemyBattleBonusRateTagCollection EnemyBattleBonusRateTags => GetTagCollection<EnemyBattleBonusRateTagCollection>(TagCollectionType.EnemyBattleBonusRate);
|
||||
|
||||
public EvoBonusTagCollection EvoBonusTags => GetTagCollection<EvoBonusTagCollection>(TagCollectionType.EvoBonus);
|
||||
|
||||
public MemberEvoBonusTagCollection MemberEvoBonusTags => GetTagCollection<MemberEvoBonusTagCollection>(TagCollectionType.MemberEvoBonus);
|
||||
|
||||
public EnemyEvoBonusTagCollection EnemyEvoBonusTags => GetTagCollection<EnemyEvoBonusTagCollection>(TagCollectionType.EnemyEvoBonus);
|
||||
|
||||
public IgnoreBreakTagCollection IgnoreBreakTags => GetTagCollection<IgnoreBreakTagCollection>(TagCollectionType.IgnoreBreak);
|
||||
|
||||
public BreakBonusTagCollection BreakBonusTags => GetTagCollection<BreakBonusTagCollection>(TagCollectionType.BreakBonus);
|
||||
|
||||
public OtherBreakBonusTagCollection OtherBreakBonusTags => GetTagCollection<OtherBreakBonusTagCollection>(TagCollectionType.OtherBreakBonus);
|
||||
|
||||
public BanishBonusTagCollection BanishBonusTags => GetTagCollection<BanishBonusTagCollection>(TagCollectionType.BanishBonus);
|
||||
|
||||
public OtherBanishBonusTagCollection OtherBanishBonusTags => GetTagCollection<OtherBanishBonusTagCollection>(TagCollectionType.OtherBanishBonus);
|
||||
|
||||
public LeaveBonusTagCollection LeaveBonusTags => GetTagCollection<LeaveBonusTagCollection>(TagCollectionType.LeaveBonus);
|
||||
|
||||
public OtherLeaveBonusTagCollection OtherLeaveBonusTags => GetTagCollection<OtherLeaveBonusTagCollection>(TagCollectionType.OtherLeaveBonus);
|
||||
|
||||
public DiscardedBonusTagCollection DiscardedBonusTags => GetTagCollection<DiscardedBonusTagCollection>(TagCollectionType.DiscardedBonus);
|
||||
|
||||
public PreprocessTagCollection PreprocessTags => GetTagCollection<PreprocessTagCollection>(TagCollectionType.Preprocess);
|
||||
|
||||
public ReanimateBonusTagCollection ReanimateBonusTags => GetTagCollection<ReanimateBonusTagCollection>(TagCollectionType.ReanimateBonus);
|
||||
|
||||
public ReanimateEvoTagCollection ReanimateEvoTags => GetTagCollection<ReanimateEvoTagCollection>(TagCollectionType.ReanimateEvo);
|
||||
|
||||
public BreakFirstTagCollection BreakFirstTags => GetTagCollection<BreakFirstTagCollection>(TagCollectionType.BreakFirst);
|
||||
|
||||
public BreakLastTagCollection BreakLastTags => GetTagCollection<BreakLastTagCollection>(TagCollectionType.BreakLast);
|
||||
|
||||
public BreakBeforePlayTagCollection BreakBeforePlayTags => GetTagCollection<BreakBeforePlayTagCollection>(TagCollectionType.BreakBeforePlay);
|
||||
|
||||
public FusionTagCollection FusionTags => GetTagCollection<FusionTagCollection>(TagCollectionType.Fusion);
|
||||
|
||||
public FusionMetamorphoseTagCollection FusionMetamorphoseTags => GetTagCollection<FusionMetamorphoseTagCollection>(TagCollectionType.FusionMetamorphose);
|
||||
|
||||
public FirstEvoTagCollection FirstEvoTags => GetTagCollection<FirstEvoTagCollection>(TagCollectionType.FirstEvo);
|
||||
|
||||
public PlayPlusTagCollection PlayPlusTags => GetTagCollection<PlayPlusTagCollection>(TagCollectionType.PlayPlus);
|
||||
|
||||
public PlayoutBonusTagCollection PlayoutBonusTags => GetTagCollection<PlayoutBonusTagCollection>(TagCollectionType.PlayoutBonus);
|
||||
|
||||
public OtherPlayoutBonusTagCollection OtherPlayoutBonusTags => GetTagCollection<OtherPlayoutBonusTagCollection>(TagCollectionType.OtherPlayoutBonus);
|
||||
|
||||
public HandBonusTagCollection HandBonusTags => GetTagCollection<HandBonusTagCollection>(TagCollectionType.HandBonus);
|
||||
|
||||
public FusionBonusTagCollection FusionBonusTags => GetTagCollection<FusionBonusTagCollection>(TagCollectionType.FusionBonus);
|
||||
|
||||
public FusionDrawTagCollection FusionDrawTags => GetTagCollection<FusionDrawTagCollection>(TagCollectionType.FusionDraw);
|
||||
|
||||
public CondChoiceTagCollection CondChoiceTags => GetTagCollection<CondChoiceTagCollection>(TagCollectionType.CondChoice);
|
||||
|
||||
public AddCardToPlayoutPlayPtnTagCollection AddCardToPlayoutPlayPtnTags => GetTagCollection<AddCardToPlayoutPlayPtnTagCollection>(TagCollectionType.AddCardToPlayoutPlayPtn);
|
||||
|
||||
public NoInstantAttackTagCollection NoInstantAttackTags => GetTagCollection<NoInstantAttackTagCollection>(TagCollectionType.NoInstantAttack);
|
||||
|
||||
public EmoteTagCollection EmoteTags => GetTagCollection<EmoteTagCollection>(TagCollectionType.Emote);
|
||||
|
||||
public EvoHandPlusTagCollection EvoHandPlusTags => GetTagCollection<EvoHandPlusTagCollection>(TagCollectionType.EvoHandPlus);
|
||||
|
||||
public NoNormalEvoTagCollection NoNormalEvoTags => GetTagCollection<NoNormalEvoTagCollection>(TagCollectionType.NoNormalEvo);
|
||||
|
||||
public PlagueCityTagCollection PlagueCityTags => GetTagCollection<PlagueCityTagCollection>(TagCollectionType.PlagueCity);
|
||||
|
||||
public RemoveByDestroyTagCollection RemoveByDestroyTags => GetTagCollection<RemoveByDestroyTagCollection>(TagCollectionType.RemoveByDestroy);
|
||||
|
||||
public SetAITribeTagCollection SetAITribeTags => GetTagCollection<SetAITribeTagCollection>(TagCollectionType.SetAITribe);
|
||||
|
||||
public PlaySkipTagCollection PlaySkipTags => GetTagCollection<PlaySkipTagCollection>(TagCollectionType.PlaySkip);
|
||||
|
||||
public GiveSkillTagCollection GiveSkillTags => GetTagCollection<GiveSkillTagCollection>(TagCollectionType.GiveSkill);
|
||||
|
||||
public ForceImmediateAttackTagCollection ForceImmediateAttackTags => GetTagCollection<ForceImmediateAttackTagCollection>(TagCollectionType.ForceImmediateAttack);
|
||||
|
||||
public RemoveSkillTagCollection RemoveSkillTags => GetTagCollection<RemoveSkillTagCollection>(TagCollectionType.RemoveSkill);
|
||||
|
||||
public OneMoreLastwordTagCollection OneMoreLastwordTags => GetTagCollection<OneMoreLastwordTagCollection>(TagCollectionType.OneMoreLastword);
|
||||
|
||||
public NoSkipAttackTagCollection NoSkipAttackTags => GetTagCollection<NoSkipAttackTagCollection>(TagCollectionType.NoSkipAttack);
|
||||
|
||||
public ResonanceTagCollection ResonanceTags => GetTagCollection<ResonanceTagCollection>(TagCollectionType.WhenResonance);
|
||||
|
||||
public AttackByLifeTagCollection AttackByLifeTags => GetTagCollection<AttackByLifeTagCollection>(TagCollectionType.AttackByLife);
|
||||
|
||||
public FixedCostTagCollection FixedCostTags => GetTagCollection<FixedCostTagCollection>(TagCollectionType.FixedCost);
|
||||
|
||||
public ForceBerserkTagCollection ForceBerserkTags => GetTagCollection<ForceBerserkTagCollection>(TagCollectionType.ForceBerserk);
|
||||
|
||||
public GetOnTagCollection GetOnTags => GetTagCollection<GetOnTagCollection>(TagCollectionType.GetOn);
|
||||
|
||||
public ModifyHealTagCollection ModifyHealTags => GetTagCollection<ModifyHealTagCollection>(TagCollectionType.ModifyHeal);
|
||||
|
||||
public PlayptnBaseStatsRateTagCollection PlayptnBaseStatsRateTags => GetTagCollection<PlayptnBaseStatsRateTagCollection>(TagCollectionType.PlayptnBaseStatsRate);
|
||||
|
||||
public RallyCountPlusTagCollection RallyCountPlusTags => GetTagCollection<RallyCountPlusTagCollection>(TagCollectionType.RallyCountPlus);
|
||||
|
||||
public AttackableClassTagCollection AttackableClassTags => GetTagCollection<AttackableClassTagCollection>(TagCollectionType.AttackableClass);
|
||||
|
||||
public WhenNecromanceTagCollection NecromanceTags => GetTagCollection<WhenNecromanceTagCollection>(TagCollectionType.WhenNecromance);
|
||||
|
||||
public TargetTagCollection TargetTags => GetTagCollection<TargetTagCollection>(TagCollectionType.Target);
|
||||
|
||||
public IgnoreTargetTagCollection IgnoreTargetTags => GetTagCollection<IgnoreTargetTagCollection>(TagCollectionType.IgnoreTarget);
|
||||
|
||||
public PlayoutNextTurnTagCollection PlayoutNextTurnTags => GetTagCollection<PlayoutNextTurnTagCollection>(TagCollectionType.PlayoutNextTurn);
|
||||
|
||||
private T GetTagCollection<T>(TagCollectionType type) where T : TagCollection
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
TagCollection collection = TagDictionary[i].Collection;
|
||||
if (collection.Type == type)
|
||||
{
|
||||
return collection as T;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AITagCollectionContainer()
|
||||
{
|
||||
_holdingTagTypes = null;
|
||||
_holdingTagCollectionTypes = null;
|
||||
TagDictionary = null;
|
||||
AttachedTags = new AIAttachedTagCollection();
|
||||
RemovedTagCollection = new AIRemovedTagCollection();
|
||||
}
|
||||
|
||||
public AITagCollectionContainer(AITagCollectionContainer container, AIVirtualCard owner)
|
||||
{
|
||||
if (container.Count <= 0)
|
||||
{
|
||||
_holdingTagTypes = null;
|
||||
_holdingTagCollectionTypes = null;
|
||||
TagDictionary = null;
|
||||
AttachedTags = new AIAttachedTagCollection();
|
||||
RemovedTagCollection = new AIRemovedTagCollection();
|
||||
return;
|
||||
}
|
||||
_holdingTagTypes = new List<AIPlayTagType>();
|
||||
_holdingTagCollectionTypes = new List<TagCollectionType>();
|
||||
TagDictionary = new List<TagCollectionWithTypeBase>();
|
||||
for (int i = 0; i < container.Count; i++)
|
||||
{
|
||||
TagCollectionWithTypeBase tagCollectionWithTypeBase = container.TagDictionary[i];
|
||||
TagDictionary.Add(tagCollectionWithTypeBase.Clone());
|
||||
tagCollectionWithTypeBase.RegisterTypes(_holdingTagTypes);
|
||||
_holdingTagCollectionTypes.Add(tagCollectionWithTypeBase.Collection.Type);
|
||||
}
|
||||
AttachedTags = container.AttachedTags.Clone();
|
||||
RemovedTagCollection = container.RemovedTagCollection.Clone();
|
||||
CreateFixedUseCostListWhenInit(owner, owner.SelfField);
|
||||
}
|
||||
|
||||
public virtual void InitTags(AIVirtualCard owner, AIParamQuery query)
|
||||
{
|
||||
if (owner.IsCountdownAmulet)
|
||||
{
|
||||
AIPlayTag tag = AIPlayTagInitializingUtility.CreateTurnStartSubtractCountdownTagForCountdownAmulet();
|
||||
AddTag(tag, owner, null);
|
||||
}
|
||||
int tagCount = query.GetTagCount(owner);
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
{
|
||||
AIPlayTag tag2 = query.GetTag(owner, i);
|
||||
AddTag(tag2, owner, null);
|
||||
}
|
||||
CreateFixedUseCostListWhenInit(owner, owner.SelfField);
|
||||
}
|
||||
|
||||
protected void CreateFixedUseCostListWhenInit(AIVirtualCard owner, AIVirtualField field)
|
||||
{
|
||||
if (HasTagCollection(TagCollectionType.FixedCost))
|
||||
{
|
||||
FixedCostTags.CreateFixedUseCostLists(owner, field);
|
||||
}
|
||||
}
|
||||
|
||||
public TagCollectionWithTypeBase AddTag(AIPlayTag tag, AIVirtualCard owner, AISituationInfo situation)
|
||||
{
|
||||
if (_holdingTagTypes == null)
|
||||
{
|
||||
_holdingTagTypes = new List<AIPlayTagType>();
|
||||
}
|
||||
if (TagDictionary == null)
|
||||
{
|
||||
TagDictionary = new List<TagCollectionWithTypeBase>();
|
||||
}
|
||||
TagCollectionWithTypeBase ownerTagCollectionWithTypes = GetOwnerTagCollectionWithTypes(tag.Type);
|
||||
if (ownerTagCollectionWithTypes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ownerTagCollectionWithTypes.AddTag(tag);
|
||||
if (!_holdingTagTypes.Contains(tag.Type))
|
||||
{
|
||||
_holdingTagTypes.Add(tag.Type);
|
||||
}
|
||||
UpdateReferringOtherInplayIds(tag);
|
||||
ownerTagCollectionWithTypes?.Collection.ExecuteWhenAddTag(owner, owner.SelfField, tag, situation);
|
||||
return ownerTagCollectionWithTypes;
|
||||
}
|
||||
|
||||
public void RemoveOneTagWithUpdatingFieldCardList(AIVirtualCard owner, AIPlayTag removingTag, AIVirtualField field)
|
||||
{
|
||||
if (_holdingTagTypes == null || !_holdingTagTypes.Contains(removingTag.Type))
|
||||
{
|
||||
return;
|
||||
}
|
||||
TagCollectionWithTypeBase ownerTagCollectionWithTypes = GetOwnerTagCollectionWithTypes(removingTag.Type);
|
||||
if (ownerTagCollectionWithTypes.RemoveOneTag(owner, field, removingTag))
|
||||
{
|
||||
_holdingTagTypes.Remove(removingTag.Type);
|
||||
if (ownerTagCollectionWithTypes is TagCollectionWithSingleType || ownerTagCollectionWithTypes.IsEmpty())
|
||||
{
|
||||
TagDictionary.Remove(ownerTagCollectionWithTypes);
|
||||
_holdingTagCollectionTypes.Remove(ownerTagCollectionWithTypes.Collection.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAllTagWithUpdatingFieldCardList(AIVirtualCard owner, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
if (TagDictionary == null || Count <= 0)
|
||||
{
|
||||
if (AttachedTags != null)
|
||||
{
|
||||
AttachedTags.RemoveAllAttachedTagInformation(situation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int num = Count - 1; num >= 0; num--)
|
||||
{
|
||||
TagCollectionWithTypeBase tagCollectionWithTypeBase = TagDictionary[num];
|
||||
if (!tagCollectionWithTypeBase.IsUnderManagement(AIPlayTagType.PuppetAttack))
|
||||
{
|
||||
tagCollectionWithTypeBase.RemoveTypes(_holdingTagTypes);
|
||||
_holdingTagCollectionTypes.Remove(tagCollectionWithTypeBase.Collection.Type);
|
||||
tagCollectionWithTypeBase.RemoveAllTags(owner, field);
|
||||
TagDictionary.Remove(tagCollectionWithTypeBase);
|
||||
}
|
||||
}
|
||||
AttachedTags.RemoveAllAttachedTagInformation(situation);
|
||||
}
|
||||
|
||||
public void AttachTag(AIAttachedTagInformation info, AIVirtualCard owner, AISituationInfo situation)
|
||||
{
|
||||
AttachedTags.AddAttachedTagInformation(info);
|
||||
AddTag(info.Tag, owner, situation);
|
||||
owner.SelfField.CardListSet.TagClassificationWhenAttachTag(owner, info.Tag);
|
||||
}
|
||||
|
||||
public void CreateChoiceBraveTag(AIVirtualCard leader)
|
||||
{
|
||||
if (!leader.IsLeader || leader.IsAlly)
|
||||
{
|
||||
AIConsoleUtility.LogError("AITagCollectionContainer.CreateChoiceBraveTag() error!! Card is not leader!!!!!");
|
||||
return;
|
||||
}
|
||||
AIPlayTag aIPlayTag = new AIPlayTag();
|
||||
AIPlayTagAsset asset = new AIPlayTagAsset
|
||||
{
|
||||
Type = "choiceBrave",
|
||||
Arg = "",
|
||||
Condition = ""
|
||||
};
|
||||
aIPlayTag.InitFromTextAsset(asset);
|
||||
AIAttachedTagInformation info = new AIAttachedTagInformation(aIPlayTag, AIScriptTokenArgType.NONE, leader, leader);
|
||||
AttachTag(info, leader, null);
|
||||
}
|
||||
|
||||
private TagCollectionWithTypeBase GetOwnerTagCollectionWithTypes(AIPlayTagType type)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
TagCollectionWithTypeBase tagCollectionWithTypeBase = TagDictionary[i];
|
||||
if (tagCollectionWithTypeBase.IsUnderManagement(type))
|
||||
{
|
||||
return tagCollectionWithTypeBase;
|
||||
}
|
||||
}
|
||||
TagCollectionWithTypeBase tagCollectionWithTypeBase2 = TagCollectionWithTypeCreator.Create(type);
|
||||
if (tagCollectionWithTypeBase2 != null)
|
||||
{
|
||||
TagDictionary.Add(tagCollectionWithTypeBase2);
|
||||
_holdingTagCollectionTypes = AIParamQuery.AddElementToList(tagCollectionWithTypeBase2.Collection.Type, _holdingTagCollectionTypes, isBlockDuplicate: true);
|
||||
}
|
||||
return tagCollectionWithTypeBase2;
|
||||
}
|
||||
|
||||
public bool HasWhenPlayDestroyPlayPtnTags()
|
||||
{
|
||||
if (_holdingTagTypes == null || _holdingTagTypes.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!_holdingTagTypes.Contains(AIPlayTagType.PlaySummonHandCard))
|
||||
{
|
||||
return _holdingTagTypes.Contains(AIPlayTagType.FanfareSummonHandCard);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasTag(AIPlayTagType type)
|
||||
{
|
||||
if (_holdingTagTypes != null)
|
||||
{
|
||||
return _holdingTagTypes.Contains(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HasTagCollection(TagCollectionType type)
|
||||
{
|
||||
if (_holdingTagCollectionTypes != null)
|
||||
{
|
||||
return _holdingTagCollectionTypes.Contains(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HasAnyTag(AIPlayTagType[] typeArray)
|
||||
{
|
||||
if (_holdingTagTypes == null || _holdingTagTypes.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _holdingTagTypes.Count; i++)
|
||||
{
|
||||
AIPlayTagType value = _holdingTagTypes[i];
|
||||
if (Array.IndexOf(typeArray, value) >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateReferringOtherInplayIds(AIPlayTag tag)
|
||||
{
|
||||
if (Array.IndexOf(DISABLED_TAG_TYPES_INPLAY, tag.Type) >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<int> referringOtherInplayIds = tag.ArgumentExpressions.GetReferringOtherInplayIds();
|
||||
List<int> referringIds = tag.ConditionExpressions.ReferringIds;
|
||||
if (referringOtherInplayIds != null)
|
||||
{
|
||||
if (ReferringOtherInplayIds == null)
|
||||
{
|
||||
ReferringOtherInplayIds = new List<int>();
|
||||
}
|
||||
ReferringOtherInplayIds.AddRange(referringOtherInplayIds);
|
||||
}
|
||||
if (referringIds != null)
|
||||
{
|
||||
if (ReferringOtherInplayIds == null)
|
||||
{
|
||||
ReferringOtherInplayIds = new List<int>();
|
||||
}
|
||||
ReferringOtherInplayIds.AddRange(referringIds);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetHash(AIVirtualCard card)
|
||||
{
|
||||
ulong num = 0uL;
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
TagCollection collection = TagDictionary[i].Collection;
|
||||
for (int j = 0; j < collection.TagList.Count; j++)
|
||||
{
|
||||
AIPlayTag aIPlayTag = collection.TagList[j];
|
||||
if (!card.IsOnField || Array.IndexOf(DISABLED_TAG_TYPES_INPLAY, aIPlayTag.Type) < 0)
|
||||
{
|
||||
num += collection.TagList[j].Hash * PRIME_NUMBERS_FOR_HASH_CALCULATION[num2];
|
||||
num2 = ((num2 < PRIME_NUMBERS_FOR_HASH_CALCULATION.Length - 1) ? (num2 + 1) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public AITokenIdCollection GetAllRegisterTokenPoolInfo(AIVirtualCard owner)
|
||||
{
|
||||
if (TagDictionary == null || TagDictionary.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AITokenIdCollection aITokenIdCollection = null;
|
||||
for (int i = 0; i < TagDictionary.Count; i++)
|
||||
{
|
||||
TagCollection collection = TagDictionary[i].Collection;
|
||||
if (collection != null && collection.HasTag)
|
||||
{
|
||||
for (int j = 0; j < collection.TagList.Count; j++)
|
||||
{
|
||||
AITokenIdCollection allRegisterTokenPoolInfo = collection.TagList[j].ArgumentExpressions.GetAllRegisterTokenPoolInfo(owner);
|
||||
aITokenIdCollection = AITokenIdCollection.CombineTwoCollection(aITokenIdCollection, allRegisterTokenPoolInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return aITokenIdCollection;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user