Copy to Clipboard Test

Better Ladder Code

//Main Files
#include "include/std.zh"
//Imports functions exclusive to my quest
//#include "CustomFunctions.zs"// You probably won't need this.
//I'm not sure you'll need this either.
#include "headers/stdExtra.zh"

// Section 28. ffcscript.zh
// Version 1.1.1
// Be sure to check if you're already importing ffcscript.zh
// Adjust to match the settings therein

// Combo to be used for generic script vehicle FFCs. This should be
// an invisible combo with no type or flag. It cannot be combo 0.
const int FFCS_INVISIBLE_COMBO = 1;

// Range of FFCs to use. Numbers must be between 1 and 32.
const int FFCS_MIN_FFC = 1;
const int FFCS_MAX_FFC = 32;


int RunFFCScript(int scriptNum, float args){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc theFFC;
    
    // Find an FFC not already in use
    for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
        theFFC=Screen->LoadFFC(i);
        
        if(theFFC->Script!=0 ||
         theFFC->Data!=0 ||
         theFFC->Flags[FFCF_CHANGER])
            continue;
        
        // Found an unused one; set it up
        theFFC->Data=FFCS_INVISIBLE_COMBO;
        theFFC->Script=scriptNum;
        
        if(args!=NULL){
            for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
                theFFC->InitD[j]=args[j];
        }
        
        return i;
    }
    
    // No FFCs available
    return 0;
}

ffc RunFFCScriptOrQuit(int scriptNum, float args){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        Quit();
    
    int ffcID=RunFFCScript(scriptNum, args);
    if(ffcID==0)
        Quit();
    
    return Screen->LoadFFC(ffcID);
}

int FindFFCRunning(int scriptNum){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc f;
    
    for(int i=1; i<=32; i++){
        f=Screen->LoadFFC(i);
        if(f->Script==scriptNum)
            return i;
    }
    
    // No FFCs running it
    return 0;
}

int FindNthFFCRunning(int scriptNum, int n){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc f;
    
    for(int i=1; i<=32; i++){
        f=Screen->LoadFFC(i);
        if(f->Script==scriptNum){
            n--;
            if(n==0)
                return i;
        }
    }
    
    // Not that many FFCs running it
    return 0;
}

int CountFFCsRunning(int scriptNum){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc f;
    int numFFCs=0;
    
    for(int i=1; i<=32; i++){
        f=Screen->LoadFFC(i);
        if(f->Script==scriptNum)
            numFFCs++;
    }
    
    return numFFCs;
}

const int LADDER_COMB0		=3;//Combo used to show ladder
const int LADDER_CSET		=5;//CSet of that combo
const int LADDER_SCRIPT		=1;//Script slot used by ladder script
const int LADDER_WALKABLE	=2;//A walkable combo. Place inherent flags to limit enemy movement
const int I_SCRIPT_LADDER	=50;//Item id of scripted ladder. Defaults to Amulet 1
const int GH_INVISIBLE_COMBO=1;//An invisible combo. 

//Place in items active slot
item script BetterLadder{
	void run(int four_way){
		//You aren't currently running the ladder script
		if(!CountFFCsRunning(LADDER_SCRIPT)){
			int Args[8]= {four_way};
			NewFFCScript(LADDER_SCRIPT, Args);
		}
	}
}

// A better function for launching ffcs
int NewFFCScript(int scriptNum, float args){
    // Invalid script
    if(scriptNum<0 || scriptNum>511)
        return 0;
    
    ffc theFFC;
    
    // Find an FFC not already in use
    for(int i=FFCS_MIN_FFC; i<=FFCS_MAX_FFC; i++){
        theFFC=Screen->LoadFFC(i);
        
        if(theFFC->Script!=0 ||
         (theFFC->Data!=0 && theFFC->Data!=FFCS_INVISIBLE_COMBO) ||
         theFFC->Flags[FFCF_CHANGER])
            continue;
        
        // Found an unused one; set it up
        theFFC->Data=FFCS_INVISIBLE_COMBO;
		theFFC->TileWidth = 1;
		theFFC->TileHeight = 1;
        theFFC->Script=scriptNum;
        
        if(args!=NULL){
            for(int j=Min(SizeOfArray(args), 8)-1; j>=0; j--)
                theFFC->InitD[j]=args[j];
        }
        theFFC->Flags[FFCF_ETHEREAL]= true;
        return i;
    }
    
    // No FFCs available
    return 0;
}

//Check to see if a particular location can be crossed with a ladder
//Supports checks of layers 1 and 2
bool CanLadder(int loc){
	int Layer1_Map = Screen->LayerMap(1);
    int Layer1_Screen= Screen->LayerScreen(1);
	int Layer2_Map = Screen->LayerMap(2);
    int Layer2_Screen= Screen->LayerScreen(2);
	if (Screen->ComboT[loc]==CT_LADDERONLY)
		return true;
	if (Screen->ComboT[loc]==CT_LADDERHOOKSHOT)
		return true;
	if (Screen->ComboT[loc]==CT_WATER)
		return true;	
    if(Game->GetComboType(Layer1_Map,Layer1_Screen,loc)==CT_LADDERONLY)
		return true;
	if(Game->GetComboType(Layer1_Map,Layer1_Screen,loc)==CT_LADDERHOOKSHOT)
		return true;	
	if(Game->GetComboType(Layer2_Map,Layer2_Screen,loc)==CT_LADDERONLY)
		return true;	
	if(Game->GetComboType(Layer2_Map,Layer2_Screen,loc)==CT_LADDERHOOKSHOT)
		return true;	
	return false;
}

