Jun 25, 2006 at 3:49 AM
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
I decided I'd share this hack with the community. I just completed it a few moments ago and it works fine. Basically it causes your health to drop when you're underwater progressively instead of giving you an air counter which kills you instantly when you run out of oxygen.
This hack does two things: it gradually reduces your health when you're underwater, and removes the air counter entirely. It's actually quite simple and didn't take much effort to write - I was mainly worried I'd run out of space for code (and I sorta did - I had to get rid of the code that detects which direction you face when rendering the drowned Quote sprite.)
As usual, back up your executable before trying this, in case you accidently delete a byte or insert one somewhere and end up screwing up the game. Happens to even the best of us, so don't take chances.
First we're going to remove the air counter. We can either insert a relative jmp over the code that does it, or NOP out the instructions. I decided to NOP them out since I was being lazy.
Change everything here to 0x90. You could probably get away with just NOPing out the call at 0184E, but I'd rather not leave crap on the stack unecessarily.
Next, the actual hack. I converted the oxygen counter into a hidden "how long before decreasing health" counter, since this function is called once every tenth of a second. Far too fast to act directly on your health as you'd die within moments of setting foot in the water. Once the counter reaches 0, we decrease the health by one and check if the player died. If so, we drown him. Otherwise we reset the counter and start over.
First we make the counter start off at 160 instead of 1000 (which is roughly 4-5 seconds' time.) You can change this value to whatever you feel works best, but keep in mind the player will probably have an air tank later on in the game, and this hack will only affect a player earlier on in the game when their health is kinda low. And we don't want to make 3hp runs impossible either now, do we.
Once the counter runs out, we'll reset it to 0x00A0 (160; again, the value is up to you) and decrease the player's health by 1. Simple enough.
Next, a test: is the player's health equal to 0? If not, we'll skip this next block of code and move on. Otherwise...
O NOEZ QWOTT IZ DED!
ow we draw the drowned Quote sprite. Note that we're not checking the direction he's facing at all - there isn't enough room left in the code, sadly. The first push instruction indicates which direction he's facing so you can mess around with that.
Finally we clean things up and tell the game, it's all over. Drowned. Kaput. No more Quote.
That's all. As with any assembly hack, this must be copied down EXACTLY as it is. No bytes must be inserted nor deleted or it won't work.
An easy hack to pull off. The hardest bit was finding out what does what, but seeing as there's only one place in the code where the current health is decremented, the routine that does it was easy enough to find.
Enjoy my little evening project!
This hack does two things: it gradually reduces your health when you're underwater, and removes the air counter entirely. It's actually quite simple and didn't take much effort to write - I was mainly worried I'd run out of space for code (and I sorta did - I had to get rid of the code that detects which direction you face when rendering the drowned Quote sprite.)
As usual, back up your executable before trying this, in case you accidently delete a byte or insert one somewhere and end up screwing up the game. Happens to even the best of us, so don't take chances.
First we're going to remove the air counter. We can either insert a relative jmp over the code that does it, or NOP out the instructions. I decided to NOP them out since I was being lazy.
Code:
01084A push 0x68 6A 68 ; The X position of the text
01084C push 0x78 6A 78 ; The Y position of the text
01084E call 0x0041a350 E8 FD 9A 00 00 ; Render the counter!
010853 add esp,0x08 83 C4 08 ; Move the stack pointer back
Next, the actual hack. I converted the oxygen counter into a hidden "how long before decreasing health" counter, since this function is called once every tenth of a second. Far too fast to act directly on your health as you'd die within moments of setting foot in the water. Once the counter reaches 0, we decrease the health by one and check if the player died. If so, we drown him. Otherwise we reset the counter and start over.
Code:
01699D C7 05 DC E6 49 00 A0 00 00 00 mov dword [0x49E6DC], 0x00A0
...
0169C4 C7 05 DC E6 49 00 A0 00 00 00 mov dword [0x49E6DC], 0x00A0
Code:
016A0B mov dword [0x49E6DC], 0x00A0 C7 05 DC E6 49 00 A0 00 00 00
016A15 mov edx,[0049E6CC] 8B 15 CC E6 49 00
016A1B sub edx,+0x1 83 EA 01
016A1E mov [0049E6CC],edx 89 15 CC E6 49 00
Code:
016A24 movsx eax,word ptr[0x0049E6CC] 0F BF 05 CC E6 49 00
016A2B test eax,eax 85 C0
016A2D jg 0x00416a65 7F 36
Code:
016A30 push 0x29 6A 29
016A32 call 0x00421990 E8 5A AF 00 00
016A36 add esp,0x04 83 C4 04
Code:
016A39 push 0x00 6A 00
016A3B push 0x08 6A 08
016A3D mov eax,[0x0049e658] A1 58 E6 49 00
016A42 push eax 50
016A43 mov ecx,[0x0049e654] 8B 0D 54 E6 49 00
016A49 push ecx 51
016A4A call 0x0040AC90 E8 41 42 FF FF
016A4F add esp,0x10 83 C4 10
Code:
016A52 movzx ecx,byte ptr[0x0049e638] 0F B6 0D 38 E6 49 00
016A59 and ecx,0xffffff7f 81 E1 7F FF FF FF
016A5F mov [0x0049e638],cl 88 0D 38 E6 49 00
That's all. As with any assembly hack, this must be copied down EXACTLY as it is. No bytes must be inserted nor deleted or it won't work.
An easy hack to pull off. The hardest bit was finding out what does what, but seeing as there's only one place in the code where the current health is decremented, the routine that does it was easy enough to find.
Enjoy my little evening project!