While this example will be in delphi, the logic can be applied to C++ hacks as well to reduce lag in your hacks.
I use 2 threads for my hacks, 1 for PTC and another for memory byte patches. The idea is to only "Process" the hacks when required, for example when we turn on or off the hack, and also when joining a new game.
To determine if you are "ingame" we can check the byte value at a given address, here is a small function that will return a boolean (True/False) if we are in the game.
[highlight=delphi]
//Declare our address and byte value for ingame
Const
dwInGameAddr = $37843B2C;
bIsGame = $01;
//Check if in game
Function IsInGame(pAddress:Pointer):Boolean;
begin
Result := (PByte(pAddress)^ = bIsGame);
end;
[/highlight]
Knowing if we are ingame or not, will determine if we should apply our hacks or restore original byte values and PTC Values. For example if "IsInGame" function returns false we would restore all original values, Other wise we would check and see what hacks we have turned on/off and process them accordingly.
Here is the thread that will be a continues loop to see if we are in game and also to see if we have turned on a hack or not, We will only process the hacks if a couple conditions have been meet. 1st are we in game, 2nd have we activated or deactivated a hack.
[highlight=delphi]
function FuncMain(const LPVOID: variant): Boolean;
begin
while (True) do
begin
asm
pushad;
end;
if ((bReset = True) and (IsInGame(Pointer(dwInGameAddr)) = True)) then
begin
bProcess:= True;
bReset:= False;
end;
if not IsInGame(Pointer(dwInGameAddr)) then
bReset:= True;
if IsInGame(Pointer(dwInGameAddr)) then
begin
//Write NoRecoil
Case bNoRecoil of
True:
begin
WriteIt(ptr(AddressNoRecoil1),PatchNoRecoil1);
WriteIt(ptr(AddressNoRecoil2),PatchNoRecoil2);
WriteIt(ptr(AddressNoRecoil3),PatchNoRecoil3);
WriteIt(ptr(AddressNoRecoil4),PatchNoRecoil4);
end;
False:
begin
WriteIt(ptr(AddressNoRecoil1),OriginalNoRecoil1);
WriteIt(ptr(AddressNoRecoil2),OriginalNoRecoil2);
WriteIt(ptr(AddressNoRecoil3),OriginalNoRecoil3);
WriteIt(ptr(AddressNoRecoil4),OriginalNoRecoil4);
end;
end;
//Write Other Memory Patches
Ect...
Sleep(500);
end
else
//Write original bytes
begin
WriteIt(ptr(AddressNoRecoil1),OriginalNoRecoil1);
WriteIt(ptr(AddressNoRecoil2),OriginalNoRecoil2);
WriteIt(ptr(AddressNoRecoil3),OriginalNoRecoil3);
WriteIt(ptr(AddressNoRecoil4),OriginalNoRecoil4);
ect...
Sleep(500);
end;
asm
popad;
end;
end;
end;
[/highlight]
Now the main part here to take notice of is...
[highlight=Delphi]
if ((bReset = True) and (IsInGame(Pointer(dwInGameAddr)) = True)) then
begin
bProcess:= True;
bReset:= False;
end;
if not IsInGame(Pointer(dwInGameAddr)) then
bReset:= True;
[/highlight]
Lets take this in reverse, "if not IsInGame(Pointer(dwInGameAddr)) then" this is basically saying if we are not in game then bReset = True, we use bReset to determine when we join a new game and will remain True until untill we join a game. "if ((bReset = True) and (IsInGame(Pointer(dwInGameAddr)) = True)) then" is saying that we must have bReset and IsInGame both equal to true which tells us we have just joined a game and can now process our hacks, we also set bReset back to false ready for next time.
"if IsInGame(Pointer(dwInGameAddr)) then" we are just checking continually if we are still in game or not and we do this every 500 milliseconds, "else" if we are not in game we will write the original bytes back.
As you might have noticed we also set "bProcess" to true when we first enter a new game, This is used in another thread for our PTC hacks, here is that thread...
[highlight=delphi]
function PresentCallBack(const Self: Pointer; pSourceRect, pDestRect: PRect; hDestWindowOverride: HWND; pDirtyRegion: PRgnData): HResult; stdcall;
begin
asm
pushad
pushfd
end;
if bProcess = True then
begin
//Keybord0
case bFps of
False: Pushit(PChar('ShowFps 0.000000'));
True : Pushit(PChar('ShowFps 1.000000'));
end;
//Our other PTC hacks
ect..
ect...
bProcess:= False;
end;
asm
popfd
popad
end;
Result := PresentNext(Self, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
end;
[/highlight]
Basically this says, if "bProcess" is true then check each hack and see which ones are turned off or on and PTC them accordingly, then after that set "bProcess" back to false so we don't keep calling our PTC commands when its not needed.
You are probably wondering how do we know when to process our PTC commands, the first is by detemining if we joined a new game, and the second in this case is dependent on if we press a hot key or not(this could be a menu item as well). I actually have this running in yet another thread to help with not overloading 1 thread to do everything. here is that thread
[highlight=delphi]
//Thread to monitor for keypad presses
Function FuncKeys(const LPVOID: variant): Boolean;
begin
while (True) do
Begin
//Frames Per Second
if (GetAsyncKeyState(VK_NUMPAD0) <> 0) then
begin
bFps:= NOT bFps;
Sleep(10);
bProcess:= True;
OffOn(bFps);
end;
//Turn off All Hacks "End" Key
if (GetAsyncKeyState(VK_END) <> 0) then
begin
bFps := False; //Keybord0
ect...
bProcess:= true;
OffOn(False);
end;
//Have a KitKat
sleep(100);
end;
end;
[/highlight]
As you see if the hotkey is pressed the "bProcess" is equal to true which means our PTC thread will process the PTC commands based on a boolean type for each hack. "OffOn" is just small function I wrote to make beep sounds so we hear if the hack is on or off(true or false).
While it might look complicated and the syntax looks weird to you guys, The logic is very straight forward using booleans and threads to help reduce lag, and using this my frame rate never really drops, If it does drop its only by a very small amount. Hope it helps people wondering how to reduce lag in there hacks.