EnemyCreater.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using cfg;
  4. using System.Threading.Tasks;
  5. using Base.Common;
  6. using System.Threading;
  7. using System.IO;
  8. using OfficeOpenXml;
  9. public class EnemyCreater : MonoBehaviour
  10. {
  11. public LevelSelect levelSelect;
  12. private CancellationTokenSource _cancellationTokenSource;
  13. public static EnemyCreater instance;
  14. public SoldierEXP soldierEXP;
  15. public List<SingleCreateEnemyConfig> cfgCreateEnemy;
  16. public List<SingleCreateEnemyConfig> cfgCreateEnemy1;
  17. public List<bool> createdEnemy;
  18. public List<bool> createdEnemy1;
  19. public List<List<float>> createEnemyTime = new();
  20. public List<List<float>> createEnemyTime1 = new();
  21. public Dictionary<string, List<Enemy>> enemyDic;
  22. public Dictionary<string, List<GameObject>> buildingDic;
  23. public Vector2Int idRange; //当前关卡为出怪表[x,y]行
  24. public Vector2Int idRange1; //当前关卡为出怪表[x,y]行
  25. public Dictionary<string, EnemyTower> enemyCreateTowerDic;
  26. public List<string> createdEnemyTower = new();
  27. public List<string> createdEnemyTower1 = new();
  28. public List<float> createdEnemyTowerHp = new();
  29. public List<float> createdEnemyTowerHp1 = new();
  30. public int nowLevel;
  31. public int[] levelTypes; //“承”“转”关卡的类型
  32. private void Awake()
  33. {
  34. if (!instance)
  35. {
  36. instance = this;
  37. }
  38. else
  39. {
  40. DestroyImmediate(gameObject);
  41. return;
  42. }
  43. soldierEXP = GetComponent<SoldierEXP>();
  44. }
  45. private void Start()
  46. {
  47. levelSelect.ReloadCfg();
  48. _cancellationTokenSource = new CancellationTokenSource();
  49. Init();
  50. ////把所有怪物prefab生成一遍防止后面初次生成卡顿
  51. ////foreach (var item in createCharacter)
  52. ////{
  53. //// for(int i = 0; i < item.tile.spawnTime[item.spawnTimeId].num; i++)
  54. //// {
  55. //// CreateEnemy(item.tile, Vector3.zero, 1, 1,false);
  56. //// }
  57. ////}
  58. }
  59. public void Init()
  60. {
  61. if (LevelSelect.instance.isDebug)
  62. {
  63. if (LevelSelect.instance.isAddLevel_debug)
  64. {
  65. levelTypes[1] = LevelSelect.instance.levelIdB_debug;
  66. GameManager.instance.leveType = LeveType.Conclusion;
  67. }
  68. nowLevel = LevelSelect.instance.levelIdA_debug;
  69. }
  70. else
  71. {
  72. switch (GameManager.instance.leveType)
  73. {
  74. case LeveType.Introduction:
  75. nowLevel = 0;
  76. break;
  77. case LeveType.Development:
  78. nowLevel = levelTypes[0];
  79. break;
  80. case LeveType.Transition:
  81. nowLevel = levelTypes[1];
  82. break;
  83. case LeveType.Conclusion:
  84. nowLevel = levelTypes[0];
  85. break;
  86. }
  87. }
  88. enemyDic = new Dictionary<string, List<Enemy>>();
  89. buildingDic = new Dictionary<string, List<GameObject>>();
  90. enemyCreateTowerDic = new Dictionary<string, EnemyTower>();
  91. createdEnemy = new List<bool>();
  92. createEnemyTime = new List<List<float>>();
  93. createdEnemyTower = new List<string>();
  94. createdEnemyTowerHp = new List<float>();
  95. float waveTime = 0;
  96. float id = 0;
  97. int startId;
  98. int endId;
  99. cfgCreateEnemy = GameManager.instance.createEnemyConfigs[nowLevel].DataList;
  100. startId = levelSelect.levelsId[nowLevel][levelSelect.curLevelID];
  101. endId = levelSelect.curLevelID < levelSelect.levels.Count - 1 ?
  102. levelSelect.levelsId[nowLevel][levelSelect.curLevelID + 1]
  103. : cfgCreateEnemy.Count;
  104. if (cfgCreateEnemy[startId].WaveID != -1 || endId != cfgCreateEnemy.Count && cfgCreateEnemy[endId].WaveID != -1)
  105. {
  106. Debug.LogError("关卡导入出错");
  107. }
  108. FileInfo fileInfo = new FileInfo($"Luban/Config/Datas/EnemyCreater/出怪表{nowLevel}.xlsx");
  109. using (ExcelPackage package = new ExcelPackage(fileInfo))
  110. {
  111. List<string> excelWorksheets = ExcelEditor.ReadExcelSheetsInfo(package);
  112. float.TryParse(ExcelEditor.GetCellData(package, excelWorksheets[levelSelect.curLevelID], "F5"), out LevelSelect.EXPRatio);
  113. }
  114. idRange = new Vector2Int(startId, endId);
  115. for (int i = startId + 1; i < endId; i++)
  116. {
  117. if (cfgCreateEnemy[i].WaveID == 0)
  118. {
  119. createdEnemy.Add(false);
  120. createEnemyTime.Add(new List<float> { cfgCreateEnemy[i].StartTime, cfgCreateEnemy[i].EndTime });
  121. createdEnemyTower.Add("");
  122. createdEnemyTowerHp.Add(0);
  123. waveTime = cfgCreateEnemy[i].WaveTime;
  124. }
  125. else if (cfgCreateEnemy[i].WaveID < 1)
  126. {
  127. createdEnemy.Add(false);
  128. createEnemyTime.Add(new List<float> { 0, 0 });
  129. if (id != cfgCreateEnemy[i].WaveID)
  130. {
  131. createdEnemyTower.Add(cfgCreateEnemy[i].BuildingID);
  132. createdEnemyTowerHp.Add(cfgCreateEnemy[i].BuildingHP);
  133. id = cfgCreateEnemy[i].WaveID;
  134. }
  135. else
  136. {
  137. int l = createdEnemyTower.Count;
  138. createdEnemyTower.Add(createdEnemyTower[l - 1]);
  139. createdEnemyTowerHp.Add(createdEnemyTowerHp[l - 1]);
  140. }
  141. }
  142. else
  143. {
  144. createdEnemy.Add(false);
  145. createEnemyTime.Add(new List<float> { waveTime + cfgCreateEnemy[i].StartTime, waveTime + cfgCreateEnemy[i].EndTime });
  146. createdEnemyTower.Add("");
  147. createdEnemyTowerHp.Add(0);
  148. if (id != cfgCreateEnemy[i].WaveID)
  149. {
  150. waveTime += cfgCreateEnemy[i].WaveTime;
  151. id = cfgCreateEnemy[i].WaveID;
  152. }
  153. }
  154. }
  155. if (GameManager.instance.leveType == LeveType.Conclusion
  156. || LevelSelect.instance.isDebug && LevelSelect.instance.isAddLevel_debug)
  157. {
  158. createdEnemy1 = new List<bool>();
  159. createEnemyTime1 = new List<List<float>>();
  160. createdEnemyTower1 = new List<string>();
  161. createdEnemyTowerHp1 = new List<float>();
  162. int startId1;
  163. int endId1;
  164. cfgCreateEnemy1 = GameManager.instance.createEnemyConfigs[levelTypes[1]].DataList;
  165. startId1 = levelSelect.levelsId[levelTypes[1]][levelSelect.curLevelID];
  166. endId1 = levelSelect.curLevelID < levelSelect.levels.Count ?
  167. levelSelect.levelsId[levelTypes[1]][levelSelect.curLevelID + 1]
  168. : cfgCreateEnemy.Count;
  169. id = 0;
  170. waveTime = 0;
  171. for (int i = startId1 + 1; i < endId1; i++)
  172. {
  173. if (cfgCreateEnemy1[i].WaveID != 0)
  174. {
  175. startId1 = i - 1;
  176. break;
  177. }
  178. }
  179. idRange1 = new Vector2Int(startId1, endId1);
  180. for (int i = startId1 + 1; i < endId1; i++)
  181. {
  182. if (cfgCreateEnemy1[i].WaveID == 0)
  183. {
  184. Debug.LogError("出怪表导入数据异常");
  185. }
  186. else if (cfgCreateEnemy1[i].WaveID < 1)
  187. {
  188. createdEnemy1.Add(false);
  189. createEnemyTime1.Add(new List<float> { 0, 0 });
  190. if (id != cfgCreateEnemy1[i].WaveID)
  191. {
  192. createdEnemyTower1.Add(cfgCreateEnemy1[i].BuildingID);
  193. createdEnemyTowerHp1.Add(cfgCreateEnemy1[i].BuildingHP);
  194. id = cfgCreateEnemy1[i].WaveID;
  195. }
  196. else
  197. {
  198. int l = createdEnemyTower1.Count;
  199. createdEnemyTower1.Add(createdEnemyTower1[l - 1]);
  200. createdEnemyTowerHp1.Add(createdEnemyTowerHp1[l - 1]);
  201. }
  202. }
  203. else
  204. {
  205. createdEnemy1.Add(false);
  206. createEnemyTime1.Add(new List<float>
  207. { waveTime + cfgCreateEnemy1[i].StartTime, waveTime + cfgCreateEnemy1[i].EndTime });
  208. createdEnemyTower1.Add("");
  209. createdEnemyTowerHp1.Add(0);
  210. if (id != cfgCreateEnemy1[i].WaveID)
  211. {
  212. waveTime += cfgCreateEnemy1[i].WaveTime;
  213. id = cfgCreateEnemy1[i].WaveID;
  214. }
  215. }
  216. }
  217. }
  218. }
  219. //计算是九个出怪表中的哪个出怪表
  220. public void GetLevelOrientation(int id)
  221. {
  222. List<int> soldierRank = new List<int>();
  223. for(int i = 0; i < 3; i++)
  224. {
  225. soldierRank.Add(SoldierEXP.expInstance.ssexp[i].level);
  226. }
  227. List<List<int>> idSort = new List<List<int>>();
  228. if (soldierRank[0] == soldierRank[1])
  229. {
  230. idSort.Add(new List<int> { 0, 1 });
  231. if (soldierRank[2] == idSort[0][0])
  232. {
  233. idSort[0].Add(2);
  234. }
  235. else if (soldierRank[2] > idSort[0][0])
  236. {
  237. idSort.Insert(0, new List<int> { 2 });
  238. }
  239. else
  240. {
  241. idSort.Add(new List<int> { 2 });
  242. }
  243. }
  244. else
  245. {
  246. if (soldierRank[0] > soldierRank[1])
  247. {
  248. idSort.Add(new List<int> { 0 });
  249. idSort.Add(new List<int> { 1 });
  250. }
  251. else
  252. {
  253. idSort.Add(new List<int> { 1 });
  254. idSort.Add(new List<int> { 0 });
  255. }
  256. for(int i = 0; i < 2; i++)
  257. {
  258. if(soldierRank[2] > soldierRank[idSort[i][0]])
  259. {
  260. idSort.Insert(i, new List<int> { 2 });
  261. break;
  262. }
  263. if(soldierRank[2] == soldierRank[idSort[i][0]])
  264. {
  265. idSort[i].Add(2);
  266. break;
  267. }
  268. if(i == 1)
  269. {
  270. idSort.Add(new List<int> { 2 });
  271. }
  272. }
  273. }
  274. List<int> idList = new List<int> { 6,4,1 };
  275. int x0 = -1;
  276. int x1 = -1;
  277. switch (idSort.Count)
  278. {
  279. case 1:
  280. levelTypes[id] = Random.Range(1, 9);
  281. break;
  282. case 2:
  283. switch (idSort[id].Count)
  284. {
  285. case 1:
  286. levelTypes[id] = idList[idSort[id][0]];
  287. break;
  288. case 2:
  289. x0 = idSort[id][0];
  290. x1 = idSort[id][1];
  291. if(x0 == 0 && x1 == 2)
  292. {
  293. levelTypes[id] = Random.Range(7, 9);
  294. }
  295. else
  296. {
  297. levelTypes[id] = Random.Range(idList[x1] + 1, idList[x0]);
  298. }
  299. break;
  300. }
  301. break;
  302. case 3:
  303. x0 = Mathf.Min(idSort[0 + id * 2][0], idSort[1][0]);
  304. x1 = Mathf.Max(idSort[0 + id * 2][0], idSort[1][0]);
  305. if (x0 == 0 && x1 == 2)
  306. {
  307. levelTypes[id] = Random.Range(7, 9);
  308. }
  309. else
  310. {
  311. levelTypes[id] = Random.Range(idList[x1] + 1, idList[x0]);
  312. }
  313. break;
  314. }
  315. if (id == 1 && levelTypes[1] == levelTypes[0])
  316. {
  317. GetLevelOrientation(1);
  318. }
  319. }
  320. public void OnGameTimeChange(float gameTime)
  321. {
  322. for (int i = idRange[0] + 1; i < idRange[1]; i++)
  323. {
  324. int id = i - idRange[0] - 1;
  325. if (!createdEnemy[id])
  326. {
  327. if (cfgCreateEnemy[i].WaveID == 0)
  328. {
  329. createdEnemy[id] = true;
  330. StartCreateEnemy(cfgCreateEnemy[i]);
  331. }
  332. else if (cfgCreateEnemy[i].WaveID < 1)
  333. {
  334. EnemyTower enemyTower = enemyCreateTowerDic[createdEnemyTower[id]];
  335. if (enemyTower != null && enemyTower.hp <= enemyTower.totalHp * createdEnemyTowerHp[id] / 100f)
  336. {
  337. createdEnemy[id] = true;
  338. StartCreateEnemy(cfgCreateEnemy[i]);
  339. }
  340. }
  341. else
  342. {
  343. if (createEnemyTime[id][0] <= gameTime)
  344. {
  345. createdEnemy[id] = true;
  346. StartCreateEnemy(cfgCreateEnemy[i]);
  347. }
  348. }
  349. }
  350. }
  351. if (GameManager.instance.leveType == LeveType.Conclusion)
  352. {
  353. for (int i = idRange1[0] + 1; i < idRange1[1]; i++)
  354. {
  355. int id = i - idRange1[0] - 1;
  356. if (!createdEnemy1[id])
  357. {
  358. if (cfgCreateEnemy1[i].WaveID == 0)
  359. {
  360. Debug.LogError("出怪表导入数据异常");
  361. }
  362. else if (cfgCreateEnemy1[i].WaveID < 1)
  363. {
  364. EnemyTower enemyTower = enemyCreateTowerDic[createdEnemyTower1[id]];
  365. if (enemyTower != null && enemyTower.hp <= enemyTower.totalHp * createdEnemyTowerHp1[id] / 100f)
  366. {
  367. createdEnemy1[id] = true;
  368. StartCreateEnemy(cfgCreateEnemy1[i]);
  369. }
  370. }
  371. else
  372. {
  373. if (createEnemyTime1[id][0] <= gameTime)
  374. {
  375. createdEnemy1[id] = true;
  376. StartCreateEnemy(cfgCreateEnemy1[i]);
  377. }
  378. }
  379. }
  380. }
  381. }
  382. }
  383. //每一行怪
  384. public async void StartCreateEnemy(SingleCreateEnemyConfig cfgCreateEnemy)
  385. {
  386. if (!instance)
  387. {
  388. return;
  389. }
  390. if (cfgCreateEnemy.Count == 0 || cfgCreateEnemy.Position.Count < 2)
  391. {
  392. return;
  393. }
  394. if (cfgCreateEnemy.Count == 1)
  395. {
  396. int randId = Random.Range(0, cfgCreateEnemy.Position.Count / 2 - 1);
  397. Vector3 pos = new Vector3(cfgCreateEnemy.Position[randId * 2], cfgCreateEnemy.Position[randId * 2 + 1], 0);
  398. CreateEnemy(cfgCreateEnemy, pos, true);
  399. return;
  400. }
  401. int num1 = cfgCreateEnemy.Count / (cfgCreateEnemy.Position.Count / 2);
  402. int num2 = cfgCreateEnemy.Count % (cfgCreateEnemy.Position.Count / 2);
  403. float TimeInterval = cfgCreateEnemy.StartTime >= cfgCreateEnemy.EndTime
  404. ? 0
  405. : (float)(cfgCreateEnemy.EndTime - cfgCreateEnemy.StartTime) / (num2 == 0 ? num1 - 1 : num1);
  406. for (int i = 0; i < num1; i++)
  407. {
  408. for (int j = 0; j < cfgCreateEnemy.Position.Count; j += 2)
  409. {
  410. Vector3 pos = new Vector3(cfgCreateEnemy.Position[j], cfgCreateEnemy.Position[j + 1], 0);
  411. CreateEnemy(cfgCreateEnemy, pos, true);
  412. }
  413. await Task.Delay((int)(TimeInterval * 1000), _cancellationTokenSource.Token);
  414. if (this == null || !this.isActiveAndEnabled || !GameManager.instance.isGaming)
  415. {
  416. Debug.Log("取消任务");
  417. return; // 如果对象已被销毁,直接返回
  418. }
  419. }
  420. List<int> randomPos = new(cfgCreateEnemy.Position);
  421. for (int i = 0; i < num2; i++)
  422. {
  423. int randId = Random.Range(0, randomPos.Count / 2 - 1);
  424. Vector3 pos = new Vector3(randomPos[randId * 2], randomPos[randId * 2 + 1], 0);
  425. randomPos.Remove(randId * 2 + 1);
  426. randomPos.Remove(randId * 2);
  427. CreateEnemy(cfgCreateEnemy, pos, true);
  428. }
  429. }
  430. //出怪表每一行怪
  431. public void CreateEnemy(SingleCreateEnemyConfig cfg, Vector3 pos, bool active = false)
  432. {
  433. float ratio = GameManager.instance.levelRatio;
  434. CreateEnemyInit(cfg.EnemyName,
  435. cfg.WaveName,
  436. cfg.HPRatio * ratio,
  437. cfg.AttackRatio * ratio,
  438. cfg.SpeedRatio,
  439. cfg.ArmorRatio,
  440. cfg.ArmorPiercingRatio,
  441. pos, active);
  442. }
  443. public GameObject CreateEnemyInit(string EnemyName, string WaveName,
  444. float HPRatio, float AttackRatio, float SpeedRatio, float ArmorRatio, float ArmorPiercingRatio,
  445. Vector3 pos, bool active = false)
  446. {
  447. SingleEnemyConfig cfgEnemy = GameManager.instance.allCfgData.CfgEnemy.Get(EnemyName);
  448. string enemyStr = $"Prefab/{cfgEnemy.Type}/{cfgEnemy.EnemyPrefab}";
  449. float posx = pos.x + Random.Range(-cfgEnemy.Radius[0], cfgEnemy.Radius[0]);
  450. float posy = pos.y + Random.Range(-cfgEnemy.Radius[1], cfgEnemy.Radius[1]) - 1;
  451. pos = new Vector3(posx, posy <= 0 ? 0 : posy, 0);
  452. GameObject enemyObj = Util.Instantiate(enemyStr, pos, active: active);
  453. AttackInfo attackInfo;
  454. if(cfgEnemy.Type == "Tower")
  455. {
  456. EnemyTower enemyTower = enemyObj.GetComponent<EnemyTower>();
  457. Tower tower = enemyObj.GetComponent<Tower>();
  458. if (enemyTower != null)
  459. {
  460. enemyTower.name = cfgEnemy.Name;
  461. enemyTower.totalHp = (int)(cfgEnemy.HP * HPRatio);
  462. enemyTower.hp = enemyTower.totalHp;
  463. attackInfo = enemyTower.attackController.attackInfo;
  464. attackInfo.damage = (int)(cfgEnemy.AttackMarch[0] * AttackRatio);
  465. enemyTower.attackController.attackInfo = attackInfo;
  466. enemyTower.Init();
  467. }
  468. if (tower != null)
  469. {
  470. tower.name = cfgEnemy.Name;
  471. tower.totalHp = (int)(cfgEnemy.HP * HPRatio);
  472. tower.hp = tower.totalHp;
  473. attackInfo = tower.attackController.attackInfo;
  474. attackInfo.damage = (int)(cfgEnemy.AttackMarch[0] * AttackRatio);
  475. tower.attackController.attackInfo = attackInfo;
  476. tower.Init();
  477. }
  478. if (!buildingDic.ContainsKey(cfgEnemy.Name))
  479. {
  480. buildingDic.Add(cfgEnemy.Name, new List<GameObject>());
  481. }
  482. buildingDic[cfgEnemy.Name].Add(enemyObj);
  483. enemyCreateTowerDic[WaveName] = enemyTower;
  484. }
  485. else
  486. {
  487. Enemy enemy = enemyObj.GetComponent<Enemy>();
  488. enemy.name = cfgEnemy.Name;
  489. if (!enemyDic.ContainsKey(cfgEnemy.Name))
  490. {
  491. enemyDic.Add(cfgEnemy.Name, new List<Enemy>());
  492. }
  493. enemyDic[cfgEnemy.Name].Add(enemy);
  494. enemy.totalHp = (int)(cfgEnemy.HP * HPRatio);
  495. enemy.hp = enemy.totalHp;
  496. enemy.minMoveSpeed = cfgEnemy.MinMoveSpeed * SpeedRatio;
  497. enemy.maxMoveSpeed = cfgEnemy.MaxMoveSpeed * SpeedRatio;
  498. enemy.attributeStatus.resistances.armor = (int)(enemy.attributeStatus.resistances.armor * ArmorRatio + 0.5f);
  499. foreach (var item in enemy.attackController.attackMethod)
  500. {
  501. if(item.id == 0)
  502. {
  503. item.attackInfo.damage = (int)(cfgEnemy.AttackSummon * AttackRatio);
  504. }
  505. else
  506. {
  507. item.attackInfo.damage = (int)(cfgEnemy.AttackMarch[item.id - 1] * AttackRatio);
  508. }
  509. item.attackInfo.armorPiercing.rate = (int)(item.attackInfo.armorPiercing.rate * ArmorPiercingRatio);
  510. }
  511. if (enemy.canFly)
  512. {
  513. enemy.flyHeight = enemy.transform.position.y;
  514. }
  515. enemy.Init();
  516. enemy.SetSortingOrder(enemy.baseSortingOrder + enemyDic[cfgEnemy.Name].Count);
  517. }
  518. enemyObj.transform.position = pos;
  519. return enemyObj;
  520. }
  521. public void OnEnemyRecycle(Enemy enemy)
  522. {
  523. if (!enemyDic.ContainsKey(enemy.name))
  524. {
  525. return;
  526. }
  527. enemyDic[enemy.name].Remove(enemy);
  528. for (int i = 0; i < enemyDic[enemy.name].Count; i++)
  529. {
  530. enemyDic[enemy.name][i].SetSortingOrder(enemy.baseSortingOrder + i);
  531. }
  532. }
  533. public Enemy GetMinDisOtherEnemy(Enemy self)
  534. {
  535. Enemy minDisEnemy = null;
  536. foreach (var item in enemyDic)
  537. {
  538. for (int i = 0; i < item.Value.Count; i++)
  539. {
  540. if (item.Value[i] != self && !item.Value[i].isDie && item.Value[i].gameObject.activeInHierarchy)
  541. {
  542. if (!minDisEnemy || (minDisEnemy.transform.position - self.transform.position).magnitude
  543. > (item.Value[i].transform.position - self.transform.position).magnitude)
  544. {
  545. minDisEnemy = item.Value[i];
  546. }
  547. }
  548. }
  549. }
  550. return minDisEnemy;
  551. }
  552. }