using BigFloatNumerics; using System; using System.Collections.Generic; using UnityEngine; using static BattleMgr; public class AtlantisDungeon : GameMod { [SerializeField] Transform playerSpawnPos; [SerializeField] AtlantisDungeonView view; BattleMgr battleMgr => BattleMgr.Instance; float modElapsedTime; IVCharacter player; Dictionary> normalEnemyPoolMap; Dictionary> epicEnemyPoolMap; int currentWave; float prevWaveTime; float elapsedTimeSincePrevWave => Time.time - prevWaveTime; public new AtlantisDungeonData Data => base.Data as AtlantisDungeonData; public float CurrentScore { get; private set; } public float ModRemainingTime => Mathf.Max(Data.LimitTime - modElapsedTime, 0f); protected override void OnInitialize() { normalEnemyPoolMap = new Dictionary>(); epicEnemyPoolMap = new Dictionary>(); } protected override void OnStartMod() { SoundMgr.Instance.PlayBgm(Data.BGMPath); BattleMgr.Instance.SetBackGround(Data.BackGroundPath); //Set enemy pool foreach (var enemy in Data.NormalEnemyCandidates) { var pool = new DynamicMonoObjectPool(); pool.Initialize( () => InstantiateEnemy(pool, enemy, Data.GetCurNormalEnemyHp, Data.GetCurNormalEnemyAtk, Data.NormalEnemyScore), DestroyEnemy, (obj) => obj.gameObject.SetActive(false), (obj) => obj.gameObject.SetActive(true)); normalEnemyPoolMap.Add(enemy.id, pool); } foreach (var enemy in Data.EpicEnemyCandidates) { var pool = new DynamicMonoObjectPool(); pool.Initialize( () => InstantiateEnemy(pool, enemy, Data.GetCurEpicEnemyHp, Data.GetCurEpicEnemyAtk, Data.EpicEnemyScore), DestroyEnemy, (obj) => obj.gameObject.SetActive(false), (obj) => obj.gameObject.SetActive(true)); epicEnemyPoolMap.Add(enemy.id, pool); } //Summon player player = battleMgr.GetPlayer(); var buffMgr = BuffMgr.Instance; player.ResetDebuff(); player.SetStatus( buffMgr.GetCharAtk(), buffMgr.GetCharHp(), buffMgr.GetCharCrtDam(), buffMgr.GetCharCrtRate(), buffMgr.GetCharMov(), buffMgr.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange); player.transform.position = playerSpawnPos.position; player.Summon(); MateMgr.Instance.EndAllSettedMateSkillCool(); MateMgr.Instance.SetAcitveMateToFirst(); MateMgr.Instance.ActiveMate?.Spawn(player, player.LookDirection); battleMgr.SetPetsSummonState(true); battleMgr.SetGudiansSummonState(true); battleMgr.ShowTalkBox(TalkType.Summon); currentWave = 0; prevWaveTime = Time.time - Data.WaveIntervalTime; modElapsedTime = 0f; CurrentScore = 0f; IVCameraController.SMoveCamera(player.transform.position); //Set UI GameUIMgr.OnOffStageInfo(false); view?.SetDungeon(this); view?.Show(); } private Character InstantiateEnemy(DynamicMonoObjectPool targetPool, CharacterProperty prop, Func getHpFunc, Func getAtkFunc, float score) { var enemyData = new CharacterData(prop); if (enemyData.TryGetStat(StatID.Hp, out var hpStat)) hpStat.DefaultValue = getHpFunc(); if (enemyData.TryGetStat(StatID.Attack, out var atkStat)) atkStat.DefaultValue = getAtkFunc(); var enemy = Instantiate(enemyData.Prefab); enemy.SetData(enemyData); enemy.AddTags(EntityTag.Enemy); enemy.SetTargetTags(LayerMask.GetMask(GameProperty.Instance.CharacterLayerName), EntityTag.Player); enemy.OnDamaged += (obj, damage) => { if (obj.CurrentHp <= 0) { CurrentScore += score; } }; enemy.OnDisposed += (obj) => { BattleMgr.Instance.UnregistBattleEntities(obj); targetPool.Return(obj); }; return enemy; } private void DestroyEnemy(Character enemy) { BattleMgr.Instance.UnregistBattleEntities(enemy); CoroutineHandler.Instance.DelayCall(1f ,() => Destroy(enemy.gameObject)); } protected override void OnUpdate() { if(BattleMgr.Instance.BattlePause) return; modElapsedTime += Time.deltaTime; if (modElapsedTime >= Data.LimitTime) { battleMgr.ShowTalkBox(TalkType.Die); FireOnDone(Result.Timeout); } else { if (player.IsDead) { battleMgr.ShowTalkBox(TalkType.Die); FireOnDone(Result.Dead); } else if(CurrentScore >= Data.GoalScore) { battleMgr.ShowTalkBox(TalkType.Attack); Data.TryGetReward(Data.Level, (totalReward, result) => { if (!result) return; GameUIMgr.SOpenPopupGoods(totalReward); GameUIMgr.RefreshAtlantisDungeonTicket(); }, Data.GetRewardMultiplier()); Data.SetLevel(Data.Level + 1); Data.EnterTicketCount--; Data.ClearCount++; FireOnDone(Result.Success); } else if(currentWave < Data.WaveCount && elapsedTimeSincePrevWave >= Data.WaveIntervalTime) { prevWaveTime = Time.time; currentWave++; SpawnWave(); } } } private void SpawnWave() { var areaSize = BattleMgr.Instance.GetBgSize(); var rndPositions = TargetFinder.GetRandom(areaSize.bounds, Data.NormalEnemyCountPerWave + Data.EpicEnemyCountPerWave); for(int i = 0; i < Data.NormalEnemyCountPerWave; i++) { if(normalEnemyPoolMap.TryGetRandomValue(out var pool)) { var enemy = pool.Get(); enemy.Spawn(rndPositions[i]); enemy.ChangeLookDirection(player.transform); BattleMgr.Instance.RegistBattleEntities(enemy); } } for (int i = 0; i < Data.EpicEnemyCountPerWave; i++) { if(epicEnemyPoolMap.TryGetRandomValue(out var pool)) { var enemy = pool.Get(); enemy.Spawn(rndPositions[i + Data.NormalEnemyCountPerWave]); enemy.ChangeLookDirection(player.transform); BattleMgr.Instance.RegistBattleEntities(enemy); } } } protected override void OnEndMod() { view?.Hide(); GameUIMgr.OnOffStageInfo(true); foreach (var pool in epicEnemyPoolMap.Values) { pool.Dispose(); } epicEnemyPoolMap.Clear(); foreach (var pool in normalEnemyPoolMap.Values) { pool.Dispose(); } normalEnemyPoolMap.Clear(); if (Data.AutoProgress && Data.EnterTicketCount <= 0) { GameUIMgr.SOpenToast(LocalizationText.GetText("notice_stop_autoprogress_0")); Data.AutoProgress = false; } Data.TryCount++; } public void QuitDungeon() { battleMgr.ShowTalkBox(TalkType.Die); FireOnDone(Result.Quit); } }