/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//::
//::====================================================================== GENERAL DETAILS ==============================================================================
//:: OnEnter Trigger Filename: placeablespeaker
//:: Additional Notes: ---
//::
//:: Created by:      Spiffy
//:: Created on date: 13/06/2023
//:: Purpose:         Have a placeable "speak" when a trigger is touched.
//::
//:: Instructions:    Put down a trigger, and assign this script "placeablespeaker" on the OnEnter event of the script.
//::                  Assign the following variables:
//::
//::                  - int nMaxLines = the maximum number of "lines" on the placeable. This will tell it what number to stop at when randomly searching or speaking "in order"
//::                  - float fTimeBetweenText = the delay between lines of text being speaking. This is in seconds.
//::                  - float fMaximumTimeBeforeIReset = There is a timer on the trigger to prevent multiple people from triggering the event and spamming the dialogue box
//::                                                     with text. This is in seconds.
//::                  - string sSpeakingPlaceable = The Tag of the Placeable you want to speak. Make sure this is UNIQUE.
//::                  - int bSpeakInOrder = 0 = random, 1= in order.
//::                  - string SpeakTextX = Assigned to the placeable, this tells the script what text to "speak." PUT THIS ON THE PLACEABLE YOU WANT TO SPEAK, NOT THE TRIGGER.
//::                                        X is a number.
//::
//::=====================================================================================================================================================================
//::=====================================================================================================================================================================
//::
//::====================================================================== MODIFICATION DETAILS =========================================================================
//:: Modified by:      ???
//:: Modified on date: DD/MM/YYYY
//:: What was added:
//::                   - (DD/MM/YYYY) TEXT ~EDITOR
//::
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// INCLUDES ///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////// END INCLUDES //////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////// CONSTANT VARIABLES //////////////////////////////////////////////////////////////////////////

//=========================================
//GLOBAL CONSTANTS
//=========================================

//Placeable related variables
const string LAST_LINE_SPOKEN_VARNAME = "nLastLineSpoken";
const string SPEAK_TEXT_VARNAME_PREFIX = "SpeakText";

//Trigger related variables
const string SPEAK_PLACEABLE_TAG_VARNAME = "sSpeakingPlaceable";
const string MAX_LINES_VARNAME = "nMaxLines";
const string AM_ACTIVATED_FLAG_VARNAME = "AmIActivated";
const string SPEAK_IN_ORDER_FLAG_VARNAME = "bSpeakInOrder";
const string TIME_BETWEEN_TEXT_VARNAME = "fTimeBetweenText";
const string MAXIMUM_TIME_BEFORE_RESET_VARNAME = "fiMaximumTimeBeforeIReset";

///////////////////////////////////////////////////////////////////////// END CONSTANT VARIABLES ////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// GENERAL FUNCTIONS DECLARATIONS ////////////////////////////////////////////////////////////////////

// This function performs speaking for a placeable in sequence
void SpeakLine(object oCodex, int nMaxLines, int bSpeakInOrder);

////////////////////////////////////////////////////////////////// END GENERAL FUNCTIONS DECLARATIONS ///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// GENERAL FUNCTIONS IMPLEMENTATION ///////////////////////////////////////////////////////////////////////

// This function performs speaking for a placeable in sequence
void SpeakLine(object oCodex, int nMaxLines, int bSpeakInOrder) {

    int nLine;
    string sVariableName, sLine;

    if(bSpeakInOrder == 1) {
        // get the last line spoken and increment it
        nLine = GetLocalInt(oCodex, LAST_LINE_SPOKEN_VARNAME) + 1;

        // if we've gone over the max lines, reset to 1
        if (nLine > nMaxLines)
            nLine = 1;

        SetLocalInt(oCodex, LAST_LINE_SPOKEN_VARNAME, nLine);
    }

    else {
        // generate a random number between 1 and nMaxLines
        nLine = Random(nMaxLines) + 1;
    }

    sVariableName = SPEAK_TEXT_VARNAME_PREFIX + IntToString(nLine);
    sLine = GetLocalString(oCodex, sVariableName);

    if(sLine == "")
        return;

    AssignCommand(oCodex, SpeakString(sLine));
}

//////////////////////////////////////////////////////////////// END GENERAL FUNCTIONS IMPLEMENTATIONS //////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main()
{
    object oTrigger = OBJECT_SELF;
    object oCodex;
    int nMaxLines, bSpeakInOrder, iLoop;
    float fTimeBetweenText, fMaximumTimeBeforeIReset;
    string sSpeakingPlaceable = GetLocalString(oTrigger, SPEAK_PLACEABLE_TAG_VARNAME);

    // Check if a placeable tag is set, if not, exit the script
    if(sSpeakingPlaceable == "")
        return;

    oCodex = GetNearestObjectByTag(sSpeakingPlaceable, oTrigger);
    nMaxLines = GetLocalInt(oTrigger, MAX_LINES_VARNAME); // retrieve max lines from trigger

    // Check if nMaxLines is set, if not, exit the script
    if (nMaxLines <= 0)
        return;

    if(GetLocalInt(oTrigger, AM_ACTIVATED_FLAG_VARNAME) == TRUE)
        return; // already activated, so do nothing

    SetLocalInt(oTrigger, AM_ACTIVATED_FLAG_VARNAME, TRUE); // set trigger as activated

    bSpeakInOrder = GetLocalInt(oTrigger, SPEAK_IN_ORDER_FLAG_VARNAME); // retrieve speak order from trigger
    fTimeBetweenText = GetLocalFloat(oTrigger, TIME_BETWEEN_TEXT_VARNAME); // retrieve time between text from trigger
    fMaximumTimeBeforeIReset = GetLocalFloat(oTrigger, MAXIMUM_TIME_BEFORE_RESET_VARNAME); // retrieve maximum time before reset from trigger
    SpeakLine(oCodex, nMaxLines, bSpeakInOrder); // start speaking lines

    // reset trigger after iMaximumTimeBeforeIReset seconds
    DelayCommand(fMaximumTimeBeforeIReset, SetLocalInt(oTrigger, AM_ACTIVATED_FLAG_VARNAME, FALSE));

    // speak a line every iTimeBetweenText seconds for the next iMaximumTimeBeforeIReset seconds
    iLoop = 1;

    while(fMaximumTimeBeforeIReset > 0.0) {
        DelayCommand(iLoop * fTimeBetweenText, SpeakLine(oCodex, nMaxLines, bSpeakInOrder));
        iLoop++;
        fMaximumTimeBeforeIReset /= fTimeBetweenText;
    }
}
