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 _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(); base.validateSkillIndexList = new List(); RegisterActionManager = new RegisterActionManager(this); base.RegisterUnapprovedList = new List(); base.registerSelectTypeSkillIndexList = new List(); 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(); 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)Delegate.Combine(_turnTransitionFunc, new Func(base.ControlTurnStartOpponent)); return NullVfx.GetInstance(); }; BattleEnemy.OnTurnEndFinish += delegate { if (IsVirtualBattle || base.IsRecovery) { return NullVfx.GetInstance(); } _turnTransitionFunc = null; _turnTransitionFunc = (Func)Delegate.Combine(_turnTransitionFunc, new Func(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(); 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(); } }