public virtual void RefreshWaypoints() { if (TargetUnit == null || TargetUnit.IsDead || GetDistanceTo(TargetUnit) <= Stats.Range.Total && Waypoints.Count == 1) { return; } if (GetDistanceTo(TargetUnit) <= Stats.Range.Total - 2f) { SetWaypoints(new List <Vector2> { new Vector2(X, Y) }); } else { SetWaypoints(new List <Vector2>() { GetPosition(), TargetUnit.GetPosition() }); /* TODO: Soon we will use path finding for this. * if(CurWaypoint >= Waypoints.Count) * { * var newWaypoints = _game.Map.NavGrid.GetPath(GetPosition(), TargetUnit.GetPosition()); * if (newWaypoints.Count > 1) * { * SetWaypoints(newWaypoints); * } * }*/ } }
// AI tasks protected bool ScanForTargets() { if (TargetUnit != null && !TargetUnit.IsDead && Vector2.Distance(TargetUnit.GetPosition(), this.GetPosition()) < DETECT_RANGE) { return(true); } IAttackableUnit nextTarget = null; var nextTargetPriority = 14; var objects = _game.ObjectManager.GetObjects(); //Find target closest to max attack range. foreach (var it in objects.OrderBy(x => GetDistanceTo(x.Value) - Stats.Range.Total)) { if (!(it.Value is IAttackableUnit u) || u.IsDead || u.Team == Team || GetDistanceTo(u) > DETECT_RANGE || !_game.ObjectManager.TeamHasVisionOn(Team, u)) { continue; } var priority = (int)ClassifyTarget(u); // get the priority. if (priority < nextTargetPriority) // if the priority is lower than the target we checked previously { nextTarget = u; // make him a potential target. nextTargetPriority = priority; } } if (nextTarget != null) // If we have a target { TargetUnit = nextTarget; // Set the new target and refresh waypoints _game.PacketNotifier.NotifySetTarget(this, nextTarget); return(true); } _game.PacketNotifier.NotifyNPC_InstantStopAttack(this, false); IsAttacking = false; return(false); }
public bool RecalculateAttackPosition() { if (Target != null && TargetUnit != null && !TargetUnit.IsDead && GetDistanceTo(Target) < CollisionRadius && GetDistanceTo(TargetUnit.X, TargetUnit.Y) <= Stats.Range.Total)//If we are already where we should be, do not move. { return(false); } var objects = _game.ObjectManager.GetObjects(); List <CirclePoly> UsedPositions = new List <CirclePoly>(); var isCurrentlyOverlapping = false; var thisCollisionCircle = new CirclePoly(((Target)Target)?.GetPosition() ?? GetPosition(), CollisionRadius + 10); foreach (var gameObject in objects) { var unit = gameObject.Value as AttackableUnit; if (unit == null || unit.NetId == NetId || unit.IsDead || unit.Team != Team || unit.GetDistanceTo(TargetUnit) > DETECT_RANGE ) { continue; } var targetCollisionCircle = new CirclePoly(((Target)unit.Target)?.GetPosition() ?? unit.GetPosition(), unit.CollisionRadius + 10); if (targetCollisionCircle.CheckForOverLaps(thisCollisionCircle)) { isCurrentlyOverlapping = true; } UsedPositions.Add(targetCollisionCircle); } if (isCurrentlyOverlapping) { var targetCircle = new CirclePoly(((Target)TargetUnit.Target)?.GetPosition() ?? TargetUnit.GetPosition(), Stats.Range.Total, 72); //Find optimal position... foreach (var point in targetCircle.Points.OrderBy(x => GetDistanceTo(X, Y))) { if (_game.Map.NavGrid.IsWalkable(point)) { var positionUsed = false; foreach (var circlePoly in UsedPositions) { if (circlePoly.CheckForOverLaps(new CirclePoly(point, CollisionRadius + 10, 20))) { positionUsed = true; } } if (!positionUsed) { SetWaypoints(new List <Vector2> { GetPosition(), point }); return(true); } } } } return(false); }