Because my love for you knows no bounds, I have created for you a small tutorial. I will describe a method by which you can prevent WoW from automatically marking you AFK after five minutes of inactivity. Pull up a chair and put on your learning caps.
The function we will be patching is named, "CGGameUI::UpdatePlayerAFK". In the current release of WoW, it can be found at 0x8327A0. This is not rebased, I will leave it as an exercise to the reader how to locate this if WoW does not load at the base address specified in its NT_HEADERS/IMAGE_OPTIONAL_HEADER structure(s).
Lets take a look at the relevant code in assembly. This code is found at the beginning of the function.
Code:
1: push ebp
2: mov ebp, esp
3: mov eax, [ebp+arg_0]
4: sub eax, dword_D19040
5: lea ecx, [eax-493E0h]
6: test ecx, ecx
7: jl short loc_8327FD
We are going to ignore the first two lines, this is part of the function prologue. Here is psuedo-code, in C/C++, that would accomplish something similar to this assembly code. You cannot tell from this segment, but the function does not return anything
Code:
void UpdatePlayerAFK(int CurrentTickCount){
int timeDifference;
timeDifference = (CurrentTickCount - TICK_COUNT_LAST_PLAYER_EVENT);
if((timeDifference - 300000) > 0){
//Mark player afk
//etc...
}
else{
return;
}
}
To help tie this psuedo-code to the assembly code:
- CurrentTickCount represents arg_0
- timeDifference represents eax on line 4
- TICK_COUNT_LAST_PLAYER_EVENT represents dword_D19040 (A global variable)
- 300000(decimal) is equal to 493E0h(hex)
- if((timeDifference - 300000) > 0) is represented by the assembly code on line 5, 6, and 7
Good god man! What does it all mean?
Okay, calm the hell down - I will explain. First off, all of the times are represented in milliseconds. The function is checking how many milliseconds have passed since you did something with your character, moved around, jumped, etc. It is taking the difference in time and subtracting 300,000 milliseconds. Why 300,000? Well lets do the math.
Code:
300,000 ms / 1000(ms in a second) = 300 seconds
300 seconds / 60(seconds in a minute) = 5 minutes (AHA!)
The game is figuring out if your last action happened more than five minutes ago. If it has been more than five minutes, "(timeDifference - 300000)" will result in a positive number i.e. "> 0" - a negative result indicates that less than five minutes have passed. In the rare event that "(timeDifference - 300000)" is exactly equal to zero, you will not be marked AFK. Although it will not buy you much time as the AFK check happens every few seconds or so.
Mother f***ing Blizzard! How can I fight back?
"Fixing" the AFK check requires but one byte to be modified. Line 7 in the assembly code occurs at the address 0x8327B4. By overwriting the existing value, 0x7C, with 0xEB we effectively change the test, "if((timeDifference - 300000) > 0)" to "if(false)" - meaning the code in the if statement will never be executed. At the assembly/machine code level, we are changing, "jl short loc_8327FD" to "jmp short loc_8327FD" - otherwise known as an unconditional jump, one that is always taken.
Go now, go unto the world (of Warcraft) and REFUSE to be AFK.