using System.Collections.Generic; namespace Wizard; public static class AIAttackSimulationUtility { public static bool IsUsePreCheckBuff(AIPlayTag tag, AIVirtualAttackInfo situation) { if (!situation.IsUsePreCheck || tag.Type != AIPlayTagType.AttackBuff) { return false; } AIAttackPreCheckInformation preCheckInformation = situation.PreCheckInformation; if (preCheckInformation.HasBuffInfo) { return preCheckInformation.HasPreCheckBuffInfo(tag); } return false; } public static void SimulateAttackIfValuable(AIVirtualAttackInfo situation, AIVirtualField field, bool useAttackLeaderPreCheck, ref bool isAttackerUsed) { AIVirtualCard actor = situation.Actor; AIVirtualCard attackTarget = situation.AttackTarget; situation.IsAttackSuccessed = false; AIVirtualCard allyClass = field.AllyClass; int attackDamageToCertainCard = AIAttackTagSimulator.GetAttackDamageToCertainCard(field, situation, allyClass); if (field.AllyClass.SimulateDamageAmount(attackDamageToCertainCard, isSkillDamage: true) >= allyClass.Life) { isAttackerUsed = true; return; } if (AIDiscardUtility.CheckAttackDiscardTargetInPlayPtn(actor.SelfField, field.BestPlayPtn, situation)) { isAttackerUsed = true; return; } if (attackTarget.IsLeader) { int attackDamageToCertainCard2 = AIAttackTagSimulator.GetAttackDamageToCertainCard(field, situation, actor); AISimulationBuffInfoCollection buffInfoListWhenCertainAttack = AIAttackTagSimulator.GetBuffInfoListWhenCertainAttack(field, situation); float attackBonus = actor.GetAttackBonus(field.BestPlayPtn, situation); AISimulationBuffInfo buffInfo = buffInfoListWhenCertainAttack?.GetBuffInfoToCertainCard(actor); if (useAttackLeaderPreCheck && !IsExecuteAttackValuable(field, actor, actor.Attack, actor.Life, attackDamageToCertainCard2, buffInfo, attackBonus)) { isAttackerUsed = true; return; } AIAttackPreCheckInformation preCheckInformation = new AIAttackPreCheckInformation(attackBonus, buffInfoListWhenCertainAttack); situation.SetPreCheckInformation(preCheckInformation); } AIVirtualAttackSimulator.Attack(situation, field); if (actor.IsDead || !actor.IsAttackable(EnemyAI.EmptyPlayPtn)) { isAttackerUsed = true; } if (!field.CardListSet.HasAttackableClassHolder) { return; } for (int i = 0; i < field.CardListSet.AttackableClassHolders.Count; i++) { AIVirtualCard aIVirtualCard = field.CardListSet.AttackableClassHolders[i]; if (aIVirtualCard.IsUnit && !aIVirtualCard.IsDead) { aIVirtualCard.TagCollectionContainer.AttackableClassTags.ChangeAttackableClassStatus(aIVirtualCard, field, field.BestPlayPtn); } } } public static bool IsAttackPossible(AIVirtualField field, AIVirtualAttackInfo attackSituation, List replacedEnemyInplayCards = null) { if (attackSituation == null || attackSituation.ActionType != AIOperationType.ATTACK) { return false; } AIVirtualCard actor = attackSituation.Actor; AIVirtualCard attackTarget = attackSituation.AttackTarget; if (actor.IsDead || attackTarget.IsDead || !actor.IsAttackable(EnemyAI.EmptyPlayPtn)) { return false; } bool flag = attackTarget == field.EnemyClass; if (actor.IsSkillCantAttackUnit) { if (flag) { return !actor.IsCantAttackClass(); } return false; } if (flag && actor.IsCantAttackClass()) { return false; } if (!(actor.IsAlly ? field.AllyInplayCards : field.EnemyInplayCards).Contains(actor)) { return false; } if (attackTarget.IsAmulet || attackTarget.IsCantUnderAttack(field.ParamQuery, actor, null, field)) { return false; } if (actor.IsCannotAttackByTag(attackSituation)) { return false; } List list = ((!actor.IsAlly) ? field.AllyInplayCards : ((replacedEnemyInplayCards == null) ? field.EnemyInplayCards : replacedEnemyInplayCards)); bool flag2 = false; if (list != null) { for (int i = 0; i < list.Count; i++) { AIVirtualCard aIVirtualCard = list[i]; if (aIVirtualCard.IsGuard && !aIVirtualCard.IsDead && !aIVirtualCard.IsCantUnderAttack(field.ParamQuery, actor, null, field)) { flag2 = true; break; } } } bool isGuard = attackTarget.IsGuard; if (flag2 && !actor.IsIgnoreGuard && !isGuard) { return false; } if (!flag && actor.IsSkillCantAtkUnitNotHasGuard && !isGuard) { return false; } return true; } public static bool IsExecuteAttackValuable(AIVirtualField field, AIVirtualCard attacker, int attack, int life, int preDamage, AISimulationBuffInfo buffInfo, float attackBonus) { int num = attack; int num2 = life; num2 -= preDamage; if (buffInfo != null) { num += buffInfo.TotalAttackBuff; num2 += buffInfo.TotalLifeBuff; } if (num2 > 0 && num > 0) { return true; } float num3 = attackBonus; if (num2 <= 0) { float num4 = attacker.EvaluateBreakValue(field.BestPlayPtn, useIgnoreBreak: true) + attacker.EvaluateLeaveValue(field.BestPlayPtn, useIgnoreInBattle: true); num3 += num4 - attacker.Value; } return num3 > 0f; } }