Copy to Clipboard Test

Z3-esque Keys (and Item Pickup) Code

import "std.zh"

//////////////////////
/// ItemHandling.zh //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// This is a global function set for handlinbg item interaction.                                           ///
/// The original author of this function set is grayswandir, who provided it to me, for use in TGC,         ///
/// and I use it for so many components, that in sharing other scriots, I may as well make it a header,     ///
/// to provide the functionality needed for many FFC scripts that I make available to others operable       ///
/// without duplicating these functions in every instance. I may expand on it at some future point.         ///
///                                                                                                         ///
/// Note: The pick-up is instantaneous, and does not need to wait for Link to touch the item.               ///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////
/// Global Constants ///
////////////////////////
 
const int MISC_LWEAPON_ITEM = 0; // The id of the item used to create an lweapon.
 
////////////////////////
/// Global Variables ///
////////////////////////
 
int LastItemUsed = 0; // The item id of the last item Link has used.
 
////////////////////////
/// Global Functions ///
////////////////////////
 
void UpdateLWeapons() {     //// Updates every LWeapon on screen. Call in the active script.
    for (int i = 1; i <= Screen->NumLWeapons(); i++) {
        UpdateLWeapon(Screen->LoadLWeapon(i));
    }
}
 

void UpdateLWeapon(lweapon lw) {    //// Update a given LWeapon.
// If the weapon does not have it's source item marked, mark it as being created by the last item that Link has used.
    if (lw->Misc[MISC_LWEAPON_ITEM] == 0) {
        lw->Misc[MISC_LWEAPON_ITEM] = LastItemUsed;
    }
}
 
/////////////////////////////////////////////////////////////////////////
/// Updates the LastItemUsed variable to our best guess at what was   ///
/// most recently used. This should be called at the end of the loop, ///
/// right before Waitdraw or Waitframe, because the item marked in    ///
/// LastItemUsed isn't actually used until after the Waitdraw or      ///
/// Waitframe.                                                        ///
/////////////////////////////////////////////////////////////////////////


void UpdateLastItem() {

  // Since we don't know which button has priority if both are pressed
  // at once, cancel the B button press if A has also been pressed
  // this frame.
  
    if (Link->PressA && Link->PressB) {
        Link->PressB = false;
    }

    // If Link is currently in an action where he obviously can't use items, then ignore his button presses.
    if (Link->Action != LA_NONE &&      
        Link->Action != LA_WALKING) {
            return;
    }

    // Check which button is being pressed, if any. Also check for the appopriate Jinx.

    if (Link->PressA && Link->SwordJinx == 0) {
        LastItemUsed = GetEquipmentA();
    }
    else if (Link->PressB && Link->ItemJinx == 0) {
        LastItemUsed = GetEquipmentB();
        }
}
 


bool IsFromItem(lweapon lw, int itemNumber) {   //// Return true if the given lweapon is from the given item.
    return lw->Misc[MISC_LWEAPON_ITEM] == itemNumber;
}
 


bool IsFromItemClass(lweapon lw, int itemClass) {   //// Return true if the given lweapon is from the given item class.
    itemdata data = Game->LoadItemData(lw->Misc[MISC_LWEAPON_ITEM]);
    return data->Family == itemClass;
}

////////////////////
/// Item Pick-Up ///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// This script creates an FFC, that gives Link a key, and clears the FFC if the FFC is touched by the      ///
/// boomerang, or the hookshot. This is useful if you want the boomerang/hookshot to pick up keys as in Z3, ///
/// without also allowing them to pick up other special items (per quest rules for Z3 boomerang.            ///
///                                                                                                         ///
/// Note: The pick-up is instantaneous, and does not need to wait for Link to touch the item.               ///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// D0 : Item Class (Positive Number), or Item Number (negative Number) of primary trigger.                ///
/// Standard value is 1 (IC_BRANG).                                                                        ///
/// D1 : Item Class (positive Number), or Item Number (negative Number) of secondary trigger.              ///
/// Standard value is 21 (IC_HOOKSHOT).                                                                    ///
/// D2: Set to 0 to give a normal key, or 1 to give a key specific to the level that the player is inside. ///
/// Set to a negative number to give a specific item, other than a key, or a level key.                    ///
/// D3: Set this to the Sound Effect to play on giving the player the item, from Quest->Audio->SFX Data.   ///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

ffc script Z3_Key_Pickup {
    void run(int trigger, int trigger2, int level, int SFX) {
    
        bool waiting = true;
            while(waiting){
                if ( Screen->D[0] >= 1 ) {   // If the FFC has already run on the screen
                    this->Data = 0; //Remove sprite
                    return; //Quit
                }
          
                else if ( Screen->D[0] == 0 ) {
                    for (int i = 1; i <= Screen->NumLWeapons(); i++) {   // Loop through all LWeapons on screen.
                    lweapon lw = Screen->LoadLWeapon(i);
                    
                        if (lw->CollDetection && Collision(this, lw)) {     // If the LWeapon is touching us.

                            if (trigger > 0) {      // If <trigger> is positive, test the lweapon for being the correct item class.
                                if (IsFromItemClass(lw, trigger) || IsFromItemClass(lw, trigger2)) {
                                        waiting = false;
                                        if ( level == 0 ) {
                                        Game->Counter[CR_KEYS] += 1;
                                        Game->PlaySound(SFX);
                                        Screen->D[0] = 1;
                                        this->Data = 0; //Remove sprite
                                        return; //Quit
                                    }
                                    else if ( level > 0 ) {
                                        item levelKeyGiven = Screen->CreateItem(I_LEVELKEY);
                                        levelKeyGiven->X = Link->X;
                                        levelKeyGiven->Y = Link->Y;
                                        levelKeyGiven->Z = Link->Z;
                                        Game->PlaySound(SFX);
                                        Screen->D[0] = 1;
                                        this->Data = 0; //Remove sprite
                                        return; //Quit
                                    }
                                    else if ( level < 0 ) {
                                        item levelKeyGiven = Screen->CreateItem(-level);
                                        levelKeyGiven->X = Link->X;
                                        levelKeyGiven->Y = Link->Y;
                                        levelKeyGiven->Z = Link->Z;
                                        Game->PlaySound(SFX);
                                        Screen->D[0] = 1;
                                        this->Data = 0; //Remove sprite
                                        return; //Quit
                                    }
                                }
                            }
                          
    //                        else {      // If <trigger> is negative, test the lweapon for being the correct item number.
    //                            if (IsFromItem(lw, -trigger) || IsFromItem(lw trigger2)) {
    //                                waiting = false;
    //                            }
    //                        }
                        }
                    }
                      
                    Waitframe();
                    //Screen->D[0] = 1;
                    //this->Data = 0; //Remove sprite
                    //return; //Quit
                }
                
                        
                
                
                
                
                
                // Do stuff
                
            }
          

          // Clear the FFC if needed
    }
}

/////////////////////////////
/// Sample Active Script. ///
/////////////////////////////

global script Active {
    void run() {
        while (true) {
            UpdateLWeapons();
            UpdateLastItem();
            if (Link->PressB) {LastItemUsed = GetEquipmentB();}
            if (Link->PressA) {LastItemUsed = GetEquipmentA();}
            Waitdraw();
            Waitframe();
        }
    }
}