Silent-hill-2-enhancements: (Spoilers) RPT Hospital Elevator Animation Bug

Created on 1 Dec 2018  ยท  25Comments  ยท  Source: elishacloud/Silent-Hill-2-Enhancements

@Bigmanjapan
I have a theory... Do you remember how a value got changed after James enters the rowboat and then any subsequent times he goes into the rowboat his animation became corrupt?

I believe that is happening with RPT when he stabs Maria. Check out the following videos (pay attention as he stabs):

Correct: https://youtu.be/MlH49MyOvPA
Incorrect: https://youtu.be/raWuBdi0cOE

Why do I think this is an issue like the rowboat animation? Because I was able to replicate this on both PC and PCSX2. The first time I played this cutscene on both platforms the animation worked correctly. When I reloaded the save (for PCSX2 done by soft menu reset (L1 + R1 + L2 + R2 + Start + Select)) the animation became corrupt on the second attempt.

Would you be able to find the address that isn't being reset for this cutscene?

All 25 comments

Another theory:

  • If Maria takes NO damage during hallway run: Bug occurs. (Because RPT never did stabbing animation prior to cutscene?)

  • If Maria DOES take damage during hallway run: Animation works correctly.

EDIT: I believe this is the correct theory.

https://youtu.be/84XDBvrQCb4?t=41

So far I have observed three way it could go:

~~1. RPT that is spawned outside of the hallway performs an attack animation, the one spawned in the hallway does a glitched attack animation (like in the video above);

  1. RPT that is spawned outside of the hallway stays still, the one spawned in the hallway does a glitched attack animation;
  2. RPT that is spawned outside of the hallway stays still, the one spawned in the hallway does a normal attack animation;~~

If I position Maria outside of the hallway and freeze her location, then the bug still happens or doesn't happen, so it's not tied to her receiving damage.

What it seems to be tied to is indeed RPT triggering stabbing animation in the hallway prior to the cutscene. Interesting part here is that, depending on where in the hallway you will make him trigger the stabbing animation, his stabbing animation starting point in the cutscene will change.

So, for example, you can make him do the animation properly in the cutscene but it will be delayed and totally asynchronized with Maria's animation of receiving the stab.

Three different ways RPT animation goes: https://youtu.be/Xo9EAsXGijE

sh2pc.exe+1BB12E8 (01FB12E8) float โ€” Maria X position
sh2pc.exe+1BB12F0 (01FB12F0) float โ€” Maria Z position

Where he first attacks during chase will determine how delayed his cutscene attack animation is?!

Welp... Now I'm even more confused.

Not an actual fix yet, just relevant info.

Cutscenes timers:

sh2pc.exe+1B7A7B8 (01F7A7B8) float
sh2pc.exe+1B7A7C8 (01F7A7C8) 4 bytes

sh2pc.exe+1B7AF4C (01F7AF4C) 4 bytes โ€” Hospital hallway RPT attack delay timer (delay is issued when he actually makes a hit on Maria or James)

Delay values:

120 โ€” hard
540 โ€” normal
960 โ€” easy
1800 โ€” beginner

RPT position during hallway chase:

sh2pc.exe+1BB1E18 (01FB1E18) float โ€” Z position
sh2pc.exe+1BB1E20 (01FB1E20) float โ€” X position

Right now it seems that the issue stems from RPT speed (walking, attacking etc) being increased for the hallway section of the game via some raggedy code that also make the moment of the stab happen sooner.

In theory, that stab animation starting point should have a value that check against a cutscene timer value and starts the animation. At least this is how blur effects in the cutscenes work. Maybe something else gets checked against the timer and starts the animation. Either way, if the starting point value is found, then it should be possible to increase it to make animation start later.

Interesting part here is that, depending on where in the hallway you will make him trigger the stabbing animation, his stabbing animation starting point in the cutscene will change.

This is only true for beginner difficulty. On other action difficulties RPT being in attack mode or delay mode doesn't make any difference on the cutscene animation.

Once again, not the stabbing animation but the attack delay that happens after the attack is responsible. If you try to receive an attack purposefully and then run towards the cutscene, then the delay will always be a little different which visually results into RPT animation being stopped at a different point of the cutscene once the delay is ended.

