ff_u_v_cycle_loc
Lock doors and placeables at specific times (dawn, day, dusk, night).
Doors and non-static placeables with at least one CYCLE_LOCK_* variable
are locked during the selected periods, and unlocked otherwise. Objects are
updated when a player enters their area, and, in the areas that have players,
every game hour and whenever the framework changes the game time
(ON_CALENDAR_TIME_CHANGED, signalled for instance by
ff_u_cal_p_time when it restores the saved time).
An object already in the expected state (locked or unlocked) is left as is.
When locked, an open door is closed first, and the lock requires the key KEY. When unlocked, no key is required.
Variables
ENABLE__FF_U_V_CYCLE_LOCK: (string) (opt-out) Set to "N" on module to disable the unit.
CYCLE_LOCK_DAWN: (int) Set to 1 on the door or placeable to lock it at dawn.
CYCLE_LOCK_DAY: (int) Set to 1 on the door or placeable to lock it during the day.
CYCLE_LOCK_DUSK: (int) Set to 1 on the door or placeable to lock it at dusk.
CYCLE_LOCK_NIGHT: (int) Set to 1 on the door or placeable to lock it during the night.
KEY: (string) Tag of the key that opens the lock. Defaults to dummy.
Examples
Set CYCLE_LOCK_DUSK and CYCLE_LOCK_NIGHT to 1 on a shop door to
lock it from dusk to dawn. Set KEY to shop_key so the shopkeeper’s
key opens it.
Source code
// @code
#include "ff_i_core"
const string ENABLE__FF_U_V_CYCLE_LOCK = "ENABLE__FF_U_V_CYCLE_LOCK";
const string KEY = "KEY";
const string DEFAULT_KEY = "dummy";
// -----------------------------------------------------------------------------
//! @brief Lock or unlock oObject from its CYCLE_LOCK_* local variables and the current time.
//! Objects other than doors and non-static placeables, without any CYCLE_LOCK_* variable,
//! or already in the expected state, are left as is.
//! @param oObject A door or a placeable.
void LockObject(object oObject);
void LockObject(object oObject)
{
int nType = GetObjectType(oObject);
if (nType == OBJECT_TYPE_DOOR)
{}
else if (nType == OBJECT_TYPE_PLACEABLE)
{
if (NWNX_Object_GetPlaceableIsStatic(oObject))
return;
}
else
return;
int nDawn = GetLocalInt(oObject, "CYCLE_LOCK_DAWN");
int nDay = GetLocalInt(oObject, "CYCLE_LOCK_DAY");
int nDusk = GetLocalInt(oObject, "CYCLE_LOCK_DUSK");
int nNight = GetLocalInt(oObject, "CYCLE_LOCK_NIGHT");
if (nDawn || nDay || nDusk || nNight)
{}
else
return;
int nLock = FALSE;
nLock |= (GetIsDawn() && nDawn);
nLock |= (GetIsDay() && nDay);
nLock |= (GetIsDusk() && nDusk);
nLock |= (GetIsNight() && nNight);
// Already in the expected state
if (GetLocked(oObject) == nLock)
return;
if (nLock)
{
string sKey = GetLocalString(oObject, KEY);
if (sKey == "")
sKey = DEFAULT_KEY;
if (nType == OBJECT_TYPE_DOOR && GetIsOpen(oObject))
AssignCommand(oObject, ActionCloseDoor(oObject));
SetLockKeyTag(oObject, sKey);
SetLockKeyRequired(oObject, TRUE);
SetLocked(oObject, TRUE);
}
else
{
SetLocked(oObject, FALSE);
SetLockKeyRequired(oObject, FALSE);
}
}
// -----------------------------------------------------------------------------
//! @brief Call LockObject on every object in oArea (skipped when the area has no players).
//! @param oArea An area.
void LockArea(object oArea);
void LockArea(object oArea)
{
int nCount = NWNX_Area_GetNumberOfPlayersInArea(oArea);
if (nCount == 0)
return;
object oObject = GetFirstObjectInArea(oArea);
while (GetIsObjectValid(oObject))
{
LockObject(oObject);
oObject = GetNextObjectInArea(oArea);
}
}
// -----------------------------------------------------------------------------
//! @brief Call LockArea on every area that has players.
void LockModule();
void LockModule()
{
// Instead of looping through all areas, just loop on players
object oPC = GetFirstPC();
while (GetIsObjectValid(oPC))
{
DelayCommand(GetRandomMaxDelay(MINUTE_MAX_DELAY), LockArea(GetArea(oPC)));
oPC = GetNextPC();
}
}
// -----------------------------------------------------------------------------
void main()
{
string sEvent = NWNX_Events_GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
if (!GetModuleFlag(ENABLE__FF_U_V_CYCLE_LOCK, TRUE))
return;
SubscribeToEvent(ON_DEFAULT_AREA_ENTER, __FILE__);
SubscribeToEvent(ON_CALENDAR_HOUR, __FILE__);
SubscribeToEvent(ON_CALENDAR_TIME_CHANGED, __FILE__);
}
else if (sEvent == ON_DEFAULT_AREA_ENTER)
LockArea(OBJECT_SELF);
else if (sEvent == ON_CALENDAR_HOUR)
LockModule();
else if (sEvent == ON_CALENDAR_TIME_CHANGED) // This event is only sent manually.
LockModule();
}