ff_i_events

Event functions.

Event types:

  • NWNX internal event - is a string - sent to a file that registered the event => Dispatched via NWNX:EE or manual NWNX_Events_SignalEvent

  • NWNX Console - is a string - uses local variables - uses a script chunk => Registers in ff_i_events::RegisterConsoleCommand => Runs on_console.nss => Dispatches via NWNX_Events_SignalEvent

  • NWNX SignalEvent

  • NWN Scripts (int, EVENT_SCRIPT_* / user defined)

  • Item Tag events (string, itm_*)

CURRENT_EVENT
int GetUserDefinedEventScript(object oObject)
Parameters:
  • oObject – An object. Returns 0 for types that have no user-defined event (item, store, waypoint).

Return oObject’s EVENT_SCRIPT_*_USER_DEFINED_EVENT.

void MoveEventScript(object oObject, int nHandler, string sFile = "")
Parameters:
  • oObject – An object.

  • nHandler – An EVENT_SCRIPT_* constant identifying the event slot.

  • sFile – Script to append to the dispatch list. Skipped when empty, SCRIPT_ON_EVENT, or SCRIPT_NULL. Defaults to “”.

Move script in nHandler’s place to a local variable for unicast dispatch.

int GetCurrentEventScript()

Returns the currently executing event script (EVENT_SCRIPT_*) or 0 if not determinable.

string GetCurrentEvent()

Return NWNX_Events_GetCurrentEvent first if it exists.

void SubscribeToEvent(string sEvent, string sFile, object oObject = OBJECT_INVALID)
Parameters:
  • sEvent – The event name.

  • sFile – Script to call when the event fires. Use

Subscribe to an event, whatever the object.

int SendEvent(string sEvent, object oTarget = OBJECT_SELF)
Parameters:
  • sEvent – Event name to signal.

  • oTarget – Object to signal. Defaults to OBJECT_SELF.

Send one event to all files for a single object.

string GetConsoleEventName(string sEvent)
Parameters:
  • sEvent – Console command name.

Return the ON_CONSOLE_COMMAND__<sEvent> event name (uppercased).

void RegisterConsoleCommand(string sCommand, string sFile)
Parameters:
  • sCommand – Command string (without “/” prefix)

  • sFile – File to call on command

Register a command that can be used from nwn-server console.

string GetItemTagEventName(string sEvent, string sFileOrTag)
Parameters:
  • sEvent – Base event name.

  • sFileOrTag – Item tag or filename; extension is stripped.

Return the tag-based event name for sEvent and sFileOrTag.

void SendItemTagEvent(string sEvent, object oObject, object oTarget = OBJECT_SELF)
Parameters:
  • sEvent – Unused; kept for API symmetry.

  • oObject – Object whose tag is used as the script name.

  • oTarget – Object the script executes on. Defaults to OBJECT_SELF.

Execute the script named by oObject’s tag on oTarget.

Source code

// @code

#include "ff_i_console"
#include "ff_i_events_c"
#include "ff_i_filesystem"
#include "ff_i_stringify"

#include "nwnx_object"
#include "nwnx_events"


// -----------------------------------------------------------------------------

const string CURRENT_EVENT = "CURRENT_EVENT";


// =============================================================================
// EVENT SCRIPT FUNCTIONS
// =============================================================================

//! @brief Return oObject's EVENT_SCRIPT_*_USER_DEFINED_EVENT
//! @param oObject An object. Returns 0 for types that have no user-defined event (item, store, waypoint).
int GetUserDefinedEventScript(object oObject);
int GetUserDefinedEventScript(object oObject)
{
  int nType = NWNX_Object_GetInternalObjectType(oObject);
  switch (nType)
  {
    case NWNX_OBJECT_TYPE_INTERNAL_AREA:      return EVENT_SCRIPT_AREA_ON_USER_DEFINED_EVENT;
    case NWNX_OBJECT_TYPE_INTERNAL_CREATURE:  return EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT;
    case NWNX_OBJECT_TYPE_INTERNAL_DOOR:      return EVENT_SCRIPT_DOOR_ON_USERDEFINED;
    case NWNX_OBJECT_TYPE_INTERNAL_ITEM:      return 0;
    case NWNX_OBJECT_TYPE_INTERNAL_MODULE:    return EVENT_SCRIPT_MODULE_ON_USER_DEFINED_EVENT;
    case NWNX_OBJECT_TYPE_INTERNAL_PLACEABLE: return EVENT_SCRIPT_PLACEABLE_ON_USER_DEFINED_EVENT;
    case NWNX_OBJECT_TYPE_INTERNAL_STORE:     return 0;
    case NWNX_OBJECT_TYPE_INTERNAL_TRIGGER:   return EVENT_SCRIPT_TRIGGER_ON_USER_DEFINED_EVENT;
    case NWNX_OBJECT_TYPE_INTERNAL_WAYPOINT:  return 0;
    default:
      LogError(__FILE__ + "::" + __FUNCTION__ + ":" + IntToString(__LINE__) + ", object type " + IntToString(nType) + " not mapped to script");
      LogStackTrace(__FILE__, __FUNCTION__, __LINE__);
      return 0;
  }
  return 0;
}

