

//:: Purpose:         Have a placeable "speak" when a trigger is touched.
//::
//:: Instructions:    Put down a trigger, and assign this script "cas_shatemple" 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 the number.

//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";

// This function performs speaking for a placeable in sequence
void SpeakLine(object oCodex, int nMaxLines, int bSpeakInOrder, int nCurrentLine);

// Function to reset trigger activation state
void ResetTriggerActivation(object oTrigger) {
    SetLocalInt(oTrigger, AM_ACTIVATED_FLAG_VARNAME, FALSE);
}

void SpeakLine(object oCodex, int nMaxLines, int bSpeakInOrder, int nCurrentLine) {
    int nLine;
    string sVariableName, sLine;

    if(bSpeakInOrder == 1) {
        nLine = nCurrentLine;
    } 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 != "") {
        AssignCommand(oCodex, SpeakString(sLine));
    }

    // Prepare for the next line
    if(nLine >= nMaxLines) {
        nLine = 1; // Reset to the first line
    } else {
        nLine++; // Increment for the next line
    }

    // Schedule the next line if in order
    if(bSpeakInOrder == 1) {
        float fTimeBetweenText = GetLocalFloat(OBJECT_SELF, TIME_BETWEEN_TEXT_VARNAME);
        DelayCommand(fTimeBetweenText, SpeakLine(oCodex, nMaxLines, bSpeakInOrder, nLine));
    }
}

void main() {
    object oTrigger = OBJECT_SELF;
    object oCodex;
    int nMaxLines, bSpeakInOrder;
    float 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);

    // 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);
    SpeakLine(oCodex, nMaxLines, bSpeakInOrder, 1); // Start from the first line

    // reset trigger after fMaximumTimeBeforeIReset seconds
    fMaximumTimeBeforeIReset = GetLocalFloat(oTrigger, MAXIMUM_TIME_BEFORE_RESET_VARNAME);
    DelayCommand(fMaximumTimeBeforeIReset, ResetTriggerActivation(oTrigger));
}
