/// <summary> /// /// </summary> /// <param name="destination">Desired location to move</param> /// <param name="walkingSpeedMin">Minimal walking speed during the move</param> /// <param name="walkingSpeedMax">Maximal walking speed during the move</param> /// <param name="functionExecutedWhileWalking">Functions #1 to be exec while walking, like task or smth</param> /// <param name="functionExecutedWhileWalking2">Functions #1 to be exec while walking, like task or smth</param> /// <param name="cancellationToken">regular session cancelation token</param> /// <param name="session">ISession param of the bot, to detect which bot started it</param> /// <param name="direct">Directly move to the point, skip routing services</param> /// <param name="waypointsToVisit">Waypoints to visit during the move, required to redure Google Directions API usage</param> /// <param name="sendRoute">Send route to the bot</param> /// <returns></returns> internal async Task <PlayerUpdateResponse> Move(GeoCoordinate destination, double walkingSpeedMin, double walkingSpeedMax, Func <Task <bool> > functionExecutedWhileWalking, Func <Task <bool> > functionExecutedWhileWalking2, CancellationToken cancellationToken, ISession session, bool direct = false, List <GeoCoordinate> waypointsToVisit = null, bool sendRoute = true) { var currentLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude, _client.CurrentAltitude); var customRouteStartState = session.LogicSettings.UseCustomRoute; var result = new PlayerUpdateResponse(); var waypoints = waypointsToVisit; if (waypoints == null || !waypoints.Any()) { waypoints = new List <GeoCoordinate> { destination }; } if (session.LogicSettings.UseHumanPathing) { waypoints = await CreateHumanRoute(destination, cancellationToken, session, direct, waypointsToVisit, currentLocation); } if (waypoints.Count == 0) { waypoints = waypointsToVisit ?? new List <GeoCoordinate> { destination } } ; else if (waypoints.Count > 1 && sendRoute) { var nextPath = waypoints.Select(item => Tuple.Create(item.Latitude, item.Longitude)).ToList(); session.EventDispatcher.Send(new NextRouteEvent { Coords = nextPath }); destination = waypoints.Last(); } var navi = new Navigation(_client, UpdatePositionEvent); var waypointsArr = waypoints.ToArray(); long nextMaintenceStamp = 0; //MILD REWRITE TO USE HUMANPATHWALKING; long nextBuddyStamp = 0; foreach (var t in waypointsArr) { if (customRouteStartState != session.LogicSettings.UseCustomRoute) //custom route setting changed { return(result); } if (session.ForceMoveTo != null) { return(await ForceMoveTask.Execute(session, cancellationToken)); } // skip waypoints under 5 meters var sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude); var distanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, t); if (distanceToTarget <= 5) { continue; } var nextSpeed = RandomExtensions.NextInRange(session.Client.Rnd, walkingSpeedMin, walkingSpeedMax); session.State = BotState.Walk; result = await navi.HumanPathWalking(session, t, nextSpeed, functionExecutedWhileWalking, functionExecutedWhileWalking2, cancellationToken); if (session.Runtime.BreakOutOfPathing || session.ForceMoveJustDone) { return(result); } UpdatePositionEvent?.Invoke(t.Latitude, t.Longitude, t.Altitude); if (nextMaintenceStamp < DateTime.UtcNow.ToUnixTime() || session.Runtime.StopsHit > 100) { await MaintenanceTask.Execute(session, cancellationToken); nextMaintenceStamp = DateTime.UtcNow.AddMinutes(3).ToUnixTime(); } if (nextBuddyStamp < DateTime.UtcNow.ToUnixTime() || session.Runtime.StopsHit > 100) { await GetBuddyWalkedTask.Execute(session, cancellationToken); nextBuddyStamp = DateTime.UtcNow.AddMinutes(2).ToUnixTime(); } await ActionQueueTask.Execute(session, cancellationToken); if (session.EggWalker != null && nextSpeed * session.Settings.MoveSpeedFactor < 12) { await session.EggWalker.ApplyDistance(distanceToTarget, cancellationToken); } } session.State = BotState.Idle; var curcoord = new GeoCoordinate(session.Client.CurrentLatitude, session.Client.CurrentLongitude); if (LocationUtils.CalculateDistanceInMeters(curcoord, destination) > 40) { var nextSpeed = RandomExtensions.NextInRange(session.Client.Rnd, walkingSpeedMin, walkingSpeedMax) * session.Settings.MoveSpeedFactor; result = await navi.HumanPathWalking(session, destination, nextSpeed, functionExecutedWhileWalking, functionExecutedWhileWalking2, cancellationToken); } await ActionQueueTask.Execute(session, cancellationToken); await MaintenanceTask.Execute(session, cancellationToken); session.State = BotState.Idle; await ActionQueueTask.Execute(session, cancellationToken); await MaintenanceTask.Execute(session, cancellationToken); return(result); }
public async Task <PlayerUpdateResponse> HumanPathWalking(ISession session, GeoCoordinate targetLocation, double walkingSpeedInKilometersPerHour, Func <Task <bool> > functionExecutedWhileWalking, Func <Task <bool> > functionExecutedWhileWalking2, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); //PlayerUpdateResponse result = null; var speedInMetersPerSecond = walkingSpeedInKilometersPerHour / 3.6; var sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude); double distanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation); Logger.Write($"Distance to target location: {distanceToTarget:0.##} meters. Will take {distanceToTarget/speedInMetersPerSecond:0.##} seconds!", LogLevel.Debug); var nextWaypointBearing = LocationUtils.DegreeBearing(sourceLocation, targetLocation); nextWaypointBearing += FuzzyFactorBearing(); var nextWaypointDistance = speedInMetersPerSecond; GeoCoordinate waypoint; double altitudeStep; double altitude; var trueAlt = false; var round = rand.Next(5) == 0 ? 6 : 1; if (Math.Abs(targetLocation.Altitude) > 0.001) { trueAlt = true; altitudeStep = (_client.Settings.DefaultAltitude - targetLocation.Altitude) / (distanceToTarget / (nextWaypointDistance > 1 ? nextWaypointDistance : 1)); altitude = Math.Round(_client.Settings.DefaultAltitude - altitudeStep, round); altitudeStep = Math.Round(altitudeStep, round); waypoint = LocationUtils.CreateWaypoint(sourceLocation, nextWaypointDistance, nextWaypointBearing, altitude); } else { var altDiff = _client.Settings.DefaultAltitude - RandomExtensions.NextInRange(_client.Rnd, _client.Settings.DefaultAltitudeMin, _client.Settings.DefaultAltitudeMax); altitudeStep = altDiff / (distanceToTarget / nextWaypointDistance); if (Math.Abs(altDiff) < Math.Abs(altitudeStep)) { altitudeStep = altDiff; } altitude = Math.Round(_client.Settings.DefaultAltitude - altitudeStep, round); altitudeStep = Math.Round(altitudeStep, round); waypoint = LocationUtils.CreateWaypoint(sourceLocation, nextWaypointDistance, nextWaypointBearing, altitude); } //Initial walking var requestSendDateTime = DateTime.Now; var result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude); UpdatePositionEvent?.Invoke(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude); long actionQueueTimeStamp = 0; do { var factoredSpeed = speedInMetersPerSecond * session.Settings.MoveSpeedFactor; if (session.Runtime.BreakOutOfPathing) { if (session.Runtime.lastPokeStopCoordinate.Latitude.Equals(targetLocation.Latitude) && session.Runtime.lastPokeStopCoordinate.Longitude.Equals(targetLocation.Latitude)) { session.Runtime.BreakOutOfPathing = true; break; } } if (session.ForceMoveJustDone) { break; } cancellationToken.ThrowIfCancellationRequested(); var millisecondsUntilGetUpdatePlayerLocationResponse = (DateTime.Now - requestSendDateTime).TotalMilliseconds; sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude); var currentDistanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation); nextWaypointDistance = Math.Min(currentDistanceToTarget, millisecondsUntilGetUpdatePlayerLocationResponse / 1000 * factoredSpeed); nextWaypointBearing = LocationUtils.DegreeBearing(sourceLocation, targetLocation) + RandomExtensions.NextInRange(_client.Rnd, -11.25, 11.25); waypoint = LocationUtils.CreateWaypoint(sourceLocation, nextWaypointDistance, nextWaypointBearing); requestSendDateTime = DateTime.Now; result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, altitude); UpdatePositionEvent?.Invoke(waypoint.Latitude, waypoint.Longitude, altitude); altitude -= altitudeStep; if (!trueAlt && (altitude < _client.Settings.DefaultAltitudeMin || altitude > _client.Settings.DefaultAltitudeMax)) //Keep altitude in range { if (altitude < _client.Settings.DefaultAltitudeMin) { altitude = _client.Settings.DefaultAltitudeMin + RandomExtensions.NextInRange(_client.Rnd, 0.3, 0.5); } else { altitude = _client.Settings.DefaultAltitudeMin - RandomExtensions.NextInRange(_client.Rnd, 0.3, 0.5); } } else if (trueAlt) //Keep altitude in range { if (altitudeStep < 0 && altitude <= targetLocation.Altitude) { altitudeStep = 0; altitude = targetLocation.Altitude; } else if (altitudeStep > 0 && altitude >= targetLocation.Altitude) { altitudeStep = 0; altitude = targetLocation.Altitude; } } if (functionExecutedWhileWalking != null) { await functionExecutedWhileWalking(); // look for pokemon & hit stops } if (functionExecutedWhileWalking2 != null) { await functionExecutedWhileWalking2(); } if (actionQueueTimeStamp < DateTime.UtcNow.ToUnixTime()) { actionQueueTimeStamp = DateTime.UtcNow.AddMinutes(2).ToUnixTime(); await ActionQueueTask.Execute(session, cancellationToken); } await Task.Delay(300, cancellationToken); } while (LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation) >= 2 && session.Runtime.BreakOutOfPathing == false); if (trueAlt) { altitude = targetLocation.Altitude; } _client.Settings.DefaultAltitude = altitude; return(result); }