New Mod Doubts

Open-source port of PoP that runs natively on Windows, Linux, etc.
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

New Mod Doubts

Post by Akruzen »

Hello Everyone,

I had a few doubts regarding the source code of SDL PoP:

1) How to set a time delay between two actions? For example, let's say you want the prince to do

Code: Select all

seqtbl_offset_char(seq_5_turn)
after

Code: Select all

seqtbl_offset_char(seq_50_crouch)
after 2 seconds. Is it possible?

2) Execute an event after any particular action. For example, after drinking red potion on level 2 in room 1, I want to trigger a raise tile located at room 3, row 3, column 3. I tried:

Code: Select all

get_tile(3, 3, 3);
trigger_button(0, 0, -1);
inside the

Code: Select all

current_level == 2 && curr_room == 1
conditional block but it did not work.

3) Teleport prince to a defined room with defined row and column. For example, in the Vanilla version, teleport the prince to the end level door after performing a certain action. Note that the rooms are all previously defined (i.e. created using any level editor or so) and I do not intend to "generate" them dynamically. I tried

Code: Select all

Char.y = y_land[3];
Char.curr_row = 3;
But that changes only the row and not the room. (Also I couldn't manipulate the X Coordinate for the kid)

4) Change the colour of vapours coming out of the potions (preferably programmatically) and detect those colours to use them in if - else statements. Any other snippet might also do provided I can add potions which perform different functions.

5) Last but not the least, has the solution been found for the bug where Prince can pass through closed gates when he has taken out his sword? (Draw sword anywhere mod)

Thanking You,

Best Regards,
Akruzen
What if life is a video game and Déjà Vu are just checkpoints?
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: New Mod Doubts

Post by dmitry_s »

1. You can create a timer variable if you know how many frames a sequence takes. Set the variable to the number of frames after the first sequence and run the second sequence when the timer variable is 0. Sequences can be interrupted so you would have to check the "curr_seq" of the character before starting a new one. This solution is a bit ugly. Maybe David would know a better way.

https://github.com/NagyD/SDLPoP/blob/98 ... 003.c#L486

2. Try passing "tiles_15_opener" as the second "trigger_button" parameter.

3. "drawn_room" and "next_room" variables are responsible for switching rooms. You probably have to change "Char.room" also. There is not enough information to provide the exact answer. You would also need to assign "Char.x" and call "determine_col" or assign the character column through "x_bump".

4. The potion color drawing logic is here.
https://github.com/NagyD/SDLPoP/blob/0c ... 008.c#L642

You can check for "(curr_modifier & 0xF8) >> 3" after calling get_tile...() in conditional statements.

5. I have made a couple of changes in my mod to the "check_gate_push" function to fix an issue where kid can walk through the gate on the left or turn with the sword through the gate. I am not sure if there is another issue.

Code: Select all

void check_gate_push() {
    // Closing gate pushes Kid
    short frame;
    short orig_col;
    frame = Char.frame;
    if (Char.action == actions_7_turn ||
            frame <= frame_15_stand || // stand/run
            (frame >= frame_45_turn && frame <= frame_65_runturn) || // turn
            (frame >= frame_108_fall_land_2 && frame < 111) || // crouch
            frame == frame_157_walk_with_sword
       ) {
        get_tile_at_char();
        orig_col = tile_col;
        int orig_room = curr_room;
        if ((curr_tile2 == tiles_4_gate ||
                get_tile(curr_room, --tile_col, tile_row) == tiles_4_gate) &&
                (curr_row_coll_flags[tile_col] & prev_coll_flags[tile_col]) == 0xFF &&
                can_bump_into_gate()
           ) {
            bumped_sound();
            // If get_tile() changed curr_room from orig_room to the left neighbor of orig_room (because tile_col was outside room orig_room),
            // then change tile_col (and curr_room) so that orig_col and tile_col are meant in the same room.
            if (curr_room == level.roomlinks[orig_room - 1].left) {
                tile_col -= 10;
                curr_room = orig_room;
            }
            // custom logic - push kid to the left of the gate when turning around with sword
            if (Char.sword == sword_2_drawn &&
                    Char.direction == dir_0_right &&
                    Opp.alive < 0 &&
                    Opp.sword == sword_2_drawn &&
                    tile_col == orig_col) {
                Char.x += 10;
                return;
            }
            // push Kid left if orig_col <= tile_col, gate at char's tile
            // push Kid right if orig_col > tile_col, gate is left from char's tile
            Char.x += 5 - (orig_col <= tile_col) * 10;
        }
    }
}
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: New Mod Doubts

Post by David »

Akruzen wrote: September 7th, 2021, 3:25 pm 2) Execute an event after any particular action. For example, after drinking red potion on level 2 in room 1, I want to trigger a raise tile located at room 3, row 3, column 3. I tried:

Code: Select all

get_tile(3, 3, 3);
trigger_button(0, 0, -1);
inside the

Code: Select all

