ItemHoldUpMessage.zh (v1.1.) | Demo Quest

Here is a new header for controlling item pick-up messages and hold-up actions, quickly and easily.

It uses an ffc launcher item script, that should be assigned as the Pick-Up Script for a given item; and the D0 ( InitD[0] ) input in the item editor to set both the string, and the item ID at one time. This launches one of three ffc scripts:
One for land, one for swimming, and one for diving, selected by Link's present action when the collect script runs.

All of the main events are handled by the ffc script that the launcher script selects, and the ffc thereafter cleans up its data, and exits.
This single value used by the item script, is split between the integer and the decimal portions, so that the integer side is the message, and the decimal side is the item number. Thus, if you want to use string 16 on item 43, you enter a value of 16.0043.

The script displays strings immediately following the item hold-up animation, so they never obscure the visual event of Link holding up the item.

The user need never set up the ffc scripts. All data is forwarded to them from the item collect script, and setting up the ffc scripts on a screen is not a very good idea. They are designed solely to run from launcher code.

All of the code is cleanly commented, and redundant blocks are reduced to script-scope functions. These also include debugging and logging routines, that report user error.



Here is the Header Code if you wish to review it on-site.
Spoiler: show

Code:
///////////////////////////
/// Item Hold Up Header ///
/// v1.1 for ZC 2.50.x  ///
/// 2nd August, 2017    ///
/// By: ZoriaRPG        ///
///////////////////////////
// Demo Quest: http://timelord.insomnia247.nl/zc/zc...Message_zh.qst

//!!!!!!!!!!!!!!!!!!!!!
//! Settings   

const int ITEM_HOLDUP_ZH__LA_HOLDUP_HANDS = 1; //The number of hands to use for the default hold-up animation.
const int ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE = 20; //Change to the sound that you want. 
const int ITEM_HOLDUP_ZH__ERROR_ON_NO_ITEM_NUMBER = 1; //Set to 0 to disable some logging. 

//!!!!!!!!!!!!!!!!!!!!!
//! Scripts 

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Item Script that Runs The FFCs
/// D0: THe integer portion is the string to use, and the decimal portion is the item to display 
///     during the hold-up animation:
///    Example: 27.0016 
///        This will use String 20, and display Item 16 in the hold-up animation. 

item script PickMessageFFCLauncher
{
    void run(int string_itmID)
    {
        int foundff;
        int __item_message_string = string_itmID << 0;
        int this_item_id = ( string_itmID - __item_message_string ) * 10000;
        int _____ffscript_id; int ___err_aborting[]="Aborting item hold-up.";

        if ( this_item_id > 0 && this_item_id < 256 )
        {
            if ( Link->Action == LA_DIVING ) 
            {
                int ff[]="FFC_DiveHoldUp";
                _____ffscript_id = Game->GetFFCScript(ff);
                if ( _____ffscript_id < 1 ) 
                {     //Error and exit if the ffc script is not in the quest matrix. 
                    ItemHoldupZH_FFC_Failure_Error(ff, ___err_aborting);
                    Quit();
                }
            }
            else if ( Link->Action == LA_SWIMMING  ) 
            {
                int ff[]="FFC_SwimHoldUp";
                _____ffscript_id = Game->GetFFCScript(ff);
                if ( _____ffscript_id < 1 ) { 
                    //Error and exit if the ffc script is not in the quest matrix. 
                    ItemHoldupZH_FFC_Failure_Error(ff, ___err_aborting);
                    Quit();
                }
            }
            else
            {
                //Link is on land. 
                int ff[]="FFC_ItemHoldUp";
                _____ffscript_id = Game->GetFFCScript(ff);
                if ( _____ffscript_id < 1 ) { 
                    //Error and exit if the ffc script is not in the quest matrix. 
                    ItemHoldupZH_FFC_Failure_Error(ff, ___err_aborting);
                    Quit();
                }
            }
            
            foundff = ItemHoldup_FindFreeFFC(); //Grab a free ffc. 
            
            if ( foundff > 0 && foundff < 33 ) 
            {    //if we find one, set it up to use the correct script. 
                ItemHoldUp_SetUpFFC(foundff, _____ffscript_id, this_item_id, __item_message_string);
                
            }
            if ( foundff <= 0  )
            {
                //Error if we cannot grab a free ffc. 
                int ferr[]="Cound not find a free ffc slot to run the ffc script for item script PickMessageFFCLauncher. ";
                TraceNL(); TraceS(ferr); Trace(___err_aborting); TraceNL();
            }
            Quit();
            
        }
        else {
            if ( ITEM_HOLDUP_ZH__ERROR_ON_NO_ITEM_NUMBER ) { ItemHoldupZH_FFC_User_Failure_On_Item_Number(this_item_id, ___err_aborting); }
            //Display the message without holding up the item. 
            Screen->Message(__item_message_string);
        }
    }
    int ItemHoldup_FindFreeFFC()
    {
        for ( int q = 32; q > 0; q-- )
        {
            ffc f = Screen->LoadFFC(q);
            if ( f->Data == 0 )
            {
                if ( f->Script == 0 )
                return q;
            }
        }
        return -1;
    }
    void ItemHoldUp_SetUpFFC(int screen_ff_index, int ffscript_id, int ________initD0, int ________initD1)
    {
        
        ffc f = Screen->LoadFFC(screen_ff_index);
        f->Data = 1;
        f->Script = ffscript_id;
        f->InitD[0] = ________initD0;
        f->InitD[1] = ________initD1;
        
    }
    void ItemHoldupZH_FFC_Failure_Error(int a, int b)
    {    //a == ff, b == ___err_aborting
        int ___errff[]="Cound not find the script: ";
        TraceNL(); TraceS(___errff); TraceS(a); TraceNL(); TraceS(b); TraceNL();
    }
    void ItemHoldupZH_FFC_User_Failure_On_Item_Number(int this_item_id, int a)
    //a == ___err_aborting
    {
        TraceNL();
        int ____err_itm_id[]="The input for the item ID to display in the script PickMessageFFCLauncher is not valid!";
        int ____err_itm_id2[]="The value that was entered was: ";
        int ____err_itm_id3[]="The valid range is 1 to 255."; 
        TraceS(____err_itm_id); TraceS(____err_itm_id2);
        Trace(this_item_id); TraceNL(); TraceS(____err_itm_id3); TraceS(a); TraceNL();
    }
}

