// SIDEVIEW LADDER --------------------------------------------------------------------------------------------
import "std.zh" // only need this once
import "ffcscript.zh" // only need this once
// ----------------------------------------------------------------------
// Setup
//
// 1. Modify the constants to fit your needs. It looks for both, so they can potentially be used by other scripts.
// If so, the other script will probably want to make sure it isn't both. isSVLadder function is helpful for this.
// 2. Use one of the existing globals (see step#3) if no other global scripts.
// Or see the sample globals at the bottom of the script to see how to combine.
// 3. Decide if using the global version or FFC version. DON'T USE BOTH!!!!
// Global - if you have lots of screens with the sideview ladder combos
// FFC - only a few sideview ladder screens, or want more flexibility reusing the Script ComboTypes/Flags.
// Both versions require adding things to the global script. Each has its own sample global script at the bottom.
// 3a. If using the FFC version, just place the Sideview_Ladder FFC on that screen. Won't run on non-SV screens.
// See the sample global, as there are numerous things to add to global for the FFC version.
// 3b. If using the global version, add or uncomment the GLB_Sideview_Ladder(); part of the global script.
// See the sample global for what needs to be included.
// 4. Watch out for compile conflicts with the isSolid function that many other scripts use.
// Optional Setup
//
// Roc's Feather
// 1. The script looks for only the default Roc Feather item#.
// So if you've changed that, or have multiple levels of Roc items, you'll need to mod that part of the script.
//
// Item use on ladder
// 1. A/B buttons are still enabled, allowing item use on the ladder
// Expect weird behavior with certain items due to the script changing Link's direction.
// i.e. can stab sword to the side while facing up
// If you use the hookshot, you're likely going to need to modify the script to make it work right, or disable it.
// ----------------------------------------------------------------------
// Constants
// Sideview Ladder constant
const int CT_SVLADDER = 142; // CT_SCRIPT1, ComboType for Sideview Ladder
const int CF_SVLADDER = 99; // CF_SCRIPT2, ComboFlag for Sideview Ladder
// This ComboFlags can be reused since this script requires both the ComboType and Flag.
// If reusing, that script should check that it isn't the SV ComboType.
// ----------------------------------------------------------------------
// Global variable
//sideview ladder
bool onLadder = false;
// ----------------------------------------------------------------------
// Sideview Ladder functions (FFC and global versions)
// Place the FFC version on any screen with your sideview ladders. won't run on non Sideview screens
// DON'T use this AND the global version
ffc script Sideview_Ladder{
void run(){
onLadder = false;
if(!IsSideview()) Quit();
itemdata feather = Game->LoadItemData(I_ROCSFEATHER);
while(true){
onLadder = false;
if( isSVLadder(Link->X+8, Link->Y+6) || isSVLadder(Link->X+8, Link->Y+15) ){
// Link is on SV ladder
onLadder = true;
if(Link->Jump < 0) Link->Jump=0;
if(Link->InputUp){
if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) )
Link->Y--;
}
else if(Link->InputDown){
if( !isSolid(Link->X+1, Link->Y+16) && !isSolid(Link->X+8, Link->Y+16) && !isSolid(Link->X+14, Link->Y+16) )
Link->Y++;
}
if( (Link->InputRight || Link->InputLeft) && useFeather() && Link->Jump == 0){
if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) ){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
if(isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+14, Link->Y+16) ){
// Link is standing on solid ground at the base of SV Ladder
onLadder = false;
if(useFeather()){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
}
else if( isSVLadder(Link->X+8,Link->Y+16) ){
// Link is standing on top of SV Ladder
Link->Jump=0;
if(Link->InputDown){
Link->Y++;
onLadder = true;
}else if(useFeather()){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
else if( isSVLadder(Link->X+8,Link->Y+17) || isSVLadder(Link->X+8,Link->Y+18) ){
// Link is falling above SV Ladder, snap him to grid so we don't miss
Link->Jump = 0;
Link->Y += 16 - (Link->Y%16);
}
Waitframe();
}// end whileloop
}//end run
}//end ffc Sideview_Ladder
// Global function that doesn't get us stuck as always climbing when leaving an FFC sideview ladder screen while climbing
// sets onLadder to false if it isn't Sideview, or if the Sideview Ladder FFC script isn't present on new screen
void FFCBugFix_SVLadder(int oldscreen, int olddmap){
if(!IsSideview()) onLadder = false;
else{
int buffer[] = "Sideview_Ladder";
if(CountFFCsRunning(Game->GetFFCScript(buffer)) == 0) onLadder = false;
}
}
// Global version of Sideview Ladder script.
// If you have lots of screens using the sideview ladder this will save you the hassle of having to place the FFC on each one
// If using the global, DON'T use the FFC.
void GLB_Sideview_Ladder(){
onLadder = false;
if(!IsSideview()) return;
itemdata feather = Game->LoadItemData(I_ROCSFEATHER);
if( isSVLadder(Link->X+8, Link->Y+6) || isSVLadder(Link->X+8, Link->Y+15) ){
// Link is on SV ladder
onLadder = true;
if(Link->Jump < 0) Link->Jump=0;
if(Link->InputUp){
if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) )
Link->Y--;
}
else if(Link->InputDown){
if( !isSolid(Link->X+1, Link->Y+16) && !isSolid(Link->X+8, Link->Y+16) && !isSolid(Link->X+14, Link->Y+16) )
Link->Y++;
}
if( (Link->InputRight || Link->InputLeft) && useFeather() && Link->Jump == 0){
if( !isSolid(Link->X+1, Link->Y-1) && !isSolid(Link->X+8, Link->Y-1) && !isSolid(Link->X+14, Link->Y-1) ){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
if(isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+8, Link->Y+16) && isSolid(Link->X+14, Link->Y+16) ){
// Link is standing on solid ground at the base of SV Ladder
onLadder = false;
if(useFeather()){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
}
else if( isSVLadder(Link->X+8,Link->Y+16) ){
// Link is standing on top of SV Ladder
Link->Jump=0;
if(Link->InputDown){
Link->Y++;
onLadder = true;
}else if(useFeather()){
Game->PlaySound(feather->UseSound);
Link->Jump = 1.6 + (feather->Power*0.8);
}
}
else if( isSVLadder(Link->X+8,Link->Y+17) || isSVLadder(Link->X+8,Link->Y+18) ){
// Link is falling above SV Ladder, snap him to grid so we don't miss
Link->Jump = 0;
Link->Y += 16 - (Link->Y%16);
}
}//end GLB_Sideview_Ladder
// ----------------------------------------------------------------------
// Utility functions used by Sideview Ladder
// Useful for other scripts to call for script interactions
// Returns true if x,y is both the SV Ladder flag and type
bool isSVLadder(int x, int y){
int loc = ComboAt(x,y);
return( Screen->ComboT[loc] == CT_SVLADDER && ComboFI(loc, CF_SVLADDER) );
}
bool isSVLadder(int loc){
return( Screen->ComboT[loc] == CT_SVLADDER && ComboFI(loc, CF_SVLADDER) );
}
// returns true if feather is equipped and being used
// could add more checks for more Roc Items in here, or some other type of jumping method, eg L-button.
bool useFeather(){
if(GetEquipmentA()==I_ROCSFEATHER && Link->PressA) return true;
if(GetEquipmentB()==I_ROCSFEATHER && Link->PressB) return true;
return false;
}
// !!!!!!!!! This function is used by a lot of scripts. Only need it once.
//returns true if the combo is solid at x/y
bool isSolid(int x, int y){
if(x<0 || x>255 || y<0 || y>175) return false;
int mask=1111b;
if(x%16<8) mask&=0011b;
else mask&=1100b;
if(y%16<8) mask&=0101b;
else mask&=1010b;
return (!(Screen->ComboS[ComboAt(x, y)]&mask)==0);
}
// ----------------------------------------------------------------------
// Sample global scripts
//
// If not using any other global scripts, just compile this.
// Load the corresponding global for the method you are using.
//
// If combining with existing global script, see the sample for the method you are using, and read the comments.
global script Slot_2_FFCVersion{
void run(){
int olddmap = Game->GetCurDMap(); //*********** other scripts may use these same variables
int oldscreen = Game->GetCurDMapScreen(); //*********** only need including once (before global loop)
while(true){
//*********** code like this if statement is common, only needs including once.
//*********** near the top of global loop (before Waitdraw)
if(Link->Action != LA_SCROLLING){
if( oldscreen != Game->GetCurDMapScreen() || olddmap != Game->GetCurDMap() ){
//********** if there is similar code to this if statement, this FFCBugFix should be added
FFCBugFix_SVLadder(oldscreen, olddmap); //*********** (before waitdraw & before oldscreen,olddmap are set)
olddmap = Game->GetCurDMap();
oldscreen = Game->GetCurDMapScreen();
}
}
Waitdraw();
if (onLadder) Link->Dir = DIR_UP; //********* (After Waitdraw)
Waitframe();
}//end whileloop
}//end run
}//end global slot2 FFC Version
global script Slot_2_GLB_Version{
void run(){
while(true){
GLB_Sideview_Ladder(); //********* (before waitdraw)
Waitdraw();
if (onLadder) Link->Dir = DIR_UP; //********* (After Waitdraw)
Waitframe();
}//end whileloop
}//end run
}//end global slot2 Global Version