current_level == 2 && curr_room == 1
conditional block but it did not work.
Rows and columns are numbered from 0, so row 3 would refer to the top row of the room below room 3.
The correct call would be: get_tile(3, 2, 2);
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

Thank You for your replies David and Dmitry_s,
dmitry_s wrote: September 10th, 2021, 6:19 pm You can create a timer variable if you know how many frames a sequence takes.Maybe David would know a better way.
I tried the timer solution, however I could not execute it. I then searched the net and found out that one can use the SDL_GetTicks() function to check time. However the solution was too complicated as the compiler did not find any libraries when I mentioned #include "SDL.h" (I have downloaded all the libraries mentioned on David's GitHub page and the code also compiles if I remove the SDL.h line). The situation I mentioned was just an example. I wanted the timer variable for many reasons. If there is any other way by which I can tell the compiler to:
Do this, then after x milliseconds do this
while the rest of the code which is not inside the so called "wait" function continues as usual, then that is also ok by me.
dmitry_s wrote: September 10th, 2021, 6:19 pm Maybe David would know a better way.
Yes, please help as without the function, my mod will not behave as expected. :)

Thanking You,
Best Regards,
Akruzen
What if life is a video game and Déjà Vu are just checkpoints?
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: New Mod Doubts

Post by dmitry_s »

I meant a timer variable in a context of SDLPoP, not SDL Timer. In seg003.c there is a "timers()" function that is executed on every frame. It has variables that typically count down. So if you set such a variable to (for example) 3 and put a logic statement "if (--var == 0)" inside that function, the if condition is going to execute after 3 frames.
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

dmitry_s wrote: September 16th, 2021, 6:11 pm I meant a timer variable in a context of SDLPoP
Thanks Dmitry_s, will do that.
Also, is there any way to know if the prince drinks empty potion? For example, there is case 0 in switch statement for potion vapour animation which represents empty pot. But I could not find similar case in switch statement in the switch case which is executed while he drinks certain potions (eg. Case 0 is health).
Also is there any way to know and toggle the torchShadow feature like the is_blind_mode? How can I make it more dark?
What if life is a video game and Déjà Vu are just checkpoints?
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: New Mod Doubts

Post by dmitry_s »

Akruzen wrote: September 19th, 2021, 5:14 pm Thanks Dmitry_s, will do that.
Also, is there any way to know if the prince drinks empty potion? For example, there is case 0 in switch statement for potion vapour animation which represents empty pot. But I could not find similar case in switch statement in the switch case which is executed while he drinks certain potions (eg. Case 0 is health).
You would have to remove the part of the if statement that checks for "pickup_obj_type == 0" first.
https://github.com/NagyD/SDLPoP/blob/98 ... 06.c#L1775

Then in the switch statement below an empty potion object type would be -1. For some reason the switch statement decrements the original value of the variable.
Akruzen wrote: September 19th, 2021, 5:14 pm Also is there any way to know and toggle the torchShadow feature like the is_blind_mode? How can I make it more dark?
I am not exactly sure what the torch shadow feature is. There is a mode that makes the room darker. It can be enabled through the "enable_lighting" option in SDLPoP.ini.

It can be flipped in the code this way.

Code: Select all

enable_lighting = 1; // or 0
need_full_redraw = 1;
You can decrease this value to make the room darker.
https://github.com/NagyD/SDLPoP/blob/98 ... ting.c#L29
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

dmitry_s wrote: September 19th, 2021, 9:25 pm You can decrease this value to make the room darker.
Thanks Dmitry_s, that helped a lot. I still am encountering few questions as I am drawing closer to finishing the mod.

1. Is there any way to declare a global variable having a default value which can be used across the segment files? How can I save this in Quicksave file so that those values are recalled when pressed Quickload? Currently when I assign any value to variable, it automatically reverts back to null or 0 once it goes out of scope or the function stops.

2. The blind mode, enable lighting options do not get saved when I press reload after re-opening the game. Is it on purpose to avoid errors or am I missing something here?

3. Is there any way to replace the default music of SDLPoP? If there is, how can I ensure the program uses music mentioned in SDLPoP folders and not the custom levelset's folder's default music? I found a topic related to this here but converting into ogg and pasting them in music folder doesn't help. Also, is it possible to add (and not replace) new music in the game?

Thanking You,
Best Regards,
Akruzen
What if life is a video game and Déjà Vu are just checkpoints?
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: New Mod Doubts

Post by dmitry_s »

Akruzen wrote: September 22nd, 2021, 8:34 pm 1. Is there any way to declare a global variable having a default value which can be used across the segment files? How can I save this in Quicksave file so that those values are recalled when pressed Quickload? Currently when I assign any value to variable, it automatically reverts back to null or 0 once it goes out of scope or the function stops.
Global variables are defined in the "data.h" file. You can assign a default value by marking it as "extern" and using "INIT=( value )". https://github.com/NagyD/SDLPoP/blob/master/src/data.h

