const int CF_ELEVATOR = 98; //Combo flag marking elevator tracks
const int CF_ELEVATORSTOP = 99; //Combo flag marking that you can get off an elevator
const int SFX_ELEVATOR_START = 6; //Sound that plays when an elevator starts moving
const int SFX_ELEVATOR_PERSISTENT = 17; //Sound that plays while an elevator moves
const int ELEVATOR_SFX_FREQ = 4; //How often the persistent sound plays
const int ELEVATOR_STEP = 4; //How fast elevators move along tracks
const int LM_ACTION = 0; //Link->Misc for special actions
const int LMA_ON_ELEVATOR = 1; //Link->Misc state for being on an elevator
ffc script Elevator{
void run(int offX, int offY, int combo){
int elevatorX = this->X+offX;
int elevatorY = this->Y+offY;
int elevatorDir;
int targetX; int targetY;
int sfxTimer;
bool onElevator;
int data = this->Data;
this->Data = FFCS_INVISIBLE_COMBO;
Waitframe();
if(combo>0){
if(Link->Misc[LM_ACTION]==LMA_ON_ELEVATOR){
this->Data = combo;
}
else{
Quit();
}
}
else
this->Data = data;
if(Link->Misc[LM_ACTION]==LMA_ON_ELEVATOR&&ComboFI(Link->X+8, Link->Y+8, CF_ELEVATOR)){
elevatorX = ComboX(ComboAt(Link->X+8, Link->Y+8));
elevatorY = ComboY(ComboAt(Link->X+8, Link->Y+8));
this->X = elevatorX-offX;
this->Y = elevatorY-offY;
if(elevatorX==0)
elevatorDir = DIR_RIGHT;
else if(elevatorX==240)
elevatorDir = DIR_LEFT;
else if(elevatorY==0)
elevatorDir = DIR_DOWN;
else if(elevatorY==160)
elevatorDir = DIR_UP;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->Misc[LM_ACTION]==LMA_ON_ELEVATOR)
Link->Misc[LM_ACTION] = 0;
while(true){
while(Link->Misc[LM_ACTION]==LMA_ON_ELEVATOR){
while(Distance(elevatorX, elevatorY, targetX, targetY)>ELEVATOR_STEP){
if(SFX_ELEVATOR_PERSISTENT>0){
sfxTimer++;
if(sfxTimer>ELEVATOR_SFX_FREQ){
sfxTimer = 0;
Game->PlaySound(SFX_ELEVATOR_PERSISTENT);
}
}
int angle = Angle(elevatorX, elevatorY, targetX, targetY);
elevatorX += VectorX(ELEVATOR_STEP, angle);
elevatorY += VectorY(ELEVATOR_STEP, angle);
this->X = elevatorX-offX;
this->Y = elevatorY-offY;
Link->X = elevatorX;
Link->Y = elevatorY;
Link->Jump = 0;
Waitframe();
}
elevatorX = targetX;
elevatorY = targetY;
this->X = elevatorX-offX;
this->Y = elevatorY-offY;
Link->X = elevatorX;
Link->Y = elevatorY;
if(ComboFI(elevatorX+8, elevatorY+8, CF_ELEVATORSTOP)){
Link->Misc[LM_ACTION] = 0;
if(Link->InputUp&&CheckElevator(elevatorX, elevatorY, DIR_UP)){
elevatorDir = DIR_UP;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputDown&&CheckElevator(elevatorX, elevatorY, DIR_DOWN)){
elevatorDir = DIR_DOWN;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputLeft&&CheckElevator(elevatorX, elevatorY, DIR_LEFT)){
elevatorDir = DIR_LEFT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputRight&&CheckElevator(elevatorX, elevatorY, DIR_RIGHT)){
elevatorDir = DIR_RIGHT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else{
while(!Link->PressUp&&!Link->PressDown&&!Link->PressLeft&&!Link->PressRight){
Waitframe();
}
Waitframe();
}
}
else{
int oldDir = elevatorDir;
elevatorDir = -1;
for(int i=0; i<4&&elevatorDir==-1; i++){
if(OppositeDir(oldDir)!=i){
if(CheckElevator(elevatorX, elevatorY, i))
elevatorDir = i;
}
}
if(elevatorDir==-1)
elevatorDir = oldDir;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
if(ElevatorNumBranches(elevatorX, elevatorY)>2){
elevatorDir = -1;
while(elevatorDir==-1){
this->X = elevatorX-offX;
this->Y = elevatorY-offY;
Link->X = elevatorX;
Link->Y = elevatorY;
Link->Jump = 0;
if(Link->InputUp&&CheckElevator(elevatorX, elevatorY, DIR_UP)){
elevatorDir = DIR_UP;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputDown&&CheckElevator(elevatorX, elevatorY, DIR_DOWN)){
elevatorDir = DIR_DOWN;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputLeft&&CheckElevator(elevatorX, elevatorY, DIR_LEFT)){
elevatorDir = DIR_LEFT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
else if(Link->InputRight&&CheckElevator(elevatorX, elevatorY, DIR_RIGHT)){
elevatorDir = DIR_RIGHT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
}
Waitframe();
}
}
}
}
if(Distance(elevatorX, elevatorY, Link->X, Link->Y)<8){
if(Link->Dir==DIR_UP&&Link->PressUp&&CheckElevator(elevatorX, elevatorY, DIR_UP)){
elevatorDir = DIR_UP;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
Game->PlaySound(SFX_ELEVATOR_START);
}
else if(Link->Dir==DIR_DOWN&&Link->PressDown&&CheckElevator(elevatorX, elevatorY, DIR_DOWN)){
elevatorDir = DIR_DOWN;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
Game->PlaySound(SFX_ELEVATOR_START);
}
else if(Link->Dir==DIR_LEFT&&Link->PressLeft&&CheckElevator(elevatorX, elevatorY, DIR_LEFT)){
elevatorDir = DIR_LEFT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
Game->PlaySound(SFX_ELEVATOR_START);
}
else if(Link->Dir==DIR_RIGHT&&Link->PressRight&&CheckElevator(elevatorX, elevatorY, DIR_RIGHT)){
elevatorDir = DIR_RIGHT;
targetX = ElevatorTargetX(elevatorX, elevatorY, elevatorDir);
targetY = ElevatorTargetY(elevatorX, elevatorY, elevatorDir);
Link->Misc[LM_ACTION] = LMA_ON_ELEVATOR;
Game->PlaySound(SFX_ELEVATOR_START);
}
}
Waitframe();
}
}
bool CheckElevator(int elevatorX, int elevatorY, int elevatorDir){
int x; int y;
if(elevatorDir==DIR_UP){
x = elevatorX+8;
y = elevatorY-8;
if(ComboFI(x, y, CF_ELEVATOR)||ComboFI(x, y, CF_ELEVATORSTOP))
return true;
}
else if(elevatorDir==DIR_DOWN){
x = elevatorX+8;
y = elevatorY+24;
if(ComboFI(x, y, CF_ELEVATOR)||ComboFI(x, y, CF_ELEVATORSTOP))
return true;
}
else if(elevatorDir==DIR_LEFT){
x = elevatorX-8;
y = elevatorY+8;
if(ComboFI(x, y, CF_ELEVATOR)||ComboFI(x, y, CF_ELEVATORSTOP))
return true;
}
else if(elevatorDir==DIR_RIGHT){
x = elevatorX+24;
y = elevatorY+8;
if(ComboFI(x, y, CF_ELEVATOR)||ComboFI(x, y, CF_ELEVATORSTOP))
return true;
}
return false;
}
int ElevatorNumBranches(int elevatorX, int elevatorY){
int count;
for(int i=0; i<4; i++){
if(CheckElevator(elevatorX, elevatorY, i))
count++;
}
return count;
}
int ElevatorTargetX(int elevatorX, int elevatorY, int elevatorDir){
if(elevatorDir==DIR_LEFT)
return elevatorX-16;
else if(elevatorDir==DIR_RIGHT)
return elevatorX+16;
else
return elevatorX;
}
int ElevatorTargetY(int elevatorX, int elevatorY, int elevatorDir){
if(elevatorDir==DIR_UP)
return elevatorY-16;
else if(elevatorDir==DIR_DOWN)
return elevatorY+16;
else
return elevatorY;
}
}