ffc script Locked{
void run(int dir, int offset, int adjacent, bool boss, bool big){
//Wait until the door is unlocked by Link if not already unlocked on screen init.
while(!GetScreenDBit(0, dir) && !OpeningDoor(this, dir%4, boss)) Waitframe();
//Initialize a variable as the location of combo the ffc is placed at.
int comboLoc = ComboAt(this->X, this->Y);
//Change the variable we just initialized according to the dir and big arguments.
if(dir%4 == 0 || big) comboLoc -= 16;
if(dir%4 == 2) comboLoc -= 1;
//Loop through the horizontal combos.
for(int i; i < 2; i++){
//In each iteration of the loop, loop through the vertical combos.
for(int j; (big && j < 3) || j < 2; j++){
//Increment the combo data of the combo by the offset argument.
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] += offset;
}
}
//Check the screen D bit (dir) on register 0, and if it's already set skip the rest of the script.
if(!GetScreenDBit(0, dir)){
//It wasn't set which means Link just opened the door. So set it so it opens on screen init.
SetScreenDBit(0, dir, true);
//For back to back doors we need to set the screen bit on the adjacent screen.
SetScreenDBit(adjacent, 0, AdjacentDir(dir), true);
//If not a boss door subtract 1 key from Link's inventory.
if(!boss){
if(Game->LKeys[Game->GetCurLevel()] > 0) Game->LKeys[Game->GetCurLevel()]--;
else Game->Counter[CR_KEYS]--;
}
//Lastly play a sound effect.
Game->PlaySound(SFX_SHUTTER);
}
}
//This function checks if link is trying to open the door, and meets the requirements to do so.
bool OpeningDoor(ffc this, int dir, bool boss){
//If a boss door and the player has no boss key return false;
if(boss && !GetLevelItem(LI_BOSSKEY)) return false;
//If not a boss door and the player has no keys return false;
else if(!boss && Game->Counter[CR_KEYS] == 0 && Game->LKeys[Game->GetCurLevel()] == 0) return false;
//Check if Link is near-centered with the door nonfacing central axis.
else if(dir < 2 && Abs(Link->X - this->X) >= 4) return false;
else if(dir >= 2 && Abs(Link->Y - this->Y) >= 4) return false;
//Lastly return whether or not Link is next to the door and pushing against it.
else if(dir == 0) return (Link->Y == this->Y + 8 && Link->InputUp);
else if(dir == 1) return (Link->Y == this->Y - 16 && Link->InputDown);
else if(dir == 2) return (Link->X == this->X + 16 && Link->InputLeft);
else if(dir == 3) return (Link->X == this->X - 16 && Link->InputRight);
}
//This Function returns the direction of the adjacent screens locked door.
int AdjacentDir(int dir){
//We need a variable for both loops which is the number of doors
int i;
//dir%4 incrementing i by one each time we wrap.
for(; dir >= 4; i++) dir -= 4;
//Flip dir around so we have the opposite direction.
dir = OppositeDir(dir);
//Now add i4 to dir.
dir += (i*4);
//Lastly return dir.
return dir;
}
}
ffc script Shutter{
void run(int dir, int offset, int type, bool oneway, bool big){
//Check if Link is in the doorway.
if(InDoorway(this, OppositeDir(dir))){
//Link is in the doorway so open the shutter, copy & pasted from above.
int comboLoc = ComboAt(this->X, this->Y);
if(dir == 0 || big) comboLoc -= 16;
if(dir == 2) comboLoc -= 1;
for(int i; i < 2; i++){
for(int j; (big && j < 3) || j < 2; j++){
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] += offset;
}
}
//Wait until the screen finishes scrolling.
do{
Waitframe(); //The scrolling doesn't start on screen init but one frame afterwards.
} while(Link->Action == LA_SCROLLING);
//Force Link into the room by nulling all controls accept the correct arrow key.
while(InDoorway(this, dir)){
NoAction();
if(dir == 0) Link->InputDown = true;
else if(dir == 1) Link->InputUp = true;
else if(dir == 2) Link->InputRight = true;
else if(dir == 3) Link->InputLeft = true;
Waitframe();
}
//Close the shutter behind Link, copy & pasted from above.
for(int i; i < 2; i++){
for(int j; (big && j < 3) || j < 2; j++){
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] -= offset;
}
}
//Play the shutter sound effect.
Game->PlaySound(SFX_SHUTTER);
}
//Otherwise wait a while. "Makes it so all shutters open simultaneously if the condition is fulfilled on screen init."
else{
do{
Waitframe();
} while(Link->Action == LA_SCROLLING);
Waitframes(25);
}
//End the script here if it's a one way shutter.
if(oneway) Quit();
//Initialize blocks as the number of blocks on the screen.
int blocks = NumBlocks();
//Wait until the condition for opening the shutter is fulfilled.
while(true){
if(type == 0 && NoEnemies()) break;
else if(type == 1 && NumBlocks() != blocks) break;
else if(type == 2 && LastComboFlagOf(CF_BLOCKTRIGGER, 0) == -1) break;
else if(type == 3 && Screen->State[ST_SECRET]) break;
//If you need a custom condition for the shutter just add a else if at the end of the loop and assign it a number other than 0-3.
Waitframe();
}
//If it's a block->shutter wait 20 frames.
if(type == 1) Waitframes(20);
//Else if it's a secret->shutter set the secret screen state to false.
else if(type == 3) Screen->State[ST_SECRET] = false;
//Open the shutter, copy and pasted from above.
int comboLoc = ComboAt(this->X, this->Y);
if(dir == 0 || big) comboLoc -= 16;
if(dir == 2) comboLoc -= 1;
for(int i; i < 2; i++){
for(int j; (big && j < 3) || j < 2; j++){
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] += offset;
}
}
//Lastly play the shutter sound since it just opened.
Game->PlaySound(SFX_SHUTTER);
}
//This function checks if link is in the doorway.
bool InDoorway(ffc this, int dir){
//Simply check link's position relative to the number and the location of the ffc.
if(dir == 0) return(Link->X == this->X && Link->Y < 32);
else if(dir == 1) return(Link->X == this->X && Link->Y > 128);
else if(dir == 2) return(Link->Y == this->Y && Link->X < 32);
else if(dir == 3) return(Link->Y == this->Y && Link->X > 208);
}
//This function check if all enemies have been defeated as if it was a normal shutter room.
bool NoEnemies(){
//Initialize a boolean as true.
bool condition = true;
//Loop through every npc.
for(int i = Screen->NumNPCs(); i > 0; i--){
//Load each npc to a pointer.
npc n = Screen->LoadNPC(i);
//Continue if the enemy is a item fairy.
if(n->ID == NPC_ITEMFAIRY) continue;
//Continue if the enemy has the "Doesn't count as beatable enemy" flag.
else if(GetNPCMiscFlag(n, 8)) continue;
//Since a beatable enemy exists, set condition to false and break out of the loop.
condition = false;
break;
}
return condition;
}
//This function returns the number of combos with push _ trigger flags.
int NumBlocks(){
//Declare the blocks variable.
int blocks;
//Loop through all 176 combos.
for(int i; i < 176; i++){
//If the inherited or placement flag is 1, 2, or 47 - 51 increment blocks.
if(ComboFI(i, 1)) blocks++;
else if(ComboFI(i, 2)) blocks++;
else if(ComboFI(i, 47)) blocks++;
else if(ComboFI(i, 48)) blocks++;
else if(ComboFI(i, 49)) blocks++;
else if(ComboFI(i, 50)) blocks++;
else if(ComboFI(i, 51)) blocks++;
}
//Return the blocks variable.
return blocks;
}
}
ffc script Bombable{
void run(int dir, int offset, int adjacent, int dustdata, int dustloc, bool big){
//Check if the wall was already bombed by checking screen d bit (dir) on register 0.
if(GetScreenDBit(0, dir)){
//Open a hole in the wall, copy and pasted from above.
int comboLoc = ComboAt(this->X, this->Y);
if(dir == 0 || big) comboLoc -= 16;
if(dir == 2) comboLoc -= 1;
for(int i; i < 2; i++){
for(int j; (big && j < 3) || j < 2; j++){
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] += offset;
}
}
//Change the ffc's data to dustdata and reposition it.
this->Data = dustdata;
this->X = ComboX(dustloc);
this->Y = ComboY(dustloc);
//Check if Link is in the doorway.
if(InDoorway(this, OppositeDir(dir), big)){
//The following is copy and pasted from the shutter script.
do{
Waitframe();
} while(Link->Action == LA_SCROLLING);
while(InDoorway(this, dir, big)){
NoAction();
if(dir%4 == 0) Link->InputDown = true;
else if(dir%4 == 1) Link->InputUp = true;
else if(dir%4 == 2) Link->InputRight = true;
else if(dir%4 == 3) Link->InputLeft = true;
Waitframe();
}
}
//Since there's nothing else to do end the script.
Quit();
}
//Declare the bombed variable.
bool bombed;
//Loop until bombed becomes true.
while(!bombed){
//Loop through each lweapon on screen.
for(int i = Screen->NumLWeapons(); i > 0 && !bombed; i--){
//Load the lweapon to a pointer.
lweapon l = Screen->LoadLWeapon(i);
//If the weapon is not a bomb blast or super bomb blast end this iteration of the loop.
if(l->ID != LW_BOMBBLAST && l->ID != LW_SBOMBBLAST) continue;
//If collision for the weapon is on and it collided with the ffc set bombed to true.
if(Collision(this, l) && l->CollDetection) bombed = true;
}
Waitframe();
}
//copy and pasted from locked script.
int comboLoc = ComboAt(this->X, this->Y);
if(dir == 0 || big) comboLoc -= 16;
if(dir == 2) comboLoc -= 1;
for(int i; i < 2; i++){
for(int j; (big && j < 3) || j < 2; j++){
int combo = comboLoc + i + (16 * j);
Screen->ComboD[combo] += offset;
}
}
//copy and pasted from above.
this->Data = dustdata;
this->X = ComboX(dustloc);
this->Y = ComboY(dustloc);
//Set the screen D bit for (dir) on register 0.
SetScreenDBit(0, dir, true);
//Set the screen D bit for the adjacent screen.
SetScreenDBit(adjacent, 0, AdjacentDir(dir), true);
}
//Function copy and pasted from shutter script.
bool InDoorway(ffc this, int dir, bool big){
int mod = 0;
if(dir < 2 || !big) mod = 8;
if(dir == 0) return(Link->X == this->X+mod && Link->Y < 32);
else if(dir == 1) return(Link->X == this->X+mod && Link->Y > 128);
else if(dir == 2) return(Link->Y == this->Y+mod && Link->X < 32);
else if(dir == 3) return(Link->Y == this->Y+mod && Link->X > 208);
}
//Function copy and pasted from locked script.
int AdjacentDir(int dir){
int i;
for(; dir >= 4; i++) dir -= 4;
dir = OppositeDir(dir);
dir += (i*4);
return dir;
}
}