// cas_repeatspeech
// Capture PC chat via OnConversation listen patterns and route it safely.
// - Responds only to PCs
// - Only the nearest C_CAS_GLORYLISTEN to the PC will trigger
// - Optional: relay to another listener if RELAY_TO_LISTENER == 1
// - Can route to placeables CAS_FROM_HOLE / CAS_INTO_HOLE based on sSEND_TO

void SpeakDelayed(object oWho, string sMsg, float fDelay)
{
    if (!GetIsObjectValid(oWho) || sMsg == "") return;
    DelayCommand(fDelay, AssignCommand(oWho, SpeakString(sMsg)));
}

object GetNearestPlaceableByTag(string sTag, object oFrom)
{
    object oNearest = GetNearestObjectByTag(sTag, oFrom, 1);
    if (GetIsObjectValid(oNearest) && GetObjectType(oNearest) == OBJECT_TYPE_PLACEABLE)
        return oNearest;
    return OBJECT_INVALID;
}

void main()
{
    // Ignore clicks; only react to listen-pattern chat
    if (GetListenPatternNumber() == -1) return;

    object oSpeaker = GetLastSpeaker();
    if (!GetIsObjectValid(oSpeaker)) return;
    if (!GetIsPC(oSpeaker)) return; // only respond to player chat (prevents echo loops)

    // Only the nearest listener to the speaking PC should process this
    object oNearestToPC = GetNearestObjectByTag("C_CAS_GLORYLISTEN", oSpeaker, 1);
    if (oNearestToPC != OBJECT_SELF) return;

    // Full spoken text for pattern "**" is substring 0
    string sText = GetMatchedSubstring(0);
    if (sText == "") return;

    // Debug + confirmation
    SendMessageToPC(oSpeaker, "[cas_repeatspeech] Heard: \"" + sText + "\"");
    SpeakDelayed(OBJECT_SELF, "I heard " + sText, 0.1f);

    // Route to placeables based on listener local
    string sSendTo = GetLocalString(OBJECT_SELF, "sSEND_TO");
    if (sSendTo == "FROM_HOLE")
    {
        object oFromHole = GetNearestPlaceableByTag("CAS_FROM_HOLE", OBJECT_SELF);
        if (GetIsObjectValid(oFromHole))
            SpeakDelayed(oFromHole, sText, 0.1f);
    }
    else if (sSendTo == "INTO_HOLE")
    {
        object oIntoHole = GetNearestPlaceableByTag("CAS_INTO_HOLE", OBJECT_SELF);
        if (GetIsObjectValid(oIntoHole))
            SpeakDelayed(oIntoHole, sText, 0.1f);
    }

    // OPTIONAL: relay to another listener in the same area
    if (GetLocalInt(OBJECT_SELF, "RELAY_TO_LISTENER") == 1)
    {
        object oOther = GetNearestObjectByTag("C_CAS_GLORYLISTEN", OBJECT_SELF, 1);
        if (oOther == OBJECT_SELF) oOther = GetNearestObjectByTag("C_CAS_GLORYLISTEN", OBJECT_SELF, 2);

        if (GetIsObjectValid(oOther) && GetArea(oOther) == GetArea(OBJECT_SELF))
        {
            // This won't cause loops because only PCs trigger our logic.
            SpeakDelayed(oOther, sText, 0.1f);
            SendMessageToPC(oSpeaker, "[cas_repeatspeech] Relayed to other listener: " + GetTag(oOther));
        }
    }
}