So it is possible to change starting point (or stretch duration) of the stab animation: https://youtu.be/vNBpdHCt1H8

Great find! And can this adjustment be done regardless of what action difficulty is being used?

And can this adjustment be done regardless of what action difficulty is being used?

Haven't checked that, was just showing that it is possible to change a starting point.

On PS2 version unloading hallway RPT results in cutscene RPT having not only all the animation synchronized right but also correct Y level elevation. PC version has some issues with unloading hallway RPT, so no fix yet.

https://youtu.be/bN4USl-NeCM

For SLUS-20228GH

20402161 byte โ€” change from 2 to 1 before entering the cutscene

Random:

204022C1 byte โ€” change from 4 to 3 to change RPT's Y level present in the cutscene. Value of 3 makes him stand on the floor properly.

My current fix is as raggedy as the code that is responsible for the issue since it involves corrupting hallway RPT. Works for all action difficulties.

https://youtu.be/jf3AnYn5Jio

sh2pc.exe+1BB1E00 (01FB1E00) 4 byte
sh2pc.exe+1BB1E0C (01FB1E0C) 4 byte

Set these two addresses to 0xFFFFFFFF value (one iteration, no constant write) right before the cutscene start to corrupt the hallway RPT and make the cutscene RPT play its animation properly.

Ideally, you would want to set the values using the cutscene index change as a condition but it might not work. If you try to set the values during the cutscene, then the cutscene RPT will corrupt too. Setting the values right on the cutscene index address value change might be fast enough not to corrupt cutscene RPT โ€” I cannot check that, it has to be programmed and tried. If it doesn't work, then it should be possible to use James Z position coordinate to make the corruption. Since James has some inertion to his forward movement there is a certain point right before the cutscene trigger area, crossing which a player will inevitably start the cutscene. That coordinate point could be used as a corruption condition.

sh2pc.exe+1B7A7C4 (01F7A7C4) 4 bytes โ€” cutscene index
The cutscene in question is 0x30.

James' position coordinates:

sh2pc.exe+1BB101C (01FB101C) float
sh2pc.exe+1BB1024 (01FB1024) float

My current fix is as raggedy as the code that is responsible for the issue since it involves corrupting hallway RPT. Works for all action difficulties.

Sometimes the way to fix something that was made with spit and glue is to fix it with some more spit and glue. :)

Setting the values right on the cutscene index address value change might be fast enough not to corrupt cutscene RPT โ€” I cannot check that, it has to be programmed and tried.

I'll ask Aero if he would make us a script for testing down the line.

Thank you, Bigmanjapan! This is a universal (across all platforms) bug that now has the potential to be resolved for PC version thanks to your research and development!

@elishacloud
Setting those two addresses to FFFFFFFF at cutscene initiation doesn't work as it renders Pyramid Head invisible. Using Bigmanjapan's other approach might be the way to go then:

Ideally, you would want to set the values using the cutscene index change as a condition but it might not work. If you try to set the values during the cutscene, then the cutscene RPT will corrupt too. Setting the values right on the cutscene index address value change might be fast enough not to corrupt cutscene RPT โ€” I cannot check that, it has to be programmed and tried. If it doesn't work, then it should be possible to use James Z position coordinate to make the corruption.

WHEN
Room ID 01FB7DAC (4 bytes) - 0000005B

AND
James Position X/Z? 01FB101C (float) IS GREATER THAN 33185

SET BOTH:
sh2pc.exe+1BB1E00 (01FB1E00) 4 byte
sh2pc.exe+1BB1E0C (01FB1E0C) 4 byte

TO:
FFFFFFFF (one iteration, no constant write)

UPON ROOM ID END:
Re-initialize this code each time the Room ID and James position conditions have been met again. (In case a player reloads a previous save point and re-initializes this area.)

@Bigmanjapan
Good news, your second recommended solution:

If it doesn't work, then it should be possible to use James Z position coordinate to make the corruption. Since James has some inertion to his forward movement there is a certain point right before the cutscene trigger area, crossing which a player will inevitably start the cutscene. That coordinate point could be used as a corruption condition.

