Skip to content
This repository was archived by the owner on Mar 30, 2019. It is now read-only.

How the software works

Tom Crane edited this page Sep 10, 2017 · 4 revisions

How the software works.

This page is an overview of each of the components which make up this software. Refer to the project overview for info on where each of the components are. These are the components which will be expanded on in this page.

Plugin.cs

Plugin.cs is the main file of the bot and is the class which implements KRelay's IPlugin interface. It contains all of the packet hook methods as well as the code to move the bot and perform several other useful features.

#region IPlugin ... #endregion

These are the methods implemented from the IPlugin interface.

#region Keys ... #endregion

This region has 4 bool properties for each key. When the property is set, SendMessage(...) will potentially be called in order to simulate a keypress by sending the keycode as the wParam to the flash players window handle (hWnd). The key changed event is also invoked in order to update the GUI when a key changes.

#region WINAPI ... #endregion

Note: As of version 1.0.64 these methods have been moved to WinApi.cs in the Services/ folder.

These are methods which are platform invoked from the Windows API.

  • GetForegroundWindow() is used to bind the bot to the client.
  • SendMessage(...) is used for keyboard input simulation as well as some GUI functionality.
  • GetWindowRect(...) and ScreenToClient(...) are used in the press play feature to help locate the part of the screen to click on.

public void Initialize(Proxy proxy){ ... }

This is called when the plugin is initialized by KRelay. It is used for several things.

  • Instantiating lists.
  • GUI and config.
  • Attempt to auto bind with client.
  • proxy.HookCommand(...) declarations. These are the commands you can use in game.
  • proxy.HookPacket(...) declarations. These are the packets which the bot intercepts in order to operate.
  • Adds event handler subscriptions for client connection/disconnections, GUI events and message events.

private void ReceiveCommand(Client client, string cmd, string[] args){ ... }

This is where the in game commands are declared.

  • "bind" calls GetForegroundWindow() to get the hWnd of the flash player.
  • "start" starts the bot.
  • "gui" opens the gui.

private void Stop(){ ... }

This stops the bot and clears all lists used by the bot.

private void Start(){ ... }

This starts the bot. It checks if the current map is the nexus and if auto connect is enabled. If that is the case the bot will attempt to connect to the fullest realm. Otherwise it will just activate the bot.

private async void PressPlay(){ ... }

This is the method which is responsible for pressing the play button. First the method checks if the bot and auto connect are enabled and if the client is connected. If the client is not connected ScreenToClient(...) is called to convert a point in screen space to a point in a space relative to the client window. SendMessage(...) is then called to click and release the mouse. The coordinates are packed in to the lParam parameter of SendMessage(...) where the y-coordinate is represented by the higher-order 16 bits and the x-coordinate is represented by the lower-order 16 bits.

private void OnUpdate(Client client, Packet p){ ... }

This method is called every time an UPDATE packet is intercepted.

  • foreach(Entity obj in packet.NewObjs){ ... } - this loop updates all player positions, portals, enemies and rocks on the map.
  • foreach (int dropId in packet.Drops){ ... } - this loop removes old player positions, portals and enemies.

private void OnMapInfo(Client client, Packet p){ ... }

This method is called every time a MAPINFO packet is intercepted. It auto-escapes from Oryx's castle and starts moving to the realms if AutoConnect is enabled when in the nexus.

private void OnHit(Client client, Packet p)

This method is called every time a PLAYERHIT packet is intercepted. It logs a message when the current health is close to the autonexus threshold.

private void OnNewTick(Client client, Packet p){ ... }

This method is called every time a NEWTICK packet is intercepted. This is where a lot of the actual work happens.

  • Events to send info to the GUI are invoked.
  • AutoNexus is checked.
  • if (tickCount % config.TickCountThreshold == 0){ ... } - this code executes every config.TickCountThreshold ticks. It calls D36n4.Invoke(...) to find the targets on the map. If there are no suitable targets or if the bot runs out of targets it will escape to nexus.
  • // Updates - player positions, enemy positions and portal player counts are updated.
  • if (!followTarget && !gotoRealm){ ... } - keys are reset when the bot is not enabled.
  • if (followTarget && targets.Count > 0) { ... } - if the bot is able to run, choose an appropriate target position:
    • Get the target position, the average of all players in the target cluster.
    • Check if the player is further than config.TeleportDistanceThreshold game tiles away from the target position and teleport closer if required.
    • Check if there are any enemies within 7 game tiles of the player. (NOTE: DistanceSquaredTo(player) < 49 is exactly the same as DistanceTo(player) < 7 but the first is slightly faster). If there are enemies which are too close:
      1. The angle between the closest enemy and the player is calculated.
      2. The angle is used to find a point on the edge of a circle with radius 8 around the closest enemy
      3. The target position is updated to that point.
    • Check if there are any rocks closer within 2 game tiles of the player. If there are rocks which are too close:
      1. The difference in degrees between the angle from the player to the target position and the player to the closest rock is calculated.
      2. If the angle difference is less than 70 degrees the rock is considered to be in the way.
      3. Depending on the angle difference, either add or remove 90 degrees to the angle between the rock and the player in order to choose the fastest route around the rock.
      4. The target position is updated.
    • Finally, CalculateMovement(...) is called to make the bot move.

private void OnText(Client client, Packet p){ ... }

This method is called every time a TEXT packet is intercepted. It is used to send messages to the GUI.

private async void MoveToRealms(Client client){ ... }

This method is used to find the most full realm and move towards it. If the current health is below 95% full the bot will stop at the fountains to heal before moving on to the realms. If more than one full realm is found the bot will look for the realm which has the most players within 2 tiles of it.

private async void AttemptConnection(Client client, int portalId)

This method is used to connect to the realm. It checks whether there are less than 85 players in the realm and will send a USEPORTAL packet if there is a free spot. If not it will recursively call itself until it can connect.

private void CalculateMovement(Client client, Location targetPosition, float tolerance)

This method is responsible for calculating which keys need to be pressed in order to move towards a target.