const int CUTSCENETRIGGER_SHOW_HITBOXES = 0; //For debugging problems with the script's hitboxes, set this to 1. const int C_CUTSCENETRIGGER_HITBOX = 0x01; //Color for the debug hitboxes const int C_CUTSCENETRIGGER_HITBOX_INACTIVE = 0x81; //Color for disabled debug hitboxes const int D_CUTSCENETRIGGER = 0; //Screen->D used for cutscene triggers //D0: The DMap to warp to for the cutscene //D1: The screen to warp to IN DECIMAL. Screens in ZQuest are numbered in hex but FFCs only take arguments // in decimal, so you'll have to convert. //D2: Width of the trigger hitbox //D3: Height of the trigger hitbox //D4: Set this to a number 1-17 to make the cutscene only play once. By giving FFCs different D4 arguments, // you can have multiple triggers for different permanent cutscenes on a screen. //D5: If you want the trigger to check for a flag under Link, set this to the number of the flag. // If you want it check for a flag just being on the screen, set to the flag + 1000 // If you want it to check for an item, set this to a negative Item ID. // If you want it to check for not having an item, set to the negative Item ID - 1000 //D6: The X position to try to walk Link to. 0 for no target point. //D7: The Y position to try to walk Link to. 0 for no target point. //A. Delay: Set to >0 if you can activate this trigger immediately even when entering the screen on top of it ffc script CutsceneTrigger{ void run(int newDMap, int newScreen, int w, int h, int oneUse, int checkItemorFlag, int targetX, int targetY){ int dbit; if(oneUse>0){ dbit = 1<<(oneUse-1); } if(this->Delay==0){ //If Link starts standing on the cutscene hitbox, wait for him to step off while(Link->X+8 >= this->X && Link->X+8 <= this->X+w-1 && Link->Y+12 >= this->Y && Link->Y+12 <= this->Y+h-1 && CanTriggerCutscene(checkItemorFlag)){ if(CUTSCENETRIGGER_SHOW_HITBOXES){ Screen->Rectangle(6, this->X-1, this->Y-1, this->X+w-1+1, this->Y+h-1+1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 64); Screen->Rectangle(6, this->X, this->Y, this->X+w-1, this->Y+h-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 128); Screen->Rectangle(6, this->X+1, this->Y+1, this->X+w-1-1, this->Y+h-1-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, true, 64); } Waitframe(); } } //Check if the cutscene has already been triggered if(oneUse&&Screen->D[D_CUTSCENETRIGGER]&dbit){ Quit(); } while(true){ int c = C_CUTSCENETRIGGER_HITBOX; if(!CanTriggerCutscene(checkItemorFlag)) c = C_CUTSCENETRIGGER_HITBOX_INACTIVE; if(CUTSCENETRIGGER_SHOW_HITBOXES){ Screen->Rectangle(6, this->X-1, this->Y-1, this->X+w-1+1, this->Y+h-1+1, c, 1, 0, 0, 0, false, 64); Screen->Rectangle(6, this->X, this->Y, this->X+w-1, this->Y+h-1, c, 1, 0, 0, 0, false, 128); Screen->Rectangle(6, this->X+1, this->Y+1, this->X+w-1-1, this->Y+h-1-1, c, 1, 0, 0, 0, false, 64); } //Find if Link has collided with the trigger hitbox if(Link->X+8 >= this->X && Link->X+8 <= this->X+w-1 && Link->Y+12 >= this->Y && Link->Y+12 <= this->Y+h-1 ){ if(CUTSCENETRIGGER_SHOW_HITBOXES){ Screen->Rectangle(6, this->X+2, this->Y+2, this->X+w-1-2, this->Y+h-1-2, c, 1, 0, 0, 0, true, 64); } //If Link meets one the requirements to trigger the cutscene, break out of the loop if(CanTriggerCutscene(checkItemorFlag)) break; } Waitframe(); } if(targetX>0||targetY>0){ //Move Link either until he's in position or 4 seconds have passed for(int i=0; i<=240&&(Link->X!=targetX||Link->Y!=targetY); i++){ //Prevent moving around while moving Link into position Link->InputStart = false; Link->PressStart = false; Link->InputMap = false; Link->PressMap = false; NoAction(); //Apply inputs that should be active if(Abs(Link->X-targetX)<=2){ Link->X = targetX; } else{ if(Link->X<targetX) Link->InputRight = true; else if(Link->X>targetX) Link->InputLeft = true; } if(Abs(Link->Y-targetY)<=2){ Link->Y = targetY; } else{ if(Link->Y<targetY) Link->InputDown = true; else if(Link->Y>targetY) Link->InputUp = true; } Waitframe(); } } if(oneUse){ Screen->D[D_CUTSCENETRIGGER] |= dbit; } Link->PitWarp(newDMap, newScreen); } bool CanTriggerCutscene(int checkItemorFlag){ //If Link meets one the requirements to trigger the cutscene, return true if(checkItemorFlag==0){ return true; } //If the checkItemorFlag argument is negative, check for an item else if(checkItemorFlag<0){ if(checkItemorFlag<-1000){ checkItemorFlag += 1000; if(!Link->Item[Abs(checkItemorFlag)]) return true; } else{ if(Link->Item[Abs(checkItemorFlag)]) return true; } } //Else check for a screen flag else{ //If >1000, the trigger becomes active even if Link isn't standing on the flag if(checkItemorFlag>1000){ checkItemorFlag -= 1000; for(int i=0; i<176; ++i){ if(ComboFI(i, checkItemorFlag)) return true; } } //Otherwise check if Link is standing on the flag else{ if(ComboFI(Link->X+8, Link->Y+12, checkItemorFlag)) return true; } } return false; } } //It's dangerous to make unscripted cutscenes that give Link control while they're playing, take this! ffc script InputDisable{ void run(){ while(true){ Link->InputStart = false; Link->PressStart = false; Link->InputMap = false; Link->PressMap = false; NoAction(); Waitframe(); } } } //For playing sounds in cutscenes //D0: SFX to play //D1: Delay in frames ffc script PlaySoundWithDelay{ void run(int sfx, int delay){ Waitframes(delay); Game->PlaySound(sfx); } } //For playing messages in cutscenes //D0: Message string to play //D1: Delay in frames ffc script PlayMessageWithDelay{ void run(int msg, int delay){ Waitframes(delay); Screen->Message(msg); } } //Okay I probably don't really need all these little scripts, but in making non-scripted cutscenes I got a little nitpicky :P //D0: Direction to set Link to ffc script SetLinkDirection{ void run(int dir){ Link->Dir = dir; } }