using CodeStage.AntiCheat.Detectors; using CodeStage.AntiCheat.ObscuredTypes; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using UnityEngine; using UnityEngine.ResourceManagement.AsyncOperations; using Random = UnityEngine.Random; public partial class InGameInfo : MyCoroutine { public static InGameInfo Ins; public TextAsset ta_StageData; public Material mat_Dissolve; public BackGroundSetting m_BackGroundSetting; public Transform[] tfs_ProjectileStart; // 0 왼쪽, 1 중앙, 2 오른쪽, 3 몹 중앙 public PCActor m_PCActor { get { return IngameUIManager.Ins.m_PCActor; } } ToolData m_ToolData; private void Awake() { Ins = this; } void Set_Init() { AddrResourceMgr.Ins.LoadObject("MainUI/GameUI.prefab", handle => { if (handle.IsDone && handle.Status == AsyncOperationStatus.Succeeded) { DSUtil.Get_Clone(handle.Result); //InappInfo.Ins.Check_Retrieved(); } }); } IEnumerator Start() { m_ToolData = JsonConvert.DeserializeObject(ta_StageData.text); DataCheckMgr.Ins.Set(); Set_Init(); while (!TableChecker.Ins.CheckAllLoad()) yield return new WaitForSeconds(0.1f); //var lst = table_effectlist.Ins.Get_DataList(1); //for (int i = 0; i < lst.Count; i++) //{ // dic_str_Effect.Add(lst[i].s_EffectPrefab, new List()); // for (int j = 0; j < lst[i].n_PreLoadCount; j++) // Load_Effect(lst[i].s_EffectPrefab, effect => { effect.transform.position = Vector3.one * 100000f; }); //} ObscuredCheatingDetector.StartDetection(OnCheaterDetected); SpeedHackDetector.StartDetection(OnCheaterDetected); //while (DSUtil.CheckNull(NewGameUI.Ins)) yield return null; if (MyValue.m_MyStageData.m_EnterType != eStageEnterType.Normal) { while (!LobbyUIManager.Ins) yield return null; Start_Game_byTool(); } while (!IngameUIManager.Ins) yield return null; dic_EnemyActor.Add(eRole.Mob, new List { m_PCActor }); dic_EnemyActor.Add(eRole.PC, MonsterNodeControler.Ins.Get_AllActor().ToList()); } void OnCheaterDetected() { Time.timeScale = 0f; Popup.Ins.Set(ePopupType.One, -99, DSUtil.Quit, DSUtil.Quit); } public void Set_TimeScale(float _scale, float _delay) { Set_Coroutine(() => { Time.timeScale = _scale; }, _delay); } #region 탐험 public void Return_To_Lobby() { IngameUIManager.Ins.Return_To_Lobby(); switch (MyValue.m_MyStageData.m_EnterType) { case eStageEnterType.Normal: LobbyUIManager.Ins.Set(); break; } if (MonsterNodeControler.Ins) MonsterNodeControler.Ins.AllOff(); // 몬스터 끄기 EffectMgr.Ins.AllOff(); // 이펙트 끄기 ProjectileMgr.Ins.AllOff(); // 투사체 끄기 } public void Start_Game() { Start_Game_Common(); } public void Start_Game_byTool() { LobbyUIManager.Ins.gameObject.SetActive(false); IngameUIManager.Ins.gameObject.SetActive(true); Start_Game_Common(); } void Start_Game_Common() { var pcid = MyValue.sdata.PCID; switch (MyValue.m_MyStageData.m_EnterType) { default: Set_StageData(MyValue.m_MyStageData.m_Chapter, MyValue.m_MyStageData.m_Stage); break; case eStageEnterType.Tool_Mob: Set_StageData(1, 1); break; } m_BackGroundSetting.Set(); IngameUIManager.Ins.Active_ExporeButton(); Init_CardData(); // Actor Set_Equipment() 전 호출해야 됨 m_PCActor.Set(0, table_pclist.Ins.Get_Data_orNull(pcid), IngameUIManager.Ins.PC_HUD_HPShield, MyValue.sdata); Init_IngameDatas(); if (MyValue.m_MyStageData.m_EnterType == eStageEnterType.Tool_Mob) IngameUIManager.Ins.Skip_Expore(); } public void Init_IngameDatas() { // 탐험 입장 시 1번 호출 PCLv = 1; dic_goodsAmount.Clear(); Set_Texts(); Set_PCLvInfo(); IngameUIManager.Ins.m_PCMainStatUI.Set(m_PCActor.Get_ActorStatInfo()); IngameUIManager.Ins.m_GainCardList.Set(list_GainCard); // Actor Set_Equipment() 후 호출됨 DefeatUI.Ins.Init(); IngameUIManager.Ins.m_DungeonInfo.Set(); m_PCActor.Init_IngameDatas(); if (MonsterNodeControler.Ins) MonsterNodeControler.Ins.Init_IngameDatas(); } void Init_CardData() { m_lvupcardcount = 0; list_GainCard.Clear(); } void Set_StageData(int chapter, int stage) { IngameStageData data = null; switch (MyValue.m_MyStageData.m_EnterType) { default: data = m_ToolData.Get_IngameStageData(chapter, stage); data.Init(); if (data == null) { Popup.Ins.Set($"{stage} 스테이지 데이터가 없습니다."); return; } break; } MyValue.m_MyStageData.m_StageData = data; IngameUIManager.Ins.m_DungeonInfo.m_DungeonProcess.Set_ExtraMark(); } public void Add_BattlePatternData(int patternid, BattlePatternData bpdata) { var data = m_ToolData.MonsterPattern.Find(f => f.m_PatternID == patternid); if (data != null) m_ToolData.MonsterPattern.Remove(data); m_ToolData.MonsterPattern.Add(bpdata); } public BattlePatternData Get_BattlePatternData(int patternid) { var rtndata = m_ToolData.MonsterPattern.Find(f => f.m_PatternID == patternid); return rtndata; } #endregion #region 몬스터 조우 ObscuredInt _pclv; public int PCLv { get { return _pclv; } set { _pclv = value; _pclv.RandomizeCryptoKey(); } } ObscuredInt _lvupcardcount; public int m_lvupcardcount { get { return _lvupcardcount; } set { _lvupcardcount = value; _lvupcardcount.RandomizeCryptoKey(); } } Dictionary dic_goodsAmount = new Dictionary(); List list_GainCard = new List(); public List Get_ListGainCard() { return list_GainCard; } Dictionary> dic_EnemyActor = new Dictionary>(); public void Init_EveryMeetMonster() { // 몬스터 만났을 때마다 한 번 실행되는 함수 m_PCActor.Init_EveryMeetMonster(); if (MonsterNodeControler.Ins) MonsterNodeControler.Ins.Init_EveryMeetMonster(); m_PCActor.OnEvent_RunSkillCard(); } public void BattleStart_AfterMakeMob() { // 몬스터, 보스 노드 만날 시 최초 한 번 실행 OnEvent_MakeMob(); Set_Battle(true); Init_EveryMeetMonster(); MonsterNodeControler.Ins.Check_LineAllDead(); OnEvent_AfterLineChange(); } public void Set_Texts() { IngameUIManager.Ins.Set_Texts(Get_GoodsAmount(MyValue.ItemID_Gold), Get_GoodsAmount(MyValue.ItemID_Soul), (int)m_PCActor.Get_ActorStatInfo().Get_TotalStat(eStat.Potion)); } public void Set_PCLvInfo(Action actgageend = null) { IngameUIManager.Ins.m_PCMainStatUI.Set_Lv(PCLv, Get_GoodsAmount(MyValue.ItemID_Exp), actgageend); } public void Set_Battle(bool battle) { m_PCActor.Set_Battle(battle); if (MonsterNodeControler.Ins) MonsterNodeControler.Ins.Set_Battle(battle); } public int Get_GoodsAmount(int itemid) { return dic_goodsAmount.ContainsKey(itemid) ? dic_goodsAmount[itemid] : 0; } public void Add_Goods(int itemid, int v) { if (!dic_goodsAmount.ContainsKey(itemid)) dic_goodsAmount.Add(itemid, 0); dic_goodsAmount[itemid] += v; dic_goodsAmount[itemid].RandomizeCryptoKey(); Set_Texts(); if (itemid == MyValue.ItemID_Exp) Set_PCLvInfo(Check_PCLvUp); } void Check_PCLvUp(bool isLvUp) { if (isLvUp) { SelectCardUI.Ins.Set(true); ++PCLv; m_PCActor.OnEvent_LvUp(); Set_PCLvInfo(Check_PCLvUp); } } public void Add_Potion(int amount, int maxpotion = 0) { if (maxpotion > 0) m_PCActor.Get_ActorStatInfo().Set_Stat(true, eStat.MaxPotion, maxpotion); m_PCActor.Get_ActorStatInfo().Set_Stat(true, eStat.Potion, amount); Set_Texts(); } public void Use_Potion() { var potion = 10; // 테스트 : 물약 회복량 m_PCActor.Use_Potion(false, potion); } public void PCLvUp_Imm() { var expdata = table_BattleLevelUp.Ins.Get_Data_orNull(PCLv); if (expdata != null) { var remainExp = expdata.n_TotalExp - Get_GoodsAmount(MyValue.ItemID_Exp); Add_Goods(MyValue.ItemID_Exp, remainExp); } } public void Heal_PC(eHealType healType, int heal) { m_PCActor.Heal(healType, heal); m_PCActor.Set_StatusEffect(eStatusConditionsType.Heal_Hp_Add, 1f); } public void Add_Card(CardListTableData card, bool islvupcard) { if (islvupcard) ++m_lvupcardcount; list_GainCard.Add(card); IngameUIManager.Ins.m_GainCardList.Set(list_GainCard); if (ServerInfo.Ins.m_ServerData != null) ServerInfo.Ins.m_ServerData.Add_Card(card.n_ID); m_PCActor.Add_CardSkill(card); Set_Texts(); IngameUIManager.Ins.m_PCMainStatUI.Set(m_PCActor.Get_ActorStatInfo()); } public void Add_Card_Random(eGrade grade) { m_PCActor.Add_Card_Random(grade); } public void Revive_PC() { m_PCActor.Revive_byDefeatUI(); } public void OnEvent_MakeMob() { for (int i = 0; i < list_GainCard.Count; i++) { var temp = list_GainCard[i]; switch (temp.e_CardType) { case eCardType.G3_DodgeFirstRangedAttack: MonsterNodeControler.Ins.OnEvent_CheckCard(temp); break; } } } public void OnEvent_Mob_ShootProjectile(MobActor mob) { for (int i = 0; i < list_GainCard.Count; i++) { var temp = list_GainCard[i]; switch (temp.e_CardType) { case eCardType.G4_RangedAttackFrontEnemyDamageShare: if (mob.IsMiddleLine() && mob.Get_AttackType() == eAttackType.Range) { var frontmob = Get_Enemy_orNull(eRole.PC, mob.Get_MobIndex() - 3); if (frontmob != null && !frontmob.IsDead()) { var dmg = (int)(mob.Get_ActorStatInfo().Get_Damage() * temp.Get_FloatValue2()); mob.Shoot_Projectile_FixedDmg(temp.e_CardType, temp.s_Projectile, dmg, frontmob); } } break; case eCardType.G1_RangedFirstAttackHitFrontAlly: if (mob.IsMiddleLine() && mob.Get_AttackType() == eAttackType.Range && mob.Get_AttackCount() == 1) { var carddata = m_PCActor.Get_CardSkillData_orNull(temp.e_CardType); if (carddata != null) { var frontmob = Get_Enemy_orNull(eRole.PC, mob.Get_MobIndex() - 3); if (frontmob != null && !frontmob.IsDead()) frontmob.Get_Dmg((int)(mob.Get_ActorStatInfo().Get_Damage() * temp.Get_FloatValue2())); } } break; } } } public void OnEvent_MeetNode(eStageNodeType nodeType) { m_PCActor.OnEvent_MeetNode(nodeType); } public void OnEvent_AfterLineChange() { if (MyValue.m_MyStageData.m_EnterType == eStageEnterType.Tool_Mob) return; m_PCActor.OnEvent_AfterLineChange(); Get_AllEnemies(eRole.PC).ForEach(f => f.OnEvent_AfterLineChange()); } #endregion #region 타겟 찾기 public List Get_AllEnemies(eRole role) { return dic_EnemyActor[role]; } public List Get_RandomAliveEnemies(eRole role, int count) { if (!dic_EnemyActor.TryGetValue(role, out var enemies)) return new List(); // 살아있는 적만 필터 var aliveList = enemies.Where(e => e != null && !e.IsDead()).ToList(); if (aliveList.Count <= count) return aliveList; // Fisher–Yates Shuffle (부분 셔플) for (int i = 0; i < count; i++) { int rand = Random.Range(i, aliveList.Count); (aliveList[i], aliveList[rand]) = (aliveList[rand], aliveList[i]); } return aliveList.GetRange(0, count); } public List Get_LineMobs(params eMobBattlePos[] pos) { var enemies = Get_AllEnemies(eRole.PC); return enemies.FindAll(f => !f.IsDead() && pos.Contains(f.Get_Line())); } public List Get_Ally(eRole role) { var actors = dic_EnemyActor[role == eRole.PC ? eRole.Mob : eRole.PC]; return actors.FindAll(f => !f.IsDead()); } public Actor Get_Enemy_orNull(eRole role, bool cantsettarget = false) { if (role == eRole.PC) { // PC가 몬스터 선택 (정인호 : 옵션 연계 필요) if (cantsettarget) { var mobs = Get_LineMobs(eMobBattlePos.Frontline, eMobBattlePos.Middleline); var aliveMobs = mobs.FindAll(m => !m.IsDead()); return aliveMobs.Count == 0 ? null : aliveMobs[Random.Range(0, aliveMobs.Count)]; } else { var mobs = Get_LineMobs(eMobBattlePos.Frontline); var aliveMobs = mobs.FindAll(m => !m.IsDead()); return aliveMobs.Count == 0 ? null : aliveMobs[Random.Range(0, aliveMobs.Count)]; } } else return m_PCActor; } public Actor Get_Enemy_orNull(eRole role, int index) { var all = Get_AllEnemies(role); return all.Find(f => f.Get_MobIndex() == index); } public Actor[] Get_Mobs_4Nearby(int mobIndex) { // 기본 패턴: 상하좌우 int[] offsets = { -1, 1, -3, 3 }; // 특수 처리: 위치별로 제외 인덱스 조정 List targetIndices = new List { mobIndex }; foreach (int offset in offsets) { int idx = mobIndex + offset; // 좌우 경계 처리 (열 구분) int col = mobIndex % 3; if ((col == 0 && offset == -1) || (col == 2 && offset == 1)) continue; // 왼쪽 끝에서 왼쪽으로 가거나, 오른쪽 끝에서 오른쪽으로 가는 경우 제외 // 범위 제한 if (idx < 0 || idx > 8) continue; targetIndices.Add(idx); } // 대상들 가져오기 (null은 제외) var mobs = targetIndices.Select(i => Get_Enemy_orNull(eRole.PC, i)).Where(t => t != null && !t.IsDead()).ToArray(); return mobs; } public Actor Get_RandomEnemy_orNull(eRole role) { var enemies = Get_AllEnemies(role); enemies = enemies.FindAll(f => !f.IsDead()); if (enemies.Count > 0) return enemies[Random.Range(0, enemies.Count)]; return null; } public List Get_Enemies_byAttackType(eRole role, eAttackType attackType) { var enemies = Get_AllEnemies(role); return enemies.FindAll(f => !f.IsDead() && f.Get_AttackType() == attackType); } #endregion }