//::////////////////////////////////////////////// //:: Created By: cawila //:: Created On: v643 //::////////////////////////////////////////////// //:: Heavily modified by Arkov in v666, v685 //::////////////////////////////////////////////// #include "inc_dmb_chat" #include "chat_listener" #include "chat_actions" #include "chat_emotes" /////////////////////////////////////////////////////////////////////////////// // DEFINES/PROTOTYPES /////////////////////////////////////////////////////////////////////////////// void chat_ProcessVoice(object oPC, string sVoice); void Eavesdrop(object oPC, string sText, object oTo, int nMode); void HandleSimpleAction(string sAction, object oPC); void ParseSimpleAction(string sInput, object oPC); /////////////////////////////////////////////////////////////////////////////// // MAIN /////////////////////////////////////////////////////////////////////////////// void main() { // speaking object object oPC = OBJECT_SELF; object oArea = GetArea(oPC); // get text SetLocalString(oPC, "NWNX!CHAT!TEXT", dmb_GetSpacer()); string sText = GetLocalString(oPC, "NWNX!CHAT!TEXT"); int nMode = StringToInt(GetStringLeft(sText,2)); int nTo = StringToInt(GetSubString(sText,2,10)); sText = dmb_GetStringFrom(sText, 12); int iLength = GetStringLength(sText); Eavesdrop(oPC, sText, dmb_getPC(nTo), nMode); if(GetSubString(sText, 0, 3) == "/c "){ chat_ProcessAction(oPC, GetStringRight(sText, iLength - 3)); SetLocalString(oPC, "NWNX!CHAT!SUPRESS", "1"); } else if(GetSubString(sText, 0, 3) == "/e "){ chat_ProcessEmote(oPC, GetStringRight(sText, iLength - 3)); SetLocalString(oPC, "NWNX!CHAT!SUPRESS", "1"); } else if(GetSubString(sText, 0, 3) == "/r "){ chat_ProcessRoll(oPC, GetStringRight(sText, iLength - 3)); SetLocalString(oPC, "NWNX!CHAT!SUPRESS", "1"); } else if(GetSubString(sText, 0, 3) == "/v "){ chat_ProcessVoice(oPC, GetStringRight(sText, iLength - 3)); SetLocalString(oPC, "NWNX!CHAT!SUPRESS", "1"); } else { if(nMode == 3) { SendMessageToAllDMs("Whisper being ignored"); return; } // Talk mode, Whisper mode, Shout mode if(nMode == 1 || nMode == 2 || nMode == 3){ if(GetLocalInt(oArea, "bHasNoListeningRegion") == FALSE){ object oListeningRegion = GetNearestObjectByTag("ListeningRegion", oPC); if(oListeningRegion == OBJECT_INVALID){ SetLocalInt(oArea, "bHasNoListeningRegion", TRUE); }else{ if(GetIsInSubArea(oPC, oListeningRegion)){ doListening(oListeningRegion, oPC, sText, nMode); } } } // Talk mode if (nMode == 1) { ParseSimpleAction(sText, oPC); SetLocalString(oPC, "sListener_LastSpoken", sText); } } } // remove garbage DeleteLocalString(oPC, "NWNX!CHAT!TEXT"); DeleteLocalString(oPC, "NWNX!CHAT!SUPRESS"); } /////////////////////////////////////////////////////////////////////////////// // UTILITY FUNCTIONS /////////////////////////////////////////////////////////////////////////////// void chat_ProcessVoice(object oPC, string sVoice) { //Speaking through an Associate: // /v a = Animal Companion // /v d = Dominated Monster // /v f = Familiar // /v h = Henchman // /v s = Summoned Creature int iLength = GetStringLength(sVoice); if(GetSubString(sVoice, 0, 2) == "a ") chat_RemoteSpeech(GetStringRight(sVoice, iLength-2), GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC), oPC); else if(GetSubString(sVoice, 0, 2) == "d ") chat_RemoteSpeech(GetStringRight(sVoice, iLength-2), GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC), oPC); else if(GetSubString(sVoice, 0, 2) == "f ") chat_RemoteSpeech(GetStringRight(sVoice, iLength-2), GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC), oPC); else if(GetSubString(sVoice, 0, 2) == "h ") chat_RemoteSpeech(GetStringRight(sVoice, iLength-2), GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC), oPC); else if(GetSubString(sVoice, 0, 2) == "s ") chat_RemoteSpeech(GetStringRight(sVoice, iLength-2), GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC), oPC); else if(GetIsDM(oPC)){ int nCritter = StringToInt(GetSubString(sVoice, 0, FindSubString(sVoice, " "))); if(nCritter > 0){ object oTarget = GetLocalObject(oPC, "LDSCRITTER" + IntToString(nCritter)); if (!GetIsObjectValid(oTarget)) SendMessageToPC(oPC, "You must first use to store a creature in slot " + IntToString(nCritter)); else chat_RemoteSpeech(GetStringRight(sVoice, iLength - FindSubString(sVoice, " ") - 1), oTarget, oPC); }else SendMessageToPC(oPC, "Invalid slot " + IntToString(nCritter)); }else SendMessageToPC(oPC, "Unrecognized command."); } // Eavesdrop: // A debugging routine that sends all text passing // through listening directly to interested DMs. There can // be ten DMs eavesdropping at a time; as soon as they're // all gone, the eavesdropping flag is set to zero and // the routine does nothing, to minimize overhead. void Eavesdrop(object oPC, string sText, object oTo, int nMode) { int nCount; object oModule = GetModule(); // Compose the logging message string sAreaName = GetName(GetArea(oPC)); if(GetStringLength(sAreaName) > 14) sAreaName = GetStringLeft(sAreaName, 4) + "..." + GetStringRight(sAreaName, 7); string sPrefix = GetName(oPC) + " (" + sAreaName + ") [" + GetSpeechModeString(nMode) + "]: "; string sMessage = sPrefix + GetSpeechModeColor(nMode) + sText + ""; string sLogfile = sPrefix + sText; nMode %= 16; if(nMode == 4 || nMode == 5 || nMode == 7){ sMessage += " >> " + GetName(oTo); sLogfile += " >> " + GetName(oTo); } string sTimeStamp = GetLocalString(GetModule(), "sModule_TimeStamp"); SetLocalString(oPC, "NWNX!CHAT!LOG", sTimeStamp + " " + sLogfile + "\n"); object oEavesdropper; for(; nCount < 10; nCount++){ oEavesdropper = GetLocalObject(oModule, "oEavesdropper_" + IntToString(nCount)); if(!GetIsObjectValid(oEavesdropper)) continue; // And send to each listening DM. if(GetIsDM(oEavesdropper)) SendMessageToPC(oEavesdropper, sMessage); else DeleteLocalObject(oModule, "oEavesdropper_" + IntToString(nCount)); } } // HandleSimpleAction: // Major routine, called on every *emote* that // goes through the Talk channel; also should be // called by voice-throwing routines. The contents // of the *emote* (e.g. "emote") are passed in as // the string sAction. void HandleSimpleAction(string sAction, object oPC) { if(GetStringUpperCase(GetStringLeft(sAction, 5)) == "ROLL ") chat_ProcessRoll(oPC, GetStringRight(sAction, GetStringLength(sAction) - 5)); else if(GetIsPC(oPC) && !GetIsDM(oPC) && !GetIsDMPossessed(oPC) && GetTokenInt(oPC, "Talus_parse_emotes")) chat_ProcessEmote_Strict(oPC, sAction); } // ParseSimpleAction: // Text processing routine to prepare strings to // be put through HandleSimpleAction. // -- doesn't really need to return the string it pulled out. void ParseSimpleAction(string sInput, object oPC) { string sAction=""; int iLength=GetStringLength(sInput); int iStar1=FindSubString(sInput, "*"); if(iStar1 >= 0 && iStar1 < iLength+1) { string sRight=GetStringRight(sInput, iLength-iStar1-1); int iStar2=FindSubString(sRight, "*"); if(iStar2 >= 0 && iStar2+iStar1 < iLength) { sAction=GetStringLeft(sRight, iStar2); if(GetStringLength(sAction)) HandleSimpleAction(sAction, oPC); string sNext = GetStringRight(sRight, GetStringLength(sRight)-iStar2-1); //recursively parse for more actions. ParseSimpleAction(sNext, oPC); } } }