feat(battle-engine): close the AI-simulation subsystem (verbatim)
Copied the 89 uncopied AI*SimulationUtility/extension files defining the AIVirtualCard/AIVirtualField extension methods; the compile loop then auto-closed the revealed type deps (~3049 files total, drift-clean). 10.0k -> 62 errors.
This commit is contained in:
55
SVSim.BattleEngine/Engine/Wizard/AIAccelerateUtility.cs
Normal file
55
SVSim.BattleEngine/Engine/Wizard/AIAccelerateUtility.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIAccelerateUtility
|
||||
{
|
||||
public static bool IsAccelerate(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (card == null || card.AccelerateCostList == null || !card.IsInHand)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (situation is AIVirtualActionInfo { ReservedPlayType: not PlaySimulationType.Undefined } aIVirtualActionInfo)
|
||||
{
|
||||
return aIVirtualActionInfo.ReservedPlayType == PlaySimulationType.Accelerate;
|
||||
}
|
||||
List<int> playPtn2 = (card.IsAlly ? playPtn : null);
|
||||
AIVariableResultContainer valResultContainer = field.AI.ValResultContainer;
|
||||
ulong hash = AIFunctionResultHashCalculator.GetHash(card, field, playPtn, null, 0uL);
|
||||
if (valResultContainer.GetContainsResultValue(AIScriptTokenVariableType.IS_ACCELERATE, hash, out var getResult))
|
||||
{
|
||||
return getResult == 1f;
|
||||
}
|
||||
bool flag = field.AI.PlayPtnRecorder.IsCardPlayingSimulationType(card, field, playPtn2, situation, PlaySimulationType.Accelerate);
|
||||
valResultContainer.CheckDuplicateAndAddRecord(AIScriptTokenVariableType.IS_ACCELERATE, hash, flag ? 1f : 0f, $"IsAccelerate(): Already hashed target and not equal value. CardName:[{card.CardName}] hash:[{hash}]");
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static int GetAccelerateCost(AIVirtualCard card, AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (card == null || card.AccelerateCostList == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
List<int> playPtn2 = (card.IsAlly ? playPtn : null);
|
||||
return field.AI.PlayPtnRecorder.GetCardPlaySimulationTypeCost(card, field, playPtn2, null, PlaySimulationType.Accelerate);
|
||||
}
|
||||
|
||||
public static int GetConditionPassedAccelerateId(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int usedCost)
|
||||
{
|
||||
if (card.AccelerateCostList == null || card.AccelerateCostList.Count <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < card.AccelerateCostList.Count; i++)
|
||||
{
|
||||
AIAccelerateInformation aIAccelerateInformation = card.AccelerateCostList[i];
|
||||
if (aIAccelerateInformation.Cost == usedCost && aIAccelerateInformation.CheckCondition(card, field, playPtn, situation))
|
||||
{
|
||||
return aIAccelerateInformation.CardId;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
176
SVSim.BattleEngine/Engine/Wizard/AIAttachTagSimulationUtility.cs
Normal file
176
SVSim.BattleEngine/Engine/Wizard/AIAttachTagSimulationUtility.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIAttachTagSimulationUtility
|
||||
{
|
||||
public static void SimulateAttachTagToAll(List<AIVirtualCard> targets, AIVirtualCard owner, AIPlayTag tag, AIScriptTokenArgType removeTiming, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!aIVirtualCard.IsDead && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
SimulateAttachTagToSingle(aIVirtualCard, owner, tag, removeTiming, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SimulateAttachTagToTarget(AISituationInfo situation, AIVirtualCard owner, AIScriptTokenArgType whichTarget, AIPlayTag tag, AIScriptTokenArgType removeTiming)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!aIVirtualCard.IsDead && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
SimulateAttachTagToSingle(aIVirtualCard, owner, tag, removeTiming, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SimulateAttachTagToSingle(AIVirtualCard target, AIVirtualCard owner, AIPlayTag tag, AIScriptTokenArgType removeTiming, AISituationInfo situation)
|
||||
{
|
||||
AIAttachedTagInformation info = new AIAttachedTagInformation(tag, removeTiming, owner, target);
|
||||
target.TagCollectionContainer.AttachTag(info, target, situation);
|
||||
RegisterAttachedTagStopPreprocess(owner, owner.SelfField, tag, removeTiming, target);
|
||||
}
|
||||
|
||||
public static void SimulateRandomSelectAttachTag(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIPlayTag tag, AIScriptTokenArgType removeTiming, AISelectLogicArgumentBase selectLogic)
|
||||
{
|
||||
AIVirtualCardRealTargetInformation aIVirtualCardRealTargetInformation = situation.DequeueRealTargetInfo(tagOwner, field);
|
||||
if (aIVirtualCardRealTargetInformation == null)
|
||||
{
|
||||
SimulateRandomSelectAttachTagToVirtualTarget(candidates, selectCount, tagOwner, field, playPtn, situation, tag, removeTiming, selectLogic);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimulateRandomSelectAttachTagToRealTarget(aIVirtualCardRealTargetInformation, candidates, selectCount, tagOwner, situation, tag, removeTiming);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SimulateRandomSelectAttachTagToVirtualTarget(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIPlayTag tag, AIScriptTokenArgType removeTiming, AISelectLogicArgumentBase selectLogic)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (selectCount >= candidates.Count)
|
||||
{
|
||||
SimulateAttachTagToAll(candidates, tagOwner, tag, removeTiming, situation);
|
||||
return;
|
||||
}
|
||||
if (selectCount == 1)
|
||||
{
|
||||
SimulateAttachTagToSingle(selectLogic.SelectSingleTarget(candidates, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst), tagOwner, tag, removeTiming, situation);
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> list = selectLogic.SelectMultipleSelectedTargets(candidates, selectCount, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
SimulateAttachTagToAll(list, tagOwner, tag, removeTiming, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SimulateRandomSelectAttachTagToRealTarget(AIVirtualCardRealTargetInformation realTargetInfo, List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AISituationInfo situation, AIPlayTag tag, AIScriptTokenArgType removeTiming)
|
||||
{
|
||||
List<AIVirtualCard> targetList = realTargetInfo.TargetList;
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
int num = selectCount;
|
||||
for (int i = 0; i < targetList.Count; i++)
|
||||
{
|
||||
AIVirtualCard item = targetList[i];
|
||||
if (candidates.Contains(item))
|
||||
{
|
||||
list.Add(item);
|
||||
num--;
|
||||
if (num <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimulateAttachTagToAll(list, tagOwner, tag, removeTiming, situation);
|
||||
}
|
||||
|
||||
private static void RegisterAttachedTagStopPreprocess(AIVirtualCard tagOwner, AIVirtualField field, AIPlayTag attachedTag, AIScriptTokenArgType removeTiming, AIVirtualCard targetCard)
|
||||
{
|
||||
AIAttachedTagStopPreprocessOption option = new AIAttachedTagStopPreprocessOption(targetCard)
|
||||
{
|
||||
TargetTag = attachedTag
|
||||
};
|
||||
switch (GetAttachedTagRemoveTimingForPreprocess(removeTiming, tagOwner))
|
||||
{
|
||||
case AIAttachedTagRemoveTiming.AllyTurnEnd:
|
||||
field.TagPreprocessContainer.AppendAllyTurnEndStopInfo(option);
|
||||
break;
|
||||
case AIAttachedTagRemoveTiming.OpponentTurnEnd:
|
||||
field.TagPreprocessContainer.AppendOpponentTurnEndStopInfo(option);
|
||||
break;
|
||||
case AIAttachedTagRemoveTiming.NextTurnEnd:
|
||||
{
|
||||
int defaultDecrementValue = (tagOwner.IsSelfTurn ? 1 : 0);
|
||||
if (tagOwner.IsAlly)
|
||||
{
|
||||
field.TagPreprocessContainer.AppendAllyTurnEndStopInfo(option, defaultDecrementValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
field.TagPreprocessContainer.AppendOpponentTurnEndStopInfo(option, defaultDecrementValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AIAttachedTagRemoveTiming.AllyTurnStart:
|
||||
field.TagPreprocessContainer.AppendAllyTurnStartStopInfo(option);
|
||||
break;
|
||||
case AIAttachedTagRemoveTiming.OpponentTurnStart:
|
||||
field.TagPreprocessContainer.AppendOpponentTurnStartStopInfo(option);
|
||||
break;
|
||||
case AIAttachedTagRemoveTiming.Leave:
|
||||
field.TagPreprocessContainer.AppendLeaveStopInfo(option, tagOwner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static AIAttachedTagRemoveTiming GetAttachedTagRemoveTimingForPreprocess(AIScriptTokenArgType srcRemoveTiming, AIVirtualCard tagOwner)
|
||||
{
|
||||
switch (srcRemoveTiming)
|
||||
{
|
||||
case AIScriptTokenArgType.WHEN_ALLY_TURNEND:
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return AIAttachedTagRemoveTiming.OpponentTurnEnd;
|
||||
}
|
||||
return AIAttachedTagRemoveTiming.AllyTurnEnd;
|
||||
case AIScriptTokenArgType.WHEN_OPPONENT_TURNEND:
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return AIAttachedTagRemoveTiming.AllyTurnEnd;
|
||||
}
|
||||
return AIAttachedTagRemoveTiming.OpponentTurnEnd;
|
||||
case AIScriptTokenArgType.WHEN_ALLY_TURNSTART:
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return AIAttachedTagRemoveTiming.OpponentTurnStart;
|
||||
}
|
||||
return AIAttachedTagRemoveTiming.AllyTurnStart;
|
||||
case AIScriptTokenArgType.WHEN_OPPONENT_TURNSTART:
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return AIAttachedTagRemoveTiming.AllyTurnStart;
|
||||
}
|
||||
return AIAttachedTagRemoveTiming.OpponentTurnStart;
|
||||
case AIScriptTokenArgType.WHEN_NEXT_TURNEND:
|
||||
return AIAttachedTagRemoveTiming.NextTurnEnd;
|
||||
case AIScriptTokenArgType.WHEN_LEAVE:
|
||||
return AIAttachedTagRemoveTiming.Leave;
|
||||
default:
|
||||
return AIAttachedTagRemoveTiming.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Wizard;
|
||||
|
||||
public enum AIAttachedTagRemoveTiming
|
||||
{
|
||||
AllyTurnEnd,
|
||||
OpponentTurnEnd,
|
||||
NextTurnEnd,
|
||||
AllyTurnStart,
|
||||
OpponentTurnStart,
|
||||
Leave,
|
||||
None
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIAttackableCountSimulationUtility : MonoBehaviour
|
||||
{
|
||||
public static void ExecuteChangeAttackableCountAll(List<AIVirtualCard> candidates, int attackableCount)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsDead)
|
||||
{
|
||||
aIVirtualCard.GiveAttackableCount(attackableCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteChangeAttackableCountTargetSelect(int attackableCount, AIScriptTokenArgType whichTarget, AISituationInfo situation)
|
||||
{
|
||||
if (situation != null)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
ExecuteChangeAttackableCountAll(situationTarget.Targets, attackableCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
SVSim.BattleEngine/Engine/Wizard/AIBanAttackSimulationUtility.cs
Normal file
120
SVSim.BattleEngine/Engine/Wizard/AIBanAttackSimulationUtility.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
using Wizard.Battle.UI;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBanAttackSimulationUtility
|
||||
{
|
||||
public static void BanAttackAll(List<AIVirtualCard> candidates, CantAttackType banAttackType)
|
||||
{
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (!aIVirtualCard.IsIndependent)
|
||||
{
|
||||
BanAttackSingle(aIVirtualCard, banAttackType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanAttackRandom(List<AIVirtualCard> candidates, CantAttackType banAttackType, int selectCount)
|
||||
{
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectTargetForBanAttack(candidates, AISelectTargetPattern.Worst);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
BanAttackSingle(aIVirtualCard, banAttackType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BanAttackAll(SelectMultipleTargetsForBanAttack(candidates, selectCount, AISelectTargetPattern.Worst), banAttackType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanAttackTarget(AISituationInfo situation, CantAttackType banAttackType, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
BanAttackAll(situationTarget.Targets, banAttackType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanAttackTargetPrediction(List<AIVirtualCard> candidates, CantAttackType banAttackType, int selectCount)
|
||||
{
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectTargetForBanAttack(candidates, AISelectTargetPattern.Best);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
BanAttackSingle(aIVirtualCard, banAttackType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BanAttackAll(SelectMultipleTargetsForBanAttack(candidates, selectCount, AISelectTargetPattern.Best), banAttackType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BanAttackSingle(AIVirtualCard target, CantAttackType banAttackType)
|
||||
{
|
||||
switch (banAttackType)
|
||||
{
|
||||
case CantAttackType.All:
|
||||
target.IsCantAttackAll = true;
|
||||
break;
|
||||
case CantAttackType.Unit:
|
||||
target.IsSkillCantAttackUnit = true;
|
||||
break;
|
||||
case CantAttackType.Class:
|
||||
target.IsSkillCantAttackClass = true;
|
||||
break;
|
||||
case CantAttackType.NotHasGuard:
|
||||
target.IsSkillCantAtkUnitNotHasGuard = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard SelectTargetForBanAttack(List<AIVirtualCard> candidates, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int num = ((worstOrBest == AISelectTargetPattern.Worst) ? int.MaxValue : int.MinValue);
|
||||
AIVirtualCard result = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if ((worstOrBest != AISelectTargetPattern.Worst) ? (aIVirtualCard.Attack > num) : (aIVirtualCard.Attack < num))
|
||||
{
|
||||
result = aIVirtualCard;
|
||||
num = aIVirtualCard.Attack;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<AIVirtualCard> SelectMultipleTargetsForBanAttack(List<AIVirtualCard> candidates, int selectCount, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
bool flag = false;
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list[j];
|
||||
if ((worstOrBest != AISelectTargetPattern.Worst) ? (aIVirtualCard.Attack > aIVirtualCard2.Attack) : (aIVirtualCard.Attack < aIVirtualCard2.Attack))
|
||||
{
|
||||
list[j] = aIVirtualCard;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (!flag && list.Count < selectCount)
|
||||
{
|
||||
list.Add(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBanishSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.BANISH_LOGIC;
|
||||
|
||||
public AIBanishSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Banish);
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Banish, selectCount);
|
||||
}
|
||||
}
|
||||
238
SVSim.BattleEngine/Engine/Wizard/AIBanishSimulationUtility.cs
Normal file
238
SVSim.BattleEngine/Engine/Wizard/AIBanishSimulationUtility.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBanishSimulationUtility
|
||||
{
|
||||
public static float EvalTargetingBanish(List<AIScriptTokenBase> argList, List<int> playPtn, AIVirtualField field, AIVirtualCard tagOwner, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothInplayCards, argList, tagOwner, playPtn, null);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
int num = 0;
|
||||
float num2 = float.MinValue;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsUnbanishable && (aIVirtualCard.IsAlly == tagOwner.IsAlly || (!aIVirtualCard.IsUntouchable && !aIVirtualCard.IsSneak)))
|
||||
{
|
||||
num++;
|
||||
float num3 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true);
|
||||
float num4 = (aIVirtualCard.IsAlly ? (0f - num3 - aIVirtualCard.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + aIVirtualCard.GetAllBanishBonus(playPtn, useIgnoreInBattle: false) + aIVirtualCard.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false)) : (num3 + aIVirtualCard.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - aIVirtualCard.GetAllBanishBonus(playPtn, useIgnoreInBattle: false) - aIVirtualCard.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false)));
|
||||
if (num4 > num2)
|
||||
{
|
||||
num2 = num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
num2 = 0f;
|
||||
}
|
||||
return num2;
|
||||
}
|
||||
|
||||
public static float EvalRandomBanish(List<AIScriptTokenBase> argList, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, int count, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothInplayCards, argList, tagOwner, playPtn, null);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
List<float> list2 = new List<float>();
|
||||
float num = 0f;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsUnbanishable && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
float num2 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
float num3 = aIVirtualCard.EvaluateBreakValue(playPtn, useIgnoreBreak: true);
|
||||
float allBanishBonus = aIVirtualCard.GetAllBanishBonus(playPtn, useIgnoreInBattle: true);
|
||||
float num4 = aIVirtualCard.EvaluateLeaveValue(playPtn, useIgnoreInBattle: true);
|
||||
float num5 = (aIVirtualCard.IsAlly ? (-1f) : 1f) * (num2 + num3 - allBanishBonus - num4);
|
||||
list2.Add(num5);
|
||||
num += num5;
|
||||
}
|
||||
}
|
||||
if (list.Count <= count)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
List<float[]> list3 = AIMathematicsLibrary.EnumerateCombinations(list2, count).ToList();
|
||||
float num6 = 0f;
|
||||
for (int j = 0; j < list3.Count; j++)
|
||||
{
|
||||
for (int k = 0; k < list3[j].Length; k++)
|
||||
{
|
||||
num6 += list3[j][k];
|
||||
}
|
||||
}
|
||||
return num6 / (float)list3.Count;
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public static float EvalAllBanish(List<AIScriptTokenBase> argList, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothInplayCards, argList, tagOwner, playPtn, null);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsUnbanishable)
|
||||
{
|
||||
float num2 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
float num3 = aIVirtualCard.EvaluateBreakValue(playPtn, useIgnoreBreak: true);
|
||||
float allBanishBonus = aIVirtualCard.GetAllBanishBonus(playPtn, useIgnoreInBattle: true);
|
||||
float num4 = aIVirtualCard.EvaluateLeaveValue(playPtn, useIgnoreInBattle: true);
|
||||
num += (aIVirtualCard.IsAlly ? (-1f) : 1f) * (num2 + num3 - allBanishBonus - num4);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static void BanishAll(List<AIVirtualCard> targetCards, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < targetCards.Count; i++)
|
||||
{
|
||||
BanishSingle(targetCards[i], situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteTargetSelectBanish(AIVirtualCard owner, List<AIVirtualCard> targets, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType selectType, int selectCount = 1)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("ExecuteTargetSelectBanish() Error!! situation is null!!!!!");
|
||||
}
|
||||
else if (situation.IsTargetExists(selectType))
|
||||
{
|
||||
BanishTarget(situation, targets, selectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
BanishTargetPrediction(situation, targets, owner, field, playPtn, selectType, selectCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BanishTargetPrediction(AISituationInfo situation, List<AIVirtualCard> candidates, AIVirtualCard banishOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType selectType, int selectCount)
|
||||
{
|
||||
List<AIVirtualCard> candidates2 = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(candidates, banishOwner, playPtn);
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard target = AISimulationRemovalUtility.SelectRemovalTarget(candidates2, banishOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Banish);
|
||||
situation.SetSingleTargetInInfo(target, TargetSelectType.Default, selectType);
|
||||
BanishTarget(situation, candidates, selectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
BanishAll(AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates2, banishOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Banish, selectCount), situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanishTarget(AISituationInfo situation, List<AIVirtualCard> candidates, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("BanishTarget error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
BanishSingle(aIVirtualCard, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanishSingle(AIVirtualCard target, AISituationInfo situation)
|
||||
{
|
||||
if (!target.IsDead && !target.IsIndependent && !target.IsUnbanishable)
|
||||
{
|
||||
target.RemoveCard(situation, AIRemovalType.Banish, isFromSkill: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BanishRandom(List<AIVirtualCard> targets, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int selectCount = 1)
|
||||
{
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = AISimulationRemovalUtility.SelectRemovalTarget(targets, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Banish);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
BanishSingle(aIVirtualCard, situation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BanishAll(AISimulationRemovalUtility.SelectMultipleRemovalTargets(targets, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Banish, selectCount), situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetInplayBanishedCount(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
return GetFilterdBanishCardList(tagOwner, field, playPtn, situation, argList, BattleCardBase.BanishInfo.BanishPlace.Field)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public static int GetHandBanishedCount(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
return GetFilterdBanishCardList(tagOwner, field, playPtn, situation, argList, BattleCardBase.BanishInfo.BanishPlace.Hand)?.Count ?? 0;
|
||||
}
|
||||
|
||||
private static List<AIVirtualCard> GetFilterdBanishCardList(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList, BattleCardBase.BanishInfo.BanishPlace place)
|
||||
{
|
||||
List<AIVirtualCard> banishedCards = field.CardListSet.BanishedCards;
|
||||
if (banishedCards == null || banishedCards.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SeparateArgListToFilterAndTimingArg(argList, out var filters, out var turnOrGame);
|
||||
if (filters == null || filters.Count <= 0 || (turnOrGame != AIScriptTokenArgType.TURN && turnOrGame != AIScriptTokenArgType.GAME))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(banishedCards, filters, tagOwner, playPtn, situation, isBlockDeadCard: false);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (turnOrGame == AIScriptTokenArgType.TURN)
|
||||
{
|
||||
list.RemoveAll((AIVirtualCard c) => !c.IsBanishedTargetTurn(field.CurrentTurnCount));
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c.BanishedInfo.Place != place);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void SeparateArgListToFilterAndTimingArg(List<AIScriptTokenBase> argList, out List<AIScriptTokenBase> filters, out AIScriptTokenArgType turnOrGame)
|
||||
{
|
||||
if (argList == null || argList.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIBanishSimulationUtility.SeparateArgListToFilterAndTimingArg() error!! argList is null!!");
|
||||
filters = null;
|
||||
turnOrGame = AIScriptTokenArgType.NONE;
|
||||
return;
|
||||
}
|
||||
if (argList[argList.Count - 1] is AIScriptArgumentToken aIScriptArgumentToken)
|
||||
{
|
||||
turnOrGame = aIScriptArgumentToken.ArgumentType;
|
||||
}
|
||||
else
|
||||
{
|
||||
AIConsoleUtility.LogError("AIBanishSimulationUtility.SeparateArgListToFilterAndTimingArg() error!! lastToken is not ArgumentToken!!");
|
||||
turnOrGame = AIScriptTokenArgType.NONE;
|
||||
}
|
||||
filters = argList.GetRange(0, argList.Count - 1);
|
||||
}
|
||||
}
|
||||
6
SVSim.BattleEngine/Engine/Wizard/AIBarrierGlobal.cs
Normal file
6
SVSim.BattleEngine/Engine/Wizard/AIBarrierGlobal.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBarrierGlobal
|
||||
{
|
||||
public const int CLIPPING_RANGE_MAX = 9999;
|
||||
}
|
||||
180
SVSim.BattleEngine/Engine/Wizard/AIBasicTargetSelectUtility.cs
Normal file
180
SVSim.BattleEngine/Engine/Wizard/AIBasicTargetSelectUtility.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBasicTargetSelectUtility
|
||||
{
|
||||
public static AIVirtualCard SelectSingleBasicSkillTarget(List<AIVirtualCard> candidates, AIScriptTokenArgType skillType, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Func<AIVirtualCard, AIVirtualCard, AISelectTargetPattern, AIVirtualCard> func = SelectCompareFunc(skillType);
|
||||
if (func == null)
|
||||
{
|
||||
return candidates[0];
|
||||
}
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
if (aIVirtualCard2.IsUnit && !aIVirtualCard2.IsDead)
|
||||
{
|
||||
aIVirtualCard = ((aIVirtualCard != null) ? func(aIVirtualCard, aIVirtualCard2, worstOrBest) : aIVirtualCard2);
|
||||
}
|
||||
}
|
||||
return aIVirtualCard;
|
||||
}
|
||||
|
||||
private static Func<AIVirtualCard, AIVirtualCard, AISelectTargetPattern, AIVirtualCard> SelectCompareFunc(AIScriptTokenArgType skillType)
|
||||
{
|
||||
switch (skillType)
|
||||
{
|
||||
case AIScriptTokenArgType.SNEAK:
|
||||
return CompareSneakCandidates;
|
||||
case AIScriptTokenArgType.QUICK:
|
||||
case AIScriptTokenArgType.RUSH:
|
||||
return CompareRushOrQuickCandidates;
|
||||
case AIScriptTokenArgType.GUARD:
|
||||
return CompareGuardCandidates;
|
||||
case AIScriptTokenArgType.KILLER:
|
||||
return CompareKillerCandidates;
|
||||
case AIScriptTokenArgType.IGNORE_GUARD:
|
||||
return CompareIgnoreGuardCandidates;
|
||||
case AIScriptTokenArgType.DRAIN:
|
||||
case AIScriptTokenArgType.UNTOUCHABLE:
|
||||
case AIScriptTokenArgType.FORCE_TARGETING:
|
||||
case AIScriptTokenArgType.UNBANISHABLE:
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard CompareRushOrQuickCandidates(AIVirtualCard currentResultTarget, AIVirtualCard checkCard, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int attack = currentResultTarget.Attack;
|
||||
int attack2 = checkCard.Attack;
|
||||
AIVirtualCard result = currentResultTarget;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (checkCard.IsSummonDrunkenness && !checkCard.IsCantAttackAll && attack2 > attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (attack2 < attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AIVirtualCard CompareGuardCandidates(AIVirtualCard currentResultTarget, AIVirtualCard checkCard, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int life = currentResultTarget.Life;
|
||||
int life2 = checkCard.Life;
|
||||
AIVirtualCard result = currentResultTarget;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (life2 > life)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (life2 < life)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AIVirtualCard CompareSneakCandidates(AIVirtualCard currentResultTarget, AIVirtualCard checkCard, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int attack = currentResultTarget.Attack;
|
||||
int life = currentResultTarget.Life;
|
||||
int attack2 = checkCard.Attack;
|
||||
int life2 = checkCard.Life;
|
||||
AIVirtualCard result = currentResultTarget;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (attack2 > attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
else if (attack2 == attack && life2 > life)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (attack2 < attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
else if (attack2 == attack && life2 < life)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AIVirtualCard CompareKillerCandidates(AIVirtualCard currentResultTarget, AIVirtualCard checkCard, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int attack = currentResultTarget.Attack;
|
||||
int attack2 = checkCard.Attack;
|
||||
AIVirtualCard result = currentResultTarget;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (attack > attack2 || (attack == attack2 && currentResultTarget.Life < checkCard.Life))
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (attack < attack2 || (attack == attack2 && currentResultTarget.Life > checkCard.Life))
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AIVirtualCard CompareIgnoreGuardCandidates(AIVirtualCard currentResultTarget, AIVirtualCard checkCard, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int attack = currentResultTarget.Attack;
|
||||
int attack2 = checkCard.Attack;
|
||||
AIVirtualCard result = currentResultTarget;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (attack2 > attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (attack2 < attack)
|
||||
{
|
||||
result = checkCard;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
43
SVSim.BattleEngine/Engine/Wizard/AIBerserkUtility.cs
Normal file
43
SVSim.BattleEngine/Engine/Wizard/AIBerserkUtility.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBerserkUtility
|
||||
{
|
||||
public static bool IsToBeBerserk(AIVirtualField field, List<int> playPtn, AISituationInfo situation, bool isAlly)
|
||||
{
|
||||
int num = 0;
|
||||
if (isAlly && playPtn != null)
|
||||
{
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
int index = playPtn[i];
|
||||
BattleCardBase baseCard = field.AllyHandCards[index].BaseCard;
|
||||
num += AIPlayOnSkillUtility.GetLifePenaltyOnPlay(baseCard, field.AI);
|
||||
}
|
||||
}
|
||||
if (SkillConditionHalfLife.IsHalfLife((isAlly ? field.AllyClass : field.EnemyClass).Life - num) || IsForceBerserk(field, playPtn, situation, isAlly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsForceBerserk(AIVirtualField field, List<int> playPtn, AISituationInfo situation, bool isAlly)
|
||||
{
|
||||
List<AIVirtualCard> forceBerserkTagHolders = field.CardListSet.ForceBerserkTagHolders;
|
||||
if (forceBerserkTagHolders == null || forceBerserkTagHolders.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < forceBerserkTagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = forceBerserkTagHolders[i];
|
||||
if (aIVirtualCard.IsAlly == isAlly && aIVirtualCard.TagCollectionContainer.ForceBerserkTags.IsForceBerserk(aIVirtualCard, playPtn, situation))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBounceSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.BOUNCE_LOGIC;
|
||||
|
||||
public AIBounceSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Bounce);
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Bounce, selectCount);
|
||||
}
|
||||
}
|
||||
134
SVSim.BattleEngine/Engine/Wizard/AIBounceSimulationUtility.cs
Normal file
134
SVSim.BattleEngine/Engine/Wizard/AIBounceSimulationUtility.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBounceSimulationUtility
|
||||
{
|
||||
public static void BounceAll(List<AIVirtualCard> candidates, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (!aIVirtualCard.IsIndependent)
|
||||
{
|
||||
aIVirtualCard.RemoveCard(situation, AIRemovalType.Bounce, isFromSkill: true);
|
||||
BounceActivation(aIVirtualCard, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void BounceRandom(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int selectCount = 1)
|
||||
{
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Bounce);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
aIVirtualCard.RemoveCard(situation, AIRemovalType.Bounce, isFromSkill: true);
|
||||
BounceActivation(aIVirtualCard, situation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BounceAll(AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Bounce, selectCount), situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteTargetSelectBounce(AIVirtualCard owner, List<AIVirtualCard> targets, AISituationInfo situation, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType selectType, AIRemovalType removalType, int selectCount = 1)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("ExecuteTargetSelectDestroy() Error!! situation is null!!!!!");
|
||||
return;
|
||||
}
|
||||
if (situation.IsTargetExists(selectType))
|
||||
{
|
||||
BounceTarget(situation, targets, selectType);
|
||||
return;
|
||||
}
|
||||
situation.SelectedTargets.UpdateRemovalType(selectType, removalType);
|
||||
BounceTargetPrediction(situation, targets, owner, field, playPtn, selectType, selectCount);
|
||||
}
|
||||
|
||||
private static void BounceTargetPrediction(AISituationInfo situation, List<AIVirtualCard> candidates, AIVirtualCard bounceOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType selectType, int selectCount)
|
||||
{
|
||||
List<AIVirtualCard> candidates2 = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(candidates, bounceOwner, playPtn);
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard target = AISimulationRemovalUtility.SelectRemovalTarget(candidates2, bounceOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Bounce);
|
||||
situation.SetSingleTargetInInfo(target, TargetSelectType.Default, selectType);
|
||||
BounceTarget(situation, candidates, selectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AIVirtualCard> list = AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates2, bounceOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Bounce, selectCount);
|
||||
situation.SetMultipleTargetsInInfo(list, TargetSelectType.Default, AIRemovalType.Bounce, selectType);
|
||||
BounceAll(list, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BounceTarget(AISituationInfo situation, List<AIVirtualCard> candidates, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("BounceTarget error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (candidates.Contains(aIVirtualCard) && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
aIVirtualCard.RemoveCard(situation, AIRemovalType.Bounce, isFromSkill: true);
|
||||
}
|
||||
BounceActivation(aIVirtualCard, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BounceActivation(AIVirtualCard bouncedCard, AISituationInfo situation)
|
||||
{
|
||||
AIVirtualField selfField = situation.Actor.SelfField;
|
||||
if (!selfField.CardListSet.HasBounceTagHolders)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> bounceTagHolders = selfField.CardListSet.BounceTagHolders;
|
||||
for (int i = 0; i < bounceTagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = bounceTagHolders[i];
|
||||
if (!aIVirtualCard.IsDead && aIVirtualCard.IsOnField)
|
||||
{
|
||||
aIVirtualCard.ExecuteBounceSkills(bouncedCard, selfField, selfField.BestPlayPtn, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetBounceCount(AIVirtualField field, AISituationInfo situation, AIScriptTokenArgType type)
|
||||
{
|
||||
int result = 0;
|
||||
switch (type)
|
||||
{
|
||||
case AIScriptTokenArgType.NOW:
|
||||
result = GetCurrentSituationBounceCount(situation);
|
||||
break;
|
||||
case AIScriptTokenArgType.TURN:
|
||||
result = field.TurnBounceCount + GetCurrentSituationBounceCount(situation);
|
||||
break;
|
||||
case AIScriptTokenArgType.GAME:
|
||||
result = field.GameBounceCount + GetCurrentSituationBounceCount(situation);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int GetCurrentSituationBounceCount(AISituationInfo situation)
|
||||
{
|
||||
if (situation.BounceCardList == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return situation.BounceCardList.Count;
|
||||
}
|
||||
}
|
||||
21
SVSim.BattleEngine/Engine/Wizard/AIBrokenCostSumUtility.cs
Normal file
21
SVSim.BattleEngine/Engine/Wizard/AIBrokenCostSumUtility.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIBrokenCostSumUtility
|
||||
{
|
||||
public static int GetBrokenCostSum(AIVirtualField field, AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
int num = 0;
|
||||
List<AIVirtualCard> list = (tagOwner.IsAlly ? field.CardListSet.AllyDestroyedCards : field.CardListSet.EnemyDestroyedCards);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, list, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num += aIVirtualCard.BaseCost;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
69
SVSim.BattleEngine/Engine/Wizard/AIBuffCountUtility.cs
Normal file
69
SVSim.BattleEngine/Engine/Wizard/AIBuffCountUtility.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBuffCountUtility
|
||||
{
|
||||
public static int GetBuffCount(AIVirtualCard owner, AIVirtualField field, AISituationInfo situation, List<int> playPtn, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
if (argList.Count < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AIScriptTokenArgType argumentType = ((AIScriptArgumentToken)argList[0]).ArgumentType;
|
||||
AIScriptTokenArgType argumentType2 = ((AIScriptArgumentToken)argList[1]).ArgumentType;
|
||||
if (!IsDurationArgLegal(argumentType2) || !IsPositionArgLegal(argumentType))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
argList.RemoveRange(0, 2);
|
||||
argList.Reverse();
|
||||
if (argumentType == AIScriptTokenArgType.PLAYED)
|
||||
{
|
||||
return GetPlayedBuffCount(owner, field, argList, situation, playPtn, argumentType2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int GetPlayedBuffCount(AIVirtualCard owner, AIVirtualField field, List<AIScriptTokenBase> filters, AISituationInfo situation, List<int> playPtn, AIScriptTokenArgType duration)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothInplayCards, filters, owner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
switch (duration)
|
||||
{
|
||||
case AIScriptTokenArgType.TURN:
|
||||
if (aIVirtualCard.BuffRecorderCollection != null)
|
||||
{
|
||||
int turn = (aIVirtualCard.IsAlly ? field.AllyTurnCount : field.EnemyTurnCount);
|
||||
num += aIVirtualCard.BuffRecorderCollection.GetTurnBuffCount(turn, aIVirtualCard.IsSelfTurn);
|
||||
}
|
||||
break;
|
||||
case AIScriptTokenArgType.GAME:
|
||||
num += aIVirtualCard.BuffCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static bool IsDurationArgLegal(AIScriptTokenArgType duration)
|
||||
{
|
||||
if (duration != AIScriptTokenArgType.TURN)
|
||||
{
|
||||
return duration == AIScriptTokenArgType.GAME;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsPositionArgLegal(AIScriptTokenArgType position)
|
||||
{
|
||||
return position == AIScriptTokenArgType.PLAYED;
|
||||
}
|
||||
}
|
||||
241
SVSim.BattleEngine/Engine/Wizard/AIBuffEvaluationUtility.cs
Normal file
241
SVSim.BattleEngine/Engine/Wizard/AIBuffEvaluationUtility.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBuffEvaluationUtility
|
||||
{
|
||||
public static readonly AIScriptTokenArgType[] LEGAL_TEMP_OR_PERM_ARGUMENTS = new AIScriptTokenArgType[2]
|
||||
{
|
||||
AIScriptTokenArgType.TEMP,
|
||||
AIScriptTokenArgType.PERM
|
||||
};
|
||||
|
||||
public static float EvalAllBuff(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (tagOwner == null || field == null || argList == null || argList.Count <= 3)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
CreateBuffInfoAndFilters(argList, out var filters, out var buffInfo);
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
return CalculateAllBuffValue(list, field, buffInfo, playPtn, situation);
|
||||
}
|
||||
|
||||
public static float EvalRandomBuff(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (tagOwner == null || field == null || argList == null || argList.Count <= 3)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
CreateBuffInfoAndFilters(argList, out var filters, out var buffInfo);
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
list.AddRange(field.CardListSet.BothClassAndInplayCards);
|
||||
List<AIVirtualCard> list2 = AIFilteringUtility.MultipleFiltering(list, filters, tagOwner, playPtn, null);
|
||||
if (list2 == null || list2.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list2.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
float num = 0f;
|
||||
for (int num2 = 0; num2 < list2.Count; num2++)
|
||||
{
|
||||
AIVirtualCard target = list2[num2];
|
||||
num += CalculateBuffValue(target, field, buffInfo, playPtn, situation);
|
||||
}
|
||||
return num / (float)list2.Count;
|
||||
}
|
||||
|
||||
public static float EvalTargetingBuff(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (tagOwner == null || field == null || argList == null || argList.Count <= 3)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
CreateBuffInfoAndFilters(argList, out var filters, out var buffInfo);
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
list.AddRange(field.CardListSet.BothClassAndInplayCards);
|
||||
List<AIVirtualCard> list2 = AIFilteringUtility.MultipleFiltering(list, filters, tagOwner, playPtn, null);
|
||||
if (list2 == null || list2.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list2.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
bool flag = true;
|
||||
float num = float.MinValue;
|
||||
for (int num2 = 0; num2 < list2.Count; num2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list2[num2];
|
||||
if (!aIVirtualCard.IsIndependent && (aIVirtualCard.IsAlly == tagOwner.IsAlly || !aIVirtualCard.CantBeFocusedSkill))
|
||||
{
|
||||
flag = false;
|
||||
float num3 = CalculateBuffValue(aIVirtualCard, field, buffInfo, playPtn, situation);
|
||||
if (num3 > num)
|
||||
{
|
||||
num = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
num = 0f;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static void CreateBuffInfoAndFilters(List<AIScriptTokenBase> argList, out List<AIScriptTokenBase> filters, out AISimulationBuffInfo buffInfo)
|
||||
{
|
||||
int index = 0;
|
||||
int index2 = 1;
|
||||
int num = 2;
|
||||
AIScriptArgumentToken aIScriptArgumentToken = argList[index] as AIScriptArgumentToken;
|
||||
bool flag = false;
|
||||
if (aIScriptArgumentToken != null)
|
||||
{
|
||||
flag = aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.TEMP;
|
||||
}
|
||||
int num2 = (int)argList[index2].Value;
|
||||
int num3 = (int)argList[num].Value;
|
||||
if (flag)
|
||||
{
|
||||
buffInfo = new AISimulationBuffInfo(num3, num2, num3, num2);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffInfo = new AISimulationBuffInfo(0, 0, num3, num2);
|
||||
}
|
||||
filters = new List<AIScriptTokenBase>();
|
||||
for (int num4 = argList.Count - 1; num4 > num; num4--)
|
||||
{
|
||||
filters.Add(argList[num4]);
|
||||
}
|
||||
}
|
||||
|
||||
private static float CalculateAllBuffValue(List<AIVirtualCard> targets, AIVirtualField field, AISimulationBuffInfo buffInfo, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCardStatusInfo> list = new List<AIVirtualCardStatusInfo>();
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyInplayCards[i];
|
||||
if (aIVirtualCard.IsUnit)
|
||||
{
|
||||
list.Add(new AIVirtualCardStatusInfo(aIVirtualCard, aIVirtualCard.Attack, aIVirtualCard.Life));
|
||||
}
|
||||
}
|
||||
List<AIVirtualCardStatusInfo> list2 = new List<AIVirtualCardStatusInfo>();
|
||||
for (int j = 0; j < field.EnemyInplayCards.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = field.EnemyInplayCards[j];
|
||||
if (aIVirtualCard2.IsUnit)
|
||||
{
|
||||
list2.Add(new AIVirtualCardStatusInfo(aIVirtualCard2, aIVirtualCard2.Attack, aIVirtualCard2.Life));
|
||||
}
|
||||
}
|
||||
float num = 0f;
|
||||
for (int k = 0; k < targets.Count; k++)
|
||||
{
|
||||
AIVirtualCard target = targets[k];
|
||||
if (!target.IsUnit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int attack = target.Attack + buffInfo.TotalAttackBuff;
|
||||
int num2 = target.Life + buffInfo.TotalLifeBuff;
|
||||
AIVirtualCardStatusInfo aIVirtualCardStatusInfo = null;
|
||||
List<AIVirtualCardStatusInfo> list3 = (target.IsAlly ? list : list2);
|
||||
aIVirtualCardStatusInfo = list3.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target));
|
||||
if (num2 <= 0)
|
||||
{
|
||||
float num3 = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
num += num3 * (target.IsAlly ? (-1f) : 1f);
|
||||
if (aIVirtualCardStatusInfo != null)
|
||||
{
|
||||
list3.Remove(aIVirtualCardStatusInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num += (float)(buffInfo.TotalAttackBuff + buffInfo.TotalLifeBuff) * (target.IsAlly ? 1f : (-1f));
|
||||
aIVirtualCardStatusInfo?.ModifyStatus(attack, num2);
|
||||
}
|
||||
}
|
||||
if (list2 != null && list2.Count > 0 && list.Count > 0)
|
||||
{
|
||||
num += AISimulationUtility.EvaluateAttackValueAfterAllSkill(field, situation, list, list2, playPtn);
|
||||
}
|
||||
if (buffInfo.TempAttackBuff > 0)
|
||||
{
|
||||
for (int num4 = 0; num4 < targets.Count; num4++)
|
||||
{
|
||||
AIVirtualCard target2 = targets[num4];
|
||||
AIVirtualCardStatusInfo aIVirtualCardStatusInfo2 = null;
|
||||
aIVirtualCardStatusInfo2 = ((!target2.IsAlly) ? list2.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target2)) : list.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target2)));
|
||||
if (aIVirtualCardStatusInfo2 != null && aIVirtualCardStatusInfo2.Life > 0)
|
||||
{
|
||||
num += (float)buffInfo.TempAttackBuff * (target2.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static float CalculateBuffValue(AIVirtualCard target, AIVirtualField field, AISimulationBuffInfo buffInfo, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCardStatusInfo> list = new List<AIVirtualCardStatusInfo>();
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyInplayCards[i];
|
||||
if (aIVirtualCard.IsUnit)
|
||||
{
|
||||
list.Add(new AIVirtualCardStatusInfo(aIVirtualCard, aIVirtualCard.Attack, aIVirtualCard.Life));
|
||||
}
|
||||
}
|
||||
List<AIVirtualCardStatusInfo> list2 = new List<AIVirtualCardStatusInfo>();
|
||||
for (int j = 0; j < field.EnemyInplayCards.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = field.EnemyInplayCards[j];
|
||||
if (aIVirtualCard2.IsUnit)
|
||||
{
|
||||
list2.Add(new AIVirtualCardStatusInfo(aIVirtualCard2, aIVirtualCard2.Attack, aIVirtualCard2.Life));
|
||||
}
|
||||
}
|
||||
float num = 0f;
|
||||
int attack = target.Attack + buffInfo.TotalAttackBuff;
|
||||
int num2 = target.Life + buffInfo.TotalLifeBuff;
|
||||
List<AIVirtualCardStatusInfo> list3 = (target.IsAlly ? list : list2);
|
||||
AIVirtualCardStatusInfo aIVirtualCardStatusInfo = list3.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target));
|
||||
if (num2 <= 0)
|
||||
{
|
||||
float num3 = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
num += num3 * (target.IsAlly ? (-1f) : 1f);
|
||||
if (aIVirtualCardStatusInfo != null)
|
||||
{
|
||||
list3.Remove(aIVirtualCardStatusInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num += (float)(buffInfo.TotalAttackBuff + buffInfo.TotalLifeBuff) * (target.IsAlly ? 1f : (-1f));
|
||||
aIVirtualCardStatusInfo?.ModifyStatus(attack, num2);
|
||||
}
|
||||
if (list2 != null && list2.Count > 0 && list.Count > 0)
|
||||
{
|
||||
num += AISimulationUtility.EvaluateAttackValueAfterAllSkill(field, situation, list, list2, playPtn);
|
||||
}
|
||||
if (buffInfo.TempAttackBuff > 0)
|
||||
{
|
||||
AIVirtualCardStatusInfo aIVirtualCardStatusInfo2 = null;
|
||||
aIVirtualCardStatusInfo2 = ((!target.IsAlly) ? list2.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target)) : list.FirstOrDefault((AIVirtualCardStatusInfo info) => info.BaseCard.IsSameCard(target)));
|
||||
if (aIVirtualCardStatusInfo2 != null && aIVirtualCardStatusInfo2.Life > 0)
|
||||
{
|
||||
num += (float)buffInfo.TempAttackBuff * (target.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
24
SVSim.BattleEngine/Engine/Wizard/AIBurialUtility.cs
Normal file
24
SVSim.BattleEngine/Engine/Wizard/AIBurialUtility.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIBurialUtility
|
||||
{
|
||||
public static bool IsBurialRite(AISituationInfo situation, List<AIScriptTokenBase> filters, AIVirtualField field)
|
||||
{
|
||||
AISelectedTargetInfo burialRiteTarget = situation.GetBurialRiteTarget();
|
||||
if (burialRiteTarget == null || burialRiteTarget.Type != TargetSelectType.BurialRite || !burialRiteTarget.HasTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<AIVirtualCard> targets = burialRiteTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(targets[i], field.AllyHandCards, filters, null, situation.Actor, situation))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AICannotPlaySimulationUtility
|
||||
{
|
||||
public static bool IsCannotPlayByTag(this AIVirtualField field, AIVirtualTargetSelectAction situation, List<int> playPtn)
|
||||
{
|
||||
if (situation.ActionType != AIOperationType.PLAY || !situation.OriginalCard.IsAlly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (field.CannotPlayInformationList == null || field.CannotPlayInformationList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AIVirtualCard originalCard = situation.OriginalCard;
|
||||
for (int i = 0; i < field.CannotPlayInformationList.Count; i++)
|
||||
{
|
||||
AICannotPlayInformation aICannotPlayInformation = field.CannotPlayInformationList[i];
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(originalCard, field.AllyHandCards, aICannotPlayInformation.Filters, playPtn, aICannotPlayInformation.Owner, situation))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIChangeClassSimulationUtility
|
||||
{
|
||||
public static void ChangeClassAll(List<AIVirtualCard> candidates, CardBasePrm.ClanType classType)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (!aIVirtualCard.IsDead && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
aIVirtualCard.ChangeClass(classType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ChangeClassTarget(List<AIVirtualCard> candidates, CardBasePrm.ClanType classType, AIScriptTokenArgType whichTarget, AISituationInfo situation)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
ChangeClassAll(situationTarget.Targets, classType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIChangeCostSimulationUtility
|
||||
{
|
||||
public static void AddCostAll(int count, List<AIVirtualCard> targets)
|
||||
{
|
||||
if (targets != null && targets.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
targets[i].AddCurrentCost(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddCostTarget(AIVirtualCard owner, int count, List<AIVirtualCard> candidates, List<AIVirtualCard> targets)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!owner.IsSameCard(aIVirtualCard) && candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
aIVirtualCard.AddCurrentCost(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetCostAll(int count, List<AIVirtualCard> targets)
|
||||
{
|
||||
if (targets != null && targets.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
targets[i].SetCurrentCost(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetCostTarget(AIVirtualCard owner, int count, List<AIVirtualCard> candidates, List<AIVirtualCard> targets)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!owner.IsSameCard(aIVirtualCard) && candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
aIVirtualCard.SetCurrentCost(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectTargetForChangeCost(AIVirtualCard owner, List<AIVirtualCard> candidates, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard = candidates[0];
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
{
|
||||
for (int j = 1; j < candidates.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard3 = candidates[j];
|
||||
if (!owner.IsSameCard(aIVirtualCard3) && aIVirtualCard.Cost < aIVirtualCard3.Cost)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AISelectTargetPattern.Worst:
|
||||
{
|
||||
for (int i = 1; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
if (!owner.IsSameCard(aIVirtualCard2) && aIVirtualCard.Cost > aIVirtualCard2.Cost)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return aIVirtualCard;
|
||||
}
|
||||
|
||||
public static void ExecuteCostChange(AIScriptTokenArgType changeType, AIScriptTokenArgType whichTarget, int changeCost, AIVirtualCard owner, List<AIVirtualCard> candidates, AISituationInfo situation, AIVirtualField field)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (whichTarget)
|
||||
{
|
||||
case AIScriptTokenArgType.ALL_SELECT:
|
||||
ChangeCostValue(isTargetAll: true, changeType, changeCost, owner, candidates, null);
|
||||
break;
|
||||
case AIScriptTokenArgType.TARGET_SELECT:
|
||||
case AIScriptTokenArgType.SECOND_TARGET_SELECT:
|
||||
if (situation != null && situation.IsTargetExists(whichTarget))
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.Log("ExecuteCostChange Nothing TargetInfo");
|
||||
break;
|
||||
}
|
||||
List<AIVirtualCard> targets2 = situationTarget.Targets;
|
||||
ChangeCostValue(isTargetAll: false, changeType, changeCost, owner, candidates, targets2);
|
||||
}
|
||||
break;
|
||||
case AIScriptTokenArgType.RANDOM_SELECT:
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectTargetForChangeCost(owner, candidates, AISelectTargetPattern.Worst);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
List<AIVirtualCard> targets = new List<AIVirtualCard> { aIVirtualCard };
|
||||
ChangeCostValue(isTargetAll: false, changeType, changeCost, owner, candidates, targets);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AIConsoleUtility.LogError("ExecuteCostChange: ilegal Target Arg type [" + whichTarget.ToString() + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ChangeCostValue(bool isTargetAll, AIScriptTokenArgType changeType, int changeCost, AIVirtualCard owner, List<AIVirtualCard> candidates, List<AIVirtualCard> targets)
|
||||
{
|
||||
switch (changeType)
|
||||
{
|
||||
case AIScriptTokenArgType.ADD:
|
||||
if (isTargetAll)
|
||||
{
|
||||
AddCostAll(changeCost, candidates);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddCostTarget(owner, changeCost, candidates, targets);
|
||||
}
|
||||
break;
|
||||
case AIScriptTokenArgType.SET:
|
||||
if (isTargetAll)
|
||||
{
|
||||
SetCostAll(changeCost, candidates);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCostTarget(owner, changeCost, candidates, targets);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError("ChangeCostValue: ilegal Cost Arg type [" + changeType.ToString() + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
SVSim.BattleEngine/Engine/Wizard/AIClashHeal.cs
Normal file
41
SVSim.BattleEngine/Engine/Wizard/AIClashHeal.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIClashHeal : AIFiltersAndSelectTypeArgument
|
||||
{
|
||||
private readonly int HEAL_ARG_OFFSET = 1;
|
||||
|
||||
private AIPolishConvertedExpression _healArg;
|
||||
|
||||
protected override int SELECT_TYPE_OFFSET => 2;
|
||||
|
||||
public AIClashHeal(string text)
|
||||
: base(text)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitExpressions(string text)
|
||||
{
|
||||
base.InitExpressions(text);
|
||||
_healArg = _exprList[_exprList.Count - HEAL_ARG_OFFSET];
|
||||
}
|
||||
|
||||
public override void Execute(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation = null)
|
||||
{
|
||||
List<AIVirtualCard> targetsFromField = GetTargetsFromField(tagOwner, field, playPtn, situation);
|
||||
if (targetsFromField != null && targetsFromField.Count > 0)
|
||||
{
|
||||
int heal = (int)_healArg.EvalArg(tagOwner, playPtn, field, situation);
|
||||
if (base.SelectType == AIScriptTokenArgType.ALL_SELECT)
|
||||
{
|
||||
AISkillSimulationUtility.HealAll(targetsFromField, field, heal, playPtn, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> GetFilteredTargets(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation, bool isBlockDead = true)
|
||||
{
|
||||
return AIFilteringUtility.FilteringForStatusEffectiveAbility(candidates, tagOwner, base.Filters, playPtn, situation, isAttackEffective: false, isBlockDead);
|
||||
}
|
||||
}
|
||||
197
SVSim.BattleEngine/Engine/Wizard/AICopyTagSimulationUtility.cs
Normal file
197
SVSim.BattleEngine/Engine/Wizard/AICopyTagSimulationUtility.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AICopyTagSimulationUtility
|
||||
{
|
||||
public static List<AIPlayTag> GetCopyTagListFromCard(AIVirtualCard target, List<AIScriptTokenArgType> timingList)
|
||||
{
|
||||
List<AIPlayTag> list = null;
|
||||
for (int i = 0; i < timingList.Count; i++)
|
||||
{
|
||||
AIScriptTokenArgType timing = timingList[i];
|
||||
List<AIPlayTag> copyTagOfCertainTiming = GetCopyTagOfCertainTiming(target, timing);
|
||||
if (copyTagOfCertainTiming != null && copyTagOfCertainTiming.Count > 0)
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(copyTagOfCertainTiming, list);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void ExecuteCopyAndAttachTagToAll(AIVirtualCard tagOwner, List<AIVirtualCard> targetList, List<AIScriptTokenArgType> skillTimingList, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (targetList == null || targetList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < targetList.Count; i++)
|
||||
{
|
||||
List<AIPlayTag> copyTagListFromCard = GetCopyTagListFromCard(targetList[i], skillTimingList);
|
||||
if (copyTagListFromCard != null)
|
||||
{
|
||||
AttachTagFromCopyTagList(tagOwner, tagOwner, copyTagListFromCard, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteCopyAndAttachTagToSelectedTarget(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, List<AIScriptTokenArgType> skillTimingList, AIScriptTokenArgType whichTarget, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (situation != null && situation.IsTargetExists(whichTarget))
|
||||
{
|
||||
CopyAndAttachTagToSituationTarget(tagOwner, candidates, skillTimingList, whichTarget, field, playPtn, situation);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyAndAttachTagPrediction(tagOwner, candidates, skillTimingList, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyAndAttachTagToSituationTarget(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, List<AIScriptTokenArgType> skillTimingList, AIScriptTokenArgType whichTarget, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.Targets != null)
|
||||
{
|
||||
ExecuteCopyAndAttachTagToAll(tagOwner, situationTarget.Targets, skillTimingList, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyAndAttachTagPrediction(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, List<AIScriptTokenArgType> skillTimingList, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard = SelecteBestCopyTarget(tagOwner, candidates, field, playPtn, situation);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
List<AIPlayTag> copyTagListFromCard = GetCopyTagListFromCard(aIVirtualCard, skillTimingList);
|
||||
if (copyTagListFromCard != null)
|
||||
{
|
||||
AttachTagFromCopyTagList(tagOwner, tagOwner, copyTagListFromCard, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard SelecteBestCopyTarget(AIVirtualCard attachTarget, List<AIVirtualCard> candidates, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard result = null;
|
||||
float num = float.MinValue;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
float num2 = 0f;
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenAttack))
|
||||
{
|
||||
num2 += (float)aIVirtualCard.TagCollectionContainer.AttackTags.TagList.Count * 1f;
|
||||
}
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword))
|
||||
{
|
||||
num2 += (float)aIVirtualCard.TagCollectionContainer.LastwordTags.TagList.Count * 1f;
|
||||
}
|
||||
num2 += (aIVirtualCard.IsQuick ? 3f : 0f);
|
||||
num2 += (aIVirtualCard.IsKiller ? 1f : 0f);
|
||||
num2 += (aIVirtualCard.IsDrain ? 1f : 0f);
|
||||
num2 += (aIVirtualCard.IsGuard ? 1f : 0f);
|
||||
if (aIVirtualCard.IsRush)
|
||||
{
|
||||
List<AIVirtualCard> list = (attachTarget.IsAlly ? field.EnemyInplayCards : field.AllyInplayCards);
|
||||
num2 += ((list != null && list.Count > 0) ? 1f : 0.5f);
|
||||
}
|
||||
if (num2 > num)
|
||||
{
|
||||
num = num2;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void AttachTagFromCopyTagList(AIVirtualCard tagOwner, AIVirtualCard attachTarget, List<AIPlayTag> copyTgList, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < copyTgList.Count; i++)
|
||||
{
|
||||
AIAttachTagSimulationUtility.SimulateAttachTagToSingle(attachTarget, tagOwner, copyTgList[i], AIScriptTokenArgType.NONE, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<AIPlayTag> GetCopyTagOfCertainTiming(AIVirtualCard target, AIScriptTokenArgType timing)
|
||||
{
|
||||
switch (timing)
|
||||
{
|
||||
case AIScriptTokenArgType.KILLER:
|
||||
case AIScriptTokenArgType.QUICK:
|
||||
case AIScriptTokenArgType.RUSH:
|
||||
case AIScriptTokenArgType.DRAIN:
|
||||
case AIScriptTokenArgType.GUARD:
|
||||
return CopyKeywordSkillTags(target, timing);
|
||||
case AIScriptTokenArgType.WHEN_DESTROY:
|
||||
return CopyWhenDestroyTags(target);
|
||||
case AIScriptTokenArgType.WHEN_ATTACK:
|
||||
return CopyWhenAttackTags(target);
|
||||
case AIScriptTokenArgType.WHEN_CLASH:
|
||||
return CopyWhenClashTags(target);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<AIPlayTag> CopyKeywordSkillTags(AIVirtualCard target, AIScriptTokenArgType skillType)
|
||||
{
|
||||
List<AIPlayTag> list = null;
|
||||
if (target.IsHoldKeywordSkill(skillType))
|
||||
{
|
||||
AIPlayTag aIPlayTag = AIPlayTagInitializingUtility.CreateBasicSkillTag(skillType);
|
||||
if (aIPlayTag == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
list = AIParamQuery.AddElementToList(aIPlayTag, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<AIPlayTag> CopyWhenDestroyTags(AIVirtualCard target)
|
||||
{
|
||||
List<AIPlayTag> list = null;
|
||||
if (target.TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword))
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(target.TagCollectionContainer.LastwordTags.TagList, list);
|
||||
}
|
||||
if (target.TagCollectionContainer.HasTag(AIPlayTagType.Break))
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(target.TagCollectionContainer.BreakBonusTags.TagList, list);
|
||||
}
|
||||
if (target.TagCollectionContainer.HasTag(AIPlayTagType.IgnoreBreak))
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(target.TagCollectionContainer.IgnoreBreakTags.TagList, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<AIPlayTag> CopyWhenAttackTags(AIVirtualCard target)
|
||||
{
|
||||
if (target.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenAttack))
|
||||
{
|
||||
return target.TagCollectionContainer.AttackTags.TagList;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<AIPlayTag> CopyWhenClashTags(AIVirtualCard target)
|
||||
{
|
||||
if (target.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenAttack))
|
||||
{
|
||||
AttackTagCollection attackTags = target.TagCollectionContainer.AttackTags;
|
||||
if (attackTags.HasClashTag)
|
||||
{
|
||||
return attackTags.ClashTags;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
122
SVSim.BattleEngine/Engine/Wizard/AICountdownChangeUtility.cs
Normal file
122
SVSim.BattleEngine/Engine/Wizard/AICountdownChangeUtility.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AICountdownChangeUtility
|
||||
{
|
||||
public static float EvalChantCountChange(AIVirtualCard actCard, int amount, List<int> playPtn, bool isSelect, AISituationInfo situation)
|
||||
{
|
||||
if (GetMemberChantFieldNum(actCard.SelfField, playPtn) <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
List<AIVirtualCard> allyClassAndInplayCards = actCard.SelfField.CardListSet.AllyClassAndInplayCards;
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < allyClassAndInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = allyClassAndInplayCards[i];
|
||||
if ((aIVirtualCard.CardIndex != actCard.CardIndex || aIVirtualCard.IsPlayer != actCard.IsPlayer) && aIVirtualCard.IsCountdownAmulet)
|
||||
{
|
||||
list.Add(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
if (playPtn != null && playPtn.Count > 0)
|
||||
{
|
||||
for (int j = 0; j < playPtn.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = actCard.SelfField.AllyHandCards[playPtn[j]];
|
||||
if ((aIVirtualCard2.CardIndex != actCard.CardIndex || aIVirtualCard2.IsPlayer != actCard.IsPlayer) && aIVirtualCard2.IsCountdownAmulet)
|
||||
{
|
||||
list.Add(aIVirtualCard2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSelect)
|
||||
{
|
||||
int bestCandidateIndex = 0;
|
||||
return CalcMaxSelectChantCountChangeBonus(amount, list, playPtn, ref bestCandidateIndex, situation);
|
||||
}
|
||||
return CalcAllChantCountChangeBonus(amount, list, playPtn, situation);
|
||||
}
|
||||
|
||||
public static float CalcMaxSelectChantCountChangeBonus(int amount, List<AIVirtualCard> targets, List<int> playPtn, ref int bestCandidateIndex, AISituationInfo situation)
|
||||
{
|
||||
float num = 0f;
|
||||
int count = targets.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
float num2 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: false, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
AIVirtualCard aIVirtualCard2 = new AIVirtualCard(aIVirtualCard, aIVirtualCard.SelfField);
|
||||
int chantCount = aIVirtualCard2.ChantCount;
|
||||
chantCount = ((chantCount > amount) ? (chantCount - amount) : 0);
|
||||
float num3 = 0f;
|
||||
if (chantCount > 0)
|
||||
{
|
||||
aIVirtualCard2.ChantCount = chantCount;
|
||||
num3 = aIVirtualCard2.EvaluateValueOnField(playPtn, situation, useStyle: false, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
num3 = aIVirtualCard.EvaluateBreakValue(playPtn, useIgnoreBreak: true);
|
||||
}
|
||||
float num4 = num3 - num2;
|
||||
if (num4 > num)
|
||||
{
|
||||
num = num4;
|
||||
bestCandidateIndex = i;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float CalcAllChantCountChangeBonus(int amount, List<AIVirtualCard> targets, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = 0f;
|
||||
int count = targets.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
float num2 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: false, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
AIVirtualCard aIVirtualCard2 = new AIVirtualCard(aIVirtualCard, aIVirtualCard.SelfField);
|
||||
int chantCount = aIVirtualCard2.ChantCount;
|
||||
chantCount = ((chantCount > amount) ? (chantCount - amount) : 0);
|
||||
float num3 = 0f;
|
||||
if (chantCount > 0)
|
||||
{
|
||||
aIVirtualCard2.ChantCount = chantCount;
|
||||
num3 = aIVirtualCard2.EvaluateValueOnField(playPtn, situation, useStyle: false, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
num3 = aIVirtualCard.EvaluateBreakValue(playPtn, useIgnoreBreak: true);
|
||||
}
|
||||
num += num3 - num2;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetMemberChantFieldNum(AIVirtualField field, List<int> handPtn)
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
if (field.AllyInplayCards[i].IsCountdownAmulet)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
if (handPtn != null)
|
||||
{
|
||||
for (int j = 0; j < handPtn.Count; j++)
|
||||
{
|
||||
if (field.AllyHandCards[handPtn[j]].IsCountdownAmulet)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
41
SVSim.BattleEngine/Engine/Wizard/AICrystalizeUtility.cs
Normal file
41
SVSim.BattleEngine/Engine/Wizard/AICrystalizeUtility.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AICrystalizeUtility
|
||||
{
|
||||
public static bool IsCrystalize(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (card == null || card.CrystalizeCostList == null || !card.IsInHand)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AIVariableResultContainer valResultContainer = field.AI.ValResultContainer;
|
||||
ulong hash = AIFunctionResultHashCalculator.GetHash(card, field, playPtn, null, 0uL);
|
||||
if (valResultContainer.GetContainsResultValue(AIScriptTokenVariableType.IS_CRYSTALIZE, hash, out var getResult))
|
||||
{
|
||||
return getResult == 1f;
|
||||
}
|
||||
List<int> playPtn2 = (card.IsAlly ? playPtn : null);
|
||||
bool flag = field.AI.PlayPtnRecorder.IsCardPlayingSimulationType(card, field, playPtn2, situation, PlaySimulationType.Crystalize);
|
||||
valResultContainer.CheckDuplicateAndAddRecord(AIScriptTokenVariableType.IS_CRYSTALIZE, hash, flag ? 1f : 0f, $"IsCrystalize(): Already hashed target and not equal value. CardName:[{card.CardName}] hash:[{hash}]");
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static int GetCrystalizeId(AIVirtualCard card, int usedCost)
|
||||
{
|
||||
if (card.CrystalizeCostList == null || card.CrystalizeCostList.Count <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < card.CrystalizeCostList.Count; i++)
|
||||
{
|
||||
AICrystalizeInformation aICrystalizeInformation = card.CrystalizeCostList[i];
|
||||
if (aICrystalizeInformation.Cost == usedCost)
|
||||
{
|
||||
return aICrystalizeInformation.CardId;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
53
SVSim.BattleEngine/Engine/Wizard/AIDamageClippingInfo.cs
Normal file
53
SVSim.BattleEngine/Engine/Wizard/AIDamageClippingInfo.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDamageClippingInfo : AIBarrierInfoBase
|
||||
{
|
||||
public override AIBarrierType BarrierType => AIBarrierType.DamageClipping;
|
||||
|
||||
public int ClippingRange { get; protected set; } = 9999;
|
||||
|
||||
public AIDamageClippingInfo(int amount, int range, AIDamageType damageType, AIBarrierStopTiming stopTiming)
|
||||
: base(amount, damageType, stopTiming)
|
||||
{
|
||||
ClippingRange = range;
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public AIDamageClippingInfo(int amount, int range, AIDamageType damageType, List<AIBarrierStopTiming> stopTimingList)
|
||||
: base(amount, damageType, stopTimingList)
|
||||
{
|
||||
ClippingRange = range;
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public override AIBarrierInfoBase Clone()
|
||||
{
|
||||
return new AIDamageClippingInfo(base.BarrierAmount, ClippingRange, base.DamageType, base.StopTimingList);
|
||||
}
|
||||
|
||||
public override bool IsShield()
|
||||
{
|
||||
if (ClippingRange == 9999)
|
||||
{
|
||||
return base.BarrierAmount <= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override int CalcDamage(AIVirtualCard owner, int damage)
|
||||
{
|
||||
if (damage > ClippingRange)
|
||||
{
|
||||
return damage;
|
||||
}
|
||||
return Mathf.Min(damage, base.BarrierAmount);
|
||||
}
|
||||
|
||||
protected override void UpdateHash()
|
||||
{
|
||||
base.Hash = AIBarrierSimulationUtility.CalculateDamageClipInfoHash(base.DamageType, BarrierType, base.StopTimingList, base.BarrierAmount, ClippingRange);
|
||||
}
|
||||
}
|
||||
41
SVSim.BattleEngine/Engine/Wizard/AIDamageCutInfo.cs
Normal file
41
SVSim.BattleEngine/Engine/Wizard/AIDamageCutInfo.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDamageCutInfo : AIBarrierInfoBase
|
||||
{
|
||||
public override AIBarrierType BarrierType => AIBarrierType.DamageCut;
|
||||
|
||||
public AIDamageCutInfo(int amount, AIDamageType damageType, AIBarrierStopTiming stopTiming)
|
||||
: base(amount, damageType, stopTiming)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public AIDamageCutInfo(int amount, AIDamageType damageType, List<AIBarrierStopTiming> stopTimingList)
|
||||
: base(amount, damageType, stopTimingList)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public override AIBarrierInfoBase Clone()
|
||||
{
|
||||
return new AIDamageCutInfo(base.BarrierAmount, base.DamageType, base.StopTimingList);
|
||||
}
|
||||
|
||||
public override bool IsShield()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override int CalcDamage(AIVirtualCard owner, int damage)
|
||||
{
|
||||
return Mathf.Max(0, damage - base.BarrierAmount);
|
||||
}
|
||||
|
||||
protected override void UpdateHash()
|
||||
{
|
||||
base.Hash = AIBarrierSimulationUtility.CalculateDamageCutInfoHash(base.DamageType, BarrierType, base.StopTimingList, base.BarrierAmount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDamageSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
private const int DAMAGE_VALUE_ARG_INDEX = 0;
|
||||
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.DAMAGE_LOGIC;
|
||||
|
||||
public AIDamageSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int damageValue = GetDamageValue(tagOwner, field, playPtn, situation);
|
||||
return AIDamageSimulationUtility.SelectDamageTarget(candidates, field, playPtn, situation, damageValue, tagOwner.IsSpell, worstOrBest);
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
LogNotImplementMultipleSelect();
|
||||
return null;
|
||||
}
|
||||
|
||||
private int GetDamageValue(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (_argumentList == null || _argumentList.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIDamageSelectLogicArgument error!! _argumentList is null");
|
||||
return 0;
|
||||
}
|
||||
return (int)_argumentList[0].EvalArg(tagOwner, playPtn, field, situation);
|
||||
}
|
||||
}
|
||||
657
SVSim.BattleEngine/Engine/Wizard/AIDamageSimulationUtility.cs
Normal file
657
SVSim.BattleEngine/Engine/Wizard/AIDamageSimulationUtility.cs
Normal file
@@ -0,0 +1,657 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIDamageSimulationUtility
|
||||
{
|
||||
public static float EvalTargetingDamageAndRandomMultiSelectDamage(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> targetFilters, List<AIScriptTokenBase> randomFilters, List<int> playPtn, AISituationInfo situation, int targetDamage, int randomDamage, int randomDamageCount)
|
||||
{
|
||||
if (tagOwner == null || field == null || targetFilters == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int num = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, targetDamage);
|
||||
int damageAmount = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, randomDamage);
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, targetFilters, tagOwner, playPtn, situation);
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
list = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
float num2 = float.MinValue;
|
||||
int count = list.Count;
|
||||
AIVirtualCard target = null;
|
||||
for (int num3 = 0; num3 < count; num3++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[num3];
|
||||
if (aIVirtualCard.IsAlly == tagOwner.IsAlly || (!aIVirtualCard.IsUntouchable && !aIVirtualCard.IsSneak))
|
||||
{
|
||||
float num4 = 0f;
|
||||
num4 = ((!aIVirtualCard.IsLeader) ? EvalDamageToCertainUnit(tagOwner, aIVirtualCard, field, num, playPtn, situation, field.AllyHandCards.Contains(tagOwner)) : AILeaderLifeEvaluationUtility.Evaluate(CalcLifeAfterDamage(aIVirtualCard, situation, num, tagOwner.IsSpell), aIVirtualCard.Life, aIVirtualCard.IsAlly, tagOwner.IsAlly));
|
||||
if (num4 > num2)
|
||||
{
|
||||
num2 = num4;
|
||||
target = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target == null)
|
||||
{
|
||||
return AIRandomMultiDamageEvaluator.EvaluateRandomDamageAverage(tagOwner, field, playPtn, situation, targetFilters, damageAmount, randomDamageCount);
|
||||
}
|
||||
int num5 = target.SimulateDamageAmount(num, tagOwner.IsUnit, tagOwner.IsSpell);
|
||||
float num6 = 0f;
|
||||
int num7 = CalcLifeAfterDamage(target, situation, num, tagOwner.IsSpell);
|
||||
if (num7 <= 0)
|
||||
{
|
||||
int num8 = target.Life - num7;
|
||||
float num9 = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - (target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false)) + (float)(num8 - target.Life) * -0.1f;
|
||||
num6 = (target.IsAlly ? (0f - num9) : num9);
|
||||
new List<AIVirtualCard>(field.CardListSet.BothClassAndInplayCards).RemoveAll((AIVirtualCard c) => c.Equals(target));
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = field.CardListSet.BothClassAndInplayCards;
|
||||
num6 = target.EvaluateValueOnField(playPtn, situation, useStyle: true);
|
||||
target.Life -= num5;
|
||||
num6 -= target.EvaluateValueOnField(playPtn, situation, useStyle: true);
|
||||
target.Life += num5;
|
||||
}
|
||||
target.Life -= num5;
|
||||
num6 += AIRandomMultiDamageEvaluator.EvaluateRandomDamageAverage(tagOwner, field, playPtn, situation, targetFilters, damageAmount, randomDamageCount);
|
||||
target.Life += num5;
|
||||
return num6;
|
||||
}
|
||||
|
||||
public static float EvalTargetingDamage(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, int damage)
|
||||
{
|
||||
if (tagOwner == null || field == null || filters == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
list = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
int damage2 = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
float num = float.MinValue;
|
||||
int count = list.Count;
|
||||
if (count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
for (int num2 = 0; num2 < count; num2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[num2];
|
||||
if (aIVirtualCard.IsAlly == tagOwner.IsAlly || (!aIVirtualCard.IsUntouchable && !aIVirtualCard.IsSneak))
|
||||
{
|
||||
float num3 = 0f;
|
||||
num3 = ((!aIVirtualCard.IsLeader) ? EvalDamageToCertainUnit(tagOwner, aIVirtualCard, field, damage2, playPtn, situation, field.AllyHandCards.Contains(tagOwner)) : AILeaderLifeEvaluationUtility.Evaluate(CalcLifeAfterDamage(aIVirtualCard, situation, damage2, tagOwner.IsSpell), aIVirtualCard.Life, aIVirtualCard.IsAlly, tagOwner.IsAlly));
|
||||
if (num3 > num)
|
||||
{
|
||||
num = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num == float.MinValue)
|
||||
{
|
||||
num = 0f;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static float EvalDamageToCertainUnit(AIVirtualCard tagOwner, AIVirtualCard target, AIVirtualField field, int damage, List<int> playPtn, AISituationInfo situation, bool isWhenPlaySkill)
|
||||
{
|
||||
float num = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - (target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false));
|
||||
int life = target.Life;
|
||||
float num2 = 0f;
|
||||
int num3 = CalcLifeAfterDamage(target, situation, damage, tagOwner.IsSpell);
|
||||
if (num3 <= 0)
|
||||
{
|
||||
int num4 = life - num3;
|
||||
float num5 = num + (float)(num4 - life) * -0.1f;
|
||||
num2 = (target.IsAlly ? (0f - num5) : num5);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target.IsAlly)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
if (target.IsCantUnderAnyAttack())
|
||||
{
|
||||
num2 += 0f;
|
||||
}
|
||||
else if (field.ParamQuery.GetEnemyGuardiansCount() > 0 && !target.IsGuard && !tagOwner.IsIgnoreGuard)
|
||||
{
|
||||
num2 += 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(null, target);
|
||||
List<int> list = new List<int>();
|
||||
List<int> list2 = new List<int>();
|
||||
List<float> list3 = new List<float>();
|
||||
if (tagOwner.IsUnit && isWhenPlaySkill && tagOwner.IsAbleEvolution())
|
||||
{
|
||||
aIVirtualAttackInfo.SetActor(tagOwner);
|
||||
list.Add(tagOwner.SimulateAttackAmount(tagOwner.Attack + tagOwner.EvoAttackPlus, aIVirtualAttackInfo));
|
||||
list2.Add(tagOwner.Life + tagOwner.EvoLifePlus);
|
||||
list3.Add(tagOwner.EvaluateValueOnField(playPtn, situation, useStyle: true));
|
||||
}
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyInplayCards[i];
|
||||
if (aIVirtualCard.IsUnit && !aIVirtualCard.IsDead && aIVirtualCard.IsAttackable(EnemyAI.EmptyPlayPtn))
|
||||
{
|
||||
aIVirtualAttackInfo.SetActor(aIVirtualCard);
|
||||
list.Add(aIVirtualCard.SimulateAttackAmount(aIVirtualAttackInfo));
|
||||
list2.Add(aIVirtualCard.Life);
|
||||
list3.Add(aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true));
|
||||
}
|
||||
}
|
||||
int num6 = (int)Mathf.Pow(2f, list.Count);
|
||||
for (int j = 0; j < num6; j++)
|
||||
{
|
||||
int num7 = j;
|
||||
int num8 = 0;
|
||||
int num9 = 0;
|
||||
float num10 = 0f;
|
||||
float num11 = 0f;
|
||||
while (num7 > 0)
|
||||
{
|
||||
if (num7 % 2 == 1)
|
||||
{
|
||||
num9 += list[num8];
|
||||
if (list2[num8] <= target.Attack)
|
||||
{
|
||||
num10 += list3[num8];
|
||||
}
|
||||
}
|
||||
num8++;
|
||||
num7 /= 2;
|
||||
}
|
||||
num9 = target.SimulateDamageAmount(num9);
|
||||
num11 = ((num9 >= life) ? (num11 + 0f) : ((num9 >= num3) ? (num11 + (num - num10)) : (num11 + 0f)));
|
||||
if (num2 < num11)
|
||||
{
|
||||
num2 = num11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return num2;
|
||||
}
|
||||
|
||||
public static float EvalRandomMultiSelectDamage(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, int damage, int selectCount)
|
||||
{
|
||||
if (tagOwner == null || field == null || filters == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
if (list.Count <= selectCount)
|
||||
{
|
||||
return CalculateMultiAllDamage(tagOwner, list, field, playPtn, situation, damage, 1);
|
||||
}
|
||||
int num = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
List<float> list2 = new List<float>();
|
||||
List<int> list3 = new List<int>();
|
||||
for (int num2 = 0; num2 < list.Count; num2++)
|
||||
{
|
||||
list2.Add(list[num2].EvaluateValueOnField(playPtn, situation, useStyle: true) - list[num2].GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - list[num2].GetAllLeaveBonus(playPtn, useIgnoreInBattle: false));
|
||||
list3.Add(num2);
|
||||
}
|
||||
List<int[]> list4 = AIMathematicsLibrary.EnumerateCombinations(list3, selectCount).ToList();
|
||||
if (list4 == null || list4.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num3 = 0f;
|
||||
for (int num4 = 0; num4 < list4.Count; num4++)
|
||||
{
|
||||
int[] array = list4[num4];
|
||||
float num5 = 0f;
|
||||
for (int num6 = 0; num6 < array.Length; num6++)
|
||||
{
|
||||
int num7 = CalcLifeAfterDamage(list[array[num6]], situation, num, tagOwner.IsSpell);
|
||||
num5 += ((num7 <= 0) ? list2[array[num6]] : ((float)num));
|
||||
}
|
||||
num3 += num5;
|
||||
}
|
||||
return num3 / (float)list4.Count;
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public static int CalcLifeAfterDamage(AIVirtualCard target, AISituationInfo situation, int damage, bool isSpell)
|
||||
{
|
||||
int num = target.SimulateDamageAmount(damage, isSkillDamage: true, isSpell);
|
||||
int num2 = target.Life - num;
|
||||
int atkBuff = 0;
|
||||
int lifeBuff = 0;
|
||||
if (target.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenDamaged))
|
||||
{
|
||||
target.TagCollectionContainer.DamagedTags.GetDamagedBuffValue(target, target.SelfField, target.SelfField.BestPlayPtn, situation, out atkBuff, out lifeBuff);
|
||||
num2 += lifeBuff;
|
||||
}
|
||||
return num2;
|
||||
}
|
||||
|
||||
public static float EvalEchoDamage(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, int damage, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
float item = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true) - aIVirtualCard.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - aIVirtualCard.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
List<AIVirtualCard> list2 = new List<AIVirtualCard> { aIVirtualCard };
|
||||
List<float> list3 = new List<float> { item };
|
||||
List<AIVirtualCard> list4 = (aIVirtualCard.IsAlly ? field.AllyInplayCards : field.EnemyInplayCards);
|
||||
for (int j = 0; j < list4.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list4[j];
|
||||
if (!aIVirtualCard2.IsSameCard(aIVirtualCard) && aIVirtualCard2.BaseId == aIVirtualCard.BaseId)
|
||||
{
|
||||
list2.Add(aIVirtualCard2);
|
||||
float item2 = aIVirtualCard2.EvaluateValueOnField(playPtn, situation, useStyle: true) - aIVirtualCard2.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - aIVirtualCard2.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
list3.Add(item2);
|
||||
}
|
||||
}
|
||||
float num2 = 0f;
|
||||
for (int k = 0; k < list2.Count; k++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard3 = list2[k];
|
||||
int damageAmount = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
damageAmount = aIVirtualCard3.SimulateDamageAmount(damageAmount, isSkillDamage: true, tagOwner.IsSpell);
|
||||
if (damageAmount >= aIVirtualCard3.Life)
|
||||
{
|
||||
num2 += list3[k];
|
||||
}
|
||||
}
|
||||
if (EnemyAI.IsLargerThan(num2, num))
|
||||
{
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectDamageTarget(List<AIVirtualCard> candidates, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int damage, bool isSpell, AISelectTargetPattern bestOrWorst)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AISimulationDamageUtility.SelectDamageTarget() : candidates is null ");
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard result = null;
|
||||
float num = ((bestOrWorst == AISelectTargetPattern.Worst) ? float.MaxValue : float.MinValue);
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (!aIVirtualCard.IsDead)
|
||||
{
|
||||
float damageValueToCertainTarget = GetDamageValueToCertainTarget(aIVirtualCard, damage, situation, playPtn, isSpell);
|
||||
bool flag = false;
|
||||
switch (bestOrWorst)
|
||||
{
|
||||
case AISelectTargetPattern.Worst:
|
||||
flag = num > damageValueToCertainTarget;
|
||||
break;
|
||||
case AISelectTargetPattern.Best:
|
||||
flag = damageValueToCertainTarget > num;
|
||||
break;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
num = damageValueToCertainTarget;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float GetDamageValueToCertainTarget(AIVirtualCard target, int damage, AISituationInfo situation, List<int> playPtn, bool isSpell)
|
||||
{
|
||||
float num = 0f;
|
||||
int num2 = CalcLifeAfterDamage(target, situation, damage, isSpell);
|
||||
float num3 = target.EvaluateValueOnField(playPtn, situation, useStyle: true);
|
||||
if (num2 <= 0)
|
||||
{
|
||||
num = num3 - target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
float num4 = 0.01f;
|
||||
num = (float)(target.Life - num2) + num3 * num4;
|
||||
}
|
||||
return num * (target.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
|
||||
public static float EvalOldestDamage(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, AIVirtualField field, int damage, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = 0f;
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int num2 = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
if (aIVirtualCard2.IsLeader)
|
||||
{
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else
|
||||
{
|
||||
AIConsoleUtility.LogError("EvalOldestDamage(): Already selected leader card! Candidate cards is illegal.");
|
||||
}
|
||||
}
|
||||
else if (aIVirtualCard2.IsUnit)
|
||||
{
|
||||
int life = aIVirtualCard2.Life;
|
||||
int num3 = ((num2 < life) ? num2 : life);
|
||||
num += EvalDamageToCertainUnit(tagOwner, aIVirtualCard2, field, num3, playPtn, situation, field.AllyHandCards.Contains(tagOwner));
|
||||
num2 -= num3;
|
||||
if (num2 <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard != null && num2 > 0)
|
||||
{
|
||||
AIBarrierPseudoSimulationInfo aIBarrierPseudoSimulationInfo = new AIBarrierPseudoSimulationInfo(aIVirtualCard);
|
||||
bool isSpell = tagOwner.IsSpell;
|
||||
int num4 = aIBarrierPseudoSimulationInfo.SimulateDamageAmount(aIVirtualCard.SimulateDamageShield(damage, isSkillDamage: true, isSpell), isSpell);
|
||||
num += AILeaderLifeEvaluationUtility.Evaluate(aIVirtualCard.Life - num4, aIVirtualCard.Life, aIVirtualCard.IsAlly, tagOwner.IsAlly);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float EvalMultiAllDamage(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, int damage, int damageCount)
|
||||
{
|
||||
if (tagOwner == null || field == null || filters == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
if (!list.IsNotNullOrEmpty())
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
AIFunctionResultContainer funcResultContainer = field.AI.FuncResultContainer;
|
||||
ulong hash = AIFunctionResultHashCalculator.GetHash(tagOwner, field, playPtn, null, GetArgumentHash(list, damage, damageCount));
|
||||
if (funcResultContainer.GetContainsResultValue(AIScriptTokenFuncType.EVAL_ALL_MULTI_DAMAGE, hash, out var getResult))
|
||||
{
|
||||
return getResult;
|
||||
}
|
||||
float result = CalculateMultiAllDamage(tagOwner, list, field, playPtn, situation, damage, damageCount);
|
||||
funcResultContainer.AddRecord(AIScriptTokenFuncType.EVAL_ALL_MULTI_DAMAGE, hash, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float CalculateMultiAllDamage(AIVirtualCard tagOwner, List<AIVirtualCard> targetList, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int damage, int damageCount)
|
||||
{
|
||||
float num = 0f;
|
||||
List<AIVirtualCardStatusInfo> list = new List<AIVirtualCardStatusInfo>();
|
||||
List<AIVirtualCardStatusInfo> list2 = new List<AIVirtualCardStatusInfo>();
|
||||
int damageAmount = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
bool isSpell = tagOwner.IsSpell;
|
||||
for (int i = 0; i < targetList.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targetList[i];
|
||||
int num2 = aIVirtualCard.Life;
|
||||
AIBarrierPseudoSimulationInfo aIBarrierPseudoSimulationInfo = new AIBarrierPseudoSimulationInfo(aIVirtualCard);
|
||||
for (int j = 0; j < damageCount; j++)
|
||||
{
|
||||
int num3 = aIBarrierPseudoSimulationInfo.SimulateDamageAmount(aIVirtualCard.SimulateDamageShield(damageAmount, isSkillDamage: true, isSpell), isSpell);
|
||||
num2 -= num3;
|
||||
if (num2 <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
aIBarrierPseudoSimulationInfo.DepriveBarrier(AIBarrierStopTiming.AfterDamage);
|
||||
}
|
||||
if (aIVirtualCard.IsLeader)
|
||||
{
|
||||
num += AILeaderLifeEvaluationUtility.Evaluate(num2, aIVirtualCard.Life, aIVirtualCard.IsAlly, tagOwner.IsAlly);
|
||||
}
|
||||
else if (num2 <= 0)
|
||||
{
|
||||
float num4 = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true) - aIVirtualCard.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - aIVirtualCard.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
num += num4 * (aIVirtualCard.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
else if (!aIVirtualCard.IsAlly || aIVirtualCard.IsAttackable(playPtn))
|
||||
{
|
||||
(aIVirtualCard.IsAlly ? list : list2).Add(new AIVirtualCardStatusInfo(aIVirtualCard, aIVirtualCard.Attack, num2));
|
||||
}
|
||||
}
|
||||
if (list2.Count > 0 && list.Count > 0)
|
||||
{
|
||||
num += AISimulationUtility.EvaluateAttackValueAfterAllSkill(field, situation, list, list2, playPtn);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static void DamageAll(List<AIVirtualCard> targets, AIVirtualCard damageOwner, AIVirtualField field, int damage, AISituationInfo situation)
|
||||
{
|
||||
int baseDamage = field.DamageModifierCollection.CalcModifiedDamage(field, field.BestPlayPtn, situation, damageOwner, damage);
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if ((targets[i].IsUnit || targets[i].IsLeader) && !targets[i].IsDead && !targets[i].IsIndependent)
|
||||
{
|
||||
targets[i].AddDamage(situation, baseDamage, isSkillDamage: true);
|
||||
if (targets[i].IsLeader && targets[i].IsAlly)
|
||||
{
|
||||
field.AllyDamageCountInGame++;
|
||||
field.AllyDamageCountInTurn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < targets.Count; j++)
|
||||
{
|
||||
if (targets[j].IsDead)
|
||||
{
|
||||
targets[j].RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DamageRandom(List<AIVirtualCard> targets, AIVirtualCard damageOwner, AIVirtualField field, int damage, AISituationInfo situation)
|
||||
{
|
||||
List<int> bestPlayPtn = field.BestPlayPtn;
|
||||
AIVirtualCard aIVirtualCard = SelectDamageTarget(targets, field, bestPlayPtn, situation, damage, damageOwner.IsSpell, AISelectTargetPattern.Worst);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsDead)
|
||||
{
|
||||
int baseDamage = field.DamageModifierCollection.CalcModifiedDamage(field, bestPlayPtn, situation, damageOwner, damage);
|
||||
aIVirtualCard.AddDamage(situation, baseDamage, isSkillDamage: true);
|
||||
if (aIVirtualCard.IsDead)
|
||||
{
|
||||
aIVirtualCard.RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DamageTarget(AISituationInfo situation, List<AIVirtualCard> candidates, AIVirtualCard damageOwner, AIVirtualField field, AIScriptTokenArgType whichTarget, int damage, int count)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("DamageTarget error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
int baseDamage = field.DamageModifierCollection.CalcModifiedDamage(field, field.BestPlayPtn, situation, damageOwner, damage);
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
bool flag = candidates.Contains(aIVirtualCard);
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
if (aIVirtualCard.Life <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
aIVirtualCard.AddDamage(situation, baseDamage, isSkillDamage: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < targets.Count; k++)
|
||||
{
|
||||
if (targets[k].IsDead)
|
||||
{
|
||||
targets[k].RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteTargetSelectDamage(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType selectType, int damageAmount, int selectCount = 1)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("ExecuteTargetSelectDamage() Error!! situation is null!!!!!");
|
||||
}
|
||||
else if (situation.IsTargetExists(selectType))
|
||||
{
|
||||
DamageTarget(situation, candidates, tagOwner, field, selectType, damageAmount, selectCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
DamageTargetPrediction(situation, candidates, tagOwner, field, playPtn, selectType, damageAmount, selectCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DamageTargetPrediction(AISituationInfo situation, List<AIVirtualCard> candidates, AIVirtualCard damageOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType whichTarget, int damage, int count)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
List<AIVirtualCard> candidates2 = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(candidates, damageOwner, playPtn);
|
||||
if (count == 1)
|
||||
{
|
||||
AIVirtualCard target = SelectDamageTarget(candidates2, field, playPtn, situation, damage, damageOwner.IsSpell, AISelectTargetPattern.Best);
|
||||
situation.SetSingleTargetInInfo(target, TargetSelectType.Default, whichTarget);
|
||||
DamageTarget(situation, candidates2, damageOwner, field, whichTarget, damage, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
AIConsoleUtility.LogError("DamageTargetPrediction(): 複数選択ダメージのPrediction未対応");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DamageRandomMultiSelect(List<AIVirtualCard> targets, AIVirtualCard owner, AIVirtualField field, int damage, int selectCount, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = null;
|
||||
List<int> bestPlayPtn = field.BestPlayPtn;
|
||||
for (int i = 0; i < selectCount; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectDamageTarget(targets, field, bestPlayPtn, situation, damage, owner.IsSpell, AISelectTargetPattern.Worst);
|
||||
if (aIVirtualCard == null || aIVirtualCard.IsDead)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int baseDamage = field.DamageModifierCollection.CalcModifiedDamage(field, bestPlayPtn, situation, owner, damage);
|
||||
aIVirtualCard.AddDamage(situation, baseDamage, isSkillDamage: true);
|
||||
targets.Remove(aIVirtualCard);
|
||||
if (targets.Count <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIVirtualCard.IsDead)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIVirtualCard, list);
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
{
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
list[j].RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DamageOldOrderedTargets(List<AIVirtualCard> targets, int damage, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (targets == null || targets.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int num = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damage);
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
List<AIVirtualCard> list = null;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (num <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard2 = targets[i];
|
||||
if (aIVirtualCard2.IsAlly != tagOwner.IsAlly && aIVirtualCard2.IsLeader)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
continue;
|
||||
}
|
||||
int num2 = 0;
|
||||
num2 = ((aIVirtualCard != null || i != targets.Count - 1) ? Math.Min(aIVirtualCard2.Life, num) : num);
|
||||
num -= num2;
|
||||
aIVirtualCard2.AddDamage(situation, num2, isSkillDamage: true);
|
||||
if (aIVirtualCard2.IsDead)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIVirtualCard2, list);
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard != null && num > 0)
|
||||
{
|
||||
aIVirtualCard.AddDamage(situation, num, isSkillDamage: true);
|
||||
if (aIVirtualCard.IsDead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
{
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
list[j].RemoveCard(situation, AIRemovalType.Destroy, isFromSkill: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ulong GetArgumentHash(List<AIVirtualCard> targets, int damage, int damageCount)
|
||||
{
|
||||
ulong[] array = new ulong[12]
|
||||
{
|
||||
907uL, 911uL, 919uL, 929uL, 937uL, 941uL, 947uL, 953uL, 967uL, 971uL,
|
||||
977uL, 983uL
|
||||
};
|
||||
ulong num = 0uL;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
num += targets[i].GetHash() * array[i];
|
||||
}
|
||||
num += (ulong)((long)damage * 3L);
|
||||
return num + (ulong)((long)damageCount * 313L);
|
||||
}
|
||||
}
|
||||
21
SVSim.BattleEngine/Engine/Wizard/AIDeckSimulationUtility.cs
Normal file
21
SVSim.BattleEngine/Engine/Wizard/AIDeckSimulationUtility.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIDeckSimulationUtility
|
||||
{
|
||||
public static List<AIVirtualCard> GetFilteredDeck(List<AIScriptTokenBase> filter, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.IsAlly ? field.AI.AllyDeckCards : field.AI.EnemyDeckCards, filter, tagOwner, playPtn, situation);
|
||||
if (list == null)
|
||||
{
|
||||
list = new List<AIVirtualCard>();
|
||||
}
|
||||
List<AIVirtualCard> list2 = AIFilteringUtility.MultipleFiltering(field.DummyDeckContainer.GetDeck(tagOwner.IsAlly), filter, tagOwner, playPtn, situation);
|
||||
if (list2 != null)
|
||||
{
|
||||
list.AddRange(list2);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDefaultSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.DEFAULT_LOGIC;
|
||||
|
||||
public AIDefaultSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
int num = Mathf.Min(candidates.Count, selectCount);
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
list.Add(candidates[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIDestroySelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.DESTROY_LOGIC;
|
||||
|
||||
public AIDestroySelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Destroy);
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Destroy, selectCount);
|
||||
}
|
||||
}
|
||||
343
SVSim.BattleEngine/Engine/Wizard/AIDestroySimulationUtility.cs
Normal file
343
SVSim.BattleEngine/Engine/Wizard/AIDestroySimulationUtility.cs
Normal file
@@ -0,0 +1,343 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIDestroySimulationUtility
|
||||
{
|
||||
public static float CalcEvalDestroy(AIVirtualCard card, List<int> playPtn, AISituationInfo situation, bool useIgnoreBreak)
|
||||
{
|
||||
return (card.EvaluateValueOnField(playPtn, situation, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreBreak) - card.GetAllBreakBonus(playPtn, useIgnoreBreak) - card.GetAllLeaveBonus(playPtn, useIgnoreBreak)) * (card.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
|
||||
public static float EvalTargetingDestroy(List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
int num = 0;
|
||||
float num2 = float.MinValue;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (aIVirtualCard.IsAlly == tagOwner.IsAlly || (!aIVirtualCard.IsUntouchable && !aIVirtualCard.IsSneak))
|
||||
{
|
||||
num++;
|
||||
float num3 = 0f;
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsIndestructible)
|
||||
{
|
||||
num3 = CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false);
|
||||
}
|
||||
if (num3 > num2)
|
||||
{
|
||||
num2 = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
num2 = 0f;
|
||||
}
|
||||
return num2;
|
||||
}
|
||||
|
||||
public static float EvalTargetingOtherDestroy(List<AIScriptTokenBase> target_filters, List<AIScriptTokenBase> destroy_filters, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation, int select_count)
|
||||
{
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(selfField.CardListSet.BothInplayCards, target_filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list2 = null;
|
||||
List<float> list3 = new List<float>();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (aIVirtualCard.IsUntouchable || aIVirtualCard.IsSneak)
|
||||
{
|
||||
if (list2 == null)
|
||||
{
|
||||
list2 = new List<AIVirtualCard>();
|
||||
}
|
||||
list2.Add(aIVirtualCard);
|
||||
bool flag = AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, selfField.AllyHandCards, destroy_filters, playPtn, tagOwner, situation);
|
||||
if (aIVirtualCard.IsIndependent || aIVirtualCard.IsIndestructible || !flag)
|
||||
{
|
||||
list3.Add(0f);
|
||||
continue;
|
||||
}
|
||||
float item = CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false);
|
||||
list3.Add(item);
|
||||
}
|
||||
}
|
||||
if (list2 != null && list.Count - list2.Count < select_count)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list4 = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
List<float> list5 = null;
|
||||
for (int j = 0; j < list4.Count; j++)
|
||||
{
|
||||
if (list5 == null)
|
||||
{
|
||||
list5 = new List<float>();
|
||||
}
|
||||
AIVirtualCard aIVirtualCard2 = list4[j];
|
||||
bool flag2 = AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard2, selfField.AllyHandCards, destroy_filters, playPtn, tagOwner, situation);
|
||||
if (aIVirtualCard2.IsIndependent || aIVirtualCard2.IsIndestructible || !flag2)
|
||||
{
|
||||
list5.Add(0f);
|
||||
continue;
|
||||
}
|
||||
float item2 = CalcEvalDestroy(aIVirtualCard2, playPtn, situation, useIgnoreBreak: false);
|
||||
list5.Add(item2);
|
||||
}
|
||||
list5?.Sort((float score0, float score1) => (int)(score1 - score0));
|
||||
List<AIVirtualCard> list6 = new List<AIVirtualCard>();
|
||||
for (int num = 0; num < list.Count; num++)
|
||||
{
|
||||
int num2 = 0;
|
||||
for (num2 = 0; num2 < list4.Count; num2++)
|
||||
{
|
||||
if (list[num].Equals(list4[num2]))
|
||||
{
|
||||
num2 = 99999999;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int num3 = 0;
|
||||
num3 = 0;
|
||||
while (list2 != null && num3 < list2.Count)
|
||||
{
|
||||
if (list[num].Equals(list2[num3]))
|
||||
{
|
||||
num3 = 99999999;
|
||||
break;
|
||||
}
|
||||
num3++;
|
||||
}
|
||||
if (num2 != 99999999 && num3 != 99999999)
|
||||
{
|
||||
list6.Add(list[num]);
|
||||
}
|
||||
}
|
||||
List<float> list7 = null;
|
||||
if (list6.Count > 0)
|
||||
{
|
||||
list7 = new List<float>();
|
||||
for (int num4 = 0; num4 < list6.Count; num4++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard3 = list6[num4];
|
||||
bool flag3 = AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard3, selfField.AllyHandCards, destroy_filters, playPtn, tagOwner, situation);
|
||||
if (aIVirtualCard3.IsIndependent || aIVirtualCard3.IsIndestructible || !flag3)
|
||||
{
|
||||
list7.Add(0f);
|
||||
continue;
|
||||
}
|
||||
float item3 = CalcEvalDestroy(aIVirtualCard3, playPtn, situation, useIgnoreBreak: false);
|
||||
list7.Add(item3);
|
||||
}
|
||||
list7.Sort((float score0, float score1) => (int)(score1 - score0));
|
||||
}
|
||||
List<float> list8 = new List<float>();
|
||||
if (list3 != null)
|
||||
{
|
||||
list8.AddRange(list3);
|
||||
}
|
||||
if (list7 != null)
|
||||
{
|
||||
list8.AddRange(list7);
|
||||
}
|
||||
if (list5 != null)
|
||||
{
|
||||
list8.AddRange(list5);
|
||||
}
|
||||
int num5 = list.Count - select_count;
|
||||
if (num5 >= list8.Count)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num6 = 0f;
|
||||
for (int num7 = 0; num7 < num5; num7++)
|
||||
{
|
||||
num6 += list8[num7];
|
||||
}
|
||||
return num6;
|
||||
}
|
||||
|
||||
public static float EvalTargetingMultiDestroy(List<AIScriptTokenBase> filter, int selectableCount, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = 0f;
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothInplayCards, filter, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAlly != tagOwner.IsAlly && (c.IsUntouchable || c.IsSneak));
|
||||
if (list.Count <= selectableCount)
|
||||
{
|
||||
for (int num2 = 0; num2 < list.Count; num2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[num2];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsIndestructible)
|
||||
{
|
||||
float num3 = CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false);
|
||||
num += num3;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
List<AIVirtualCard> list2 = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, tagOwner, playPtn);
|
||||
if (list2.Count <= selectableCount)
|
||||
{
|
||||
for (int num4 = 0; num4 < list2.Count; num4++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list2[num4];
|
||||
num += CalcEvalDestroy(aIVirtualCard2, playPtn, situation, useIgnoreBreak: false);
|
||||
list.Remove(aIVirtualCard2);
|
||||
selectableCount--;
|
||||
if (selectableCount <= 0)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list = list2;
|
||||
}
|
||||
Dictionary<AIVirtualCard, float> dictionary = new Dictionary<AIVirtualCard, float>();
|
||||
for (int num5 = 0; num5 < list.Count; num5++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard3 = list[num5];
|
||||
dictionary.Add(aIVirtualCard3, CalcEvalDestroy(aIVirtualCard3, playPtn, situation, useIgnoreBreak: false));
|
||||
}
|
||||
for (int num6 = 0; num6 < selectableCount; num6++)
|
||||
{
|
||||
float num7 = float.MinValue;
|
||||
AIVirtualCard aIVirtualCard4 = null;
|
||||
for (int num8 = 0; num8 < list.Count; num8++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard5 = list[num8];
|
||||
float num9 = dictionary[aIVirtualCard5];
|
||||
if (num9 > num7)
|
||||
{
|
||||
num7 = num9;
|
||||
aIVirtualCard4 = aIVirtualCard5;
|
||||
}
|
||||
}
|
||||
num += num7;
|
||||
if (aIVirtualCard4 != null)
|
||||
{
|
||||
list.Remove(aIVirtualCard4);
|
||||
dictionary.Remove(aIVirtualCard4);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float EvalAllDestroy(List<AIScriptTokenBase> argList, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothInplayCards, argList, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsIndestructible)
|
||||
{
|
||||
float num2 = CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false);
|
||||
num += num2;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float EvalRandomDestroy(List<AIScriptTokenBase> argList, int count, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
if (count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(selfField.CardListSet.BothInplayCards, argList, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
if (list.Count <= count)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsIndestructible)
|
||||
{
|
||||
float num2 = CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false);
|
||||
num += num2;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
List<int> list2 = new List<int>();
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
list2.Add(j);
|
||||
}
|
||||
List<int[]> list3 = AIMathematicsLibrary.EnumerateCombinations(list2, count).ToList();
|
||||
for (int k = 0; k < list3.Count; k++)
|
||||
{
|
||||
int[] array = list3[k];
|
||||
for (int l = 0; l < array.Length; l++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list[array[l]];
|
||||
if (!aIVirtualCard2.IsIndependent && !aIVirtualCard2.IsIndestructible)
|
||||
{
|
||||
float num3 = CalcEvalDestroy(aIVirtualCard2, playPtn, situation, useIgnoreBreak: false);
|
||||
num += num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num / (float)list3.Count;
|
||||
}
|
||||
|
||||
public static void ExecuteTargetSelectDestroy(AIVirtualCard owner, List<AIVirtualCard> targets, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType selectType, int selectCount = 1)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("ExecuteTargetSelectDestroy() Error!! situation is null!!!!!");
|
||||
}
|
||||
else if (situation.IsTargetExists(selectType))
|
||||
{
|
||||
AISkillSimulationUtility.DestroyTarget(situation, targets, selectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyTargetPrediction(owner, targets, field, playPtn, situation, selectCount, selectType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DestroyTargetPrediction(AIVirtualCard tagOwner, List<AIVirtualCard> candidates, AIVirtualField field, List<int> playPtn, AISituationInfo situation, int selectCount, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(candidates, tagOwner, playPtn);
|
||||
if (selectCount <= 1)
|
||||
{
|
||||
AIVirtualCard target = AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Destroy);
|
||||
situation.SetSingleTargetInInfo(target, TargetSelectType.Default, whichTarget);
|
||||
AISkillSimulationUtility.DestroyTarget(situation, candidates, whichTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AIVirtualCard> targets = AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Destroy, selectCount);
|
||||
situation.SetMultipleTargetsInInfo(targets, TargetSelectType.Default, AIRemovalType.Destroy, whichTarget);
|
||||
AISkillSimulationUtility.DestroyTarget(situation, candidates, whichTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
SVSim.BattleEngine/Engine/Wizard/AIDrawCountUtility.cs
Normal file
52
SVSim.BattleEngine/Engine/Wizard/AIDrawCountUtility.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIDrawCountUtility
|
||||
{
|
||||
public static int GetDrawCount(AIVirtualCard owner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType period, AIScriptTokenArgType range)
|
||||
{
|
||||
int num = 0;
|
||||
switch (range)
|
||||
{
|
||||
case AIScriptTokenArgType.PLAYPTN:
|
||||
return num + GetDrawCountOfPlayptn(owner, field, playPtn);
|
||||
case AIScriptTokenArgType.PLAYED:
|
||||
return num + GetDrawCountOfPlayed(period, field);
|
||||
default:
|
||||
num += GetDrawCountOfPlayptn(owner, field, playPtn);
|
||||
return num + GetDrawCountOfPlayed(period, field);
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetDrawCountOfPlayptn(AIVirtualCard owner, AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (playPtn == null || playPtn.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AISinglePlayptnRecord playptnRecordOnSim = field.GetPlayptnRecordOnSim(playPtn);
|
||||
if (playptnRecordOnSim == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
List<PlayedCardInfo> playedCardList = playptnRecordOnSim.PlayedCardList;
|
||||
for (int i = 0; i < playedCardList.Count && !playedCardList[i].Card.IsSameCard(owner); i++)
|
||||
{
|
||||
num += playedCardList[i].DrawCount;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static int GetDrawCountOfPlayed(AIScriptTokenArgType period, AIVirtualField field)
|
||||
{
|
||||
int virtualDrawCount = field.VirtualDrawCount;
|
||||
return period switch
|
||||
{
|
||||
AIScriptTokenArgType.TURN => virtualDrawCount + field.TurnDrawCount,
|
||||
AIScriptTokenArgType.GAME => virtualDrawCount + field.GameDrawCount,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
48
SVSim.BattleEngine/Engine/Wizard/AIEmoteCtrlNull.cs
Normal file
48
SVSim.BattleEngine/Engine/Wizard/AIEmoteCtrlNull.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIEmoteCtrlNull : IAIEmoteCtrl
|
||||
{
|
||||
public void SetUpEmoteEvent(BattlePlayerBase self, BattlePlayerBase opponent, OperateMgr operateManager)
|
||||
{
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentEmotion(ClassCharaPrm.EmotionType emoteType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyTurnStart(AISituationInfo situation)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyTurnEnd()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentTurnStart(AISituationInfo situation)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnOpponentTurnEnd()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnCardPlay(AISituationInfo situation)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnCardDestroy(AISituationInfo situation)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public AIEmoteCmd OnAllyEvolution(AISituationInfo situation)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
internal class AIEnemyHandTagCollectionContainer : AITagCollectionContainer
|
||||
{
|
||||
private readonly AIPlayTagType[] ENEMY_HAND_LEGAL_TAG_TYPES = new AIPlayTagType[19]
|
||||
{
|
||||
AIPlayTagType.TurnEndAttachTag,
|
||||
AIPlayTagType.Enhance,
|
||||
AIPlayTagType.Accelerate,
|
||||
AIPlayTagType.Crystalize,
|
||||
AIPlayTagType.ChoiceTransform,
|
||||
AIPlayTagType.GenerateTag,
|
||||
AIPlayTagType.PlayCopyTag,
|
||||
AIPlayTagType.FanfareCopyTag,
|
||||
AIPlayTagType.PlayAttachTag,
|
||||
AIPlayTagType.FanfareAttachTag,
|
||||
AIPlayTagType.PlaySelect,
|
||||
AIPlayTagType.FanfareSelect,
|
||||
AIPlayTagType.PlayHandSelect,
|
||||
AIPlayTagType.FanfareHandSelect,
|
||||
AIPlayTagType.FanfareAttachStyle,
|
||||
AIPlayTagType.PlayReanimate,
|
||||
AIPlayTagType.FanfareReanimate,
|
||||
AIPlayTagType.PlayRemoveSkill,
|
||||
AIPlayTagType.FanfareRemoveSkill
|
||||
};
|
||||
|
||||
public AIEnemyHandTagCollectionContainer()
|
||||
{
|
||||
}
|
||||
|
||||
public AIEnemyHandTagCollectionContainer(AITagCollectionContainer container, AIVirtualCard owner)
|
||||
{
|
||||
if (container.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_holdingTagTypes = new List<AIPlayTagType>();
|
||||
_holdingTagCollectionTypes = new List<TagCollectionType>();
|
||||
base.TagDictionary = new List<TagCollectionWithTypeBase>();
|
||||
for (int i = 0; i < container.Count; i++)
|
||||
{
|
||||
TagCollectionWithTypeBase tagCollectionWithTypeBase = container.TagDictionary[i];
|
||||
if (IsEnemyHandLegalTagCollection(tagCollectionWithTypeBase))
|
||||
{
|
||||
base.TagDictionary.Add(tagCollectionWithTypeBase.Clone());
|
||||
tagCollectionWithTypeBase.RegisterTypes(_holdingTagTypes);
|
||||
_holdingTagCollectionTypes.Add(tagCollectionWithTypeBase.Collection.Type);
|
||||
}
|
||||
}
|
||||
CreateFixedUseCostListWhenInit(owner, owner.SelfField);
|
||||
}
|
||||
|
||||
public override void InitTags(AIVirtualCard owner, AIParamQuery query)
|
||||
{
|
||||
int tagCount = query.GetTagCount(owner);
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
{
|
||||
AIPlayTag tag = query.GetTag(owner, i);
|
||||
if (Array.IndexOf(ENEMY_HAND_LEGAL_TAG_TYPES, tag.Type) >= 0)
|
||||
{
|
||||
AddTag(tag, owner, null);
|
||||
}
|
||||
}
|
||||
CreateFixedUseCostListWhenInit(owner, owner.SelfField);
|
||||
}
|
||||
|
||||
private bool IsEnemyHandLegalTagCollection(TagCollectionWithTypeBase tagCollectionWithTypes)
|
||||
{
|
||||
for (int i = 0; i < ENEMY_HAND_LEGAL_TAG_TYPES.Length; i++)
|
||||
{
|
||||
if (tagCollectionWithTypes.IsUnderManagement(ENEMY_HAND_LEGAL_TAG_TYPES[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
50
SVSim.BattleEngine/Engine/Wizard/AIEnhanceUtility.cs
Normal file
50
SVSim.BattleEngine/Engine/Wizard/AIEnhanceUtility.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIEnhanceUtility
|
||||
{
|
||||
public static bool IsEnhanced(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (card == null || card.EnhanceCostList == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AIVariableResultContainer valResultContainer = field.AI.ValResultContainer;
|
||||
ulong hash = AIFunctionResultHashCalculator.GetHash(card, field, playPtn, null, 0uL);
|
||||
if (valResultContainer.GetContainsResultValue(AIScriptTokenVariableType.IS_ENHANCED, hash, out var getResult))
|
||||
{
|
||||
return getResult == 1f;
|
||||
}
|
||||
bool flag = false;
|
||||
if (card.PlayedCost < 0 && card.IsInHand)
|
||||
{
|
||||
List<int> playPtn2 = (card.IsAlly ? playPtn : null);
|
||||
flag = field.AI.PlayPtnRecorder.IsCardPlayingSimulationType(card, field, playPtn2, situation, PlaySimulationType.Enhance);
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = card.PlayedCost >= 0 && card.EnhanceCostList.Contains(card.PlayedCost);
|
||||
}
|
||||
valResultContainer.CheckDuplicateAndAddRecord(AIScriptTokenVariableType.IS_ENHANCED, hash, flag ? 1f : 0f, $"IsEnhanced(): Already hashed target and not equal value. CardName:[{card.CardName}] hash:[{hash}]");
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static int GetEnhanceCost(AIVirtualCard card, AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (card == null || card.EnhanceCostList == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (card.PlayedCost >= 0)
|
||||
{
|
||||
if (card.EnhanceCostList.Contains(card.PlayedCost))
|
||||
{
|
||||
return card.PlayedCost;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
List<int> playPtn2 = (card.IsAlly ? playPtn : null);
|
||||
return field.AI.PlayPtnRecorder.GetCardPlaySimulationTypeCost(card, field, playPtn2, null, PlaySimulationType.Enhance);
|
||||
}
|
||||
}
|
||||
149
SVSim.BattleEngine/Engine/Wizard/AIEvalAttackRemoveUtility.cs
Normal file
149
SVSim.BattleEngine/Engine/Wizard/AIEvalAttackRemoveUtility.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIEvalAttackRemoveUtility
|
||||
{
|
||||
private const int REMOVE_TYPE_INDEX = 1;
|
||||
|
||||
private const int REMOVE_COUNT_INDEX = 0;
|
||||
|
||||
public static float EvalAttackRemove(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
List<AIVirtualCard> list = (tagOwner.IsAlly ? field.EnemyInplayCards : field.AllyInplayCards);
|
||||
if (list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<AIVirtualCard> list2 = null;
|
||||
List<AIVirtualCard> list3 = null;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (aIVirtualCard.IsUnit && !aIVirtualCard.IsCantUnderAnyAttack())
|
||||
{
|
||||
if (aIVirtualCard.IsGuard)
|
||||
{
|
||||
list2 = AIParamQuery.AddElementToList(aIVirtualCard, list2);
|
||||
}
|
||||
else
|
||||
{
|
||||
list3 = AIParamQuery.AddElementToList(aIVirtualCard, list3);
|
||||
}
|
||||
}
|
||||
}
|
||||
int num = list2?.Count ?? 0;
|
||||
int num2 = list3?.Count ?? 0;
|
||||
if (num + num2 <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int removeCount = (int)argList[0].Value;
|
||||
AIScriptTokenArgType removeType = GetRemoveType(argList[1]);
|
||||
List<AIVirtualCard> replacedTargetSideInplayCardList = new List<AIVirtualCard>(list);
|
||||
return CalculateAttackRemoveValue(tagOwner, field, playPtn, removeCount, removeType, list2, list3, replacedTargetSideInplayCardList);
|
||||
}
|
||||
|
||||
private static float CalculateAttackRemoveValue(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, int removeCount, AIScriptTokenArgType removeType, List<AIVirtualCard> guardList, List<AIVirtualCard> nonGuardList, List<AIVirtualCard> replacedTargetSideInplayCardList)
|
||||
{
|
||||
AIVirtualCard sourceCard = AIInstantAttackUtility.CreateDummyAttacker(field, tagOwner, 1, 1, 1, isEvalRush: true);
|
||||
Dictionary<int, (float, bool)> dictionary = null;
|
||||
if (removeCount > 1)
|
||||
{
|
||||
dictionary = new Dictionary<int, (float, bool)>();
|
||||
}
|
||||
float num = 0f;
|
||||
for (int i = 0; i < removeCount; i++)
|
||||
{
|
||||
List<AIVirtualCard> list = ((guardList == null || guardList.Count <= 0) ? nonGuardList : guardList);
|
||||
if (list == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
float num2 = float.MinValue;
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
bool flag = false;
|
||||
for (int j = 0; j < list.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list[j];
|
||||
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(sourceCard, aIVirtualCard2);
|
||||
bool isRemoved = false;
|
||||
if (!AIAttackSimulationUtility.IsAttackPossible(field, aIVirtualAttackInfo, replacedTargetSideInplayCardList))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float num3;
|
||||
if (removeCount > 1 && dictionary.ContainsKey(aIVirtualCard2.CardIndex))
|
||||
{
|
||||
(num3, isRemoved) = dictionary[aIVirtualCard2.CardIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
num3 = CalculateSingleRemoveValue(aIVirtualAttackInfo, field, playPtn, removeType, ref isRemoved);
|
||||
if (removeCount > 1)
|
||||
{
|
||||
dictionary.Add(aIVirtualCard2.CardIndex, (num3, isRemoved));
|
||||
}
|
||||
}
|
||||
if (num3 > num2)
|
||||
{
|
||||
num2 = num3;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
flag = isRemoved;
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
num += num2;
|
||||
if (flag)
|
||||
{
|
||||
list.Remove(aIVirtualCard);
|
||||
replacedTargetSideInplayCardList.Remove(aIVirtualCard);
|
||||
if (removeCount > 1)
|
||||
{
|
||||
dictionary.Remove(aIVirtualCard.CardIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
AIInstantAttackUtility.RemoveDummyCardFromField(field);
|
||||
return num;
|
||||
}
|
||||
|
||||
private static float CalculateSingleRemoveValue(AIVirtualAttackInfo situation, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType removeType, ref bool isRemoved)
|
||||
{
|
||||
AIVirtualCard attackTarget = situation.AttackTarget;
|
||||
isRemoved = true;
|
||||
AIRemovalType removeType2;
|
||||
switch (removeType)
|
||||
{
|
||||
case AIScriptTokenArgType.DESTROY:
|
||||
removeType2 = AIRemovalType.Destroy;
|
||||
isRemoved = !attackTarget.IsIndependent && !attackTarget.IsIndestructible;
|
||||
break;
|
||||
case AIScriptTokenArgType.BANISH:
|
||||
removeType2 = AIRemovalType.Banish;
|
||||
isRemoved = !attackTarget.IsIndependent && !attackTarget.IsUnbanishable;
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError("AIEvalAttackRemoveUtility.CalculateSingleRemoveValue() error!! Not implemented removeType = " + removeType);
|
||||
isRemoved = false;
|
||||
return 0f;
|
||||
}
|
||||
if (isRemoved)
|
||||
{
|
||||
return AISimulationRemovalUtility.CalculateRemovalValue(attackTarget, field, playPtn, situation, removeType2, null);
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
private static AIScriptTokenArgType GetRemoveType(AIScriptTokenBase token)
|
||||
{
|
||||
if (token is AIScriptArgumentToken aIScriptArgumentToken)
|
||||
{
|
||||
return aIScriptArgumentToken.ArgumentType;
|
||||
}
|
||||
return AIScriptTokenArgType.NONE;
|
||||
}
|
||||
}
|
||||
73
SVSim.BattleEngine/Engine/Wizard/AIEvalReanimateUtility.cs
Normal file
73
SVSim.BattleEngine/Engine/Wizard/AIEvalReanimateUtility.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIEvalReanimateUtility
|
||||
{
|
||||
private const int SIDE_INDEX = 0;
|
||||
|
||||
private const int REANIMATE_COST_INDEX = 1;
|
||||
|
||||
public static float EvalReanimate(AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
if (argList.Count < 2)
|
||||
{
|
||||
AIConsoleUtility.LogError("EVAL_REANIMATE error!!! argList count = " + argList.Count);
|
||||
return 0f;
|
||||
}
|
||||
argList.Reverse();
|
||||
if (!TryGetIsSummonToAllySide(argList[0], out var isSummonToAllySide))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int reanimateCost = (int)argList[1].Value;
|
||||
argList.RemoveRange(0, 2);
|
||||
return EvalReanimate(tagOwner, isSummonToAllySide, reanimateCost, argList, playPtn, situation);
|
||||
}
|
||||
|
||||
private static float EvalReanimate(AIVirtualCard tagOwner, bool isSummonAllyField, int reanimateCost, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = 0f;
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
List<AIVirtualCard> list = (((tagOwner.IsAlly && isSummonAllyField) || (!tagOwner.IsAlly && !isSummonAllyField)) ? selfField.CardListSet.AllyDestroyedCards : selfField.CardListSet.EnemyDestroyedCards);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list = AIReanimateSimulationUtility.FilteringReanimateTargets(list, reanimateCost, tagOwner, filters, playPtn, situation);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard target = list[i];
|
||||
num += EvalReanimateTargetValue(target, selfField, playPtn, situation);
|
||||
}
|
||||
num /= (float)list.Count;
|
||||
}
|
||||
return num * (isSummonAllyField ? 1f : (-1f));
|
||||
}
|
||||
|
||||
public static float EvalReanimateTargetValue(AIVirtualCard target, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return ((float)(target.DefaultAttack * target.DefaultMaxAttackableCount) + (float)target.DefaultLife + field.StyleQuery.GetUnitBonus(field, target, playPtn)) * field.StyleQuery.GetUnitRate(field, target, playPtn) * target.EvaluateAllBattleBonusRate(playPtn, useOthersTag: true, useIgnoreInBattle: false, situation) + target.GetFieldBonus(playPtn) + target.GetReanimateBonus(playPtn);
|
||||
}
|
||||
|
||||
private static bool TryGetIsSummonToAllySide(AIScriptTokenBase sideToken, out bool isSummonToAllySide)
|
||||
{
|
||||
if (sideToken is AIScriptArgumentToken { ArgumentType: var argumentType })
|
||||
{
|
||||
switch (argumentType)
|
||||
{
|
||||
case AIScriptTokenArgType.ALLY:
|
||||
isSummonToAllySide = true;
|
||||
return true;
|
||||
case AIScriptTokenArgType.OPPONENT:
|
||||
isSummonToAllySide = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
AIConsoleUtility.LogError("EVAL_REANIMATE error!!! Argument[0] is not ALLY or ENEMY");
|
||||
isSummonToAllySide = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
1088
SVSim.BattleEngine/Engine/Wizard/AIEvaluateTagExtension.cs
Normal file
1088
SVSim.BattleEngine/Engine/Wizard/AIEvaluateTagExtension.cs
Normal file
File diff suppressed because it is too large
Load Diff
102
SVSim.BattleEngine/Engine/Wizard/AIFusionCountUtility.cs
Normal file
102
SVSim.BattleEngine/Engine/Wizard/AIFusionCountUtility.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIFusionCountUtility
|
||||
{
|
||||
public static int GetFusionCount(AIVirtualCard tagOwner, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> allFusionIngredientsList = tagOwner.GetAllFusionIngredientsList(situation);
|
||||
if (allFusionIngredientsList == null || allFusionIngredientsList.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
argList.Reverse();
|
||||
return AIFilteringUtility.MultipleFiltering(allFusionIngredientsList, argList, tagOwner, playPtn, situation)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public static int GetFusionCountAtOnce(AIVirtualCard tagOwner, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (situation == null || !situation.Actor.IsSameCard(tagOwner))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
List<AIVirtualCard> list = null;
|
||||
if (situation is AIFusionSituationInfo || situation is AIVirtualTargetSelectAction { ActionType: AIOperationType.FUSION })
|
||||
{
|
||||
if (situation.IsTargetExists(AIScriptTokenArgType.TARGET_SELECT))
|
||||
{
|
||||
argList.Reverse();
|
||||
list = AIFilteringUtility.MultipleFiltering(situation.GetSituationTarget(AIScriptTokenArgType.TARGET_SELECT).Targets, argList, tagOwner, playPtn, situation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AIConsoleUtility.LogError("AIFusionCountUtility.GetFusionCountAtOnce(): Unexpected situation type. Not fusion situation.");
|
||||
}
|
||||
return list?.Count ?? 0;
|
||||
}
|
||||
|
||||
public static int GetNowFusionCount(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn)
|
||||
{
|
||||
if (tagOwner.FusionIngredients == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return AIFilteringUtility.MultipleFiltering(tagOwner.FusionIngredients.CardList, filters, tagOwner, playPtn, null)?.Count ?? 0;
|
||||
}
|
||||
|
||||
public static int GetFusionNameCount(AIVirtualCard tagOwner, List<AIScriptTokenBase> argList, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> allFusionIngredientsList = tagOwner.GetAllFusionIngredientsList(situation);
|
||||
if (allFusionIngredientsList == null || allFusionIngredientsList.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
argList.Reverse();
|
||||
return AIFilteringUtility.GetCardNameCountFromList(allFusionIngredientsList, argList, tagOwner, playPtn, situation);
|
||||
}
|
||||
|
||||
public static int GetFusedCardCountInGame(AIVirtualCard tagOwner, List<AIScriptTokenBase> filter, List<int> playPtn, AISituationInfo situation, bool isWithoutSameId)
|
||||
{
|
||||
List<AIVirtualCard> list = (tagOwner.IsAlly ? tagOwner.SelfField.AllyGameFusedCards : tagOwner.SelfField.EnemyGameFusedCards);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
List<AIVirtualCard> list2 = AIFilteringUtility.MultipleFiltering(list, filter, tagOwner, playPtn, situation, isBlockDeadCard: false);
|
||||
if (list2 == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int count = list2.Count;
|
||||
if (isWithoutSameId)
|
||||
{
|
||||
HashSet<int> hashSet = new HashSet<int>();
|
||||
for (int i = 0; i < list2.Count; i++)
|
||||
{
|
||||
hashSet.Add(list2[i].BaseId);
|
||||
}
|
||||
count = hashSet.Count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static List<AIVirtualCard> GetAllFusionIngredientsList(this AIVirtualCard card, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = null;
|
||||
if (card.FusionIngredients != null && card.FusionIngredients.HasFusionIngredients)
|
||||
{
|
||||
list = new List<AIVirtualCard>(card.FusionIngredients.CardList);
|
||||
}
|
||||
else if (card.BeforeTransformCard != null && card.BeforeTransformCard.FusionIngredients != null && card.BeforeTransformCard.FusionIngredients.HasFusionIngredients)
|
||||
{
|
||||
list = new List<AIVirtualCard>(card.BeforeTransformCard.FusionIngredients.CardList);
|
||||
}
|
||||
if (situation != null && situation is AIFusionSituationInfo aIFusionSituationInfo && aIFusionSituationInfo.Actor.IsSameCard(card) && aIFusionSituationInfo.IsTargetExists(AIScriptTokenArgType.TARGET_SELECT))
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(aIFusionSituationInfo.GetSituationTarget(AIScriptTokenArgType.TARGET_SELECT).Targets, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
111
SVSim.BattleEngine/Engine/Wizard/AIGenerateTagUtility.cs
Normal file
111
SVSim.BattleEngine/Engine/Wizard/AIGenerateTagUtility.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIGenerateTagUtility
|
||||
{
|
||||
private class GenerateTagExecutingInfo
|
||||
{
|
||||
public AIVirtualCard Owner;
|
||||
|
||||
public AIVirtualCard Target;
|
||||
|
||||
public AIAttachedTagInformation AttachedTagInfo;
|
||||
}
|
||||
|
||||
public static void ExecuteGenerateTag(AISituationInfo situation, AIVirtualField field, AIGenerateTagOwnerTable generateTagOwnerTable, AttachedSkillInfoReceiveDataCollection attachedInfoReceiveCollection)
|
||||
{
|
||||
List<GenerateTagExecutingInfo> list = CreateGeneratedTagExecutingInfoList(generateTagOwnerTable, attachedInfoReceiveCollection, field, situation);
|
||||
if (list != null)
|
||||
{
|
||||
AttachGenerateTagOnField(list, field, situation);
|
||||
}
|
||||
attachedInfoReceiveCollection.Clear();
|
||||
}
|
||||
|
||||
private static List<GenerateTagExecutingInfo> CreateGeneratedTagExecutingInfoList(AIGenerateTagOwnerTable generateTagOwnerTable, AttachedSkillInfoReceiveDataCollection attachedInfoReceiveCollection, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
List<GenerateTagExecutingInfo> list = null;
|
||||
for (int i = 0; i < attachedInfoReceiveCollection.InfoList.Count; i++)
|
||||
{
|
||||
List<GenerateTagExecutingInfo> list2 = CreateGenerateTagExecutingInfoFromReceiveData(generateTagOwnerTable, attachedInfoReceiveCollection.InfoList[i], field, situation);
|
||||
if (list2 != null)
|
||||
{
|
||||
list = AIParamQuery.AddRangeToList(list2, list);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<GenerateTagExecutingInfo> CreateGenerateTagExecutingInfoFromReceiveData(AIGenerateTagOwnerTable generateTagOwnerTable, AttachedSkillInfoReceiveData attachedInfoReceiveData, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
List<GenerateTagExecutingInfo> list = null;
|
||||
AIGenerateTagOwnerTable.GenerateTagOwnerInfo generateTagOwnerInfo = generateTagOwnerTable.GetGenerateTagOwnerInfo(attachedInfoReceiveData.OwnerBaseCardId, attachedInfoReceiveData.OwnerIndex, attachedInfoReceiveData.OwnerIsPlayer);
|
||||
if (generateTagOwnerInfo == null || generateTagOwnerInfo.GenerateTagList == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIPlayTag> generateTagList = generateTagOwnerInfo.GenerateTagList;
|
||||
bool flag = field.AllyBattlePlayer.IsPlayer == generateTagOwnerInfo.OwnerIsPlayer;
|
||||
AIVirtualCard owner = FindVirtualCard(generateTagOwnerInfo.OwnerCardIndex, flag, field);
|
||||
for (int i = 0; i < attachedInfoReceiveData.TargetInfoList.Count; i++)
|
||||
{
|
||||
AttachedSkillInfoReceiveData.TargetInfo targetInfo = attachedInfoReceiveData.TargetInfoList[i];
|
||||
bool flag2 = field.AllyBattlePlayer.IsPlayer == targetInfo.TargetIsPlayer;
|
||||
AIVirtualCard aIVirtualCard = FindVirtualCard(targetInfo.TargetIndex, flag2, field);
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < generateTagList.Count; j++)
|
||||
{
|
||||
if (generateTagList[j].ArgumentExpressions is AIGenerateTag aIGenerateTag && aIGenerateTag.CheckMatchedHashList(targetInfo.SkillHashList))
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(new GenerateTagExecutingInfo
|
||||
{
|
||||
Owner = owner,
|
||||
Target = aIVirtualCard,
|
||||
AttachedTagInfo = new AIAttachedTagInformation(aIGenerateTag.Tag, aIGenerateTag.RemoveTiming, generateTagOwnerInfo.OwnerBaseCardId, generateTagOwnerInfo.OwnerCardIndex, flag, targetInfo.TargetIndex, flag2)
|
||||
}, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void AttachGenerateTagOnField(List<GenerateTagExecutingInfo> executingInfoList, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
if (executingInfoList != null)
|
||||
{
|
||||
for (int i = 0; i < executingInfoList.Count; i++)
|
||||
{
|
||||
GenerateTagExecutingInfo generateTagExecutingInfo = executingInfoList[i];
|
||||
AIVirtualCard target = generateTagExecutingInfo.Target;
|
||||
target.TagCollectionContainer.AttachTag(generateTagExecutingInfo.AttachedTagInfo, target, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard FindVirtualCard(int cardIndex, bool isAlly, AIVirtualField field)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
aIVirtualCard = FindFromList<AIVirtualCard>(field.CardListSet.AllReferableCards);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
return aIVirtualCard;
|
||||
}
|
||||
return FindFromList<AIVirtualCard>(field.GetEnemyHandCardList());
|
||||
AIVirtualCard FindFromList<T>(List<T> _cardList) where T : AIVirtualCard
|
||||
{
|
||||
for (int i = 0; i < _cardList.Count; i++)
|
||||
{
|
||||
T val = _cardList[i];
|
||||
if (val.CardIndex == cardIndex && val.IsAlly == isAlly)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIGetPreprocessInformationUtility
|
||||
{
|
||||
public static int GetEarthRiteCount(AIVirtualCard owner, AISituationInfo situation)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (situation.PreprocessRecorder == null || !situation.PreprocessRecorder.HasRecord)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < situation.PreprocessRecorder.RecordList.Count; i++)
|
||||
{
|
||||
AISinglePreprocessRecord aISinglePreprocessRecord = situation.PreprocessRecorder.RecordList[i];
|
||||
if (aISinglePreprocessRecord.RealActor.IsSameCard(owner) || aISinglePreprocessRecord.OriginalCard.IsSameCard(owner))
|
||||
{
|
||||
num += aISinglePreprocessRecord.EarthRiteCount;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetNecromanceCount(AIVirtualCard owner, AISituationInfo situation)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (situation.PreprocessRecorder == null || !situation.PreprocessRecorder.HasRecord)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < situation.PreprocessRecorder.RecordList.Count; i++)
|
||||
{
|
||||
AISinglePreprocessRecord aISinglePreprocessRecord = situation.PreprocessRecorder.RecordList[i];
|
||||
if (aISinglePreprocessRecord.RealActor.IsSameCard(owner) || aISinglePreprocessRecord.OriginalCard.IsSameCard(owner))
|
||||
{
|
||||
num += aISinglePreprocessRecord.NecromanceCount;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
26
SVSim.BattleEngine/Engine/Wizard/AIGetStatusUtility.cs
Normal file
26
SVSim.BattleEngine/Engine/Wizard/AIGetStatusUtility.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIGetStatusUtility
|
||||
{
|
||||
public static int GetLife(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.AllReferableCards, filters, tagOwner, playPtn, situation, isBlockDeadCard: false);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return list[0].Life;
|
||||
}
|
||||
|
||||
public static int GetAttack(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.AllReferableCards, filters, tagOwner, playPtn, situation, isBlockDeadCard: false);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return list[0].Attack;
|
||||
}
|
||||
}
|
||||
143
SVSim.BattleEngine/Engine/Wizard/AIHandBuffSimulationUtility.cs
Normal file
143
SVSim.BattleEngine/Engine/Wizard/AIHandBuffSimulationUtility.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIHandBuffSimulationUtility
|
||||
{
|
||||
public static void ExecuteHandBuffAll(List<AIVirtualCard> candidates, AIBuffExecutingInfo_old buffInfo, AISituationInfo situation)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.IsInHand && aIVirtualCard.IsUnit)
|
||||
{
|
||||
aIVirtualCard.GiveBuff(situation, buffInfo, isTemp: false);
|
||||
list.Add(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
if (list.Count > 0)
|
||||
{
|
||||
situation.RegisterLatestTargetList(list);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteHandBuffRandom(List<AIVirtualCard> candidates, AIBuffExecutingInfo_old buffInfo, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (candidates != null && candidates.Count > 0)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectHandBuffTarget(candidates, AISelectTargetPattern.Worst, playPtn, situation);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
aIVirtualCard.GiveBuff(situation, buffInfo, isTemp: false);
|
||||
situation.RegisterSingleLatestTarget(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteHandBuffTargetSelect(AIBuffExecutingInfo_old buffInfo, AIScriptTokenArgType whichTarget, AISituationInfo situation)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
ExecuteHandBuffAll(situationTarget.Targets, buffInfo, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteHandBuffBestTarget(List<AIVirtualCard> candidates, AIBuffExecutingInfo_old buffInfo, AISituationInfo situation)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = SelectHandBuffTarget(candidates, AISelectTargetPattern.Best, EnemyAI.EmptyPlayPtn, situation);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
aIVirtualCard.GiveBuff(situation, buffInfo, isTemp: false);
|
||||
situation.RegisterSingleLatestTarget(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectHandBuffTarget(List<AIVirtualCard> candidates, AISelectTargetPattern worstOrBest, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
float num = 0f;
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
float handBonus = aIVirtualCard2.GetHandBonus(playPtn, situation, isIgnoreInFusion: false);
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
num = handBonus;
|
||||
continue;
|
||||
}
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
if (handBonus > num)
|
||||
{
|
||||
num = handBonus;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handBonus < num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIVirtualCard2.Cost < aIVirtualCard.Cost)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else if (aIVirtualCard2.Cost <= aIVirtualCard.Cost)
|
||||
{
|
||||
if (aIVirtualCard2.Attack > aIVirtualCard.Attack)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else if (aIVirtualCard2.Attack == aIVirtualCard.Attack && aIVirtualCard2.Life > aIVirtualCard.Life)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
if (handBonus < num)
|
||||
{
|
||||
num = handBonus;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handBonus > num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (aIVirtualCard2.Cost > aIVirtualCard.Cost)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else if (aIVirtualCard2.Cost <= aIVirtualCard.Cost)
|
||||
{
|
||||
if (aIVirtualCard2.Attack < aIVirtualCard.Attack)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
else if (aIVirtualCard2.Attack == aIVirtualCard.Attack && aIVirtualCard2.Life < aIVirtualCard.Life)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return aIVirtualCard;
|
||||
}
|
||||
}
|
||||
45
SVSim.BattleEngine/Engine/Wizard/AIHandCountUtility.cs
Normal file
45
SVSim.BattleEngine/Engine/Wizard/AIHandCountUtility.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIHandCountUtility
|
||||
{
|
||||
public static int GetHandCount(AIVirtualField field, List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, AISituationInfo situation, List<int> playPtn)
|
||||
{
|
||||
ReplaceIllegalFilter(filters);
|
||||
int num = ((!tagOwner.IsAlly) ? AIFilteringUtility.MultipleFiltering(field.GetEnemyHandCardList(), filters, tagOwner, playPtn, situation) : AIFilteringUtility.MultipleFiltering(field.AllyHandCards, filters, tagOwner, playPtn, situation))?.Count ?? 0;
|
||||
if (filters[0] is AIScriptArgumentToken { ArgumentType: AIScriptTokenArgType.ALL })
|
||||
{
|
||||
num += field.VirtualDrawCount;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetHandNameCount(AIVirtualField field, List<AIScriptTokenBase> filters, AIVirtualCard tagOwner, AISituationInfo situation, List<int> playPtn)
|
||||
{
|
||||
ReplaceIllegalFilter(filters);
|
||||
return AIFilteringUtility.GetCardNameCountFromList(tagOwner.IsAlly ? field.AllyHandCards : field.GetEnemyHandCardList(), filters, tagOwner, playPtn, situation);
|
||||
}
|
||||
|
||||
private static void ReplaceIllegalFilter(List<AIScriptTokenBase> filters)
|
||||
{
|
||||
for (int i = 0; i < filters.Count; i++)
|
||||
{
|
||||
if (filters[i] is AIScriptArgumentToken { ArgumentType: var argumentType } aIScriptArgumentToken)
|
||||
{
|
||||
switch (argumentType)
|
||||
{
|
||||
case AIScriptTokenArgType.FOLLOWER:
|
||||
aIScriptArgumentToken.ArgumentType = AIScriptTokenArgType.FOLLOWER_CARD_TYPE;
|
||||
break;
|
||||
case AIScriptTokenArgType.BUFFED_FOLLOWER:
|
||||
aIScriptArgumentToken.ArgumentType = AIScriptTokenArgType.BUFFED_FOLLOWER_CARD_TYPE;
|
||||
break;
|
||||
case AIScriptTokenArgType.SPELL:
|
||||
aIScriptArgumentToken.ArgumentType = AIScriptTokenArgType.SPELL_CARD_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
SVSim.BattleEngine/Engine/Wizard/AIHealCountUtility.cs
Normal file
35
SVSim.BattleEngine/Engine/Wizard/AIHealCountUtility.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIHealCountUtility
|
||||
{
|
||||
public static int GetHealCount(AIVirtualCard owner, AIVirtualField field, AISituationInfo situation, List<int> playPtn, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
if (argList.Count < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AIScriptTokenArgType argumentType = ((AIScriptArgumentToken)argList[0]).ArgumentType;
|
||||
AIScriptTokenArgType durationType;
|
||||
AIScriptTokenArgType aIScriptTokenArgType;
|
||||
if (argumentType == AIScriptTokenArgType.TURN || argumentType == AIScriptTokenArgType.GAME)
|
||||
{
|
||||
durationType = argumentType;
|
||||
aIScriptTokenArgType = AIScriptTokenArgType.NONE;
|
||||
argList.RemoveAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
aIScriptTokenArgType = argumentType;
|
||||
durationType = ((AIScriptArgumentToken)argList[1]).ArgumentType;
|
||||
argList.RemoveRange(0, 2);
|
||||
}
|
||||
argList.Reverse();
|
||||
if (aIScriptTokenArgType == AIScriptTokenArgType.NONE)
|
||||
{
|
||||
return AIHealSimulationUtility.GetSelfTurnHealCountAll(owner, field, argList, playPtn, situation, durationType);
|
||||
}
|
||||
return AIHealSimulationUtility.GetSelfTurnHealCountAtCountType(owner, field, argList, playPtn, situation, durationType, aIScriptTokenArgType);
|
||||
}
|
||||
}
|
||||
216
SVSim.BattleEngine/Engine/Wizard/AIHealSimulationUtility.cs
Normal file
216
SVSim.BattleEngine/Engine/Wizard/AIHealSimulationUtility.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIHealSimulationUtility
|
||||
{
|
||||
public static int CalcHealModifier(AIVirtualCard healTarget, List<int> playPtn, AISituationInfo situation, int originalHealValue)
|
||||
{
|
||||
if (!healTarget.TagCollectionContainer.HasTag(AIPlayTagType.ModifyHeal))
|
||||
{
|
||||
return originalHealValue;
|
||||
}
|
||||
return healTarget.TagCollectionContainer.ModifyHealTags.GetModifiedHealValue(healTarget, healTarget, originalHealValue, playPtn, situation);
|
||||
}
|
||||
|
||||
public static float EvalTargetingHeal(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn, int heal)
|
||||
{
|
||||
float num = float.MinValue;
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(selfField.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list[i];
|
||||
if (aIVirtualCard2.IsAlly == tagOwner.IsAlly || (!aIVirtualCard2.IsUntouchable && !aIVirtualCard2.IsSneak))
|
||||
{
|
||||
int num2 = CalcHealModifier(aIVirtualCard2, playPtn, null, heal);
|
||||
float num3 = 0f;
|
||||
if (aIVirtualCard2.IsUnit)
|
||||
{
|
||||
num3 = (float)Mathf.Min(num2, aIVirtualCard2.MaxLife - aIVirtualCard2.Life) * (aIVirtualCard2.IsAlly ? 1f : (-1f));
|
||||
}
|
||||
else if (aIVirtualCard2.IsLeader)
|
||||
{
|
||||
num3 = AILeaderLifeEvaluationUtility.Evaluate(Mathf.Min(aIVirtualCard2.MaxLife, aIVirtualCard2.Life + num2), aIVirtualCard2.Life, aIVirtualCard2.IsAlly, tagOwner.IsAlly);
|
||||
}
|
||||
if (num < num3)
|
||||
{
|
||||
num = num3;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
float num4 = CalcEvalHealAfterAttack(aIVirtualCard2, num2);
|
||||
if (num < num4)
|
||||
{
|
||||
num = num4;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public static float EvalAllHeal(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn, int heal)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (aIVirtualCard.IsAlly == tagOwner.IsAlly)
|
||||
{
|
||||
int num2 = CalcHealModifier(aIVirtualCard, playPtn, null, heal);
|
||||
float num3 = 0f;
|
||||
if (aIVirtualCard.IsUnit)
|
||||
{
|
||||
num3 = (float)Mathf.Min(num2, aIVirtualCard.MaxLife - aIVirtualCard.Life) * (aIVirtualCard.IsAlly ? 1f : (-1f));
|
||||
}
|
||||
else if (aIVirtualCard.IsLeader)
|
||||
{
|
||||
num3 = AILeaderLifeEvaluationUtility.Evaluate(Mathf.Min(aIVirtualCard.MaxLife, aIVirtualCard.Life + num2), aIVirtualCard.Life, aIVirtualCard.IsAlly, tagOwner.IsAlly);
|
||||
}
|
||||
num += num3;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float CalcEvalHealAfterAttack(AIVirtualCard healTarget, int heal)
|
||||
{
|
||||
AIVirtualField selfField = healTarget.SelfField;
|
||||
if (!healTarget.IsUnit || !healTarget.IsAlly)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = float.MinValue;
|
||||
bool flag = healTarget.IsAbleEvolution();
|
||||
for (int i = 0; i < selfField.EnemyInplayCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = selfField.EnemyInplayCards[i];
|
||||
if (aIVirtualCard.IsCantUnderAttack(selfField.ParamQuery, healTarget, EnemyAI.EmptyPlayPtn, selfField))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(healTarget, aIVirtualCard);
|
||||
if (!(AIAttackSimulationUtility.IsAttackPossible(selfField, aIVirtualAttackInfo) || flag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num2 = healTarget.SimulateDamageAmount(aIVirtualCard.SimulateAttackAmount(aIVirtualAttackInfo));
|
||||
if (healTarget.Life > num2)
|
||||
{
|
||||
int b = healTarget.MaxLife - (healTarget.Life - num2);
|
||||
float num3 = Mathf.Min(heal, b);
|
||||
if (num3 > num)
|
||||
{
|
||||
num = num3;
|
||||
}
|
||||
}
|
||||
else if (flag && healTarget.EvolutionLife > num2)
|
||||
{
|
||||
int b2 = healTarget.BaseCard.BaseParameter.EvoLife - (healTarget.EvolutionLife - num2);
|
||||
float num4 = Mathf.Min(heal, b2);
|
||||
if (num4 > num)
|
||||
{
|
||||
num = num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetSelfTurnHealCountAll(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType durationType)
|
||||
{
|
||||
return GetSelfTurnHealCountPlayed(tagOwner, field, filters, playPtn, durationType, situation) + GetSelfTurnHealCountPlayPtn(tagOwner, field, filters, playPtn, situation);
|
||||
}
|
||||
|
||||
public static int GetSelfTurnHealCountAtCountType(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType durationType, AIScriptTokenArgType countType)
|
||||
{
|
||||
return countType switch
|
||||
{
|
||||
AIScriptTokenArgType.PLAYED => GetSelfTurnHealCountPlayed(tagOwner, field, filters, playPtn, durationType, situation),
|
||||
AIScriptTokenArgType.PLAYPTN => GetSelfTurnHealCountPlayPtn(tagOwner, field, filters, playPtn, situation),
|
||||
AIScriptTokenArgType.BEFORE_PLAYPTN => GetSelfTurnHealCountBeforePlayPtn(tagOwner, field, filters, playPtn, situation, durationType),
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetSelfTurnHealCountPlayed(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AIScriptTokenArgType durationType, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int turn = (tagOwner.IsAlly ? field.AllyTurnCount : field.EnemyTurnCount);
|
||||
return 0 + field.HealRecorderCollection.GetTurnHealCount(turn, list, tagOwner.IsAlly);
|
||||
}
|
||||
|
||||
private static int GetSelfTurnHealCountPlayPtn(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (playPtn == null || !tagOwner.IsAlly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[playPtn[i]];
|
||||
if (aIVirtualCard.IsSameCard(tagOwner))
|
||||
{
|
||||
break;
|
||||
}
|
||||
num += aIVirtualCard.GetWhenPlayHealCount(list, field, playPtn, situation);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static int GetSelfTurnHealCountBeforePlayPtn(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType durationType)
|
||||
{
|
||||
if (playPtn == null || !tagOwner.IsAlly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return GetSelfTurnHealCountPlayPtn(tagOwner, field, filters, playPtn, situation) + GetSelfTurnHealCountPlayed(tagOwner, field, filters, playPtn, durationType, situation);
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectBestTarget(List<AIVirtualCard> targets, int healPoint)
|
||||
{
|
||||
float num = -1f;
|
||||
AIVirtualCard result = null;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (!targets[i].IsIndependent)
|
||||
{
|
||||
float num2 = Mathf.Min(healPoint, targets[i].MaxLife - targets[i].Life);
|
||||
if (num2 > num)
|
||||
{
|
||||
num = num2;
|
||||
result = targets[i];
|
||||
}
|
||||
if (num2 >= (float)healPoint)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
18
SVSim.BattleEngine/Engine/Wizard/AIIsSelectableUtility.cs
Normal file
18
SVSim.BattleEngine/Engine/Wizard/AIIsSelectableUtility.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIIsSelectableUtility
|
||||
{
|
||||
public static bool IsSelectable(List<AIScriptTokenBase> filters, float minSelectableCount, AIVirtualCard owner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.AllReferableCards, filters, owner, playPtn, situation);
|
||||
list.RemoveAll((AIVirtualCard card) => card.IsAlly != owner.IsAlly && card.CantBeFocusedSkill);
|
||||
list = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(list, owner, playPtn);
|
||||
if (list == null || (float)list.Count < minSelectableCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
134
SVSim.BattleEngine/Engine/Wizard/AILethalTargetSelectUtility.cs
Normal file
134
SVSim.BattleEngine/Engine/Wizard/AILethalTargetSelectUtility.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AILethalTargetSelectUtility
|
||||
{
|
||||
public class LethalTargetSelectResult
|
||||
{
|
||||
public AISelectedTargetInfoSet TargetSet;
|
||||
|
||||
public AIVirtualField ResultField;
|
||||
}
|
||||
|
||||
public static bool LethalSelectTarget(AIVirtualField field, AIVirtualTargetSelectAction situation, AISinglePlayptnRecord playPtnRecord)
|
||||
{
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
List<AIVirtualTargetSelectInfo> list = actor.CreateAIVirtualSelectInfo(field, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return TargetSelectAction(field, situation);
|
||||
}
|
||||
AISelectedTargetInfoSet preDecidedTargetSet = null;
|
||||
if (situation.SelectedTargets.IsAnyTargetExists())
|
||||
{
|
||||
preDecidedTargetSet = situation.SelectedTargets;
|
||||
}
|
||||
List<AISelectedTargetInfoSet> allTargetSelectSimulationPattern = AIVirtualTargetSelectSimulator.GetAllTargetSelectSimulationPattern(list, preDecidedTargetSet, situation, field, playPtnRecord);
|
||||
if (allTargetSelectSimulationPattern == null || allTargetSelectSimulationPattern.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("LethalSelectTarget error!! Cannot find target pattern!!!!! actor.id == " + actor.BaseId);
|
||||
return TargetSelectAction(field, situation);
|
||||
}
|
||||
LethalTargetSelectResult lethalTargetSelectResult = new LethalTargetSelectResult
|
||||
{
|
||||
ResultField = field,
|
||||
TargetSet = null
|
||||
};
|
||||
CalculateBestTargetPattern(lethalTargetSelectResult, field, situation, allTargetSelectSimulationPattern, playPtnRecord, list);
|
||||
situation.SelectedTargets = lethalTargetSelectResult.TargetSet;
|
||||
return TargetSelectAction(field, situation);
|
||||
}
|
||||
|
||||
private static bool TargetSelectAction(AIVirtualField field, AIVirtualTargetSelectAction situation)
|
||||
{
|
||||
switch (situation.ActionType)
|
||||
{
|
||||
case AIOperationType.PLAY:
|
||||
{
|
||||
PlaySimulationInfo playSimulationInfo = AIPlayCardSimulationUtility.CreatePlaySimulationInfo(situation.Actor, situation, field);
|
||||
if (playSimulationInfo != null)
|
||||
{
|
||||
AIVirtualPlaySimulator.PlayCard(situation, field, playSimulationInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case AIOperationType.EVOLVE:
|
||||
AIVirtualEvolutionSimulator.ManualEvolve(situation, field);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CalculateBestTargetPattern(LethalTargetSelectResult result, AIVirtualField field, AIVirtualTargetSelectAction situation, List<AISelectedTargetInfoSet> patternSet, AISinglePlayptnRecord playptnRecord, List<AIVirtualTargetSelectInfo> selectInfoList)
|
||||
{
|
||||
AIVirtualCard originalCard = situation.OriginalCard;
|
||||
AIOperationType actionType = situation.ActionType;
|
||||
int giveQuickSelectIndex = GetGiveQuickSelectIndex(selectInfoList);
|
||||
bool isSecondTargetForbbidenSelectedTarget = selectInfoList.Count > 1 && selectInfoList[1].IsForbiddenSelectedTarget;
|
||||
for (int i = 0; i < patternSet.Count; i++)
|
||||
{
|
||||
AISelectedTargetInfoSet aISelectedTargetInfoSet = patternSet[i];
|
||||
if (!AIVirtualTargetSelectSimulator.IsAbleToReplaceDummyTarget(aISelectedTargetInfoSet, result.TargetSet, isSecondTargetForbbidenSelectedTarget))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!aISelectedTargetInfoSet.IsTargetExist(0) && aISelectedTargetInfoSet.IsTargetExist(1))
|
||||
{
|
||||
AIConsoleUtility.LogError("AILethalTargetSelectUtility.CalculateBestTargetPattern error!! targetPattern.firstTarget is null & secondTaget is not null");
|
||||
continue;
|
||||
}
|
||||
AIVirtualField aIVirtualField = new AIVirtualField(field);
|
||||
AISelectedTargetInfoSet similarTargetInfoSet = aISelectedTargetInfoSet.GetSimilarTargetInfoSet(aIVirtualField);
|
||||
AIVirtualCard aIVirtualCard = aIVirtualField.SearchVirtualCard(originalCard);
|
||||
AIVirtualCard actor = aIVirtualCard;
|
||||
if (actionType == AIOperationType.PLAY)
|
||||
{
|
||||
actor = aIVirtualCard.FindRealActor(playptnRecord);
|
||||
}
|
||||
AIVirtualTargetSelectAction situation2 = new AIVirtualTargetSelectAction(actor, aIVirtualCard, actionType, similarTargetInfoSet);
|
||||
TargetSelectAction(aIVirtualField, situation2);
|
||||
if (giveQuickSelectIndex >= 0)
|
||||
{
|
||||
GiveQuickTargetSelectSimulation(similarTargetInfoSet.Get(giveQuickSelectIndex), aIVirtualField);
|
||||
}
|
||||
if (result.TargetSet == null || aIVirtualField.EnemyClass.Life < result.ResultField.EnemyClass.Life)
|
||||
{
|
||||
result.ResultField = aIVirtualField;
|
||||
result.TargetSet = aISelectedTargetInfoSet.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetGiveQuickSelectIndex(List<AIVirtualTargetSelectInfo> selectInfoList)
|
||||
{
|
||||
for (int i = 0; i < selectInfoList.Count; i++)
|
||||
{
|
||||
AIVirtualTargetSelectInfo aIVirtualTargetSelectInfo = selectInfoList[i];
|
||||
if (aIVirtualTargetSelectInfo.SelectRule != null && (aIVirtualTargetSelectInfo.SelectRule.Type == AIPlayTagType.PlayQuick || aIVirtualTargetSelectInfo.SelectRule.Type == AIPlayTagType.FanfareQuick))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static void GiveQuickTargetSelectSimulation(AISelectedTargetInfo receiveQuickTargets, AIVirtualField field)
|
||||
{
|
||||
if (!receiveQuickTargets.HasTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < receiveQuickTargets.Targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = receiveQuickTargets.Targets[i];
|
||||
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(aIVirtualCard, field.EnemyClass);
|
||||
if (AIAttackSimulationUtility.IsAttackPossible(field, aIVirtualAttackInfo) && !aIVirtualAttackInfo.WillTargetDestroyByAttackTags(field, field.BestPlayPtn, aIVirtualCard))
|
||||
{
|
||||
AIVirtualAttackSimulator.Attack(aIVirtualAttackInfo, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
SVSim.BattleEngine/Engine/Wizard/AILifeLowerLimitInfo.cs
Normal file
37
SVSim.BattleEngine/Engine/Wizard/AILifeLowerLimitInfo.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AILifeLowerLimitInfo : AIBarrierInfoBase
|
||||
{
|
||||
public override AIBarrierType BarrierType => AIBarrierType.DamageClippingLifeLowerLimit;
|
||||
|
||||
public AILifeLowerLimitInfo(AIDamageType damageType, AIBarrierStopTiming stopTiming)
|
||||
: base(0, damageType, stopTiming)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public AILifeLowerLimitInfo(AIDamageType damageType, List<AIBarrierStopTiming> stopTimingList)
|
||||
: base(0, damageType, stopTimingList)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public override AIBarrierInfoBase Clone()
|
||||
{
|
||||
return new AILifeLowerLimitInfo(base.DamageType, base.StopTimingList);
|
||||
}
|
||||
|
||||
public override bool IsShield()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override int CalcDamage(AIVirtualCard owner, int damage)
|
||||
{
|
||||
int b = owner.Life - 1;
|
||||
return Mathf.Min(damage, b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIMaxAttackSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.MAX_ATTACK_LOGIC;
|
||||
|
||||
public AIMaxAttackSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
int compare = 0;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
if (aIVirtualCard2.IsUnit && (aIVirtualCard == null || IsWellChosenTarget(aIVirtualCard2, compare, worstOrBest)))
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
compare = aIVirtualCard2.Attack;
|
||||
}
|
||||
}
|
||||
return aIVirtualCard;
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
LogNotImplementMultipleSelect();
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsWellChosenTarget(AIVirtualCard target, int compare, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return worstOrBest switch
|
||||
{
|
||||
AISelectTargetPattern.Best => target.Attack > compare,
|
||||
AISelectTargetPattern.Worst => target.Attack < compare,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIMetamorphoseSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
private const int INVALID_ID = -1;
|
||||
|
||||
private const int METAMORPHOSE_ID_ARG_INDEX = 0;
|
||||
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.METAMORPHOSE_LOGIC;
|
||||
|
||||
public AIMetamorphoseSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIRemovalEvaluationOption aIRemovalEvaluationOption = CreateMetamorphoseOption(tagOwner, field);
|
||||
if (aIRemovalEvaluationOption == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return AISimulationRemovalUtility.SelectRemovalTarget(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Metamorphose, aIRemovalEvaluationOption);
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIRemovalEvaluationOption aIRemovalEvaluationOption = CreateMetamorphoseOption(tagOwner, field);
|
||||
if (aIRemovalEvaluationOption == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, tagOwner, field, playPtn, situation, worstOrBest, AIRemovalType.Metamorphose, selectCount, aIRemovalEvaluationOption);
|
||||
}
|
||||
|
||||
private AIRemovalEvaluationOption CreateMetamorphoseOption(AIVirtualCard tagOwner, AIVirtualField field)
|
||||
{
|
||||
if (_argumentList == null || _argumentList.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIMetamorphoseSelectLogicArgument error!! _argumentList is null");
|
||||
return null;
|
||||
}
|
||||
int num = _argumentList[0].EvalID();
|
||||
if (num == -1)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIMetamorphoseSelectLogicArgument error!! tokenId is invalid");
|
||||
return null;
|
||||
}
|
||||
return AIMetamorphoseSimulationUtility.CreateMetamorphoseEvaluationOption(tagOwner, field, num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIMetamorphoseSimulationUtility
|
||||
{
|
||||
private struct SwappedMetamorphoseInfo
|
||||
{
|
||||
public AIVirtualCard TargetCard;
|
||||
|
||||
public AIVirtualCard TokenCard;
|
||||
|
||||
public List<AIVirtualCard> SwappedCardList;
|
||||
|
||||
public int SwappedIndex;
|
||||
}
|
||||
|
||||
public static AIRemovalEvaluationOption CreateMetamorphoseEvaluationOption(AIVirtualCard tagOwner, AIVirtualField field, int metamorphoseId)
|
||||
{
|
||||
return new AIRemovalEvaluationOption
|
||||
{
|
||||
TagOwner = tagOwner,
|
||||
MetamorphoseTokenId = metamorphoseId
|
||||
};
|
||||
}
|
||||
|
||||
public static void MetamorphoseAll(AIVirtualField field, List<AIVirtualCard> range, int metamorphoseId, AIVirtualCard actor, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = range[i];
|
||||
if (!aIVirtualCard.IsIndependent && !aIVirtualCard.IsDead)
|
||||
{
|
||||
ExecuteMetamorphose(aIVirtualCard, metamorphoseId, actor, field, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseRandom(AIVirtualField field, List<AIVirtualCard> range, int metamorphoseId, AIVirtualCard actor, List<int> playPtn, AISituationInfo situation, int selectCount = 1)
|
||||
{
|
||||
if (selectCount <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError($"AIMetamorphoseSimulationUtility.MetamorphoseRandom() error!! selectCount == {selectCount}");
|
||||
return;
|
||||
}
|
||||
AIRemovalEvaluationOption aIRemovalEvaluationOption = CreateMetamorphoseEvaluationOption(actor, field, metamorphoseId);
|
||||
if (aIRemovalEvaluationOption == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIMetamorphoseSimulationUtility.MetamorphoseRandom() error!! failed create option");
|
||||
return;
|
||||
}
|
||||
if (selectCount == 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = AISimulationRemovalUtility.SelectRemovalTarget(range, actor, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Metamorphose, aIRemovalEvaluationOption);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
ExecuteMetamorphose(aIVirtualCard, metamorphoseId, actor, field, situation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> list = AISimulationRemovalUtility.SelectMultipleRemovalTargets(range, actor, field, playPtn, situation, AISelectTargetPattern.Worst, AIRemovalType.Metamorphose, selectCount, aIRemovalEvaluationOption);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
ExecuteMetamorphose(list[i], metamorphoseId, actor, field, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseTarget(AIVirtualField field, List<AIVirtualCard> candidates, int metamorphoseId, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType whichTarget, int count)
|
||||
{
|
||||
if (situation.IsTargetExists(whichTarget))
|
||||
{
|
||||
MetamorphoseSelectedTarget(field, metamorphoseId, situation, whichTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetamorphoseTargetPrediction(field, candidates, metamorphoseId, playPtn, situation, whichTarget, count);
|
||||
}
|
||||
}
|
||||
|
||||
private static void MetamorphoseSelectedTarget(AIVirtualField field, int metamorphoseId, AISituationInfo situation, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseSelectedTarget(): error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
ExecuteMetamorphose(targets[i], metamorphoseId, situation.Actor, field, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void MetamorphoseTargetPrediction(AIVirtualField field, List<AIVirtualCard> candidates, int metamorphoseId, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType whichTarget, int count)
|
||||
{
|
||||
if (candidates.Count < count)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseTargetPrediction(): Target candidates is not enough");
|
||||
return;
|
||||
}
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
AIRemovalEvaluationOption aIRemovalEvaluationOption = CreateMetamorphoseEvaluationOption(actor, field, metamorphoseId);
|
||||
if (aIRemovalEvaluationOption == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseTargetPrediction() error!! failed create option");
|
||||
return;
|
||||
}
|
||||
if (count == 1)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = AISimulationRemovalUtility.SelectRemovalTarget(candidates, actor, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Metamorphose, aIRemovalEvaluationOption);
|
||||
if (aIVirtualCard != null && !aIVirtualCard.IsIndependent)
|
||||
{
|
||||
ExecuteMetamorphose(aIVirtualCard, metamorphoseId, actor, field, situation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> list = AISimulationRemovalUtility.SelectMultipleRemovalTargets(candidates, actor, field, playPtn, situation, AISelectTargetPattern.Best, AIRemovalType.Metamorphose, count, aIRemovalEvaluationOption);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
ExecuteMetamorphose(list[i], metamorphoseId, actor, field, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteMetamorphose(AIVirtualCard target, int metamorphoseTokenId, AIVirtualCard actor, AIVirtualField field, AISituationInfo situation)
|
||||
{
|
||||
target.MetamorphoseLeave(situation);
|
||||
MetamorphoseTokenOnVirtualField(target, metamorphoseTokenId, actor, field);
|
||||
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
|
||||
field.ExecuteWhenChangeInplayTags(emptyPlayPtn, situation);
|
||||
}
|
||||
|
||||
public static float EvalTargetingMetamorphose(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, int tokenId, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = float.MinValue;
|
||||
List<AIVirtualCard> bothClassAndInplayCards = tagOwner.SelfField.CardListSet.BothClassAndInplayCards;
|
||||
bothClassAndInplayCards = AIFilteringUtility.MultipleFiltering(bothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
bothClassAndInplayCards.RemoveAll((AIVirtualCard c) => c.IsLeader);
|
||||
if (bothClassAndInplayCards == null || bothClassAndInplayCards.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
if (bothClassAndInplayCards.IsNotNullOrEmpty())
|
||||
{
|
||||
bothClassAndInplayCards = AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(bothClassAndInplayCards, tagOwner, playPtn);
|
||||
for (int num2 = 0; num2 < bothClassAndInplayCards.Count; num2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = bothClassAndInplayCards[num2];
|
||||
if (!aIVirtualCard2.IsIndependent && (aIVirtualCard2.IsAlly == tagOwner.IsAlly || (!aIVirtualCard2.IsUntouchable && !aIVirtualCard2.IsSneak)))
|
||||
{
|
||||
float num3 = EvaluateSingleMetamorphoseValue(aIVirtualCard2, tokenId, tagOwner, field, playPtn, situation);
|
||||
if (num < num3)
|
||||
{
|
||||
num = num3;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static float EvalRandomMetamorphose(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, int tokenId, List<int> playPtn, int count, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> bothClassAndInplayCards = field.CardListSet.BothClassAndInplayCards;
|
||||
bothClassAndInplayCards = AIFilteringUtility.MultipleFiltering(bothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
if (bothClassAndInplayCards == null || bothClassAndInplayCards.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
bothClassAndInplayCards.RemoveAll((AIVirtualCard c) => c.IsLeader);
|
||||
if (bothClassAndInplayCards == null || bothClassAndInplayCards.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
if (bothClassAndInplayCards.Count <= count)
|
||||
{
|
||||
return EvalAllMetamorphose(bothClassAndInplayCards, tokenId, tagOwner, field, playPtn, situation);
|
||||
}
|
||||
float num = 0f;
|
||||
new List<SwappedMetamorphoseInfo>();
|
||||
List<AIVirtualCard[]> list = AIMathematicsLibrary.EnumerateCombinations(bothClassAndInplayCards, count).ToList();
|
||||
for (int num2 = 0; num2 < list.Count; num2++)
|
||||
{
|
||||
List<AIVirtualCard> targetCards = new List<AIVirtualCard>(list[num2]);
|
||||
num += EvalAllMetamorphose(targetCards, tokenId, tagOwner, field, playPtn, situation);
|
||||
}
|
||||
return num / (float)list.Count;
|
||||
}
|
||||
|
||||
public static float EvalAllMetamorphose(AIVirtualCard tagOwner, AIVirtualField field, List<AIScriptTokenBase> filters, int tokenId, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return EvalAllMetamorphose(AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null), tokenId, tagOwner, field, playPtn, situation);
|
||||
}
|
||||
|
||||
private static float EvalAllMetamorphose(List<AIVirtualCard> targetCards, int tokenId, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
targetCards.RemoveAll((AIVirtualCard c) => c.IsLeader);
|
||||
if (targetCards == null || targetCards.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
if (targetCards == null || targetCards.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
List<SwappedMetamorphoseInfo> swappedList = new List<SwappedMetamorphoseInfo>();
|
||||
float num = 0f;
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
AIVirtualCard aIVirtualCard2 = null;
|
||||
for (int num2 = 0; num2 < targetCards.Count; num2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard3 = targetCards[num2];
|
||||
if (aIVirtualCard3.IsIndependent)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard4 = null;
|
||||
if (aIVirtualCard3.IsAlly)
|
||||
{
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
aIVirtualCard = field.AI.tokenManager.GetTokenFromId(tokenId, isAlly: true, field);
|
||||
}
|
||||
aIVirtualCard4 = aIVirtualCard;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aIVirtualCard2 == null)
|
||||
{
|
||||
aIVirtualCard2 = field.AI.tokenManager.GetTokenFromId(tokenId, isAlly: false, field);
|
||||
}
|
||||
aIVirtualCard4 = aIVirtualCard2;
|
||||
}
|
||||
if (aIVirtualCard4 == null)
|
||||
{
|
||||
AIConsoleUtility.LogError(string.Format("AIMetamorphosSimulationUtility.EvaluateSingleMetamorphoseValue() error!! Not found {0}: {1}", aIVirtualCard3.IsAlly ? "Ally" : "ENEMY", tokenId));
|
||||
return 0f;
|
||||
}
|
||||
num += EvaluateMetamorphoseTargetValue(aIVirtualCard3, playPtn, situation) * ((tagOwner.IsAlly != aIVirtualCard3.IsAlly) ? 1f : (-1f));
|
||||
list.Add(aIVirtualCard4);
|
||||
}
|
||||
for (int num3 = 0; num3 < targetCards.Count; num3++)
|
||||
{
|
||||
SwapInplayMetamorphoseCard(list[num3], targetCards[num3], field, ref swappedList);
|
||||
}
|
||||
float num4 = 0f;
|
||||
for (int num5 = 0; num5 < list.Count; num5++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard5 = list[num5];
|
||||
float num6 = EvaluateMetamorphoseTokenValue(aIVirtualCard5, playPtn, situation);
|
||||
num4 += num6 * ((tagOwner.IsAlly != aIVirtualCard5.IsAlly) ? 1f : (-1f));
|
||||
}
|
||||
RestoreInplayMetamorphoseCard(swappedList);
|
||||
list.Clear();
|
||||
return (num - num4) * (tagOwner.IsAlly ? 1f : (-1f));
|
||||
}
|
||||
|
||||
public static float EvaluateSingleMetamorphoseValue(AIVirtualCard targetCard, int afterMetamorphoseTokenId, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
float num = EvaluateMetamorphoseTargetValue(targetCard, playPtn, situation);
|
||||
AIVirtualCard tokenFromId = field.AI.tokenManager.GetTokenFromId(afterMetamorphoseTokenId, targetCard.IsAlly, field);
|
||||
if (tokenFromId == null)
|
||||
{
|
||||
AIConsoleUtility.LogError($"AIMetamorphosSimulationUtility.EvaluateSingleMetamorphoseValue() error!! Not found id == {afterMetamorphoseTokenId}");
|
||||
return 0f;
|
||||
}
|
||||
List<SwappedMetamorphoseInfo> swappedList = new List<SwappedMetamorphoseInfo>();
|
||||
SwapInplayMetamorphoseCard(tokenFromId, targetCard, field, ref swappedList);
|
||||
float num2 = EvaluateMetamorphoseTokenValue(tokenFromId, playPtn, situation);
|
||||
float result = (num - num2) * ((targetCard.IsAlly != tagOwner.IsAlly) ? 1f : (-1f));
|
||||
RestoreInplayMetamorphoseCard(swappedList);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float EvaluateMetamorphoseTargetValue(AIVirtualCard target, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return target.EvaluateValueOnField(playPtn, situation, useStyle: true) + (target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + target.GetAllBanishBonus(playPtn, useIgnoreInBattle: false) + target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false));
|
||||
}
|
||||
|
||||
private static float EvaluateMetamorphoseTokenValue(AIVirtualCard tokenCard, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return tokenCard.EvaluateValueOnField(playPtn, situation, useStyle: true, doesUseLostLife: true, useOthersTag: true, useIgnoreInBattle: true) + (tokenCard.EvaluateBreakValue(playPtn, useIgnoreBreak: true) + tokenCard.EvaluateLeaveValue(playPtn, useIgnoreInBattle: true)) * EnemyAI.BREAKBONUS_RATE_IN_HAND;
|
||||
}
|
||||
|
||||
private static void SwapInplayMetamorphoseCard(AIVirtualCard tokenCard, AIVirtualCard targetCard, AIVirtualField fieldTemp, ref List<SwappedMetamorphoseInfo> swappedList)
|
||||
{
|
||||
if (targetCard.IsAlly)
|
||||
{
|
||||
Swap(fieldTemp.AllyInplayCards, swappedList);
|
||||
Swap(fieldTemp.CardListSet.AllAllyCards, swappedList);
|
||||
Swap(fieldTemp.CardListSet.AllyClassAndInplayCards, swappedList);
|
||||
}
|
||||
else
|
||||
{
|
||||
Swap(fieldTemp.EnemyInplayCards, swappedList);
|
||||
Swap(fieldTemp.CardListSet.EnemyClassAndInplayCards, swappedList);
|
||||
}
|
||||
Swap(fieldTemp.CardListSet.AllReferableCards, swappedList);
|
||||
Swap(fieldTemp.CardListSet.BothClassAndInplayCards, swappedList);
|
||||
Swap(fieldTemp.CardListSet.BothInplayCards, swappedList);
|
||||
void Swap(List<AIVirtualCard> _cardList, List<SwappedMetamorphoseInfo> _swappedList)
|
||||
{
|
||||
int num = _cardList.IndexOf(targetCard);
|
||||
if (num >= 0 && num < _cardList.Count)
|
||||
{
|
||||
_cardList.Insert(num, tokenCard);
|
||||
_cardList.Remove(targetCard);
|
||||
_swappedList = AIParamQuery.AddElementToList(new SwappedMetamorphoseInfo
|
||||
{
|
||||
TargetCard = targetCard,
|
||||
TokenCard = tokenCard,
|
||||
SwappedCardList = _cardList,
|
||||
SwappedIndex = num
|
||||
}, _swappedList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RestoreInplayMetamorphoseCard(List<SwappedMetamorphoseInfo> swappedList)
|
||||
{
|
||||
if (swappedList != null)
|
||||
{
|
||||
for (int i = 0; i < swappedList.Count; i++)
|
||||
{
|
||||
SwappedMetamorphoseInfo swappedMetamorphoseInfo = swappedList[i];
|
||||
List<AIVirtualCard> swappedCardList = swappedMetamorphoseInfo.SwappedCardList;
|
||||
int swappedIndex = swappedMetamorphoseInfo.SwappedIndex;
|
||||
swappedCardList.Insert(swappedIndex, swappedMetamorphoseInfo.TargetCard);
|
||||
swappedCardList.Remove(swappedMetamorphoseInfo.TokenCard);
|
||||
}
|
||||
swappedList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseTokenOnVirtualField(AIVirtualCard targetCard, int tokenId, AIVirtualCard tagOwner, AIVirtualField field)
|
||||
{
|
||||
AIVirtualCard tokenFromId = field.AI.tokenManager.GetTokenFromId(tokenId, targetCard.IsAlly, field, needsClone: true);
|
||||
if (tokenFromId == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseTokenOnVirtualField: tokenCard is null");
|
||||
return;
|
||||
}
|
||||
tokenFromId.InitAtMetamorphose(targetCard, tagOwner);
|
||||
field.CardListSet.ReplaceInplayCard(targetCard.IsAlly, tokenFromId, targetCard);
|
||||
targetCard.IsMetamorphosed = true;
|
||||
if (targetCard.IsAlly)
|
||||
{
|
||||
List<AIVirtualCard> allyInplayCards = field.AllyInplayCards;
|
||||
allyInplayCards.Insert(allyInplayCards.IndexOf(targetCard), tokenFromId);
|
||||
allyInplayCards.Remove(targetCard);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AIVirtualCard> enemyInplayCards = field.EnemyInplayCards;
|
||||
enemyInplayCards.Insert(enemyInplayCards.IndexOf(targetCard), tokenFromId);
|
||||
enemyInplayCards.Remove(targetCard);
|
||||
field.EnemyTokenQueue.Enqueue(new Tuple<AIVirtualCard, AIVirtualCard>(targetCard, tokenFromId));
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseHandAll(AIVirtualField field, List<AIVirtualCard> range, int metamorphoseId, AIVirtualCard actor, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
MetamorphoseHandOnVirtualField(range[i], metamorphoseId, actor, field);
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseHandRandom(AIVirtualField field, List<AIVirtualCard> range, int metamorphoseId, AIVirtualCard actor, List<int> playPtn, AISituationInfo situaion)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
float num = float.MinValue;
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = range[i];
|
||||
float num2 = aIVirtualCard2.EvaluatePlayValue(playPtn, situaion) + aIVirtualCard2.GetHandBonus(playPtn, situaion, isIgnoreInFusion: false);
|
||||
if (num < num2)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
MetamorphoseHandOnVirtualField(aIVirtualCard, metamorphoseId, actor, field);
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseHandTarget(AIVirtualField field, List<AIVirtualCard> candidates, int metamorphoseId, AISituationInfo situation, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseHandTarget error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < situationTarget.Targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = situationTarget.Targets[i];
|
||||
if (candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
MetamorphoseHandOnVirtualField(aIVirtualCard, metamorphoseId, situation.Actor, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MetamorphoseHandOnVirtualField(AIVirtualCard targetCard, int tokenId, AIVirtualCard tagOwner, AIVirtualField field)
|
||||
{
|
||||
AIVirtualCard tokenFromId = field.AI.tokenManager.GetTokenFromId(tokenId, tagOwner.IsAlly, field, needsClone: true);
|
||||
if (tokenFromId == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("MetamorphoseHandOnVirtualField: tokenCard is null");
|
||||
return;
|
||||
}
|
||||
tokenFromId.InitAtHandMetamorphose(targetCard, tagOwner);
|
||||
targetCard.IsMetamorphosed = true;
|
||||
if (targetCard.IsAlly)
|
||||
{
|
||||
field.CardListSet.ReplaceAllyHandCard(tokenFromId, targetCard);
|
||||
}
|
||||
List<AIVirtualCard> obj = (targetCard.IsAlly ? field.AllyHandCards : field.GetEnemyHandCardList());
|
||||
obj.Insert(obj.IndexOf(targetCard), tokenFromId);
|
||||
obj.Remove(targetCard);
|
||||
}
|
||||
}
|
||||
503
SVSim.BattleEngine/Engine/Wizard/AINetworkBattleManager.cs
Normal file
503
SVSim.BattleEngine/Engine/Wizard/AINetworkBattleManager.cs
Normal file
@@ -0,0 +1,503 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Wizard.Battle;
|
||||
using Wizard.Battle.Phase;
|
||||
using Wizard.Battle.Recovery;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
using Wizard.BattleMgr;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AINetworkBattleManager : NetworkBattleManagerBase
|
||||
{
|
||||
private AITurnControl _aiTurnControl;
|
||||
|
||||
private Func<VfxBase> _turnTransitionFunc;
|
||||
|
||||
private VfxBase _initiateGameEndFunc;
|
||||
|
||||
private bool _sendFinshBattleTask;
|
||||
|
||||
private bool _isWin;
|
||||
|
||||
public AIBattleInfoReceiver BattleInfoReceiver { get; protected set; }
|
||||
|
||||
public AINetworkBattleManager(IBattleMgrContentsCreator contentsCreator)
|
||||
: base(contentsCreator)
|
||||
{
|
||||
_turnTransitionFunc = null;
|
||||
}
|
||||
|
||||
protected override void NetworkBattleManagerSetup()
|
||||
{
|
||||
DataMgr dataMgr = GameMgr.GetIns().GetDataMgr();
|
||||
dataMgr.SetDeckMaxCount(40, isSelf: true);
|
||||
dataMgr.SetDeckMaxCount(40, isSelf: false);
|
||||
IsShowDisconnectPanel = false;
|
||||
IsShowOpponentDisconnectPanel = false;
|
||||
NotReplaceCardList = new List<ReplaceReceivedCard.CardIdAndIndex>();
|
||||
base.validateSkillIndexList = new List<ValidateSkillData>();
|
||||
RegisterActionManager = new RegisterActionManager(this);
|
||||
base.RegisterUnapprovedList = new List<RegisterUnapproved>();
|
||||
base.registerSelectTypeSkillIndexList = new List<int>();
|
||||
sendKeyActionDataManager = new SendKeyActionDataManager();
|
||||
TouchControl = new NetworkTouchControl(this, _battleCamera, _backGround);
|
||||
networkTouchControl = TouchControl as NetworkTouchControl;
|
||||
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.NotFinish;
|
||||
if (base.IsRecovery || GameMgr.GetIns().IsReplayBattle)
|
||||
{
|
||||
networkTouchControl.SetDisableTouch();
|
||||
base.networkBattleData = new NetworkRecoveryBattleData(this);
|
||||
networkReceiver = new NetworkReplayBattleReceiver(this);
|
||||
OperateReceive = new RecoveryOperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
|
||||
int selfIdxSeed = (base.IsRecovery ? _contentsCreator.RecoveryManager.IdxChangeSeed : Data.ReplayBattleInfo.IdxChangeSeed);
|
||||
int oppIdxSeed = (GameMgr.GetIns().IsReplayBattle ? Data.ReplayBattleInfo.OppoIdxChangeSeed : (-1));
|
||||
CreateXorShift(selfIdxSeed, oppIdxSeed);
|
||||
BattleEnemy.EnableEnemyAI = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.networkBattleData = new NetworkBattleData(this);
|
||||
networkReceiver = new NetworkBattleReceiver(this);
|
||||
OperateReceive = new OperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
|
||||
}
|
||||
OperateMgr.SetTouchControl(TouchControl);
|
||||
networkConsistency = new NetworkConsistency(this);
|
||||
_networkBattleSetupCardEventBase = new NetworkAIBattleSetupCardEvent(this, RegisterActionManager, base.networkBattleData);
|
||||
operateReceiveChecker = new OperateReceiveChecker(this, base.networkBattleData);
|
||||
_intervalCheckList = new List<NetworkBattleIntervalCheckerBase>();
|
||||
base.opponentRecoveryToDispChecker = new OpponentRecoveryToDispChecker();
|
||||
base.disconnectToDispChecker = new DisconnectToDispChecker();
|
||||
_intervalCheckList.Add(base.disconnectToDispChecker);
|
||||
base.disconnectToLoseChecker = new DisconnectToLoseChecker();
|
||||
base.disconnectToLoseChecker.OnDisconnectLose += delegate
|
||||
{
|
||||
DisconnectLose();
|
||||
};
|
||||
base.disconnectToLoseChecker.OnBeforeDisconnectLose += delegate
|
||||
{
|
||||
BeforeDisconnectLose();
|
||||
};
|
||||
_intervalCheckList.Add(base.disconnectToLoseChecker);
|
||||
base.notMulliganEndToJudgeChecker = new NullNotMulliganEndToJudgeChecker();
|
||||
base.notTurnEndToLoseChecker = new NullNotTurnEndToLoseChecker(this);
|
||||
base.receiveTurnEndToJudgeResult = new NullReceiveTurnEndToJudgeResult();
|
||||
_intervalCheckList.Add(base.notTurnEndToLoseChecker);
|
||||
base.notTurnStartToLoseChecker = new NullNotTurnStartToLoseChecker();
|
||||
_intervalCheckList.Add(base.notTurnStartToLoseChecker);
|
||||
SendIntervalTriggerMain = new AISendIntervalTrigger();
|
||||
base.NetworkSender = new NetworkBattleSender(this, RegisterActionManager, base.RegisterUnapprovedList, networkConsistency);
|
||||
_aiTurnControl = new AITurnControl();
|
||||
if (!base.IsRecovery)
|
||||
{
|
||||
SettingOpponentAliveEvent();
|
||||
IsStopIntervalCheck = false;
|
||||
ToolboxGame.RealTimeNetworkAgent.StartPreparedStartTimer(DateTime.Now);
|
||||
ToolboxGame.RealTimeNetworkAgent.StartRecoveryRecording();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisconnectLose()
|
||||
{
|
||||
JudgeErrorDialog(isError: false);
|
||||
}
|
||||
|
||||
public override VfxBase ChangePhase(IPhase phase)
|
||||
{
|
||||
if (phase is NetworkMulliganPhase || (phase is MainPhase && base.IsRecovery))
|
||||
{
|
||||
base.notMulliganEndToJudgeChecker.StartChecker();
|
||||
base.disconnectToDispChecker.OnDisp += delegate
|
||||
{
|
||||
ControlDisconnectOffTouchAndView(flag: true);
|
||||
};
|
||||
base.disconnectToDispChecker.OnErase += delegate
|
||||
{
|
||||
ControlDisconnectOffTouchAndView(flag: false);
|
||||
};
|
||||
}
|
||||
if (phase is OpeningPhase)
|
||||
{
|
||||
ConnectionReportTrigger.ConnectionReport(this);
|
||||
}
|
||||
return base.ChangePhase(phase);
|
||||
}
|
||||
|
||||
public override void Update(float dt)
|
||||
{
|
||||
base.Update(dt);
|
||||
if (_turnTransitionFunc != null && ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
|
||||
{
|
||||
base.VfxMgr.RegisterSequentialVfx(_turnTransitionFunc.GetAllFuncVfxResults());
|
||||
_turnTransitionFunc = null;
|
||||
}
|
||||
if (_initiateGameEndFunc != null && ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
|
||||
{
|
||||
base.VfxMgr.RegisterSequentialVfx(_initiateGameEndFunc);
|
||||
_initiateGameEndFunc = null;
|
||||
}
|
||||
if (ToolboxGame.RealTimeNetworkAgent != null && _turnTransitionFunc == null && !IsBattleEnd && BattleEnemy.IsSelfTurn)
|
||||
{
|
||||
_aiTurnControl.Update(EnemyAI);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetupBattlePlayersEvent()
|
||||
{
|
||||
BattlePlayer.OnSetupCardEvent += SetupCardEvent;
|
||||
BattleEnemy.OnSetupCardEvent += SetupCardEvent;
|
||||
BattlePlayer.OnSetupClassEvent += SetupPlayerClassEvent;
|
||||
BattleEnemy.OnSetupClassEvent += SetupOpponentClassEvent;
|
||||
BattlePlayer.Setup(BattleEnemy);
|
||||
BattleEnemy.Setup(BattlePlayer);
|
||||
BattlePlayer.OnTurnEnd += delegate
|
||||
{
|
||||
base.VfxMgr.Cancel();
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetupNetworkEvent(bool isRecovery)
|
||||
{
|
||||
BattlePlayer.OnPlayerActive += delegate
|
||||
{
|
||||
if (turnEndTimeController != null)
|
||||
{
|
||||
turnEndTimeController.StartCountDown("AIOnPlayerActive");
|
||||
}
|
||||
};
|
||||
BattlePlayer battlePlayer = BattlePlayer;
|
||||
battlePlayer.OnPostTurnEndComplete = (Action)Delegate.Combine(battlePlayer.OnPostTurnEndComplete, (Action)delegate
|
||||
{
|
||||
if (turnEndTimeController != null)
|
||||
{
|
||||
turnEndTimeController.EndCountDown("AIOnTurnEndComplete");
|
||||
}
|
||||
SendTurnEndAction();
|
||||
});
|
||||
BattleEnemy.OnTurnStartBeforeDraw += delegate
|
||||
{
|
||||
if (!IsVirtualBattle)
|
||||
{
|
||||
_aiTurnControl.StartTurnTimer();
|
||||
}
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
BattleEnemy battleEnemy = BattleEnemy;
|
||||
battleEnemy.OnPostTurnEndComplete = (Action)Delegate.Combine(battleEnemy.OnPostTurnEndComplete, (Action)delegate
|
||||
{
|
||||
if (!IsVirtualBattle)
|
||||
{
|
||||
_aiTurnControl.StopTurnTimer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void InitiateGameEndSequence(bool hasWon)
|
||||
{
|
||||
if (ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
|
||||
{
|
||||
if (!_sendFinshBattleTask)
|
||||
{
|
||||
_sendFinshBattleTask = true;
|
||||
_isWin = hasWon;
|
||||
BattleFinishToEffectClear();
|
||||
BattleFinishToStopIntervalChecker();
|
||||
ToolboxGame.RealTimeNetworkAgent.FinishBattleTask(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_initiateGameEndFunc = InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void FinishBattleEffect(bool classDead)
|
||||
{
|
||||
classDead = !_isWin;
|
||||
if (classDead)
|
||||
{
|
||||
BattleCardBase battleCardBase = GetBattlePlayer(classDead).Class;
|
||||
if (battleCardBase.Life >= 1 && !battleCardBase.IsDead)
|
||||
{
|
||||
battleCardBase.FlagCardAsDestroyedByKiller();
|
||||
FINISH_TYPE finishTypeByStatus = GetFinishTypeByStatus();
|
||||
base.VfxMgr.RegisterSequentialVfx(DeadClass(classDead, finishTypeByStatus));
|
||||
}
|
||||
}
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
base.InitiateGameEndSequence(!classDead);
|
||||
}));
|
||||
}
|
||||
|
||||
public override VfxBase JudgeBattleResult()
|
||||
{
|
||||
if (BattlePlayer.Class.IsDead && BattleEnemy.Class.IsDead)
|
||||
{
|
||||
return InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(!BattlePlayer.IsSelfTurn);
|
||||
});
|
||||
}
|
||||
if (BattlePlayer.Class.IsDead)
|
||||
{
|
||||
return InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: false);
|
||||
});
|
||||
}
|
||||
if (BattleEnemy.Class.IsDead)
|
||||
{
|
||||
return InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: true);
|
||||
});
|
||||
}
|
||||
return NullVfx.GetInstance();
|
||||
}
|
||||
|
||||
protected override void SetupEvent()
|
||||
{
|
||||
base.SetupEvent();
|
||||
BattlePlayer.OnShortageDeck += () => OnShortageDeck(BattlePlayer);
|
||||
BattleEnemy.OnShortageDeck += () => OnShortageDeck(BattleEnemy);
|
||||
SetUpTurnTransitionEvent();
|
||||
}
|
||||
|
||||
private void SetUpTurnTransitionEvent()
|
||||
{
|
||||
BattlePlayer.OnTurnEndFinish += delegate
|
||||
{
|
||||
if (IsVirtualBattle || base.IsRecovery)
|
||||
{
|
||||
return NullVfx.GetInstance();
|
||||
}
|
||||
_turnTransitionFunc = null;
|
||||
_turnTransitionFunc = (Func<VfxBase>)Delegate.Combine(_turnTransitionFunc, new Func<VfxBase>(base.ControlTurnStartOpponent));
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
BattleEnemy.OnTurnEndFinish += delegate
|
||||
{
|
||||
if (IsVirtualBattle || base.IsRecovery)
|
||||
{
|
||||
return NullVfx.GetInstance();
|
||||
}
|
||||
_turnTransitionFunc = null;
|
||||
_turnTransitionFunc = (Func<VfxBase>)Delegate.Combine(_turnTransitionFunc, new Func<VfxBase>(base.ControlTurnStartPlayer));
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetupBattlePlayerRegisterEvents(BattlePlayerBase battlePlayer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void SetupNetworkActionProcessorEvent(ActionProcessor processor, bool isPlayer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetupFieldAndHandAfterRecovery(Action onEndRecoveryCallback, RecoveryOperationInfo aiBattleRecoveryData = null)
|
||||
{
|
||||
if (aiBattleRecoveryData.SetupInfo.HasMulliganInfo)
|
||||
{
|
||||
BattlePlayer.PlayerBattleView.ClearPlayQueue();
|
||||
BattleEnemy.BattleEnemyView.ClearPlayQueue();
|
||||
RecreateCardViews(BattlePlayer.InPlayCards);
|
||||
RecreateCardViews(BattlePlayer.HandCardList);
|
||||
RecreateCardViews(BattlePlayer.DeckCardList);
|
||||
RecreateCardViews(BattlePlayer.ReservedCardList);
|
||||
RecreateCardViews(BattleEnemy.InPlayCards);
|
||||
RecreateCardViews(BattleEnemy.HandCardList);
|
||||
RecreateCardViews(BattleEnemy.DeckCardList);
|
||||
RecreateCardViews(BattleEnemy.ReservedCardList);
|
||||
RefreshHealthVfx refreshHealthVfx = new RefreshHealthVfx(BattlePlayer);
|
||||
RefreshHealthVfx refreshHealthVfx2 = new RefreshHealthVfx(BattleEnemy);
|
||||
ParallelVfxPlayer parallelVfxPlayer = ParallelVfxPlayer.Create(BattlePlayer.BattleView.Recovery(doseFirst: false), BattleEnemy.BattleView.Recovery(doseFirst: false), refreshHealthVfx, refreshHealthVfx2);
|
||||
VfxBase vfxBase = (BattleEnemy.IsSelfTurn ? BattleEnemy.CreateThinkingVfx(this) : NullVfx.GetInstance());
|
||||
SequentialVfxPlayer vfx = SequentialVfxPlayer.Create(RecoveryAfterMulliganPhase.RestoreUI(this), parallelVfxPlayer, HandViewBase.CreateHideCardMeshesVfx(BattleEnemy.HandCardList), vfxBase, InstantVfx.Create(delegate
|
||||
{
|
||||
ResetLeaderAnimation(BattlePlayer, BattleEnemy);
|
||||
}));
|
||||
base.VfxMgr.RegisterSequentialVfx(vfx);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RecoveryEnd()
|
||||
{
|
||||
base.IsRecovery = false;
|
||||
SettingOpponentAliveEvent();
|
||||
IsStopIntervalCheck = false;
|
||||
SetUpTurnTransitionEvent();
|
||||
networkTouchControl.SetEnableTouch();
|
||||
NetworkBattleData networkBattleData = base.networkBattleData;
|
||||
base.networkBattleData = new NetworkBattleData(this);
|
||||
base.networkBattleData.isPlayerMulliganEnd = networkBattleData.isPlayerMulliganEnd;
|
||||
base.networkBattleData.isOppoMulliganEnd = networkBattleData.isOppoMulliganEnd;
|
||||
base.networkBattleData.SetReceiveData(networkBattleData.GetReceiveData());
|
||||
base.networkBattleData.isEnemyFirstTurn = networkBattleData.isEnemyFirstTurn;
|
||||
_networkBattleSetupCardEventBase.OverwriteNetworkBattleData(base.networkBattleData);
|
||||
SetupCreateBattleCardFunc(createCardWithoutGameObject: false);
|
||||
OperateMgr operateMgr = OperateMgr;
|
||||
OperateMgr = CreateOperateMgr();
|
||||
OperateMgr.SetUpRecoveryEvent(operateMgr);
|
||||
StartRecoveryRecording();
|
||||
operateMgr = null;
|
||||
OperateReceive = new OperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
|
||||
if (_phase is NetworkMulliganPhase)
|
||||
{
|
||||
(_phase as NetworkMulliganPhase).MulliganEventSetting();
|
||||
}
|
||||
operateReceiveChecker = new OperateReceiveChecker(this, base.networkBattleData);
|
||||
networkReceiver = new NetworkBattleReceiver(this);
|
||||
SetupNetworkEvent(isRecovery: true);
|
||||
if (_specialWinVfx == null)
|
||||
{
|
||||
ClearRegisterCardList();
|
||||
}
|
||||
BattleEnemy.EnableEnemyAI = true;
|
||||
BattlePlayer.Emotion.Enable = true;
|
||||
BattleEnemy.Emotion.Enable = true;
|
||||
if (BattleEnemy.IsSelfTurn)
|
||||
{
|
||||
EnemyAI.StopEnemyAI();
|
||||
EnemyAI.ExecuteEnemyAI(useWait: true);
|
||||
}
|
||||
ConnectionReportTrigger.ConnectionReport(this);
|
||||
}
|
||||
|
||||
protected override void FirstRecoverySetting()
|
||||
{
|
||||
if (!base.IsRecovery)
|
||||
{
|
||||
StartRecoveryRecording();
|
||||
}
|
||||
}
|
||||
|
||||
protected override int CreateBackgroundId()
|
||||
{
|
||||
if (_contentsCreator is RecoveryNetworkBattleMgrContentsCreator)
|
||||
{
|
||||
int backGroundId = ((RecoveryNetworkBattleMgrContentsCreator)_contentsCreator).RecoveryControllerInstance.AIBattleRecoveryData.SetupInfo.BackGroundId;
|
||||
if (backGroundId >= 0)
|
||||
{
|
||||
return backGroundId;
|
||||
}
|
||||
}
|
||||
return CalculationRandomStage();
|
||||
}
|
||||
|
||||
public override void FinishBattle()
|
||||
{
|
||||
EnemyAI.StopEnemyAI();
|
||||
}
|
||||
|
||||
public override void RecoveryTimeOutSetting(float extendTime, bool isMulliganEnd, long startTime = -1L)
|
||||
{
|
||||
if (!isMulliganEnd)
|
||||
{
|
||||
if (MulliganMgr != null)
|
||||
{
|
||||
MulliganMgr.GetMulliganInfo().SetExtendTime(extendTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!BattlePlayer.IsSelfTurn)
|
||||
{
|
||||
if (startTime != -1)
|
||||
{
|
||||
_aiTurnControl.SetAndStartTurnTimer(DateTimeOffset.FromUnixTimeSeconds(startTime).LocalDateTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (turnEndTimeController == null)
|
||||
{
|
||||
TurnEndButtonUI component = SBattleLoad.m_TurnEndBtnUI.GetComponent<TurnEndButtonUI>();
|
||||
turnEndTimeController = new TurnEndTimeController(this, BattlePlayer, component);
|
||||
}
|
||||
if (!turnEndTimeController.IsCountdownRunning())
|
||||
{
|
||||
turnEndTimeController.StartCountDown("SetTimeoutSetting");
|
||||
}
|
||||
turnEndTimeController.SetExtendTime(extendTime);
|
||||
}
|
||||
|
||||
public void SetupMulliganLaunchCompleteEvent()
|
||||
{
|
||||
_contentsCreator.RecoveryRecordManager.SetupMulliganStartTimeRecorderEvent(this);
|
||||
}
|
||||
|
||||
public override VfxBase StartBattle()
|
||||
{
|
||||
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
||||
LocalLog.SetLastTraceLogTurn(1);
|
||||
sequentialVfxPlayer.Register(ChangePhase(base.PhaseCreator.CreateMainPhase()));
|
||||
if (IsFirst)
|
||||
{
|
||||
sequentialVfxPlayer.Register(BattlePlayer.StartTurnControl("AIFirst"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sequentialVfxPlayer.Register(BattleEnemy.StartTurnControl());
|
||||
}
|
||||
return sequentialVfxPlayer;
|
||||
}
|
||||
|
||||
public override void SetupEnemyAI()
|
||||
{
|
||||
EnemyAI enemyAI = new RankMatchEnemyAI();
|
||||
enemyAI.LoadBufferedBattleState();
|
||||
EnemyAI = enemyAI;
|
||||
BattleInfoReceiver = new AIBattleInfoReceiver(EnemyAI);
|
||||
EnemyAI.InitOnGame(BattleEnemy, BattlePlayer);
|
||||
if (!base.IsRecovery)
|
||||
{
|
||||
BattleEnemy.EnableEnemyAI = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override BattleCardBase MetamorphoseCard(int cardId, bool isPlayer, int addIndex, SkillBase skill, bool isFusion = false)
|
||||
{
|
||||
return CreateBattleCardWithGameObject(new CardCreateInfo(cardId, isPlayer, skill.ApplyingTargetFilter is SkillTargetChosenCardsFilter, NetworkBattleDefine.NetworkCardPlaceState.None, isReferenceOpponentCard: false, skill), new IndexInfo(addIndex));
|
||||
}
|
||||
|
||||
public override BattleCardBase CreateBattleCardWithGameObject(CardCreateInfo info, IndexInfo indexInfo, int repeatCount = -1, bool isVirtual = false, bool isActualCard = false)
|
||||
{
|
||||
CardParameter cardParameterFromId = CardMaster.GetInstanceForBattle().GetCardParameterFromId(info.Id);
|
||||
BattlePlayerBase battlePlayer = GetBattlePlayer(info.IsPlayer);
|
||||
int cardIndex = SetupCardIndex(battlePlayer, indexInfo.AddIndex);
|
||||
GameObject cardGameObject = null;
|
||||
if (!base.IsRecovery || !isVirtual)
|
||||
{
|
||||
cardGameObject = CreateBaseCardGameObject(cardParameterFromId, info.IsPlayer, cardIndex);
|
||||
}
|
||||
BattleCardBase battleCardBase = CreateBattleCard(info.Id, info.IsPlayer, cardGameObject, cardParameterFromId, battlePlayer, cardIndex);
|
||||
if (!base.IsRecovery || !isVirtual)
|
||||
{
|
||||
SetupCardObjectMaterials(cardGameObject, battleCardBase);
|
||||
}
|
||||
return battleCardBase;
|
||||
}
|
||||
|
||||
protected override void ControlDisconnectOffTouchAndView(bool flag)
|
||||
{
|
||||
if (!_sendFinshBattleTask)
|
||||
{
|
||||
base.ControlDisconnectOffTouchAndView(flag);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PlayRetire()
|
||||
{
|
||||
if (RecoveryRecordManagerBase.IsExistsAINetworkRecoveryFile())
|
||||
{
|
||||
GameMgr.GetIns().GetDataMgr().SetRecoveryData(RecoveryOperationInfo.ReadRecoveryFile(OperationRecorderBase.RecordDirectoryPath + "recovery_ai_network.json"));
|
||||
RecoveryRecordManagerBase.DeleteRecoveryFile();
|
||||
}
|
||||
base.PlayRetire();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AINotBeAttackedSimulationUtility
|
||||
{
|
||||
public static void GiveNotBeAttackedToAll(List<AIVirtualCard> targets)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!aIVirtualCard.IsIndependent)
|
||||
{
|
||||
aIVirtualCard.NotBeAttacked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void GiveNotBeAttackedToTargeted(AISituationInfo situation, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("GiveNotBeAttackedToTargeted error! No target!");
|
||||
}
|
||||
else
|
||||
{
|
||||
GiveNotBeAttackedToAll(situationTarget.Targets);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
SVSim.BattleEngine/Engine/Wizard/AIOneMoreLastwordUtility.cs
Normal file
134
SVSim.BattleEngine/Engine/Wizard/AIOneMoreLastwordUtility.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIOneMoreLastwordUtility
|
||||
{
|
||||
public static bool IsHoldingOneMoreLastword(AIVirtualCard tagOwner, AIVirtualField field)
|
||||
{
|
||||
if (!tagOwner.TagCollectionContainer.HasTag(AIPlayTagType.OneMoreLastword))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return tagOwner.TagCollectionContainer.OneMoreLastwordTags.CheckCondition(tagOwner, field);
|
||||
}
|
||||
|
||||
private static bool IsOneMoreLastwordHolderInplay(AIVirtualField field, List<int> enemyTargets, ref int holderIndex, ref float threshold)
|
||||
{
|
||||
for (int i = 0; i < enemyTargets.Count; i++)
|
||||
{
|
||||
AIVirtualCard owner = field.EnemyInplayCards[enemyTargets[i]];
|
||||
if (IsGiveTagOfOneMoreLastwordTagged(field, owner, ref threshold))
|
||||
{
|
||||
holderIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SortEnemyTargetByBreakBonus(AIVirtualField field, List<int> enemyTargets)
|
||||
{
|
||||
if (IsHoldingOneMoreLastword(field.EnemyClass, field))
|
||||
{
|
||||
SortEnemyTargetsWhenLeaderTaggedOneMoreLastword(field, enemyTargets);
|
||||
return;
|
||||
}
|
||||
float threshold = 0f;
|
||||
int holderIndex = -1;
|
||||
if (IsOneMoreLastwordHolderInplay(field, enemyTargets, ref holderIndex, ref threshold))
|
||||
{
|
||||
SortEnemyTargetsWhenOneMoreLastwordHolderInplay(field, enemyTargets, holderIndex, threshold);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SortEnemyTargetsWhenLeaderTaggedOneMoreLastword(AIVirtualField field, List<int> enemyTargets)
|
||||
{
|
||||
float num = float.MaxValue;
|
||||
int num2 = -1;
|
||||
for (int i = 0; i < enemyTargets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.EnemyInplayCards[enemyTargets[i]];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword))
|
||||
{
|
||||
float num3 = aIVirtualCard.EvaluateBreakValue(field.BestPlayPtn, useIgnoreBreak: true);
|
||||
if (num3 < num)
|
||||
{
|
||||
num = num3;
|
||||
num2 = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num2 > 0)
|
||||
{
|
||||
int value = enemyTargets[num2];
|
||||
for (int num4 = num2; num4 > 0; num4--)
|
||||
{
|
||||
enemyTargets[num4] = enemyTargets[num4 - 1];
|
||||
}
|
||||
enemyTargets[0] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SortEnemyTargetsWhenOneMoreLastwordHolderInplay(AIVirtualField field, List<int> enemyTargets, int holderIndex, float breakBonusThreshold)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
List<int> list2 = new List<int>();
|
||||
float num = float.MaxValue;
|
||||
for (int i = 0; i < enemyTargets.Count; i++)
|
||||
{
|
||||
if (i == holderIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num2 = enemyTargets[i];
|
||||
AIVirtualCard aIVirtualCard = field.EnemyInplayCards[num2];
|
||||
if (!aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Lastword) && !aIVirtualCard.TagCollectionContainer.HasTag(AIPlayTagType.Break))
|
||||
{
|
||||
list2.Add(num2);
|
||||
continue;
|
||||
}
|
||||
float num3 = aIVirtualCard.EvaluateBreakValue(field.BestPlayPtn, useIgnoreBreak: true);
|
||||
if (num3 >= breakBonusThreshold)
|
||||
{
|
||||
list.Add(num2);
|
||||
}
|
||||
else if (num3 <= num)
|
||||
{
|
||||
num = num3;
|
||||
list2.Insert(0, num2);
|
||||
}
|
||||
else
|
||||
{
|
||||
list2.Add(num2);
|
||||
}
|
||||
}
|
||||
list.Add(enemyTargets[holderIndex]);
|
||||
enemyTargets.Clear();
|
||||
enemyTargets.AddRange(list);
|
||||
enemyTargets.AddRange(list2);
|
||||
}
|
||||
|
||||
private static bool IsGiveTagOfOneMoreLastwordTagged(AIVirtualField field, AIVirtualCard owner, ref float threshold)
|
||||
{
|
||||
if (!owner.TagCollectionContainer.HasTag(AIPlayTagType.LastwordAttachTag))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<AIPlayTag> lastwordAttachTagContents = owner.TagCollectionContainer.LastwordTags.GetLastwordAttachTagContents();
|
||||
if (lastwordAttachTagContents == null || lastwordAttachTagContents.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < lastwordAttachTagContents.Count; i++)
|
||||
{
|
||||
AIPlayTag aIPlayTag = lastwordAttachTagContents[i];
|
||||
if (aIPlayTag.Type == AIPlayTagType.OneMoreLastword)
|
||||
{
|
||||
threshold = aIPlayTag.EvalArg(field.EnemyClass, field.BestPlayPtn, field, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
19
SVSim.BattleEngine/Engine/Wizard/AIPlayBounce.cs
Normal file
19
SVSim.BattleEngine/Engine/Wizard/AIPlayBounce.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayBounce : AIFiltersAndSelectTypeArgument
|
||||
{
|
||||
public AIPlayBounce(string text)
|
||||
: base(text)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateLegalSelectTypes()
|
||||
{
|
||||
base.LegalSelectTypes = new AIScriptTokenArgType[3]
|
||||
{
|
||||
AIScriptTokenArgType.ALL_SELECT,
|
||||
AIScriptTokenArgType.RANDOM_SELECT,
|
||||
AIScriptTokenArgType.TARGET_SELECT
|
||||
};
|
||||
}
|
||||
}
|
||||
47
SVSim.BattleEngine/Engine/Wizard/AIPlayReanimate.cs
Normal file
47
SVSim.BattleEngine/Engine/Wizard/AIPlayReanimate.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIPlayReanimate : AIScriptArgumentExpressions
|
||||
{
|
||||
private AIPolishConvertedExpression _reanimateCostArg;
|
||||
|
||||
private AIPolishConvertedExpression _reanimateCountArg;
|
||||
|
||||
private const int REANIMATE_COST_INDEX = 0;
|
||||
|
||||
private const int REANIMATE_COUNT_INDEX = 1;
|
||||
|
||||
public AIPlayReanimate(string text)
|
||||
: base(text)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitExpressions(string text)
|
||||
{
|
||||
base.InitExpressions(text);
|
||||
if (_exprList.Count > 1)
|
||||
{
|
||||
_reanimateCostArg = _exprList[0];
|
||||
_reanimateCountArg = _exprList[1];
|
||||
}
|
||||
}
|
||||
|
||||
public int GetReanimateCost(AIVirtualCard tagOwner, List<int> playPtn)
|
||||
{
|
||||
if (_reanimateCostArg == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (int)_reanimateCostArg.EvalArg(tagOwner, playPtn, tagOwner.SelfField);
|
||||
}
|
||||
|
||||
public int GetReanimateCount(AIVirtualCard tagOwner, List<int> playPtn)
|
||||
{
|
||||
if (_reanimateCountArg == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)_reanimateCountArg.EvalArg(tagOwner, playPtn, tagOwner.SelfField);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIPlayerLifeSimulationUtility
|
||||
{
|
||||
public static int GetAllSelfTurnDamageCount(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType durationType)
|
||||
{
|
||||
return GetSelfTurnDamageCountAtPlayed(tagOwner, field, playPtn, durationType) + GetSelfTurnDamageCountAtPlayPtn(tagOwner, field, playPtn);
|
||||
}
|
||||
|
||||
public static int GetSelfTurnDamageCountAtPlayed(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType durationType)
|
||||
{
|
||||
int num = 0;
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
_ = field.EnemyBattlePlayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = field.AllyBattlePlayer;
|
||||
}
|
||||
return durationType switch
|
||||
{
|
||||
AIScriptTokenArgType.TURN => field.AllyDamageCountInTurn,
|
||||
AIScriptTokenArgType.GAME => tagOwner.IsAlly ? field.AllyDamageCountInGame : field.EnemyDamageCountInGame,
|
||||
_ => num,
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetSelfTurnDamageCountAtPlayPtn(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn)
|
||||
{
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
IEnumerable<SkillBase> enumerable = null;
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
enumerable = GetSelfInjurySkillsOnPlay(field.AllyHandCards[playPtn[i]], field);
|
||||
if (enumerable != null)
|
||||
{
|
||||
num += enumerable.Count();
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetSelfTurnDamageCountAtBeforePlayPtn(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType durationType)
|
||||
{
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
IEnumerable<SkillBase> enumerable = null;
|
||||
for (int i = 0; i < playPtn.Count && !tagOwner.IsSameCard(field.AllyHandCards[playPtn[i]]); i++)
|
||||
{
|
||||
enumerable = GetSelfInjurySkillsOnPlay(field.AllyHandCards[playPtn[i]], field);
|
||||
if (enumerable != null)
|
||||
{
|
||||
num += enumerable.Count();
|
||||
}
|
||||
}
|
||||
return num + GetSelfTurnDamageCountAtPlayed(tagOwner, field, playPtn, durationType);
|
||||
}
|
||||
|
||||
public static IEnumerable<SkillBase> GetSelfInjurySkillsOnPlay(AIVirtualCard card, AIVirtualField field)
|
||||
{
|
||||
foreach (SkillBase battleSkill in card.BattleSkills)
|
||||
{
|
||||
if (!(battleSkill is Skill_damage) || !battleSkill.IsWhenPlaySkill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BattlePlayerReadOnlyInfoPair playerInfoPair = new BattlePlayerReadOnlyInfoPair(field.AllyBattlePlayer, field.EnemyBattlePlayer);
|
||||
if (!battleSkill.CheckConditionAI(playerInfoPair, new SkillConditionCheckerOption(), isPrePlay: true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
IEnumerable<BattleCardBase> selectableCards = battleSkill.GetSelectableCards(playerInfoPair, new SkillConditionCheckerOption());
|
||||
foreach (BattleCardBase item in selectableCards)
|
||||
{
|
||||
if (item == field.AllyBattlePlayer.Class)
|
||||
{
|
||||
yield return battleSkill;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIPlayoutAttackerCountUtility
|
||||
{
|
||||
public static int GetPlayoutAttackerCount(AIVirtualField field, AIVirtualCard tagOwner, List<int> playPtn, List<AIScriptTokenBase> filters, AISituationInfo situation)
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < field.AllyInplayCards.Count; i++)
|
||||
{
|
||||
if (IsPlayoutAttacker(field.AllyInplayCards[i], field, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
AISinglePlayptnRecord playptnRecordOnSim = field.GetPlayptnRecordOnSim(playPtn);
|
||||
for (int j = 0; j < playPtn.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[playPtn[j]];
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (IsPlayoutAttacker(aIVirtualCard, field, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
AIVirtualCard actor = aIVirtualCard;
|
||||
if (playptnRecordOnSim != null)
|
||||
{
|
||||
PlayedCardInfo playedCardInfo = playptnRecordOnSim.PlayedCardList[j];
|
||||
actor = ((playedCardInfo.TransformCard != null) ? playedCardInfo.TransformCard : aIVirtualCard);
|
||||
}
|
||||
AIVirtualTargetSelectAction aIVirtualTargetSelectAction = new AIVirtualTargetSelectAction(actor, aIVirtualCard, AIOperationType.PLAY, (AISelectedTargetInfoSet)null);
|
||||
aIVirtualTargetSelectAction.forceLethalMode = true;
|
||||
List<AITokenInformation> allySideTokenIdsOfPlaySituation = AIPlayTokenSimulationUtility.GetAllySideTokenIdsOfPlaySituation(field, playPtn, aIVirtualTargetSelectAction);
|
||||
if (allySideTokenIdsOfPlaySituation == null || allySideTokenIdsOfPlaySituation.Count <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int k = 0; k < allySideTokenIdsOfPlaySituation.Count; k++)
|
||||
{
|
||||
if (IsPlayoutAttacker(field.AI.tokenManager.GetTokenFromId(allySideTokenIdsOfPlaySituation[k].TokenId, isAlly: true, field), field, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
if (num >= 6)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static bool IsPlayoutAttacker(AIVirtualCard card, AIVirtualField field, List<AIScriptTokenBase> filters, List<int> playPtn, AIVirtualCard tagOwner, AISituationInfo situation)
|
||||
{
|
||||
if (!card.IsAlly || !card.IsOnField)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!card.IsUnit || card.IsDead || !AIAttackSimulationUtility.IsAttackPossible(field, card.AttackLeaderSituation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!AIFilteringUtility.CheckMatchTargetFiltering(card, field.AllyInplayCards, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
36
SVSim.BattleEngine/Engine/Wizard/AIRallySimulationUtility.cs
Normal file
36
SVSim.BattleEngine/Engine/Wizard/AIRallySimulationUtility.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIRallySimulationUtility
|
||||
{
|
||||
public static void ExecuteAppendRallyCount(AIVirtualField field, AIVirtualCard summonCard)
|
||||
{
|
||||
if (summonCard != null && CanAppendRallyCount(field, summonCard))
|
||||
{
|
||||
field.AddRallyCount(1, summonCard.IsAlly);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanAppendRallyCount(AIVirtualField field, AIVirtualCard summonCard)
|
||||
{
|
||||
if (summonCard.IsUnit)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<AIVirtualCard> tagHolders = field.CardListSet.GetTagHolders(CardListsForReference.TagHolderReferenceType.RallyCountPlus);
|
||||
if (tagHolders == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < tagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = tagHolders[i];
|
||||
if (aIVirtualCard.TagCollectionContainer.RallyCountPlusTags.CanAppendRallyCount(aIVirtualCard, summonCard))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
733
SVSim.BattleEngine/Engine/Wizard/AIRandomMultiDamageEvaluator.cs
Normal file
733
SVSim.BattleEngine/Engine/Wizard/AIRandomMultiDamageEvaluator.cs
Normal file
@@ -0,0 +1,733 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIRandomMultiDamageEvaluator
|
||||
{
|
||||
private struct DamageSituationInfo
|
||||
{
|
||||
public AIVirtualCard TagOwner;
|
||||
|
||||
public AIVirtualField Field;
|
||||
|
||||
public List<int> PlayPtn;
|
||||
|
||||
public bool IsAlly;
|
||||
|
||||
public bool IsSpell;
|
||||
|
||||
public int DamageAmount;
|
||||
|
||||
public int DamageCount;
|
||||
|
||||
public List<AIBarrierPseudoSimulationInfo> BarrierSimList;
|
||||
}
|
||||
|
||||
private class RandomDamageSimulationResult
|
||||
{
|
||||
public float BreakValue;
|
||||
|
||||
public List<int> RestLifeList;
|
||||
|
||||
public List<AIBarrierPseudoSimulationInfo> BarrierSimulationList;
|
||||
}
|
||||
|
||||
private class CardValueInformationForEvalRandomMultiDamage
|
||||
{
|
||||
public float BreakValue;
|
||||
|
||||
public float BattleBonusRate;
|
||||
}
|
||||
|
||||
public static void CreateEvalRandomDamageArgList(List<AIScriptTokenBase> src, out List<AIScriptTokenBase> filters, out int damage, out int count)
|
||||
{
|
||||
filters = src.GetRange(0, src.Count - 2);
|
||||
damage = (int)src[src.Count - 2].Value;
|
||||
count = (int)src[src.Count - 1].Value;
|
||||
}
|
||||
|
||||
private static float CalcSingleTargetEvaluation(AIVirtualCard target, AIVirtualField field, List<int> playPtn, AISituationInfo situation, bool ownerIsAlly, int damageAmount, bool isSpellDamage)
|
||||
{
|
||||
float num = 0f;
|
||||
int num2 = target.SimulateDamageAmount(damageAmount, isSkillDamage: true, isSpellDamage);
|
||||
int num3 = target.Life - num2;
|
||||
if (target.IsLeader)
|
||||
{
|
||||
return AILeaderLifeEvaluationUtility.Evaluate(num3, target.Life, target.IsAlly, ownerIsAlly);
|
||||
}
|
||||
if (num3 > 0)
|
||||
{
|
||||
float num4 = field.StyleQuery.GetUnitRate(field, target, playPtn) * target.EvaluateAllBattleBonusRate(playPtn, useOthersTag: true, useIgnoreInBattle: false, situation);
|
||||
num = (float)num2 * num4;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false, situation);
|
||||
}
|
||||
return num * (target.IsAlly ? (-1f) : 1f);
|
||||
}
|
||||
|
||||
public static float EvaluateRandomDamageAverage(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters, int damageAmount, int damageCount)
|
||||
{
|
||||
if (damageCount < 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("EvaluateRandomMultiDamageAverage() error!! damageCount < 0");
|
||||
return 0f;
|
||||
}
|
||||
if (damageCount == 1)
|
||||
{
|
||||
return EvaluateSingleTargetAverage(tagOwner, field, playPtn, situation, filters, damageAmount);
|
||||
}
|
||||
return EvaluateMultiTargetsAverage(tagOwner, playPtn, field, filters, situation, damageAmount, damageCount);
|
||||
}
|
||||
|
||||
private static float EvaluateSingleTargetAverage(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters, int damageAmount)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => !c.IsUnit && !c.IsLeader);
|
||||
if (list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
bool isSpellDamage = tagOwner.IsSpell || tagOwner.IsAccelerated(field, playPtn, situation);
|
||||
float num = 0f;
|
||||
for (int num2 = 0; num2 < list.Count; num2++)
|
||||
{
|
||||
float num3 = CalcSingleTargetEvaluation(list[num2], field, playPtn, situation, tagOwner.IsAlly, damageAmount, isSpellDamage);
|
||||
num += num3;
|
||||
}
|
||||
return num / (float)list.Count;
|
||||
}
|
||||
|
||||
private static float EvaluateMultiTargetsAverage(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, List<AIScriptTokenBase> filters, AISituationInfo situation, int damageAmount, int damageCount)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
if (!list.IsNotNullOrEmpty())
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int count = list.Count;
|
||||
SeparateTargetCardBySide(list, out var allyInplays, out var enemyInplays, out var allyLeader, out var enemyLeader);
|
||||
int num = damageCount / count;
|
||||
int num2 = ((allyLeader != null) ? num : 0);
|
||||
int num3 = ((enemyLeader != null) ? num : 0);
|
||||
int num4 = ((allyInplays != null && allyInplays.Count > 0) ? ((damageCount - num2 - num3) / 2) : 0);
|
||||
int num5 = ((enemyInplays != null && enemyInplays.Count > 0) ? ((damageCount - num2 - num3) / 2) : 0);
|
||||
int num6 = damageCount - (num2 + num4 + num3 + num5);
|
||||
if (num6 > 0)
|
||||
{
|
||||
if (enemyLeader != null)
|
||||
{
|
||||
num3 += num6;
|
||||
}
|
||||
else if (enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num5 += num6;
|
||||
}
|
||||
else if (allyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num4 += num6;
|
||||
}
|
||||
else if (allyLeader != null)
|
||||
{
|
||||
num2 += num6;
|
||||
}
|
||||
}
|
||||
num6 = 0;
|
||||
DamageSituationInfo damageSituation = new DamageSituationInfo
|
||||
{
|
||||
DamageAmount = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damageAmount),
|
||||
TagOwner = tagOwner,
|
||||
Field = field,
|
||||
PlayPtn = playPtn,
|
||||
IsSpell = (tagOwner.IsSpell || tagOwner.IsAccelerated(field, playPtn))
|
||||
};
|
||||
Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList = CreateCardValueInformationDictionary(allyInplays, field, playPtn, situation);
|
||||
Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList2 = CreateCardValueInformationDictionary(enemyInplays, field, playPtn, situation);
|
||||
List<AIBarrierPseudoSimulationInfo> barrierSimList = new List<AIBarrierPseudoSimulationInfo>(field.CardListSet.BothClassAndInplayCards.Select((AIVirtualCard c) => new AIBarrierPseudoSimulationInfo(c)));
|
||||
List<AIBarrierPseudoSimulationInfo> barrierSimList2 = new List<AIBarrierPseudoSimulationInfo>(field.CardListSet.BothClassAndInplayCards.Select((AIVirtualCard c) => new AIBarrierPseudoSimulationInfo(c)));
|
||||
damageSituation.IsAlly = false;
|
||||
float num7 = 0f;
|
||||
RandomDamageSimulationResult randomDamageSimulationResult = new RandomDamageSimulationResult();
|
||||
RandomDamageSimulationResult randomDamageSimulationResult2 = new RandomDamageSimulationResult();
|
||||
if (enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
damageSituation.DamageCount = num5;
|
||||
damageSituation.BarrierSimList = barrierSimList2;
|
||||
List<int> targetLifeList = GetTargetLifeList(enemyInplays);
|
||||
randomDamageSimulationResult = EvalWorstInplayRandomDamage(enemyInplays, targetLifeList, cardValueList2, damageSituation, situation, ref num6);
|
||||
if (randomDamageSimulationResult.RestLifeList.Sum() == 0)
|
||||
{
|
||||
randomDamageSimulationResult2.BreakValue = randomDamageSimulationResult.BreakValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
randomDamageSimulationResult2 = EvalBestInplayRandomDamage(enemyInplays, targetLifeList, cardValueList2, damageSituation, situation, ref num6);
|
||||
}
|
||||
}
|
||||
float num8 = 0f;
|
||||
int restLife = enemyLeader?.Life ?? 0;
|
||||
if (enemyLeader != null)
|
||||
{
|
||||
damageSituation.DamageCount = num3 + num6;
|
||||
damageSituation.BarrierSimList = barrierSimList;
|
||||
num8 = EvalRandomMultiDamageToLeader(enemyLeader, damageSituation, tagOwner.IsAlly, ref restLife, out num6);
|
||||
}
|
||||
damageSituation.IsAlly = true;
|
||||
float num9 = 0f;
|
||||
if (allyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
damageSituation.DamageCount = num4 + num6;
|
||||
damageSituation.BarrierSimList = barrierSimList2;
|
||||
List<int> targetLifeList2 = GetTargetLifeList(allyInplays);
|
||||
RandomDamageSimulationResult randomDamageSimulationResult3 = EvalWorstInplayRandomDamage(allyInplays, targetLifeList2, cardValueList, damageSituation, situation, ref num6);
|
||||
float breakValue = randomDamageSimulationResult3.BreakValue;
|
||||
num9 = ((randomDamageSimulationResult3.RestLifeList.Sum() != 0) ? ((EvalBestInplayRandomDamage(allyInplays, targetLifeList2, cardValueList, damageSituation, situation, ref num6).BreakValue + breakValue) / 2f) : breakValue);
|
||||
}
|
||||
float num10 = 0f;
|
||||
if (allyLeader != null)
|
||||
{
|
||||
int restLife2 = allyLeader.Life;
|
||||
damageSituation.DamageCount = num2 + num6;
|
||||
damageSituation.BarrierSimList = barrierSimList;
|
||||
num10 = EvalRandomMultiDamageToLeader(allyLeader, damageSituation, tagOwner.IsAlly, ref restLife2, out num6);
|
||||
}
|
||||
if (num6 > 0)
|
||||
{
|
||||
damageSituation.IsAlly = false;
|
||||
if (enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
damageSituation.DamageCount = num6;
|
||||
damageSituation.BarrierSimList = randomDamageSimulationResult.BarrierSimulationList;
|
||||
RandomDamageSimulationResult randomDamageSimulationResult4 = EvalWorstInplayRandomDamage(enemyInplays, randomDamageSimulationResult.RestLifeList, cardValueList2, damageSituation, situation, ref num6);
|
||||
randomDamageSimulationResult.BreakValue += randomDamageSimulationResult4.BreakValue;
|
||||
if (randomDamageSimulationResult4.RestLifeList.Sum() == 0)
|
||||
{
|
||||
randomDamageSimulationResult2.BreakValue = randomDamageSimulationResult.BreakValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
damageSituation.BarrierSimList = randomDamageSimulationResult2.BarrierSimulationList;
|
||||
randomDamageSimulationResult2.BreakValue += EvalBestInplayRandomDamage(enemyInplays, randomDamageSimulationResult2.RestLifeList, cardValueList2, damageSituation, situation, ref num6).BreakValue;
|
||||
}
|
||||
}
|
||||
if (num6 > 0 && enemyLeader != null && restLife > 0)
|
||||
{
|
||||
damageSituation.DamageCount = num6;
|
||||
damageSituation.BarrierSimList = barrierSimList;
|
||||
num8 += EvalRandomMultiDamageToLeader(enemyLeader, damageSituation, tagOwner.IsAlly, ref restLife, out num6);
|
||||
}
|
||||
}
|
||||
num7 = (randomDamageSimulationResult2.BreakValue + randomDamageSimulationResult.BreakValue) / 2f;
|
||||
return num8 + num7 + num10 + num9;
|
||||
}
|
||||
|
||||
public static float EvaluateRandomDamageMax(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, List<AIScriptTokenBase> filters, AISituationInfo situation, int damageAmount, int damageCount)
|
||||
{
|
||||
if (damageCount < 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("EvaluateRandomMultiDamageAverage() error!! damageCount < 0");
|
||||
return 0f;
|
||||
}
|
||||
if (damageCount == 1)
|
||||
{
|
||||
return EvaluateSingleTargetMax(tagOwner, field, playPtn, situation, filters, damageAmount);
|
||||
}
|
||||
return EvaluateMultiTargetsMax(tagOwner, playPtn, field, filters, situation, damageAmount, damageCount);
|
||||
}
|
||||
|
||||
private static float EvaluateSingleTargetMax(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters, int damageAmount)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => !c.IsUnit && !c.IsLeader);
|
||||
if (list.Count <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
bool flag = false;
|
||||
bool isSpellDamage = tagOwner.IsSpell || tagOwner.IsAccelerated(field, playPtn, situation);
|
||||
float num = float.MinValue;
|
||||
for (int num2 = 0; num2 < list.Count; num2++)
|
||||
{
|
||||
float num3 = CalcSingleTargetEvaluation(list[num2], field, playPtn, situation, tagOwner.IsAlly, damageAmount, isSpellDamage);
|
||||
if (num3 > num)
|
||||
{
|
||||
num = num3;
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
num = 0f;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static float EvaluateMultiTargetsMax(AIVirtualCard tagOwner, List<int> playPtn, AIVirtualField field, List<AIScriptTokenBase> filters, AISituationInfo situation, int damageAmount, int damageCount)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, null);
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsAmulet);
|
||||
if (!list.IsNotNullOrEmpty())
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
_ = list.Count;
|
||||
SeparateTargetCardBySide(list, out var allyInplays, out var enemyInplays, out var allyLeader, out var enemyLeader);
|
||||
DamageSituationInfo damageSituation = new DamageSituationInfo
|
||||
{
|
||||
DamageAmount = field.DamageModifierCollection.CalcModifiedDamage(field, playPtn, situation, tagOwner, damageAmount),
|
||||
TagOwner = tagOwner,
|
||||
Field = field,
|
||||
PlayPtn = playPtn,
|
||||
IsSpell = (tagOwner.IsSpell || tagOwner.IsAccelerated(field, playPtn))
|
||||
};
|
||||
Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList = CreateCardValueInformationDictionary(allyInplays, field, playPtn, situation);
|
||||
Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList2 = CreateCardValueInformationDictionary(enemyInplays, field, playPtn, situation);
|
||||
List<AIBarrierPseudoSimulationInfo> barrierSimList = new List<AIBarrierPseudoSimulationInfo>(field.CardListSet.BothClassAndInplayCards.Select((AIVirtualCard c) => new AIBarrierPseudoSimulationInfo(c)));
|
||||
List<AIBarrierPseudoSimulationInfo> barrierSimList2 = new List<AIBarrierPseudoSimulationInfo>(field.CardListSet.BothClassAndInplayCards.Select((AIVirtualCard c) => new AIBarrierPseudoSimulationInfo(c)));
|
||||
damageSituation.IsAlly = false;
|
||||
float num = 0f;
|
||||
int restDamageCount = damageCount;
|
||||
if (enemyLeader != null)
|
||||
{
|
||||
int restLife = enemyLeader.Life;
|
||||
damageSituation.DamageCount = restDamageCount;
|
||||
damageSituation.BarrierSimList = barrierSimList;
|
||||
num = EvalRandomMultiDamageToLeader(enemyLeader, damageSituation, tagOwner.IsAlly, ref restLife, out restDamageCount);
|
||||
if (restLife <= 0)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
}
|
||||
float num2 = 0f;
|
||||
int restDamageCount2 = damageCount;
|
||||
if (enemyInplays != null && enemyInplays.Count > 0)
|
||||
{
|
||||
damageSituation.DamageCount = restDamageCount2;
|
||||
damageSituation.BarrierSimList = barrierSimList2;
|
||||
List<int> targetLifeList = GetTargetLifeList(enemyInplays);
|
||||
RandomDamageSimulationResult randomDamageSimulationResult = EvalBestInplayRandomDamage(enemyInplays, targetLifeList, cardValueList2, damageSituation, situation, ref restDamageCount2);
|
||||
num2 = randomDamageSimulationResult.BreakValue;
|
||||
if (restDamageCount2 > 0 && enemyLeader != null)
|
||||
{
|
||||
int restLife2 = enemyLeader.Life;
|
||||
damageSituation.DamageCount = restDamageCount2;
|
||||
damageSituation.BarrierSimList = randomDamageSimulationResult.BarrierSimulationList;
|
||||
num2 += EvalRandomMultiDamageToLeader(enemyLeader, damageSituation, tagOwner.IsAlly, ref restLife2, out restDamageCount);
|
||||
if (restLife2 <= 0)
|
||||
{
|
||||
return num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
float num3 = 0f;
|
||||
if (enemyLeader != null && enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num3 = Mathf.Max(num2, num);
|
||||
}
|
||||
else if (enemyLeader != null && !enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num3 = num;
|
||||
}
|
||||
else if (enemyLeader == null && enemyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num3 = num2;
|
||||
}
|
||||
if (restDamageCount2 <= 0)
|
||||
{
|
||||
return num3;
|
||||
}
|
||||
damageSituation.IsAlly = true;
|
||||
int restDamageCount3 = restDamageCount2;
|
||||
float num4 = 0f;
|
||||
if (allyLeader != null)
|
||||
{
|
||||
int restLife3 = allyLeader.Life;
|
||||
damageSituation.DamageCount = restDamageCount3;
|
||||
damageSituation.BarrierSimList = barrierSimList;
|
||||
num4 = EvalRandomMultiDamageToLeader(allyLeader, damageSituation, tagOwner.IsAlly, ref restLife3, out restDamageCount3);
|
||||
}
|
||||
float num5 = 0f;
|
||||
int restDamageCount4 = restDamageCount2;
|
||||
if (allyInplays != null && allyInplays.Count > 0)
|
||||
{
|
||||
damageSituation.DamageCount = restDamageCount4;
|
||||
damageSituation.BarrierSimList = barrierSimList2;
|
||||
List<int> targetLifeList2 = GetTargetLifeList(allyInplays);
|
||||
RandomDamageSimulationResult randomDamageSimulationResult2 = EvalWorstInplayRandomDamage(allyInplays, targetLifeList2, cardValueList, damageSituation, situation, ref restDamageCount4);
|
||||
num5 = randomDamageSimulationResult2.BreakValue;
|
||||
if (restDamageCount4 > 0 && allyLeader != null)
|
||||
{
|
||||
int restLife4 = allyLeader.Life;
|
||||
damageSituation.DamageCount = restDamageCount4;
|
||||
damageSituation.BarrierSimList = randomDamageSimulationResult2.BarrierSimulationList;
|
||||
num4 += EvalRandomMultiDamageToLeader(allyLeader, damageSituation, tagOwner.IsAlly, ref restLife4, out restDamageCount4);
|
||||
}
|
||||
}
|
||||
float num6 = 0f;
|
||||
if (allyLeader != null && allyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num6 = Mathf.Max(num5, num4);
|
||||
}
|
||||
else if (allyLeader != null && !allyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num6 = num4;
|
||||
}
|
||||
else if (allyLeader == null && allyInplays.IsNotNullOrEmpty())
|
||||
{
|
||||
num6 = num5;
|
||||
}
|
||||
return num3 + num6;
|
||||
}
|
||||
|
||||
private static RandomDamageSimulationResult EvalWorstInplayRandomDamage(List<AIVirtualCard> targetCards, List<int> targetLifeList, Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList, DamageSituationInfo damageSituation, AISituationInfo situation, ref int restDamageCount)
|
||||
{
|
||||
restDamageCount = damageSituation.DamageCount;
|
||||
RandomDamageSimulationResult simResult = new RandomDamageSimulationResult
|
||||
{
|
||||
BreakValue = 0f,
|
||||
RestLifeList = new List<int>(targetLifeList),
|
||||
BarrierSimulationList = new List<AIBarrierPseudoSimulationInfo>(damageSituation.BarrierSimList.Select((AIBarrierPseudoSimulationInfo info) => new AIBarrierPseudoSimulationInfo(info)))
|
||||
};
|
||||
List<AIVirtualCard> list = targetCards.OrderBy((AIVirtualCard c) => cardValueList[c].BreakValue).ToList();
|
||||
List<int> list2 = list.Select((AIVirtualCard sortedCard) => targetCards.FindIndex((AIVirtualCard originalCard) => originalCard.IsSameCard(sortedCard))).ToList();
|
||||
List<int> list3 = list2.Select((int index2) => targetLifeList[index2]).ToList();
|
||||
List<int> list4 = new List<int>(list.Select((AIVirtualCard c) => 0));
|
||||
List<AIBarrierPseudoSimulationInfo> list5 = list.Select((AIVirtualCard c) => simResult.BarrierSimulationList.Find((AIBarrierPseudoSimulationInfo info) => info.Owner.IsSameCard(c))).ToList();
|
||||
bool isSpell = damageSituation.IsSpell;
|
||||
for (int num = 0; num < damageSituation.DamageCount; num++)
|
||||
{
|
||||
int num2 = int.MaxValue;
|
||||
int num3 = -1;
|
||||
int num4 = 0;
|
||||
if (list3.Count((int life) => life > 0) == 0)
|
||||
{
|
||||
simResult.BreakValue *= (damageSituation.IsAlly ? (-1f) : 1f);
|
||||
return simResult;
|
||||
}
|
||||
int num5 = -1;
|
||||
for (int num6 = 0; num6 < list.Count; num6++)
|
||||
{
|
||||
if (list3[num6] > 0)
|
||||
{
|
||||
if (num5 < 0)
|
||||
{
|
||||
num5 = num6;
|
||||
}
|
||||
int damage = list[num6].SimulateDamageShield(damageSituation.DamageAmount, isSkillDamage: true, isSpell);
|
||||
damage = list5[num6].SimulateDamageAmount(damage, isSpell);
|
||||
if (damage > 0 && list3[num6] <= damage)
|
||||
{
|
||||
num4++;
|
||||
}
|
||||
else if (damage < num2)
|
||||
{
|
||||
num2 = damage;
|
||||
num3 = num6;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num4 == list3.Count((int life) => life > 0))
|
||||
{
|
||||
num3 = num5;
|
||||
num2 = list[num3].SimulateDamageShield(damageSituation.DamageAmount, isSkillDamage: true, isSpell);
|
||||
num2 = list5[num3].SimulateDamageAmount(num2, isSpell);
|
||||
}
|
||||
if (0 <= num3)
|
||||
{
|
||||
int index = list2[num3];
|
||||
AIVirtualCard key = list[num3];
|
||||
list3[num3] = Mathf.Max(0, list3[num3] - num2);
|
||||
simResult.RestLifeList[index] = list3[num3];
|
||||
list4[num3]++;
|
||||
AIBarrierPseudoSimulationInfo targetBarrierInfo = list5[num3];
|
||||
bool flag = list3[num3] <= 0;
|
||||
PseudoRemoveBarrierWhenTargetGetDamaged(targetBarrierInfo, simResult.BarrierSimulationList, flag);
|
||||
if (flag)
|
||||
{
|
||||
simResult.BreakValue += cardValueList[key].BreakValue;
|
||||
}
|
||||
}
|
||||
restDamageCount--;
|
||||
}
|
||||
for (int num7 = 0; num7 < targetCards.Count; num7++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targetCards[num7];
|
||||
int num8 = list4[num7];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTag(AIPlayTagType.DamagedBuff) && num8 > 0 && simResult.RestLifeList[num7] > 0)
|
||||
{
|
||||
DamagedTagCollection damagedTags = aIVirtualCard.TagCollectionContainer.DamagedTags;
|
||||
for (int num9 = 0; num9 < num8; num9++)
|
||||
{
|
||||
int atkBuff = 0;
|
||||
int lifeBuff = 0;
|
||||
damagedTags.GetDamagedBuffValue(aIVirtualCard, aIVirtualCard.SelfField, damageSituation.PlayPtn, situation, out atkBuff, out lifeBuff);
|
||||
simResult.RestLifeList[num7] += lifeBuff;
|
||||
if (simResult.RestLifeList[num7] <= 0)
|
||||
{
|
||||
simResult.BreakValue += cardValueList[aIVirtualCard].BreakValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (simResult.RestLifeList[num7] > 0)
|
||||
{
|
||||
simResult.BreakValue += aIVirtualCard.Life - simResult.RestLifeList[num7];
|
||||
}
|
||||
}
|
||||
simResult.BreakValue *= (damageSituation.IsAlly ? (-1f) : 1f);
|
||||
return simResult;
|
||||
}
|
||||
|
||||
private static RandomDamageSimulationResult EvalBestInplayRandomDamage(List<AIVirtualCard> targetCards, List<int> targetLifeList, Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList, DamageSituationInfo damageSituation, AISituationInfo situation, ref int restDamageCount)
|
||||
{
|
||||
RandomDamageSimulationResult randomDamageSimulationResult = new RandomDamageSimulationResult();
|
||||
randomDamageSimulationResult.BreakValue = float.MinValue;
|
||||
int num = (int)Mathf.Pow(2f, targetCards.Count);
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
List<int> list = new List<int>();
|
||||
List<int> list2 = new List<int>();
|
||||
int num2 = i;
|
||||
for (int j = 0; j < targetCards.Count; j++)
|
||||
{
|
||||
int num3 = (int)Mathf.Pow(2f, targetCards.Count - j - 1);
|
||||
if (num2 / num3 <= 0)
|
||||
{
|
||||
list.Add(j);
|
||||
continue;
|
||||
}
|
||||
list2.Add(j);
|
||||
num2 -= num3;
|
||||
}
|
||||
float num4 = 0f;
|
||||
int damageCount = damageSituation.DamageCount;
|
||||
List<AIBarrierPseudoSimulationInfo> list3 = new List<AIBarrierPseudoSimulationInfo>(damageSituation.BarrierSimList.Select((AIBarrierPseudoSimulationInfo info) => new AIBarrierPseudoSimulationInfo(info)));
|
||||
List<int> list4 = new List<int>(targetLifeList);
|
||||
if (0 < list2.Count)
|
||||
{
|
||||
num4 += EvalRandomMultiDamageBreakValue(damageSituation.DamageAmount, ref damageCount, list2, damageSituation.IsSpell, targetCards, damageSituation.PlayPtn, situation, list4, cardValueList, list3);
|
||||
}
|
||||
if (0 < damageCount && 0 < list.Count)
|
||||
{
|
||||
num4 += EvalRandomMultiDamageBreakValue(damageSituation.DamageAmount, ref damageCount, list, damageSituation.IsSpell, targetCards, damageSituation.PlayPtn, situation, list4, cardValueList, list3);
|
||||
}
|
||||
num4 *= (damageSituation.IsAlly ? (-1f) : 1f);
|
||||
if (randomDamageSimulationResult.BreakValue < num4)
|
||||
{
|
||||
randomDamageSimulationResult.BreakValue = num4;
|
||||
randomDamageSimulationResult.BarrierSimulationList = list3;
|
||||
randomDamageSimulationResult.RestLifeList = list4;
|
||||
restDamageCount = damageCount;
|
||||
}
|
||||
}
|
||||
if (randomDamageSimulationResult.RestLifeList == null)
|
||||
{
|
||||
randomDamageSimulationResult.RestLifeList = new List<int>(targetLifeList);
|
||||
}
|
||||
if (randomDamageSimulationResult.BarrierSimulationList == null)
|
||||
{
|
||||
randomDamageSimulationResult.BarrierSimulationList = new List<AIBarrierPseudoSimulationInfo>(damageSituation.BarrierSimList.Select((AIBarrierPseudoSimulationInfo info) => new AIBarrierPseudoSimulationInfo(info)));
|
||||
}
|
||||
return randomDamageSimulationResult;
|
||||
}
|
||||
|
||||
private static float EvalRandomMultiDamageBreakValue(int damageAmount, ref int damageCount, List<int> targetIdxList, bool isSpell, List<AIVirtualCard> candidates, List<int> playPtn, AISituationInfo situation, List<int> lifeList, Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> cardValueList, List<AIBarrierPseudoSimulationInfo> removeBarrierSimList)
|
||||
{
|
||||
if (lifeList.Sum() == 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
float num = 0f;
|
||||
int num2 = damageCount;
|
||||
float num3 = 0f;
|
||||
if (targetIdxList.Count > 0)
|
||||
{
|
||||
int num4 = -1;
|
||||
for (int i = 0; i < targetIdxList.Count; i++)
|
||||
{
|
||||
if (lifeList[targetIdxList[i]] > 0)
|
||||
{
|
||||
num4 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num4 < 0 || num4 >= targetIdxList.Count)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
int index = targetIdxList[num4];
|
||||
int num5 = 0;
|
||||
int num6 = lifeList[index];
|
||||
AIVirtualCard target = candidates[index];
|
||||
AIBarrierPseudoSimulationInfo aIBarrierPseudoSimulationInfo = removeBarrierSimList.Find((AIBarrierPseudoSimulationInfo info) => info.Owner.IsSameCard(target));
|
||||
float battleBonusRate = cardValueList[target].BattleBonusRate;
|
||||
while (true)
|
||||
{
|
||||
if (num2 <= 0)
|
||||
{
|
||||
damageCount = num2;
|
||||
return num + num3;
|
||||
}
|
||||
int num7 = target.SimulateDamageShield(damageAmount, isSkillDamage: true, isSpell);
|
||||
if (num7 > 0)
|
||||
{
|
||||
num7 = aIBarrierPseudoSimulationInfo.SimulateDamageAmount(damageAmount, isSpell);
|
||||
}
|
||||
num5++;
|
||||
num3 += (float)num7 * battleBonusRate;
|
||||
lifeList[index] -= num7;
|
||||
aIBarrierPseudoSimulationInfo.DepriveBarrier(AIBarrierStopTiming.AfterDamage);
|
||||
num2--;
|
||||
if (target.TagCollectionContainer.HasTag(AIPlayTagType.DamagedBuff) && num5 >= num6)
|
||||
{
|
||||
DamagedTagCollection damagedTags = target.TagCollectionContainer.DamagedTags;
|
||||
for (int num8 = 0; num8 < num5; num8++)
|
||||
{
|
||||
int atkBuff = 0;
|
||||
int lifeBuff = 0;
|
||||
damagedTags.GetDamagedBuffValue(target, target.SelfField, playPtn, situation, out atkBuff, out lifeBuff);
|
||||
lifeList[index] += lifeBuff;
|
||||
if (lifeList[index] <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lifeList[index] <= 0)
|
||||
{
|
||||
lifeList[index] = 0;
|
||||
num3 = 0f;
|
||||
num5 = 0;
|
||||
num += cardValueList[target].BreakValue;
|
||||
num4 = targetIdxList.FindIndex((int idx) => lifeList[idx] > 0);
|
||||
if (num4 < 0 || num4 >= targetIdxList.Count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
index = targetIdxList[num4];
|
||||
num6 = lifeList[index];
|
||||
target = candidates[index];
|
||||
battleBonusRate = cardValueList[target].BattleBonusRate;
|
||||
aIBarrierPseudoSimulationInfo = removeBarrierSimList.Find((AIBarrierPseudoSimulationInfo info) => info.Owner.IsSameCard(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
damageCount = num2;
|
||||
return num + num3;
|
||||
}
|
||||
|
||||
private static float EvalRandomMultiDamageToLeader(AIVirtualCard leader, DamageSituationInfo damageSituation, bool isAllyOwner, ref int restLife, out int restDamageCount)
|
||||
{
|
||||
restDamageCount = damageSituation.DamageCount;
|
||||
int defaultLife = restLife;
|
||||
AIBarrierPseudoSimulationInfo aIBarrierPseudoSimulationInfo = damageSituation.BarrierSimList.Find((AIBarrierPseudoSimulationInfo c) => c.Owner.IsSameCard(leader));
|
||||
bool isSpell = damageSituation.IsSpell;
|
||||
for (int num = 0; num < damageSituation.DamageCount; num++)
|
||||
{
|
||||
if (restLife <= 0)
|
||||
{
|
||||
restLife = 0;
|
||||
break;
|
||||
}
|
||||
int num2 = aIBarrierPseudoSimulationInfo.SimulateDamageAmount(leader.SimulateDamageShield(damageSituation.DamageAmount, isSkillDamage: true, isSpell), isSpell);
|
||||
restLife -= num2;
|
||||
aIBarrierPseudoSimulationInfo.DepriveBarrier(AIBarrierStopTiming.AfterDamage);
|
||||
restDamageCount--;
|
||||
}
|
||||
return AILeaderLifeEvaluationUtility.Evaluate(restLife, defaultLife, leader.IsAlly, isAllyOwner);
|
||||
}
|
||||
|
||||
private static void SeparateTargetCardBySide(List<AIVirtualCard> allTargets, out List<AIVirtualCard> allyInplays, out List<AIVirtualCard> enemyInplays, out AIVirtualCard allyLeader, out AIVirtualCard enemyLeader)
|
||||
{
|
||||
allyInplays = null;
|
||||
enemyInplays = null;
|
||||
allyLeader = null;
|
||||
enemyLeader = null;
|
||||
if (allTargets == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < allTargets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = allTargets[i];
|
||||
if (aIVirtualCard.IsAlly)
|
||||
{
|
||||
if (aIVirtualCard.IsLeader)
|
||||
{
|
||||
allyLeader = aIVirtualCard;
|
||||
}
|
||||
else
|
||||
{
|
||||
allyInplays = AIParamQuery.AddElementToList(aIVirtualCard, allyInplays);
|
||||
}
|
||||
}
|
||||
else if (aIVirtualCard.IsLeader)
|
||||
{
|
||||
enemyLeader = aIVirtualCard;
|
||||
}
|
||||
else
|
||||
{
|
||||
enemyInplays = AIParamQuery.AddElementToList(aIVirtualCard, enemyInplays);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<int> GetTargetLifeList(List<AIVirtualCard> targets)
|
||||
{
|
||||
if (targets == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<int> list = null;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(targets[i].Life, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> CreateCardValueInformationDictionary(List<AIVirtualCard> cardList, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (cardList == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage> dictionary = new Dictionary<AIVirtualCard, CardValueInformationForEvalRandomMultiDamage>();
|
||||
for (int i = 0; i < cardList.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = cardList[i];
|
||||
float breakValue = aIVirtualCard.EvaluateValueOnField(playPtn, situation, useStyle: true) - (aIVirtualCard.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) + aIVirtualCard.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false));
|
||||
float battleBonusRate = field.StyleQuery.GetUnitRate(field, aIVirtualCard, playPtn) * aIVirtualCard.EvaluateAllBattleBonusRate(playPtn, useOthersTag: true, useIgnoreInBattle: false, situation);
|
||||
CardValueInformationForEvalRandomMultiDamage value = new CardValueInformationForEvalRandomMultiDamage
|
||||
{
|
||||
BreakValue = breakValue,
|
||||
BattleBonusRate = battleBonusRate
|
||||
};
|
||||
dictionary.Add(aIVirtualCard, value);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private static void PseudoRemoveBarrierWhenTargetGetDamaged(AIBarrierPseudoSimulationInfo targetBarrierInfo, List<AIBarrierPseudoSimulationInfo> otherDamageCandidateBarrierInfoList, bool isTargetLeaveFromField)
|
||||
{
|
||||
targetBarrierInfo.DepriveBarrier(AIBarrierStopTiming.AfterDamage);
|
||||
if (isTargetLeaveFromField)
|
||||
{
|
||||
AIVirtualCard owner = targetBarrierInfo.Owner;
|
||||
owner.SelfField.TagPreprocessContainer.LeaveStopInfoContainer?.PseudoSimulateForEvalRandomMultiDamage(otherDamageCandidateBarrierInfoList, owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
118
SVSim.BattleEngine/Engine/Wizard/AIReanimateSimulationUtility.cs
Normal file
118
SVSim.BattleEngine/Engine/Wizard/AIReanimateSimulationUtility.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cute;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIReanimateSimulationUtility
|
||||
{
|
||||
public const int NONE_REANIMATE_COST = -1;
|
||||
|
||||
public const int NONE_REANIMATE_ID = -1;
|
||||
|
||||
public static bool IsReanimate(AIVirtualCard tagOwner, int cost)
|
||||
{
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
return (tagOwner.IsAlly ? selfField.CardListSet.AllyDestroyedCards : selfField.CardListSet.EnemyDestroyedCards).Any((AIVirtualCard c) => c.IsUnit && c.Cost <= cost);
|
||||
}
|
||||
|
||||
public static int GetReanimateTokenId(AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> filters, AIPolishConvertedExpression costExpression, AIScriptTokenArgType side, out bool isTokenAlly)
|
||||
{
|
||||
int num = (int)costExpression.EvalArg(tagOwner, playPtn, field, situation);
|
||||
if (num < 0)
|
||||
{
|
||||
isTokenAlly = true;
|
||||
return -1;
|
||||
}
|
||||
isTokenAlly = AISummonTokenUtility.GetIsTokenAlly(tagOwner, side);
|
||||
return EvalReanimateTokenID(tagOwner, num, filters, isTokenAlly, playPtn, situation);
|
||||
}
|
||||
|
||||
private static int EvalReanimateTokenID(AIVirtualCard tagOwner, int reanimateCost, List<AIScriptTokenBase> filters, bool isTokenAlly, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (reanimateCost == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int result = -1;
|
||||
AIVirtualField selfField = tagOwner.SelfField;
|
||||
List<AIVirtualCard> list = (isTokenAlly ? selfField.CardListSet.AllyDestroyedCards : selfField.CardListSet.EnemyDestroyedCards);
|
||||
if (list.IsNotNullOrEmpty())
|
||||
{
|
||||
list = FilteringReanimateTargets(list, reanimateCost, tagOwner, filters, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
int baseId = list[i].BaseId;
|
||||
if (dictionary.ContainsKey(baseId))
|
||||
{
|
||||
dictionary[baseId]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(baseId, 1);
|
||||
}
|
||||
}
|
||||
int maxDestroyedCount = dictionary.Max((KeyValuePair<int, int> pair) => pair.Value);
|
||||
if (dictionary.Count((KeyValuePair<int, int> pair) => pair.Value == maxDestroyedCount) == 1)
|
||||
{
|
||||
result = dictionary.First((KeyValuePair<int, int> pair) => pair.Value == maxDestroyedCount).Key;
|
||||
}
|
||||
else
|
||||
{
|
||||
float num = float.MaxValue;
|
||||
List<KeyValuePair<int, int>> maxDestroyedPair = dictionary.Where((KeyValuePair<int, int> pair) => pair.Value == maxDestroyedCount).ToList();
|
||||
int i2;
|
||||
for (i2 = 0; i2 < maxDestroyedPair.Count; i2++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list.First((AIVirtualCard c) => c.BaseId == maxDestroyedPair[i2].Key);
|
||||
float num2 = AIEvalReanimateUtility.EvalReanimateTargetValue(aIVirtualCard, selfField, playPtn, situation);
|
||||
num2 *= (isTokenAlly ? 1f : (-1f));
|
||||
if (num2 < num)
|
||||
{
|
||||
result = aIVirtualCard.BaseId;
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> FilteringReanimateTargets(List<AIVirtualCard> reanimateTargets, int reanimateCost, AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (reanimateTargets == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int maxReanimateCost = -1;
|
||||
List<AIVirtualCard> list = null;
|
||||
for (int i = 0; i < reanimateTargets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = reanimateTargets[i];
|
||||
int cost = aIVirtualCard.Cost;
|
||||
if (aIVirtualCard.IsUnit && cost <= reanimateCost && (filters == null || filters.Count < 0 || AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, reanimateTargets, filters, playPtn, tagOwner, situation)))
|
||||
{
|
||||
if (maxReanimateCost < cost)
|
||||
{
|
||||
maxReanimateCost = cost;
|
||||
}
|
||||
if (list == null)
|
||||
{
|
||||
list = new List<AIVirtualCard>();
|
||||
}
|
||||
list.Add(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c.Cost != maxReanimateCost);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIRecoverAttackableCountUtility
|
||||
{
|
||||
public static void RecoverAttackableCountTarget(AIScriptTokenArgType targetSelectType, AISituationInfo situation)
|
||||
{
|
||||
if (situation != null && situation.IsTargetExists(targetSelectType))
|
||||
{
|
||||
RecoverAttackableCountAll(situation.GetSituationTarget(targetSelectType).Targets);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecoverAttackableCountTargetPrediction(List<AIVirtualCard> candidatis, int selectCount)
|
||||
{
|
||||
if (selectCount > 1)
|
||||
{
|
||||
List<AIVirtualCard> list = SelectMultipleTarget(candidatis, selectCount, AISelectTargetPattern.Best);
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
RecoverAttackableCountAll(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectSingleTarget(candidatis, AISelectTargetPattern.Best)?.RecoverAttackableCount();
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecoverAttackableCountAll(List<AIVirtualCard> targets)
|
||||
{
|
||||
if (targets != null)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
targets[i].RecoverAttackableCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard result = null;
|
||||
int num = ((worstOrBest == AISelectTargetPattern.Best) ? int.MinValue : int.MaxValue);
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.IsUnit && aIVirtualCard.AttackableCount <= 0 && !aIVirtualCard.IsCantAttackAll)
|
||||
{
|
||||
int num2 = aIVirtualCard.Attack * aIVirtualCard.MaxAttackableCount;
|
||||
bool flag = false;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
flag = num2 > num;
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
flag = num2 < num;
|
||||
break;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
result = aIVirtualCard;
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<AIVirtualCard> SelectMultipleTarget(List<AIVirtualCard> candidates, int selectCount, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIVirtualCard> list = null;
|
||||
for (int i = 0; i < selectCount; i++)
|
||||
{
|
||||
if (list != null && list.Count == selectCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
int num = ((worstOrBest == AISelectTargetPattern.Best) ? int.MinValue : int.MaxValue);
|
||||
for (int j = 0; j < candidates.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[j];
|
||||
if (aIVirtualCard2.IsUnit && aIVirtualCard2.AttackableCount <= 0 && !aIVirtualCard2.IsCantAttackAll && (list == null || !list.Contains(aIVirtualCard2)))
|
||||
{
|
||||
int num2 = aIVirtualCard2.Attack * aIVirtualCard2.MaxAttackableCount;
|
||||
bool flag = false;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Best:
|
||||
flag = num2 > num;
|
||||
break;
|
||||
case AISelectTargetPattern.Worst:
|
||||
flag = num2 < num;
|
||||
break;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(aIVirtualCard, list);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIRemovalEvaluationOption
|
||||
{
|
||||
public AIVirtualCard TagOwner;
|
||||
|
||||
public int MetamorphoseTokenId;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIRemoveSkillSimulationUtility
|
||||
{
|
||||
public static void RemoveSkillAll(List<AIVirtualCard> candidates, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
candidates[i].RemoveAllSkills(situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSkillTargetSelect(AIScriptTokenArgType whichTarget, AISituationInfo situation)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
RemoveSkillAll(situationTarget.Targets, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSkillRandom(List<AIVirtualCard> candidates, AISituationInfo situation)
|
||||
{
|
||||
SelectRemoveSkillTarget(candidates, AISelectTargetPattern.Worst)?.RemoveAllSkills(situation);
|
||||
}
|
||||
|
||||
private static AIVirtualCard SelectRemoveSkillTarget(List<AIVirtualCard> candidates, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
if (candidates == null || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
float posiOrNega = ((worstOrBest == AISelectTargetPattern.Best) ? 1f : (-1f));
|
||||
float num = 0f;
|
||||
AIVirtualCard aIVirtualCard = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = candidates[i];
|
||||
if (aIVirtualCard == null)
|
||||
{
|
||||
num = CalcValue(aIVirtualCard2);
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
continue;
|
||||
}
|
||||
float num2 = CalcValue(aIVirtualCard2);
|
||||
if (num2 > num)
|
||||
{
|
||||
num = num2;
|
||||
aIVirtualCard = aIVirtualCard2;
|
||||
}
|
||||
}
|
||||
return aIVirtualCard;
|
||||
float CalcValue(AIVirtualCard card)
|
||||
{
|
||||
return (card.Value - (float)card.Attack - (float)card.Life) * posiOrNega;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIReverseDiscardSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public AIReverseDiscardSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIReverseEvaluateValueListOrder aIReverseEvaluateValueListOrder = new AIReverseEvaluateValueListOrder();
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
float value = aIVirtualCard.GetHandBonus(playPtn, situation, isIgnoreInFusion: false) + aIVirtualCard.GetDiscardedBonus(playPtn, situation, isIgnroeInBattle: true);
|
||||
aIReverseEvaluateValueListOrder.AddData(value, aIVirtualCard);
|
||||
}
|
||||
return aIReverseEvaluateValueListOrder.GetFirst();
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIConsoleUtility.Log("REVERSE_DISCARD_LOGIC は複数選択に未対応です");
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsWellTarget(float maxHandBonus, float currentHandBonus, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
return worstOrBest switch
|
||||
{
|
||||
AISelectTargetPattern.Best => maxHandBonus < currentHandBonus,
|
||||
AISelectTargetPattern.Worst => maxHandBonus > currentHandBonus,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIReverseEvaluateValueListOrder
|
||||
{
|
||||
private List<float> evalvalues = new List<float>();
|
||||
|
||||
private List<AIVirtualCard> cards = new List<AIVirtualCard>();
|
||||
|
||||
public void AddData(float value, AIVirtualCard card)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("CompValue:AddData() Target card is null");
|
||||
}
|
||||
else if (evalvalues.Any())
|
||||
{
|
||||
bool flag = false;
|
||||
for (int i = 0; i < evalvalues.Count; i++)
|
||||
{
|
||||
if (evalvalues[i] > value)
|
||||
{
|
||||
evalvalues.Insert(i, value);
|
||||
cards.Insert(i, card);
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
evalvalues.Add(value);
|
||||
cards.Add(card);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
evalvalues.Add(value);
|
||||
cards.Add(card);
|
||||
}
|
||||
}
|
||||
|
||||
public List<AIVirtualCard> GetCardList(int takeCount)
|
||||
{
|
||||
if (takeCount <= 0 || cards.Count < takeCount)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
for (int i = 0; i < takeCount; i++)
|
||||
{
|
||||
list.Add(cards[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public AIVirtualCard GetFirst()
|
||||
{
|
||||
if (cards == null || cards.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return cards[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISelectLogicSimulationUtility
|
||||
{
|
||||
public static AISelectLogicArgumentBase CreateSelectLogicArgument(string args)
|
||||
{
|
||||
List<string> list = AIPlayTagInitializingUtility.TrimAttachTagArgument(args).Replace(" ", "").Split(';')
|
||||
.ToList();
|
||||
AIScriptTokenArgType aIScriptTokenArgType = AIScriptTokenArgType.NONE;
|
||||
if (AIScriptParser.ConvertWordToToken(list[0]) is AIScriptArgumentToken aIScriptArgumentToken)
|
||||
{
|
||||
aIScriptTokenArgType = aIScriptArgumentToken.ArgumentType;
|
||||
}
|
||||
if (aIScriptTokenArgType <= AIScriptTokenArgType.SELECT_LOGIC_TYPE_BEGIN || aIScriptTokenArgType >= AIScriptTokenArgType.SELECT_LOGIC_TYPE_END)
|
||||
{
|
||||
AIConsoleUtility.LogError($"CreateSelectLogicArgument error!! logicType == {aIScriptTokenArgType}");
|
||||
return null;
|
||||
}
|
||||
list.RemoveAt(0);
|
||||
return aIScriptTokenArgType switch
|
||||
{
|
||||
AIScriptTokenArgType.DEFAULT_LOGIC => new AIDefaultSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.DESTROY_LOGIC => new AIDestroySelectLogicArgument(list),
|
||||
AIScriptTokenArgType.DAMAGE_LOGIC => new AIDamageSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.BOUNCE_LOGIC => new AIBounceSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.BANISH_LOGIC => new AIBanishSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.METAMORPHOSE_LOGIC => new AIMetamorphoseSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.MAX_ATTACK_LOGIC => new AIMaxAttackSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.TYRANT_ORDER_LOGIC => new AITyrantOrderSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.REVERSE_DISCARD_LOGIC => new AIReverseDiscardSelectLogicArgument(list),
|
||||
AIScriptTokenArgType.WHITEFROST_WHISPER_LOGIC => new AIWhitefrostWhisperLogicArgument(list),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISetStatusSimulationUtility
|
||||
{
|
||||
public static bool IsNoneSetValue(AIPolishConvertedExpression expression)
|
||||
{
|
||||
if (expression.TokenList[0] is AIScriptArgumentToken aIScriptArgumentToken)
|
||||
{
|
||||
return aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.NONE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetMaxStatusToAll(List<AIVirtualCard> targets, int attack, int life, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (attack >= 0)
|
||||
{
|
||||
aIVirtualCard.SetAttack(attack);
|
||||
}
|
||||
if (life >= 0)
|
||||
{
|
||||
aIVirtualCard.SetMaxLife(situation, life);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetMaxStatusToTarget(AISituationInfo situation, int attack, int life, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget != null && situationTarget.HasTarget)
|
||||
{
|
||||
SetMaxStatusToAll(situationTarget.Targets, attack, life, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static (AIVirtualCard allyLeader, AIVirtualCard enemyLeader) GetTargetSideLeaders(AIVirtualCard tagOwner, AIVirtualField field)
|
||||
{
|
||||
if (tagOwner == null)
|
||||
{
|
||||
return (allyLeader: null, enemyLeader: null);
|
||||
}
|
||||
if (!tagOwner.IsAlly)
|
||||
{
|
||||
return (allyLeader: field.EnemyClass, enemyLeader: field.AllyClass);
|
||||
}
|
||||
return (allyLeader: field.AllyClass, enemyLeader: field.EnemyClass);
|
||||
}
|
||||
|
||||
public static void SetLeaderMaxLife(AIVirtualCard tagOwner, int maxLife, AIScriptTokenArgType sideType, AIVirtualField field, AISituationInfo situation = null)
|
||||
{
|
||||
(AIVirtualCard, AIVirtualCard) targetSideLeaders = GetTargetSideLeaders(tagOwner, field);
|
||||
if (targetSideLeaders.Item1 == null || targetSideLeaders.Item2 == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AISetStatusSimulationUtility.SetLeaderMaxLife(): Failed to get the leader.");
|
||||
return;
|
||||
}
|
||||
switch (sideType)
|
||||
{
|
||||
case AIScriptTokenArgType.ALLY:
|
||||
targetSideLeaders.Item1.SetMaxLife(situation, maxLife);
|
||||
break;
|
||||
case AIScriptTokenArgType.OPPONENT:
|
||||
targetSideLeaders.Item2.SetMaxLife(situation, maxLife);
|
||||
break;
|
||||
case AIScriptTokenArgType.BOTH:
|
||||
targetSideLeaders.Item1.SetMaxLife(situation, maxLife);
|
||||
targetSideLeaders.Item2.SetMaxLife(situation, maxLife);
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError($"AISetStatusSimulationUtility.SetLeaderMaxLife(): Unexpected side type. type:{sideType}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
SVSim.BattleEngine/Engine/Wizard/AIShieldInfo.cs
Normal file
35
SVSim.BattleEngine/Engine/Wizard/AIShieldInfo.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIShieldInfo : AIBarrierInfoBase
|
||||
{
|
||||
public override AIBarrierType BarrierType => AIBarrierType.Shield;
|
||||
|
||||
public AIShieldInfo(AIDamageType damageType, AIBarrierStopTiming stopTiming)
|
||||
: base(0, damageType, stopTiming)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public AIShieldInfo(AIDamageType damageType, List<AIBarrierStopTiming> stopTimingList)
|
||||
: base(0, damageType, stopTimingList)
|
||||
{
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
public override bool IsShield()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override AIBarrierInfoBase Clone()
|
||||
{
|
||||
return new AIShieldInfo(base.DamageType, base.StopTimingList);
|
||||
}
|
||||
|
||||
protected override int CalcDamage(AIVirtualCard owner, int damage)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
285
SVSim.BattleEngine/Engine/Wizard/AISimulationRemovalUtility.cs
Normal file
285
SVSim.BattleEngine/Engine/Wizard/AISimulationRemovalUtility.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISimulationRemovalUtility
|
||||
{
|
||||
public static bool WillDieBySkillPrediction(AIVirtualCard card, AIVirtualField field, List<int> playPtn, AISituationInfo situation, bool isHandTagValid)
|
||||
{
|
||||
LifeRecord lifeRecord = new LifeRecord
|
||||
{
|
||||
MaxLife = card.MaxLife,
|
||||
CurrentLife = card.Life
|
||||
};
|
||||
if (isHandTagValid && playPtn != null && playPtn.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
GetRestLifeAfterCardPlay(field.AllyHandCards[playPtn[i]], card, field, playPtn, situation, lifeRecord);
|
||||
if (lifeRecord.CurrentLife <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lifeRecord.CurrentLife <= 0;
|
||||
}
|
||||
|
||||
private static void GetRestLifeAfterCardPlay(AIVirtualCard playCard, AIVirtualCard target, AIVirtualField field, List<int> playPtn, AISituationInfo situation, LifeRecord targetLife)
|
||||
{
|
||||
if (playCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Fanfare))
|
||||
{
|
||||
FanfareTagCollection fanfareTags = playCard.TagCollectionContainer.FanfareTags;
|
||||
if (fanfareTags.HasRemovalTags)
|
||||
{
|
||||
fanfareTags.RemovalPrediction(playCard, target, targetLife, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
if (playCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Play))
|
||||
{
|
||||
PlayTagCollection playTags = playCard.TagCollectionContainer.PlayTags;
|
||||
if (playTags.HasRemovalTags)
|
||||
{
|
||||
playTags.RemovalPrediction(playCard, target, targetLife, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
if (!field.CardListSet.HasOtherPlayTagHolder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < field.CardListSet.OtherPlayTagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.CardListSet.OtherPlayTagHolders[i];
|
||||
OtherPlayTagCollection otherPlayTags = aIVirtualCard.TagCollectionContainer.OtherPlayTags;
|
||||
if (otherPlayTags.HasRemovalTags)
|
||||
{
|
||||
otherPlayTags.RemovalPrediction(aIVirtualCard, playCard, target, targetLife, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void PredictSurvivorsLifeAfterCardPlay(AIVirtualCard playCard, List<AIVirtualCard> targetList, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<LifeRecord> targetLifeList)
|
||||
{
|
||||
if (playCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Fanfare))
|
||||
{
|
||||
FanfareTagCollection fanfareTags = playCard.TagCollectionContainer.FanfareTags;
|
||||
if (fanfareTags.HasRemovalTags)
|
||||
{
|
||||
fanfareTags.MultipleRemovalPrediction(playCard, targetList, field, playPtn, situation, targetLifeList);
|
||||
}
|
||||
}
|
||||
if (playCard.TagCollectionContainer.HasTagCollection(TagCollectionType.Play))
|
||||
{
|
||||
PlayTagCollection playTags = playCard.TagCollectionContainer.PlayTags;
|
||||
if (playTags.HasRemovalTags)
|
||||
{
|
||||
playTags.MultipleRemovalPrediction(playCard, targetList, field, playPtn, situation, targetLifeList);
|
||||
}
|
||||
}
|
||||
if (!field.CardListSet.HasOtherPlayTagHolder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < field.CardListSet.OtherPlayTagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.CardListSet.OtherPlayTagHolders[i];
|
||||
if (!aIVirtualCard.IsSameCard(playCard))
|
||||
{
|
||||
OtherPlayTagCollection otherPlayTags = aIVirtualCard.TagCollectionContainer.OtherPlayTags;
|
||||
if (otherPlayTags.HasRemovalTags)
|
||||
{
|
||||
otherPlayTags.MultipleRemovalPrediction(aIVirtualCard, playCard, targetList, field, playPtn, situation, targetLifeList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectRemovalTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest, AIRemovalType removeType, AIRemovalEvaluationOption removalEvalOption = null)
|
||||
{
|
||||
if (removeType == AIRemovalType.None)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AIVirtualCard result = null;
|
||||
float num = ((worstOrBest == AISelectTargetPattern.Worst) ? float.MaxValue : float.MinValue);
|
||||
bool flag = worstOrBest == AISelectTargetPattern.Best;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
bool flag2 = tagOwner.IsAlly != aIVirtualCard.IsAlly && (aIVirtualCard.IsSneak || aIVirtualCard.IsUntouchable);
|
||||
if (!aIVirtualCard.IsDead && !aIVirtualCard.IsIndependent && !(flag && flag2))
|
||||
{
|
||||
float num2 = CalculateRemovalValue(aIVirtualCard, field, playPtn, situation, removeType, removalEvalOption);
|
||||
bool flag3 = false;
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Worst:
|
||||
flag3 = num2 < num;
|
||||
break;
|
||||
case AISelectTargetPattern.Best:
|
||||
flag3 = num2 > num;
|
||||
break;
|
||||
}
|
||||
if (flag3)
|
||||
{
|
||||
num = num2;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> SelectMultipleRemovalTargets(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest, AIRemovalType removeType, int count, AIRemovalEvaluationOption removalEvalOption = null)
|
||||
{
|
||||
if (removeType == AIRemovalType.None)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>();
|
||||
float[] array = new float[count];
|
||||
float num = ((worstOrBest == AISelectTargetPattern.Worst) ? float.MaxValue : float.MinValue);
|
||||
bool flag = worstOrBest == AISelectTargetPattern.Best;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = num;
|
||||
list.Add(null);
|
||||
}
|
||||
for (int j = 0; j < candidates.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[j];
|
||||
bool flag2 = tagOwner.IsAlly != aIVirtualCard.IsAlly && (aIVirtualCard.IsSneak || aIVirtualCard.IsUntouchable);
|
||||
if (aIVirtualCard.IsDead || aIVirtualCard.IsIndependent || (flag && flag2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float num2 = CalculateRemovalValue(aIVirtualCard, field, playPtn, situation, removeType, removalEvalOption);
|
||||
bool flag3 = false;
|
||||
int num3 = -1;
|
||||
for (int k = 0; k < list.Count; k++)
|
||||
{
|
||||
float num4 = array[k];
|
||||
switch (worstOrBest)
|
||||
{
|
||||
case AISelectTargetPattern.Worst:
|
||||
flag3 = num2 < num4;
|
||||
break;
|
||||
case AISelectTargetPattern.Best:
|
||||
flag3 = num2 > num4;
|
||||
break;
|
||||
}
|
||||
if (flag3)
|
||||
{
|
||||
num3 = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag3)
|
||||
{
|
||||
AIVirtualCard value = aIVirtualCard;
|
||||
float num5 = num2;
|
||||
for (int l = num3; l < list.Count; l++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = list[l];
|
||||
float num6 = array[l];
|
||||
list[l] = value;
|
||||
array[l] = num5;
|
||||
value = aIVirtualCard2;
|
||||
num5 = num6;
|
||||
}
|
||||
}
|
||||
}
|
||||
list.RemoveAll((AIVirtualCard c) => c == null);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static float CalculateRemovalValue(AIVirtualCard target, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIRemovalType removeType, AIRemovalEvaluationOption removalEvalOption)
|
||||
{
|
||||
float num = 0f;
|
||||
switch (removeType)
|
||||
{
|
||||
case AIRemovalType.Destroy:
|
||||
if (!target.IsIndestructible)
|
||||
{
|
||||
num = target.EvaluateValueOnField(playPtn, situation, useStyle: true) - target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false);
|
||||
}
|
||||
break;
|
||||
case AIRemovalType.Banish:
|
||||
if (!target.IsUnbanishable)
|
||||
{
|
||||
num = target.EvaluateValueOnField(playPtn, situation, useStyle: true) + target.GetAllBreakBonus(playPtn, useIgnoreInBattle: false) - target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false) - target.GetAllBanishBonus(playPtn, useIgnoreInBattle: false);
|
||||
}
|
||||
break;
|
||||
case AIRemovalType.Bounce:
|
||||
{
|
||||
int restPp = (target.IsAlly ? field.AI.PlayPtnRecorder.GetRestPp(playPtn, field) : field.EnemyBattlePlayer.Pp);
|
||||
num = target.EvaluateBounceValue(playPtn, restPp);
|
||||
num -= target.GetAllLeaveBonus(playPtn, useIgnoreInBattle: false) * (float)((!target.IsAlly) ? 1 : (-1));
|
||||
break;
|
||||
}
|
||||
case AIRemovalType.Metamorphose:
|
||||
if (removalEvalOption == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("SelectRemovalTarget()でMetamorphoseを指定する場合はremovalEvalOptionが必要です");
|
||||
return 0f;
|
||||
}
|
||||
num = AIMetamorphoseSimulationUtility.EvaluateSingleMetamorphoseValue(target, removalEvalOption.MetamorphoseTokenId, removalEvalOption.TagOwner, field, playPtn, situation);
|
||||
break;
|
||||
}
|
||||
if (target.IsAlly && removeType != AIRemovalType.Bounce && removeType != AIRemovalType.Metamorphose)
|
||||
{
|
||||
num *= -1f;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectWorstTargetForBuff(List<AIVirtualCard> candidates, AIBuffExecutingInfo_old buffInfo)
|
||||
{
|
||||
AIVirtualCard result = null;
|
||||
float num = float.MaxValue;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.IsUnit && !aIVirtualCard.IsDead)
|
||||
{
|
||||
int num2 = (aIVirtualCard.IsAttackable(aIVirtualCard.SelfField.BestPlayPtn) ? aIVirtualCard.AttackableCount : 0);
|
||||
float num3 = (100f - (float)aIVirtualCard.Attack) * (float)num2;
|
||||
float num4 = 100f + (float)aIVirtualCard.Attack;
|
||||
int expectedAttackBuffValue = buffInfo.GetExpectedAttackBuffValue(aIVirtualCard);
|
||||
int expectedLifeBuffValue = buffInfo.GetExpectedLifeBuffValue(aIVirtualCard);
|
||||
float num5 = (aIVirtualCard.IsAlly ? 1f : (-1f)) * ((float)expectedAttackBuffValue * num3 + (float)expectedLifeBuffValue * num4);
|
||||
if (num5 < num)
|
||||
{
|
||||
num = num5;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectBestTargetForBuff(List<AIVirtualCard> candidates, AIBuffExecutingInfo_old buff)
|
||||
{
|
||||
AIVirtualCard result = null;
|
||||
float num = float.MinValue;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.IsUnit && !aIVirtualCard.IsDead)
|
||||
{
|
||||
int num2 = (aIVirtualCard.IsAttackable(aIVirtualCard.SelfField.BestPlayPtn) ? aIVirtualCard.AttackableCount : 0);
|
||||
float num3 = (100f - (float)aIVirtualCard.Attack) * (float)num2;
|
||||
float num4 = 100f + (float)aIVirtualCard.Attack;
|
||||
int expectedAttackBuffValue = buff.GetExpectedAttackBuffValue(aIVirtualCard);
|
||||
int expectedLifeBuffValue = buff.GetExpectedLifeBuffValue(aIVirtualCard);
|
||||
float num5 = (aIVirtualCard.IsAlly ? 1f : (-1f)) * ((float)expectedAttackBuffValue * num3 + (float)expectedLifeBuffValue * num4);
|
||||
if (num5 > num)
|
||||
{
|
||||
num = num5;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISituationCurrentProcessAccessExtension
|
||||
{
|
||||
public static AIVirtualCard GetCurrentTriggerCard(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.TriggerInfo.TriggerCard;
|
||||
}
|
||||
|
||||
public static bool IsSameCurrentTriggerCardAndTriggerType(this AISituationInfo situation, AIVirtualCard card, AISituationTriggerInformation.TriggerType triggerType)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AISituationTriggerInformation triggerInfo = situation.CurrentSkillProcessInfo.TriggerInfo;
|
||||
if (triggerInfo.TriggerCard == null || triggerInfo.Type != triggerType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return triggerInfo.IsTriggerCardAndTriggerType(card, triggerType);
|
||||
}
|
||||
|
||||
public static bool IsSameCurrentTriggerCard(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AISituationTriggerInformation triggerInfo = situation.CurrentSkillProcessInfo.TriggerInfo;
|
||||
if (triggerInfo.TriggerCard == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return triggerInfo.IsTriggerCard(card);
|
||||
}
|
||||
|
||||
public static bool IsBanishTrigger(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AISituationTriggerInformation triggerInfo = situation.CurrentSkillProcessInfo.TriggerInfo;
|
||||
if (triggerInfo.Type == AISituationTriggerInformation.TriggerType.Banish)
|
||||
{
|
||||
return triggerInfo.TriggerCard != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsOwnSummonedCard(this AISituationInfo situation, AIVirtualCard card, AIScriptTokenArgType targetCardType, bool isLatest = false)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<AIVirtualCard> list = (isLatest ? situation.GetOwnLatestSummonedCards() : situation.GetOwnSummonedCards());
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (targetCardType)
|
||||
{
|
||||
case AIScriptTokenArgType.FOLLOWER:
|
||||
if (!card.IsUnit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case AIScriptTokenArgType.AMULET:
|
||||
if (!card.IsAmulet)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AIConsoleUtility.LogError($"IsOwnSummonedCard(): Unsupported target card type. type:{targetCardType}");
|
||||
return false;
|
||||
case AIScriptTokenArgType.ALL:
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsLatestOwnDrewCard(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<AIVirtualCard> ownLatestDrewCards = situation.GetOwnLatestDrewCards();
|
||||
if (ownLatestDrewCards == null || ownLatestDrewCards.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ownLatestDrewCards.Count; i++)
|
||||
{
|
||||
if (ownLatestDrewCards[i].IsSameCard(card))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsLatestTarget(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
List<AIVirtualCard> latestTargets = situation.GetLatestTargets();
|
||||
if (latestTargets == null || latestTargets.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("IsLatestTarget error!! candidates is empty!!!!!");
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < latestTargets.Count; i++)
|
||||
{
|
||||
if (card.IsSameCard(latestTargets[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> GetOwnDestroyedCards(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.OwnDestroyedCards;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> GetOwnSummonedCards(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.OwnSummonedCards;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> GetOwnLatestSummonedCards(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.OwnLatestSummonedCards;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> GetOwnLatestDrewCards(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.OwnLatestDrewCards;
|
||||
}
|
||||
|
||||
public static List<AIVirtualCard> GetLatestTargets(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.LatestTargets;
|
||||
}
|
||||
|
||||
public static int GetCurrentProcessDefaultDamage(this AISituationInfo situation)
|
||||
{
|
||||
if (situation.IsNull())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return situation.CurrentSkillProcessInfo.OwnProcessRecord.DefaultDamage;
|
||||
}
|
||||
|
||||
public static void RegisterOwnDestroyedCard(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
if (!situation.IsNull())
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.AddOwnDestroyedCard(card);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterOwnBanishedCard(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
if (!situation.IsNull())
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.AddOwnBanishedCard(card);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterOwnSummonedCardList(this AISituationInfo situation, List<AIVirtualCard> cards)
|
||||
{
|
||||
if (!situation.IsNull() && cards != null && cards.Count > 0)
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.AddOwnSummonedCards(cards);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterOwnDrewCardList(this AISituationInfo situation, List<AIVirtualCard> cards)
|
||||
{
|
||||
if (!situation.IsNull() && cards != null && cards.Count > 0)
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.AddOwnDrewCards(cards);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterSingleLatestTarget(this AISituationInfo situation, AIVirtualCard card)
|
||||
{
|
||||
if (!situation.IsNull())
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.RegisterSingleLatestTarget(card);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterLatestTargetList(this AISituationInfo situation, List<AIVirtualCard> list)
|
||||
{
|
||||
if (!situation.IsNull() && list != null && list.Count > 0)
|
||||
{
|
||||
situation.CurrentSkillProcessInfo.OwnProcessRecord.RegisterLatestTargetList(list);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNull(this AISituationInfo situation)
|
||||
{
|
||||
if (situation != null)
|
||||
{
|
||||
return situation.CurrentSkillProcessInfo == null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
134
SVSim.BattleEngine/Engine/Wizard/AISkillActivateCountUtility.cs
Normal file
134
SVSim.BattleEngine/Engine/Wizard/AISkillActivateCountUtility.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISkillActivateCountUtility
|
||||
{
|
||||
public const int NONE_LIMIT_ACTIVATE_COUNT = -1;
|
||||
|
||||
public static void AllActivateCountHolderIncrement(this AIVirtualField field, AISituationInfo situation, AIPlayTagType counterType, AIVirtualCard triggerCard = null)
|
||||
{
|
||||
if (field.CardListSet.HasActivateCountHolder)
|
||||
{
|
||||
List<AIVirtualCard> activateCountHolders = field.CardListSet.ActivateCountHolders;
|
||||
for (int i = 0; i < activateCountHolders.Count; i++)
|
||||
{
|
||||
activateCountHolders[i].Increment(situation, counterType, triggerCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AllActivateCountHolderIncrement(this AIVirtualField field, AISituationInfo situation, AIPlayTagType counterType, List<AIVirtualCard> triggerCardList)
|
||||
{
|
||||
if (field.CardListSet.HasActivateCountHolder)
|
||||
{
|
||||
List<AIVirtualCard> activateCountHolders = field.CardListSet.ActivateCountHolders;
|
||||
for (int i = 0; i < activateCountHolders.Count; i++)
|
||||
{
|
||||
activateCountHolders[i].Increment(situation, counterType, triggerCardList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Increment(this AIVirtualCard card, AISituationInfo situation, AIPlayTagType counterType, AIVirtualCard triggerCard = null)
|
||||
{
|
||||
if (card.TagCollectionContainer.HasTag(counterType) && CheckCounterTypeCommonIncrementCondition(counterType, card, situation))
|
||||
{
|
||||
card.TagCollectionContainer.ActivateCountTags.Increment(card, situation, counterType, triggerCard);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Increment(this AIVirtualCard card, AISituationInfo situation, AIPlayTagType counterType, List<AIVirtualCard> triggerCardList)
|
||||
{
|
||||
if (card.TagCollectionContainer.HasTag(counterType) && CheckCounterTypeCommonIncrementCondition(counterType, card, situation))
|
||||
{
|
||||
card.TagCollectionContainer.ActivateCountTags.Increment(card, situation, counterType, triggerCardList);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CheckCounterTypeCommonIncrementCondition(AIPlayTagType counterType, AIVirtualCard holder, AISituationInfo situation)
|
||||
{
|
||||
if (counterType == AIPlayTagType.TurnEndActivateCount)
|
||||
{
|
||||
return holder.IsAlly == situation.Actor.IsAlly;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int GetSkillActivateCount(this AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
if (!field.CardListSet.HasActivateCountHolder)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!CheckActivateCounterFilteringArgument(argList, out var filters, out var skillOwnerId, out var skillIndex))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
List<AIVirtualCard> activateCountHolders = field.CardListSet.ActivateCountHolders;
|
||||
for (int i = 0; i < activateCountHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = activateCountHolders[i];
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, null, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num += aIVirtualCard.GetSkillActivateCountFromOneCard(skillOwnerId, skillIndex);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static bool IsSkillOccurred(this AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, List<AIScriptTokenBase> argList)
|
||||
{
|
||||
if (!field.CardListSet.HasActivateCountHolder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CheckActivateCounterFilteringArgument(argList, out var filters, out var skillOwnerId, out var skillIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<AIVirtualCard> activateCountHolders = field.CardListSet.ActivateCountHolders;
|
||||
for (int i = 0; i < activateCountHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = activateCountHolders[i];
|
||||
if (AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, null, filters, playPtn, tagOwner, situation) && !aIVirtualCard.GetIsSkillOccurredFromOneCard(skillOwnerId, skillIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CheckActivateCounterFilteringArgument(List<AIScriptTokenBase> argList, out List<AIScriptTokenBase> filters, out int skillOwnerId, out int skillIndex)
|
||||
{
|
||||
filters = null;
|
||||
skillOwnerId = -1;
|
||||
skillIndex = 0;
|
||||
if (!(argList[0] is AIScriptNumericToken aIScriptNumericToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
skillIndex = (int)aIScriptNumericToken.Value;
|
||||
argList.RemoveAt(0);
|
||||
if (!(argList[0] is AIScriptIDToken aIScriptIDToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
skillOwnerId = aIScriptIDToken.ID;
|
||||
argList.RemoveAt(0);
|
||||
argList.Reverse();
|
||||
filters = argList;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int GetSkillActivateCountFromOneCard(this AIVirtualCard counterOwner, int counterSourceCardId, int counterIndex)
|
||||
{
|
||||
return counterOwner.TagCollectionContainer.ActivateCountTags.GetActivateCount(counterSourceCardId, counterIndex);
|
||||
}
|
||||
|
||||
private static bool GetIsSkillOccurredFromOneCard(this AIVirtualCard counterOwner, int counterSourceCardId, int counterIndex)
|
||||
{
|
||||
return counterOwner.TagCollectionContainer.ActivateCountTags.IsSkillOccurred(counterSourceCardId, counterIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISkillCountFromIdUtility
|
||||
{
|
||||
public static int GetSkillCountFromID(List<AIScriptTokenBase> filters, int skillOwnerId, AIVirtualCard tagOwner, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
num += GetAttachedSkillCount(list[i].BaseCard, skillOwnerId);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetAttachedSkillCount(BattleCardBase targetCard, int skillOwnerId)
|
||||
{
|
||||
int num = 0;
|
||||
List<int> ownerCardIdList = targetCard.SkillApplyInformation.AttachedSkillsInfo.OwnerCardIdList;
|
||||
for (int i = 0; i < ownerCardIdList.Count; i++)
|
||||
{
|
||||
if (EnemyAI.GetBaseId(ownerCardIdList[i]) == skillOwnerId)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISpellboostSimulationUtility
|
||||
{
|
||||
public static void SpellboostAll(List<AIVirtualCard> targets, int count)
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
targets[i].Spellboost(count);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SpellboostTarget(AISituationInfo situation, int count, List<AIVirtualCard> candidates, AIScriptTokenArgType whichTarget)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
aIVirtualCard.Spellboost(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SpellboostWhenPlaySpellAtEvaluation(AIVirtualCard playCard, AIVirtualField field)
|
||||
{
|
||||
for (int i = 0; i < field.AllyHandCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[i];
|
||||
if (aIVirtualCard.HasSpellboost)
|
||||
{
|
||||
aIVirtualCard.Spellboost(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SpellboostWhenPlaySpell(AIVirtualCard playCard, AIVirtualField field)
|
||||
{
|
||||
if (!playCard.IsAlly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < field.AllyHandCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.AllyHandCards[i];
|
||||
if (!aIVirtualCard.IsSameCard(playCard) && aIVirtualCard.HasSpellboost)
|
||||
{
|
||||
aIVirtualCard.Spellboost(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AIVirtualCard SelectBestTargetForSpellboost(AIVirtualField field, int boostCount, List<AIVirtualCard> candidates)
|
||||
{
|
||||
AIVirtualCard result = null;
|
||||
float num = float.MinValue;
|
||||
List<int> list = new List<int>();
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
int spellboostCount = aIVirtualCard.SpellboostCount;
|
||||
list.Clear();
|
||||
list.Add(field.AllyHandCards.IndexOf(aIVirtualCard));
|
||||
float num2 = CalculateCardValueForSpellboostEvaluation(aIVirtualCard, list);
|
||||
aIVirtualCard.Spellboost(boostCount);
|
||||
float num3 = CalculateCardValueForSpellboostEvaluation(aIVirtualCard, list);
|
||||
aIVirtualCard.SetSpellboostCount(spellboostCount);
|
||||
float num4 = num3 - num2;
|
||||
if (num4 > num)
|
||||
{
|
||||
result = aIVirtualCard;
|
||||
num = num4;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float CalculateCardValueForSpellboostEvaluation(AIVirtualCard card, List<int> playPtn)
|
||||
{
|
||||
return card.EvaluatePlayValue(playPtn) + card.GetHandBonus(playPtn, null, isIgnoreInFusion: false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISubtractCountdownSimulationUtility
|
||||
{
|
||||
public static void SubtractCountdownAll(List<AIVirtualCard> targetCards, int value, AISituationInfo situation)
|
||||
{
|
||||
for (int i = 0; i < targetCards.Count; i++)
|
||||
{
|
||||
SubtractCountdownSingle(targetCards[i], value, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteTargetSelectSubtractCountdown(AIVirtualCard tagOwner, List<AIVirtualCard> candidats, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AIScriptTokenArgType selectType, int countChange)
|
||||
{
|
||||
if (situation == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("ExecuteTargetSelectSubtractCountdown() Error!! situation is null!!!!!");
|
||||
}
|
||||
else if (situation.IsTargetExists(selectType))
|
||||
{
|
||||
SubtractCountdownTarget(situation, candidats, selectType, countChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubtractCountdownTargetPrediction(situation, candidats, tagOwner, field, playPtn, selectType, countChange);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SubtractCountdownTarget(AISituationInfo situation, List<AIVirtualCard> candidates, AIScriptTokenArgType whichTarget, int value)
|
||||
{
|
||||
AISelectedTargetInfo situationTarget = situation.GetSituationTarget(whichTarget);
|
||||
if (situationTarget == null || !situationTarget.HasTarget)
|
||||
{
|
||||
AIConsoleUtility.LogError("SubtractCountdownTarget error!! No target!!!!!");
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> targets = situationTarget.Targets;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (candidates.Contains(aIVirtualCard))
|
||||
{
|
||||
SubtractCountdownSingle(aIVirtualCard, value, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SubtractCountdownTargetPrediction(AISituationInfo situation, List<AIVirtualCard> candidates, AIVirtualCard owner, AIVirtualField field, List<int> playPtn, AIScriptTokenArgType whichTarget, int countChange)
|
||||
{
|
||||
AIVirtualCard target = SelectBestTarget(AITargetSelectFilteringUtility.SelectCandidatesWithForceTargeting(candidates, owner, playPtn), countChange);
|
||||
situation.SetSingleTargetInInfo(target, TargetSelectType.Default, whichTarget);
|
||||
SubtractCountdownTarget(situation, candidates, whichTarget, countChange);
|
||||
}
|
||||
|
||||
public static void SubtractCountdownSingle(AIVirtualCard target, int value, AISituationInfo situation)
|
||||
{
|
||||
if (!target.IsDead && target.IsCountdownAmulet)
|
||||
{
|
||||
target.ChantCountDown(situation, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard SelectBestTarget(List<AIVirtualCard> candidates, int countChange)
|
||||
{
|
||||
AIVirtualCard result = null;
|
||||
float num = float.MinValue;
|
||||
List<int> emptyPlayPtn = EnemyAI.EmptyPlayPtn;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
float num2 = aIVirtualCard.EvaluateBreakValue(emptyPlayPtn, useIgnoreBreak: false);
|
||||
int num3 = Mathf.Max(0, aIVirtualCard.ChantCount - countChange);
|
||||
float num4 = num2 * Mathf.Pow(0.75f, num3);
|
||||
if (num4 > num)
|
||||
{
|
||||
result = aIVirtualCard;
|
||||
num = num4;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
89
SVSim.BattleEngine/Engine/Wizard/AISummonCountUtility.cs
Normal file
89
SVSim.BattleEngine/Engine/Wizard/AISummonCountUtility.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AISummonCountUtility
|
||||
{
|
||||
public static bool ClassificateSummonCountArgument(List<AIScriptTokenBase> argList, out List<AIScriptTokenBase> filters, out AIScriptTokenArgType turnOrGame, out AIScriptTokenArgType playedType)
|
||||
{
|
||||
filters = new List<AIScriptTokenBase>();
|
||||
turnOrGame = AIScriptTokenArgType.NONE;
|
||||
playedType = AIScriptTokenArgType.NONE;
|
||||
if (argList == null || argList.Count < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool flag = false;
|
||||
if (argList[0] is AIScriptArgumentToken aIScriptArgumentToken)
|
||||
{
|
||||
if (aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.PLAYED || aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.PLAYPTN)
|
||||
{
|
||||
playedType = aIScriptArgumentToken.ArgumentType;
|
||||
flag = true;
|
||||
}
|
||||
else if (aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.TURN || aIScriptArgumentToken.ArgumentType == AIScriptTokenArgType.GAME)
|
||||
{
|
||||
turnOrGame = aIScriptArgumentToken.ArgumentType;
|
||||
}
|
||||
argList.RemoveAt(0);
|
||||
if (flag)
|
||||
{
|
||||
if (argList[0] is AIScriptArgumentToken aIScriptArgumentToken2 && (aIScriptArgumentToken2.ArgumentType == AIScriptTokenArgType.TURN || aIScriptArgumentToken2.ArgumentType == AIScriptTokenArgType.GAME))
|
||||
{
|
||||
turnOrGame = aIScriptArgumentToken2.ArgumentType;
|
||||
}
|
||||
argList.RemoveAt(0);
|
||||
}
|
||||
if (turnOrGame == AIScriptTokenArgType.NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
argList.Reverse();
|
||||
filters = argList;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int GetSummonCount(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, AIScriptTokenArgType turnOrGame, AIScriptTokenArgType playedType, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (turnOrGame != AIScriptTokenArgType.TURN && turnOrGame != AIScriptTokenArgType.GAME)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return playedType switch
|
||||
{
|
||||
AIScriptTokenArgType.NONE => GetSummonCountAtPlayed(tagOwner, filters, turnOrGame, playPtn, situation) + GetSummonCountAtPlayPtn(tagOwner, filters, playPtn, situation),
|
||||
AIScriptTokenArgType.PLAYED => GetSummonCountAtPlayed(tagOwner, filters, turnOrGame, playPtn, situation),
|
||||
AIScriptTokenArgType.PLAYPTN => GetSummonCountAtPlayPtn(tagOwner, filters, playPtn, situation),
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetSummonCountAtPlayed(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, AIScriptTokenArgType turnOrGame, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
return AIFilteringUtility.MultipleFiltering(tagOwner.SelfField.SummonedCardContainer.GetSummonedList(tagOwner.IsAlly, turnOrGame == AIScriptTokenArgType.TURN), filters, tagOwner, playPtn, situation)?.Count ?? 0;
|
||||
}
|
||||
|
||||
private static int GetSummonCountAtPlayPtn(AIVirtualCard tagOwner, List<AIScriptTokenBase> filters, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (!tagOwner.IsAlly || playPtn == null || playPtn.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
List<AIVirtualCard> allyHandCards = tagOwner.SelfField.AllyHandCards;
|
||||
for (int i = 0; i < playPtn.Count; i++)
|
||||
{
|
||||
if (playPtn[i] < allyHandCards.Count)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = allyHandCards[playPtn[i]];
|
||||
if ((((aIVirtualCard.IsUnit || aIVirtualCard.IsAmulet) && !aIVirtualCard.IsAccelerated(tagOwner.SelfField, playPtn, situation)) || aIVirtualCard.IsCrystalize(tagOwner.SelfField, playPtn, situation)) && AIFilteringUtility.CheckMatchTargetFiltering(aIVirtualCard, null, filters, playPtn, tagOwner, situation))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
26
SVSim.BattleEngine/Engine/Wizard/AITagCountFromIdUtility.cs
Normal file
26
SVSim.BattleEngine/Engine/Wizard/AITagCountFromIdUtility.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AITagCountFromIdUtility
|
||||
{
|
||||
public static int GetTagCountFromId(AIVirtualCard tagOwner, int id, List<AIScriptTokenBase> filters, AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
List<AIVirtualCard> list = AIFilteringUtility.MultipleFiltering(field.CardListSet.BothClassAndInplayCards, filters, tagOwner, playPtn, situation);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
num += GetAttachedTagCount(list[i], id);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int GetAttachedTagCount(AIVirtualCard card, int id)
|
||||
{
|
||||
return card.TagCollectionContainer.AttachedTags?.GetAttachedTagCountFromId(id) ?? 0;
|
||||
}
|
||||
}
|
||||
13
SVSim.BattleEngine/Engine/Wizard/AITurnEndMove.cs
Normal file
13
SVSim.BattleEngine/Engine/Wizard/AITurnEndMove.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Wizard;
|
||||
|
||||
internal class AITurnEndMove : AIMove
|
||||
{
|
||||
public AITurnEndMove()
|
||||
: base(AIOperationType.TURNEND)
|
||||
{
|
||||
}
|
||||
|
||||
public override void RunOperation(BattleManagerBase mgr, bool isPlayer)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AITyrantOrderSelectLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.TYRANT_ORDER_LOGIC;
|
||||
|
||||
public AITyrantOrderSelectLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIConsoleUtility.LogError("AITyrantOrderSelectLogicArgument: This logic is cant use single target select");
|
||||
return null;
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
List<AIVirtualCard> list = new List<AIVirtualCard>(candidates);
|
||||
list.RemoveAll((AIVirtualCard c) => c.IsLeader || c.IsDead || c.IsIndependent || c.IsSneak || c.IsUntouchable);
|
||||
if (list.Count == selectCount)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
if (list.Count < selectCount)
|
||||
{
|
||||
AIConsoleUtility.LogError("AITyrantOrderSelectLogicArgument:SelectMultipleSelectedTargets() - Targets dont meet the minimum number.");
|
||||
return null;
|
||||
}
|
||||
AIReverseEvaluateValueListOrder aIReverseEvaluateValueListOrder = new AIReverseEvaluateValueListOrder();
|
||||
for (int num = 0; num < list.Count; num++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[num];
|
||||
float value = ((!aIVirtualCard.IsForceTargeting) ? ((!aIVirtualCard.IsAmulet) ? AISimulationRemovalUtility.CalculateRemovalValue(aIVirtualCard, field, playPtn, situation, AIRemovalType.Destroy, null) : 0f) : float.MinValue);
|
||||
aIReverseEvaluateValueListOrder.AddData(value, aIVirtualCard);
|
||||
}
|
||||
return aIReverseEvaluateValueListOrder.GetCardList(selectCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AIUntouchableStopPreprocessOption : AITagPreprocessCreationOptionBase
|
||||
{
|
||||
public AIUntouchableStopPreprocessOption(AIVirtualCard targetCard)
|
||||
: base(AITagPreprocessInfoType.UNTOUCHABLE_STOP, targetCard)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIVirtualCardUpdateInformationExtension
|
||||
{
|
||||
public static void UpdateCardInformation(this AIVirtualCard card, AIVirtualCard source)
|
||||
{
|
||||
card.UpdateOtherEvolveParameter(source);
|
||||
card.UpdateAttachTagInformation(source);
|
||||
card.UpdateRemovedTagInformation(source);
|
||||
card.UpdateBarrierInfo(source);
|
||||
card.UpdateWhenChangeInplayTagInformation(source);
|
||||
card.UpdateRemovedAttachTagInformation(source);
|
||||
card.UpdateActivateCounter(source);
|
||||
card.CopyCannotAttackInfoList(source);
|
||||
}
|
||||
|
||||
private static void UpdateOtherEvolveParameter(this AIVirtualCard card, AIVirtualCard source)
|
||||
{
|
||||
card.SetOtherEvolveParameterFromVirtualCard(source);
|
||||
}
|
||||
|
||||
private static void UpdateWhenChangeInplayTagInformation(this AIVirtualCard owner, AIVirtualCard updateSource)
|
||||
{
|
||||
if (owner.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenChangeInplay) && updateSource.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenChangeInplay))
|
||||
{
|
||||
ChangeInplayTagCollection changeInplayTags = owner.TagCollectionContainer.ChangeInplayTags;
|
||||
ChangeInplayTagCollection changeInplayTags2 = updateSource.TagCollectionContainer.ChangeInplayTags;
|
||||
changeInplayTags.UpdateIsActivatedInformation(changeInplayTags2.TagIsActivatedList, changeInplayTags2.AddedChangeInplayActivatedInfoIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateAttachTagInformation(this AIVirtualCard owner, AIVirtualCard updateSource)
|
||||
{
|
||||
AIAttachedTagCollection attachedTags = updateSource.TagCollectionContainer.AttachedTags;
|
||||
if (attachedTags == null || !attachedTags.HasAnyTag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<ulong> list = null;
|
||||
AIAttachedTagCollection attachedTags2 = owner.TagCollectionContainer.AttachedTags;
|
||||
if (attachedTags2 != null && attachedTags2.HasAnyTag)
|
||||
{
|
||||
for (int i = 0; i < attachedTags2.AllList.Count; i++)
|
||||
{
|
||||
list = AIParamQuery.AddElementToList(attachedTags2.AllList[i].Hash, list);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < attachedTags.AllList.Count; j++)
|
||||
{
|
||||
AIAttachedTagInformation aIAttachedTagInformation = attachedTags.AllList[j];
|
||||
int num = -1;
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
num = list.IndexOf(aIAttachedTagInformation.Hash);
|
||||
}
|
||||
if (num >= 0)
|
||||
{
|
||||
list.RemoveAt(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.TagCollectionContainer.AttachTag(aIAttachedTagInformation, owner, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateRemovedTagInformation(this AIVirtualCard tagOwner, AIVirtualCard updateSource)
|
||||
{
|
||||
AIRemovedTagCollection removedTagCollection = tagOwner.TagCollectionContainer.RemovedTagCollection;
|
||||
AIRemovedTagCollection removedTagCollection2 = updateSource.TagCollectionContainer.RemovedTagCollection;
|
||||
if ((removedTagCollection.AllList == null && removedTagCollection2.AllList == null) || removedTagCollection2.AllList == null || removedTagCollection2.AllList.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int num = ((removedTagCollection.AllList != null) ? removedTagCollection.AllList.Count : 0);
|
||||
int num2 = ((removedTagCollection2.AllList != null) ? removedTagCollection2.AllList.Count : 0);
|
||||
if (num < num2)
|
||||
{
|
||||
for (int i = num; i < removedTagCollection2.AllList.Count; i++)
|
||||
{
|
||||
AIRemovedTagInformation aIRemovedTagInformation = removedTagCollection2.AllList[i];
|
||||
tagOwner.TagCollectionContainer.RemoveOneTagWithUpdatingFieldCardList(tagOwner, aIRemovedTagInformation.Tag, tagOwner.SelfField);
|
||||
removedTagCollection.Add(aIRemovedTagInformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateRemovedAttachTagInformation(this AIVirtualCard owner, AIVirtualCard source)
|
||||
{
|
||||
AIAttachedTagCollection attachedTags = owner.TagCollectionContainer.AttachedTags;
|
||||
AIAttachedTagCollection attachedTags2 = source.TagCollectionContainer.AttachedTags;
|
||||
if (attachedTags != null && attachedTags.HasAnyTag && attachedTags2 != null && attachedTags2.HasRemovedInfoCaches)
|
||||
{
|
||||
List<AIPlayTag> removedTagCacheList = attachedTags2.RemovedTagCacheList;
|
||||
for (int i = 0; i < removedTagCacheList.Count; i++)
|
||||
{
|
||||
AIPlayTag removingInfo = removedTagCacheList[i];
|
||||
AIRemoveTagUtility.RemoveTemporaryAttachedTag(owner, owner.SelfField, removingInfo, null);
|
||||
}
|
||||
removedTagCacheList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateBarrierInfo(this AIVirtualCard card, AIVirtualCard source)
|
||||
{
|
||||
card.BarrierInfoCollection = source.BarrierInfoCollection.Clone();
|
||||
}
|
||||
|
||||
private static void UpdateActivateCounter(this AIVirtualCard card, AIVirtualCard source)
|
||||
{
|
||||
if (card.TagCollectionContainer.HasTagCollection(TagCollectionType.ActivateCount) && source.TagCollectionContainer.HasTagCollection(TagCollectionType.ActivateCount))
|
||||
{
|
||||
ActivateCountTagCollection activateCountTags = card.TagCollectionContainer.ActivateCountTags;
|
||||
ActivateCountTagCollection activateCountTags2 = source.TagCollectionContainer.ActivateCountTags;
|
||||
activateCountTags.UpdateCounterList(activateCountTags2.ActivateCounterList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIVirtualFieldInitializeUtility
|
||||
{
|
||||
public static void FindBuildParameterAndApply(this AIVirtualCard self, AIVirtualFieldBuildParameterCollction fieldBuildParameter)
|
||||
{
|
||||
ReferableVirtualCardBuildParameterCollection referableCardBuildParameter = fieldBuildParameter.GetReferableCardBuildParameter(self);
|
||||
if (referableCardBuildParameter != null)
|
||||
{
|
||||
self.GetInformationFromCardBuildParameter(referableCardBuildParameter);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetInformationFromCardBuildParameter(this AIVirtualCard self, ReferableVirtualCardBuildParameterCollection cardBuildParameter)
|
||||
{
|
||||
self.BarrierInfoCollection.GetBarrierInfoFromPreviousField(cardBuildParameter.BarrierInfoCollection);
|
||||
cardBuildParameter.AttachedTags.AttachTagToReceiver(self);
|
||||
cardBuildParameter.RemovedTags.RemoveTagFromCard(self);
|
||||
if (self.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenChangeInplay))
|
||||
{
|
||||
self.TagCollectionContainer.ChangeInplayTags.UpdateIsActivatedInformation(cardBuildParameter.ChangeInplayTagIsActivatedInfoList, cardBuildParameter.AddedChangeInplayTagActivatedInfoIncrement);
|
||||
}
|
||||
if (self.TagCollectionContainer.HasTagCollection(TagCollectionType.ActivateCount))
|
||||
{
|
||||
self.TagCollectionContainer.ActivateCountTags.UpdateCounterList(cardBuildParameter.ActivateCounterList);
|
||||
}
|
||||
self.SetOtherEvolveParameterFromBuildParameter(cardBuildParameter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIVirtualFieldTagProcessExtension
|
||||
{
|
||||
public static void ExecuteWhenChangeInplayTags(this AIVirtualField field, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (!field.CardListSet.HasWhenChangeInplayHolder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<AIVirtualCard> whenChangeInplayHolders = field.CardListSet.WhenChangeInplayHolders;
|
||||
for (int i = 0; i < whenChangeInplayHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = whenChangeInplayHolders[i];
|
||||
if (!aIVirtualCard.IsDead)
|
||||
{
|
||||
aIVirtualCard.ExecuteWhenChangeInplayTag(field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTagInformationFromLatestAction(this AIVirtualField currentField, AIRealActionInformation latestAction, AIVirtualField beforeLatestActionField)
|
||||
{
|
||||
AIVirtualField aIVirtualField = new AIVirtualField(beforeLatestActionField, isLatestAction: true);
|
||||
AISituationInfo aISituationInfo = latestAction.CreateSituationInfo(aIVirtualField);
|
||||
if (aISituationInfo != null)
|
||||
{
|
||||
EnemyAI aI = currentField.AI;
|
||||
List<AIVirtualCard> enemyHandCardList = currentField.GetEnemyHandCardList();
|
||||
for (int i = 0; i < enemyHandCardList.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = enemyHandCardList[i];
|
||||
aI.tokenManager.AddTokenFromId(aIVirtualCard.BaseId, aIVirtualCard.IsAlly);
|
||||
}
|
||||
aISituationInfo.SetLatestActionSimulationParameter();
|
||||
SimulateLatestAction(aISituationInfo, aIVirtualField);
|
||||
currentField.UpdateFieldParameterFromLatestActionField(aIVirtualField);
|
||||
AIGenerateTagUtility.ExecuteGenerateTag(aISituationInfo, currentField, aI.GenerateTagOwnerTable, aI.BattleInfoReceivedData.AttachedInfoReceiveCollection);
|
||||
}
|
||||
}
|
||||
|
||||
private static AIVirtualCard FindSimilarCardFromSimulationField(AIVirtualCard card, AIVirtualField realField, AIVirtualField simulationField)
|
||||
{
|
||||
List<AIVirtualCard> list = null;
|
||||
int num = -1;
|
||||
if (card.IsInHand)
|
||||
{
|
||||
list = simulationField.AllyHandCards;
|
||||
num = realField.AllyHandCards.IndexOf(card);
|
||||
}
|
||||
else if (card.IsOnField)
|
||||
{
|
||||
if (card.IsAlly)
|
||||
{
|
||||
list = simulationField.CardListSet.AllyClassAndInplayCards;
|
||||
num = realField.CardListSet.AllyClassAndInplayCards.IndexOf(card);
|
||||
}
|
||||
else
|
||||
{
|
||||
list = simulationField.CardListSet.EnemyClassAndInplayCards;
|
||||
num = realField.CardListSet.EnemyClassAndInplayCards.IndexOf(card);
|
||||
}
|
||||
}
|
||||
if (list == null || num < 0 || num >= list.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsDead)
|
||||
{
|
||||
if (num2 < num)
|
||||
{
|
||||
num2++;
|
||||
}
|
||||
else if (num2 == num && aIVirtualCard.BaseId == card.BaseId)
|
||||
{
|
||||
return aIVirtualCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static AIVirtualCard FindSimilarCardFromEnemyHand(AIVirtualCard card, AIVirtualField realField, AIVirtualField simulationField)
|
||||
{
|
||||
List<AIVirtualCard> list = null;
|
||||
int num = -1;
|
||||
if (card.IsInHand)
|
||||
{
|
||||
list = simulationField.GetEnemyHandCardList();
|
||||
num = realField.GetEnemyHandCardList().IndexOf(card);
|
||||
}
|
||||
if (list == null || num < 0 || num >= list.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (num2 < num && !aIVirtualCard.IsDead)
|
||||
{
|
||||
num2++;
|
||||
}
|
||||
else if (num2 == num && aIVirtualCard.BaseId == card.BaseId)
|
||||
{
|
||||
return aIVirtualCard;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SimulateLatestAction(AISituationInfo latestAction, AIVirtualField field)
|
||||
{
|
||||
switch (latestAction.ActionType)
|
||||
{
|
||||
case AIOperationType.PLAY:
|
||||
{
|
||||
PlaySimulationInfo playInfo = AIPlayCardSimulationUtility.CreatePlaySimulationInfo(latestAction.Actor, latestAction, field);
|
||||
AIVirtualPlaySimulator.PlayCard((AIVirtualTargetSelectAction)latestAction, field, playInfo);
|
||||
break;
|
||||
}
|
||||
case AIOperationType.EVOLVE:
|
||||
AIVirtualEvolutionSimulator.ManualEvolve((AIVirtualTargetSelectAction)latestAction, field);
|
||||
break;
|
||||
case AIOperationType.ATTACK:
|
||||
AIVirtualAttackSimulator.Attack((AIVirtualAttackInfo)latestAction, field);
|
||||
break;
|
||||
case AIOperationType.TURNEND:
|
||||
{
|
||||
AIVirtualTurnEndSimulator.TurnEnd((AIVirtualTurnEndInfo)latestAction, field);
|
||||
AIVirtualTurnStartInfo aIVirtualTurnStartInfo = new AIVirtualTurnStartInfo(latestAction.Actor.IsAlly ? field.EnemyClass : field.AllyClass);
|
||||
aIVirtualTurnStartInfo.SetLatestActionSimulationParameterFromPreAction(latestAction);
|
||||
AIVirtualTurnStartSimulator.TurnStart(aIVirtualTurnStartInfo, field);
|
||||
break;
|
||||
}
|
||||
case AIOperationType.FUSION:
|
||||
AIVirtualFusionSimulator.Fusion((AIVirtualTargetSelectAction)latestAction, field);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateFieldParameterFromLatestActionField(this AIVirtualField field, AIVirtualField afterLatestActionField)
|
||||
{
|
||||
field.UpdateFieldInformationBeforeCardUpdating(afterLatestActionField);
|
||||
for (int i = 0; i < field.CardListSet.AllReferableCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard card = field.CardListSet.AllReferableCards[i];
|
||||
AIVirtualCard aIVirtualCard = FindSimilarCardFromSimulationField(card, field, afterLatestActionField);
|
||||
if (aIVirtualCard != null)
|
||||
{
|
||||
card.UpdateCardInformation(aIVirtualCard);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < field.GetEnemyHandCardList().Count; j++)
|
||||
{
|
||||
AIVirtualCard card2 = field.GetEnemyHandCardList()[j];
|
||||
AIVirtualCard aIVirtualCard2 = FindSimilarCardFromEnemyHand(card2, field, afterLatestActionField);
|
||||
if (aIVirtualCard2 != null)
|
||||
{
|
||||
card2.UpdateCardInformation(aIVirtualCard2);
|
||||
}
|
||||
}
|
||||
field.UpdateFieldInformationAfterCardUpdating(afterLatestActionField);
|
||||
}
|
||||
|
||||
private static void UpdateFieldInformationBeforeCardUpdating(this AIVirtualField currentField, AIVirtualField otherField)
|
||||
{
|
||||
currentField.SetParametersFromOtherField(otherField);
|
||||
}
|
||||
|
||||
private static void UpdateFieldInformationAfterCardUpdating(this AIVirtualField currentField, AIVirtualField otherField)
|
||||
{
|
||||
currentField.TagPreprocessContainer = otherField.TagPreprocessContainer.Clone(currentField);
|
||||
currentField.DamageModifierCollection = otherField.DamageModifierCollection.Clone(currentField);
|
||||
currentField.IsNoInstantAttackRecheck();
|
||||
}
|
||||
|
||||
public static void ApplyAttackBonus(this AIVirtualField field, AIVirtualAttackInfo situation)
|
||||
{
|
||||
if (situation.IsUsePreCheck)
|
||||
{
|
||||
field.SimulationExtraBonus += situation.PreCheckInformation.AttackBonus;
|
||||
}
|
||||
else
|
||||
{
|
||||
field.SimulationExtraBonus += situation.Actor.GetAttackBonus(field.BestPlayPtn, situation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplyClashBonus(this AIVirtualField field, AIVirtualAttackInfo situation)
|
||||
{
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
AIVirtualCard attackTarget = situation.AttackTarget;
|
||||
if (attackTarget.IsUnit)
|
||||
{
|
||||
field.SimulationExtraBonus += actor.GetClashBonus();
|
||||
field.SimulationExtraBonus += attackTarget.GetClashBonus();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ApplyBuffBonus(this AIVirtualField field, AIVirtualCard buffedCard, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
field.SimulationExtraBonus += buffedCard.GetBuffBonus(playPtn, situation);
|
||||
}
|
||||
|
||||
public static void ExecuteWhenDamageTags(this AIVirtualField field, AIVirtualCard damagedTarget, int defaultDamage, List<int> playPtn, AISituationInfo situation)
|
||||
{
|
||||
if (damagedTarget.Life <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (damagedTarget.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenDamaged))
|
||||
{
|
||||
damagedTarget.TagCollectionContainer.DamagedTags.RegisterPassedConditionTags(damagedTarget, field, playPtn, situation);
|
||||
}
|
||||
List<AIVirtualCard> otherDamagedTagHolders = field.CardListSet.OtherDamagedTagHolders;
|
||||
if (otherDamagedTagHolders != null)
|
||||
{
|
||||
for (int i = 0; i < otherDamagedTagHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = otherDamagedTagHolders[i];
|
||||
aIVirtualCard.TagCollectionContainer.OtherDamagedTags.RegisterPassedConditionTags(aIVirtualCard, damagedTarget, defaultDamage, field, playPtn, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
SVSim.BattleEngine/Engine/Wizard/AIVirtualFusionSimulator.cs
Normal file
45
SVSim.BattleEngine/Engine/Wizard/AIVirtualFusionSimulator.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIVirtualFusionSimulator
|
||||
{
|
||||
public static void Fusion(AIVirtualTargetSelectAction situation, AIVirtualField field)
|
||||
{
|
||||
if (situation.ActionType != AIOperationType.FUSION)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIVirtualFusionSimulator:Fusion() error!! situation is not [FUSION] ActionType!!!!!");
|
||||
return;
|
||||
}
|
||||
if (!situation.IsTargetExists(AIScriptTokenArgType.TARGET_SELECT))
|
||||
{
|
||||
AIConsoleUtility.LogError("AIVirtualFusionSimulator:Fusion() error!! cannot find fusion ingredients!!!!!");
|
||||
return;
|
||||
}
|
||||
FusionMoveCard(situation, field);
|
||||
AIVirtualCard actor = situation.Actor;
|
||||
if (actor.TagCollectionContainer.HasTag(AIPlayTagType.FusionMetamorphose))
|
||||
{
|
||||
actor.TagCollectionContainer.FusionMetamorphoseTags.ExecuteMetamorphose(actor, field, field.BestPlayPtn, situation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FusionMoveCard(AIVirtualTargetSelectAction situation, AIVirtualField field)
|
||||
{
|
||||
List<AIVirtualCard> targets = situation.GetSituationTarget(AIScriptTokenArgType.TARGET_SELECT).Targets;
|
||||
bool isAlly = situation.Actor.IsAlly;
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (isAlly)
|
||||
{
|
||||
field.RemoveAllyHandCard(aIVirtualCard);
|
||||
}
|
||||
else
|
||||
{
|
||||
field.RemoveEnemyHandCard(aIVirtualCard);
|
||||
}
|
||||
situation.Actor.FusionIngredients.AddFusionIngredient(aIVirtualCard, field.CurrentTurnCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
SVSim.BattleEngine/Engine/Wizard/AIVirtualRemovalInfo.cs
Normal file
16
SVSim.BattleEngine/Engine/Wizard/AIVirtualRemovalInfo.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIVirtualRemovalInfo
|
||||
{
|
||||
public bool IsFirstTargetSelected;
|
||||
|
||||
public List<AIPlayTag> Tags { get; private set; }
|
||||
|
||||
public AIVirtualRemovalInfo(List<AIPlayTag> tags)
|
||||
{
|
||||
Tags = tags;
|
||||
IsFirstTargetSelected = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIVirtualTurnStartSimulator
|
||||
{
|
||||
public static void TurnStart(AIVirtualTurnStartInfo situation, AIVirtualField field)
|
||||
{
|
||||
if (situation.ActionType != AIOperationType.TURNSTART)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIVirtualTurnStartSimulator:TurnStart() error!! situation is not [TURNSTART] ActionType!!!!!");
|
||||
return;
|
||||
}
|
||||
field.TurnStartFieldProcess(situation);
|
||||
List<AIVirtualCard> whenChangeInplayHolders = field.CardListSet.WhenChangeInplayHolders;
|
||||
if (whenChangeInplayHolders != null)
|
||||
{
|
||||
for (int i = 0; i < whenChangeInplayHolders.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = whenChangeInplayHolders[i];
|
||||
if (!aIVirtualCard.IsDead && aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenChangeInplay))
|
||||
{
|
||||
aIVirtualCard.TagCollectionContainer.ChangeInplayTags.ExecuteWhenTurnStart(aIVirtualCard, field, situation);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<AIVirtualCard> turnStartTagHolders = field.CardListSet.TurnStartTagHolders;
|
||||
if (turnStartTagHolders != null && turnStartTagHolders.Count > 0)
|
||||
{
|
||||
for (int j = 0; j < turnStartTagHolders.Count; j++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard2 = turnStartTagHolders[j];
|
||||
if (!aIVirtualCard2.IsDead && aIVirtualCard2.TagCollectionContainer.HasTagCollection(TagCollectionType.WhenTurnStart))
|
||||
{
|
||||
AIScriptTokenArgType turnStartSide = GetTurnStartSide(aIVirtualCard2, situation);
|
||||
aIVirtualCard2.TagCollectionContainer.TurnStartTags.RegisterConditionPassedTagActions(aIVirtualCard2, situation, turnStartSide);
|
||||
}
|
||||
}
|
||||
}
|
||||
field.TagPreprocessContainer.SimulateAllTurnStartInfo(situation.Actor.IsAlly, situation);
|
||||
situation.ExecuteAllSkillProcess();
|
||||
}
|
||||
|
||||
private static AIScriptTokenArgType GetTurnStartSide(AIVirtualCard owner, AIVirtualTurnStartInfo situation)
|
||||
{
|
||||
if (owner.IsAlly == situation.Actor.IsAlly)
|
||||
{
|
||||
return AIScriptTokenArgType.ALLY;
|
||||
}
|
||||
return AIScriptTokenArgType.OPPONENT;
|
||||
}
|
||||
|
||||
public static void TurnStartFieldProcess(this AIVirtualField field, AIVirtualTurnStartInfo situation)
|
||||
{
|
||||
field.ReverseAllCardIsSelfTurn();
|
||||
field.PlayedCardContainer.ClearInTurn(situation);
|
||||
if (situation.Actor.IsAlly)
|
||||
{
|
||||
field.AllyTurnCount++;
|
||||
field.AllyPpTotal = Math.Min(field.AllyPpTotal + 1, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
field.EnemyTurnCount++;
|
||||
field.EnemyPpTotal = Math.Min(field.EnemyPpTotal + 1, 10);
|
||||
}
|
||||
if (!field.IsLatestActionField)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < field.CardListSet.AllReferableCards.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = field.CardListSet.AllReferableCards[i];
|
||||
if (aIVirtualCard.TagCollectionContainer.HasTagCollection(TagCollectionType.ActivateCount))
|
||||
{
|
||||
bool isOwnerTurn = aIVirtualCard.IsAlly == situation.Actor.IsAlly;
|
||||
aIVirtualCard.TagCollectionContainer.ActivateCountTags.ResetAllCounter(isOwnerTurn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public static class AIWhiteRitualSimulationUtility
|
||||
{
|
||||
public static void SimulateStack(AIVirtualCard stackOwner, AIVirtualField field, AISituationInfo situation, int defaultStack)
|
||||
{
|
||||
int num = defaultStack;
|
||||
List<AIVirtualCard> list = (stackOwner.IsAlly ? field.AllyInplayCards : field.EnemyInplayCards);
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
stackOwner.SetWhiteRitual(num);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = list[i];
|
||||
if (!aIVirtualCard.IsDead && aIVirtualCard.IsAmulet && aIVirtualCard.IsStackWhiteRitual && aIVirtualCard.WhiteRitualCount > 0 && !aIVirtualCard.IsSameCard(stackOwner))
|
||||
{
|
||||
aIVirtualCard.RemoveCard(situation, AIRemovalType.Banish, isFromSkill: true);
|
||||
if (aIVirtualCard.IsDead)
|
||||
{
|
||||
num += aIVirtualCard.WhiteRitualCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
stackOwner.SetWhiteRitual(num);
|
||||
}
|
||||
|
||||
public static bool AddWhiteRitualTargetCard(int count, AIVirtualCard target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
AIConsoleUtility.LogError("AddWhiteRitualTargetCard : target is missing!");
|
||||
return false;
|
||||
}
|
||||
return target.AddWhiteRitual(count);
|
||||
}
|
||||
|
||||
public static void AddWhiteRitualSingle(int count, List<AIVirtualCard> targets)
|
||||
{
|
||||
if (targets == null || targets.Count <= 0)
|
||||
{
|
||||
AIConsoleUtility.LogError("AddWhiteRitualSingle : target is missing!");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = targets[i];
|
||||
if (!aIVirtualCard.IsIndependent && aIVirtualCard.WhiteRitualCount > 0 && AddWhiteRitualTargetCard(count, aIVirtualCard))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AIWhitefrostWhisperLogicArgument : AISelectLogicArgumentBase
|
||||
{
|
||||
private const int WHITEFROST_WHISPER_DAMAGE = 1;
|
||||
|
||||
public override AIScriptTokenArgType LogicType => AIScriptTokenArgType.WHITEFROST_WHISPER_LOGIC;
|
||||
|
||||
public AIWhitefrostWhisperLogicArgument(List<string> args)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override AIVirtualCard SelectSingleTarget(List<AIVirtualCard> candidates, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
float num = float.MinValue;
|
||||
AIVirtualCard result = null;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
AIVirtualCard aIVirtualCard = candidates[i];
|
||||
if (aIVirtualCard.IsDead)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIWhitefrostWhisperLogicArgument.SelectSingleTarget() error!! candidate is already dead!!!!!");
|
||||
continue;
|
||||
}
|
||||
float num2 = ((aIVirtualCard.Life >= aIVirtualCard.MaxLife) ? AIDamageSimulationUtility.GetDamageValueToCertainTarget(aIVirtualCard, 1, situation, playPtn, tagOwner.IsSpell) : ((!aIVirtualCard.IsIndependent && !aIVirtualCard.IsIndestructible) ? AIDestroySimulationUtility.CalcEvalDestroy(aIVirtualCard, playPtn, situation, useIgnoreBreak: false) : 0f));
|
||||
if (num2 > num)
|
||||
{
|
||||
num = num2;
|
||||
result = aIVirtualCard;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override List<AIVirtualCard> SelectMultipleSelectedTargets(List<AIVirtualCard> candidates, int selectCount, AIVirtualCard tagOwner, AIVirtualField field, List<int> playPtn, AISituationInfo situation, AISelectTargetPattern worstOrBest)
|
||||
{
|
||||
AIConsoleUtility.LogError("AIWhitefrostWhisperLogicArgument.SelectMultipleSelectedTargets() error!! Not implemented!!!!!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AbortSoloPlayRecoveryTask : BaseTask
|
||||
{
|
||||
public AbortSoloPlayRecoveryTask()
|
||||
{
|
||||
base.type = ApiType.Type.AbortSoloPlayRecovery;
|
||||
}
|
||||
}
|
||||
73
SVSim.BattleEngine/Engine/Wizard/AcceptAgreementTask.cs
Normal file
73
SVSim.BattleEngine/Engine/Wizard/AcceptAgreementTask.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AcceptAgreementTask : BaseTask
|
||||
{
|
||||
private class Param : BaseParam
|
||||
{
|
||||
public int agreement_type;
|
||||
|
||||
public int agreement_id;
|
||||
}
|
||||
|
||||
public enum Type
|
||||
{
|
||||
TOS = 1,
|
||||
PrivacyPolicy,
|
||||
KorAuthority
|
||||
}
|
||||
|
||||
private Type _agreedType;
|
||||
|
||||
public static int _tosId;
|
||||
|
||||
public static int _privacyPolicyId;
|
||||
|
||||
public static int KorAuthorityId;
|
||||
|
||||
public AcceptAgreementTask()
|
||||
{
|
||||
base.type = ApiType.Type.AcceptAgreement;
|
||||
}
|
||||
|
||||
public void SetParameter(Type agreedType)
|
||||
{
|
||||
_agreedType = agreedType;
|
||||
Param param = new Param();
|
||||
param.agreement_type = (int)agreedType;
|
||||
switch (agreedType)
|
||||
{
|
||||
case Type.TOS:
|
||||
param.agreement_id = _tosId;
|
||||
break;
|
||||
case Type.PrivacyPolicy:
|
||||
param.agreement_id = _privacyPolicyId;
|
||||
break;
|
||||
case Type.KorAuthority:
|
||||
param.agreement_id = KorAuthorityId;
|
||||
break;
|
||||
}
|
||||
base.Params = param;
|
||||
}
|
||||
|
||||
protected override int Parse()
|
||||
{
|
||||
int num = base.Parse();
|
||||
if (num != 1)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
switch (_agreedType)
|
||||
{
|
||||
case Type.TOS:
|
||||
PlayerStaticData._tosAgreementState = PlayerStaticData.AgreementState.Agreed;
|
||||
break;
|
||||
case Type.PrivacyPolicy:
|
||||
PlayerStaticData._privacyPolicyAgreementState = PlayerStaticData.AgreementState.Agreed;
|
||||
break;
|
||||
case Type.KorAuthority:
|
||||
PlayerStaticData.KorAuthorityAgreementState = PlayerStaticData.AgreementState.Agreed;
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class AchievementReceiveRewardTask : BaseTask
|
||||
{
|
||||
public class AchievementReceiveRewardTaskParam : BaseParam
|
||||
{
|
||||
public int achievement_type;
|
||||
|
||||
public int level;
|
||||
}
|
||||
|
||||
public AchievementReceiveRewardTask()
|
||||
{
|
||||
base.type = ApiType.Type.AchievementReceiveReward;
|
||||
}
|
||||
|
||||
public void SetParameter(int achievement_type, int level)
|
||||
{
|
||||
AchievementReceiveRewardTaskParam achievementReceiveRewardTaskParam = new AchievementReceiveRewardTaskParam();
|
||||
achievementReceiveRewardTaskParam.achievement_type = achievement_type;
|
||||
achievementReceiveRewardTaskParam.level = level;
|
||||
base.Params = achievementReceiveRewardTaskParam;
|
||||
}
|
||||
|
||||
protected override int Parse()
|
||||
{
|
||||
int num = base.Parse();
|
||||
if (num != 1)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
Data.MissionInfo.data = new MissionInfoDetail(base.ResponseData["data"]);
|
||||
PlayerStaticData.UpdateHaveUserGoodsNumByJsonData(base.ResponseData["data"]["reward_list"]);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
205
SVSim.BattleEngine/Engine/Wizard/ArenaCommonLobby.cs
Normal file
205
SVSim.BattleEngine/Engine/Wizard/ArenaCommonLobby.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
using Wizard.ErrorDialog;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobby : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private BoxCollider _clickProtectionCollider;
|
||||
|
||||
[SerializeField]
|
||||
private UITexture _charaTexture;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _mainObjectRoot;
|
||||
|
||||
[SerializeField]
|
||||
private ArenaCommonLobbyBattleInfo _battleInfo;
|
||||
|
||||
[SerializeField]
|
||||
private ArenaCommonLobbyTreasureBoxInfo _treasureBoxInfo;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _buttonsRoot;
|
||||
|
||||
[SerializeField]
|
||||
private UIButton _decisionButton;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _decisionButtonLabel;
|
||||
|
||||
private const ResourcesManager.AssetLoadPathType CHARA_TEXTURE_TYPE = ResourcesManager.AssetLoadPathType.ClassCharaBase;
|
||||
|
||||
private const iTween.EaseType MOVE_EASE_TYPE = iTween.EaseType.easeOutExpo;
|
||||
|
||||
private const float CHARA_MOVE_DIST = 4.6875f;
|
||||
|
||||
private const float CHARA_MOVE_TIME = 0.5f;
|
||||
|
||||
private const float MAIN_OBJECT_MOVE_DIST = 2.8125f;
|
||||
|
||||
private const float MAIN_OBJECT_MOVE_TIME = 0.5f;
|
||||
|
||||
private const float MAIN_OBJECT_MOVE_DELAY = 0.2f;
|
||||
|
||||
private const float BUTTON_MOVE_DIST = 1.5625f;
|
||||
|
||||
private const float BUTTON_MOVE_TIME = 0.5f;
|
||||
|
||||
private const float BUTTON_MOVE_DELAY = 0.5f;
|
||||
|
||||
private List<string> _unloadAssetList = new List<string>();
|
||||
|
||||
private GameObject _decisionButtonEffect;
|
||||
|
||||
private bool _isDecisionButtonDark;
|
||||
|
||||
private Vector3 _charaInitPos = Vector3.zero;
|
||||
|
||||
private Vector3 _mainObjectInitPos = Vector3.zero;
|
||||
|
||||
private Vector3 _buttonInitPos = Vector3.zero;
|
||||
|
||||
public BoxCollider ClickProtectionCollider => _clickProtectionCollider;
|
||||
|
||||
public ArenaCommonLobbyTreasureBoxInfo TreasureBoxInfo => _treasureBoxInfo;
|
||||
|
||||
public GameObject ButtonsRoot => _buttonsRoot;
|
||||
|
||||
public bool IsReady { get; private set; }
|
||||
|
||||
public void Init(ArenaCommonLobbyInitParam initParam)
|
||||
{
|
||||
_clickProtectionCollider.gameObject.SetActive(value: false);
|
||||
_charaInitPos = _charaTexture.transform.position;
|
||||
_mainObjectInitPos = _mainObjectRoot.transform.position;
|
||||
_buttonInitPos = _decisionButton.transform.position;
|
||||
_charaTexture.transform.position = _charaInitPos + Vector3.right * 4.6875f;
|
||||
_mainObjectRoot.transform.position = _mainObjectInitPos + Vector3.left * 2.8125f;
|
||||
_decisionButton.transform.position = _buttonInitPos + Vector3.right * 1.5625f;
|
||||
SystemText systemText = Data.SystemText;
|
||||
int num = initParam.BattleResultList.Length;
|
||||
bool battleExists = num < initParam.BattleMaxNum;
|
||||
_decisionButtonLabel.text = (battleExists ? systemText.Get("Arena_0051", (num + 1).ToString()) : systemText.Get("Arena_0027"));
|
||||
UIEventListener.Get(_decisionButton.gameObject).onClick = delegate
|
||||
{
|
||||
if (battleExists && initParam.BattleMaintenanceType.HasValue)
|
||||
{
|
||||
NetworkDefine.MAINTENANCE_TYPE value = initParam.BattleMaintenanceType.Value;
|
||||
if (Data.MaintenanceCodeList.Contains(value))
|
||||
{
|
||||
Wizard.ErrorDialog.Dialog.Create((int)value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
(battleExists ? initParam.BattleButtonClickCallback : initParam.RewardReceiveButtonClickCallback)();
|
||||
};
|
||||
List<string> loadAssetList = new List<string>();
|
||||
List<Action> loadEndCallbackList = new List<Action>();
|
||||
ResourcesManager resMgr = Toolbox.ResourcesManager;
|
||||
string strSkinId = GameMgr.GetIns().GetDataMgr().GetCharaPrmByClassId(initParam.ClassId)
|
||||
.skin_id.ToString();
|
||||
loadAssetList.Add(resMgr.GetAssetTypePath(strSkinId, ResourcesManager.AssetLoadPathType.ClassCharaBase));
|
||||
loadAssetList.Add(resMgr.GetAssetTypePath("cmn_ui_btn_1", ResourcesManager.AssetLoadPathType.Effect2D));
|
||||
ArenaCommonLobbyLoadRequest arenaCommonLobbyLoadRequest = _battleInfo.Init(initParam, _unloadAssetList);
|
||||
loadAssetList.AddRange(arenaCommonLobbyLoadRequest.LoadAssetList);
|
||||
loadEndCallbackList.Add(arenaCommonLobbyLoadRequest.LoadEndCallback);
|
||||
arenaCommonLobbyLoadRequest = _treasureBoxInfo.Init(initParam, _unloadAssetList);
|
||||
loadAssetList.AddRange(arenaCommonLobbyLoadRequest.LoadAssetList);
|
||||
loadEndCallbackList.Add(arenaCommonLobbyLoadRequest.LoadEndCallback);
|
||||
StartCoroutine(resMgr.LoadAssetGroupAsync(loadAssetList, delegate
|
||||
{
|
||||
_unloadAssetList.AddRange(loadAssetList);
|
||||
for (int i = 0; i < loadEndCallbackList.Count; i++)
|
||||
{
|
||||
loadEndCallbackList[i]();
|
||||
}
|
||||
UIManager.GetInstance().AttachAtlas(base.gameObject);
|
||||
_charaTexture.mainTexture = resMgr.LoadObject<Texture>(resMgr.GetAssetTypePath(strSkinId, ResourcesManager.AssetLoadPathType.ClassCharaBase, isfetch: true));
|
||||
_decisionButtonEffect = EffectUtility.CreateEffect2D(new Effect2dCreateParam
|
||||
{
|
||||
Parent = _decisionButton.gameObject,
|
||||
EffectName = "cmn_ui_btn_1",
|
||||
ColorCode = eColorCodeId.DECISION_BTN_2_COLOR,
|
||||
InitActive = !_isDecisionButtonDark,
|
||||
UnloadAssetList = _unloadAssetList
|
||||
});
|
||||
AppearAnimation();
|
||||
IsReady = true;
|
||||
}));
|
||||
}
|
||||
|
||||
public void Final()
|
||||
{
|
||||
Toolbox.ResourcesManager.RemoveAssetGroup(_unloadAssetList);
|
||||
_unloadAssetList.Clear();
|
||||
}
|
||||
|
||||
private void AppearAnimation()
|
||||
{
|
||||
StartCoroutine(AppearAnimationCoroutine());
|
||||
}
|
||||
|
||||
private IEnumerator AppearAnimationCoroutine()
|
||||
{
|
||||
while (UIManager.GetInstance().isFading())
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
GameMgr.GetIns().GetSoundMgr().PlaySe(Se.TYPE.SYS_WINDOW_MOVE);
|
||||
iTween.MoveTo(_charaTexture.gameObject, iTween.Hash("position", _charaInitPos, "time", 0.5f, "islocal", false, "easetype", iTween.EaseType.easeOutExpo));
|
||||
iTween.MoveTo(_mainObjectRoot, iTween.Hash("position", _mainObjectInitPos, "time", 0.5f, "delay", 0.2f, "islocal", false, "easetype", iTween.EaseType.easeOutExpo));
|
||||
iTween.MoveTo(_decisionButton.gameObject, iTween.Hash("position", _buttonInitPos, "time", 0.5f, "delay", 0.5f, "islocal", false, "easetype", iTween.EaseType.easeOutExpo));
|
||||
}
|
||||
|
||||
public void SetDecisionButtonToDark(bool isDark)
|
||||
{
|
||||
UIManager.SetObjectToGrey(_decisionButton.gameObject, isDark);
|
||||
_decisionButtonEffect?.SetActive(!isDark);
|
||||
_isDecisionButtonDark = isDark;
|
||||
}
|
||||
|
||||
public static void GenerateDeckCode(GenerateDeckCodeTask.SubmitDeckType deckType, int classId, int[] cardIdList, int[] phantomCardIdList = null)
|
||||
{
|
||||
GenerateDeckCodeTask generateDeckCodeTask = new GenerateDeckCodeTask();
|
||||
generateDeckCodeTask.SetParameter(classId, deckType, cardIdList, phantomCardIdList);
|
||||
UIManager.GetInstance().StartCoroutine(Toolbox.NetworkManager.Connect(generateDeckCodeTask, delegate
|
||||
{
|
||||
OpenDeckCodeGenerateCompleteDialog();
|
||||
}, null, null, encrypt: false));
|
||||
}
|
||||
|
||||
private static DialogBase OpenDeckCodeGenerateCompleteDialog()
|
||||
{
|
||||
string deckCode = Data.GenerateDeckCode.deck_code;
|
||||
SystemText text = Data.SystemText;
|
||||
DialogBase dialogBase = UIManager.GetInstance().CreateDialogClose();
|
||||
dialogBase.SetSize(DialogBase.Size.S);
|
||||
dialogBase.SetTitleLabel(text.Get("Card_0120"));
|
||||
dialogBase.SetText(text.Get("Card_0128", deckCode));
|
||||
dialogBase.SetButtonLayout(DialogBase.ButtonLayout.BlueBtn_GrayBtn);
|
||||
dialogBase.SetButtonText(text.Get("Card_0133"), text.Get("Common_0008"));
|
||||
dialogBase.onPushButton1 = delegate
|
||||
{
|
||||
NativePluginWrapper.SetStringToClipboard(deckCode);
|
||||
UIManager.GetInstance().CreateConfirmationDialog(text.Get("Card_0132", deckCode));
|
||||
};
|
||||
return dialogBase;
|
||||
}
|
||||
|
||||
public static DialogBase OpenRetireConfirmDialog()
|
||||
{
|
||||
SystemText systemText = Data.SystemText;
|
||||
DialogBase dialogBase = UIManager.GetInstance().CreateDialogClose();
|
||||
dialogBase.SetTitleLabel(systemText.Get("Common_0051"));
|
||||
dialogBase.SetText(systemText.Get("Arena_0026"));
|
||||
dialogBase.SetButtonLayout(DialogBase.ButtonLayout.RedBtn_CancelBtn);
|
||||
dialogBase.SetButtonText(systemText.Get("Dia_Arena_006_Button"));
|
||||
return dialogBase;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobbyBattleInfo : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private UIGrid _battleStateObjectsGrid;
|
||||
|
||||
[SerializeField]
|
||||
private ArenaCommonLobbyBattleStateObject _battleStateObjectOriginal;
|
||||
|
||||
[SerializeField]
|
||||
private UISprite _battleStateObjectsLine;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _winNumLabel;
|
||||
|
||||
public ArenaCommonLobbyLoadRequest Init(ArenaCommonLobbyInitParam initParam, List<string> unloadAssetList)
|
||||
{
|
||||
int maxNum = initParam.BattleMaxNum;
|
||||
bool[] battleResultList = initParam.BattleResultList;
|
||||
int num = battleResultList.Length;
|
||||
ArenaCommonLobbyBattleStateObject[] stateObjectList = new ArenaCommonLobbyBattleStateObject[maxNum];
|
||||
for (int i = 0; i < maxNum; i++)
|
||||
{
|
||||
ArenaCommonLobbyBattleStateObject component = NGUITools.AddChild(_battleStateObjectsGrid.gameObject, _battleStateObjectOriginal.gameObject).GetComponent<ArenaCommonLobbyBattleStateObject>();
|
||||
stateObjectList[i] = component;
|
||||
ArenaCommonLobbyBattleStateObject.eState state = ArenaCommonLobbyBattleStateObject.eState.None;
|
||||
if (i < num)
|
||||
{
|
||||
state = (battleResultList[i] ? ArenaCommonLobbyBattleStateObject.eState.Won : ArenaCommonLobbyBattleStateObject.eState.Lost);
|
||||
}
|
||||
else if (i == num)
|
||||
{
|
||||
state = ArenaCommonLobbyBattleStateObject.eState.Next;
|
||||
}
|
||||
component.ChangeState(state);
|
||||
component.SetTitleText(Data.SystemText.Get("Common_0103", (i + 1).ToString()));
|
||||
}
|
||||
_battleStateObjectsGrid.cellWidth = _battleStateObjectsLine.width / (maxNum - 1);
|
||||
_battleStateObjectsGrid.Reposition();
|
||||
int battleWinNum = initParam.BattleWinNum;
|
||||
_winNumLabel.text = battleWinNum.ToString();
|
||||
ArenaCommonLobbyLoadRequest arenaCommonLobbyLoadRequest = new ArenaCommonLobbyLoadRequest();
|
||||
bool loadExists = false;
|
||||
if (battleWinNum > 0)
|
||||
{
|
||||
arenaCommonLobbyLoadRequest.LoadAssetList.Add(Toolbox.ResourcesManager.GetAssetTypePath("cmn_ui_orb_1", ResourcesManager.AssetLoadPathType.Effect2D));
|
||||
loadExists = true;
|
||||
}
|
||||
if (num - battleWinNum > 0)
|
||||
{
|
||||
arenaCommonLobbyLoadRequest.LoadAssetList.Add(Toolbox.ResourcesManager.GetAssetTypePath("cmn_ui_orb_2", ResourcesManager.AssetLoadPathType.Effect2D));
|
||||
loadExists = true;
|
||||
}
|
||||
arenaCommonLobbyLoadRequest.LoadEndCallback = delegate
|
||||
{
|
||||
if (loadExists)
|
||||
{
|
||||
for (int j = 0; j < maxNum; j++)
|
||||
{
|
||||
ArenaCommonLobbyBattleStateObject arenaCommonLobbyBattleStateObject = stateObjectList[j];
|
||||
bool isWon = arenaCommonLobbyBattleStateObject.IsWon;
|
||||
if (isWon || arenaCommonLobbyBattleStateObject.IsLost)
|
||||
{
|
||||
EffectUtility.CreateEffect2D(new Effect2dCreateParam
|
||||
{
|
||||
Parent = arenaCommonLobbyBattleStateObject.gameObject,
|
||||
EffectName = (isWon ? "cmn_ui_orb_1" : "cmn_ui_orb_2"),
|
||||
ColorCode = (isWon ? eColorCodeId.WIN_ORB_EFFECT_COLOR : eColorCodeId.LOSE_ORB_EFFECT_COLOR),
|
||||
InitActive = true,
|
||||
UnloadAssetList = unloadAssetList
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return arenaCommonLobbyLoadRequest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobbyBattleStateObject : MonoBehaviour
|
||||
{
|
||||
public enum eState
|
||||
{
|
||||
None,
|
||||
Won,
|
||||
Lost,
|
||||
Next,
|
||||
Max
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _nextBattleMark;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _winLabel;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _loseLabel;
|
||||
|
||||
[SerializeField]
|
||||
private UISprite _stateIcon;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _titleLabel;
|
||||
|
||||
private readonly string[] STATE_ICON_SPRITE_NAME_TABLE = new string[4] { "orb_empty", "orb_win", "orb_lose", "orb_empty" };
|
||||
|
||||
private readonly int[] STATE_ICON_SPRITE_SIZE_TABLE = new int[4] { 25, 70, 70, 70 };
|
||||
|
||||
public eState State { get; private set; }
|
||||
|
||||
public bool IsWon => State == eState.Won;
|
||||
|
||||
public bool IsLost => State == eState.Lost;
|
||||
|
||||
public void ChangeState(eState state)
|
||||
{
|
||||
State = state;
|
||||
_nextBattleMark.SetActive(state == eState.Next);
|
||||
_winLabel.gameObject.SetActive(state == eState.Won);
|
||||
_loseLabel.gameObject.SetActive(state == eState.Lost);
|
||||
_stateIcon.spriteName = STATE_ICON_SPRITE_NAME_TABLE[(int)state];
|
||||
UISprite stateIcon = _stateIcon;
|
||||
int width = (_stateIcon.height = STATE_ICON_SPRITE_SIZE_TABLE[(int)state]);
|
||||
stateIcon.width = width;
|
||||
}
|
||||
|
||||
public void SetTitleText(string text)
|
||||
{
|
||||
_titleLabel.text = text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobbyInitParam
|
||||
{
|
||||
public int ClassId { get; set; }
|
||||
|
||||
public int BattleMaxNum { get; set; }
|
||||
|
||||
public int BattleWinNum { get; set; }
|
||||
|
||||
public bool[] BattleResultList { get; set; }
|
||||
|
||||
public Action BattleButtonClickCallback { get; set; }
|
||||
|
||||
public Action RewardReceiveButtonClickCallback { get; set; }
|
||||
|
||||
public NetworkDefine.MAINTENANCE_TYPE? BattleMaintenanceType { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobbyLoadRequest
|
||||
{
|
||||
public List<string> LoadAssetList { get; set; }
|
||||
|
||||
public Action LoadEndCallback { get; set; }
|
||||
|
||||
public ArenaCommonLobbyLoadRequest()
|
||||
{
|
||||
LoadAssetList = new List<string>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaCommonLobbyTreasureBoxInfo : MonoBehaviour
|
||||
{
|
||||
[Header("現在の宝箱")]
|
||||
[SerializeField]
|
||||
private GameObject _nowBoxTitleRoot;
|
||||
|
||||
[SerializeField]
|
||||
private UISprite _nowBoxSprite;
|
||||
|
||||
[SerializeField]
|
||||
private Transform _movePos;
|
||||
|
||||
[Header("次の宝箱")]
|
||||
[SerializeField]
|
||||
private GameObject _nextBoxRoot;
|
||||
|
||||
[SerializeField]
|
||||
private UISprite _nextBoxSprite;
|
||||
|
||||
private const float MOVE_TIME = 0.5f;
|
||||
|
||||
private const float OPEN_ANIMATION_START_TIME = 0.8f;
|
||||
|
||||
private const float OPEN_ANIMATION_TIME = 1.5f;
|
||||
|
||||
private GameObject _openEffect;
|
||||
|
||||
private Vector3 _backupNowBoxPos = Vector3.zero;
|
||||
|
||||
private bool _backupNextBoxRootActive;
|
||||
|
||||
public ArenaCommonLobbyLoadRequest Init(ArenaCommonLobbyInitParam initParam, List<string> unloadAssetList)
|
||||
{
|
||||
int battleWinNum = initParam.BattleWinNum;
|
||||
_nowBoxSprite.spriteName = $"box_2pick_{battleWinNum:D2}_close";
|
||||
bool flag = initParam.BattleResultList.Length < initParam.BattleMaxNum;
|
||||
_nextBoxRoot.SetActive(flag);
|
||||
if (flag)
|
||||
{
|
||||
_nextBoxSprite.spriteName = $"box_2pick_{battleWinNum + 1:D2}_close";
|
||||
}
|
||||
ArenaCommonLobbyLoadRequest arenaCommonLobbyLoadRequest = new ArenaCommonLobbyLoadRequest();
|
||||
string effectName = $"cmn_arena_treasure_{battleWinNum + 1}";
|
||||
arenaCommonLobbyLoadRequest.LoadAssetList.Add(Toolbox.ResourcesManager.GetAssetTypePath(effectName, ResourcesManager.AssetLoadPathType.Effect2D));
|
||||
arenaCommonLobbyLoadRequest.LoadEndCallback = delegate
|
||||
{
|
||||
_openEffect = EffectUtility.CreateEffect2D(new Effect2dCreateParam
|
||||
{
|
||||
Parent = _nowBoxSprite.gameObject,
|
||||
EffectName = effectName,
|
||||
InitActive = false,
|
||||
UnloadAssetList = unloadAssetList
|
||||
});
|
||||
};
|
||||
return arenaCommonLobbyLoadRequest;
|
||||
}
|
||||
|
||||
public void OpenBox(Action animationEndCallback = null)
|
||||
{
|
||||
StartCoroutine(OpenBoxCoroutine(animationEndCallback));
|
||||
}
|
||||
|
||||
private IEnumerator OpenBoxCoroutine(Action animationEndCallback)
|
||||
{
|
||||
GameMgr.GetIns().GetSoundMgr().PlaySe(Se.TYPE.SYS_2PICK_BOX_OPEN);
|
||||
_backupNowBoxPos = _nowBoxSprite.transform.position;
|
||||
_backupNextBoxRootActive = _nextBoxRoot.activeSelf;
|
||||
_nowBoxTitleRoot.SetActive(value: false);
|
||||
_nextBoxRoot.SetActive(value: false);
|
||||
iTween.MoveTo(_nowBoxSprite.gameObject, iTween.Hash("position", _movePos.position, "time", 0.5f, "islocal", false, "easetype", iTween.EaseType.easeOutExpo));
|
||||
yield return new WaitForSeconds(0.8f);
|
||||
_nowBoxSprite.enabled = false;
|
||||
_openEffect.SetActive(value: true);
|
||||
yield return new WaitForSeconds(1.5f);
|
||||
animationEndCallback.Call();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_nowBoxTitleRoot.SetActive(value: true);
|
||||
_nowBoxSprite.enabled = true;
|
||||
_nowBoxSprite.transform.position = _backupNowBoxPos;
|
||||
_nextBoxRoot.SetActive(_backupNextBoxRootActive);
|
||||
_openEffect.SetActive(value: false);
|
||||
}
|
||||
}
|
||||
24
SVSim.BattleEngine/Engine/Wizard/ArenaConfigUpdateTask.cs
Normal file
24
SVSim.BattleEngine/Engine/Wizard/ArenaConfigUpdateTask.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Wizard;
|
||||
|
||||
public class ArenaConfigUpdateTask : BaseTask
|
||||
{
|
||||
public class ArenaConfigUpdateTaskParam : BaseParam
|
||||
{
|
||||
public int use_challenge_two_pick_premium_card;
|
||||
|
||||
public long challenge_two_pick_sleeve_id;
|
||||
}
|
||||
|
||||
public ArenaConfigUpdateTask()
|
||||
{
|
||||
base.type = ApiType.Type.ArenaConfigUpdate;
|
||||
}
|
||||
|
||||
public void SetParameter(bool useChallenge2pickPremiumCard, long useChallenge2pickSleeveId)
|
||||
{
|
||||
ArenaConfigUpdateTaskParam arenaConfigUpdateTaskParam = new ArenaConfigUpdateTaskParam();
|
||||
arenaConfigUpdateTaskParam.use_challenge_two_pick_premium_card = (useChallenge2pickPremiumCard ? 1 : 0);
|
||||
arenaConfigUpdateTaskParam.challenge_two_pick_sleeve_id = useChallenge2pickSleeveId;
|
||||
base.Params = arenaConfigUpdateTaskParam;
|
||||
}
|
||||
}
|
||||
261
SVSim.BattleEngine/Engine/Wizard/AvatarAbilityDetailDialog.cs
Normal file
261
SVSim.BattleEngine/Engine/Wizard/AvatarAbilityDetailDialog.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cute;
|
||||
using UnityEngine;
|
||||
using Wizard.Battle.View;
|
||||
using Wizard.RoomMatch;
|
||||
|
||||
namespace Wizard;
|
||||
|
||||
public class AvatarAbilityDetailDialog : MonoBehaviour
|
||||
{
|
||||
private const int KEYWORD_DIALOG_DEPTH = 20;
|
||||
|
||||
private const int KEYWORD_PANEL_DEPTH = 25;
|
||||
|
||||
private const int TEXT_COLLIDER_HEIGHT_OFFSET = 22;
|
||||
|
||||
private const float PASSIVE_TEXT_OFFSET = 140f;
|
||||
|
||||
private const int DEFAULT_LABEL_HEIGHT = 60;
|
||||
|
||||
[SerializeField]
|
||||
private UITexture _characterTexture;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _characterName;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _characterHBP;
|
||||
|
||||
[SerializeField]
|
||||
private UISprite _classIcon;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _itemRoot;
|
||||
|
||||
[SerializeField]
|
||||
private UILabel _passiveAbilityDescLabel;
|
||||
|
||||
[SerializeField]
|
||||
private List<UILabel> _abilityDescLabel = new List<UILabel>();
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _passiveKeyWordCollider;
|
||||
|
||||
[SerializeField]
|
||||
private List<GameObject> _keyWordCollider = new List<GameObject>();
|
||||
|
||||
[SerializeField]
|
||||
private List<UIWidget> _abilityItemRoot = new List<UIWidget>();
|
||||
|
||||
[SerializeField]
|
||||
private UIWidget _passiveAbilityRoot;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject _thirdUnderLine;
|
||||
|
||||
[SerializeField]
|
||||
private List<UILabel> _costLabel = new List<UILabel>();
|
||||
|
||||
[SerializeField]
|
||||
private List<UILabel> _signLabel = new List<UILabel>();
|
||||
|
||||
[SerializeField]
|
||||
private UIScrollView _scrollView;
|
||||
|
||||
private DeckData _deckData;
|
||||
|
||||
private AvatarBattleInfo _avatarBattleInfo;
|
||||
|
||||
private static DialogBase _avatarAbilityDialog;
|
||||
|
||||
private static DialogBase _keywordDialog;
|
||||
|
||||
private List<string> _loadList = new List<string>();
|
||||
|
||||
public static void Create(AvatarBattleInfo avatarBattleInfo, DeckData deck)
|
||||
{
|
||||
GameObject gameObject = UnityEngine.Object.Instantiate(Resources.Load("UI/layoutParts/AvatarAbilityDetailDialog")) as GameObject;
|
||||
string titleLabel = Data.SystemText.Get("HeroesBattle_0006");
|
||||
_avatarAbilityDialog = UIManager.GetInstance().CreateDialogClose();
|
||||
_avatarAbilityDialog.SetTitleLabel(titleLabel);
|
||||
_avatarAbilityDialog.SetSize(DialogBase.Size.L);
|
||||
_avatarAbilityDialog.SetButtonLayout(DialogBase.ButtonLayout.CloseBtn);
|
||||
_avatarAbilityDialog.SetObj(gameObject);
|
||||
gameObject.GetComponent<AvatarAbilityDetailDialog>().Initialize(avatarBattleInfo, deck);
|
||||
}
|
||||
|
||||
private void Initialize(AvatarBattleInfo avatarBattleInfo, DeckData deck)
|
||||
{
|
||||
_deckData = deck;
|
||||
_avatarBattleInfo = avatarBattleInfo;
|
||||
_itemRoot.SetActive(value: false);
|
||||
RoomBase.StartDialogLoading();
|
||||
UIManager.GetInstance().createInSceneCenterLoading();
|
||||
StartCoroutine(LoadResources(deck.GetSkinId(), delegate
|
||||
{
|
||||
StartCoroutine(SetResources());
|
||||
}));
|
||||
}
|
||||
|
||||
private IEnumerator SetResources()
|
||||
{
|
||||
ClassCharacterMasterData charaPrmByCharaId = GameMgr.GetIns().GetDataMgr().GetCharaPrmByCharaId(_deckData.GetSkinId());
|
||||
InitializeClassCharacter(_deckData.GetSkinId());
|
||||
InitializeDescLabel(_avatarBattleInfo);
|
||||
_characterName.text = charaPrmByCharaId.chara_name;
|
||||
_characterHBP.text = _avatarBattleInfo.Bonus.BattleStartFirstPlayerTurnBp.ToString();
|
||||
ClassCharaPrm.SetClassLabelSetting(_characterName, charaPrmByCharaId.clan);
|
||||
_classIcon.spriteName = ClassCharaPrm.GetIconSpriteName(charaPrmByCharaId.clan);
|
||||
_itemRoot.SetActive(value: true);
|
||||
yield return null;
|
||||
_scrollView.GetComponent<FlexibleGrid>().Reposition();
|
||||
_scrollView.ResetPosition();
|
||||
UIManager.GetInstance().closeInSceneCenterLoading();
|
||||
RoomBase.FinishDiloagLoading();
|
||||
}
|
||||
|
||||
private void InitializeDescLabel(AvatarBattleInfo avatarBattleInfo)
|
||||
{
|
||||
string allAbilityText = avatarBattleInfo.Bonus.PassiveAbilityDesc;
|
||||
string[] abilityDesc = avatarBattleInfo.Bonus.AbilityDesc;
|
||||
foreach (string text in abilityDesc)
|
||||
{
|
||||
allAbilityText += text;
|
||||
}
|
||||
if (avatarBattleInfo.Bonus.PassiveAbilityDesc == string.Empty)
|
||||
{
|
||||
_passiveAbilityRoot.gameObject.SetActive(value: false);
|
||||
_passiveAbilityRoot.transform.localPosition = new Vector3(0f, 140f, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_passiveAbilityDescLabel.SetWrapText(BattleCardBase.ConvertSkillDescriptionText(avatarBattleInfo.Bonus.PassiveAbilityDesc));
|
||||
UIEventListener.Get(_passiveAbilityDescLabel.gameObject).onClick = delegate
|
||||
{
|
||||
OnClickDescLabel(allAbilityText, _passiveAbilityDescLabel);
|
||||
};
|
||||
UIEventListener.Get(_passiveKeyWordCollider).onPress = delegate(GameObject g, bool b)
|
||||
{
|
||||
BattlePlayerView.PressKeyWordColorChange(_passiveAbilityDescLabel, b);
|
||||
};
|
||||
UIEventListener.Get(_passiveKeyWordCollider).onDragStart = delegate
|
||||
{
|
||||
BattlePlayerView.SetKeyWordLabelColor(_passiveAbilityDescLabel);
|
||||
};
|
||||
_passiveAbilityRoot.height = _passiveAbilityDescLabel.height;
|
||||
_passiveAbilityDescLabel.GetComponent<BoxCollider>().size = new Vector3(_passiveAbilityRoot.localSize.x, _passiveAbilityRoot.localSize.y + 22f, 0f);
|
||||
}
|
||||
if (avatarBattleInfo.Bonus.AbilityCosts.Length < 3 || avatarBattleInfo.Bonus.AbilityDesc.Length < 3)
|
||||
{
|
||||
_abilityItemRoot[2].gameObject.SetActive(value: false);
|
||||
_thirdUnderLine.SetActive(value: false);
|
||||
}
|
||||
for (int num = 0; num < avatarBattleInfo.Bonus.AbilityDesc.Length; num++)
|
||||
{
|
||||
int textNum = num;
|
||||
_abilityDescLabel[textNum].SetWrapText(BattleCardBase.ConvertSkillDescriptionText(avatarBattleInfo.Bonus.AbilityDesc[textNum]));
|
||||
UIEventListener.Get(_abilityDescLabel[textNum].gameObject).onClick = delegate
|
||||
{
|
||||
OnClickDescLabel(allAbilityText, _abilityDescLabel[textNum]);
|
||||
};
|
||||
UIEventListener.Get(_keyWordCollider[textNum]).onPress = delegate(GameObject g, bool b)
|
||||
{
|
||||
BattlePlayerView.PressKeyWordColorChange(_abilityDescLabel[textNum], b);
|
||||
};
|
||||
UIEventListener.Get(_keyWordCollider[textNum]).onDragStart = delegate
|
||||
{
|
||||
BattlePlayerView.SetKeyWordLabelColor(_abilityDescLabel[textNum]);
|
||||
};
|
||||
_abilityItemRoot[textNum].height = 60;
|
||||
if (_abilityItemRoot[textNum].height < _abilityDescLabel[textNum].height)
|
||||
{
|
||||
_abilityItemRoot[textNum].height = _abilityDescLabel[textNum].height;
|
||||
}
|
||||
_abilityDescLabel[textNum].GetComponent<BoxCollider>().size = new Vector3(_abilityItemRoot[textNum].localSize.x, _abilityItemRoot[textNum].localSize.y + 22f, 0f);
|
||||
_abilityDescLabel[textNum].GetComponent<BoxCollider>().center = new Vector3(-22f, 0f, 0f);
|
||||
if (!int.TryParse(avatarBattleInfo.Bonus.AbilityCosts[textNum], out var result))
|
||||
{
|
||||
_signLabel[textNum].text = "-";
|
||||
_costLabel[textNum].text = "X";
|
||||
}
|
||||
else if (result != 0)
|
||||
{
|
||||
_signLabel[textNum].text = ((result < 0) ? "-" : "+");
|
||||
_costLabel[textNum].text = Mathf.Abs(result).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
_signLabel[textNum].text = string.Empty;
|
||||
_costLabel[textNum].text = "0";
|
||||
_costLabel[textNum].transform.localPosition = new Vector3(0f, 2f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClickDescLabel(string abilityText, UILabel textLabel)
|
||||
{
|
||||
if (HasKeyword(abilityText))
|
||||
{
|
||||
GameMgr.GetIns().GetSoundMgr().PlaySe(Se.TYPE.SYS_COMMON_BUTTON);
|
||||
IList<string> keywords = BattleKeywordInfoListMgr.GetKeywords(abilityText);
|
||||
_keywordDialog = BattlePlayerView.CreateKeyPanel(textLabel, keywords, CardMaster.CardMasterId.Default);
|
||||
_keywordDialog.SetPanelDepth(20, isSetBackViewDepthImmediately: true);
|
||||
_keywordDialog.GetComponentInChildren<BattleKeywordInfoListMgr>().SetPanelDepth(25);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasKeyword(string skillText)
|
||||
{
|
||||
IList<string> keywords = BattleKeywordInfoListMgr.GetKeywords(skillText);
|
||||
bool result = false;
|
||||
foreach (string item in keywords)
|
||||
{
|
||||
if (Data.Master.BattleKeyWordDic.ContainsKey(item))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Toolbox.ResourcesManager.RemoveAssetGroup(_loadList);
|
||||
_loadList.Clear();
|
||||
}
|
||||
|
||||
public static bool LiveDialog()
|
||||
{
|
||||
return _avatarAbilityDialog != null;
|
||||
}
|
||||
|
||||
public static void CloseDialog()
|
||||
{
|
||||
_avatarAbilityDialog.Close();
|
||||
if (_keywordDialog != null)
|
||||
{
|
||||
_keywordDialog.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LoadResources(int skinId, Action callBack)
|
||||
{
|
||||
_loadList.Add(GetCharacterTexturePath(skinId, isFetch: false));
|
||||
yield return StartCoroutine(Toolbox.ResourcesManager.LoadAssetGroupAsync(_loadList, null));
|
||||
callBack.Call();
|
||||
}
|
||||
|
||||
private string GetCharacterTexturePath(int skinId, bool isFetch)
|
||||
{
|
||||
return Toolbox.ResourcesManager.GetAssetTypePath(skinId.ToString("00"), ResourcesManager.AssetLoadPathType.ClassCharaSkinThumbnail, isFetch);
|
||||
}
|
||||
|
||||
private void InitializeClassCharacter(int skinId)
|
||||
{
|
||||
_characterTexture.mainTexture = Toolbox.ResourcesManager.LoadObject(GetCharacterTexturePath(skinId, isFetch: true)) as Texture;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user