The "quick_process" method is responsible for saving/restoring the variable in quicksave/quickload. Put it at the bottom of the function to avoid previously stored quicksaves from breaking.
https://github.com/NagyD/SDLPoP/blob/98 ... 000.c#L254

Methods responsible for saving variables for the standard save/load functionality (Ctrl-G/Ctrl-L) can be found here. Make sure the type is "word/int" because "byte" or other types with a different number of bits do not work properly here.
https://github.com/NagyD/SDLPoP/blob/98 ... 00.c#L2058
Akruzen wrote: September 22nd, 2021, 8:34 pm 2. The blind mode, enable lighting options do not get saved when I press reload after re-opening the game. Is it on purpose to avoid errors or am I missing something here?
Add the "enable_lighting" variable to the "quick_process" method.
Akruzen wrote: September 22nd, 2021, 8:34 pm 3. Is there any way to replace the default music of SDLPoP? If there is, how can I ensure the program uses music mentioned in SDLPoP folders and not the custom levelset's folder's default music? I found a topic related to this here but converting into ogg and pasting them in music folder doesn't help. Also, is it possible to add (and not replace) new music in the game?
PR editor can be used to extract and reimport DIGISND?.DAT files. They contain wav files that can be replaced. Only 8-bit per sample files will work.
viewtopic.php?t=3365
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

dmitry_s wrote: September 23rd, 2021, 7:49 am
Global variables are defined in the "data.h" file. You can assign a default value by marking it as "extern" and using "INIT=( value )". https://github.com/NagyD/SDLPoP/blob/master/src/data.h
I tried it but it says "undefined reference to custom_timer". Then I even tried putting it in "process" function in seg000.c but it isn't happening. Can you please elaborate? Also is there any way to detect what is prince's current frame and store such multiple frames of kid in global variables?
What if life is a video game and Déjà Vu are just checkpoints?
dmitry_s
Developer
Developer
Posts: 148
Joined: July 27th, 2021, 7:22 am

Re: New Mod Doubts

Post by dmitry_s »

Did you do a full project rebuild after modifying an ".h" file?
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: New Mod Doubts

Post by David »

Akruzen wrote: September 22nd, 2021, 8:34 pm 3. Is there any way to replace the default music of SDLPoP? If there is, how can I ensure the program uses music mentioned in SDLPoP folders and not the custom levelset's folder's default music? I found a topic related to this here but converting into ogg and pasting them in music folder doesn't help.
You can do either of these:

a) You can delete or rename the MIDISND*.DAT and IBM_SND*.DAT files in the custom levelset's folder.
While I was testing this, I found out that SDLPoP doesn't like if sound files are missing from a mod's folder, due to how sounds are loaded in load_all_sounds().
I pushed a fix: https://github.com/NagyD/SDLPoP/commit/ ... 815878ba95

b) In load_all_sounds(), change the if condition so that it's always true.
This way all OGG files will override all music from DAT files.
(Should I add an INI option for this?)

The current form of load_all_sounds() was added in this commit: https://github.com/NagyD/SDLPoP/commit/ ... 6a9d8515e9
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

dmitry_s wrote: September 25th, 2021, 2:22 am Did you do a full project rebuild after modifying an ".h" file?
Yes, rebuilding files worked. Any idea how to set prince to a particular frame? I tried setting

Code: Select all

Kid.frame = frame_106_fall;
in a if statement but that doesn't affect prince at all. The rest of the code in that if statement works, so the statement is reachable.
David wrote: September 26th, 2021, 9:38 am This way all OGG files will override all music from DAT files.
(Should I add an INI option for this?)
Yes, that would be very helpful. Is there any similar way by which we can use the graphics of SDLPoP and not the custom mod's folder? That would be very helpful :)
What if life is a video game and Déjà Vu are just checkpoints?
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: New Mod Doubts

Post by David »

Akruzen wrote: September 26th, 2021, 12:41 pm Any idea how to set prince to a particular frame? I tried setting

Code: Select all

Kid.frame = frame_106_fall;
in a if statement but that doesn't affect prince at all. The rest of the code in that if statement works, so the statement is reachable.
You need to call seqtbl_offset_char() with the seq_XXX constant corresponding to the animation you want to start.

You can find them here: https://github.com/NagyD/SDLPoP/blob/v1 ... pes.h#L986
User avatar
Akruzen
Developer
Developer
Posts: 141
Joined: April 30th, 2016, 10:16 am

Re: New Mod Doubts

Post by Akruzen »

David wrote: September 26th, 2021, 12:52 pm You need to call seqtbl_offset_char() with the seq_XXX constant corresponding to the animation you want to start.

You can find them here: https://github.com/NagyD/SDLPoP/blob/v1 ... pes.h#L986
Thank You for prompt reply David, however, I don't want to start any animation. I want prince to take a certain frame for 1 frame. That's why I tried putting the if statement in timers() function in seg003. Though the rest get's executed in the timer, prince doesn't change its frame for that particular moment. Any idea how to do this?
What if life is a video game and Déjà Vu are just checkpoints?
Post Reply