using System.Collections.Generic; using UnityEngine; using cfg; using System.Threading.Tasks; using Base.Common; using System.Threading; using System.IO; using OfficeOpenXml; public class EnemyCreater : MonoBehaviour { public LevelSelect levelSelect; private CancellationTokenSource _cancellationTokenSource; public static EnemyCreater instance; public SoldierEXP soldierEXP; public List cfgCreateEnemy; public List cfgCreateEnemy1; public List createdEnemy; public List createdEnemy1; public List> createEnemyTime = new(); public List> createEnemyTime1 = new(); public Dictionary> enemyDic; public Dictionary> buildingDic; public Vector2Int idRange; //当前关卡为出怪表[x,y]行 public Vector2Int idRange1; //当前关卡为出怪表[x,y]行 public Dictionary enemyCreateTowerDic; public List createdEnemyTower = new(); public List createdEnemyTower1 = new(); public List createdEnemyTowerHp = new(); public List createdEnemyTowerHp1 = new(); public int nowLevel; public int[] levelTypes; //“承”“转”关卡的类型 private void Awake() { if (!instance) { instance = this; } else { DestroyImmediate(gameObject); return; } soldierEXP = GetComponent(); } private void Start() { levelSelect.ReloadCfg(); _cancellationTokenSource = new CancellationTokenSource(); Init(); ////把所有怪物prefab生成一遍防止后面初次生成卡顿 ////foreach (var item in createCharacter) ////{ //// for(int i = 0; i < item.tile.spawnTime[item.spawnTimeId].num; i++) //// { //// CreateEnemy(item.tile, Vector3.zero, 1, 1,false); //// } ////} } public void Init() { if (LevelSelect.instance.isDebug) { if (LevelSelect.instance.isAddLevel_debug) { levelTypes[1] = LevelSelect.instance.levelIdB_debug; GameManager.instance.leveType = LeveType.Conclusion; } nowLevel = LevelSelect.instance.levelIdA_debug; } else { switch (GameManager.instance.leveType) { case LeveType.Introduction: nowLevel = 0; break; case LeveType.Development: nowLevel = levelTypes[0]; break; case LeveType.Transition: nowLevel = levelTypes[1]; break; case LeveType.Conclusion: nowLevel = levelTypes[0]; break; case LeveType.Boss: nowLevel = 0; levelSelect.curLevelID = 4; break; } } enemyDic = new Dictionary>(); buildingDic = new Dictionary>(); enemyCreateTowerDic = new Dictionary(); createdEnemy = new List(); createEnemyTime = new List>(); createdEnemyTower = new List(); createdEnemyTowerHp = new List(); float waveTime = 0; float id = 0; int startId; int endId; cfgCreateEnemy = GameManager.instance.createEnemyConfigs[nowLevel].DataList; startId = levelSelect.levelsId[nowLevel][levelSelect.curLevelID]; endId = levelSelect.curLevelID < levelSelect.levels.Count - 1 ? levelSelect.levelsId[nowLevel][levelSelect.curLevelID + 1] : cfgCreateEnemy.Count; if (cfgCreateEnemy[startId].WaveID != -1 || endId != cfgCreateEnemy.Count && cfgCreateEnemy[endId].WaveID != -1) { Debug.LogError("关卡导入出错"); } FileInfo fileInfo = new FileInfo($"Luban/Config/Datas/EnemyCreater/出怪表{nowLevel}.xlsx"); using (ExcelPackage package = new ExcelPackage(fileInfo)) { List excelWorksheets = ExcelEditor.ReadExcelSheetsInfo(package); float.TryParse(ExcelEditor.GetCellData(package, excelWorksheets[levelSelect.curLevelID], "F5"), out LevelSelect.EXPRatio); } idRange = new Vector2Int(startId, endId); for (int i = startId + 1; i < endId; i++) { if (cfgCreateEnemy[i].WaveID == 0) { createdEnemy.Add(false); createEnemyTime.Add(new List { cfgCreateEnemy[i].StartTime, cfgCreateEnemy[i].EndTime }); createdEnemyTower.Add(""); createdEnemyTowerHp.Add(0); waveTime = cfgCreateEnemy[i].WaveTime; } else if (cfgCreateEnemy[i].WaveID < 1) { createdEnemy.Add(false); createEnemyTime.Add(new List { 0, 0 }); if (id != cfgCreateEnemy[i].WaveID) { createdEnemyTower.Add(cfgCreateEnemy[i].BuildingID); createdEnemyTowerHp.Add(cfgCreateEnemy[i].BuildingHP); id = cfgCreateEnemy[i].WaveID; } else { int l = createdEnemyTower.Count; createdEnemyTower.Add(createdEnemyTower[l - 1]); createdEnemyTowerHp.Add(createdEnemyTowerHp[l - 1]); } } else { if (id != cfgCreateEnemy[i].WaveID) { if(i - 1 >= 0) { waveTime += cfgCreateEnemy[i - 1].WaveTime; } id = cfgCreateEnemy[i].WaveID; } createdEnemy.Add(false); createEnemyTime.Add(new List { waveTime + cfgCreateEnemy[i].StartTime, waveTime + cfgCreateEnemy[i].EndTime }); createdEnemyTower.Add(""); createdEnemyTowerHp.Add(0); } } if (GameManager.instance.leveType == LeveType.Conclusion || LevelSelect.instance.isDebug && LevelSelect.instance.isAddLevel_debug) { createdEnemy1 = new List(); createEnemyTime1 = new List>(); createdEnemyTower1 = new List(); createdEnemyTowerHp1 = new List(); int startId1; int endId1; cfgCreateEnemy1 = GameManager.instance.createEnemyConfigs[levelTypes[1]].DataList; startId1 = levelSelect.levelsId[levelTypes[1]][levelSelect.curLevelID]; endId1 = levelSelect.curLevelID < levelSelect.levels.Count ? levelSelect.levelsId[levelTypes[1]][levelSelect.curLevelID + 1] : cfgCreateEnemy.Count; id = 0; waveTime = 0; for (int i = startId1 + 1; i < endId1; i++) { if (cfgCreateEnemy1[i].WaveID != 0) { startId1 = i - 1; break; } } idRange1 = new Vector2Int(startId1, endId1); for (int i = startId1 + 1; i < endId1; i++) { if (cfgCreateEnemy1[i].WaveID == 0) { Debug.LogError("出怪表导入数据异常"); } else if (cfgCreateEnemy1[i].WaveID < 1) { createdEnemy1.Add(false); createEnemyTime1.Add(new List { 0, 0 }); if (id != cfgCreateEnemy1[i].WaveID) { createdEnemyTower1.Add(cfgCreateEnemy1[i].BuildingID); createdEnemyTowerHp1.Add(cfgCreateEnemy1[i].BuildingHP); id = cfgCreateEnemy1[i].WaveID; } else { int l = createdEnemyTower1.Count; createdEnemyTower1.Add(createdEnemyTower1[l - 1]); createdEnemyTowerHp1.Add(createdEnemyTowerHp1[l - 1]); } } else { createdEnemy1.Add(false); createEnemyTime1.Add(new List { waveTime + cfgCreateEnemy1[i].StartTime, waveTime + cfgCreateEnemy1[i].EndTime }); createdEnemyTower1.Add(""); createdEnemyTowerHp1.Add(0); if (id != cfgCreateEnemy1[i].WaveID) { waveTime += cfgCreateEnemy1[i].WaveTime; id = cfgCreateEnemy1[i].WaveID; } } } } } //计算是九个出怪表中的哪个出怪表 public void GetLevelOrientation(int id) { List soldierRank = new List(); for(int i = 0; i < 3; i++) { soldierRank.Add(SoldierEXP.expInstance.ssexp[i].level); } List> idSort = new List>(); if (soldierRank[0] == soldierRank[1]) { idSort.Add(new List { 0, 1 }); if (soldierRank[2] == idSort[0][0]) { idSort[0].Add(2); } else if (soldierRank[2] > idSort[0][0]) { idSort.Insert(0, new List { 2 }); } else { idSort.Add(new List { 2 }); } } else { if (soldierRank[0] > soldierRank[1]) { idSort.Add(new List { 0 }); idSort.Add(new List { 1 }); } else { idSort.Add(new List { 1 }); idSort.Add(new List { 0 }); } for(int i = 0; i < 2; i++) { if(soldierRank[2] > soldierRank[idSort[i][0]]) { idSort.Insert(i, new List { 2 }); break; } if(soldierRank[2] == soldierRank[idSort[i][0]]) { idSort[i].Add(2); break; } if(i == 1) { idSort.Add(new List { 2 }); } } } List idList = new List { 6,4,1 }; int x0 = -1; int x1 = -1; switch (idSort.Count) { case 1: levelTypes[id] = Random.Range(1, 9); break; case 2: switch (idSort[id].Count) { case 1: levelTypes[id] = idList[idSort[id][0]]; break; case 2: x0 = idSort[id][0]; x1 = idSort[id][1]; if(x0 == 0 && x1 == 2) { levelTypes[id] = Random.Range(7, 9); } else { levelTypes[id] = Random.Range(idList[x1] + 1, idList[x0]); } break; } break; case 3: x0 = Mathf.Min(idSort[0 + id * 2][0], idSort[1][0]); x1 = Mathf.Max(idSort[0 + id * 2][0], idSort[1][0]); if (x0 == 0 && x1 == 2) { levelTypes[id] = Random.Range(7, 9); } else { levelTypes[id] = Random.Range(idList[x1] + 1, idList[x0]); } break; } if (id == 1 && levelTypes[1] == levelTypes[0]) { GetLevelOrientation(1); } } public void OnGameTimeChange(float gameTime) { for (int i = idRange[0] + 1; i < idRange[1]; i++) { int id = i - idRange[0] - 1; if (!createdEnemy[id]) { if (cfgCreateEnemy[i].WaveID == 0) { createdEnemy[id] = true; StartCreateEnemy(cfgCreateEnemy[i]); } else if (cfgCreateEnemy[i].WaveID < 1) { EnemyTower enemyTower = enemyCreateTowerDic[createdEnemyTower[id]]; if (enemyTower != null && enemyTower.hp <= enemyTower.totalHp * createdEnemyTowerHp[id] / 100f) { createdEnemy[id] = true; StartCreateEnemy(cfgCreateEnemy[i]); } } else { if (createEnemyTime[id][0] <= gameTime) { createdEnemy[id] = true; StartCreateEnemy(cfgCreateEnemy[i]); } } } } if (GameManager.instance.leveType == LeveType.Conclusion) { for (int i = idRange1[0] + 1; i < idRange1[1]; i++) { int id = i - idRange1[0] - 1; if (!createdEnemy1[id]) { if (cfgCreateEnemy1[i].WaveID == 0) { Debug.LogError("出怪表导入数据异常"); } else if (cfgCreateEnemy1[i].WaveID < 1) { EnemyTower enemyTower = enemyCreateTowerDic[createdEnemyTower1[id]]; if (enemyTower != null && enemyTower.hp <= enemyTower.totalHp * createdEnemyTowerHp1[id] / 100f) { createdEnemy1[id] = true; StartCreateEnemy(cfgCreateEnemy1[i]); } } else { if (createEnemyTime1[id][0] <= gameTime) { createdEnemy1[id] = true; StartCreateEnemy(cfgCreateEnemy1[i]); } } } } } } //每一行怪 public async void StartCreateEnemy(SingleCreateEnemyConfig cfgCreateEnemy) { if (!instance) { return; } if (cfgCreateEnemy.Count == 0 || cfgCreateEnemy.Position.Count < 2) { return; } if (cfgCreateEnemy.Count == 1) { int randId = Random.Range(0, cfgCreateEnemy.Position.Count / 2 - 1); Vector3 pos = new Vector3(cfgCreateEnemy.Position[randId * 2], cfgCreateEnemy.Position[randId * 2 + 1], 0); CreateEnemy(cfgCreateEnemy, pos, true); return; } int num1 = cfgCreateEnemy.Count / (cfgCreateEnemy.Position.Count / 2); int num2 = cfgCreateEnemy.Count % (cfgCreateEnemy.Position.Count / 2); float TimeInterval = cfgCreateEnemy.StartTime >= cfgCreateEnemy.EndTime ? 0 : (float)(cfgCreateEnemy.EndTime - cfgCreateEnemy.StartTime) / (num2 == 0 ? num1 - 1 : num1); for (int i = 0; i < num1; i++) { for (int j = 0; j < cfgCreateEnemy.Position.Count; j += 2) { Vector3 pos = new Vector3(cfgCreateEnemy.Position[j], cfgCreateEnemy.Position[j + 1], 0); CreateEnemy(cfgCreateEnemy, pos, true); } await Task.Delay((int)(TimeInterval * 1000), _cancellationTokenSource.Token); if (this == null || !this.isActiveAndEnabled || !GameManager.instance.isGaming) { Debug.Log("取消任务"); return; // 如果对象已被销毁,直接返回 } } List randomPos = new(cfgCreateEnemy.Position); for (int i = 0; i < num2; i++) { int randId = Random.Range(0, randomPos.Count / 2 - 1); Vector3 pos = new Vector3(randomPos[randId * 2], randomPos[randId * 2 + 1], 0); randomPos.Remove(randId * 2 + 1); randomPos.Remove(randId * 2); CreateEnemy(cfgCreateEnemy, pos, true); } } //出怪表每一行怪 public void CreateEnemy(SingleCreateEnemyConfig cfg, Vector3 pos, bool active = false) { float ratio = GameManager.instance.levelRatio; CreateEnemyInit(cfg.EnemyName, cfg.WaveName, cfg.HPRatio * ratio, cfg.AttackRatio * ratio, cfg.SpeedRatio, cfg.ArmorRatio, cfg.ArmorPiercingRatio, pos, active); } public GameObject CreateEnemyInit(string EnemyName, string WaveName, float HPRatio, float AttackRatio, float SpeedRatio, float ArmorRatio, float ArmorPiercingRatio, Vector3 pos, bool active = false) { SingleEnemyConfig cfgEnemy = GameManager.instance.allCfgData.CfgEnemy.Get(EnemyName); if (cfgEnemy.Type == "ESpirits" && GameManager.instance.leveType == LeveType.Development) { return null; } string enemyStr = $"Prefab/{cfgEnemy.Type}/{cfgEnemy.EnemyPrefab}"; float posx = pos.x + Random.Range(-cfgEnemy.Radius[0], cfgEnemy.Radius[0]); float posy = pos.y + Random.Range(-cfgEnemy.Radius[1], cfgEnemy.Radius[1]) - 1; pos = new Vector3(posx, posy <= 0 ? 0 : posy, 0); GameObject enemyObj = Util.Instantiate(enemyStr, pos, active: active); AttackInfo attackInfo; if(cfgEnemy.Type == "Tower") { EnemyTower enemyTower = enemyObj.GetComponent(); Tower tower = enemyObj.GetComponent(); if (enemyTower != null) { enemyTower.name = cfgEnemy.Name; enemyTower.totalHp = (int)(cfgEnemy.HP * HPRatio); enemyTower.hp = enemyTower.totalHp; attackInfo = enemyTower.attackController.attackInfo; attackInfo.damage = (int)(cfgEnemy.AttackMarch[0] * AttackRatio); enemyTower.attackController.attackInfo = attackInfo; enemyTower.Init(); } if (tower != null) { tower.name = cfgEnemy.Name; tower.totalHp = (int)(cfgEnemy.HP * HPRatio); tower.hp = tower.totalHp; attackInfo = tower.attackController.attackInfo; attackInfo.damage = (int)(cfgEnemy.AttackMarch[0] * AttackRatio); tower.attackController.attackInfo = attackInfo; tower.Init(); } if (!buildingDic.ContainsKey(cfgEnemy.Name)) { buildingDic.Add(cfgEnemy.Name, new List()); } buildingDic[cfgEnemy.Name].Add(enemyObj); enemyCreateTowerDic[WaveName] = enemyTower; } else { Enemy enemy = enemyObj.GetComponent(); enemy.name = cfgEnemy.Name; if (!enemyDic.ContainsKey(cfgEnemy.Name)) { enemyDic.Add(cfgEnemy.Name, new List()); } enemyDic[cfgEnemy.Name].Add(enemy); enemy.totalHp = (int)(cfgEnemy.HP * HPRatio); enemy.hp = enemy.totalHp; enemy.minMoveSpeed = cfgEnemy.MinMoveSpeed * SpeedRatio; enemy.maxMoveSpeed = cfgEnemy.MaxMoveSpeed * SpeedRatio; enemy.attributeStatus.resistances.armor = (int)(enemy.attributeStatus.resistances.armor * ArmorRatio + 0.5f); foreach (var item in enemy.attackController.attackMethod) { if(item.id == 0) { item.attackInfo.damage = (int)(cfgEnemy.AttackSummon * AttackRatio); } else { item.attackInfo.damage = (int)(cfgEnemy.AttackMarch[item.id - 1] * AttackRatio); } item.attackInfo.armorPiercing.rate = (int)(item.attackInfo.armorPiercing.rate * ArmorPiercingRatio); } if (enemy.canFly) { enemy.flyHeight = enemy.transform.position.y; } enemy.Init(); enemy.SetSortingOrder(enemy.baseSortingOrder + enemyDic[cfgEnemy.Name].Count); } enemyObj.transform.position = pos; return enemyObj; } public void OnEnemyRecycle(Enemy enemy) { if (!enemyDic.ContainsKey(enemy.name)) { return; } enemyDic[enemy.name].Remove(enemy); for (int i = 0; i < enemyDic[enemy.name].Count; i++) { enemyDic[enemy.name][i].SetSortingOrder(enemy.baseSortingOrder + i); } } public Enemy GetMinDisOtherEnemy(Enemy self) { Enemy minDisEnemy = null; foreach (var item in enemyDic) { for (int i = 0; i < item.Value.Count; i++) { if (item.Value[i] != self && !item.Value[i].isDie && item.Value[i].gameObject.activeInHierarchy) { if (!minDisEnemy || (minDisEnemy.transform.position - self.transform.position).magnitude > (item.Value[i].transform.position - self.transform.position).magnitude) { minDisEnemy = item.Value[i]; } } } } return minDisEnemy; } }