We're also going to have to modify the Callback of EnumerateVisibleObjects in the ObjectManager class to handle this new object type. Recall that EnumerateVisibleObjects will call Callback internally, passing in the filter parameter, and the guid of the object. Thankfully, the guid for the player will always come back as 1, so we can look for that to easily find our player. First add a property on the ObjectManager class to store a reference to the local player:

internal WoWPlayer Player { get; private set; }

Then modify the Callback method to look for an object with a guid equal to 1, and set the Player parameter:

There's one quirk that we need to fix related to the Name property on the WoWUnit class. We access a Player's name in a different way. So we're going to modify the Name property on the WoWUnit class to make it virtual, then we'll override that method in the WoWPlayer class. I haven't looked too closely at this section of the decompiled code from the WoW client, but I assume all player names are stored in a specific area of memory, and non-player units' names are stored elsewhere. We have the base address of that player name collection. We also know the offset between names. So we start at the base address, then walk the collection until we find the guid of the Player, then we read a string from memory at that location. Here's the code for the WoWPlayer class:

Next we're going to start talking about positions in 3D space. It's very common in 3D games to use a 3D coordinate system to store the relative position of objects in the world. A basic understanding of geometry is necessary before jumping into the operations we'll be making in 3D coordinate space, so if this is new to you, take a look at this article.

Our bot needs to be able to move around, so eventually we're going to need to know the player's position in 3D space, as well as the position of all units around the player. Let's do that now. Unlike the Name property, both WoWUnit and WoWPlayer find their positions in the same relative place in memory, so we should add the new code to the base WoWUnit class. We'll most often be interested in all three dimensions at the same time (x, y, and z), so instead of implementing separate properties for each, let's create a Position class to encapsulate all three dimensions. Let's also have the Position class override the ToString() method so we can easily print a unit's position for debugging purposes. Here's the code::

Like usual, let's test this by modifying our Test method in the UI to print the position of all units. You'll see something like this:

Now that we know the player's position, and the positions of all units around the player, we can perform all sorts of useful calculations. A simple example would be finding the unit closest to the player. First, let's make a quick fix to the ObjectManager class. Consider the following code:

internal IEnumerable<WoWUnit> Units => Objects.OfType<WoWUnit>();

The Units property is actually going to return units AND players, because a WoWPlayer is actually a specific type of WoWUnit. It would be more useful if we could get ONLY units, excluding the players. Let's change this property to be more specific (notice we need to to call ToList() here - the way LINQ does deferred execution here will screw up the cast from WoWObject to WoWUnit without it):

So, in order to find the closest NPC to the player, we first need the ability to determine the distance between two positions. Let's make that it's own method on the Position class. Most people are probably familiar with using the pythagorean theorem to find the length of the hypotenuse of a triangle in 2D space. The technique is pretty much the same for 3D space. First we're going to find the deltas of all three coordinates, then we'll apply the pythagorean theorem.

Now that we can find the distance between two positions, in order to determine the closest unit to the player, we can simply order the units by distance to the player in ascending order, then take the first element. Let's test it:

Considering a bot spends most of its time running between enemies and laying waste to them, being able to find the nearest enemy is a fundamental piece of behavior. In the next chapter we'll see how to make the bot move.