Shynd’s WoW Modification Journal

June 15, 2008

GetUnitReaction

Filed under: World of Warcraft — Tags: , , , , , — Shynd @ 12:59 pm

Okay, this is the big one.  We all want to be able to find out how to determine which enemies are hostile and which enemies are neutral.  Kynox, bless his awesome ass, showed us how to do it in-process here (by in-process, I mean injecting a DLL and calling a game function that compares your faction with the faction of the unit in question).  First, let’s outline Kynox’s version.

As of the current patch, 2.4.2, the class method for CObject->GetUnitReaction(CObject obj) is at address 0×005D4AB0 (can be found in WoWOffsets.h in the download posted by Kynox in the above link).  Basically, when it’s called, the two units’ factions are compared and a value representing their reaction is returned (1 for hostile, 3 for neutral, 4 for friendly, etc.). [Note: 1 is actually "extremely hostile" and 3 is actually "hostile", but 1 is fundamentally equivalent to aggressive and 3 is fundamentally equivalent to neutral]

You’ll notice that there’s not two arguments passed to this function; you don’t call it like GetUnitReaction(unit1, unit2).  That is because it is a class method.  You don’t have to specify unit1 because it is being called as a part of unit1.  It’s actually called like so: unit1->GetUnitReaction(unit2).  Therefore, in ASM, the ECX register is set to equal the base address of unit1, and the base address of unit2 is passed as an argument.  This allows the function to compare the two.  Just thought I’d point that out for those of you who are reverse-engineering the client to see the inner-workings, so to speak (all two of you!).

Now then, how does it compare the two factions: ay, there’s the rub.  That’s what everyone wants to know.  Well, let’s start off with how it finds the factions of the two units.

A unit’s faction is held at [[unitBase + 0x120]+0×74].  That’s two memory reads.  In C#, it looks like so:

int Faction = Memory.ReadUInt(hProcess,(Memory.ReadUInt(hProcess, (curObj + 0x120)) + 0x74));

Next question: once you get the faction of both units, what do you do? Well, what the WoW client does is pass unit1’s faction and unit2’s base address to the subroutine at address 0×005D1AE0. For instance, if you’re a Tauren (tauren faction == 6) and you’re comparing your faction to the unit at base 0×1DF00008, it’d look like this: CompareUnitFaction(6, 0×1DF00008); CompareUnitFaction (temporary name until someone comes up with something better) then grabs the unit’s faction at [[0x1DF00008+0x120]+0×74] and compares it with 6.  How does it compare it?  Well, that’s taken me hours and hours of reverse-engineering to figure out, so I’ll save you the time and explain it (as I understand it, which may be wrong).

CompareUnitFaction takes the factions of each unit and gets the address of that particular faction’s data struct in memory.  It does this by doing something like the following (pseudo code):

int startIndex = *0x93E80C;
DWORD factionPointer = *0x93E818;
DWORD totalFactions = *0x93E808;
DWORD hash1, hash2;
if (unit1.Faction >= startIndex && unit1.Faction < totalFactions && unit2.Faction >= startIndex && unit2.Faction < totalFactions)
{
hash1 = (factionPointer + ((unit1.Faction - startIndex) * 4))
hash2 = (factionPointer + ((unit2.Faction - startIndex) * 4))
return CompareFactionHash(hash1, hash2);
}

So, what’s CompareFactionHash(hash1, hash2) do?  Well, it looks through the client’s faction data struct and compares flags depending on which factions are being compared.  Here’s a link to the ASM subroutine. Here’s a link to my C# implementation of that ASM subroutine (should be understandable, I would think).

I’ve only tested it under the most contained of circumstances, but all tests came back positive.  It seems to be a pretty good way of determining whether a unit is Hostile, Neutral, or Friendly towards you without injecting any code.

Here’s my full C# code; you’re welcome to convert it to whatever you want, redistribute it, etc., as long as credit is given.

More to come, as always! :)

Click here to read the next article in this journal.

1 Comment »

  1. I am so itching (no im not on crack) to join you in your WoW reversing endeavors but:
    1. If I cant find class member function on a simpler game, then how am I expected to figure it out on WoW?

    2. The game I am hacking has a unique engine and netcode (its also dying so I must hurry!)

    In the mean time I will read up on your posts and attempt to leave educated feedback. (FYI I do NOT have WoW on my computer so adding on to your abstraction info is a NO. Maybe when I get a HD larger than 35 GB)

    /*BEGIN FEEDBACK*/
    Lol I respect that you reversed a function. Those things get really annoying to do. The single most frustrating part is the stack arguments and pointers to pointers to structures with objects etc. Oh any luck on teleporting with out d/c or warden bAn?

    -CRBY

    Comment by craby987 — June 21, 2008 @ 11:24 pm


RSS feed for comments on this post.

Leave a comment

You must be logged in to post a comment.

Blog at WordPress.com.