// -----------------------------------------------------------------------------

// Fixup the string by removing duplicates, double commas, etc.
string _TrimScripts(string sScripts)
{
  sScripts = GetStringTrim(sScripts) + ",";
  sScripts = GetStringReplace(sScripts, " ", "");
  sScripts = GetStringReplace(sScripts, ",,", ",");
  sScripts = GetStringReplace(sScripts, SCRIPT_NULL + ",", ",");
  if (GetStringLeft(sScripts, 1) == ",")
    sScripts = GetSubStringEx(sScripts, 1);
  return sScripts;
}


// -----------------------------------------------------------------------------

void _AppendScriptToUserDefinedVariable(object oObject, string sEvent, string sFile)
{
  string sScripts = GetLocalString(oObject, sEvent);
  string sNewFile = RemoveExtension(sFile) + ",";

  // Clean up the string, and only add once.
  sScripts = _TrimScripts(sScripts);
  sScripts = GetStringReplace(sScripts, sNewFile, "");
  sScripts += RemoveExtension(sFile) + ",";
  if (GetStringLeft(sScripts, 1) == ",")
    sScripts = GetSubStringEx(sScripts, 1);

  SetLocalString(oObject, sEvent, sScripts);
}


// -----------------------------------------------------------------------------

//! @brief Move script in nHandler's place to a local variable for unicast dispatch
//! @param oObject An object.
//! @param nHandler An EVENT_SCRIPT_* constant identifying the event slot.
//! @param sFile Script to append to the dispatch list. Skipped when empty, SCRIPT_ON_EVENT, or SCRIPT_NULL. Defaults to "".
void MoveEventScript(object oObject, int nHandler, string sFile = "");
void MoveEventScript(object oObject, int nHandler, string sFile = "")
{
  // If a file is present, move it to a variable, and that variable will
  // be just a list of files to execute when event happens
  if (sFile != "" && sFile != SCRIPT_ON_EVENT && sFile != SCRIPT_NULL)
  {
    string sEvent = EventScriptToEvent(nHandler);
    _AppendScriptToUserDefinedVariable(oObject, sEvent, sFile);
  }

  // Set the script to SCRIPT_ON_EVENT, unless it's "null" which
  // we promised not to change.
  string sCurrentFile = GetEventScript(oObject, nHandler);
  if (sCurrentFile == SCRIPT_NULL)
    { /* do nothing */}
  else
    SetEventScript(oObject, nHandler, SCRIPT_ON_EVENT);
}

// -----------------------------------------------------------------------------

//! @brief Returns the currently executing event script (EVENT_SCRIPT_*) or 0 if not determinable.
int GetCurrentEventScript();
int GetCurrentEventScript()
{
  int nHandler = GetCurrentlyRunningEvent(FALSE);
  if (nHandler == 0)
    nHandler = GetCurrentlyRunningEvent(TRUE);
  return nHandler;
}


// =============================================================================
// EVENT FUNCTIONS
// =============================================================================

//! @brief Return NWNX_Events_GetCurrentEvent first if it exists.
string GetCurrentEvent();
string GetCurrentEvent()
{
  // If the event name is forced, then return it
  string sEvent = GetLocalString(GetModule(), CURRENT_EVENT);
  if (sEvent != "")
    return sEvent;

  // Otherwise, we might be in a NWNX event
  sEvent = NWNX_Events_GetCurrentEvent();
  if (sEvent != "")
    return sEvent;

  // Last, send the corresponding Event from EventScript
  int nHandler = GetCurrentEventScript();
  if (nHandler != 0)
    return EventScriptToEvent(nHandler);

  return "";
}


