/// Metroid Save Point and Warp System /// v0.8.0 /// 25-JULY-2016 /// By: ZoriaRPG //Usage Constants - ! Do not change ! const int BUTTON_A = 0; const int BUTTON_B = 1; const int BUTTON_L = 2; const int BUTTON_R = 3; const int BUTTON_EX1 = 4; const int BUTTON_EX2 = 5; const int BUTTON_EX3 = 6; const int BUTTON_EX4 = 7; const int BUTTON_START = 8; const int BUTTON_MAP = 9; //!Indices 0-5 are not used to store coordinates const int MET_SAVE_LAST_SAVESTATION = 0; //ID of last save station used. arr[0] const int ISWARPING = 1; //arr[1] : Used by accessors const int FLASHINGGREEN = 2; //arr[2] : ... const int TELEPORTING = 3; //arr[3] : ... const int ARRIVING = 4; //arr[4] : ... //Because we number stations starting at '1', array indices arr[5] through arr[10] are unused. const int MET_SAVE_BASE = 5; // First index of save point values. //! In reality, it is this, plus six, because we start Warp Station IDs at '1'. const int MET_SAVE_INDICES = 6; //Math. Indices used per set o hold warp station datum. const int MET_SAVE_ID = 0; //Holds the ID of the point in game. const int MET_SAVE_DMAP = 1; //The DMAP for a given warp. const int MET_SAVE_SCREEN = 2; //The screen of a given warp. const int MET_SAVE_X = 3; //The X position to warp to. const int MET_SAVE_Y = 4; //The Y position to warp to. const int MET_SAVE_STATION_ACTIVE = 5; //The Y position to warp to. //////////////// /// Settings /// //////////////// const int DEBUG_MENUS = 1; //Set to 1 to enable debugging. 0 to disable. const int SFX_ERROR = 0; //Set to generic error sound. const int MET_SAVE_NUMBER_OF_SAVEPOINTS = 20; //Activation Buttons const int MET_SAVE_USE_BUTTON_A = 0; const int MET_SAVE_USE_BUTTON_B = 0; const int MET_SAVE_USE_BUTTON_L = 0; const int MET_SAVE_USE_BUTTON_R = 0; const int MET_SAVE_USE_BUTTON_EX1 = 0; const int MET_SAVE_USE_BUTTON_EX2 = 1; const int MET_SAVE_USE_BUTTON_EX3 = 0; const int MET_SAVE_USE_BUTTON_EX4 = 1; const int MET_SAVE_USE_BUTTON_START = 1; const int MET_SAVE_USE_BUTTON_MAP = 0; //Settings const int MET_WARP_EFFECT_DURATION = 60; //Duration of warp special visuals. int MetroidWarps[214747]; const int MET_SAVE_STATION_REG = 9; //Screen->D[reg] const int MET_SAVE_STATION_DRAW_ID_FONT = 0; const int MET_SAVE_STATION_DRAW_ID_FONT_LAYER = 2; const int MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_COLOUR = 0x0F; //Black const int MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_COLOUR = 0x01; //White const int MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_Y_SCALE = -1; //DrawString(0 scale factor const int MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_X_OFFSET = 8; //Offset from f->X const int MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_X_OFFSET = 9; //Offset from f->X const int MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_Y_OFFSET = 8; //Offset from f->Y const int MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_Y_OFFSET = 9; //Offset from f->Y const int MET_SAVE_STATION_ = 0; //Default constant template for this beast. const int MET_SAVE_STATION_DRAW_ID_FONT_WIDTH = 16; const int MET_SAVE_STATION_DRAW_ID_FONT_HEIGHT = 16; const int SFX_SAVE_ERROR = 80; // const int SFX_SAVE_SUCCESS = 7; // const int SFX_TELEPORT_TRANSITION = 37; //Sound effect of teleportation EFFECT. const int SFX_WARP_ERROR = 80; const int SFX_TELEPORT = 67; //Sound effect for teleportation matrix item. //const int WARP_WAVE = 30; const int TELEPORT_CIRCLE_COLOUR = 181; //Colour for teleport circle. const int TELEPORT_WAVE = 60; //Duration of Teleport Wave Effect //! We'll remove this in a future edit. const int SFX_SET_TELEPORT = 21; //Menu Sound for Setting Teleport Destination //const int FLASH_LAYER = 6; //const int TELEPORT_OVERLAY = 5; //const int TELEPORT_SAFETY = 10; //const int WARP_DURATION = 80; //Drawing Colours - ! Set to colours in your palette, or adjust as you see fit. const int WARP_GREEN = 45; const int WARP_BLUE = 11; const int WARP_YELLOW = 126; const int WARP_TEAL = 88; const int WARP_LTBLUE = 93; //or 88 const int WARP_LTGREEN = 44; const int WARP_BRIGHTGREEN = 47; const int WARP_PERIDOT = 97; const int WARP_SMOKE = 73; //Accessors bool SamusIsWarping(){ return (MetroidWarps[ISWARPING] != 0); } bool FlashingGreen(){ return (MetroidWarps[FLASHINGGREEN] != 0); } bool SamusTeleporting(){ return (MetroidWarps[TELEPORTING] != 0); } bool SamusArriving(){ return (MetroidWarps[ARRIVING] != 0); } void SamusWarping(bool state){ if ( state ) MetroidWarps[ISWARPING] = 1; else MetroidWarps[ISWARPING] = 0;} void FlashingGreen(bool state){ if ( state ) MetroidWarps[FLASHINGGREEN] = 1; else MetroidWarps[FLASHINGGREEN] = 0;} void SamusTeleporting(bool state){ if ( state ) MetroidWarps[TELEPORTING] = 1; else MetroidWarps[TELEPORTING] = 0;} void SamusArriving(bool state){ if ( state ) MetroidWarps[ARRIVING] = 1; else MetroidWarps[ARRIVING] = 0;} //Returns if samus can teleport, or activate a save point station. bool SamusCanTeleport(){ return ( !jumping && !onLadder && ( SamusAction == SAMUS_ACTION_NONE || SamusAction == SAMUS_ACTION_CROUCH ) && !isShineSpark && OnGround() && !isSpeedBoosting && !SamusHasDied ); } //We do this when we activate the station. void SetWarpPoint(int warp_id, ffc f){ MetroidWarps[MET_SAVE_BASE + MET_SAVE_ID + ( warp_id * MET_SAVE_INDICES ) ] = warp_id; MetroidWarps[MET_SAVE_BASE + MET_SAVE_DMAP + ( warp_id * MET_SAVE_INDICES ) ] = Game->GetCurDMap(); MetroidWarps[MET_SAVE_BASE + MET_SAVE_SCREEN + ( warp_id * MET_SAVE_INDICES ) ] = Game->GetCurScreen(); MetroidWarps[MET_SAVE_BASE + MET_SAVE_X + ( warp_id * MET_SAVE_INDICES ) ] = f->X; MetroidWarps[MET_SAVE_BASE + MET_SAVE_Y + ( warp_id * MET_SAVE_INDICES ) ] = f->Y; } //A way to set the point based on Samus coordinates, instead of ffc coordinates, if needed. void SetWarpPoint(int warp_id){ MetroidWarps[MET_SAVE_BASE + MET_SAVE_ID + ( warp_id * MET_SAVE_INDICES ) ] = warp_id; MetroidWarps[MET_SAVE_BASE + MET_SAVE_DMAP + ( warp_id * MET_SAVE_INDICES ) ] = Game->GetCurDMap(); MetroidWarps[MET_SAVE_BASE + MET_SAVE_SCREEN + ( warp_id * MET_SAVE_INDICES ) ] = Game->GetCurScreen(); MetroidWarps[MET_SAVE_BASE + MET_SAVE_X + ( warp_id * MET_SAVE_INDICES ) ] = Link->X; MetroidWarps[MET_SAVE_BASE + MET_SAVE_Y + ( warp_id * MET_SAVE_INDICES ) ] = Link->Y; } //Checks if a given station is active. int WarpPointActive(int station_id) { return MetroidWarps[MET_SAVE_BASE + MET_SAVE_STATION_ACTIVE + ( station_id * MET_SAVE_INDICES )]; } //Sets a given warp point active/inactive. void WarpPointActive(int station_id, bool setting) { if ( setting ) MetroidWarps[MET_SAVE_BASE + MET_SAVE_STATION_ACTIVE + ( station_id * MET_SAVE_INDICES )] = 1; else MetroidWarps[MET_SAVE_BASE + MET_SAVE_STATION_ACTIVE + ( station_id * MET_SAVE_INDICES )] = 0; } //Saving the game automation. void SaveGame(int station_id){ SetGameRestoreStation(station_id); /// Game->Save(); } //Save and quit automation. void SaveGameAndQuit(int station_id){ SetGameRestoreStation(station_id); Game->Save(); Game->End(); } //Sets the station that we'll load when the player reloads the game. void SetGameRestoreStation(int station_id){ MetroidWarps[MET_SAVE_LAST_SAVESTATION] = station_id; } //Gets the station to use as a restore point, on player death, or onContinue. int GetGameRestoreStation(){ return MetroidWarps[MET_SAVE_LAST_SAVESTATION]; } //Call during onContinue script, or on death. void RestoreGame(){ //if the game has been saved, then we have a restore station set if ( GetGameRestoreStation() ) { WarpSamus( GetGameRestoreStation(), MET_WARP_EFFECT_DURATION ); } } // Tango Functions // There are certainly other ways to handle these... // Vars used by the Tango menu. int menuCommand; int menuArg; //Tango Menu Init void SetUpWindow(int slot, int style, int x, int y, int size) { SetStyleSize(style, size); Tango_ClearSlot(slot); Tango_SetSlotStyle(slot, style); Tango_SetSlotPosition(slot, x, y); } //Quick way to drop a string into a Tango dialogue box. void ShowString(int string, int slot, int style, int x, int y) { SetUpWindow(slot, style, x, y, SIZE_LARGE); Tango_LoadString(slot, string); Tango_ActivateSlot(slot); while(Tango_SlotIsActive(slot)) Waitframe(); } //ffc script WarpSamus{ // void run(int station_id){ // bool running; //This may not work via an ffc. Didn't we go down this road before? // } //} const int I_ZSUIT = 255; //If of Z Suit item, if desired. This should be a dummy, passive item. //Special suit upgrade to warp anytime. //Call in global active script, before Waitfdraw() as : // if ( Link->Item[I_ZSUIT] ) MetroidZSuit(BUTTON1,BUTTON2); int MetroidZSuit(int button1, int button2){ if ( button1 == button2 ) { int err[]="Report: MetroidXSuit buttons are both bound to the same input!"; TraceNL(); TraceS(err); TraceNL(); return 0; } int pressed[3]; //button 1, button2, button 3 if ( button1 == BUTTON_A && ( Link->PressA || Link->InputA ) ) pressed[0] = 1; if ( button1 == BUTTON_B && ( Link->PressB || Link->InputB ) ) pressed[0] = 1; if ( button1 == BUTTON_L && ( Link->PressL || Link->InputL ) ) pressed[0] = 1; if ( button1 == BUTTON_R && ( Link->PressR || Link->InputR ) ) pressed[0] = 1; if ( button1 == BUTTON_EX1 && ( Link->PressEx1 || Link->InputEx1 ) ) pressed[0] = 1; if ( button1 == BUTTON_EX2 && ( Link->PressEx2 || Link->InputEx2 ) ) pressed[0] = 1; if ( button1 == BUTTON_EX3 && ( Link->PressEx3 || Link->InputEx3 ) ) pressed[0] = 1; if ( button1 == BUTTON_EX4 && ( Link->PressEx4 || Link->InputEx4 ) ) pressed[0] = 1; if ( button2 == BUTTON_A && ( Link->PressA || Link->InputA ) ) pressed[1] = 1; if ( button2 == BUTTON_B && ( Link->PressB || Link->InputB ) ) pressed[1] = 1; if ( button2 == BUTTON_L && ( Link->PressL || Link->InputL ) ) pressed[1] = 1; if ( button2 == BUTTON_R && ( Link->PressR || Link->InputR ) ) pressed[1] = 1; if ( button2 == BUTTON_EX1 && ( Link->PressEx1 || Link->InputEx1 ) ) pressed[1] = 1; if ( button2 == BUTTON_EX2 && ( Link->PressEx2 || Link->InputEx2 ) ) pressed[1] = 1; if ( button2 == BUTTON_EX3 && ( Link->PressEx3 || Link->InputEx3 ) ) pressed[1] = 1; if ( button2 == BUTTON_EX4 && ( Link->PressEx4 || Link->InputEx4 ) ) pressed[1] = 1; if ( pressed[0] && pressed[1] && SamusCanTeleport() ) { pressed[2] = 1; int f[]="FFC_Z_Suit"; int ff = Game->GetFFCScript(f); RunFFCScript(f,NULL); //WarpMenu(); return 1; } } ffc script FFC_Z_Suit{ void run(){ //Tango menu from Warp menu int lineBreak[]="@26"; //Three springs per destination pair. We'll check if they are active, and only display those that are actie. int line1_both[]="@choice(1)Go 1@tab(56)@choice(2)Go 2@26"; int line1_first[]="@choice(1)Go 1@26"; int line1_second[]=" @tab(56)@choice(2)Go 2@26"; int line2_both[]="@choice(3)Go 3@tab(56)@choice(4)Go 4@26"; int line2_first[]="@choice(3)Go 3@26"; int line2_second[]=" @tab(56)@choice(4)Go 4@26"; int line3_both[]="@choice(5)Go 5@tab(56)@choice(6)Go 6@26"; int line3_first[]="@choice(5)Go 5@26"; int line3_second[]=" @tab(56)@choice(6)Go 6@26"; int line4_both[]="@choice(7)Go 7@tab(56)@choice(8)Go 8@26"; int line4_first[]="@choice(7)Go 7@26"; int line4_second[]=" @tab(56)@choice(8)Go 8@26"; int line5_both[]="@choice(9)Go 9@tab(56)@choice(10)Go 10@26"; int line5_first[]="@choice(9)Go 9@26"; int line5_second[]=" @tab(56)@choice(10)Go 10@26"; int initmenu[]="@domenu(1)@suspend()"; //We can change '10' to cancel if needed. SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_3, 32, 32, SIZE_LARGE); if ( WarpPointActive(1) && WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_1, line1_both); if ( WarpPointActive(1) && !WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_1, line1_first); if ( !WarpPointActive(1) && WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_1, line1_second); if ( WarpPointActive(3) && WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_1, line2_both); if ( WarpPointActive(3) && !WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_1, line2_first); if ( WarpPointActive(3) && WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_1, line2_second); if ( WarpPointActive(5) && WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_1, line3_both); if ( WarpPointActive(5) && !WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_1, line3_first); if ( WarpPointActive(5) && WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_1, line3_second); if ( WarpPointActive(7) && WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_1, line4_both); if ( WarpPointActive(7) && !WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_1, line4_first); if ( WarpPointActive(7) && WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_1, line4_second); if ( WarpPointActive(9) && WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_1, line5_both); if ( WarpPointActive(9) && !WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_1, line5_first); if ( WarpPointActive(9) && WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_1, line5_second); Tango_AppendString(WINDOW_SLOT_1, initmenu); Tango_ActivateSlot(WINDOW_SLOT_1); while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state again... int slotState[278]; int menuState[960]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_1, slotState); Tango_SaveMenuState(menuState); int done = 0; int choice; while(true){ while( Tango_MenuIsActive() ) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice = Tango_GetLastMenuChoice(); if ( choice ) { Tango_ClearSlot(WINDOW_SLOT_1); done = choice * -1; } if ( done ) { break; // return choice; } else { Tango_RestoreSlotState(WINDOW_SLOT_1, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } Waitframe(); } Tango_ClearSlot(WINDOW_SLOT_1); if ( DEBUG_MENUS ) DebugWarpChoice(done); WarpSamus( (choice * -1), MET_WARP_EFFECT_DURATION ); } } //! The physical save station. //! D0 : Each station needs a unique ID, ranging from 1 to 10. //! The script is set up to allow up to a total of ten save stations using the menus. ffc script MetroidSaveStation{ void run(int station_number, int refill){ bool pressed; int choice; while ( true ) { //If this station is active... //Draw station ID. if ( WarpPointActive(station_number) && station_number ) { //Draw the station ID, firstthe background Screen->DrawInteger( MET_SAVE_STATION_DRAW_ID_FONT_LAYER, this->X + MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_X_OFFSET, this->Y + MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_Y_OFFSET, MET_SAVE_STATION_DRAW_ID_FONT, MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_COLOUR, 0, MET_SAVE_STATION_DRAW_ID_FONT_WIDTH, MET_SAVE_STATION_DRAW_ID_FONT_HEIGHT, station_number, 0, OP_OPAQUE); //Then, the foreground... Screen->DrawInteger( MET_SAVE_STATION_DRAW_ID_FONT_LAYER, this->X + MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_X_OFFSET, this->Y + MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_Y_OFFSET, MET_SAVE_STATION_DRAW_ID_FONT, MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_COLOUR, 0, MET_SAVE_STATION_DRAW_ID_FONT_WIDTH, MET_SAVE_STATION_DRAW_ID_FONT_HEIGHT, station_number, 0, OP_OPAQUE); } //|| ( !Tango_MenuIsActive() && SamusCanTeleport() ) while ( ( !pressed && !Tango_MenuIsActive() ) ) { if ( DistX(this, 16) && DistY(this, 32) && SamusCanTeleport() ) { if ( MET_SAVE_USE_BUTTON_R && Link->PressR ) { pressed = true; Link->PressR = false; Link->InputR = false; } if ( MET_SAVE_USE_BUTTON_L && Link->PressL ) { pressed = true; Link->PressL = false; Link->InputL = false; } if ( MET_SAVE_USE_BUTTON_A && Link->PressA ) { pressed = true; Link->PressA = false; Link->InputA = false; } if ( MET_SAVE_USE_BUTTON_B && Link->PressB ) { pressed = true; Link->PressB = false; Link->InputB = false; } if ( MET_SAVE_USE_BUTTON_EX1 && Link->PressEx1 ) { pressed = true; Link->PressEx1 = false; Link->InputEx1 = false; } if ( MET_SAVE_USE_BUTTON_EX2 && Link->PressEx2 ) { pressed = true; Link->PressEx2 = false; Link->InputEx2 = false; } if ( MET_SAVE_USE_BUTTON_EX3 && Link->PressEx3 ) { pressed = true; Link->PressEx3 = false; Link->InputEx3 = false; } if ( MET_SAVE_USE_BUTTON_EX4 && Link->PressEx4 ) { pressed = true; Link->PressEx4 = false; Link->InputEx4 = false; } if ( MET_SAVE_USE_BUTTON_START && Link->PressStart ) { pressed = true; Link->PressStart = false; Link->InputStart = false; } if ( MET_SAVE_USE_BUTTON_MAP && Link->PressMap ) { pressed = true; Link->PressMap = false; Link->InputMap = false; } } //If this station is active... //Draw station ID. if ( WarpPointActive(station_number) && station_number ) { //Draw the station ID, firstthe background Screen->DrawInteger( MET_SAVE_STATION_DRAW_ID_FONT_LAYER, this->X + MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_X_OFFSET, this->Y + MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_Y_OFFSET, MET_SAVE_STATION_DRAW_ID_FONT, MET_SAVE_STATION_DRAW_ID_FONT_BACKGROUND_COLOUR, 0, MET_SAVE_STATION_DRAW_ID_FONT_WIDTH, MET_SAVE_STATION_DRAW_ID_FONT_HEIGHT, station_number, 0, OP_OPAQUE); //Then, the foreground... Screen->DrawInteger( MET_SAVE_STATION_DRAW_ID_FONT_LAYER, this->X + MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_X_OFFSET, this->Y + MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_Y_OFFSET, MET_SAVE_STATION_DRAW_ID_FONT, MET_SAVE_STATION_DRAW_ID_FONT_FOREGROUND_COLOUR, 0, MET_SAVE_STATION_DRAW_ID_FONT_WIDTH, MET_SAVE_STATION_DRAW_ID_FONT_HEIGHT, station_number, 0, OP_OPAQUE); } Waitframe(); } if ( pressed ) { pressed = false; //Set coordinates for this station: if ( station_number ) SetWarpPoint(station_number,this); //Activate this station if it is inactive if ( !WarpPointActive(station_number) && station_number ) WarpPointActive(station_number,true); //MetroidSaveStationMenu(int station_number); //Do menu if ( !station_number && !refill ) choice = MetroidSaveStationMenu(station_number,3); else choice = MetroidSaveStationMenu(station_number,refill); if ( choice < 0 && choice > -9999) WarpSamus( (choice * -1), MET_WARP_EFFECT_DURATION ); //Do save, activate, or warp when menu returns //!No, handled by the manu. } Waitframe(); //Main while loop. } } } void DebugMetroidSaveStationMenu(int val) { int t[]="MetroidSaveStationMenu() returned: "; TraceNL(); TraceS(t); Trace(val); TraceNL(); } void DebugRefill(int val){ int t[]="Refill is set to: "; TraceNL(); TraceS(t); Trace(val); TraceNL(); } void DebuggingMetroidSaveStation(){ int t[]="Debugging int MetroidSaveStationMenu(int station_id, int refill)"; TraceNL(); TraceS(t); TraceNL(); } //Menu called by the save station ffc. int MetroidSaveStationMenu(int station_id, int refill) { if ( DEBUG_MENUS ) { DebuggingMetroidSaveStation(); DebugRefill(refill); } int lineBreak[]="@26"; int line3[]="@choice(1)Save@26"; int line1[]="@choice(2)Warp@26"; int line2[]="@choice(5)Refill@26"; int line4[]="@choice(3)Save and Quit@26"; int line5[]="@choice(4)Cancel"; int initmenu[]="@domenu(1)@suspend()"; if ( station_id ) { SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_1, 32, 32, SIZE_LARGE); Tango_LoadString(WINDOW_SLOT_1, line1); if ( refill ) Tango_AppendString(WINDOW_SLOT_1, line2); Tango_AppendString(WINDOW_SLOT_1, line3); Tango_AppendString(WINDOW_SLOT_1, line4); Tango_AppendString(WINDOW_SLOT_1, line5); Tango_AppendString(WINDOW_SLOT_1, initmenu); Tango_ActivateSlot(WINDOW_SLOT_1); } else { //Refill station, only. Arg d1 will default to 3 in this case, if it is un-set. SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_1, 32, 32, SIZE_LARGE); Tango_LoadString(WINDOW_SLOT_1, line2); Tango_AppendString(WINDOW_SLOT_1, line5); Tango_AppendString(WINDOW_SLOT_1, initmenu); Tango_ActivateSlot(WINDOW_SLOT_1); } while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state again... int slotState[278]; int menuState[960]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_1, slotState); Tango_SaveMenuState(menuState); int done = 0; int choice; while(true){ while( Tango_MenuIsActive() ) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice = Tango_GetLastMenuChoice(); if ( choice == 1 ) { // Save the game SaveGame(station_id); Game->PlaySound(SFX_SAVE_SUCCESS); int text[]="Game Saved"; Tango_ClearSlot(2); ShowString(text, WINDOW_SLOT_2, WINDOW_STYLE_2, 48, 48); done = -9999; } else if ( choice == 2 ) { //Warp //! Run the warp menu. done = WarpMenu(); // done = choice; //menuArg = choice; } else if ( choice == 3 ) { //Save and quit Game->PlaySound(SFX_SAVE_SUCCESS); SaveGameAndQuit(station_id); done = choice; } else if ( choice == 4 ) {//cancel done = -9999; } else if ( choice == 5 ) { //refill RefillMenu(refill); done = -9999; } if ( done ) { break; // return choice; } else { Tango_RestoreSlotState(WINDOW_SLOT_1, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } } Tango_ClearSlot(WINDOW_SLOT_1); if ( DEBUG_MENUS ) DebugMetroidSaveStationMenu(done); return done; } //Populte these functions with instructions to refill stocks. void RefillMissiles() {}; void RefillHealth() {}; void DebuggingRefillMenu(){ int t[]="Debugging Refillmeny(int type)"; TraceNL(); TraceS(t); TraceNL(); } int RefillMenu(int type){ if ( DEBUG_MENUS ) { DebuggingRefillMenu(); DebugRefill(type); } int lineBreak[]="@26"; //Three springs per destination pair. We'll check if they are active, and only display those that are actie. int missiles[]="@choice(1)Refill Missiles@26"; int health[]="@choice(2)Refill Energy@26"; int both[]="@choice(3)Refill Both@26"; int initmenu[]="@domenu(1)@suspend()"; int restoredmissiles[]="Missile supply replenished."; int restoredhealth[]="Enery supply replenished."; int restoredboth[]="Energy and missile supplies replenished."; //We can change '10' to cancel if needed. SetUpWindow(WINDOW_SLOT_3, WINDOW_STYLE_1, 32, 32, SIZE_LARGE); //Missiles Only //ShowString(restoredmissiles, WINDOW_SLOT_4, WINDOW_STYLE_1, 48, 48); if ( type == 1 ) { Tango_LoadString(WINDOW_SLOT_3, missiles); Tango_AppendString(WINDOW_SLOT_3, initmenu); Tango_ActivateSlot(WINDOW_SLOT_3); } //Health only if ( type == 2 ) { Tango_LoadString(WINDOW_SLOT_3, health); Tango_AppendString(WINDOW_SLOT_3, initmenu); Tango_ActivateSlot(WINDOW_SLOT_3); } //Both if ( type == 3 ) { Tango_LoadString(WINDOW_SLOT_3, missiles); Tango_LoadString(WINDOW_SLOT_3, health); Tango_LoadString(WINDOW_SLOT_3, both); Tango_AppendString(WINDOW_SLOT_3, initmenu); Tango_ActivateSlot(WINDOW_SLOT_3); } while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state again... int slotState[278]; int menuState[960]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_3, slotState); Tango_SaveMenuState(menuState); int done = 0; int choice; while(true){ while( Tango_MenuIsActive() ) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice = Tango_GetLastMenuChoice(); if ( choice == 1 ) { //Refill missiles RefillMissiles(); ShowString(restoredmissiles, WINDOW_SLOT_4, WINDOW_STYLE_1, 48, 48); Tango_ClearSlot(WINDOW_SLOT_2); done = -99999; } if ( choice == 2 ) { //Refill missiles RefillHealth(); ShowString(restoredhealth, WINDOW_SLOT_4, WINDOW_STYLE_1, 48, 48); Tango_ClearSlot(WINDOW_SLOT_2); done = -99999; } if ( choice == 3 ) { //Refill both RefillMissiles(); RefillHealth(); ShowString(restoredboth, WINDOW_SLOT_4, WINDOW_STYLE_1, 48, 48); Tango_ClearSlot(WINDOW_SLOT_2); done = -99999; } if ( done ) { break; // return choice; } else { Tango_RestoreSlotState(WINDOW_SLOT_3, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } } Tango_ClearSlot(WINDOW_SLOT_3); return done; } //Warp menu, called by MetroidSaveStationMenu(), or by other functions/scripts. int WarpMenu(){ int lineBreak[]="@26"; //Three springs per destination pair. We'll check if they are active, and only display those that are actie. int line1_both[]="@choice(1)Go 1@tab(56)@choice(2)Go 2@26"; int line1_first[]="@choice(1)Go 1@26"; int line1_second[]=" @tab(56)@choice(2)Go 2@26"; int line2_both[]="@choice(3)Go 3@tab(56)@choice(4)Go 4@26"; int line2_first[]="@choice(3)Go 3@26"; int line2_second[]=" @tab(56)@choice(4)Go 4@26"; int line3_both[]="@choice(5)Go 5@tab(56)@choice(6)Go 6@26"; int line3_first[]="@choice(5)Go 5@26"; int line3_second[]=" @tab(56)@choice(6)Go 6@26"; int line4_both[]="@choice(7)Go 7@tab(56)@choice(8)Go 8@26"; int line4_first[]="@choice(7)Go 7@26"; int line4_second[]=" @tab(56)@choice(8)Go 8@26"; int line5_both[]="@choice(9)Go 9@tab(56)@choice(10)Go 10@26"; int line5_first[]="@choice(9)Go 9@26"; int line5_second[]=" @tab(56)@choice(10)Go 10@26"; int line6_both[]="@choice(11)Go 11@tab(56)@choice(12)Go 12@26"; int line6_first[]="@choice(11)Go 11@26"; int line6_second[]=" @tab(56)@choice(12)Go 12@26"; int line7_both[]="@choice(13)Go 13@tab(56)@choice(14)Go 14@26"; int line7_first[]="@choice(13)Go 13@26"; int line7_second[]=" @tab(56)@choice(14)Go 14@26"; int line8_both[]="@choice(15)Go 15@tab(56)@choice(16)Go 16@26"; int line8_first[]="@choice(15)Go 15@26"; int line8_second[]=" @tab(56)@choice(16)Go 16@26"; int line9_both[]="@choice(17)Go 17@tab(56)@choice(18)Go 18@26"; int line9_first[]="@choice(17)Go 17@26"; int line9_second[]=" @tab(56)@choice(18)Go 18@26"; int line10_both[]="@choice(19)Go 19@tab(56)@choice(20)Go 20@26"; int line10_first[]="@choice(19)Go 19@26"; int line10_second[]=" @tab(56)@choice(20)Go 20@26"; int initmenu[]="@domenu(1)@suspend()"; //We can change '10' to cancel if needed. SetUpWindow(WINDOW_SLOT_2, WINDOW_STYLE_3, 32, 32, SIZE_LARGE); if ( WarpPointActive(1) && WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_2, line1_both); if ( WarpPointActive(1) && !WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_2, line1_first); if ( !WarpPointActive(1) && WarpPointActive(2) ) Tango_LoadString(WINDOW_SLOT_2, line1_second); if ( WarpPointActive(3) && WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_2, line2_both); if ( WarpPointActive(3) && !WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_2, line2_first); if ( WarpPointActive(3) && WarpPointActive(4) ) Tango_AppendString(WINDOW_SLOT_2, line2_second); if ( WarpPointActive(5) && WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_2, line3_both); if ( WarpPointActive(5) && !WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_2, line3_first); if ( WarpPointActive(5) && WarpPointActive(6) ) Tango_AppendString(WINDOW_SLOT_2, line3_second); if ( WarpPointActive(7) && WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_2, line4_both); if ( WarpPointActive(7) && !WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_2, line4_first); if ( WarpPointActive(7) && WarpPointActive(8) ) Tango_AppendString(WINDOW_SLOT_2, line4_second); if ( WarpPointActive(9) && WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_2, line5_both); if ( WarpPointActive(9) && !WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_2, line5_first); if ( WarpPointActive(9) && WarpPointActive(10) ) Tango_AppendString(WINDOW_SLOT_2, line5_second); if ( WarpPointActive(11) && WarpPointActive(12) ) Tango_AppendString(WINDOW_SLOT_2, line6_both); if ( WarpPointActive(11) && !WarpPointActive(12) ) Tango_AppendString(WINDOW_SLOT_2, line6_first); if ( WarpPointActive(11) && WarpPointActive(12) ) Tango_AppendString(WINDOW_SLOT_2, line6_second); if ( WarpPointActive(13) && WarpPointActive(14) ) Tango_AppendString(WINDOW_SLOT_2, line7_both); if ( WarpPointActive(13) && !WarpPointActive(14) ) Tango_AppendString(WINDOW_SLOT_2, line7_first); if ( WarpPointActive(13) && WarpPointActive(14) ) Tango_AppendString(WINDOW_SLOT_2, line7_second); if ( WarpPointActive(15) && WarpPointActive(16) ) Tango_AppendString(WINDOW_SLOT_2, line8_both); if ( WarpPointActive(15) && !WarpPointActive(16) ) Tango_AppendString(WINDOW_SLOT_2, line8_first); if ( WarpPointActive(15) && WarpPointActive(16) ) Tango_AppendString(WINDOW_SLOT_2, line8_second); if ( WarpPointActive(17) && WarpPointActive(18) ) Tango_AppendString(WINDOW_SLOT_2, line9_both); if ( WarpPointActive(17) && !WarpPointActive(18) ) Tango_AppendString(WINDOW_SLOT_2, line9_first); if ( WarpPointActive(17) && WarpPointActive(18) ) Tango_AppendString(WINDOW_SLOT_2, line9_second); if ( WarpPointActive(19) && WarpPointActive(20) ) Tango_AppendString(WINDOW_SLOT_2, line10_both); if ( WarpPointActive(19) && !WarpPointActive(20) ) Tango_AppendString(WINDOW_SLOT_2, line10_first); if ( WarpPointActive(19) && WarpPointActive(20) ) Tango_AppendString(WINDOW_SLOT_2, line10_second); Tango_AppendString(WINDOW_SLOT_2, initmenu); Tango_ActivateSlot(WINDOW_SLOT_2); while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state again... int slotState[278]; int menuState[960]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_2, slotState); Tango_SaveMenuState(menuState); int done = 0; int choice; while(true){ while( Tango_MenuIsActive() ) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice = Tango_GetLastMenuChoice(); if ( choice ) { Tango_ClearSlot(WINDOW_SLOT_2); done = choice * -1; } if ( done ) { break; // return choice; } else { Tango_RestoreSlotState(WINDOW_SLOT_2, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } } Tango_ClearSlot(WINDOW_SLOT_2); if ( DEBUG_MENUS ) DebugWarpChoice(done); return done; } void DebugWarpChoice(int val){ int t[]="WarpMenu() returned: "; TraceNL(); TraceS(t); Trace(val); TraceNL(); } //Does the warp animation, and the phsyical warp. void WarpSamus(int warp_id, int warpDuration) { int startHP = Link->HP; int goDMAP = MetroidWarps[MET_SAVE_BASE + MET_SAVE_DMAP + ( warp_id * MET_SAVE_INDICES )]; int goSCREEN = MetroidWarps[MET_SAVE_BASE + MET_SAVE_SCREEN + ( warp_id * MET_SAVE_INDICES )]; int goX = MetroidWarps[MET_SAVE_BASE + MET_SAVE_X + ( warp_id * MET_SAVE_INDICES )]; int goY = MetroidWarps[MET_SAVE_BASE + MET_SAVE_Y + ( warp_id * MET_SAVE_INDICES )]; if ( SamusCanTeleport() ) { Game->PlaySound(SFX_TELEPORT_TRANSITION); //freezeAction(); SamusTeleporting(true); SamusArriving(true); for(int i = warpDuration; i > 0; i--){ //Duration of song/effect. NoAction(); //Freeze Link //Game->PlaySound(SFX_TELEPORT_TRANSITION); //Create animation. Screen->Circle ( 6, Link->X+8, Link->Y+8, 20*i/warpDuration, WARP_TEAL, 1, 0, 0, 0, false, 100 ); FlashingGreen(false); do { for ( int j = 1; j > 0; j--){ ScreenToLayer(goDMAP, goSCREEN, 4, 75); Screen->Rectangle(5, 0, 0, 256, 172, WARP_GREEN, 1, 0, 0, 0, true, 25); Screen->Circle ( 6, Link->X+8, Link->Y+8, 20*i/warpDuration, 1, 1, 0, 0, 0, false, 100 ); FlashingGreen(true); Waitframe(); } } while(SamusTeleporting() && !FlashingGreen()); do { for ( int j = 1; j > 0; j--){ ScreenToLayer(goDMAP, goSCREEN, 4, 80); Screen->Rectangle(5, 0, 0, 256, 172, WARP_LTGREEN, 1, 0, 0, 0, true, 10); Screen->Circle ( 6, Link->X+8, Link->Y+8, 20*i/warpDuration, WARP_TEAL, 1, 0, 0, 0, false, 100 ); FlashingGreen(false); Waitframe(); } } while(SamusTeleporting() && FlashingGreen()); if ( Link->HP < startHP ) { return; //If Link is hurt, quit } Waitframe(); } Screen->Wavy =60; Link->PitWarp( goDMAP, goSCREEN ); Link->X = goX; Link->Y = goY; SamusTeleporting(false); //unfreezeAction(); Waitframe(); SamusTeleporting(false); FlashingGreen(false); } else { Game->PlaySound(SFX_WARP_ERROR); SamusWarping(false); //NotEnoughMP(); //return; } } //! Not ready for use. item script TeleportationMatrix{ void run(int cost, int counter){ //int args[]={ //STATION ID }; int ff[]= "TeleportMenu"; int ffid = GetFFCScript(ff); if ( Game->Counter[counter] >= cost || !cost ) { if ( cost ) Game->Counter[counter] -= cost; //RunFFCScript(ffid, args); } else Game->PlaySound(SFX_ERROR); } } //! Do not use as-is. This is the base teleport menu from LoE ffc script TeleportMenu{ void run(int station_id){ //Three springs per destination pair. We'll check if they are active, and onyl display those tat are. int line1_both[]="@choice(1)Set 1@tab(56)@choice(7)Go 1@26"; int line1_first[]="@choice(1)Set 1@tab(56)@choice(7)Go 1@26"; int line1_second[]="@choice(1)Set 1@tab(56)@choice(7)Go 1@26"; int line2[]="@choice(2)Set 2@tab(56)@choice(8)Go 2@26"; int line3[]="@choice(3)Set 3@tab(56)@choice(9)Go 3@26"; int line4[]="@choice(4)Set 4@tab(56)@choice(10)Go 4@26"; int line5[]="@choice(5)Set 5@tab(56)@choice(11)Go 5@26"; int line6[]="@choice(6)Set 6@tab(56)@choice(12)Go 6@26"; int line8[]="@domenu(1)@suspend()"; SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_1, 16, 16, SIZE_LARGE); Tango_LoadString(WINDOW_SLOT_1, line2); //Tango_AppendString(WINDOW_SLOT_1, line1); //Tango_AppendString(WINDOW_SLOT_1, line2); Tango_AppendString(WINDOW_SLOT_1, line3); Tango_AppendString(WINDOW_SLOT_1, line4); Tango_AppendString(WINDOW_SLOT_1, line5); Tango_AppendString(WINDOW_SLOT_1, line6); // Tango_AppendString(WINDOW_SLOT_1, line7); Tango_AppendString(WINDOW_SLOT_1, line8); Tango_ActivateSlot(WINDOW_SLOT_1); while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state of the text slot and menu. The bitmap won't change, // so it doesn't need saved. int slotState[274]; int menuState[60]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_1, slotState); Tango_SaveMenuState(menuState); bool done=false; int choice; while(true) { if ( Link->PressEx1 ){ Quit(); } //if ( done == false && menuOpen == false ) { // menuOpen = true; //} //if ( done == true && menuOpen == true ){ // menuOpen = false; //} while(Tango_MenuIsActive()) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice=Tango_GetLastMenuChoice(); //if(choice==1) // Set Teleport One //{ // Trace(teleportSetOneCost); // if ( Link->MP >= teleportSetOneCost ) { // Link->MP -= teleportSetOneCost; // setTeleport(TEL_1); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==2) // Set Teleport Two // { // if ( Link->MP >= teleportSetOneCost ) { // Link->MP -= teleportSetOneCost; // setTeleport(TEL_2); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==3) // Set Teleport Three // { // if ( Link->MP >= teleportSetTwoCost ) { // Link->MP -= teleportSetTwoCost; // setTeleport(TEL_3); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==4){ // Set Teleport Four // if ( Link->MP >= teleportSetTwoCost ) { // Link->MP -= teleportSetTwoCost; // setTeleport(TEL_4); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==5) // Set Teleport Five // { // if ( Link->MP >= teleportSetThreeCost ) { // Link->MP -= teleportSetThreeCost; // setTeleport(TEL_5); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==6) // Set Teleport Six // { // if ( Link->MP >= teleportSetThreeCost ) { // Link->MP -= teleportSetThreeCost; // setTeleport(TEL_6); // Game->PlaySound(SFX_SET_TELEPORT); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==7) // GO Teleport One // { // Trace(teleportOneCost); // if ( Link->MP >= teleportOneCost ) { // Link->MP -= teleportOneCost; // ActivateTeleport(TEL_1,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==8) // GO Teleport Two // { // if ( Link->MP >= teleportOneCost ) { // Link->MP -= teleportOneCost; // ActivateTeleport(TEL_2,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==9) // GO Teleport Three // { // if ( Link->MP >= teleportTwoCost ) { // Link->MP -= teleportTwoCost; // ActivateTeleport(TEL_3,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==10) // GO Teleport Four // { // if ( Link->MP >= teleportTwoCost ) { // Link->MP -= teleportTwoCost; // ActivateTeleport(TEL_4,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // else if(choice==11) // GO Teleport Five // { // if ( Link->MP >= teleportThreeCost ) { // Link->MP -= teleportThreeCost; // ActivateTeleport(TEL_5,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // // else if(choice==12) // GO Teleport Six // { // if ( Link->MP >= teleportThreeCost ) { // Link->MP -= teleportThreeCost; // ActivateTeleport(TEL_6,TELEPORT_WAVE); // done=true; // } // else { // Game->PlaySound(SFX_WARP_ERROR); // NotEnoughMP(); // } // } // // else if (Link->PressEx1){ // // Quit(); // } // else{ // // done=true; // } // If we need to return to the top-level menu, // restore the state and loop again. if(done){ break; } else { Tango_RestoreSlotState(WINDOW_SLOT_1, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } } Tango_ClearSlot(WINDOW_SLOT_1); } } //Used if teleporting requires magic. Modify and use if desired. bool NotEnoughMP(){ int lineBreak[]="@26"; int menuEnd[]="@domenu(1)@suspend()"; int line2[]="You do not have enough MP to do that.@26"; int line1[]="@choice(1)Done@26@26"; SetUpWindow(WINDOW_SLOT_2, WINDOW_STYLE_2, 32, 32, SIZE_LARGE); Tango_LoadString(WINDOW_SLOT_2, line1); Tango_AppendString(WINDOW_SLOT_2, line2); Tango_AppendString(WINDOW_SLOT_2, menuEnd); Tango_ActivateSlot(WINDOW_SLOT_2); while(!Tango_MenuIsActive()){ Waitframe(); } // Save the state again... int slotState[274]; int menuState[60]; int cursorPos; Tango_SaveSlotState(WINDOW_SLOT_2, slotState); Tango_SaveMenuState(menuState); int done=0; int choice; while(true) { while(Tango_MenuIsActive()) { cursorPos=Tango_GetMenuCursorPosition(); Waitframe(); } choice=Tango_GetLastMenuChoice(); if(choice==0) // Canceled done=2; else if(choice == 1) { done=2; } else if (Link->PressEx1){ done = 2; } else done=2; if(done>0){ break; } else { Tango_RestoreSlotState(WINDOW_SLOT_2, slotState); Tango_RestoreMenuState(menuState); Tango_SetMenuCursorPosition(cursorPos); } } Tango_ClearSlot(WINDOW_SLOT_2); if(done==1) return true; // Tell parent menu to close else return false; // Tell parent not to close }