Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/AITimeOverAttackSimulator.cs
gamer147 957af3d1ec feat(battle-engine): full Unity/VFX/god-object shims + expanded copy closure (2570 files)
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.
2026-06-05 17:22:20 -04:00

302 lines
8.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cute;
using UnityEngine;
namespace Wizard;
public class AITimeOverAttackSimulator : IBattleSimulationAI
{
private const int NONE_EVOLVE_INDEX = -1;
private AIRuleBaseBattleSimulator _ruleBaseSimulator;
private SimulationResult _bestResult;
private int _originalFieldInplayCount;
private ulong[] _defaultPlayptnHashArray;
private SimulationAdditionalActionInfoSet _simAdditionalOptions;
public AIVirtualField Cr_MaxField
{
get
{
if (_bestResult == null)
{
return null;
}
return _bestResult.BestResultField;
}
}
public float Cr_MaxFieldValue
{
get
{
if (_bestResult == null)
{
return 0f;
}
return _bestResult.MaxFieldValue;
}
}
public float Cr_MaxFieldValueAtSelfTurnEnd
{
get
{
if (_bestResult == null)
{
return 0f;
}
return _bestResult.MaxFieldValueAtSelfTurnEnd;
}
}
public List<AIVirtualActionInfo> Cr_MaxActionInfoSequence => _bestResult.ActionSequence;
public PlayPtnWithToken Cr_BestPlayPtnWithToken { get; private set; }
public AIVirtualActionInfo Cr_FirstActionInfo { get; private set; }
public IEnumerator _CrSimulate(AIVirtualField originalField, bool doesUseEvo, bool checkTimeOverLogic, PlayPtnWithToken[] bestPlayPtnWithToken = null, SimulationAdditionalActionInfoSet additionalActions = null)
{
originalField.AI.IsInVirutalSimulation = true;
_ruleBaseSimulator = new AIRuleBaseBattleSimulator(originalField.AI, bestPlayPtnWithToken, canChangeToTimeOverLogic: true);
_bestResult = new SimulationResult();
_originalFieldInplayCount = originalField.AllyInplayCards.Count((AIVirtualCard c) => !c.IsDead);
_defaultPlayptnHashArray = AISimulationUtility.CalculatePlayptnWithTokenHashs(originalField, bestPlayPtnWithToken);
_simAdditionalOptions = additionalActions;
ParallelJob job = ParallelJob.Dispatch(delegate
{
try
{
AIVirtualField field = new AIVirtualField(originalField);
int[] attackerIdxList = SortByOneAttackBreak(field);
if (additionalActions != null)
{
_ = additionalActions.ForceEvoAction;
}
SimulateEvoPatternBattle(field, attackerIdxList, doesUseEvo);
if (bestPlayPtnWithToken != null && Cr_MaxField != null)
{
int num = Cr_MaxField.AllyInplayCards.Count((AIVirtualCard c) => !c.IsDead);
int num2 = Mathf.Min(Mathf.Max(0, _originalFieldInplayCount - num), bestPlayPtnWithToken.Length - 1);
Cr_BestPlayPtnWithToken = null;
for (int num3 = num2; num3 >= 0; num3--)
{
if (bestPlayPtnWithToken[num3] != null)
{
Cr_BestPlayPtnWithToken = bestPlayPtnWithToken[num3];
break;
}
}
}
}
catch (Exception)
{
}
});
while (!job.isDone)
{
yield return null;
}
if (Cr_MaxField != null)
{
Cr_FirstActionInfo = BattleSequencer.GetFirstActionInfo(_bestResult.ActionSequence, Cr_MaxField, Cr_MaxField.BestPlayPtn);
}
originalField.AI.IsInVirutalSimulation = false;
}
private int[] SortByOneAttackBreak(AIVirtualField field)
{
List<int> sortedAttackerIndexList = GetSortedAttackerIndexList(field);
int num = ((field.EnemyInplayCards != null) ? field.EnemyInplayCards.Count : 0);
if (num == 0)
{
return sortedAttackerIndexList.ToArray();
}
List<int> list = new List<int>();
List<int> list2 = new List<int>();
List<int> list3 = new List<int>(sortedAttackerIndexList);
for (int i = 0; i < sortedAttackerIndexList.Count; i++)
{
int num2 = 0;
bool flag = false;
int num3 = 0;
for (int j = 0; j < num; j++)
{
AIVirtualCard aIVirtualCard = field.AllyInplayCards[sortedAttackerIndexList[i]];
AIVirtualCard aIVirtualCard2 = field.EnemyInplayCards[j];
if (!aIVirtualCard2.IsUnit)
{
continue;
}
int num4 = aIVirtualCard2.SimulateDamageAmount(aIVirtualCard.Attack);
if (aIVirtualCard2.Life <= num4)
{
num2++;
if (!flag)
{
flag = aIVirtualCard2.IsBreakFirst(field.BestPlayPtn);
}
if (aIVirtualCard2.IsBreakLast(field.BestPlayPtn))
{
num3++;
}
break;
}
}
if (num2 > 0 && flag)
{
int item = sortedAttackerIndexList[i];
list.Add(item);
list3.Remove(item);
}
else if (num2 == 0 || (num2 > 0 && num3 == num2))
{
int item2 = sortedAttackerIndexList[i];
list2.Add(item2);
list3.Remove(item2);
}
}
list.AddRange(list3);
list.AddRange(list2);
return list.ToArray();
}
private void SimulateEvoPatternBattle(AIVirtualField field, int[] attackerIdxList, bool useEve)
{
List<int> sortedAttackTargetIndexList = GetSortedAttackTargetIndexList(field);
if (((_simAdditionalOptions != null) ? _simAdditionalOptions.ForceEvoAction : null) != null)
{
SimulateTargetsBreakPattern(field, attackerIdxList, -1, sortedAttackTargetIndexList);
return;
}
int num = (useEve ? field.AllyInplayCards.Count : 0);
for (int i = -1; i < num; i++)
{
if (AISimulationUtility.IsValuableEvoIndex(i, field))
{
SimulateTargetsBreakPattern(field, attackerIdxList, i, sortedAttackTargetIndexList);
}
}
}
private void SimulateTargetsBreakPattern(AIVirtualField field, int[] attackrIndecies, int evoIndex, List<int> enemyAllTargets)
{
List<ulong> list = new List<ulong>();
List<int> list2 = new List<int>();
_ruleBaseSimulator.RunSequence(field, attackrIndecies, evoIndex, new List<int>(), _bestResult, _simAdditionalOptions, null, checkActFailure: false);
list.Add(AISimulationUtility.CalculateTargetSequenceHash(list2.ToArray(), field));
int num = enemyAllTargets.Count;
while (num > 0 && !field.AI.IsBattleEnd)
{
int[] patternGroup = AISimulationUtility.GetPatternGroup(num);
if (patternGroup != null)
{
for (int i = 0; i < patternGroup.Length; i++)
{
List<int> enemyTargets = AISimulationUtility.GetEnemyTargets(field.EnemyInplayCards, enemyAllTargets, patternGroup[i], field.BestPlayPtn);
ulong item = AISimulationUtility.CalculateTargetSequenceHash(enemyTargets.ToArray(), field);
if (!list.Contains(item))
{
AIOneMoreLastwordUtility.SortEnemyTargetByBreakBonus(field, enemyTargets);
if (!AISimulationUtility.IsValidEnemyTargetIndexes(field.EnemyInplayCards, enemyTargets))
{
return;
}
_ruleBaseSimulator.RunSequence(field, attackrIndecies, evoIndex, enemyTargets, _bestResult, _simAdditionalOptions, null, checkActFailure: false);
list.Add(item);
}
}
}
num--;
}
}
private List<int> GetSortedAttackerIndexList(AIVirtualField field)
{
List<int> list = new List<int>();
List<bool> list2 = new List<bool>();
List<AIVirtualCard> allyInplayCards = field.AllyInplayCards;
for (int i = 0; i < allyInplayCards.Count; i++)
{
list2.Add(AIAttackSimulationUtility.IsAttackPossible(field, allyInplayCards[i].AttackLeaderSituation));
}
for (int j = 0; j < allyInplayCards.Count; j++)
{
AIVirtualCard aIVirtualCard = allyInplayCards[j];
if (!aIVirtualCard.IsUnit)
{
continue;
}
int num = -1;
for (int k = 0; k < list.Count; k++)
{
int index = list[k];
AIVirtualCard aIVirtualCard2 = allyInplayCards[index];
if (aIVirtualCard.Attack < aIVirtualCard2.Attack)
{
num = k;
break;
}
if (aIVirtualCard.Attack == aIVirtualCard2.Attack && (!list2[j] || list2[index]) && ((!list2[j] && list2[index]) || aIVirtualCard.Life < aIVirtualCard2.Life))
{
num = k;
break;
}
}
if (num >= 0 && num < list.Count)
{
list.Insert(num, j);
}
else
{
list.Add(j);
}
}
return list;
}
private List<int> GetSortedAttackTargetIndexList(AIVirtualField field)
{
List<int> list = new List<int>();
List<int> list2 = new List<int>();
List<AIVirtualCard> enemyInplayCards = field.EnemyInplayCards;
for (int i = 0; i < enemyInplayCards.Count; i++)
{
AIVirtualCard aIVirtualCard = enemyInplayCards[i];
if (!aIVirtualCard.IsUnit)
{
continue;
}
int num = -1;
List<int> list3 = (aIVirtualCard.IsGuard ? list2 : list);
for (int j = 0; j < list3.Count; j++)
{
AIVirtualCard aIVirtualCard2 = enemyInplayCards[list3[j]];
if (aIVirtualCard.Life < aIVirtualCard2.Life || (aIVirtualCard.Life == aIVirtualCard2.Life && aIVirtualCard.Attack > aIVirtualCard2.Attack))
{
num = j;
break;
}
}
if (num >= 0 && num < list3.Count)
{
list3.Insert(num, i);
}
else
{
list3.Add(i);
}
}
list2.AddRange(list);
return list2;
}
}