EyeOfTheMind86 wrote: ↑Thu May 25, 2023 6:20 pm
Rixef, thank you very much for your help, you provided me with new useful techniques I wasn't completely familiar with.
Method 1, however, reminds me a lot of the commonality scan where you use a specific register and offset, with its relevant value, to filter when and how run the default instruction. I think the concept is the same.
The structure dissect is kind of an eye sore as well cause everything is green or red but it really makes everything a bit easier.
I still need to try method 2, and I let you know.
By the way, base RCX points to the player, enemy, item,etc. max health. So basically the value displayed is the max health while 0C points to the current health. It makes things easier when you know what is the max health of your character so I just used that for the cmp and it worked.
There is a catch though, even though the script just points and retrieves the player health, everything else doesn't die or gets destroyed, even though their health decreases as expected. If I deactivate the script to bring everything to default, the game still behaves like this until I find, kill or destroy a new different enemy/item.
The full default instruction is the following:
Code: Select all
cmp dword ptr [rcx+70],00
movss [rcx+0C],xmm0
Basically, everytime the script is activated, the address [rcx+70] changes his default value from 00 to 01, and everytime you get hit it rises by 1.
Everything acts normally when that value stays to 0. I guess by adding a new script which operates right before the cmp and force that value to 00 could be a solution as I keep the condition to be true, but why is this happening? Could the push and pop of the script "pollute" the register somehow? I think here I need to know more theory about how register works and are handled by the system.
Hey, no problem! Glad I could shed some light on new techniques! Lol whenever I'm tryin' to help someone and I don't know how much they know, I try to make it as detailed as possible so as not to miss anything just in case. So if I'm ever pointing out something that seems obvious to you, that's the reasoning.
Oh okay! Yee, Method 1 is the same concept as that.
To summarize and try to clarify method 1 more; it looks for a unique value near your player health in memory to compare to so we know we're messing with the correct one.
To summarize and try to clarify method 2 more; somewhat similar to method 1 except it more-so disregards the memory around your player health and mostly just pays attention to the register states when health is passed through which can sometimes be in completely different memory regions nowhere near your health. But that doesn't matter as long as it's consistent and unique to when it's dealing with your player health.
Oh okay! So RCX is max health, RCX+ 0C is current health, and RCX + 70 is a flag saying whether an entity is being hit or not at that time. 1 = true if your player or an entity is hit, 0 = false.
So a question; are you going for a Godmode script or a OneHitKill script? Or both?
Sounds like you might be going for a combo of both in one script so I'll carry on with that in mind. Okay yeah so in the Memory Viewer window, go one address up to that
cmp dword ptr [rcx+70],00
(make sure it's at the top of the Memory Viewer Window and selected) and then hit
Ctrl+A and then the scripting window should pop up, so in that window hit
Ctrl+Shift+A and then a little window should pop up saying "
On what address do you want the jump?" Just hit "OK", that's fine as is. And then another window will pop up and you can give it a name like GodmodeOHK. In the script window this should set it up mostly similar to how it was in the script I put in my previous post.
So your script at the moment should look something like (spoiler tags to save some space lol):
Code: Select all
{
default info
}
[ENABLE]
aobscanmodule(GodmodeOHK, Game.exe, XX XX XX XX F3 0F11 41 0C) //unique AOB
alloc(newmem, $1000, GodmodeOHK)
label(code)
label(return)
newmem:
code:
cmp dword ptr [rcx+70],00
movss [rcx+0C],xmm0
GodmodeOHK:
jmp newmem
nop 4
return:
registersymbol(GodmodeOHK)
[DISABLE]
GodmodeOHK:
db XX XX XX XX F3 0F 11 41 0C
unregistersymbol(GodmodeOHK)
dealloc(newmem)
So using your max health as a unique value to your player we'll edit the script like so (
it might be easier on the eyes to read these scripts if you copy paste this into the CE Auto Assembler scripting window since it will color all the text appropriately lol):
Code: Select all
{
default info
}
[ENABLE]
aobscanmodule(GodmodeOHK, Game.exe, XX XX XX XX F3 0F11 41 0C) //unique AOB
alloc(newmem, $1000, GodmodeOHK) //allocate a thousand bytes near GodmodeOHK address(this is our memory space)
define(PlayerMaxHealth, (float)1337) //define your max health here (note; do (float) if your player health is a float or (double) if double, (int), etc.)
label(code)
label(return)
label(OHK) //we're adding an extra label for OneHitKill here
newmem:
cmp [rcx],PlayerMaxHealth //compare the value of RCX to PlayerMaxHealth
jne OHK //jump if not equal(jne) to OHK
movss xmm0,[rcx] //but if it is equal then move our player's max health into xmm0 register
mov dword ptr [rcx+70],00 //move 00 into our player's hit flag to trick the game into thinking we're not even being hit
jmp code //and then jump to the original code with these new set values
OHK: //this is where we are going to kill enemies
cmp dword ptr [rcx+70],01 //compare the entity's hit flag to 1 to see if they're even being hit
jne code //jump if not equal to the original code. Why? 'cause you said items are also being passed through this function. So this will weed those out from the enemy entities. We don't want to kill the item loots
movss [rcx+0C],(float)0 //otherwise if it is equal then move (float)0 into the enemies' current health
jmp return //and then jump straight over the original code to return 'cause otherwise the original code will just undo what we just did to enemies
code:
cmp dword ptr [rcx+70],00
movss [rcx+0C],xmm0
jmp return
GodmodeOHK:
jmp newmem
nop 4
return:
registersymbol(GodmodeOHK)
[DISABLE]
GodmodeOHK:
db XX XX XX XX F3 0F 11 41 0C
unregistersymbol(GodmodeOHK)
dealloc(newmem)
So it seems we actually don't even need to push and pop things here. But let me try to explain push and pop a bit anyways 'cause they do come in handy very often.
So nope, push and pop do not pollute the register.
When you
push a register onto the stack it basically
saves it's value and the state it was in at that very moment. It sets it on top of the stack exactly in the state that it's in. So now that we have that saved we can use that register however we want. So long as we restore it's value once we're done with it.
Which brings us to
pop. When you pop a register off the stack, you're
restoring/loading the exact state it was in when it was pushed onto the stack. So it's as if you'd never even touched it. The game you're messing with is none-the-wiser that you just borrowed it's register used it and then put it back exactly how you found it.