//////////////////////////////////////// /// Specific item and Button Bubbles /// /// By: ZoriaRPG /// /// v0.6.7 /// /// 15th February, 2016 /// /// -------------------------------- ////////////////////////////////// /// The following ghosted enemies replicate bubbles, but instead of /// /// affecting all non-sword items, or all sword items, they jinx /// /// either specific items, or specific buttons. /// /////////////////////////////////////////////////////////////////////// /// Credits: /// /// ZoriaRPG: Button Bubble Concept, Script /// /// Moosh: Telling me to make it work with specific items. /// /// Some ghost.zh things. /// /// Lejes: Debugging/Testing /// /////////////////////////////////////////////////////////////////////// /////////////// /// Set-Up //////////////////////////////////////////////////////////////////////////////////// /// The following ghost attributes determine the item or button toaffect, and the jinxtime. /// /// --------------------------------------------------------------------------------------- /// /// ghost->Attributes[GHOST_BUBBLE_ITEM_ID] is the item to affect. /// /// ghost->Attributes[GHOST_BUBBLE_ITEM_TIMER] is the duration to affect the item. /// /// -1 for infinite. /// /// ghost->Attributes[GHOST_BUBBLE_BUTTON_ID] is the button to affect /// /// ghost->Attributes[GHOST_BUBBLE_BUTTON_TIMER] is the duration to jinx that button. /// /// -1 for infinite. /// /// ghost->Attributes[GHOST_BUBBLE_HALT] is the Halt argument for Ghost_HaltingWalk() /// /// Probably should be 10 to 45. /// /////////////////////////////////////////////////////////////////////////////////////////////// ////////////////// // Global Array // ////////////////// int Jinxes[555]; //Holds timers, and other values for jinxed items, and buttons. ///////////////////////////// // Ghosted Bubbles /// // Constants and Settings /// ///////////////////////////// //////////////// /// Settings /// //////////////// //! Set to '1' to enable, or '0' to disable. const int CLEAR_BUTTON_JINXES_ON_CONTINUE = 1; // Clears Button Jinxes on Death, or on F6 const int CLEAR_BUTTON_JINXES_ON_RELOAD = 1; // Clears Button Jinxes when resuming a // saved game from the game select screen. const int CLEAR_ITEM_JINXES_ON_CONTINUE = 1; // Clears Item Jinxes on Death, or on F6 const int CLEAR_ITEM_JINXES_ON_RELOAD = 1; // Clears Button Jinxes when resuming a // saved game from the game select screen. ///////////////////// // Array Constants // ///////////////////// // Global Array Indices const int JINXED_BUTTONS = 512; //Offset for Jinxed Button Timers //Ghost->Attributes[] Indices const int GHOST_BUBBLE_ITEM_ID = 0; const int GHOST_BUBBLE_ITEM_TIMER = 1; const int GHOST_BUBBLE_BUTTON_ID = 2; const int GHOST_BUBBLE_BUTTON_TIMER = 3; const int GHOST_BUBBLE_FLAG = 4; //Not used. What the flidd did I intend to do with this? Lock a bubble from walking on this flag? const int GHOST_BUBBLE_HALT = 5; //Bubble FFC Script Local Array ( bubblevars[] ) Indices const int GHOST_BUBBLE_ARR_ITM = 0; const int GHOST_BUBBLE_ARR_ITMDUR = 1; const int GHOST_BUBBLE_ARR_BTN = 2; const int GHOST_BUBBLE_ARR_BTNDUR = 3; const int GHOST_BUBBLE_COUNTER = 4; //Buttons const int JINX_BTN_A = 1; const int JINX_BTN_B = 2; const int JINX_BTN_L = 3; const int JINX_BTN_R = 4; const int JINX_BTN_UP = 5; const int JINX_BTN_DOWN = 6; const int JINX_BTN_LEFT = 7; const int JINX_BTN_RIGHT = 8; const int JINX_BTN_START = 9; const int JINX_BTN_MAP = 10; const int JINX_BTN_EX1 = 11; const int JINX_BTN_EX2 = 12; const int JINX_BTN_EX3 = 13; const int JINX_BTN_EX4 = 14; //Bubble->Attributes[] Values (for reference) const int GHOST_BUBBLE_INFINITE_DUR = -1; ///////////////////////////// /// FFC AutoGhost Scripts /// ///////////////////////////// //! Apply these to an enemy with the type 'Other' ffc script Bubbles{ void run(int enemID){ npc ghost = Ghost_InitAutoGhost(this, enemID); //Init the enemy, and set tis properties... Ghost_SetFlag(GHF_NORMAL); //Can be stunned, affected by clocks, has knockback. Ghost_SetFlag(GHF_FULL_TILE_MOVEMENT); //Will not move onto partially solid combos. Ghost_SetFlag(GHF_4WAY); //4-Way walking. int bubblevars[5]; //Array to hold variables. //Initialise array values using ghost properties. bubblevars[GHOST_BUBBLE_ARR_ITM] = ghost->Attributes[GHOST_BUBBLE_ITEM_ID]; bubblevars[GHOST_BUBBLE_ARR_ITMDUR] = ghost->Attributes[GHOST_BUBBLE_ITEM_TIMER]; bubblevars[GHOST_BUBBLE_ARR_BTN] = ghost->Attributes[GHOST_BUBBLE_BUTTON_ID]; bubblevars[GHOST_BUBBLE_ARR_BTNDUR] = ghost->Attributes[GHOST_BUBBLE_BUTTON_TIMER]; bubblevars[GHOST_BUBBLE_COUNTER] = -1; while(true){ if ( LinkCollision(ghost) && ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) ){ if ( bubblevars[GHOST_BUBBLE_ARR_ITM] && Link->Item[bubblevars[GHOST_BUBBLE_ARR_ITM]] && Jinxes[bubblevars[GHOST_BUBBLE_ARR_ITM]] != GHOST_BUBBLE_INFINITE_DUR ) { Jinxes[bubblevars[GHOST_BUBBLE_ARR_ITM]] = bubblevars[GHOST_BUBBLE_ARR_ITMDUR]; } if ( bubblevars[GHOST_BUBBLE_ARR_BTN] && Jinxes[bubblevars[GHOST_BUBBLE_ARR_BTNDUR]] != GHOST_BUBBLE_INFINITE_DUR ) { Jinxes[JINXED_BUTTONS+ bubblevars[GHOST_BUBBLE_ARR_BTN]] = bubblevars[GHOST_BUBBLE_ARR_BTNDUR]; } } bubblevars[GHOST_BUBBLE_COUNTER] = Ghost_HaltingWalk4(bubblevars[GHOST_BUBBLE_COUNTER], ghost->Step, ghost->Rate, ghost->Homing, ghost->Hunger, ghost->Haltrate, ghost->Attributes[GHOST_BUBBLE_HALT]); Ghost_Waitframe(this,ghost); } } } ffc script AntiBubbles{ void run(int enemID){ npc ghost = Ghost_InitAutoGhost(this, enemID); //Init the enemy, and set its properties... Ghost_SetFlag(GHF_NORMAL); //Can be stunned, affected by clocks, has knockback. Ghost_SetFlag(GHF_FULL_TILE_MOVEMENT); //Will not move onto partially solid combos. Ghost_SetFlag(GHF_4WAY); //4-Way walking. int bubblevars[5]; //Array to hold variables. //Initialise array values using ghost properties. bubblevars[GHOST_BUBBLE_ARR_ITM] = ghost->Attributes[GHOST_BUBBLE_ITEM_ID]; //bubblevars[GHOST_BUBBLE_ARR_ITMDUR] = ghost->Attributes[GHOST_BUBBLE_ITEM_TIMER]; bubblevars[GHOST_BUBBLE_ARR_BTN] = ghost->Attributes[GHOST_BUBBLE_BUTTON_ID]; //bubblevars[GHOST_BUBBLE_ARR_BTNDUR] = ghost->Attributes[GHOST_BUBBLE_BUTTON_TIMER]; bubblevars[GHOST_BUBBLE_COUNTER] = -1; while(true){ if ( LinkCollision(ghost) && ( Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ) ){ if ( bubblevars[GHOST_BUBBLE_ARR_ITM] && Jinxes[bubblevars[GHOST_BUBBLE_ARR_ITM]] ) { Jinxes[bubblevars[GHOST_BUBBLE_ARR_ITM]] = 0; } if ( bubblevars[GHOST_BUBBLE_ARR_BTN] && Jinxes[bubblevars[GHOST_BUBBLE_ARR_BTNDUR]] ) { Jinxes[JINXED_BUTTONS+ bubblevars[GHOST_BUBBLE_ARR_BTN]] = 0; } } bubblevars[GHOST_BUBBLE_COUNTER] = Ghost_HaltingWalk4(bubblevars[GHOST_BUBBLE_COUNTER], ghost->Step, ghost->Rate, ghost->Homing, ghost->Hunger, ghost->Haltrate, ghost->Attributes[GHOST_BUBBLE_HALT]); Ghost_Waitframe(this,ghost); } } } //////////////////////// /// Global Functions /// //////////////////////// //Main function to call before Waitdraw() as Jinxes(JinxedItems); void DoJinxes(int arr){ JinxedItems(arr); JinxedButtons(arr); ReduceJinxTimers(arr); } //Clears a jinx arbitrarily. void UnJinx(int itemOrButton){ Jinxes[itemOrButton] = 0; } //Clears all jinxes caused by the ghosted bubbles in this header. void ClearAllJinxes(int arr){ for ( int q = 0; q < SizeOfArray(arr); q++ ) arr[q] = 0; } //Clears all item jinxes caused by the ghosted bubbles in this header. void ClearItemJinxes(int arr){ for ( int q = 0; q < JINXED_BUTTONS; q++ ) arr[q] = 0; } //Clears all button jinxer caused by the ghosted bubbles in this header. void ClearButtonJinxes(int arr){ for ( int q = JINXED_BUTTONS; q < SizeOfArray(arr); q++ ) arr[q] = 0; } //! Functions called by Jinxes() // Halts inputs on A/B for jinxed items. void JinxedItems(int arr){ if ( Link->PressA && arr[Link->GetEquipmentA()] ) Link->PressA = false; if ( Link->PressB && arr[Link->GetEquipmentB()] ) Link->PressB = false; if ( Link->InputA && arr[Link->GetEquipmentA()] ) Link->InputA = false; if ( Link->InputB && arr[Link->GetEquipmentB()] ) Link->InputB = false; } // Halts inputs for jinxed buttons. void JinxedButtons(int arr){ if ( Link->PressA && arr[JINXED_BUTTONS + JINX_BTN_A] ) Link->PressA = false; if ( Link->PressB && arr[JINXED_BUTTONS + JINX_BTN_B] ) Link->PressB = false; if ( Link->InputA && arr[JINXED_BUTTONS + JINX_BTN_A] ) Link->InputA = false; if ( Link->InputB && arr[JINXED_BUTTONS + JINX_BTN_B] ) Link->InputB = false; if ( Link->PressL && arr[JINXED_BUTTONS + JINX_BTN_L] ) Link->PressL = false; if ( Link->PressR && arr[JINXED_BUTTONS + JINX_BTN_R] ) Link->PressR = false; if ( Link->InputL && arr[JINXED_BUTTONS + JINX_BTN_L] ) Link->InputL = false; if ( Link->InputR && arr[JINXED_BUTTONS + JINX_BTN_R] ) Link->InputR = false; if ( Link->PressUp && arr[JINXED_BUTTONS + JINX_BTN_UP] ) Link->PressUp = false; if ( Link->PressDown && arr[JINXED_BUTTONS + JINX_BTN_DOWN] ) Link->PressDown = false; if ( Link->InputUp && arr[JINXED_BUTTONS + JINX_BTN_UP] ) Link->InputUp = false; if ( Link->InputDown && arr[JINXED_BUTTONS + JINX_BTN_DOWN ] ) Link->InputDown = false; if ( Link->PressLeft && arr[JINXED_BUTTONS + JINX_BTN_LEFT] ) Link->PressLeft = false; if ( Link->PressRight && arr[JINXED_BUTTONS + JINX_BTN_RIGHT] ) Link->PressRight = false; if ( Link->InputLeft && arr[JINXED_BUTTONS + JINX_BTN_LEFT] ) Link->InputLeft = false; if ( Link->InputRight && arr[JINXED_BUTTONS + JINX_BTN_RIGHT] ) Link->InputRight = false; if ( Link->PressStart && arr[JINXED_BUTTONS + JINX_BTN_START] ) Link->PressStart = false; if ( Link->PressMap && arr[JINXED_BUTTONS + JINX_BTN_MAP] ) Link->PressMap = false; if ( Link->InputStart && arr[JINXED_BUTTONS + JINX_BTN_START] ) Link->InputStart = false; if ( Link->InputMap && arr[JINXED_BUTTONS + JINX_BTN_MAP] ) Link->InputMap = false; if ( Link->PressEx1 && arr[JINXED_BUTTONS + JINX_BTN_EX1] ) Link->PressEx1 = false; if ( Link->PressEx2 && arr[JINXED_BUTTONS + JINX_BTN_EX2] ) Link->PressEx2 = false; if ( Link->InputEx1 && arr[JINXED_BUTTONS + JINX_BTN_EX1] ) Link->InputEx1 = false; if ( Link->InputEx2 && arr[JINXED_BUTTONS + JINX_BTN_EX2] ) Link->InputEx2 = false; if ( Link->PressEx3 && arr[JINXED_BUTTONS + JINX_BTN_EX3] ) Link->PressEx3 = false; if ( Link->PressEx4 && arr[JINXED_BUTTONS + JINX_BTN_EX4] ) Link->PressEx4 = false; if ( Link->InputEx3 && arr[JINXED_BUTTONS + JINX_BTN_EX3] ) Link->InputEx3 = false; if ( Link->InputEx4 && arr[JINXED_BUTTONS + JINX_BTN_EX4] ) Link->InputEx4 = false; } //Reduces timers in the main array by one, each frame. void ReduceJinxTimers(int arr){ for ( int q = 0; q < SizeOfArray(arr); q++ ) { if ( arr[q] > 0 ) arr[q]--; } } ////////////////////////////// /// Example Global Scripts /// ////////////////////////////// global script active{ void run(){ StartGhostZH(); if ( CLEAR_BUTTON_JINXES_ON_CONTINUE ) ClearButtonJinxes(Jinxes); if ( CLEAR_ITEM_JINXES_ON_CONTINUE ) ClearItemJinxes(Jinxes); while(true){ DoJinxes(Jinxes); UpdateGhostZH1();//! Enable if using ghost.zh Waitdraw(); UpdateGhostZH2(); //! Enable if using ghost.zh Waitframe(); } } } global script OnContinue{ void run(){ if ( CLEAR_BUTTON_JINXES_ON_RELOAD ) ClearButtonJinxes(Jinxes); if ( CLEAR_ITEM_JINXES_ON_RELOAD ) ClearItemJinxes(Jinxes); } } //////////////////// /// Item Scripts ///////////////////////////////////////////////// /// Apply these as item scripts for potions, to clear jinxes. /// /// If you already have itemscripts for your potions, call the /// /// global functions ClearItemJinxes() and ClearButtonJinxes() /// /// firectly in those scripts. /// ////////////////////////////////////////////////////////////////// //Clears all Item-Specific and Button Jinxes caused by these ghosted bubbles. item script ItemAndButtonJinxPotion{ void run(){ for ( int q = 0; q < SizeOfArray(Jinxes); q++ ) arr[q] = 0; } } //Clears Item Jinxes, but not Button Jinxes caused by these ghosted bubbles. item script ItemJinxPotion{ void run(){ for ( int q = 0; q < JINXED_BUTTONS; q++ ) arr[q] = 0; } } //Clears Button Jinxes, but not Item Jinxes caused by these ghosted bubbles. item script ButtonJinxPotion{ void run(){ for ( int q = JINXED_BUTTONS; q < SizeOfArray(Jinxes); q++ ) arr[q] = 0; } } ///----==----\\\ //! Deprecated !\\ //----------------\\ //const int BUBBLE_COUNTERS = 768; //int GetBubbleCounter(int arr){ // for ( int q = 768; q < SizeOfArray(arr); q++ ) { // if ( !arr[q] ) return q; // } // return -1; //! DCdprecated by using other attribs for item and button, instead of this. //Bubble->Attributes[] Values (for reference) //const int GHOST_BUBBLE_AFFECT_NONE = 0; //const int GHOST_BUBBLE_AFFECT_ITEM = 1; //const int GHOST_BUBBLE_AFFECT_BUTTON = 2; //const int GHOST_BUBBLE_AFFECT_BOTH = 3; //const int GHOST_BUBBLE_INFINITE_DUR = -1;