ff_u_plc_persist

Persistent placeable inventories.

Saves and restores the inventory of eligible placeables across server restarts. When an eligible placeable is destroyed, its saved items are deleted from the database.

Eligibility requires all of the following on the placeable:

  • Not static.

  • Has inventory.

  • Has a unique tag.

  • PERSISTENT flag set to "Y".

Variables

ENABLE__FF_U_PLC_PERSISTENT: (string) (opt-out) Set to "N" on module to disable the unit.

PERSISTENT: (string) Set to "Y" on a placeable to opt in.

Source code

// @code

#include "ff_i_core"


const string ENABLE__FF_U_PLC_PERSISTENT = "ENABLE__FF_U_PLC_PERSISTENT";

const string PERSISTENT = "PERSISTENT";

const string LOCAL_CAMPAIGN_NAME = "p_plc";

const string TABLE_NAME = "placeables";

//! Local int set on a placeable once its items were restored, so they are never restored twice.
const string FF_U_PLC_PERSISTENT = "__FF_U_PLC_PERSISTENT";

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

//! @brief Return TRUE if oObject is a PERSISTENT non-static placeable with a unique tag and inventory.
//! @param oObject An object.
int IsEligible(object oObject);
int IsEligible(object oObject)
{
  if (GetObjectType(oObject) != OBJECT_TYPE_PLACEABLE)
    return FALSE;

  // A placeable with an inventory cannot be static
  if (!GetHasInventory(oObject))
    return FALSE;

  if (!GetObjectFlag(oObject, PERSISTENT))
    return FALSE;

  if (!IsTagUnique(oObject))
    return FALSE;

  return TRUE;
}


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

//! @brief Restore persisted items from the campaign database into oObject.
//! @param oObject An eligible placeable.
void LoadItems(object oObject);
void LoadItems(object oObject)
{
  if (!IsEligible(oObject))
    return;

  if (GetLocalInt(oObject, FF_U_PLC_PERSISTENT))
    return;
  SetLocalInt(oObject, FF_U_PLC_PERSISTENT, TRUE);

  int nCount = LoadPersistentItems(oObject, LOCAL_CAMPAIGN_NAME, TABLE_NAME);
  if (nCount)
    LogInfo(__FILE__ + ": Restored " + IntToString(nCount) + " item(s) into " + GetTag(oObject));
}


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

//! @brief Save the current inventory of oObject to the campaign database.
//! @param oObject An eligible placeable.
void SaveItems(object oObject);
void SaveItems(object oObject)
{
  if (!IsEligible(oObject))
    return;
  SavePersistentItems(oObject, LOCAL_CAMPAIGN_NAME, TABLE_NAME);
}


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

//! @brief Delete the saved items of oObject from the campaign database.
//! @param oObject An eligible placeable.
void DestroyItems(object oObject);
void DestroyItems(object oObject)
{
  if (!IsEligible(oObject))
    return;

  DestroyPersistentItems(oObject, LOCAL_CAMPAIGN_NAME, TABLE_NAME);
}


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

//! @brief Restore the items of every eligible placeable in oArea.
//! @param oArea An area.
void OnArea(object oArea);
void OnArea(object oArea)
{
  object oObject = GetFirstObjectInArea(oArea);
  while (GetIsObjectValid(oObject))
  {
    LoadItems(oObject);
    oObject = GetNextObjectInArea(oArea);
  }
}


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

void OnVerify(object oPlaceable);
void OnVerify(object oPlaceable)
{
  if (!IsEligible(oPlaceable))
    return;
  ExpectUniqueTag(oPlaceable);
}


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

void main()
{
  string sEvent = NWNX_Events_GetCurrentEvent();
  if (sEvent == ON_REGISTER)
  {
    if (!GetModuleFlag(ENABLE__FF_U_PLC_PERSISTENT, TRUE))
      return;

    SubscribeToEvent(ON_MODULE_CREATED, __FILE__);
    SubscribeToEvent(ON_AFTER_OBJECT_CREATED, __FILE__);
    SubscribeToEvent(ON_OBJECT_VERIFY, __FILE__);
    SubscribeToEvent(ON_DEFAULT_PLACEABLE_CLOSED, __FILE__);
    SubscribeToEvent(ON_DEFAULT_PLACEABLE_DEATH, __FILE__);
    SubscribeToEvent(ON_DEFAULT_AREA_ENTER_ONCE, __FILE__);
  }
  else if (sEvent == ON_MODULE_CREATED)
    CreatePersistentDatabase(LOCAL_CAMPAIGN_NAME, TABLE_NAME);
  else if (sEvent == ON_OBJECT_VERIFY)
    OnVerify(OBJECT_SELF);
  else if (sEvent == ON_AFTER_OBJECT_CREATED)
    LoadItems(OBJECT_SELF);
  else if (sEvent == ON_DEFAULT_AREA_ENTER_ONCE)
    OnArea(OBJECT_SELF);
  else if (sEvent == ON_DEFAULT_PLACEABLE_CLOSED)
    SaveItems(OBJECT_SELF);
  else if (sEvent == ON_DEFAULT_PLACEABLE_DEATH)
    DestroyItems(OBJECT_SELF);
}