So, I'm working in the Dance of Remembrace Hybrid tileset using the latest version of 2.5 and I wanted to incorporate the Flowing Water script by MoscowModder into my latest dungeon. In case you're not familiar with it, here it is.
Spoiler
const int WATER_CURRENT_FREQ = 5; //# of frames between moving Link (CANNOT BE LOWER THAN 0)
const int WATER_CURRENT_FLAG = 99; //First of 4 flags to use in the order Up, Down, Left, Right. I changed this from flag 98 because I'm using that for something else and didn't want it to interfere.
//FFC version
//D0 = current frequency (defaults to WATER_CURRENT_FREQ)
ffc script flowingWater{
void run ( int frequency ){
if( frequency < 1 )
frequency = WATER_CURRENT_FREQ;
while ( true ){
doCurrents();
Waitframes(frequency);
swimLandCheck();
}
}
}
void doCurrents (){
if ( Link->Action==LA_SWIMMING || Link->Action==LA_DIVING ){//If Link is swimming...
//Move Link based on the current's direction...
//but make sure it isn't solid
//Up
if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG) //If swimming in the appropriate flag
//And the following combos ahead of Link are not solid
&& !Screen->isSolid(Link->X,Link->Y+6) //NW
&& !Screen->isSolid(Link->X+7,Link->Y+6) //N
&& !Screen->isSolid(Link->X+15,Link->Y+6) //NE
//Check if the combo below Link is water to prevent getting pushed out
&& waterCheck( ComboAt(Link->X,Link->Y+6))
&& waterCheck( ComboAt(Link->X+7,Link->Y+6))
&& waterCheck( ComboAt(Link->X+15,Link->Y+6))
)
Link->Y -= 2;
//Down
if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+1 )
&& !Screen->isSolid(Link->X,Link->Y+17) //SW
&& !Screen->isSolid(Link->X+7,Link->Y+17) //S
&& !Screen->isSolid(Link->X+15,Link->Y+17) //SE
&& waterCheck( ComboAt(Link->X,Link->Y+17))
&& waterCheck( ComboAt(Link->X+7,Link->Y+17))
&& waterCheck( ComboAt(Link->X+15,Link->Y+17))
)
Link->Y += 2;
//Left
if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+2 )
&& !Screen->isSolid(Link->X-2,Link->Y+8) //NW
&& !Screen->isSolid(Link->X-2,Link->Y+15) //SW
)
Link->X -= 2;
//Right
if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+3 )
&& !Screen->isSolid(Link->X+17,Link->Y+8) //NE
&& !Screen->isSolid(Link->X+17,Link->Y+15) //SE
&& waterCheck( ComboAt(Link->X+17,Link->Y+8) )
&& waterCheck( ComboAt(Link->X+17,Link->Y+15) )
)
Link->X += 2;
}
}
//Prevents Link from swimming on land
void swimLandCheck(){
if( !waterCheck( ComboAt(Link->X,Link->Y+8) ) //If Link is not in the water...
&& ( Link->Action==LA_SWIMMING || Link->Action==LA_DIVING ) ) //and swimming...
Link->Action = LA_NONE; //Make him stop swimming
}
//Checks if the designated combo is any water type
bool waterCheck(int cmb){
if( Screen->ComboT[cmb] == CT_WATER
|| Screen->ComboT[cmb] == CT_SWIMWARP
|| Screen->ComboT[cmb] == CT_SWIMWARPB
|| Screen->ComboT[cmb] == CT_SWIMWARPC
|| Screen->ComboT[cmb] == CT_SWIMWARPD
|| Screen->ComboT[cmb] == CT_DIVEWARP
|| Screen->ComboT[cmb] == CT_DIVEWARPB
|| Screen->ComboT[cmb] == CT_DIVEWARPC
|| Screen->ComboT[cmb] == CT_DIVEWARPD
)
return true; //The combo is water
return false;
}
Part of the idea I had was that there would be a way to alter the direction that the water flows on some screens. However, there are some problems with this idea.
The first is that the only way I can figure to alter the flags set on the combos that are water is either by making them have inherent flags of the appropriate number, then have all combos covered by secret flags and have the secret change the combos to identical combos with the inherent flag for whatever direction I want it to become.
This version seems needlessly complex to me, so my second idea was to create a script that changed the flag for me. I'd seen a few scripts which scanned every combo for a particular flag and if it found it, changed it to something else. Here's one example of code that does that from the Pegasus Boots script.
I thought it would be possible to create an ffc script as follows.
ffc script SwitchFlags{
void run(int oldflag, int newflag){
while(true){
if (Screen->State[ST_SECRET] == true){
for(int i = 0; i< 175; i++){
if (Screen->ComboF[i] == oldflag) Screen->ComboF[i] = newflag;
}
}
Waitframe();
}
}
}
However, expanding this to more than one flag per screen becomes problematic. For example, if you set it up with four variables (oldflag1, oldflag2, newflag1 and newflag2) and then said to change 101 to 102 and 102 to 101; all seem to be changed to 101.
I know that I'm doing something wrong with my SwitchFlags script, though I'm not sure what. So what I was looking for was a way to change the flowing water script so that if the screen secrets were triggered, you could alter which flags were set in it. How to do that I'm not sure.
I'd also kind of like a way to switch the direction in other parts of the dungeon as well when that secret is triggered. That means it may have to be global, like the script that control dungeon barriers. I'm not fluent in enough in Zscript to work that out just yet.
This code should work. It runs through every combo on the screen only once, instead of continuously, so it should avoid any issues with double switching.
ffc script SwitchFlags{
void run(int oldflag1, int oldflag2, int newflag1, int newflag2){
while(!Screen->State[ST_SECRET]){
Waitframe();
}
for(int i = 0; i < 176; i++){
if (Screen->ComboF[i] == oldflag1) Screen->ComboF[i] = newflag1;
else if (Screen->ComboF[i] == oldflag2) Screen->ComboF[i] = newflag2;
}
}
}
It uses placed flags only. Checking/replacing inherent flags only needs a copy paste of the existing code, though, replacing ComboF with ComboI.
void SetComboFlag(int map, int screen, int position, int value);
This function can set a combo flag from any room, if that's what you need instead.
@Lejes- That script works perfectly for one room... but when I set Screen-State Carryover to trigger an adjacent room's secrets and have the scripts set up there, it doesn't trigger properly.
The rooms I have set up now are horizontally aligned with two rivers, one that flows right at the top and the other that flows left at the bottom. You have to go right to reach the one that goes left, hit a switch there and then take the reversed river back right to reach the other river that will now flow left to where you need to go.
So while I can use it in one room the way I envisioned, I really need a version that could do both. Perhaps a method could be used like in your latter example where I could tell the script that when this secret is triggered, to change the flag of my choice on this map (or dmap) to a preset alternate. For example, up and down could be switched as would left and right. I can even see a way to do that (on one screen) using your code. But applying that to multiple screens or an entire map is a little out of my league at the moment. Thanks for what you've done so far and anything anyone may contribute in the future!
Are you sure you have it set up right? The script will immediately change combo flags based on the FFC arguments if that screen has permanent secrets activated. It needs to be placed in every room where the changes occur. I just tested it and it works like you'd expect. What dungeon type are you using?
Interior dungeon... for reference, the first screen (where the secret is) is Map 16 (on Dmap 22), Screen 22 and has screen state carryovers set to Map 16, Screen 23. When I go from 22 to 23 after hitting the switch, even though the proper ffcs are on both screens, it acts as if they haven't been switched. I'm also using 2.50.1 if that makes any difference.
The only thing I can think of is that for some reason the screen state isn't carrying over, since there are no secret flags on the second screen. I can post a demo quest if that helps any.
This quest is set to initiate at the screen on the righthand end of the two rivers in question with the flippers automatically equipped. When I hop in the water, it takes me left to the switch. I then hit the switch and the water flow on that screen changes. But when it carries me to the next screen right, it is obvious that the secret hasn't been triggered because I am immediately pushed back to the left. Both scripts are on all screens and for testing purposes they and the global script were the only ones I loaded into slots.
Any ideas on what is going wrong would be appreciated.
It's because you have the two scripts in the wrong order. You loaded flowing water into the first FFC, which means it runs first. It runs for the first frame, and immediately shifts you in the wrong direction before SwitchFlags has a chance to switch the flags.
Scripts have to be loaded in a certain order? Good to know... I've never run into that problem before honestly. Then again, I've never had two scripts that ran on the same screen which might counteract one another. Your solution works, if applied to all of the screens. (Even the one where you first triggered the secret.)
I also note that ffcs have the option 'run script at screen init'. Would this make one script run before other scripts no matter what order the ffc is? Because I have some scripts that use this function on screens where I might run other scripts and I'd need to know what order to place those scripts in to keep them from interfering with one another.
I think that option causes the script to run for a single frame when the screen is first loaded (before scrolling is done). So if it gets everything done on that frame, then yes, it will effectively cause it to run before other scripts regardless of how you've ordered them.
In this case... no. I'm trying to make it where you can't go a certain direction until after the switch is hit. Which is why I'm using the flowing water script, since it allows me to set the frequency with which the water pushes me high enough that I can't swim against the current.
I know MoscowModder created a different version which allowed for fast conveyors; but since the entire point of this was to make streams of water where you could only swim in one direction, then have those switch to another flag to move in another direction; this version looks like it would work best.
However, I can see a way for a fast conveyor to work on layers so that only the combo would have to be changed and could be done via secret flags rather than the script flags. But since what I have does the same thing without messing around with that, I'm not going to take the time to set that up.
@Lejes- thanks for modifying my script so that it works. I can see some easy ways to expand it to include up to 4 old flags and 4 new flags, which would cover all four directions that the flowing water script can push you in. Just got to remember to put those scripts in the ffcs in order and all...
As for my question about running the script at screen init, I haven't really tried it with this script. I just have a few scripts where that is recommended and since this is the first time I'd heard about having to have scripts in a particular order for them to run correctly, I wanted to make sure I understood how it worked so that I'd be able to resolve any issues that developed later on my own. Thanks for your help!