Mirror: DarkHook.zip
Hello everyone.
Been busy lately updating DarkHook to work with NewDark version of the game. I noticed there is actually only one executable for all games in the series, despite the file size. I'm guessing the different size is cause of file resources - icon, xml versioning, etc.. - although the caption in T1, TG and T2 states "Thief 2 Final 1.21". Back on track, I'll describe below how DarkHook works now.
[ PRE-REQUISITES ]
First off, you will need to get Cheat Engine from this location: [ http://cheatengine.org/downloads.php ]
I'm currently using Cheat Engine 6.3. Although not accustomed with, you may find good uses for it in other games as well.
Next up, fetch the hotlinked archive: [ http://www.mediafire.com/download/dd...0/DarkHook.zip ] (mirror it please)
It contains two tables: one for T1, TG, T2 v1.21 - and - one for DromEd v1.21. The reason why there are two tables is simple: DromEd contains way too much functions than the game executable, so for the game release I had to "improvise" and rebuild missing functions or properties. Such as: physics, ai_aware_of_player, ai_sleep_all, ai_wake_all - and probably future more.
[ MECHANICS ]
To use the table, follow the steps below:
- open the game;
- open Cheat Engine;
- in CE, choose File > Open Process - OR - click the first top icon (a computer with a magnifying glass);
- once the Process List is up, find 'thief.exe', 'thief2.exe' OR 'DROMED.exe' in there;
- once found, double-click it - OR - click Open;
Top part of CE should look like this now: (note that the process ID will be different on your end - e.g.: 00000F88)
Based on your preference: T1, G, T2 - OR - DromEd, open the corresponding table from the provided archive via File > Open File - OR - Ctrl+O - OR - clicking the second icon in CE's top part. Choose 'DarkHook.CT' and hit Open. Once that is done, the table data should appear in CE's bottom window:
To proceed, click [Enable]. When you do that, two things can happen: the checkbox doesn't tick - meaning something wasn't found (at which point please notify me) - or everything is OK and the line will look like the below:
For future reference, when you see the checkbox, everything is OK.
[Enable] is a script - you can open it selecting the line, then hitting Enter key, if curious what it contains - that uses patterns to identify locations in game's code for later use or just simple hooking. Once active, it will allow access to sub-sections:
[Coordinates] - here you will find Garrett's in-game coordinates (you have to be in a map);
[Scripts] - here you will find DarkHook script;
It's best you ignore the [Debug] section. Or if you want to fool around, be my guest
To activate DarkHook, tick [Scripts], then tick DarkHook. Everything should look like this now:
[ FEATURES ]
Get back in-game and use the following hotkeys for their effects:
F2: Will display the menu.
NUMPAD1: PlayersOnly.
The name of the option is taken from UnrealEngine's command, where, once activated, it would freeze entire world but the player. In DarkEngine, you may know it as the combo ai_sleep_all/ai_wake_all. I found that the aforementioned engine functions are a bit buggy - if you knock-out or kill an AI, then use ai_wake_all, they'll be back on their feet, although inactive. This might be a bit strange when you play the game, to find AIs that were taken care of staring at you ai_sleep_all sets the AIs state to 0 (Asleep), without storing previous state. ai_wake_all sets state to 3 (Normal), only for the Asleep AIs (state 0). This is where I intend to make some changes of logic: get each AI state through GetProperty, store it and when setting state through SetProperty, check stored AI states and restore their original ones instead of forcing them all to Normal for the Asleep ones.
-- UPDATE --
PlayersOnly works perfectly now! When activated, AI IDs and states are backed-up, then Asleep state (0) is set for all of them. When deactivated, AI states are restored based on the backed-up values. You should now be able to blackjack an AI, "pause" game while he begins to fall, then "unpause" to see him touch the ground.
Toggleable ON/OFF with the press of the key.
NUMPAD2: Fly.
This option makes use of two functions: PhysSetGravity and PhysSetBaseFriction. When active, it will 0 the gravity and set friction to 320.0f. When inactive, will restore original state, setting gravity to 1 and friction to 0.
Toggleable ON/OFF with the press of the key.
NUMPAD3: Ghost.
Option name taken from UE again. What it actually uses from DarkEngine is physics, setting it to 0 or 1. When active, you will notice the message "Collisions: OFF" (meaning you can walk through doors, walls, or if you jump, fall through the map). I suggest you use Fly with it. When inactive, message will be "Collisions: ON". The physics BOOL is checked in two locations: one which is generic, taking care of all objects AND one which only works for trees, doors, AIs but not walls, floors. If need be, I can adjust this to work to the player's advantage, thus allowing you to play normally without Fly, but without the ability to walk through walls.
In the game release, the checks were removed, so I had to find the spots, hook them and "plant" the missing code
Toggleable ON/OFF with the press of the key.
NUMPAD4: Super Speed.
Option will mimic the effects of the Speed Potion. You can play with the values if you want, by changing code inside DarkHook script here:
Note that setting higher values will result in the player movement setting off, like an airplane
Toggleable ON/OFF with the press of the key.
NUMPAD5: God Mode.
This option makes use of a hook location (where your health is decremented) and two adjacent functions: ObjGetMaxHitPoints and ObjSetHitPoints. What they do is to acquire the max health points your character (Garrett) can have and set them accordingly. Option works like healing as well: say you got 2 bars left and want to just heal yourself - what you do is hit the key twice (hitting it once will enable God, but at the same time heal you to your maximum health; hitting the key again will disable God).
Toggleable ON/OFF with the press of the key.
NUMPAD6: Activate/Deactivate LockCheat Script
This feature should only be used in Thief or Thief Gold. Read below, in the LockCheat section!
NUMPAD7: LockCheat.
You may know this cheat. To work with it, one would have to open up user.cfg and type it in there on a line, save file, load game, and all locks would be open. Well, now you can do this without having to type it in the .cfg file. Option works via two functions: hash_set and hash_delete. Their purpose is to fetch strings and hash them to values. Based on these values, corresponding options are activated/deactivated - such as these cheats.
Toggleable ON/OFF with the press of the key.
-- UPDATE --
In Thief or Thief Gold, LockCheat is not available. I've managed to get a workaround ready, so follow below steps:
- load up T1 or TG and target it in CE;
- activate [Enable] script, then activate Scripts > DarkHook;
- back in-game, hit NUMPAD6 to activate LockCheat Script script - you'll see it becoming active in CE's list and bOldThief address is set to 1 <- DO NOT TOUCH IT! (as in, change its value - it's done on NUMPAD6 key press);
- use NUMPAD7 as before to activate/deactivate the option;
Inside technical:
- when you enable LockCheat Script in T1/TG, you will see the message "LockCheat Script is enabled." in-game - so you know it'on;
- a secondary BOOL is used - bOldThief - that becomes 0 or 1, depending on LockCheat Script's state (active or disabled);
- bOldThief is checked for in DarkHook, so: when it's 0, normal LockCheat is executed (for T2); when it's 1, the T1/TG version is executed;
- how do you know which one is active when you hit NUMPAD7? For T2, message is "LockCheat: ON" or "OFF"; for T1/TG, message will be "LockCheat: Active" or "Inactive";
- furthermore, since array pattern won't be found, you won't be able to activate it in T2 (it won't get enabled/ticked)
In T2, the check happens in gen.osm. In T1/TG, most missions have their own .osm files. Therefore, you will have to do it like this:
- play a mission - hit NUMPAD6, to activate script, then NUMPAD7 to activate option;
- if you finish mission OR reload map, .osm gets reloaded - hit NUMPAD6 to deactivate script, and one more time to activate it (you will see status on screen), then use NUMPAD7 as you wish;
NUMPAD8: Infinite Item Timeout.
This feature can also be set in the .cfg files, but I've managed to go without it. Simple as is, once enabled you'll see: "Inventory Item Timeout: OFF", meaning all inventory items will remain on your screen indefinitely. Turning it off will show "Inventory Item Timeout: ON", restoring the timeout.
Toggleable ON/OFF with the press of the key.
NUMPAD9: AI Awareness.
Option will mimic the DromEd BOOL. This variable was used to check whether AI Sight and Listening casts would involve the player as well. It was removed in the game release, so I had to hook the 2 or 3 locations where this BOOL was used. Simply put - when enabled, you will see: "AI Awareness: OFF" - AIs will ignore you on sight or sound. Turning it off will show "AI Awareness: ON" - you'll be 'visible' again
Toggleable ON/OFF with the press of the key.
NUMPAD0: Set Weapon Amount to 100.
Option uses g_pPlayerInventory pointer to fetch currently in-use weapon (located at 0x1C in this structure). If not NULL, will use Set::cStoredProperty function to raise quota to 100. In short, select a weapon - sword and blackjack work too - and then hit the key. You'll see "100" displayed next to the weapon on your left screen side.
NUMPAD. (NUMPAD DEL): Set Item Amount to 100.
Option uses g_pPlayerInventory pointer to fetch currently in-use item (located at 0x20 in this structure). If not NULL, will use Set::cStoredProperty function to raise quota to 100. In short, select any item and then hit the key. You'll see "100" displayed next to it on your right screen side.
Values can be changed in the DarkHook script to suit your needs:
Just alter the lines with "push 64" (100 in hexa).
F3: Will kill use of keys, in case you decide you don't want to use the features anymore or just want free numeric keys usage without turning on/off DarkHook options. In case you change your mind, hit the key again to restore use.
Note that the keys can easily be changed in the DarkHook script itself. If interested how, do let me know.
That's about it for now. Feel free to post feedback, as it helps perfecting it.
Best regards,
Sun
Last edited by SunBeam; 13th Oct 2013 at 19:52.
Mirror: DarkHook.zip
I've dug a little bit deeper in ai_sleep_all / ai_wake_all functions. I loaded up 'miss1.mis' in DromEd 1.21 and used g_pAIManager and _g_pAIModeProperty pointers to fetch number of AIs I got in map and getting to the AI I desired. Pictogramatically speaking, I've done the below:
As you can see, my target is a bowman - first on the left as you enter the courtyard in first mission. His ID is 155 and state he's in is Normal (if you do the counting, top to bottom, that is 3). The map has a total of 16 AIs. That is the correlation between what you see in DromEd and what you see in CE (what I've marked with arrows).
Now, I wanted to alter my AI's state. Therefore, I enabled ai_aware_of_player so they couldn't see or hear me. Went behind my guy and whacked him. The result:
Apparently, when you blackjack a person, its state turns to 5 (which, based on above explanation of 'Current mode', means Dead). I think there is a different BOOL being set to determine if he's dead or just asleep.
What ai_sleep_all does is to set state to 0 for all AIs (Asleep). Their original state is not saved, so when you use ai_wake_all, what the function will do is to set state to 3 (Normal) to every AI, regardless of the state they were in before. Since you blackjacked the guy, he'll get up and stand in front of you doing nothing.
As previously explained, what we want is to allocate a spot (a cave) in which, when we call our modified ai_sleep_all function, we save their original states (AI_ID and AI_State). Once saved, we can then do what the original function did - set all the states to 0 (Asleep). Later on, when ai_wake_all is used, we won't set state to 3 (Normal). Instead, we pick up each AI_ID and their corresponding AI_State and set those instead That way we do a perfect restore of each AI behavior.
I recommend watching below video directly on youtube, at 1080p resolution to be able to read the text.
Be back with more later.
BR,
Sun
Last edited by SunBeam; 13th Oct 2013 at 11:18.
Thank you SunBeam for your hard work!
I´ve tested all features on Thief Gold.
Only the "LockCheat" doesn´t work in-game. Any ideas here?
Thanks, Gecko.
Will check out why it doesn't work, although if it does in Thief 2, it should in Gold as well - it's the same table.
EDIT #1:
I found the issue. Nothing to do with the way DarkHook does its job.
The check for LockCheat in T2 is performed from gen.osm library. In T1/TG I looked at the list of loaded modules while playing first map. The library doesn't appear to be loaded. Just miss01.osm. Still, I wanted to see if gen.osm has the check implemented and it's not there. Then I checked all around the internet to find that LockCheat appears only in T2.
Back to the drawing board.
I'll check where the BOOL LockCheat sets is checked for and find the location in T1/TG's .osm files. Since TG loads for each map a separate .osm, you can imagine now why CE comes in handy. Only downside is that you'll probably have to activate/deactivate DarkHook for each loaded map (remember .osm files are different for each mission? so hook will have to be reinstated via patterns each time you load a new map).
My folder looks like this:
As you can see from above, not all missions have an .osm file - missions: 15, 17 and 18 don't have an .osm file - I bet game will use default gen.osm for those maps.Code:miss1.mis miss01.osm miss2.mis miss2.mis.dml miss02.osm miss3.mis miss3.mis.dml miss03.osm miss4.mis miss04.osm miss5.mis miss5.mis.dml miss05.osm miss6.mis miss6.mis.dml miss06.osm miss7.mis miss7.mis.dml miss07.osm miss9.mis miss9.mis.dml miss09.osm miss10.mis miss10.mis.dml miss10.osm miss11.mis miss11.mis.dml miss11.osm miss12.mis miss12.osm miss13.mis miss13.mis.dml miss13.osm miss14.mis miss14.mis.dml miss14.osm miss15.mis miss15.mis.dml miss16.mis miss16.mis.dml miss16.osm miss17.mis miss18.mis
Simply put, this is what's missing between the two .osm versions (I'm assuming each of the Gold .osm files have the same code):
EDIT #2: I've solved it Please redownload from main post - I've overwritten the archive, mediafire allows me to do so apparently - and let me in on the feedback (check the LockCheat section for usage!).
Best regards,
Sun
Last edited by SunBeam; 13th Oct 2013 at 14:08.
Fixed PlayersOnly, now it works perfectly Updated both the 'DromEd' version and 'T1, TG, T2' one. Redownload from link in first post, I've updated it on mediafire!
BR,Code:ai_sleep_all: push ebp mov ebp,esp mov edi,[g_pAIManager] mov eax,[edi+30] add edi,2C xor esi,esi test eax,eax jbe lbl_2 lbl_0: mov edx,[edi] mov edx,[edx+esi*4] mov eax,[edx+8] // edx is AI_ID mov ecx,[edx+C] // ecx is AI_State mov [AI_Storage+esi*8],eax mov [AI_Storage+esi*8+4],ecx mov eax,[edi+4] inc esi cmp esi,eax jb lbl_0 xor esi,esi lbl_1: mov edx,[edi] mov edx,[edx+esi*4] mov eax,[_g_pAIModeProperty] mov edx,[edx+8] mov ecx,[eax] push 0 // set Asleep state push edx push eax call [ecx+48] mov eax,[edi+4] inc esi cmp esi,eax jb lbl_1 lbl_2: mov esp,ebp pop ebp ret ai_wake_all: push ebp mov ebp,esp mov edi,[g_pAIManager] mov eax,[edi+30] add edi,2C xor esi,esi test eax,eax jbe lbl_4 lbl_3: mov eax,[_g_pAIModeProperty] mov ecx,[eax] push [AI_Storage+esi*8+4] // AI_State push [AI_Storage+esi*8] // AI_ID push eax call [ecx+48] mov eax,[edi+4] inc esi cmp esi,eax jb lbl_3 lbl_4: mov esp,ebp pop ebp ret
Sun
Last edited by SunBeam; 13th Oct 2013 at 19:49.
@Albert: I've never tried Cheat Engine in other OSes than Windows. As far as this page is concerned, CE should be working on Wine. See the test results:
Some hints here as well, might help. Also, Dark Byte, program author, mentions one thing here. 4th post in this thread kinda mentions the same thing:What works
- Loading processes
- Searching for specific values, changing them (multiple)
- Freezing specific addresses to specific values
So the main function of RAM manipulating works as expected
What does not
Could not find anything that didn't work!
What was not tested
Anything fancy like value fixing by formulae etc.
Hope you can figure out a way. Otherwise, get Windows cookin' :PCheatEngine runs under Wine.
sudo apt-get install wine
Install Cheatengine. Run it.
BR,
Sun
Last edited by SunBeam; 21st Oct 2013 at 17:41.
Hi Albert,
Your observations weren't clear enough. You started talking about OSes, so I lost track of the real issue After you target the game process, make sure you open the .CT file corresponding to the game you play - as in, open it from one of the folders in the archive. You may as well just double-click it if the .CT extension is already assigned to be opened with CE. With game targeted, and script loaded, try Enable one more time.
The brief application freeze means an array of data wasn't found or code was not allocated. Just to be safe on this - you need latest CE, not any other version, since some of the script language is not compatible with other versions.
If that doesn't work, you may want to open up the script (right-click, Change Script) and manually search each of the arrays in there in memory, till you find one that can't be found. Then report back. Just to be sure on this, executable I run on (thief2.exe) is 4.28 MB (4,495,360 bytes) big.
I will be absent for a while (1 week tops) since I'm getting surgery - had my ankle broken, time to remove the metallic stuff inside :\ In the meantime, please specify what game are you trying this on, and, if you have the time to, can you record yourself doing it? With a desktop tool such as Instant Demo?
BR,
Sun
When i start game and open cheat engine then open files thief2.exe and darkhook.ct in cheat engine nothing shows up at the bottom of cheat engine.
what am i doing wrong please.
thanks
This needs a update so it will work with new dark 1.22 and 1.23
thanks
Why wouldn't you just open the mission in DromEd? It would give you the same, and many more features, to cheat with :P
DarkHook works perfectly with the newest NewDark version! There is no problem...
Good to hear, let me know if you encounter any issues
BR,
Sun
Thanks for this! It works perfectly and has allowed for me to set up a save file for skipping Casing the Joint in T2, and configuring it to my preference.
how does one change the hotkeys?
Thanks for this! It saved my mission 9 in The Black Parade where a bug can happen that a guard locks you into an area and walks away with the key so you can't pickpocket him. It essentially soft locks the level after getting a good half way through it. So this saved my day Clipped through the locked door and was able to continue on.
Don't know why but Darkhook won't work for me any more i tried uninstalling and reinstalling tried with no mods and with mods but as soon as i click on enable/scripts/ using Cheat Engine 7.5 the game quits. Does anyone have any Ideal why? Everything is up to date with the Game and Windows 11 Pro