Keep guards after they fall offscreen

Open-source port of PoP that runs natively on Windows, Linux, etc.
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Keep guards after they fall offscreen

Post by David »

Shauing wrote: January 22nd, 2022, 11:07 am How can it be made that all guards can fall to other rooms without dying?
In addition to the hex edit, I also implemented this in SDLPoP, on a new branch:
https://github.com/NagyD/SDLPoP/compare ... llen_guard
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

David wrote: March 20th, 2022, 12:57 pm In addition to the hex edit, I also implemented this in SDLPoP, on a new branch:
https://github.com/NagyD/SDLPoP/compare ... llen_guard
This is an interesting feature. I think it can be improved in a couple of ways.

1. "leave_guard" function should return if the "Guard.action" is 3 or 4 so that the guard does not get stuck in the air when you exit the room.

There is also going to be an edge where you leave the room when the guard is standing on a loose tile. The tile is going to fall but the guard will not.

2. "leave_guard" should be called after the guard had landed in a room that is not "drawn_room".
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP

Post by David »

dmitry_s wrote: March 21st, 2022, 4:02 pm 1. "leave_guard" function should return if the "Guard.action" is 3 or 4 so that the guard does not get stuck in the air when you exit the room.
I tried this:

Code: Select all

void __pascal far leave_guard() {
	word room_minus_1;

#ifdef KEEP_FALLEN_GUARD
	if (Guard.action == actions_3_in_midair || Guard.action == actions_4_in_freefall) {
		//follow_guard();
		return;
	}
#endif
But then a new bug appears:
If the guard is falling when I leave the room, he will return to his original position when I re-enter the room!

If I uncomment follow_guard() then the guard will still stop mid-air when I exit the room.
But then at least he will continue with his previous speed when I re-enter the room.

dmitry_s wrote: March 21st, 2022, 4:02 pm 2. "leave_guard" should be called after the guard had landed in a room that is not "drawn_room".
I added this at the end of land():

Code: Select all

#ifdef KEEP_FALLEN_GUARD
	if (Char.charid != charid_0_kid && Char.room != drawn_room) {
		leave_guard();
	}
#endif
Was this intended to fix the bug I described above?
This doesn't fix it.

At this point, Guard.action == 4, so leave_guard() doesn't even do anything because of the change above.

What am I doing wrong?


Attached is the levelset I used for testing.
Start level 4.
keep_fallen_guard_test_level_4.zip
(8.47 KiB) Downloaded 74 times
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

Here are my changes as well as some scenarios that I have tested.

https://github.com/dstarosta/SDLPoP/com ... f76cdc9848





Last edited by dmitry_s on March 29th, 2022, 6:08 am, edited 1 time in total.
User avatar
atrueprincefanfrom18
Site Shah
Site Shah
Posts: 1782
Joined: January 21st, 2020, 2:53 pm
Contact:

Re: SDLPoP; David's open-source port of PoP

Post by atrueprincefanfrom18 »

OMG!! :shock:
Love to create new MODS :)

My complete list of mods until now!

My channel. Do consider subscribing it! :)
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

Added a bugfix where dead fallen guards got saved as alive.

https://github.com/dstarosta/SDLPoP/com ... e6a5d8bc62
User avatar
VelCheran
Vizier
Vizier
Posts: 127
Joined: May 28th, 2020, 7:26 pm

Re: SDLPoP; David's open-source port of PoP

Post by VelCheran »

dmitry_s wrote: March 27th, 2022, 8:26 pm Here are my changes as well as some scenarios that I have tested.
That's great!
Now shauing can port his Queen of Light mod to DOS :D
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

I am wondering if it would be better to extend the "FIX_OFFSCREEN_GUARDS_DISAPPEARING" setting to include this behavior.
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

I added a couple of commits to fix bugs and allow guard to follow kid down the room.
https://github.com/dstarosta/SDLPoP/com ... llen_guard

All this logic allows to create some interesting levels where you have to get the guard down several rooms without killing him. Guards are useful to hold gates open.

dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: SDLPoP; David's open-source port of PoP

Post by dmitry_s »

The first commit had that problem. It should be fixed in the second commit.

https://github.com/dstarosta/SDLPoP/com ... baff6bR268

If you can reproduce it, please post a video or a replay file.

Here is some information about how prince saves guards. There is a "Guard" variable that represents the guard in the prince's room. Normally it is only applicable to the current room but this change allows you to have the active guard to fall into a different room or follow prince from a room above.

However, if prince exits a room without a guard following him the "leave_guard" function saves guard coordinates into multiple arrays such as "level.guards_tile", "level.guards_seq_hi" and a few others that display the guard's coordinates, whether the guard is alive (by saving the sequence for dead guards and setting it to 0 for non-dead guards), direction, skill, etc. The array index is the room number which limits guards to 1 per room. This way the Guard variable can be reused for the next room. The "enter_guard" function uses those arrays to construct the Guard variable instance.

If a guard is following prince, then "leave_guard" is not called and the guards coordinates switch to the new room as prince exits it. The guard is also cleared from the previous room the in the arrays. But because of the limitation of 1 guard per room, guards cannot follow or fall into a room with an active guard without causing him to disappear.