Works consistently every time! Pyramid Head's attack is now always in sync to the rest of the cutscene animation. Elisha implemented the following solution above.

However, there is one unintended consequence of corrupting the Pyramid Head that chases you: His footstep SFX goes on a continuous loop while the cutscene plays.

https://youtu.be/orWj8aa5nyI

The speed/loudness/intensity of his footstep sounds varies each time you initiate the cutscene. Sometimes the footsteps go crazy-fast, other times they may not play at all.

Is it possible to kill the footsteps during this part? If that can be resolved, then this fix should be good to check-in? Here is a test build with the current fix in place: d3d8_b1.2.1315.zip

Well, a rather quick and dirty solution would be setting RPT coordinates to 0 right before the cutscene in order to move him far way from the hospital maze location. Since footsteps' sound events are tied to his model position, it will be silent once he's positioned far away.

Bear in mind that the RPT coordinates addresses change depending on whether the hospital maze location is loaded via regular game progression (when savefiles are not used) or loaded via regular saving system / quickloading.

When loading is not used (addresses has to be confirmed one more time):

sh2pc.exe+1BB1B4C (01FB1B4) float โ€” Z position
sh2pc.exe+1BB1B54 (01FB154) float โ€” X position

When loaded via quickloading:

sh2pc.exe+1BB1E18 (01FB1E18) float โ€” Z position
sh2pc.exe+1BB1E20 (01FB1E20) float โ€” X position

I will try to find another solution though.

Actually, @Bigmanjapan , I tried out your solution of moving RPT far away and it seems to work great; the footsteps are gone.

Unless you think there's an issues with it, we could go ahead and use this solution so we don't have to worry about it any more than we need to?

If we'd want to use this, here is what needs to be done:

Just like before:

WHEN
Room ID 01FB7DAC (4 bytes) - 0000005B

AND
James Position X/Z? 01FB101C (float) IS GREATER THAN 33185

In addition to setting the previous addresses, ALSO SET BOTH:
RPT Hospital X position (no load) sh2pc.exe+1BB1B54 (01FB1B54) float
RPT Hospital X position (game load) sh2pc.exe+1BB1E20 (01FB1E20) float

TO:
999999 (one iteration, no constant write)

Just like before, UPON ROOM ID END:
Re-initialize this code each time the Room ID and James position conditions have been met again. (In case a player reloads a previous save point and re-initializes this area.)

@Polymega, Here is a test module. See if this works: d3d8.zip

BTW: I think there is a typo in your addresses. It should be:

  • RPT Hospital X position (no load) sh2pc.exe+1BB1B54 (01FB1B54) float

Alright, I'm going to delete my most recent posts and consolidate everything to better explain:

For this fix, as mentioned by Bigmanjapan, it turns out the game uses different sets of addresses depending on whether or not you loaded a game save file to get to this point or if you started a fresh, new game and made it all the way to this point from the beginning without loading back in.

For all my previous play tests, I loaded right to this point for convenience and ease.

Our current fix iteration works every time for when you load a save file and get to this point. but not for "fresh" playthroughs.

Every time I think I found the addresses to fix it for fresh playthroughs, different addresses are used for these values on my next playtest. The memory addresses are always the same to fix this when loading a save file to get to this point, but that doesn't seem to be the case for fresh playthroughs.

Here are _some_ of the addresses I found that affect RPT's corruption and X position on fresh playthroughs. But again, these change each time. So some of the corruption addresses will corrupt RPT on one fresh playthrough, but other addresses will do so on another playthrough:

RPT corruption addresses (no game load):
sh2pc.exe+1BB293C (01FB293C) 4 byte
sh2pc.exe+1BB3F90 (01FB3F90) 4 byte
sh2pc.exe+1BB3F9C (01FB3F9C) 4 byte
sh2pc.exe+1B7DF10 (01F7DF10) 4 byte

RPT position X (no game load):
sh2pc.exe+1BB4548 (01FB4548) float

And here is where our fix stands right now:

Room ID 01FB7DAC (4 bytes) - 0000005B

AND
James Position X/Z? 01FB101C (float) *IS GREATER THAN* 33185

