Authored Unity primitive/object-model shim, VFX layer (control-flow-preserving, InstantVfx never invokes its action -- headless suppression), god-object stubs (GameMgr/EffectMgr/UIManager with faithfully-extracted nested enums), View/UI/Touch tree, LitJson+BetterList+Tuple copied, third-party stubs. Discovered Roslyn header-error masking: fixing class-header type errors unmasks body references, so the true copy closure is ~2570 files (was 782 under masking). Errors: masked-25720 -> 268; our shim files compile clean. Remaining: ~50 residual shim/external types, 24 NGUI UI-base overrides, static-type fixes, plus likely 1-2 more unmask waves.
306 lines
10 KiB
C#
306 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Wizard;
|
|
|
|
public static class BattleSequencer
|
|
{
|
|
public static void ExecSimulation(AIVirtualField field, List<AIVirtualActionInfo> actionInfoSequence, List<AIVirtualCard> enemyTargetSequence, SimulationSetting setting)
|
|
{
|
|
AIVirtualActionInfo aIVirtualActionInfo = actionInfoSequence.FirstOrDefault((AIVirtualActionInfo a) => a.ActionType == AIOperationType.EVOLVE);
|
|
AIVirtualActionInfo aIVirtualActionInfo2 = null;
|
|
while (actionInfoSequence.Any((AIVirtualActionInfo a) => !a.IsAlreadyUsed))
|
|
{
|
|
field.EnemyTokenQueue.Clear();
|
|
int num = -1;
|
|
for (int num2 = 0; num2 < actionInfoSequence.Count; num2++)
|
|
{
|
|
AIVirtualActionInfo aIVirtualActionInfo3 = actionInfoSequence[num2];
|
|
if (!aIVirtualActionInfo3.IsAlreadyUsed)
|
|
{
|
|
aIVirtualActionInfo2 = aIVirtualActionInfo3;
|
|
num = num2;
|
|
break;
|
|
}
|
|
}
|
|
if (aIVirtualActionInfo2 != null)
|
|
{
|
|
if (aIVirtualActionInfo2 == aIVirtualActionInfo)
|
|
{
|
|
aIVirtualActionInfo = null;
|
|
}
|
|
bool flag = AISimulationUtility.ExecuteVirtualAction(aIVirtualActionInfo2, aIVirtualActionInfo, enemyTargetSequence, setting);
|
|
if (num == 0 && !flag && setting.CheckFirstActionFailure)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if (field.EnemyClass.IsDead || field.AllyClass.IsDead)
|
|
{
|
|
return;
|
|
}
|
|
List<int> bestPlayPtn = field.BestPlayPtn;
|
|
for (int num3 = 0; num3 < field.AllyInplayCards.Count; num3++)
|
|
{
|
|
AIVirtualCard aIVirtualCard = field.AllyInplayCards[num3];
|
|
if (!aIVirtualCard.IsAttackable(bestPlayPtn))
|
|
{
|
|
continue;
|
|
}
|
|
bool flag2 = false;
|
|
for (int num4 = 0; num4 < actionInfoSequence.Count; num4++)
|
|
{
|
|
if (actionInfoSequence[num4].Actor.CardIndex == aIVirtualCard.CardIndex)
|
|
{
|
|
flag2 = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag2)
|
|
{
|
|
actionInfoSequence.Insert(num + 1, new AIVirtualAttackInfo(aIVirtualCard, isAttackFollower: true, aIVirtualActionInfo2));
|
|
}
|
|
}
|
|
while (field.EnemyTokenQueue.Count > 0)
|
|
{
|
|
Tuple<AIVirtualCard, AIVirtualCard> tuple = field.EnemyTokenQueue.Dequeue();
|
|
AIVirtualCard first = tuple.first;
|
|
AIVirtualCard second = tuple.second;
|
|
int num5 = enemyTargetSequence.IndexOf(first);
|
|
if (num5 >= 0 && (IsToBeKilled(field) || second.IsGuard))
|
|
{
|
|
enemyTargetSequence.Insert(num5 + 1, second);
|
|
if (first.IsMetamorphosed)
|
|
{
|
|
enemyTargetSequence.Remove(first);
|
|
}
|
|
}
|
|
}
|
|
if (aIVirtualActionInfo2 != null && aIVirtualActionInfo2 is AIVirtualAttackInfo { IsAttackSuccessed: not false } && field.AllyInplayCards.Count((AIVirtualCard card) => !card.IsDead) < 5 && aIVirtualActionInfo2.Actor.TagCollectionContainer.HasTag(AIPlayTagType.PuppetAttack))
|
|
{
|
|
aIVirtualActionInfo2.Actor.TagCollectionContainer.PuppetAttackTags.ExecutePuppetAttack(aIVirtualActionInfo2.Actor, aIVirtualActionInfo2, actionInfoSequence);
|
|
}
|
|
}
|
|
field.CallAfterLeaderAttackSimulation();
|
|
}
|
|
|
|
public static AIVirtualCard FindAttackTarget(AIVirtualField field, AIVirtualAttackInfo attack, List<AIVirtualCard> enemyTargetSequence, AIVirtualActionInfo evolutionInfo, bool isHandAllRemovalValid, bool isNoSkipAttack, bool isAttackFollower)
|
|
{
|
|
AIVirtualCard aIVirtualCard = null;
|
|
if (isAttackFollower)
|
|
{
|
|
for (int i = 0; i < enemyTargetSequence.Count; i++)
|
|
{
|
|
AIVirtualCard aIVirtualCard2 = enemyTargetSequence[i];
|
|
attack.SetAttackTarget(aIVirtualCard2);
|
|
if (AIAttackSimulationUtility.IsAttackPossible(field, attack))
|
|
{
|
|
AIVirtualCard nextTarget = ((enemyTargetSequence.Count > i + 1) ? enemyTargetSequence[i + 1] : field.EnemyClass);
|
|
if (isNoSkipAttack || !IsSkipAttack(field, attack, nextTarget, evolutionInfo, isHandAllRemovalValid))
|
|
{
|
|
aIVirtualCard = aIVirtualCard2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (aIVirtualCard == null)
|
|
{
|
|
attack.SetAttackTarget(field.EnemyClass);
|
|
if (AIAttackSimulationUtility.IsAttackPossible(field, attack))
|
|
{
|
|
aIVirtualCard = field.EnemyClass;
|
|
}
|
|
else
|
|
{
|
|
attack.SetAttackTarget(null);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
attack.SetAttackTarget(aIVirtualCard);
|
|
}
|
|
return aIVirtualCard;
|
|
}
|
|
|
|
private static bool IsSkipAttack(AIVirtualField field, AIVirtualAttackInfo situation, AIVirtualCard nextTarget, AIVirtualActionInfo evolutionInfo, bool isHandAllRemovalValid)
|
|
{
|
|
AIVirtualCard actor = situation.Actor;
|
|
AIVirtualCard attackTarget = situation.AttackTarget;
|
|
if (!attackTarget.IsGuard && AISimulationRemovalUtility.WillDieBySkillPrediction(attackTarget, field, field.BestPlayPtn, situation, isHandAllRemovalValid))
|
|
{
|
|
return true;
|
|
}
|
|
if (evolutionInfo != null && !attackTarget.IsGuard && !attackTarget.IsIndependent && !attackTarget.IsIndestructible && field.CheckDestroyByEvoTags(evolutionInfo, attackTarget))
|
|
{
|
|
return true;
|
|
}
|
|
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(actor, nextTarget);
|
|
if (!attackTarget.IsGuard && !attackTarget.IsIndependent && aIVirtualAttackInfo.WillTargetDestroyByAttackTags(field, field.BestPlayPtn, attackTarget))
|
|
{
|
|
return true;
|
|
}
|
|
if (situation.WillTargetDestroyByAttackTags(field, field.BestPlayPtn, attackTarget))
|
|
{
|
|
return true;
|
|
}
|
|
if (situation.WillAnyOtherAttackerDestroyed(field, field.BestPlayPtn))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static void OnAfterExecuteAttackCommon(AIVirtualField field, AIVirtualTurnEndInfo turnEndSituation, ref List<AIVirtualActionInfo> moves, bool isAttackToLeaderAgain = false)
|
|
{
|
|
if (moves == null || moves.Count <= 0)
|
|
{
|
|
AIConsoleUtility.LogError("OnAfterExecuteAttackCommon error!! moves is empty!!!!!");
|
|
return;
|
|
}
|
|
List<AIVirtualCard> beforeCards = new List<AIVirtualCard>(field.AllyInplayCards);
|
|
AIPlayCardSimulationUtility.ExecuteRestPlayPtnAfterAttack(field, ref moves);
|
|
if (isAttackToLeaderAgain)
|
|
{
|
|
AttackToLeaderByNewInplayCards(field, beforeCards);
|
|
}
|
|
ProcessAllyTurnEndToOpponentTurnStart(field, turnEndSituation);
|
|
}
|
|
|
|
public static void ProcessAllyTurnEndToOpponentTurnStart(AIVirtualField field, AIVirtualTurnEndInfo turnEndSituation)
|
|
{
|
|
AIVirtualTurnEndSimulator.TurnEnd(turnEndSituation, field);
|
|
AIVirtualTurnStartInfo situation = new AIVirtualTurnStartInfo(field.EnemyClass);
|
|
AIVirtualTurnStartSimulator.TurnStart(situation, field);
|
|
field.DrawCard(isAlly: false, 1, EnemyAI.EmptyPlayPtn, situation);
|
|
}
|
|
|
|
private static void AttackToLeaderByNewInplayCards(AIVirtualField currentField, List<AIVirtualCard> beforeCards)
|
|
{
|
|
if (currentField.AllyInplayCards.Count <= beforeCards.Count)
|
|
{
|
|
return;
|
|
}
|
|
AIVirtualCard enemyClass = currentField.EnemyClass;
|
|
int actionLength = currentField.ActionLength;
|
|
for (int i = beforeCards.Count; i < currentField.AllyInplayCards.Count; i++)
|
|
{
|
|
AIVirtualAttackInfo aIVirtualAttackInfo = new AIVirtualAttackInfo(currentField.AllyInplayCards[i], enemyClass);
|
|
if (AIAttackSimulationUtility.IsAttackPossible(currentField, aIVirtualAttackInfo))
|
|
{
|
|
bool isAttackerUsed = false;
|
|
AIAttackSimulationUtility.SimulateAttackIfValuable(aIVirtualAttackInfo, currentField, useAttackLeaderPreCheck: false, ref isAttackerUsed);
|
|
if (enemyClass.IsDead)
|
|
{
|
|
currentField.ActionLength -= actionLength;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool IsToBeKilled(AIVirtualField field)
|
|
{
|
|
int life = field.AllyClass.Life;
|
|
int num = field.GetInplayAttackSumToLeader(isAlly: false);
|
|
if (field.AI.OPPONENT.IsEvolve)
|
|
{
|
|
num += field.EnemyInplayCards.Max((AIVirtualCard card) => card.EvolutionAttack - card.Attack);
|
|
}
|
|
return num - life >= 0;
|
|
}
|
|
|
|
public static AIVirtualActionInfo GetFirstActionInfo(List<AIVirtualActionInfo> actionInfoSequence, AIVirtualField field, List<int> playPtn)
|
|
{
|
|
AIVirtualActionInfo aIVirtualActionInfo = null;
|
|
int num = 0;
|
|
while (num < actionInfoSequence.Count)
|
|
{
|
|
AIVirtualActionInfo aIVirtualActionInfo2 = actionInfoSequence[num];
|
|
int nextIndexInFindingFirstAction = GetNextIndexInFindingFirstAction(actionInfoSequence, aIVirtualActionInfo2, num);
|
|
if (aIVirtualActionInfo2.ActionType == AIOperationType.PLAY || aIVirtualActionInfo2.ActionType == AIOperationType.TURNEND)
|
|
{
|
|
aIVirtualActionInfo = aIVirtualActionInfo2;
|
|
break;
|
|
}
|
|
AIVirtualCard actor = aIVirtualActionInfo2.Actor;
|
|
List<AIVirtualCard> list = (actor.IsAlly ? field.AllyInplayCards : field.EnemyInplayCards);
|
|
bool flag = false;
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
AIVirtualCard aIVirtualCard = list[i];
|
|
if (actor.CardIndex == aIVirtualCard.CardIndex)
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
num = nextIndexInFindingFirstAction;
|
|
continue;
|
|
}
|
|
if (aIVirtualActionInfo2.ActionType == AIOperationType.EVOLVE)
|
|
{
|
|
aIVirtualActionInfo = aIVirtualActionInfo2;
|
|
break;
|
|
}
|
|
if (aIVirtualActionInfo2.ActionType == AIOperationType.ATTACK)
|
|
{
|
|
if (!(aIVirtualActionInfo2 is AIVirtualAttackInfo { AttackTarget: var attackTarget } aIVirtualAttackInfo))
|
|
{
|
|
AIConsoleUtility.LogError("GetFirstAction() error!! candidate is not virtualAttackInfo");
|
|
continue;
|
|
}
|
|
if (attackTarget == null)
|
|
{
|
|
num = nextIndexInFindingFirstAction;
|
|
continue;
|
|
}
|
|
if (!aIVirtualAttackInfo.IsAttackSuccessed)
|
|
{
|
|
num = nextIndexInFindingFirstAction;
|
|
continue;
|
|
}
|
|
if (attackTarget.IsBreakLast(playPtn) && !attackTarget.IsGuard)
|
|
{
|
|
if (aIVirtualActionInfo == null)
|
|
{
|
|
aIVirtualActionInfo = aIVirtualActionInfo2;
|
|
}
|
|
num = nextIndexInFindingFirstAction;
|
|
continue;
|
|
}
|
|
List<AIVirtualCard> list2 = (attackTarget.IsAlly ? field.CardListSet.AllyClassAndInplayCards : field.CardListSet.EnemyClassAndInplayCards);
|
|
bool flag2 = false;
|
|
for (int j = 0; j < list2.Count; j++)
|
|
{
|
|
AIVirtualCard aIVirtualCard2 = list2[j];
|
|
if (attackTarget.CardIndex == aIVirtualCard2.CardIndex)
|
|
{
|
|
flag2 = true;
|
|
break;
|
|
}
|
|
}
|
|
if (flag2)
|
|
{
|
|
aIVirtualActionInfo = aIVirtualActionInfo2;
|
|
break;
|
|
}
|
|
}
|
|
num = nextIndexInFindingFirstAction;
|
|
}
|
|
return aIVirtualActionInfo;
|
|
}
|
|
|
|
private static int GetNextIndexInFindingFirstAction(List<AIVirtualActionInfo> actionInfoSequence, AIVirtualActionInfo candidate, int currentIndex)
|
|
{
|
|
int result = currentIndex + 1;
|
|
for (int i = currentIndex + 1; i < actionInfoSequence.Count && actionInfoSequence[i].PremiseAction == candidate; i++)
|
|
{
|
|
result = i;
|
|
}
|
|
return result;
|
|
}
|
|
}
|