Compile-driven bulk-copy loop (tools/engine-port/m1_copy_loop.py) pulled the precise reference closure of the battle-core roots, stopping at the classify god-object/View-VFX-UI boundary. 782 files; no re-explosion (M0 had estimated ~order 1000). Residual frontier = 52 shim-classified + 80 external (Unity/BCL) types to author next.
296 lines
11 KiB
C#
296 lines
11 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Cute;
|
|
using Wizard.Battle.Card;
|
|
using Wizard.Battle.View.Vfx;
|
|
|
|
namespace Wizard;
|
|
|
|
public class AIOperationProcessor
|
|
{
|
|
private BattleManagerBase _battleMgr;
|
|
|
|
private EnemyAI _ai;
|
|
|
|
public AIOperationProcessor(BattleManagerBase mgr, EnemyAI ai)
|
|
{
|
|
_battleMgr = mgr;
|
|
_ai = ai;
|
|
}
|
|
|
|
public VfxBase AIPlayCard(AISituationInfo situation)
|
|
{
|
|
_ai.BestPlayPtnRecord = null;
|
|
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
|
VfxBase emote = _ai.GetEmote(AIEmoteCmdType.ON_CARD_PLAY_ALLY, situation);
|
|
sequentialVfxPlayer.Register(emote);
|
|
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
|
AISelectedTargetInfoSet selectedTargets = situation.SelectedTargets;
|
|
if (targetList.IsNotNullOrEmpty() && !selectedTargets.HasChoiceTarget)
|
|
{
|
|
SequentialVfxPlayer sequentialVfxPlayer2 = SequentialVfxPlayer.Create();
|
|
for (int i = 0; i < targetList.Count; i++)
|
|
{
|
|
BattleCardBase battleCardBase = targetList[i];
|
|
if (!battleCardBase.IsClass && !battleCardBase.BattleCardView.IsLoadResorces)
|
|
{
|
|
sequentialVfxPlayer2.Register(WaitVfx.Create(0.07f));
|
|
sequentialVfxPlayer2.Register(battleCardBase.LoadResource());
|
|
sequentialVfxPlayer2.Register(WaitVfx.Create(0.2f));
|
|
}
|
|
}
|
|
sequentialVfxPlayer.Register(sequentialVfxPlayer2);
|
|
}
|
|
BattleCardBase battleCardBase2 = actor;
|
|
int num = 0;
|
|
if (actor.HasSkillAccelerate || actor.HasSkillCrystallize)
|
|
{
|
|
int num2 = CalcFixedUseCostTransformId(actor, actor.SelfBattlePlayer.Pp);
|
|
if (num2 > 0)
|
|
{
|
|
battleCardBase2 = BattleManagerBase.GetIns().CreateTransformCardRegisterVfx(actor, num2, actor.IsPlayer);
|
|
}
|
|
}
|
|
else if (actor.Skills.CheckWhenPlayChoice && actor.Skills.Count() > 1)
|
|
{
|
|
SkillBase skillBase = actor.Skills.Get(0);
|
|
SkillBase skillBase2 = actor.Skills.Get(1);
|
|
if (skillBase.IsChoiceType && skillBase2 is Skill_transform)
|
|
{
|
|
battleCardBase2 = targetList[0];
|
|
num = 1;
|
|
}
|
|
}
|
|
BattlePlayerPair battlePlayerPair = _ai.PlayerPair.VirtualClone(CloneActualFlags.All);
|
|
battlePlayerPair.Self.AddCurrentTrunPlayCount(1);
|
|
BattleCardBase battleCardBase3 = battlePlayerPair.Self.HandCardList.Where((BattleCardBase c) => c.Index == actor.Index && c.CardId == actor.CardId && c.IsPlayer == actor.IsPlayer).FirstOrDefault();
|
|
if (battleCardBase3 != null)
|
|
{
|
|
battlePlayerPair.Self.HandCardList.Remove(battleCardBase3);
|
|
}
|
|
List<SkillBase> checkSkillList = GetCheckSkillList(battleCardBase2.Skills, battlePlayerPair);
|
|
if (CheckSelectTypeSkillTargetCount(actor, checkSkillList, targetList, num, "[PlayCard]") || targetList != null)
|
|
{
|
|
CheckSelectTypeSkillTarget(actor, battlePlayerPair, checkSkillList, targetList, num, "[PlayCard]");
|
|
}
|
|
if (!targetList.IsNotNullOrEmpty() || !targetList.Any((BattleCardBase c) => c is IVirtualBattleCard) || !actor.Skills.HaveChoiceTransformSkill())
|
|
{
|
|
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.InitSetCard(actor, actor.IsPlayer, targetList.IsNotNullOrEmpty()));
|
|
}
|
|
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.PlayCard(actor, actor.IsPlayer, targetList));
|
|
return sequentialVfxPlayer;
|
|
}
|
|
|
|
public VfxBase AIEvolutionCard(AISituationInfo situation)
|
|
{
|
|
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
|
if (!actor.CanEvolution(isSkill: false, isSelfBattlePlayer: true))
|
|
{
|
|
AIConsoleUtility.LogError("Evolution Condition Error!!!");
|
|
}
|
|
if (actor.EvolutionSkills.HasEvolutionSkillWithSelection)
|
|
{
|
|
List<SkillBase> checkSkillList = GetCheckSkillList(actor.EvolutionSkills, _ai.PlayerPair);
|
|
CheckSelectTypeSkillTarget(actor, _ai.PlayerPair, checkSkillList, targetList, 0, "[Evolution]");
|
|
}
|
|
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
|
VfxBase emote = _ai.GetEmote(AIEmoteCmdType.ON_ALLY_EVOLUTION, situation);
|
|
sequentialVfxPlayer.Register(emote);
|
|
if (emote != NullVfx.GetInstance())
|
|
{
|
|
_ai.EmoteQuery.OnCardPlayEmotion();
|
|
}
|
|
sequentialVfxPlayer.Register(_battleMgr.OperateMgr.EvolutionCard(actor, actor.IsPlayer, targetList));
|
|
return sequentialVfxPlayer;
|
|
}
|
|
|
|
public VfxBase AIFusionCard(AISituationInfo situation)
|
|
{
|
|
AIRealBattleCardSearcher.SearchBattleCardFromSituation(_ai.PlayerPair, situation, out var actor, out var targetList);
|
|
SkillBase item = actor.Skills.FirstOrDefault((SkillBase s) => s is Skill_fusion);
|
|
CheckSelectTypeSkillTarget(actor, _ai.PlayerPair, new List<SkillBase> { item }, targetList, 0, "[Fusion]");
|
|
return _battleMgr.OperateMgr.FusionCard(actor, actor.IsPlayer, targetList);
|
|
}
|
|
|
|
private List<SkillBase> GetCheckSkillList(SkillCollectionBase skillCollection, BattlePlayerPair playerPair)
|
|
{
|
|
List<SkillBase> list = new List<SkillBase>();
|
|
IEnumerable<SkillBase> selectTypeSkill = skillCollection.GetSelectTypeSkill(isEvolve: true, isFusion: false, isActivateFanfare: false, playerPair);
|
|
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
|
foreach (SkillBase item in skillCollection.Where((SkillBase s) => s.IsChoiceType && s.CheckCondition(playerPair, option, isPrePlay: true)))
|
|
{
|
|
if (!list.Contains(item))
|
|
{
|
|
list.Add(item);
|
|
}
|
|
}
|
|
foreach (SkillBase item2 in selectTypeSkill)
|
|
{
|
|
if (!list.Contains(item2))
|
|
{
|
|
list.Add(item2);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private void CheckSelectTypeSkillTarget(BattleCardBase actor, BattlePlayerPair playerPair, IEnumerable<SkillBase> skills, List<BattleCardBase> targetList, int selectTargetNumber, string checkTimingName)
|
|
{
|
|
int num = selectTargetNumber;
|
|
bool flag = false;
|
|
foreach (SkillBase skill in skills)
|
|
{
|
|
if (skill.IsBurialRite)
|
|
{
|
|
BattleCardBase card = targetList[num];
|
|
if (!actor.SelfBattlePlayer.HandCardList.Any((BattleCardBase c) => c.Index == card.Index && c.IsPlayer == card.IsPlayer))
|
|
{
|
|
string message = actor.BaseParameter.CardName + checkTimingName + "BURIAL_RITE Target not in Hand list Error!!!";
|
|
ThrowErrorMessage(message);
|
|
}
|
|
else if (!card.IsInHand || !card.IsUnit)
|
|
{
|
|
string message2 = actor.BaseParameter.CardName + checkTimingName + "BURIAL_RITE Wrong targeted selection criteria Error!!!";
|
|
ThrowErrorMessage(message2);
|
|
}
|
|
flag = true;
|
|
num++;
|
|
}
|
|
if (skill.ApplySelectFilter is SkillRandomSelectFilter || skill.ApplySelectFilter is SkillSelectAllFilter || (!skill.IsChoiceType && skill.ApplySelectFilter is SkillSelectNullFilter))
|
|
{
|
|
continue;
|
|
}
|
|
IEnumerable<BattleCardBase> selectableCards = skill.GetSelectableCards(playerPair, new SkillConditionCheckerOption());
|
|
int skillSelectCount = skill.GetSkillSelectCount();
|
|
int num2 = targetList.Count - num;
|
|
skillSelectCount = ((skillSelectCount > num2) ? num2 : skillSelectCount);
|
|
List<BattleCardBase> list = new List<BattleCardBase>(targetList.GetRange(num, skillSelectCount));
|
|
num += skillSelectCount;
|
|
if (list.Count > 1)
|
|
{
|
|
for (int num3 = 0; num3 < list.Count; num3++)
|
|
{
|
|
BattleCardBase card2 = list[num3];
|
|
List<BattleCardBase> list2 = list.Where((BattleCardBase c) => c.Index == card2.Index && c.IsPlayer == card2.IsPlayer).ToList();
|
|
if (list2.Count > 1)
|
|
{
|
|
string message3 = $"{actor.BaseParameter.CardName}{checkTimingName}Duplicate {list2.Count} selected card Error!!!";
|
|
ThrowErrorMessage(message3);
|
|
}
|
|
}
|
|
}
|
|
int num4 = 0;
|
|
for (int num5 = 0; num5 < list.Count; num5++)
|
|
{
|
|
BattleCardBase card3 = list[num5];
|
|
if (!selectableCards.Any((BattleCardBase c) => c.Index == card3.Index && c.IsPlayer == card3.IsPlayer))
|
|
{
|
|
if (num4 < selectableCards.Count() && !flag)
|
|
{
|
|
targetList[num5] = selectableCards.ElementAt(num4);
|
|
num4++;
|
|
}
|
|
string message4 = actor.BaseParameter.CardName + checkTimingName + "Target not in selection list Error!!!";
|
|
ThrowErrorMessage(message4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool CheckSelectTypeSkillTargetCount(BattleCardBase actor, IEnumerable<SkillBase> skills, List<BattleCardBase> targetList, int selectCardCount, string checkTimingName)
|
|
{
|
|
string text = checkTimingName + actor.BaseParameter.CardName + "\n";
|
|
int num = selectCardCount;
|
|
foreach (SkillBase skill in skills)
|
|
{
|
|
if (skill.IsBurialRite)
|
|
{
|
|
selectCardCount++;
|
|
num++;
|
|
text += "BurialRite1回";
|
|
if (skill is Skill_none)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
if (!(skill.ApplySelectFilter is SkillRandomSelectFilter) && !(skill.ApplySelectFilter is SkillSelectAllFilter) && (!skill.IsBurialRite || skill.ApplySelectFilter is SkillUserSelectFilter) && (skill.IsChoiceType || !(skill.ApplySelectFilter is SkillSelectNullFilter)))
|
|
{
|
|
BattlePlayerReadOnlyInfoPair playerInfoPair = new BattlePlayerReadOnlyInfoPair(actor.SelfBattlePlayer, actor.OpponentBattlePlayer);
|
|
SkillConditionCheckerOption option = new SkillConditionCheckerOption();
|
|
if (skill.CheckCondition(playerInfoPair, option, isPrePlay: true))
|
|
{
|
|
int skillSelectCount = skill.GetSkillSelectCount();
|
|
selectCardCount += skillSelectCount;
|
|
num += ((!actor.IsUnit && !actor.IsField) ? 1 : 0);
|
|
text += $"{skill}{skillSelectCount}回";
|
|
}
|
|
}
|
|
}
|
|
if (selectCardCount <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
bool flag = false;
|
|
if (targetList == null || targetList.Count <= 0)
|
|
{
|
|
if (num <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
text += "\n選択されていません";
|
|
flag = true;
|
|
}
|
|
else
|
|
{
|
|
int count = targetList.Count;
|
|
int num2 = count - selectCardCount;
|
|
if (num2 < 0 && count < num)
|
|
{
|
|
text += "\n少なく選択されています";
|
|
flag = true;
|
|
}
|
|
if (num2 > 0)
|
|
{
|
|
text += $"\n{num2}回多く選択されています";
|
|
flag = true;
|
|
}
|
|
}
|
|
if (flag)
|
|
{
|
|
ThrowErrorMessage(text);
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
public int CalcFixedUseCostTransformId(BattleCardBase actor, int currentPp)
|
|
{
|
|
int num = -1;
|
|
int cost = actor.Cost;
|
|
int result = -1;
|
|
for (int i = 0; i < actor.Skills.Count(); i++)
|
|
{
|
|
if (!(actor.Skills.ElementAt(i) is Skill_pp_fixeduse skill_pp_fixeduse) || currentPp < skill_pp_fixeduse._fixedUsePP)
|
|
{
|
|
continue;
|
|
}
|
|
bool num2 = skill_pp_fixeduse.CheckCondition(_ai.PlayerPair, new SkillConditionCheckerOption(), isPrePlay: true);
|
|
bool flag = num2 && num < skill_pp_fixeduse._fixedUsePP;
|
|
bool flag2 = num2 && skill_pp_fixeduse._fixedUsePP < cost && currentPp < cost;
|
|
if (flag || flag2)
|
|
{
|
|
if (actor.Skills.ElementAt(i + 1) is Skill_transform skill_transform)
|
|
{
|
|
result = skill_transform.TransformId;
|
|
}
|
|
num = skill_pp_fixeduse._fixedUsePP;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void ThrowErrorMessage(string message)
|
|
{
|
|
AIConsoleUtility.LogError(message);
|
|
}
|
|
}
|