////////////////////////////////////////////////////////////////////
/// FFC Scripts
/// These drive the effects for item hold-up and message display, 
/// and are called automatically by the launcher. 
/// DO NOT PLACE THESE ON A SCREEN!

ffc script FFC_SwimHoldUp{
    void run(int itm, int __item_message_string)
    {
        Waitframe();     // An initial waitframe so that the item pick-up script is fully closed,
                // and so that the item collect script  effects finish running before
                // we do anything else. 
                
        if ( ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE > 0 && ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE < 255) 
        {
            Game->PlaySound(ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE);
        }
        Link->Action = LA_HOLD1WATER + (ITEM_HOLDUP_ZH__LA_HOLDUP_HANDS-1);
        Link->HeldItem = itm;
        //do-while loop to delay the message display until the hold-up animation eneds. 
        do{
            Waitframe();
        } while( Link->Action == LA_HOLD1WATER || Link->Action == LA_HOLD2WATER );
        Screen->Message(__item_message_string);
        this->Data = 0;
        this->Script = 0;
        Quit();
    }
}

ffc script FFC_DiveHoldUp{
    void run(int itm, int __item_message_string){
        
        do {
            Waitframe();
        } while(Link->Action == LA_DIVING);
        
        do {
            Waitframe();
        } while( Link->Action == LA_HOLD1WATER || Link->Action == LA_HOLD2WATER );
        
        //ZC Automatically Holds Up all dive items, and plays the Item Fanfare SFX (SFX: 20, hardcoded).
        
        Screen->Message(__item_message_string);
        this->Data = 0;
        this->Script = 0;
        Quit();
    }
}


ffc script FFC_ItemHoldUp{
    void run(int itm, int __item_message_string){
        
        Link->Action = LA_HOLD1LAND + (ITEM_HOLDUP_ZH__LA_HOLDUP_HANDS-1);
        Link->HeldItem = itm;
        if ( ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE > 0 && ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE < 255) 
        {
            Game->PlaySound(ITEM_HOLDUP_ZH__SFX_HOLD_ITEM_FANFARE);
        }
        
        // This do-while loop is to ensure that the message does not obscure the item during the hold-up animation. 
        do {
            Waitframe();
        } while(Link->Action == LA_HOLD1LAND || Link->Action == LA_HOLD2LAND);
        
        Screen->Message(__item_message_string);
        this->Data = 0;
        this->Script = 0;
        Quit();
    }
}


It requires std.zh (In fact, it only requires std_constants.zh).

This is the by-product of a series of code concepts that I made for Cukeman on PureZC, but it is ultimately different to any prior script set of this sort, and I hope, infinitely better than prior scripts of this sort, as well.