using System; using Framework; using System.Linq; using Gameplay.Unit; using Gameplay.Area; using Gameplay.Level; using cfg.CharacterCfg; using Gameplay.Character; using System.Collections.Generic; namespace Gameplay.AI { public static partial class AIUtils { #region 寻找敌人 /// /// 寻找视野内的最近敌人 range为-1则为索敌范围 /// public static GameUnit FindNearestTarget(GameUnit owner, int range = -1, Ejob job = Ejob.Job_Other) { try { var inSightDistanceDic = FindEnemiesInRange(owner, range, job); return GetNearestUnit(inSightDistanceDic); } catch (Exception e) { DebugUtil.LogError("AIUtils.FindNearestTarget error: {0}", e); return null; } } /// /// 寻找范围内符合条件的所有敌人 /// public static Dictionary FindEnemiesInRange(GameUnit owner, int range = -1, Ejob job = Ejob.Job_Other, uint targetID = 0) { if (owner == null || range == 0) return null; var enemies = GameUnitManager.instance.SearchEnemies(owner); var filter = new EnemyFilter(owner, range, job, targetID); return AITargetFinder.FindUnits(owner, enemies, filter); } /// /// 获取最近的单位 /// public static GameUnit GetNearestUnit(Dictionary units) { var minDistance = float.MaxValue; GameUnit nearestUnit = null; foreach (var pair in units) { if (minDistance > pair.Value) { minDistance = pair.Value; nearestUnit = pair.Key; } } return nearestUnit; } /// /// 获取更近的攻击来源单位 /// public static GameUnit GetNearestAttackGameUnit(GameUnit owner, GameUnit newUnit, GameUnit unit) { try { if (owner == null || newUnit == null || unit == null) return null; var map = LevelManager.Instance.CurrentLevel.Map; if (map == null) return null; var ownerCellIndex = owner.transData?.cellIndex; var unitCellIndex = unit.transData?.cellIndex; var newUnitCellIndex = newUnit.transData?.cellIndex; if (!ownerCellIndex.HasValue || !unitCellIndex.HasValue || !newUnitCellIndex.HasValue) return null; var distance = MapUtils.Distance(map, ownerCellIndex.Value, unitCellIndex.Value); var newDistance = MapUtils.Distance(map, ownerCellIndex.Value, newUnitCellIndex.Value); return distance <= newDistance ? unit : newUnit; } catch (Exception e) { DebugUtil.LogError("AIUtils.GetNearestGameUnit error: {0}", e); // 异常返回默认单位 return unit; } } #endregion #region 寻找友军 /// /// 通过MonsterID寻找友军 只返回第一个Monster /// public static GameUnit FindFriendByMonsterID(int id) { foreach (var unit in GameUnitManager.instance.totalUnits.unitList) { if (unit.unitLevelData != null && !unit.statusData.isDead && unit.unitLevelData.monsterId == id) { return unit; } } return null; } /// /// 寻找视野内的最近敌人 range为-1则为索敌范围 /// public static GameUnit FindNearestFriend(GameUnit owner, int range = -1, Ejob job = Ejob.Job_Other) { try { var inSightDistanceDic = FindFriendInRange(owner, range, job); return GetNearestUnit(inSightDistanceDic); } catch (Exception e) { DebugUtil.LogError("AIUtils.FindNearestFriend error: {0}", e); return null; } } /// /// 寻找范围内符合条件的友军 /// public static Dictionary FindFriendInRange(GameUnit owner, int range = -1, Ejob job = Ejob.Job_Other) { if (owner == null || range == 0) return null; var friends = GameUnitManager.instance.SearchFriends(owner); var filter = new FriendFilter(owner, range, job); return AITargetFinder.FindUnits(owner, friends, filter); } /// /// 检测某个地格是否有友军单位 /// public static GameUnit FindFriendByCellIndex(int cellIndex) { var units = AreaManager.instance.GetUnitsByCellIndex(cellIndex); foreach (var unit in units) { if (unit.commonData.troopId == ETroopsId.Enemy) { return unit; } } return null; } #endregion #region 寻找随机目标 public static int FindRandomCell(GameUnit owner, int maxStep = 0) { try { var map = LevelManager.Instance.CurrentLevel?.Map; if (map == null || owner == null) return -1; var cellIndex = owner.transData.cellIndex; if (!AreaManager.instance.CheckContainsMoveUnit(cellIndex)) return -1; var randomCells = new List(); for (var i = 1; i <= maxStep; i++) { var minSteps = i - 1; var maxSteps = i; var cells = map.TerrainGridSystem.CellGetNeighboursWithinRange(cellIndex, minSteps, maxSteps, canCrossCheckType: TGS.CanCrossCheckType.IgnoreCanCrossCheckOnAllCells); foreach (var cell in cells) { if (!CheckCellCanSelect(cell)) continue; if (!PathFinder.CanBasePass(cell, owner)) continue; if (AreaManager.instance.CheckContainsMoveUnit(cell)) continue; if (maxSteps > 1) { if (CheckPathExits(owner, cell)) { randomCells.Add(cell); } } else { randomCells.Add(cell); } } } if (randomCells.Count == 0) return -1; var randomIndex = UnityEngine.Random.Range(0, randomCells.Count); return randomCells[randomIndex]; } catch (Exception e) { DebugUtil.LogError("AIUtils.FindRandomCell error: {0}", e); return -1; } } /// /// 寻找随机单位 /// public static GameUnit FindRandomTarget(GameUnit owner, uint enemy, int range = -1) { try { var targetID = enemy; var inSightDistanceDic = FindEnemiesInRange(owner, range, targetID: targetID); return GetRandomUnit(inSightDistanceDic); } catch (Exception e) { DebugUtil.LogError("AIUtils.FindRandomTarget error: {0}", e); return null; } } /// /// 获取随机单位 /// private static GameUnit GetRandomUnit(Dictionary units) { if (units == null || units.Count == 0) return null; var unitList = units.Keys.ToList(); var randomUnit = unitList[UnityEngine.Random.Range(0, unitList.Count)]; return randomUnit; } #endregion #region 组内单位 寻找 判断 public static bool GroupTargetInRange(GameUnit owner, List group) { var inRange = false; var groupFriends = FindGroupUnits(owner, group); foreach (var groupFriend in groupFriends) { var targetID = groupFriend.unitLevelData.AIBattleInfo.Value.targetID; if (targetID == Constants.INVALID_UINT_ID) continue; var target = GameUnitManager.instance.infightUnits.Search(targetID); var distance = GetDistance(owner.transData.cellIndex, target.transData.cellIndex); if (distance <= groupFriend.fightData.trackRange) { inRange = true; break; } } return inRange; } public static List FindGroupUnits(GameUnit owner, List group) { var groupUnits = new List(); if (owner == null || group == null || group.Count == 0) return groupUnits; var friends = GameUnitManager.instance.SearchFriends(owner); foreach (var friend in friends) { if (friend.unitLevelData == null || friend.unitLevelData.AIBattleInfo == null) continue; var unitGroups = friend.unitLevelData.AIBattleInfo.Value.groupInfo; if (unitGroups == null || unitGroups.Count <= 0) continue; // 检查当前单位的组ID列表与传入的组ID列表是否有交集 foreach (var groupId in unitGroups) { if (group.Contains(groupId)) { groupUnits.Add(friend); break; // 找到一个匹配就可以添加该单位,无需继续检查其他组ID } } } return groupUnits; } #endregion } }