Drowning Progressively

Jun 25, 2006 at 3:49 AM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
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.

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
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.

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
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. ;)

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
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.

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
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...

Code:
016A30 push 0x29			6A 29
016A32 call 0x00421990			E8 5A AF 00 00
016A36 add esp,0x04 			83 C4 04
O NOEZ QWOTT IZ DED! ;)

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
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.

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
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!
 
Jun 25, 2006 at 3:33 PM
Junior Member
"Wow! The more I drink of this magical beverage, the more games I can play! Wheee!"
Join Date: Nov 30, 2005
Location:
Posts: 25
This would be perfect for a hack that replaces the water with acid or lava or some dangerous liquid. It's too bad we can't have normal water along with this though.
 
Jun 25, 2006 at 4:38 PM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 32
Wow! It's awesome so much code changed ;)))!!!
I'am lookin foward your hacks, good luck for more!
 
Jun 25, 2006 at 6:59 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
Chuchino said:
It's too bad we can't have normal water along with this though.
I was hoping there'd be a way, myself. But the only possible way would be to expand the code a little. The easiest way to do that would be a long jmp to some other address, but it's more effort than it's worth.

Regardless, you'd also have to create a new tile type. ;)

ShInIng PhAnToM said:
Wow! It's awesome so much code changed ))!!!
I'am lookin foward your hacks, good luck for more!
Thanks. ;) But like I said this isn't anything too complicated. I once wrote an FF6 ROM hack where I had replaced entirely the Esper system. That was a real mess that involved digging through deep layers of 65816 machine code to get Square's buggy code to work the way I wanted it.

I only had to write a single function for this one (and NOP out part of another.) It wasn't too hard to pull off. ;) Editing weapon behavior will yield much bigger hacks than this (trust me - I'm looking at some really packed and tangled code right now. :D)
 
Jun 25, 2006 at 8:18 PM
Junior Member
"It's dangerous to go alone!"
Join Date: Apr 14, 2006
Location:
Posts: 39
If it doesn't eat up too much space, it may be more appropriate to make the first load of air last around 500, and have Quote recover around 100 for each point of damage he takes. You may find this model to be a little more ... realistic, but if you are out room, what can you do?

RuneLancer said:
I once wrote an FF6 ROM hack where I had replaced entirely the Esper system.

What name does this FF6 project have (or where can I find it)? I'd like to check it out, if that's alright with you.
 
Jun 25, 2006 at 8:43 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
That project was never released publicly. It was a bit of a bet between myself and a few fellow ROM hackers from a community I was a part of until I lost interest in FF6 hacking. I might still have it on a CD somewhere in one of my boxes - I'll post it if I find it. I do have a few screenshots laying about.



I rather like your idea. It'd be easy to do since the first two MOV instructions set the initial value, and the third one sets the value once it resets. Good idea. ;)
 
Top