public void UpdateMonsterFlags(TrinityActor actor, AvoidanceLayer layer) { if (actor.ActorType != ActorType.Monster) { return; } foreach (var node in TrinityGrid.Instance.GetNodesInRadius(actor.Position, actor.CollisionRadius * MonsterWeightRadiusFactor)) { node.Weight += 2; if (actor.IsHostile) { node.HostileMonsterCount++; } node.AddNodeFlags(AvoidanceFlags.Monster); layer.Add(node); if (node.Center.Distance(actor.Position.ToVector2()) < actor.CollisionRadius) { node.AddNodeFlags(AvoidanceFlags.NavigationBlocking); } } }
public void UpdateKiteFromFlags(TrinityActor actor, AvoidanceLayer layer) { if (TrinityCombat.Routines.Current == null) { s_logger.Debug($"[{nameof(UpdateKiteFromFlags)}] UpdateKiteFromFlags failed to update becasue no routine is selected"); return; } var kiteMode = TrinityCombat.Routines.Current.KiteMode; var kiteDistance = TrinityCombat.Routines.Current.KiteDistance; if (kiteMode == KiteMode.Never) { return; } if (actor.ActorType != ActorType.Monster || actor.IsQuestMonster || actor.IsNpc) { return; } var kiteFromBoss = kiteMode == KiteMode.Bosses && actor.IsBoss; var kiteFromElites = kiteMode == KiteMode.Elites && actor.IsElite; var kiteAlways = kiteMode == KiteMode.Always; var isKiting = kiteFromBoss || kiteFromElites || kiteAlways; var weight = 1; if (!isKiting) { return; } foreach (var node in TrinityGrid.Instance.GetNodesInRadius(actor.Position, actor.CollisionRadius + kiteDistance)) { if (!node.IsWalkable) { continue; } node.Weight = weight; node.AddNodeFlags(AvoidanceFlags.KiteFrom); layer.Add(node); } }
public void UpdateGrid() { TrinityGrid.Instance.IsUpdatingNodes = true; using (new PerformanceLogger("UpdateGrid")) { HighestNodeWeight = 0; if (TrinityGrid.Instance.NearestNode == null || TrinityGrid.Instance.NearestNode.DynamicWorldId != ZetaDia.Globals.WorldId) { s_logger.Debug($"[{nameof(UpdateGrid)}] No Player Nearest Node or WorldId Mismatch"); Core.Scenes.Reset(); Core.Scenes.Update(); return; } var safeNodes = new AvoidanceLayer(); var kiteNodes = new AvoidanceLayer(); var avoidanceNodes = new AvoidanceLayer(); var monsterNodes = new AvoidanceLayer(); var obstacleNodes = new AvoidanceLayer(); var activeAvoidanceSnoIds = new HashSet <SNOActor>(); var kiteFromNodes = new AvoidanceLayer(); var nodePool = TrinityGrid.Instance .GetNodesInRadius(Core.Player.Position, node => node.IsWalkable, MaxDistance) .Select(n => n.Reset()).ToList(); //var allNodes = Grid.GetNodesInRadius(Core.Player.Position, node => node != null, MaxDistance).ToList(); var nearestNodes = TrinityGrid.Instance .GetNodesInRadius(Core.Player.Position, node => node != null && node.NodeFlags.HasFlag(NodeFlags.AllowWalk), Settings.AvoiderLocalRadius) .ToList(); var weightSettings = Settings.WeightingOptions; try { if (!ZetaDia.IsInGame || ZetaDia.Globals.IsLoadingWorld) { return; } if (!nodePool.Any()) { return; } foreach (var obj in Core.Targets) { if (obj.IsMe) { continue; } UpdateGizmoFlags(obj); UpdateGlobeFlags(obj); UpdateMonsterFlags(obj, monsterNodes); UpdateKiteFromFlags(obj, kiteFromNodes); UpdateProjectileBlockers(obj); } foreach (var door in Core.Actors.Actors.Where(a => a.Type == TrinityObjectType.Door)) { UpdateDoorFlags(door); } //foreach (var obstacle in CacheData.NavigationObstacles) //{ // UpdateObstacleFlags(obstacle, obstacleNodes); //} //UpdateBacktrackFlags(); foreach (var avoidance in Core.Avoidance.CurrentAvoidances) { try { if (!avoidance.Settings.IsEnabled || avoidance.IsImmune) { continue; } var handler = avoidance.Definition.Handler; if (handler == null) { s_logger.Error($"[{nameof(UpdateGrid)}] Avoidance: {avoidance.Definition.Name} has no handler"); continue; } if (avoidance.IsAllowed && !avoidance.IsExpired) { handler.UpdateNodes(TrinityGrid.Instance, avoidance); avoidance.Actors.ForEach(a => { activeAvoidanceSnoIds.Add(a.ActorSnoId); Core.DBGridProvider.AddCellWeightingObstacle(a.ActorSnoId, a.CollisionRadius); //Core.Logger.Warn(LogCategory.Avoidance, $"Avoidance Flagged {a} for {avoidance.Definition.Name}, handler={avoidance.Definition.Handler.GetType().Name}"); }); } else { //Core.Logger.Warn(LogCategory.Avoidance, $"Avoidance {avoidance.Definition.Name} is not allowed. Enabled={avoidance.Settings.IsEnabled} IsAllowed={avoidance.IsAllowed} PlayerHealth={Core.Player.CurrentHealthPct * 100} SettingsHealth={avoidance.Settings.HealthPct} "); } } catch (Exception ex) { s_logger.Error($"[{nameof(UpdateGrid)}] Exception in AvoidanceHandler updating nodes. Name={avoidance.Definition?.Name} Handler={avoidance.Definition?.Handler?.GetType()}", ex); } } AvoidanceCentroid = avoidanceNodes.GetCentroid(); MonsterCentroid = monsterNodes.GetCentroid(); foreach (var node in nodePool) { if (weightSettings.HasFlag(WeightingOptions.Backtrack) && node.AvoidanceFlags.HasFlag(AvoidanceFlags.Backtrack)) { node.Weight--; } if (weightSettings.HasFlag(WeightingOptions.AvoidanceCentroid) && node.NavigableCenter.Distance(AvoidanceCentroid) < 15f) { node.Weight += 2; } if (weightSettings.HasFlag(WeightingOptions.MonsterCentroid) && node.NavigableCenter.Distance(MonsterCentroid) > 15f) { node.Weight--; } // Disabled for performance - 12ms @80yd //if (Grid.IsInKiteDirection(node.NavigableCenter, 70)) //{ // node.AddNodeFlags(AvoidanceFlags.Kite); // node.Weight--; // kiteNodes.Add(node); //} //else //{ // node.Weight++; //} var anyAdjacentUnsafe = node.AdjacentNodes.Any(n => !n.NodeFlags.HasFlag(NodeFlags.AllowWalk) || n.AvoidanceFlags.HasFlag(AvoidanceFlags.Avoidance) || n.AvoidanceFlags.HasFlag(AvoidanceFlags.Monster) || n.AvoidanceFlags.HasFlag(AvoidanceFlags.KiteFrom)); if (!anyAdjacentUnsafe) { if (weightSettings.HasFlag(WeightingOptions.AdjacentSafe)) { node.Weight--; } node.AddNodeFlags(AvoidanceFlags.AdjacentSafe); safeNodes.Add(node); } if (node.Weight > HighestNodeWeight) { HighestNodeWeight = node.Weight; HighestNode = node; } } } catch (Exception ex) { s_logger.Error($"[{nameof(UpdateGrid)}] Exception in UpdateGrid", ex); if (ex is CoroutineStoppedException) { throw; } } //AllNodes = allNodes; CurrentNodes = nodePool; //.OrderBy(n => n.Weight).ThenByDescending(n => n.Distance).ToList(); SafeNodesByWeight = safeNodes.Nodes.OrderBy(n => n.Weight).ThenByDescending(n => n.Distance); SafeNodesByDistance = safeNodes.Nodes.OrderBy(n => n.Distance); SafeNodeLayer = safeNodes; KiteNodeLayer = kiteNodes; KiteFromLayer = kiteFromNodes; AvoidanceNodeLayer = avoidanceNodes; MonsterNodeLayer = monsterNodes; NearbyNodes = nearestNodes; ObstacleNodeLayer = obstacleNodes; ActiveAvoidanceSnoIds = activeAvoidanceSnoIds; } TrinityGrid.Instance.IsUpdatingNodes = true; }