private void OnNewTick(Client client, Packet p) { NewTickPacket packet = p as NewTickPacket; tickCount++; // Health changed event. float healthPercentage = (float)client.PlayerData.Health / (float)client.PlayerData.MaxHealth * 100f; healthChanged?.Invoke(this, new HealthChangedEventArgs(healthPercentage)); // Autonexus. if (healthPercentage < config.AutonexusThreshold && !(currentMapName?.Equals("Nexus") ?? false) && enabled) { Escape(client); } // Fame event. fameUpdate?.Invoke(this, new FameUpdateEventArgs(client.PlayerData?.CharacterFame ?? -1, client.PlayerData?.CharacterFameGoal ?? -1)); if (tickCount % config.TickCountThreshold == 0) { if (followTarget && playerPositions.Count > 0 && !gotoRealm) { List <Target> newTargets = D36n4.Invoke(playerPositions.Values.ToList(), config.Epsilon, config.MinPoints, config.FindClustersNearCenter); if (newTargets == null) { if (targets.Count != 0 && config.EscapeIfNoTargets) { Escape(client); } targets.Clear(); Log("No valid clusters found."); } else { if (targets.Count != newTargets.Count) { Log(string.Format("Now targeting {0} players.", newTargets.Count)); } targets = newTargets; } } tickCount = 0; } // Updates. foreach (Status status in packet.Statuses) { // Update player positions. if (playerPositions.ContainsKey(status.ObjectId)) { playerPositions[status.ObjectId].UpdatePosition(status.Position); } // Update enemy positions. if (enemies.Exists(en => en.ObjectId == status.ObjectId)) { enemies.Find(en => en.ObjectId == status.ObjectId).Location = status.Position; } // Update portal player counts when in nexus. if (portals.Exists(ptl => ptl.ObjectId == status.ObjectId) && (isInNexus)) { foreach (var data in status.Data) { if (data.StringValue != null) { var strCount = data.StringValue.Split(' ')[1].Split('/')[0].Remove(0, 1); portals[portals.FindIndex(ptl => ptl.ObjectId == status.ObjectId)].PlayerCount = int.Parse(strCount); } } } // Change the speed if in Nexus. if (isInNexus && status.ObjectId == client.ObjectId) { foreach (var data in status.Data) { if (data.Id == StatsType.Speed) { if (data.IntValue > 45) { List <StatData> list = new List <StatData>(status.Data) { new StatData { Id = StatsType.Speed, IntValue = 45 } }; status.Data = list.ToArray(); } } } } } // Reset keys if the bot is not active. if (!followTarget && !gotoRealm) { W_PRESSED = false; A_PRESSED = false; S_PRESSED = false; D_PRESSED = false; } if (followTarget && targets.Count > 0) { // Get the target position: the average of all current targets. var targetPosition = new Location(targets.Average(t => t.Position.X), targets.Average(t => t.Position.Y)); if (client.PlayerData.Pos.DistanceTo(targetPosition) > config.TeleportDistanceThreshold) { // If the distance exceeds the teleport threshold, send a text packet to teleport. var name = targets.OrderBy(t => t.Position.DistanceTo(targetPosition)).First().Name; if (name != client.PlayerData.Name) { var tpPacket = (PlayerTextPacket)Packet.Create(PacketType.PLAYERTEXT); tpPacket.Text = "/teleport " + name; client.SendToServer(tpPacket); } } if (enemies.Exists(en => en.Location.DistanceSquaredTo(client.PlayerData.Pos) <= 49)) { // If there is an enemy within 7 tiles, actively attempt to avoid it. Location closestEnemy = enemies.OrderBy(en => en.Location.DistanceSquaredTo(client.PlayerData.Pos)).First().Location; // Get the angle between the enemy and the player. double angle = Math.Atan2(client.PlayerData.Pos.Y - closestEnemy.Y, client.PlayerData.Pos.X - closestEnemy.X); // Calculate a point on a 'circle' around the enemy with a radius 8 at the angle specified. float newX = closestEnemy.X + 8f * (float)Math.Cos(angle); float newY = closestEnemy.Y + 8f * (float)Math.Sin(angle); var avoidPos = new Location(newX, newY); CalculateMovement(client, avoidPos, config.FollowDistanceThreshold); return; } if (rocks.Exists(rock => rock.Location.DistanceSquaredTo(client.PlayerData.Pos) <= 4)) { // If there is a rock within 2 tiles, actively attempt to move around it. Location closestRock = rocks.OrderBy(rock => rock.Location.DistanceSquaredTo(client.PlayerData.Pos)).First().Location; double angleDifference = client.PlayerData.Pos.GetAngleDifferenceDegrees(targetPosition, closestRock); if (Math.Abs(angleDifference) < 70.0) { double angle = Math.Atan2(client.PlayerData.Pos.Y - closestRock.Y, client.PlayerData.Pos.X - closestRock.X); if (angleDifference <= 0) { angle += (Math.PI / 2); // add 90 degrees to the angle to go clockwise around the rock. } if (angleDifference > 0) { angle -= (Math.PI / 2); // remove 90 degrees from the angle to go anti-clockwise around the rock. } float newX = closestRock.X + 2f * (float)Math.Cos(angle); float newY = closestRock.Y + 2f * (float)Math.Sin(angle); var avoidRockPos = new Location(newX, newY); CalculateMovement(client, avoidRockPos, 0.5f); return; } } CalculateMovement(client, targetPosition, config.FollowDistanceThreshold); } }
private void OnNewTick(Client client, Packet p) { NewTickPacket packet = p as NewTickPacket; tickCount++; float healthPercentage = (float)client.PlayerData.Health / (float)client.PlayerData.MaxHealth * 100f; healthChanged?.Invoke(this, new HealthChangedEventArgs(healthPercentage)); if (healthPercentage < config.AutonexusThreshold && !(currentMapName?.Equals("Nexus") ?? false) && enabled) { Escape(client); } fameUpdate?.Invoke(this, new FameUpdateEventArgs(client.PlayerData?.CharacterFame ?? -1, client.PlayerData?.CharacterFameGoal ?? -1)); if (tickCount % config.TickCountThreshold == 0) { if (followTarget && playerPositions.Count > 0 && !gotoRealm) { List <Target> newTargets = D36n4.Invoke(playerPositions.Values.ToList(), config.Epsilon, config.MinPoints, config.FindClustersNearCenter); if (newTargets == null) { if (targets.Count != 0 && config.EscapeIfNoTargets) { Escape(client); } targets.Clear(); Log("No valid clusters found."); } else { if (targets.Count != newTargets.Count) { Log(string.Format("Now targeting {0} players.", newTargets.Count)); } targets = newTargets; } } tickCount = 0; } foreach (Status status in packet.Statuses) { if (playerPositions.ContainsKey(status.ObjectId)) { playerPositions[status.ObjectId].UpdatePosition(status.Position); } if (enemies.Exists(en => en.ObjectId == status.ObjectId)) { enemies.Find(en => en.ObjectId == status.ObjectId).Location = status.Position; } if (portals.Exists(ptl => ptl.ObjectId == status.ObjectId) && (isInNexus)) { foreach (var data in status.Data) { if (data.StringValue != null) { var strCount = data.StringValue.Split(' ') [1].Split('/') [0].Remove(0, 1); portals[portals.FindIndex(ptl => ptl.ObjectId == status.ObjectId)].PlayerCount = int.Parse(strCount); } } } if (isInNexus && status.ObjectId == client.ObjectId) { foreach (var data in status.Data) { if (data.Id == StatsType.Speed) { if (data.IntValue > 45) { List <StatData> list = new List <StatData> (status.Data) { new StatData { Id = StatsType.Speed, IntValue = 45 } }; status.Data = list.ToArray(); } } } } } if (enabled) { if (lastLocation != null) { if (client.PlayerData.Pos.X == lastLocation.X && client.PlayerData.Pos.Y == lastLocation.Y) { ResetAllKeys(); } } lastLocation = client.PlayerData.Pos; } if (!followTarget && !gotoRealm) { ResetAllKeys(); } if (followTarget && targets.Count > 0) { var targetPosition = new Location(targets.Average(t => t.Position.X), targets.Average(t => t.Position.Y)); if (lastAverage != null) { var dir = targetPosition.Subtract(lastAverage); var faraway = targetPosition.Add(dir.Scale(20)); var desiredTargets = (int)(targets.Count * (config.TrainTargetPercentage / 100f)); List <Target> newTargets = new List <Target> (); for (int i = 0; i < desiredTargets; i++) { var closest = targets.OrderBy((t) => t.Position.DistanceSquaredTo(faraway)).First(); newTargets.Add(closest); targets.RemoveAll((t) => t.Name == closest.Name); } targets.AddRange(newTargets); lastAverage = targetPosition; targetPosition = new Location(newTargets.Average(t => t.Position.X), newTargets.Average(t => t.Position.Y)); } else { lastAverage = targetPosition; } if (client.PlayerData.Pos.DistanceTo(targetPosition) > config.TeleportDistanceThreshold) { var name = targets.OrderBy(t => t.Position.DistanceTo(targetPosition)).First().Name; if (name != client.PlayerData.Name) { var tpPacket = (PlayerTextPacket)Packet.Create(PacketType.PLAYERTEXT); tpPacket.Text = "/teleport " + name; client.SendToServer(tpPacket); } } if (config.EnableEnemyAvoidance && enemies.Exists(en => en.Location.DistanceSquaredTo(client.PlayerData.Pos) <= (config.EnemyAvoidanceDistance * config.EnemyAvoidanceDistance))) { Location closestEnemy = enemies.OrderBy(en => en.Location.DistanceSquaredTo(client.PlayerData.Pos)).First().Location; double angleDifference = client.PlayerData.Pos.GetAngleDifferenceDegrees(targetPosition, closestEnemy); if (Math.Abs(angleDifference) < 70.0) { double angle = Math.Atan2(client.PlayerData.Pos.Y - closestEnemy.Y, client.PlayerData.Pos.X - closestEnemy.X); if (angleDifference <= 0) { angle += (Math.PI / 2); } if (angleDifference > 0) { angle -= (Math.PI / 2); } float newX = closestEnemy.X + config.EnemyAvoidanceDistance * (float)Math.Cos(angle); float newY = closestEnemy.Y + config.EnemyAvoidanceDistance * (float)Math.Sin(angle); var avoidPos = new Location(newX, newY); CalculateMovement(client, avoidPos, config.FollowDistanceThreshold); return; } } if (obstacles.Exists(obstacle => obstacle.Location.DistanceSquaredTo(client.PlayerData.Pos) <= 4)) { Location closestObstacle = obstacles.OrderBy(obstacle => obstacle.Location.DistanceSquaredTo(client.PlayerData.Pos)).First().Location; double angleDifference = client.PlayerData.Pos.GetAngleDifferenceDegrees(targetPosition, closestObstacle); if (Math.Abs(angleDifference) < 70.0) { double angle = Math.Atan2(client.PlayerData.Pos.Y - closestObstacle.Y, client.PlayerData.Pos.X - closestObstacle.X); if (angleDifference <= 0) { angle += (Math.PI / 2); } if (angleDifference > 0) { angle -= (Math.PI / 2); } float newX = closestObstacle.X + 2f * (float)Math.Cos(angle); float newY = closestObstacle.Y + 2f * (float)Math.Sin(angle); var avoidObstaclePos = new Location(newX, newY); CalculateMovement(client, avoidObstaclePos, 0.75f); return; } } CalculateMovement(client, targetPosition, config.FollowDistanceThreshold); } }