// -----------------------------------------------------------------------------

//! @brief Subscribe to an event, whatever the object.
//! @param sEvent The event name.
//! @param sFile Script to call when the event fires. Use __FILE__. Scoped to oObject via dispatch list if oObject is valid.
void SubscribeToEvent(string sEvent, string sFile, object oObject = OBJECT_INVALID);
void SubscribeToEvent(string sEvent, string sFile, object oObject = OBJECT_INVALID)
{
  sFile = RemoveExtension(sFile);

  if (GetIsObjectValid(oObject))
  {
    int nHandler = EventToEventScript(oObject, sEvent);
    if (nHandler <= 0)
    {
      NWNX_Events_SubscribeEvent(sEvent, sFile);
      NWNX_Events_ToggleDispatchListMode(sEvent, sFile, TRUE);
      NWNX_Events_AddObjectToDispatchList(sEvent, sFile, oObject);
    }
    else
      MoveEventScript(oObject, nHandler, sFile);
  }
  else
      NWNX_Events_SubscribeEvent(sEvent, sFile);
}


// =============================================================================
// BROADCAST FUNCTIONS
// =============================================================================

//! @brief Send one event to all files for a single object.
//! @param sEvent Event name to signal.
//! @param oTarget Object to signal. Defaults to OBJECT_SELF.
int SendEvent(string sEvent, object oTarget = OBJECT_SELF);
int SendEvent(string sEvent, object oTarget = OBJECT_SELF)
{
  if (sEvent == "")
    return FALSE;
  if (!GetIsObjectValid(oTarget))
    return FALSE;
  return (NWNX_Events_SignalEvent(sEvent, oTarget));
}


// =============================================================================
// CONSOLE
// =============================================================================

//! @brief Return the ON_CONSOLE_COMMAND__<sEvent> event name (uppercased).
//! @param sEvent Console command name.
string GetConsoleEventName(string sEvent);
string GetConsoleEventName(string sEvent)
{
  return GetStringUpperCase(ON_CONSOLE_COMMAND + "__" + sEvent);
}


// -----------------------------------------------------------------------------

//! @brief Register a command that can be used from nwn-server console.
//! @param sCommand Command string (without "/" prefix)
//! @param sFile File to call on command
void RegisterConsoleCommand(string sCommand, string sFile);
void RegisterConsoleCommand(string sCommand, string sFile)
{
  // There's already a warning during module start if
  // NWNX_CORE_ALLOW_NWNX_FUNCTIONS_IN_EXECUTE_SCRIPT_CHUNK is not set

  // Commands are all in lowercase, but the event will be in uppercase
  sCommand = GetStringLowerCase(sCommand);

  string sScript = "";
  sScript += "SetLocalString(GetModule(), \"" + CONSOLE_COMMAND + "\", \"" + sCommand + "\");";
  sScript += "SetLocalString(GetModule(), \"" + CONSOLE_ARGS + "\", \"$args\");";
  sScript += "ExecuteScript(\"" + SCRIPT_ON_CONSOLE + "\");";
  NWNX_Util_RegisterServerConsoleCommand(sCommand, sScript);

  sFile = RemoveExtension(sFile);
  NWNX_Events_SubscribeEvent(GetConsoleEventName(sCommand), sFile);
}

// =============================================================================
// TAG BASED EXECUTION
// =============================================================================

//! @brief Return the tag-based event name for sEvent and sFileOrTag.
//! @param sEvent Base event name.
//! @param sFileOrTag Item tag or filename; extension is stripped.
string GetItemTagEventName(string sEvent, string sFileOrTag);
string GetItemTagEventName(string sEvent, string sFileOrTag)
{
  // We abuse the fact that item tag == filename
  return GetStringUpperCase(sEvent + "__" + RemoveExtension(sFileOrTag));
}


// -----------------------------------------------------------------------------

//! @brief Execute the script named by oObject's tag on oTarget.
//! @param sEvent Unused; kept for API symmetry.
//! @param oObject Object whose tag is used as the script name.
//! @param oTarget Object the script executes on. Defaults to OBJECT_SELF.
void SendItemTagEvent(string sEvent, object oObject, object oTarget = OBJECT_SELF);
void SendItemTagEvent(string sEvent, object oObject, object oTarget = OBJECT_SELF)
{
  ExecuteScript(GetTag(oObject), oTarget);
}