ff_u_gc_plc
Placeable garbage collector.
Destroys placeables that have been in the world longer than GC_PLC_DURATION game hours and whose area has no players in it.
Variables
ENABLE__FF_U_GC_PLC: (string) (opt-out) Set to "N" to disable unit.
GC_PLC_DURATION: (int) Maximum age in module game hours before a placeable is destroyed. Defaults to 7 days.
Source code
// @code
#include "ff_i_core"
const string ENABLE__FF_U_GC_PLC = "ENABLE__FF_U_GC_PLC";
const string ARRAY_NAME = "__FF_U_GC_PLC__ARRAY";
const string GC_PLC_TIMESTAMP = "__FF_U_GC_PLC__TIMESTAMP";
const string GC_PLC_DURATION = "GC_PLC_DURATION";
const int DEFAULT_DURATION = 7 * 24 * 60; // 7 days
const string GARBAGE_COLLECT = "GARBAGE_COLLECT";
// -----------------------------------------------------------------------------
//! @brief Return TRUE if oObject is a non-static placeable with inventory and the GARBAGE_COLLECT flag set.
//! @param oObject An object.
int IsEligible(object oObject);
int IsEligible(object oObject)
{
if (!GetObjectFlag(oObject, GARBAGE_COLLECT))
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;
return TRUE;
}
// -----------------------------------------------------------------------------
//! @brief Remove the GC timestamp from oObject.
//! @param oObject A tracked item.
void UntrackItem(object oObject);
void UntrackItem(object oObject)
{
DeleteLocalInt(oObject, GC_PLC_TIMESTAMP);
}
// -----------------------------------------------------------------------------
//! @brief Destroy items in oPlaceable that have exceeded GC_PLC_DURATION.
//! @param oPlaceable An eligible placeable.
void DeleteItems(object oPlaceable);
void DeleteItems(object oPlaceable)
{
int nNow = GetTimeStamp();
object oItem = GetFirstItemInInventory(oPlaceable);
while (GetIsObjectValid(oItem))
{
int nStart = GetLocalInt(oItem, GC_PLC_TIMESTAMP);
if (nStart == 0)
SetLocalInt(oItem, GC_PLC_TIMESTAMP, GetTimeStamp());
else
{
int nMaxAge = GetRecursiveInt(oPlaceable, GC_PLC_DURATION, DEFAULT_DURATION);
nMaxAge = max(nMaxAge, 1);
nMaxAge = nMaxAge * 60;
int nSeconds = nNow - nStart;
if (nSeconds > 0 && nSeconds >= nMaxAge)
{
LogInfo("Placeable Garbage Collector: Removal of " + GetObjectInfo(oItem)
+ " (age: " + IntToString(nSeconds)
+ ", max age: " + IntToString(nMaxAge) + ")");
DestroyObject(oItem, 0.0f);
}
}
oItem = GetNextItemInInventory(oItem);
}
}
// -----------------------------------------------------------------------------
//! @brief Stamp a GC timestamp on every untracked item in oPlaceable.
//! @param oPlaceable An eligible placeable.
void TrackItems(object oPlaceable);
void TrackItems(object oPlaceable)
{
object oItem = GetFirstItemInInventory(oPlaceable);
while (GetIsObjectValid(oItem))
{
if (!GetLocalInt(oItem, GC_PLC_TIMESTAMP))
SetLocalInt(oItem, GC_PLC_TIMESTAMP, GetTimeStamp());
oItem = GetNextItemInInventory(oItem);
}
}
// -----------------------------------------------------------------------------
void main()
{
object oModule = GetModule();
if (!GetModuleFlag(ENABLE__FF_U_GC_PLC, TRUE))
return;
string sEvent = GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
SubscribeToEvent(ON_DEFAULT_ITEM_ACQUIRE, __FILE__);
SubscribeToEvent(ON_AFTER_PLACEABLE_CLOSE, __FILE__);
SubscribeToEvent(ON_BEFORE_PLACEABLE_OPEN, __FILE__);
}
else if (sEvent == ON_DEFAULT_ITEM_ACQUIRE)
UntrackItem(GetModuleItemAcquired());
else if (sEvent == ON_BEFORE_PLACEABLE_OPEN && IsEligible(OBJECT_SELF))
DeleteItems(OBJECT_SELF);
else if (sEvent == ON_AFTER_PLACEABLE_CLOSE && IsEligible(OBJECT_SELF))
TrackItems(OBJECT_SELF);
}