//Script run when ladder is used
ffc script That_Ladder{
	void run(bool four_way){
		//Set up appearance of ladder ffc
		this->Data= LADDER_COMB0;
		this->CSet= LADDER_CSET;
		//Make sure it still runs while holding up an item
		this->Flags[FFCF_IGNOREHOLDUP]= true;
		//Orient based on the direction you're facing
		if(Link->Dir==DIR_LEFT||
			Link->Dir==DIR_RIGHT){
			if(Link->Dir==DIR_LEFT)
				this->X= GridX(Link->X-8);
			else
				this->X= GridX(Link->X+24);
			this->Y= GridY(Link->Y+8);
		}
		else{
			if(Link->Dir==DIR_UP)
				this->Y= GridY(Link->Y-8);
			else
				this->Y= GridY(Link->Y+24);
			this->X= GridX(Link->X+8);
		}
		//Check what button is being used by the ladder
		bool A_Button;
		if(GetEquipmentA()==I_SCRIPT_LADDER)
			A_Button= true;
		//FFC position checks
		int Combo_X= GridX(this->X);
		int Combo_Y= GridY(this->Y);
		int loc = ComboAt(Combo_X,Combo_Y);
		//Hold data for combo replaced by the script
		int Saved_Combo=-1;
		int Saved_CSet;
		//Used to simplify checks for future ffc position
		int X;
		int Y;
		//Check if the spot the ffc is on is a ladder spot
		if(CanLadder(loc)){
			//Replace the walkable combo's tile with the tile of the combo the ladder is on
			CopyTile(Game->ComboTile(Screen->ComboD[loc]),
						Game->ComboTile(LADDER_WALKABLE));
			//Save the data for the combo the ladder is on
			Saved_Combo= Screen->ComboD[loc];
			Saved_CSet= Screen->ComboC[loc];
			//Replace the combo the ladder is on with a walkable one
			Screen->ComboD[loc] =LADDER_WALKABLE;
			Screen->ComboC[loc] = Saved_CSet;
		}
		//Save the direction you're facing when you place the ladder
		int dir= Link->Dir;
		//You've made a ladder spot walkable
		if(Saved_Combo!=-1){
			//The ladder is on the A button
			if(A_Button){
				//You haven't pressed A
				while(!Link->PressA){
					Waitframe();
					//Check what direction you were facing when you placed the ladder
					if(dir==DIR_UP
						||dir==DIR_DOWN){
						//Check your current coordinates relative to the ffc
						if(Link->Y<=this->Y+15
							&& Link->Y+17>=this->Y){
							if(Link->X>=this->X-2
								&& Link->X<=this->X+18){
								//You're on the ladder
								//Don't let the player walk off the left or right side
								//Don't let the player remove the ladder
								if(!four_way)
									Link->X= this->X;
								Link->PressA=false;
							}
						}
					}
					else{
						if(Link->X<=this->X+15
							&& Link->X+17<=this->X){
							if(Link->Y<=this->Y+18
								&& Link->Y+17>=this->Y){
								if(!four_way)
									Link->Y= this->Y;
								Link->PressA=false;
							}
						}
					}
				}
			}
			else{
				//This ladder is on the B button
				//You haven't pressed B
				while(!Link->PressB){
					Waitframe();
					if(dir==DIR_UP
						||dir==DIR_DOWN){
						if(Link->Y<=this->Y+15
							&& Link->Y+17>=this->Y){
							if(Link->X<=this->X+15
								&& Link->X+17>=this->X){
								if(!four_way)
									Link->X= this->X;
								Link->PressB=false;
							}
						}
					}
					else{
						if(Link->X<=this->X+15
							&& Link->X+15>=this->X){
							if(Link->Y<=this->Y+15
								&& Link->Y+17>=this->Y){
								if(!four_way)
									Link->Y= this->Y;
								Link->PressB=false;
							}
						}
					}
				}
			}
		}
		else{
			//The ladder isn't on a ladder spot
			while(true){
				//On the A button
				if(A_Button){
					//You haven't pressed A
					while(!Link->PressA)
						Waitframe();
					break;
				}
				else{
					//On the B button
					//You haven't pressed B
					while(!Link->PressB)
						Waitframe();
					break;
				}
				Waitframe();
			}
		}
		//Make the ladder invisible
		this->Data= FFCS_INVISIBLE_COMBO;
		//If you replaced a combo, restore it
		if(Saved_Combo!=-1){
			Screen->ComboD[loc]= Saved_Combo;
			Screen->ComboC[loc]= Saved_CSet;
		}
		//Keep you from using the ladder for a bit
		Waitframes(30);
		//This script is done
		Quit();
	}
}

//Checks for matching combo flag and type.

//D0- On scren location.
//D1- Combo Flag to check.
//D2- Combo Type to check.

bool ComboFIT(int loc,int flag,int type){
	if(ComboFI(loc,flag)&& Screen->ComboT[loc]==type)return true;
	return false;
}

//Checks for matching combo flag and type.

//D0- On scren location.
//D1- Combo Flag to check.
//D2- Combo Type to check.

bool ComboFIT(int X, int Y,int flag,int type){
	int loc = ComboAt(X,Y);
	if(ComboFI(loc,flag)&& Screen->ComboT[loc]==type)return true;
	return false;
}