Quicksave saves the Guard variable and the arrays. The problem happens in the "leave_function" that determines whether the guard is alive or not by checking whether the "Guard.alive < 0". But there is also a "guardhitp_curr" variable that stores the number of guard's lives/hit points. And it takes a frame to set the "alive" variable for the guard after there are no more hit points left.

This is not a problem when leaving rooms since it takes a few frames to switch the room. However, if you "quickload" on a perfect frame, the "leave_guard" function is going to store the guard as alive since the "alive" variable is still set to -1.

In order to store the fallen guard in a different room, I have to call the "leave_guard" function explained in a few posts above. But when after the guard falls and dies, the "take_hp" method only zeros out the hit points which caused the "leave_function" to store the guard as alive. But unless you re-enter the room or quickload the "Guard" variable is still going to show a dead guard.

Setting the "alive" variable to 0 manually kinda works. But the problem is the "on_guard_killed" function is not going to get called because it is normally called where the code checks guard's hit points and sets the "alive" variable. Calling the "on_guard_killed" function manually is also not ideal because you would not get the splash/spiked sound. There could be other side effects in edge cases as that function does other things like opening the last level door after Jaffar is killed.

To get around this behavior, I had to set the "alive" variable to -128 and modify the "leave_guard" function to store the guard as dead while the game still thinks he is alive for a few more frames. That allowed all the sounds and special events to work correctly as well as getting rid of the bug. Quicksave/load also works fine because it stores all of the variables.

I have no idea why Mechner did not use a Guard (char_type) array which would have made things way simpler. Instead there is a lot of different logic, as you can see in my commits, where guards were restricted to a single room. The original logic also can save guards in mid-air as there are no arrays for fall_x/fall_y data. If you enter the room back, the guard will appear in mid-air but the fall speed is going to be reset causing glitches as in level 7 during speed runs. With the new logic guards can continue falling as long as there is no new guard in the other room. In that case the "Guard" variable gets overwritten and the falling guard in the other room disappears.
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Keep guards after they fall offscreen

Post by David »

(Moved posts to a new thread.)
User avatar
yourantumayel69
Calif
Calif
Posts: 565
Joined: November 12th, 2019, 9:53 am
Location: Indonesia
Contact:

Re: SDLPoP; David's open-source port of PoP

Post by yourantumayel69 »

dmitry_s wrote: March 31st, 2022, 1:50 am I added a couple of commits to fix bugs and allow guard to follow kid down the room.
https://github.com/dstarosta/SDLPoP/com ... llen_guard

All this logic allows to create some interesting levels where you have to get the guard down several rooms without killing him. Guards are useful to hold gates open.

Can you please give me SDLPoP ZIP file? I wait for you
Pengkhotbah 3:1 (TB) Untuk segala sesuatu ada masanya, untuk apa pun di bawah langit ada waktunya.
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: Keep guards after they fall offscreen

Post by dmitry_s »

SDLPoP_fallen_guard.zip
(1.86 MiB) Downloaded 80 times
User avatar
yourantumayel69
Calif
Calif
Posts: 565
Joined: November 12th, 2019, 9:53 am
Location: Indonesia
Contact:

Re: Keep guards after they fall offscreen

Post by yourantumayel69 »

dmitry_s wrote: April 9th, 2022, 6:36 pm SDLPoP_fallen_guard.zip
Thanks for ZlP file for test play. It's simple if I test keep fallen guard. If possible, I suggest you: multiple keep fallen guard, multiple death guard offscreen, and guard die by loose floor like your mod (Prince 1.5)
Pengkhotbah 3:1 (TB) Untuk segala sesuatu ada masanya, untuk apa pun di bawah langit ada waktunya.
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: Keep guards after they fall offscreen

Post by dmitry_s »

yourantumayel69 wrote: April 14th, 2022, 8:22 am
dmitry_s wrote: April 9th, 2022, 6:36 pm SDLPoP_fallen_guard.zip
Thanks for ZlP file for test play. It's simple if I test keep fallen guard. If possible, I suggest you: multiple keep fallen guard, multiple death guard offscreen, and guard die by loose floor like your mod (Prince 1.5)
In the standard PoP1 implementation there is only 1 guard slot per room that can store a dead or alive guard. Storing dead guards separately can be done (like in my mod) at the expense of breaking binary compatibility of saves and replays.

But guards can fall or get pushed into other rooms and that requires a lot of code changes since a fallen/pushed guard is not a dead guard and has to move across rooms which already have the guard slot taken by another guard.

In my mod I have separate slots and a additional (mini) sequence table for those scenarios and that involves a lot of code. But it also supports 2 alive guards per room (only 1 guard can be stabbed, the other one will perfectly block all attacks or step back) and up to 5 total guards.

Prince of Persia 2 does has a few more tricks. The fight sequence has been completely rewritten so you do not just deal with 2 variables at a time (Char and Opp) but I think the fight physics became worse. They also have multiple death frames per guard. And once you have over 2 guards in a room stabbed guards start to randomly fall out of the screen so they do not have to be tracked while falling.

https://www.youtube.com/watch?v=dhwU33IPmVQ&t=4552s
Post Reply