SET:
RPT corruption pt. 1 (from game load) sh2pc.exe+1BB1E00 (01FB1E00) 4 byte
RPT corruption pt. 2 (from game load) sh2pc.exe+1BB1E0C (01FB1E0C) 4 byte
RPT corruption pt. 1 (no game load) sh2pc.exe+??????? (????????) 4 byte
RPT corruption pt. 2 (no game load) sh2pc.exe+??????? (????????) 4 byte

TO:
FFFFFFFF (one iteration, no constant write)

AND SET: 
RPT Hospital X position (from game load) sh2pc.exe+1BB1E20 (01FB1E20) float
RPT Hospital X position (no game load) sh2pc.exe+??????? (????????) float

TO: 
999999 (one iteration, no constant write)

@Polymega
Throughout the whole game HP values are assigned dynamically to a small region of addresses which in their turn could be traced via a single pointer address. I'll find the pointer a bit later.

I'll point out again that I don't really like this corruption solution since if you wait long enough after corrupting RPT (some internal RPT animation cycle?) the game will just crash. It only works because a player will step into a cutscene fast enough for the game not to crash.

I'll point out again that I don't really like this corruption solution since if you wait long enough after corrupting RPT (some internal RPT animation cycle?) the game will just crash. It only works because a player will step into a cutscene fast enough for the game not to crash.

I see. I wasn't aware of potential crash issues. If you're up to it, we could pause this current solution, to see if you find a more suitable fix?

I tried another route of finding addresses that could put RPT to an unspawn state instead of corrupting him.

sh2pc.exe+1B7AEA1 (01F7AEA1) byte โ€” one of the RPT state addresses
Set it to 5 once upon Room ID 01FB7DAC (4 bytes) - 0000005B and James Position X/Z? 01FB101C (float) *IS GREATER THAN* 33185

This will suspend RPT without corrupting him (no game crashes). It will also make him silent, so there is no need in shifting his position to get rid of the footsteps' sounds.

And it's consolidated down to a single address now? Beautiful, Bigmanjapan, _beautiful._

@elishacloud an update for the HospitalChaseFix fix. Things that are strikethroughed below will be dropped from the current iteration of this fix. Things that are bold will be added:

WHEN:
Room ID 01FB7DAC (4 bytes) - 0000005B

AND:
James Position X/Z? 01FB101C (float) is greater than 33185

SET:
RPT State Address sh2pc.exe+1B7AEA1 (01F7AEA1) byte

  • TO: 5 (one iteration, no constant write)

RPT Corruption pt. 1 (from game load) sh2pc.exe+1BB1E00 (01FB1E00) 4 byte
RPT Corruption pt. 2 (from game load) sh2pc.exe+1BB1E0C (01FB1E0C) 4 byte

  • TO: FFFFFFFF (one iteration, no constant write)

RPT Hospital X position (no load) sh2pc.exe+1BB1B54 (01FB1B54) float
RPT Hospital X position (game load) sh2pc.exe+1BB1E20 (01FB1E20) float

  • TO: 999999 (one iteration, no constant write)

UPON ROOM ID END:
Re-initialize this code each time the Room ID and James position conditions have been met again. (In case a player reloads a previous save point and re-initializes this area.)

Here is a test module with this fix implemented. Take a look at it and let me know if there are any issues with it. Test module: d3d8.zip

_Note: this only works on v1.0._

Played it both on a "no game load" run and a loaded save file run and it worked flawlessly both times. Great work you two!

I implemented a fix to get this working on all versions of SH2, however I am not completely sure the addresses on v1.1 and vDC are correct. Try this one and see if it works on all versions: d3d8.zip

Good news: This works on all versions. :)

Very good. Implemented in check in 8795f76.

Crazy that for 18+ years I always though RPT's bugged animation was just the way that was supposed to be. But nope, Bigmanjapan came to the rescue once more with his research and proposed solution! Thank you and Elisha for implementing the fix!

An update has been released with this fix in it. See v1.3.1340.0

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Storm3000 picture Storm3000  ยท  10Comments

Polymega picture Polymega  ยท  14Comments

gregitol picture gregitol  ยท  5Comments

Polymega picture Polymega  ยท  18Comments

Storm3000 picture Storm3000  ยท  3Comments