ff_u_p_plc
Persistent placeable inventories.
Saves and restores the inventory of eligible placeables across server restarts.
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_P_PLC: (string) (opt-out) Set to "N" on module to disable unit.
PERSISTENT: (string) Set to "Y" on a placeable to opt in.
Source code
// @code
#include "ff_i_core"
const string ENABLE__FF_U_P_PLC = "ENABLE__FF_U_P_PLC";
const string PERSISTENT = "PERSISTENT";
const string LOCAL_CAMPAIGN_NAME = "persistent_plc";
// -----------------------------------------------------------------------------
//! @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 (!GetObjectFlag(oObject, PERSISTENT))
return FALSE;
int nObjectType = GetObjectType(oObject);
if (nObjectType != OBJECT_TYPE_PLACEABLE)
return FALSE;
if (NWNX_Object_GetPlaceableIsStatic(oObject))
return FALSE;
if (!GetHasInventory(oObject))
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)
{
string sCampaign = GetCampaignName(LOCAL_CAMPAIGN_NAME);
string sTag = GetStringLowerCase(GetTag(oObject));
sqlquery sqlQuery = SqlPrepareQueryCampaign(sCampaign, "SELECT object FROM placeables WHERE TAG = @sTag");
SqlBindString(sqlQuery, "@sTag", sTag);
int nCount = 0;
while (SqlStep(sqlQuery))
{
object oItem = NWNX_Object_Deserialize(SqlGetString(sqlQuery, 0));
if (GetIsObjectValid(oItem))
{
CopyItem(oItem, oObject, TRUE);
DestroyObject(oItem);
}
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) // object oObject)
{
string sCampaign = GetCampaignName(LOCAL_CAMPAIGN_NAME);
string sTag = GetStringLowerCase(GetTag(oObject));
sqlquery sqlQuery = SqlPrepareQueryCampaign(sCampaign, "CREATE TABLE IF NOT EXISTS placeables (tag TEXT NOT NULL, object TEXT NOT NULL);");
SqlStep(sqlQuery);
sqlQuery = SqlPrepareQueryCampaign(sCampaign, "DELETE FROM placeables WHERE TAG = @sTag");
SqlBindString(sqlQuery, "@sTag", sTag);
SqlStep(sqlQuery);
int nCount = 0;
object oItem = GetFirstItemInInventory(oObject);
while (GetIsObjectValid(oItem))
{
sqlQuery = SqlPrepareQueryCampaign(sCampaign, "INSERT INTO placeables (tag, object) VALUES (@sTag, @oItem);");
SqlBindString(sqlQuery, "@sTag", sTag);
SqlBindString(sqlQuery, "@oItem", NWNX_Object_Serialize(oItem));
SqlStep(sqlQuery);
nCount++;
oItem = GetNextItemInInventory(oObject);
}
LogDebug(__FILE__ + ": Saved " + IntToString(nCount) + " item(s) from " + GetTag(oObject));
}
// -----------------------------------------------------------------------------
void main()
{
object oModule = GetModule();
if (!GetModuleFlag(ENABLE__FF_U_P_PLC, TRUE))
return;
string sEvent = GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
SubscribeToEvent(ON_OBJECT_CREATED, __FILE__);
SubscribeToEvent(ON_AFTER_PLACEABLE_CLOSE, __FILE__);
}
else if (sEvent == ON_OBJECT_CREATED && IsEligible(OBJECT_SELF))
{
LoadItems(OBJECT_SELF);
SendEvent(ON_BEFORE_PLACEABLE_OPEN, OBJECT_SELF);
}
else if (sEvent == ON_AFTER_PLACEABLE_CLOSE && IsEligible(OBJECT_SELF))
SaveItems(OBJECT_SELF);
}