RATDOG/_module/nss/spawn_functions.nss
Jaysyn904 269eca1d1e Encounter work
Separated static spawns in "Forest of Hope: Central".  Fixed faction issues with Corrak's Crew.  Added "Faction Zoo" area for future faction work.  Tweaked factions.  Made sure creatures with CODI AI were granting XP.  Tweaked Masterwork weapons.  Fixed Warforged appearance not showing up properly in toolset.
2022-12-04 12:37:44 -05:00

3337 lines
105 KiB
Plaintext

//
// NESS V8.1.3
// Spawn Functions
//
// Do NOT Modify this File
// See 'spawn__readme' for Instructions
//
#include "spawn_timefuncs"
#include "spawn_flags"
#include "spawn_cfg_cusflg"
#include "x0_i0_corpses"
//
//void main (){}
//
void InitFlags(object oSpawn, string sSpawnName, string sSpawnTag);
int SetSpawns(location lBase);
string PadIntToString(int nInt, int nDigits);
void ResetSpawn(object oSpawn, int nTimeNow);
int IsRestoreBlocked(object oSpawn, location lChildLoc, int iExpireTime,
int nTimeNow);
void SetupSpawned(object oSpawn, object oSpawned, location lHome, int nTimeNow,
int nWalkToHome = FALSE);
void SetupCampSpawned(object oSpawn, object oSpawned, vector vCampPosition,
location lHome, string sFlags);
// Returns new nNextSpawnTime
int SetupSpawnDelay(int nSpawnDelay, int nDelayMinimum, int nDelayRandom,
int nTimeNow);
// Writes all the necessary info onto a spawn and its child after spawning
void RecordSpawned(object oSpawn, object oSpawned, location lHome,
location lEntranceExit, float fSpawnedFacing);
// Saves the state of one child onto the spawn (or a camp object) for respawning
void SaveStateOnDespawn(object oSpawned, object oSpawn, int nCamp=FALSE);
// Saves a camp object onto the spawn for respawning
void SaveCampStateOnDespawn(object oCamp, object oSpawn);
// Respawns all saved children/camps
void RestorePCDespawns(object oSpawn, int nTimeNow);
void ReturnHome(location lHome);
int FindNextEmptyChildSlot(object oSpawn);
//
// Pseudo-heartbeat support
//
const string SPAWN_INTERVAL = "Spawn_Interval";
const string SPAWN_PCS_IN_AREA = "Spawn_PCsInArea";
const string SPAWN_AREA_COUNT = "AreaSpawnCount";
const string SPAWN_HEARTBEAT_SCRIPT = "SpawnHeartbeatScript";
const string SPAWN_HEARTBEAT_SCHEDULED = "SpawnHeartbeatScheduled";
// This checks conditions to determine if a pseudo-heartbeat should be called
int NeedPseudoHeartbeat( object oArea );
// ... and if it should, this schedules it.
void ScheduleNextPseudoHeartbeat( object oArea );
// Pseudo-heartbeat area enter and exit functions
void Spawn_OnAreaEnter( string sHeartbeatScript = "spawn_sample_hb",
float fHeartbeatInterval = 6.0, float fFirstDelay = 0.0 );
void Spawn_OnAreaExit();
// Externals
void LootTable(object oSpawn, object oSpawned, int nLootTable);
effect ObjectEffect(object oSpawn);
int SPAWN_DELAY_DEBUG = FALSE;
int SPAWN_COUNT_DEBUG = FALSE;
int CONSOLE_DEBUG = TRUE;
void SpawnDelayDebug(object oSpawn, string str)
{
if (SPAWN_DELAY_DEBUG)
{
WriteTimestampedLogEntry("[sd " + GetName(GetArea(oSpawn)) + "] " +
GetLocalString(oSpawn, "f_Template") + " (" + ObjectToString(oSpawn) + "): " + str);
if (CONSOLE_DEBUG)
{
SendMessageToAllDMs("[sd " + GetName(GetArea(oSpawn)) + "] "
+ GetLocalString(oSpawn, "f_Template") + " (" + ObjectToString(oSpawn) + "): " + str);
}
/*
object oPC = GetFirstPC();
if (! GetIsDM(oPC))
SendMessageToPC(oPC, str);
*/
}
}
void SpawnCountDebug(object oSpawn, string str)
{
if (SPAWN_COUNT_DEBUG)
{
WriteTimestampedLogEntry("[sc " + GetName(GetArea(oSpawn)) + "] " +
GetLocalString(oSpawn, "f_Template") + " (" +ObjectToString(oSpawn) + "): " + str);
if (CONSOLE_DEBUG)
{
SendMessageToAllDMs("[sc " + GetName(GetArea(oSpawn)) + "] "
+ GetLocalString(oSpawn, "f_Template") + " (" +ObjectToString(oSpawn) + "): " + str);
}
/*
object oPC = GetFirstPC();
if (! GetIsDM(oPC))
SendMessageToPC(oPC, str);
*/
}
}
//
// Custom Functions
//
object GetChildByTag(object oSpawn, string sChildTag);
object GetChildByNumber(object oSpawn, int nChildNum);
object GetSpawnByID(int nSpawnID);
void DeactivateSpawn(object oSpawn);
void DeactivateSpawnsByTag(string sSpawnTag);
void DeactivateAllSpawns();
void DespawnChildren(object oSpawn);
void DespawnChildrenByTag(object oSpawn, string sSpawnTag);
void AddChild(object oSpawn, object oSpawned);
void ReportSpawns(int nAreaSpawns, int nModuleSpawns);
void TrackModuleSpawns(int nAreaSpawnCount, int nTrackModuleSpawns);
void DumpModuleSpawns();
void DumpModuleSpawns();
//
// PC and NPC Functions
//
int CountPCsInArea(object oArea = OBJECT_INVALID, int nDM = FALSE);
int CountPCsInRadius(location lCenter, float fRadius, int nDM = FALSE);
object GetRandomPCInArea(object oArea, object oSpawn);
// This struct is returned by TransferAllInventorySlots() to return back the
// object ids of the armor, right hand weapon, and left hand weapons (if any)
// both left on the (original) corpse and copied to the lootable corpse
struct NESS_CorpseInfo
{
object origLftWpn;
object origRgtWpn;
object origArmor;
object lootLftWpn;
object lootRgtWpn;
object lootArmor;
};
// This is equivalent to (and adapted from) the Bioware LootInventorySlots() function.
// However, it does not schedule deletions for a hardcoded
// corpse decay time later (the corpse decay script handles those).
struct NESS_CorpseInfo TransferAllInventorySlots(object oCreature, object oTarget,
int bDropWielded=FALSE);
int IsCreatureItem(object oItem);
void RandomWalk(object oSpawn, float fWalkingRadius, int nRun);
void FindSeat(object oSpawn, object oSpawned);
void NESS_CleanInventory(object oSpawned);
// for back compatibility (grr) will remove at some point
void CleanInventory(object oSpawned)
{
NESS_CleanInventory(oSpawned);
}
void NESS_CleanEquipped(object oSpawned);
void NESS_CleanCorpse(object oSpawned);
object NESS_CopyCorpseItem(object oSource, object oInventory);
void StripNonDroppables(object oSpawned);
void DestroyIfNonDrop(object oItem);
//
// Date and Time Functions
//
int IsBetweenDays(int nCheckDay, int nDayStart, int nDayEnd);
int IsBetweenHours(int nCheckHour, int nHourStart, int nHourEnd);
//
// Patrol Route Functions
//
void SetPatrolRoute(int nPatrolRoute, int nStartClosest=FALSE);
void DoPatrolRoute(int nPatrolRoute, int nRouteType);
void AddPatrolStop(int nPatrolRoute, int nStopNumber, int bJump=FALSE);
void CheckForStuckPatrol(object oCreature, int nPatrolRoute, int nRouteType);
//
// Camp Functions
//
int ProcessCamp(object oCamp);
void DestroyCamp(object oCamp, float fCampDecay, int nSaveState);
//
// Outside Functions
//
void SpawnFlags(object oSpawn, int nFlagTableNumber);
//
//
// Functions for External Use.
object NESS_GetSpawnByID(int nSpawnID, object oArea);
void NESS_ActivateSpawnByID(int nSpawnID, object oAreaD);
void NESS_DeactivateSpawnByID(int nSpawnID, object oArea);
void NESS_ActivateSpawn(object oSpawn);
void NESS_DeactivateSpawn(object oSpawn);
void NESS_ForceProcess(object oSpawn);
void NESS_TrackModuleSpawns(int flag=TRUE);
int NESS_IsModuleSpawnTracking();
void NESS_DumpModuleSpawns(int flag=TRUE);
int NESS_IsModuleSpawnDumping();
void NESS_ReturnHome(object oCreature, int bRun=FALSE);
void NESS_ProcessDeadCreature(object oCreature, object oSpawn=OBJECT_INVALID);
// This Function Initializes the Flags
void InitFlags(object oSpawn, string sSpawnName, string sSpawnTag)
{
// These are true when certain flags are present, false otherwise
// Retreive Defaults
object oModule = GetModule();
// These have values associated with them, although in some cases value
// of 0 is treated as a non-existent flag
int dfProcessFrequency = GetLocalInt(oModule, "df_processFrequency");
int dfProcessOffset = GetLocalInt(oModule, "df_processOffest");
int dfInitialState = GetLocalInt(oModule, "df_InitialState");
int dfInitialDelay = GetLocalInt(oModule, "df_InitialDelay");
int dfFlagTableNumber = GetLocalInt(oModule, "df_FlagTableNumber");
int dfSpawnDelay = GetLocalInt(oModule, "df_SpawnDelay");
int dfDelayMinimum = GetLocalInt(oModule, "df_DelayMinimum");
int dfSpawnNumber = GetLocalInt(oModule, "df_SpawnNumber");
int dfSpawnNumberMin = GetLocalInt(oModule, "df_SpawnNumberMin");
int dfSpawnNumberAtOnce = GetLocalInt(oModule, "df_SpawnNumberAtOnce");
int dfSpawnNumberAtOnceMin = GetLocalInt(oModule, "df_SpawnNumberAtOnceMin");
int dfSpawnDayStart = GetLocalInt(oModule, "df_SpawnDayStart");
int dfSpawnDayEnd = GetLocalInt(oModule, "df_SpawnDayEnd");
int dfSpawnHourStart = GetLocalInt(oModule, "df_SpawnHourStart");
int dfSpawnHourEnd = GetLocalInt(oModule, "df_SpawnHourEnd");
int dfWanderRange = GetLocalInt(oModule, "df_WanderRange");
int dfReturnHomeRange = GetLocalInt(oModule, "df_ReturnHomeRange");
int dfPCCheckDelay = GetLocalInt(oModule, "df_PCCheckDelay");
int dfRandomGold = GetLocalInt(oModule, "df_RandomGold");
int dfRandomGoldMin = GetLocalInt(oModule, "df_RandomGoldMin");
int dfGoldChance = GetLocalInt(oModule, "df_GoldChance");
int dfSpawnEffect = GetLocalInt(oModule, "df_SpawnEffect");
int dfDespawnEffect = GetLocalInt(oModule, "df_DespawnEffect");
int dfPatrolRoute = GetLocalInt(oModule, "df_PatrolRoute");
int dfRouteType = GetLocalInt(oModule, "df_RouteType");
int dfPlaceableType = GetLocalInt(oModule, "df_PlaceableType");
int dfTrapDisabled = GetLocalInt(oModule, "df_TrapDisabled");
int dfPlaceableRefreshPeriod = GetLocalInt(oModule, "df_PlaceableRefreshPeriod");
int dfLootTable = GetLocalInt(oModule, "df_LootTable");
int dfLootTable1ItemChance = GetLocalInt(oModule, "df_LootTable1ItemChance");
int dfLootTable2ItemChance = GetLocalInt(oModule, "df_LootTable2ItemChance");
int dfLootTable3ItemChance = GetLocalInt(oModule, "df_LootTable3ItemChance");
int dfDeactivateSpawn = GetLocalInt(oModule, "df_DeactivateSpawn");
int dfDeactivateScript = GetLocalInt(oModule, "df_DeactivateScript");
int dfDeactivationInfo = GetLocalInt(oModule, "df_DeactivationInfo");
int dfChildLifespanMax = GetLocalInt(oModule, "df_ChildLifespanMax");
int dfChildLifespanMin = GetLocalInt(oModule, "df_ChildLifespanMin");
int dfSpawnRadius = GetLocalInt(oModule, "df_SpawnRadius");
int dfSpawnRadiusMin = GetLocalInt(oModule, "df_SpawnRadiusMin");
int dfSpawnUnseen = GetLocalInt(oModule, "df_SpawnUnseen");
int dfUnseenRetryCount = GetLocalInt(oModule, "df_dfUnseenRetryCount");
int dfCorpseDecay = GetLocalInt(oModule, "df_CorpseDecay");
int dfCorpseDecayType = GetLocalInt(oModule, "df_CorpseDecayType");
int dfCorpseRemainsType = GetLocalInt(oModule, "df_CorpseRemainsType");
int dfCampDecay = GetLocalInt(oModule, "df_CampDecay");
int dfSpawnScript = GetLocalInt(oModule, "df_SpawnScript");
int dfDespawnScript = GetLocalInt(oModule, "df_DespawnScript");
int dfDeathScript = GetLocalInt(oModule, "df_DeathScript");
int dfSpawnCheckCustom = GetLocalInt(oModule, "df_SpawnCheckCustom");
int dfSpawnCheckPCs = GetLocalInt(oModule, "df_SpawnCheckPCs");
int dfCheckPCsRadius = GetLocalInt(oModule, "f_CheckPCsRadius");
int dfSpawnTrigger = GetLocalInt(oModule, "df_SpawnTrigger");
int dfDespawnTrigger = GetLocalInt(oModule, "df_DespawnTrigger");
int dfSpawnAreaEffect = GetLocalInt(oModule, "df_SpawnAreaEffect");
int dfAreaEffectDuration = GetLocalInt(oModule, "df_AreaEffectDuration");
int dfObjectEffect = GetLocalInt(oModule, "df_ObjectEffect");
int dfObjectEffectDuration = GetLocalInt(oModule, "df_ObjectEffectDuration");
int dfRandomSpawn = GetLocalInt(oModule, "df_RandomSpawn");
int dfSpawnFaction = GetLocalInt(oModule, "df_SpawnFaction");
int dfSpawnAlignment = GetLocalInt(oModule, "df_SpawnAlignment");
int dfAlignmentShift = GetLocalInt(oModule, "df_AlignmentShift");
int dfHeartbeatScript = GetLocalInt(oModule, "df_HeartbeatScript");
int dfSpawnLocation = GetLocalInt(oModule, "df_SpawnLocation");
int dfSpawnLocationMin = GetLocalInt(oModule, "df_SpawnLocationMin");
int dfSpawnFacing = GetLocalInt(oModule, "df_SpawnFacing");
int dfEntranceExit = GetLocalInt(oModule, "df_EntranceExit");
int dfEntranceExitMin = GetLocalInt(oModule, "df_EntranceExitMin");
int dfExit = GetLocalInt(oModule, "df_Exit");
int dfExitMin = GetLocalInt(oModule, "df_ExitMin");
int dfHealChildren = GetLocalInt(oModule, "df_HealChildren");
int dfGlobalSuppressDR = GetLocalInt(oModule, "df_GlobalSuppressDR");
int dfSuppressDR = GetLocalInt(oModule, "df_SuppressDR");
int dfEncounterLevel = GetLocalInt(oModule, "df_EncounterLevel");
//debug("init flags: " + sSpawnName);
SetLocalString(oSpawn, "f_Flags", sSpawnName);
SetLocalString(oSpawn, "f_Template", sSpawnTag);
// Initialize FlagTable
int nFlagTable = IsFlagPresent(sSpawnName, "_FT");
int nFlagTableNumber = GetFlagValue(sSpawnName, "_FT", dfFlagTableNumber);
if (nFlagTable == TRUE)
{
SpawnFlags(oSpawn, nFlagTableNumber);
if (GetStringLeft(GetLocalString(oSpawn, "f_Flags"), 2) == "SP")
{
sSpawnName = GetLocalString(oSpawn, "f_Flags");
}
else if (GetStringLeft(GetLocalString(oSpawn, "f_Flags"), 1) == "_")
{
sSpawnName = sSpawnName + GetLocalString(oSpawn, "f_Flags");
}
SetLocalString(oSpawn, "f_Flags", sSpawnName);
sSpawnTag = GetLocalString(oSpawn, "f_Template");
}
// Initialize CustomFlag
string sCustomFlag;
int nCustomFlag = IsFlagPresent(sSpawnName, "CF");
if (nCustomFlag == TRUE)
{
sCustomFlag = GetStringRight(sSpawnName, GetStringLength(sSpawnName) -
(FindSubString(sSpawnName, "CF") + 2));
sSpawnName = GetStringLeft(sSpawnName, GetStringLength(sSpawnName) -
(GetStringLength(sCustomFlag) + 3));
SetLocalString(oSpawn, "f_Flags", sSpawnName);
}
// Record CustomFlag
SetLocalString(oSpawn, "f_CustomFlag", sCustomFlag);
ParseCustomFlags(oSpawn, sCustomFlag);
// Initialize Process Frequency
int nProcessFrequency = GetFlagValue(sSpawnName, "SP", dfProcessFrequency);
int nProcessOffset = GetSubFlagValue(sSpawnName, "SP", "O", dfProcessOffset);
if (nProcessFrequency <= 0)
{
nProcessFrequency = 1;
}
// Record Process Frequency
SetLocalInt(oSpawn, "f_ProcessFrequency", nProcessFrequency);
SetLocalInt(oSpawn, "f_ProcessOffset", nProcessOffset);
// Initialize InitialState
int nInitialState = GetFlagValue(sSpawnName, "IS", dfInitialState);
int nInitialDelay = GetSubFlagValue(sSpawnName, "IS", "D", dfInitialDelay);
nInitialDelay *= 60; // convert to seconds
// Record InitialState
SetLocalInt(oSpawn, "f_InitialState", nInitialState);
SetLocalInt(oSpawn, "f_InitialDelay", nInitialDelay);
// Initialize SpawnID
int nSpawnID = GetFlagValue(sSpawnName, "ID", 0);
// Record SpawnID
if (nSpawnID > 0)
{
SetLocalInt(oSpawn, "SpawnID", nSpawnID);
}
// Initialize SpawnDelay
int nSpawnDelay = GetFlagValue(sSpawnName, "SD", dfSpawnDelay);
nSpawnDelay *= 60; // convert to seconds
int nDelayRandom = IsSubFlagPresent(sSpawnName, "SD", "M");
int nDelayMinimum = GetSubFlagValue(sSpawnName, "SD", "M", dfDelayMinimum);
nDelayMinimum *= 60; // convert to seconds
int nSpawnDelayPeriodic = IsSubFlagPresent(sSpawnName, "SD", "P");
if (nDelayMinimum > nSpawnDelay)
{
nDelayRandom = FALSE;
nDelayMinimum = 0;
}
// Record SpawnDelay
SetLocalInt(oSpawn, "f_SpawnDelay", nSpawnDelay);
SetLocalInt(oSpawn, "f_DelayRandom", nDelayRandom);
SetLocalInt(oSpawn, "f_DelayMinimum", nDelayMinimum);
SetLocalInt(oSpawn, "f_SpawnDelayPeriodic", nSpawnDelayPeriodic);
// Initialize SpawnNumber
int nSpawnNumber = GetFlagValue(sSpawnName, "SN", dfSpawnNumber);
int nSpawnNumberMax = nSpawnNumber;
int nSpawnNumberMin = GetSubFlagValue(sSpawnName, "SN", "M", dfSpawnNumberMin);
int nSpawnAllAtOnce = IsFlagPresent(sSpawnName, "SA");
int nSpawnNumberAtOnce = GetFlagValue(sSpawnName, "SA", dfSpawnNumberAtOnce);
int nSpawnNumberAtOnceMin = GetSubFlagValue(sSpawnName, "SA", "M",
dfSpawnNumberAtOnceMin);
if (nSpawnNumberMin > nSpawnNumber)
{
nSpawnNumberMin = -1;
}
if (nSpawnNumberMin > -1)
{
int nRndSpawnNumber = Random(nSpawnNumberMax + 1);
while (nRndSpawnNumber < nSpawnNumberMin)
{
nRndSpawnNumber = Random(nSpawnNumberMax + 1);
}
nSpawnNumber = nRndSpawnNumber;
}
if (nSpawnNumberAtOnce == 1)
{
nSpawnAllAtOnce = FALSE;
}
if (nSpawnNumberAtOnceMin > nSpawnNumberAtOnce)
{
nSpawnNumberAtOnceMin = 0;
}
// Record SpawnNumber
SetLocalInt(oSpawn, "f_SpawnNumber", nSpawnNumber);
SetLocalInt(oSpawn, "f_SpawnNumberMin", nSpawnNumberMin);
SetLocalInt(oSpawn, "f_SpawnNumberMax", nSpawnNumberMax);
SetLocalInt(oSpawn, "f_SpawnAllAtOnce", nSpawnAllAtOnce);
SetLocalInt(oSpawn, "f_SpawnNumberAtOnce", nSpawnNumberAtOnce);
SetLocalInt(oSpawn, "f_SpawnNumberAtOnceMin", nSpawnNumberAtOnceMin);
// Initialize Day/Night Only
int nDayOnly = IsFlagPresent(sSpawnName, "DO");
int nDayOnlyDespawn = IsSubFlagPresent(sSpawnName, "DO", "D");
int nNightOnly = IsFlagPresent(sSpawnName, "NO");
int nNightOnlyDespawn = IsSubFlagPresent(sSpawnName, "NO", "D");
// Record Day/Night Only
SetLocalInt(oSpawn, "f_DayOnly", nDayOnly);
SetLocalInt(oSpawn, "f_DayOnlyDespawn", nDayOnlyDespawn);
SetLocalInt(oSpawn, "f_NightOnly", nNightOnly);
SetLocalInt(oSpawn, "f_NightOnlyDespawn", nNightOnlyDespawn);
// Initialize Day/Hour Spawns
int nSpawnDayStart = GetFlagValue(sSpawnName, "DY", dfSpawnDayStart);
int nSpawnDayEnd = GetSubFlagValue(sSpawnName, "DY", "T", dfSpawnDayEnd);
if (nSpawnDayEnd > nSpawnDayStart)
{
nSpawnDayEnd = -1;
}
int nSpawnHourStart = GetFlagValue(sSpawnName, "HR", dfSpawnHourStart);
int nSpawnHourEnd = GetSubFlagValue(sSpawnName, "HR", "T", dfSpawnHourEnd);
if (nSpawnHourStart > nSpawnHourEnd)
{
nSpawnHourEnd = -1;
}
// Record Day/Hour Spawns
SetLocalInt(oSpawn, "f_SpawnDayStart", nSpawnDayStart);
SetLocalInt(oSpawn, "f_SpawnDayEnd", nSpawnDayEnd);
SetLocalInt(oSpawn, "f_SpawnHourStart", nSpawnHourStart);
SetLocalInt(oSpawn, "f_SpawnHourEnd", nSpawnHourEnd);
// Initialize RandomWalk
int nRandomWalk = IsFlagPresent(sSpawnName, "RW");
float fWanderRange = IntToFloat(GetSubFlagValue(sSpawnName, "RW", "R", dfWanderRange));
// Record RandomWalk
SetLocalInt(oSpawn, "f_RandomWalk", nRandomWalk);
SetLocalFloat(oSpawn, "f_WanderRange", fWanderRange);
// Initialize ReturnHome
int nReturnHome = IsFlagPresent(sSpawnName, "RH");
float fReturnHomeRange = IntToFloat(GetFlagValue(sSpawnName, "RH", dfReturnHomeRange));
// Record ReturnHome
SetLocalInt(oSpawn, "f_ReturnHome", nReturnHome);
SetLocalFloat(oSpawn, "f_ReturnHomeRange", fReturnHomeRange);
// Initialize PCCheck
int nPCCheck = IsFlagPresent(sSpawnName, "PC");
int nPCCheckDelay = GetFlagValue(sSpawnName, "PC", dfPCCheckDelay);
nPCCheckDelay *= 60; // convert to seconds
int nPCReset = IsSubFlagPresent(sSpawnName, "PC", "R");
// Record PCCheck
SetLocalInt(oSpawn, "f_PCCheck", nPCCheck);
SetLocalInt(oSpawn, "f_PCCheckDelay", nPCCheckDelay);
SetLocalInt(oSpawn, "f_PCReset", nPCReset);
// Initialize RandomGold
int nRandomGold = GetFlagValue(sSpawnName, "RG", dfRandomGold);
int nRandomGoldMin = GetSubFlagValue(sSpawnName, "RG", "M", dfRandomGoldMin);
int nGoldChance = GetSubFlagValue(sSpawnName, "RG", "C", dfGoldChance);
// Record RandomGold
SetLocalInt(oSpawn, "f_RandomGold", nRandomGold);
SetLocalInt(oSpawn, "f_RandomGoldMin", nRandomGoldMin);
SetLocalInt(oSpawn, "f_GoldChance", nGoldChance);
// Initialize SpawnEffects
int nSpawnEffect = GetFlagValue(sSpawnName, "FX", dfSpawnEffect);
int nDespawnEffect = GetSubFlagValue(sSpawnName, "FX", "D", dfDespawnEffect);
// Record SpawnEffects
SetLocalInt(oSpawn, "f_SpawnEffect", nSpawnEffect);
SetLocalInt(oSpawn, "f_DespawnEffect", nDespawnEffect);
// Initialize PatrolRoutes
int nPatrolRoute = GetFlagValue(sSpawnName, "PR", dfPatrolRoute);
int nRouteType = GetSubFlagValue(sSpawnName, "PR", "T", dfRouteType);
int nStartAtClosest = IsSubFlagPresent(sSpawnName, "PR", "C");
// Record PatrolRoutes
SetLocalInt(oSpawn, "f_PatrolRoute", nPatrolRoute);
SetLocalInt(oSpawn, "f_RouteType", nRouteType);
SetLocalInt(oSpawn, "f_PatrolStartAtClosest", nStartAtClosest);
// Initialize Placeables
int nPlaceable = IsFlagPresent(sSpawnName, "PL");
int nPlaceableType = GetFlagValue(sSpawnName, "PL", dfPlaceableType);
int nTrapDisabled = GetSubFlagValue(sSpawnName, "PL", "T", dfTrapDisabled);
int nPlaceableRefreshPeriod = GetSubFlagValue(sSpawnName, "PL", "P", dfPlaceableRefreshPeriod);
nPlaceableRefreshPeriod *= 60; // convert to seconds
// Record Placeables
SetLocalInt(oSpawn, "f_Placeable", nPlaceable);
SetLocalInt(oSpawn, "f_PlaceableType", nPlaceableType);
SetLocalInt(oSpawn, "f_TrapDisabled", nTrapDisabled);
SetLocalInt(oSpawn, "f_PlaceableRefreshPeriod", nPlaceableRefreshPeriod);
// Initialize SpawnGroups
int nSpawnGroup = IsFlagPresent(sSpawnName, "SG");
// Record SpawnGroups
SetLocalInt(oSpawn, "f_SpawnGroup", nSpawnGroup);
// Initialize LootTable
int nLootTable = GetFlagValue(sSpawnName, "LT", dfLootTable);
int nLootTable1ItemChance = GetSubFlagValue(sSpawnName, "LT", "A", dfLootTable1ItemChance);
int nLootTable2ItemChance = GetSubFlagValue(sSpawnName, "LT", "B", dfLootTable2ItemChance);
int nLootTable3ItemChance = GetSubFlagValue(sSpawnName, "LT", "C", dfLootTable3ItemChance);
if (nLootTable1ItemChance > 100) nLootTable1ItemChance = 100;
if (nLootTable2ItemChance > 100) nLootTable2ItemChance = 100;
if (nLootTable3ItemChance > 100) nLootTable3ItemChance = 100;
// Record LootTable
SetLocalInt(oSpawn, "f_LootTable", nLootTable);
SetLocalInt(oSpawn, "f_LootTable1ItemChance", nLootTable1ItemChance);
SetLocalInt(oSpawn, "f_LootTable2ItemChance", nLootTable2ItemChance);
SetLocalInt(oSpawn, "f_LootTable3ItemChance", nLootTable3ItemChance);
// Initialize SpawnDeactivation
int nDeactivateSpawn = GetFlagValue(sSpawnName, "DS", dfDeactivateSpawn);
int nDeactivateScript = GetSubFlagValue(sSpawnName, "DS", "S", dfDeactivateScript);
int nDeactivationInfo = GetFlagValue(sSpawnName, "DI", dfDeactivationInfo);
// Record SpawnDeactivations
SetLocalInt(oSpawn, "f_DeactivateSpawn", nDeactivateSpawn);
SetLocalInt(oSpawn, "f_DeactivateScript", nDeactivateScript);
if (nDeactivateSpawn == 4)
{
nDeactivationInfo *= 60; // convert minutes to seconds
}
else if (nDeactivateSpawn == 5)
{
nDeactivationInfo *= 6; // convert cycles to seconds
}
SetLocalInt(oSpawn, "f_DeactivationInfo", nDeactivationInfo);
// Initialize ChildLifespan
int nChildLifespanMax = GetFlagValue(sSpawnName, "CL", dfChildLifespanMax);
nChildLifespanMax *= 60; // convert to seconds
int nChildLifespanMin = GetSubFlagValue(sSpawnName, "CL", "M", dfChildLifespanMin);
nChildLifespanMin *= 60; // convert to seconds
if (nChildLifespanMin > nChildLifespanMax)
{
nChildLifespanMin = -1;
}
// Record ChildLifespan
SetLocalInt(oSpawn, "f_ChildLifespanMax", nChildLifespanMax);
SetLocalInt(oSpawn, "f_ChildLifespanMin", nChildLifespanMin);
// Initialize SpawnRadius
float fSpawnRadius = IntToFloat(GetFlagValue(sSpawnName, "SR", dfSpawnRadius));
float fSpawnRadiusMin = IntToFloat(GetSubFlagValue(sSpawnName, "SR", "M", dfSpawnRadiusMin));
int nSpawnNearPCs = IsSubFlagPresent(sSpawnName, "SR", "P");
if (fSpawnRadiusMin > fSpawnRadius)
{
fSpawnRadiusMin = 0.0;
}
// Record SpawnRadius
SetLocalFloat(oSpawn, "f_SpawnRadius", fSpawnRadius);
SetLocalFloat(oSpawn, "f_SpawnRadiusMin", fSpawnRadiusMin);
SetLocalInt(oSpawn, "f_SpawnNearPCs", nSpawnNearPCs);
// Initialize SpawnUnseen
float fSpawnUnseen = IntToFloat(GetFlagValue(sSpawnName, "SU", dfSpawnUnseen));
int nUnseenIndividual = IsSubFlagPresent(sSpawnName, "SU", "I");
int nUnseenRetryCount = GetSubFlagValue(sSpawnName, "SU", "I", dfUnseenRetryCount);
// Record SpawnUnseen
SetLocalFloat(oSpawn, "f_SpawnUnseen", fSpawnUnseen);
SetLocalInt(oSpawn, "f_UnseenIndividual", nUnseenIndividual);
SetLocalInt(oSpawn, "f_UnseenRetryCount", nUnseenRetryCount);
// Initialize CorpseDecay
float fCorpseDecay = IntToFloat(GetFlagValue(sSpawnName, "CD", dfCorpseDecay));
int nCorpseDecayType = GetSubFlagValue(sSpawnName, "CD", "T", dfCorpseDecayType);
int nCorpseRemainsType = GetSubFlagValue(sSpawnName, "CD", "R", dfCorpseRemainsType);
int bDropWielded = IsSubFlagPresent(sSpawnName, "CD", "D");
string sCorpseRemainsResRef;
int bDeleteLootOnDecay = FALSE;
switch (nCorpseRemainsType)
{
case 0: sCorpseRemainsResRef = "invis_corpse_obj"; break;
case 1: sCorpseRemainsResRef = "invis_corpse_bdy"; break;
case 2: sCorpseRemainsResRef = "invis_corpse_bon"; break;
case 3: sCorpseRemainsResRef = "invis_corpse_pot"; break;
case 4: sCorpseRemainsResRef = "invis_corpse_pch"; break;
case 5: sCorpseRemainsResRef = "invis_corpse_scr"; break;
case 6: sCorpseRemainsResRef = "invis_corpse_tre"; break;
case 7:
sCorpseRemainsResRef = "invis_corpse_obj";
bDeleteLootOnDecay = TRUE;
break;
}
// Record CorpseDecay
SetLocalFloat(oSpawn, "f_CorpseDecay", fCorpseDecay);
SetLocalInt(oSpawn, "f_CorpseDecayType", nCorpseDecayType);
SetLocalString(oSpawn, "f_CorpseRemainsResRef", sCorpseRemainsResRef);
SetLocalInt(oSpawn, "f_CorpseDropWielded", bDropWielded);
SetLocalInt(oSpawn, "f_CorpseDeleteLootOnDecay", bDeleteLootOnDecay);
// Initialize SpawnCamp
int nSpawnCamp = IsFlagPresent(sSpawnName, "CM");
float fCampDecay = IntToFloat(GetSubFlagValue(sSpawnName, "CM", "D", dfCampDecay));
// Record SpawnCamp
SetLocalInt(oSpawn, "f_SpawnCamp", nSpawnCamp);
SetLocalFloat(oSpawn, "f_CampDecay", fCampDecay);
// Initialize Spawn Scripts
int nSpawnScript = GetFlagValue(sSpawnName, "SS", dfSpawnScript);
int nDespawnScript = GetSubFlagValue(sSpawnName, "SS", "D", dfDespawnScript);
// Record Spawn Scripts
SetLocalInt(oSpawn, "f_SpawnScript", nSpawnScript);
SetLocalInt(oSpawn, "f_DespawnScript", nDespawnScript);
// Initialize Death Scripts
int nDeathScript = GetFlagValue(sSpawnName, "DT", dfDeathScript);
// Record Death Scripts
SetLocalInt(oSpawn, "f_DeathScript", nDeathScript);
// Initialize SpawnCheckCustom
int nSpawnCheckCustom = GetFlagValue(sSpawnName, "CC", dfSpawnCheckCustom);
// Record SpawnCheckCustom
SetLocalInt(oSpawn, "f_SpawnCheckCustom", nSpawnCheckCustom);
// Initialize SpawnCheckPCs
int nSpawnCheckPCs = GetFlagValue(sSpawnName, "CP", dfSpawnCheckPCs);
float fCheckPCsRadius = IntToFloat(GetSubFlagValue(sSpawnName, "CP", "R", dfCheckPCsRadius));
// Record SpawnCheckPCs
SetLocalInt(oSpawn, "f_SpawnCheckPCs", nSpawnCheckPCs);
SetLocalFloat(oSpawn, "f_CheckPCsRadius", fCheckPCsRadius);
// Intialize SpawnTrigger
float fSpawnTrigger = IntToFloat(GetFlagValue(sSpawnName, "TR", dfSpawnTrigger));
float fDespawnTrigger = IntToFloat(GetSubFlagValue(sSpawnName, "TR", "D", dfDespawnTrigger));
// Record SpawnTrigger
SetLocalFloat(oSpawn, "f_SpawnTrigger", fSpawnTrigger);
SetLocalFloat(oSpawn, "f_DespawnTrigger", fDespawnTrigger);
// Initialize AreaEffect
int nSpawnAreaEffect = GetFlagValue(sSpawnName, "AE", dfSpawnAreaEffect);
float fAreaEffectDuration = IntToFloat(GetSubFlagValue(sSpawnName, "AE", "D", dfAreaEffectDuration));
// Record AreaEffect
SetLocalInt(oSpawn, "f_SpawnAreaEffect", nSpawnAreaEffect);
SetLocalFloat(oSpawn, "f_AreaEffectDuration", fAreaEffectDuration);
// Initialize ObjectEffect
int nObjectEffect = GetFlagValue(sSpawnName, "OE", dfObjectEffect);
float fObjectEffectDuration = IntToFloat(GetSubFlagValue(sSpawnName, "OE", "D", dfObjectEffectDuration));
if (fObjectEffectDuration == 0.0)
{
fObjectEffectDuration = -1.0;
}
// Record ObjectEffect
SetLocalInt(oSpawn, "f_ObjectEffect", nObjectEffect);
SetLocalFloat(oSpawn, "f_ObjectEffectDuration", fObjectEffectDuration);
// Initialize RandomSpawn
int nRandomSpawn = GetFlagValue(sSpawnName, "RS", dfRandomSpawn);
// Record RandomSpawn
SetLocalInt(oSpawn, "f_RandomSpawn", nRandomSpawn);
// Initialize SpawnFaction
int nSpawnFaction = GetFlagValue(sSpawnName, "FC", dfSpawnFaction);
// Record SpawnFaction
SetLocalInt(oSpawn, "f_SpawnFaction", nSpawnFaction);
// Initialize SpawnAlignment
int nSpawnAlignment = GetFlagValue(sSpawnName, "AL", dfSpawnAlignment);
int nAlignmentShift = GetSubFlagValue(sSpawnName, "AL", "S", dfAlignmentShift);
// Record SpawnAlignment
SetLocalInt(oSpawn, "f_SpawnAlignment", nSpawnAlignment);
SetLocalInt(oSpawn, "f_AlignmentShift", nAlignmentShift);
// Initialize Heartbeat
int nHeartbeatScript = GetFlagValue(sSpawnName, "HB", dfHeartbeatScript);
// Record HeartBeat
SetLocalInt(oSpawn, "f_HeartbeatScript", nHeartbeatScript);
// Initialize SpawnLocation
int nSpawnLocation = GetFlagValue(sSpawnName, "SL", dfSpawnLocation);
int nSpawnLocationMin = GetSubFlagValue(sSpawnName, "SL", "R", dfSpawnLocationMin);
int nSpawnLocationInd = IsSubFlagPresent(sSpawnName, "SL", "I");
if (nSpawnLocationMin > nSpawnLocation)
{
nSpawnLocationMin = -1;
}
// Record SpawnLocation
SetLocalInt(oSpawn, "f_SpawnLocation", nSpawnLocation);
SetLocalInt(oSpawn, "f_SpawnLocationMin", nSpawnLocationMin);
SetLocalInt(oSpawn, "f_SpawnLocationInd", nSpawnLocationInd);
// Initialize SpawnFacing
float fSpawnFacing;
int nSpawnFacing = IsFlagPresent(sSpawnName, "SF");
if (nSpawnFacing == TRUE)
{
fSpawnFacing = GetFacingFromLocation(GetLocation(oSpawn));
}
else
{
// If f_Facing is false, fSpawnFacing is now calculated for
// each individual creature
fSpawnFacing = 0.0;
// fSpawnFacing = IntToFloat(Random(360));
}
// Record SpawnFacing
SetLocalInt(oSpawn, "f_Facing", nSpawnFacing);
SetLocalFloat(oSpawn, "f_SpawnFacing", fSpawnFacing);
// Initialize EntranceExit
int nEntranceExit = GetFlagValue(sSpawnName, "EE", dfEntranceExit);
int nEntranceExitMin = GetSubFlagValue(sSpawnName, "EE", "R", dfEntranceExitMin);
if (nEntranceExitMin > nEntranceExit)
{
nEntranceExitMin = -1;
}
int nExit = GetFlagValue(sSpawnName, "EX", dfExit);
int nExitMin = GetSubFlagValue(sSpawnName, "EX", "R", dfExitMin);
if (nExitMin > nExit)
{
nExitMin = -1;
}
// Record EntranceExit
SetLocalInt(oSpawn, "f_EntranceExit", nEntranceExit);
SetLocalInt(oSpawn, "f_EntranceExitMin", nEntranceExitMin);
SetLocalInt(oSpawn, "f_Exit", nExit);
SetLocalInt(oSpawn, "f_ExitMin", nExitMin);
// Initialize HealChildren
int nHealChildren = GetFlagValue(sSpawnName, "HL", dfHealChildren);
int nHealEffects = IsSubFlagPresent(sSpawnName, "HL", "E");
if (nHealChildren == 1)
{
nHealChildren == 100;
}
// Record HealChildren
SetLocalInt(oSpawn, "f_HealChildren", nHealChildren);
SetLocalInt(oSpawn, "f_HealEffects", nHealEffects);
// Initialize SpawnItem
int nSpawnItem = IsFlagPresent(sSpawnName, "IT");
// Record SpawnItem
SetLocalInt(oSpawn, "f_SpawnItem", nSpawnItem);
// Initialize SpawnSit
int nSpawnSit = IsFlagPresent(sSpawnName, "ST");
// Record SpawnSit
SetLocalInt(oSpawn, "f_SpawnSit", nSpawnSit);
// Initialize SpawnPlot
int nSpawnPlot = IsFlagPresent(sSpawnName, "PT");
// Record SpawnPlot
SetLocalInt(oSpawn, "f_SpawnPlot", nSpawnPlot);
// Initialize SpawnMerchant
int nSpawnMerchant = IsFlagPresent(sSpawnName, "SM");
// Record SpawnMerchant
SetLocalInt(oSpawn, "f_SpawnMerchant", nSpawnMerchant);
// Initialize Dim Returns Suppression
int nSuppressDimReturns = IsFlagPresent(sSpawnName, "SX");
if (nSuppressDimReturns)
{
// If the flag is present, get suppression mode from its value
nSuppressDimReturns = GetFlagValue(sSpawnName, "SX", dfSuppressDR);
}
else
{
// Use the global setting
nSuppressDimReturns = dfGlobalSuppressDR;
}
// Record Dim Returns Suppression
SetLocalInt(oSpawn, "f_SuppressDimReturns", nSuppressDimReturns);
// Initialize Loot Suppression
int nSuppressLooting = IsFlagPresent(sSpawnName, "NL");
// Record Loot Suppression
SetLocalInt(oSpawn, "f_SuppressLooting", nSuppressLooting);
// Initialize Subdual Mode
int nSubdualMode = IsFlagPresent(sSpawnName, "SB");
// Record Subdual Mode
SetLocalInt(oSpawn, "f_SubdualMode", nSubdualMode);
int nEncounterLevel;
// Initialize Encounter Level
if (IsFlagPresent(sSpawnName, "EL"))
{
nEncounterLevel = GetFlagValue(sSpawnName, "EL", dfEncounterLevel);
SetLocalInt(oSpawn, "f_EncounterLevel", nEncounterLevel);
}
// Record Flags Initialized
SetLocalInt(oSpawn, "FlagsInitialized", TRUE);
}
//
// This Function Sets the Spawns
int SetSpawns(location lBase)
{
string sSpawnName, sSpawnNum, sSpawnTag;
int nNth = 1;
int nSpawnNum = 0;
// Enumerate Waypoints in the Area
object oSpawn = GetFirstObjectInArea(OBJECT_SELF);
while (oSpawn != OBJECT_INVALID)
{
// Check for a local string called "NESS" on the waypoint
// first. If it exists, use it instead of the name
sSpawnName = GetLocalString(oSpawn, "NESS");
if (GetStringLeft(sSpawnName, 2) != "SP")
{
// Retrieve Name
sSpawnName = GetName(oSpawn);
}
// Check if Waypoint is a Spawn Controller
if (GetStringLeft(sSpawnName, 2) == "SP")
{
// Set Spawn
nSpawnNum++;
sSpawnNum = "Spawn" + PadIntToString(nSpawnNum, 2);
SetLocalObject(OBJECT_SELF, sSpawnNum, oSpawn);
sSpawnTag = GetLocalString(oSpawn, "NESS_TAG");
if (sSpawnTag == "")
{
sSpawnTag = GetTag(oSpawn);
}
DelayCommand(0.0, InitFlags(oSpawn, sSpawnName, sSpawnTag));
}
nNth++;
oSpawn = GetNextObjectInArea(OBJECT_SELF);
}
SetLocalInt(OBJECT_SELF, "Spawns", nSpawnNum);
return nSpawnNum;
}
//
// This Function returns the Number of PCs in an Area
int CountPCsInArea(object oArea = OBJECT_INVALID, int nDM = FALSE)
{
int retVal = 0;
if (oArea == OBJECT_INVALID)
{
oArea = GetArea(OBJECT_SELF);
}
object oPC = GetFirstPC();
while (oPC != OBJECT_INVALID)
{
if (GetArea(oPC) == oArea)
{
if (GetIsDM(oPC) == TRUE)
{
if (nDM == TRUE)
{
retVal++;
}
}
else
{
retVal++;
}
}
oPC = GetNextPC();
}
return retVal;
}
//
// This Function Returns the Number of PCs in a Radius
int CountPCsInRadius(location lCenter, float fRadius, int nDM = FALSE)
{
int nPCs = 0;
object oPC = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lCenter, FALSE,
OBJECT_TYPE_ALL);
while (oPC != OBJECT_INVALID)
{
if (GetIsPC(oPC))
{
if (GetIsDM(oPC))
{
//debug(GetName(oPC) + " is a DM ");
if (nDM == TRUE)
{
nPCs++;
}
}
else
{
//debug("found a real PC");
nPCs++;
}
}
oPC = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lCenter, FALSE,
OBJECT_TYPE_ALL);
}
return nPCs;
}
//
int IsCreatureItem(object oItem)
{
if (GetBaseItemType(oItem) == BASE_ITEM_CREATUREITEM ||
GetBaseItemType(oItem) == BASE_ITEM_CBLUDGWEAPON ||
GetBaseItemType(oItem) == BASE_ITEM_CPIERCWEAPON ||
GetBaseItemType(oItem) == BASE_ITEM_CSLASHWEAPON ||
GetBaseItemType(oItem) == BASE_ITEM_CSLSHPRCWEAP)
{
return TRUE;
}
return FALSE;
}
// This Function Returns a Random PC from Area
object GetRandomPCInArea(object oArea, object oSpawn)
{
int nPCsInArea = CountPCsInArea(oArea, TRUE);
int nNth = Random(nPCsInArea) + 1;
object oRandomPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oSpawn, nNth);
return oRandomPC;
}
object NESS_CopyCorpseItem(object oSource, object oInventory)
{
int bWasPlot = GetPlotFlag(oSource);
object oNewItem = CopyItem(oSource, oInventory);
if (bWasPlot == TRUE)
{
SetPlotFlag(oNewItem,TRUE);
}
return oNewItem;
}
//
struct NESS_CorpseInfo TransferAllInventorySlots(object oVictim,
object oCorpse, int bDropWielded=FALSE)
{
int i=0;
object oItem = OBJECT_INVALID;
location locItem;
struct NESS_CorpseInfo stCorpseInfo;
// Initialize
stCorpseInfo.origRgtWpn = OBJECT_INVALID;
stCorpseInfo.origLftWpn = OBJECT_INVALID;
stCorpseInfo.origArmor = OBJECT_INVALID;
stCorpseInfo.lootRgtWpn = OBJECT_INVALID;
stCorpseInfo.lootLftWpn = OBJECT_INVALID;
stCorpseInfo.lootArmor = OBJECT_INVALID;
for (i=0; i < NUM_INVENTORY_SLOTS; i++)
{
oItem = GetItemInSlot(i, oVictim);
// See if we're going to allow looting of this item.
if (GetIsObjectValid(oItem) && GetDroppableFlag(oItem))
{
// Handle different items slightly differently.
if (i == INVENTORY_SLOT_CHEST && GetIsVictimDressed(oVictim))
{
// The victim is wearing the armor. We don't want to destroy
// it while the corpse is around, since that would leave the
// body naked.
stCorpseInfo.origArmor = oItem;
stCorpseInfo.lootArmor = NESS_CopyCorpseItem(oItem, oCorpse);
}
else if (i == INVENTORY_SLOT_RIGHTHAND)
{
if (bDropWielded)
{
// This is a wielded item. Drop it nearby.
locItem = GetStepRightLocation(oVictim);
CreateObject(OBJECT_TYPE_ITEM, GetResRef(oItem), locItem);
DestroyObject(oItem, 0.1);
}
else
{
stCorpseInfo.origRgtWpn = oItem;
stCorpseInfo.lootRgtWpn = NESS_CopyCorpseItem(oItem, oCorpse);
}
}
else if (i == INVENTORY_SLOT_LEFTHAND)
{
if(bDropWielded)
{
// This is a wielded item. Drop it nearby.
locItem = GetStepLeftLocation(oVictim);
CreateObject(OBJECT_TYPE_ITEM, GetResRef(oItem), locItem);
DestroyObject(oItem, 0.1);
}
else
{
stCorpseInfo.origLftWpn = oItem;
stCorpseInfo.lootLftWpn = NESS_CopyCorpseItem(oItem, oCorpse);
}
}
else
{
NESS_CopyCorpseItem(oItem, oCorpse);
DestroyObject(oItem, 0.1);
}
}
}
return stCorpseInfo;
}
//
// This Function Checks if the Party is within fDistance Meters of Each Other
int IsPartyTogether(object oPC, float fDistance)
{
int nTogether = TRUE;
object oMember = GetFirstFactionMember(oPC, TRUE);
while (oMember != OBJECT_INVALID)
{
if (GetIsDead(oMember) == FALSE)
{
if (GetDistanceBetween(oPC, oMember) > fDistance)
{
nTogether = FALSE;
oMember = OBJECT_INVALID;
}
}
oMember = GetNextFactionMember(oPC, TRUE);
}
return nTogether;
}
//
// This Function Returns the Number of PCs in a Party
int CountMembersInParty(object oPC, int bPCOnly = TRUE)
{
int nCount;
object oMember = GetFirstFactionMember(oPC, bPCOnly);
while (oMember != OBJECT_INVALID)
{
nCount++;
oMember = GetNextFactionMember(oPC, bPCOnly);
}
return nCount;
}
//
// This Function Checks if nCheckDay is Between Days
int IsBetweenDays(int nCheckDay, int nDayStart, int nDayEnd)
{
if (nDayEnd > -1)
{
if (nCheckDay >= nDayStart && nCheckDay <= nDayEnd)
{
return TRUE;
}
}
else
{
if (nCheckDay == nDayStart)
{
return TRUE;
}
}
return FALSE;
}
//
// This Function Checks if nCheckHour is Between Hours
int IsBetweenHours(int nCheckHour, int nHourStart, int nHourEnd)
{
if (nHourEnd > -1)
{
if (nCheckHour >= nHourStart && nCheckHour <= nHourEnd)
{
return TRUE;
}
}
else
{
if (nCheckHour == nHourStart)
{
return TRUE;
}
}
return FALSE;
}
//
// This Function Pads an IntToString with 0s
string PadIntToString(int nInt, int nDigits)
{
string sRetString;
string sTempInt = IntToString(nInt);
int iCount;
sRetString = "";
for (iCount = 1; iCount <= (nDigits - GetStringLength(sTempInt)); iCount++)
{
sRetString = sRetString + "0";
}
sRetString = sRetString + sTempInt;
return sRetString;
}
//
// This Function returns a Child Object by Tag
object GetChildByTag(object oSpawn, string sChildTag)
{
object oChild;
object oRetChild = OBJECT_INVALID;
string sChildSlot;
int nChildSlot;
string sSpawnName = GetLocalString(oSpawn, "f_Flags");
int nSpawnNumber = GetFlagValue(sSpawnName, "SN", 1);
// Cycle through Children
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
if (GetTag(oChild) == sChildTag)
{
oRetChild = oChild;
}
}
return oRetChild;
}
//
// This Function returns a Child Object by Slot Number
object GetChildByNumber(object oSpawn, int nChildNum)
{
object oRetChild = OBJECT_INVALID;
string sChildSlot;
string sSpawnName = GetLocalString(oSpawn, "f_Flags");
int nSpawnNumber = GetFlagValue(sSpawnName, "SN", 1);
// Check if Valid Number
if (nChildNum > nSpawnNumber)
{
return oRetChild;
}
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildNum, 2);
oRetChild = GetLocalObject(oSpawn, sChildSlot);
// Return Child
return oRetChild;
}
//
object NESS_GetSpawnByID(int nSpawnID, object oArea)
{
string sSpawnName;
object oRetSpawn;
// Enumerate Waypoints in the Area
object oSpawn = GetFirstObjectInArea(oArea);
while (oSpawn != OBJECT_INVALID)
{
// Retrieve Name
sSpawnName = GetLocalString(oSpawn, "f_Flags");
// Check if Waypoint is a Spawn Controller
if (GetStringLeft(sSpawnName, 2) == "SP")
{
if (GetLocalInt(oSpawn, "SpawnID") == nSpawnID)
{
oRetSpawn = oSpawn;
}
}
oSpawn = GetNextObjectInArea(oArea);
}
return oRetSpawn;
}
//
// This Function returns a Spawn Object by ID
object GetSpawnByID(int nSpawnID)
{
return NESS_GetSpawnByID(nSpawnID, OBJECT_SELF);
}
//
// This Function Sets Children to Despawn
void DespawnChildren(object oSpawn)
{
object oChild;
string sChildSlot;
int nChildSlot;
string sSpawnName = GetLocalString(oSpawn, "f_Flags");
int nSpawnNumber = GetFlagValue(sSpawnName, "SN", 1);
// Cycle through Children
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
SetLocalInt(oChild, "ForceDespawn", TRUE);
}
}
//
// This Function Sets Children to Despawn by Tag
void DespawnChildrenByTag(object oSpawn, string sChildTag)
{
object oChild;
string sChildSlot;
int nChildSlot;
string sSpawnName = GetLocalString(oSpawn, "f_Flags");
int nSpawnNumber = GetFlagValue(sSpawnName, "SN", 1);
// Cycle through Children
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
if (GetTag(oChild) == sChildTag)
{
SetLocalInt(oChild, "ForceDespawn", TRUE);
}
}
}
//
// This Function Adds a Child to a Spawn
void AddChild(object oSpawn, object oSpawned)
{
// Declare Variables
int nEmptyChildSlot, nChildSlot;
int nSpawnNumber, nSpawnCount, nChildrenSpawned;
string sChildSlot, sEmptyChildSlot;
object oChild;
// Retreive Values
nSpawnNumber = GetLocalInt(oSpawn, "f_SpawnNumber");
nChildrenSpawned = GetLocalInt(oSpawn, "ChildrenSpawned");
nSpawnCount = GetLocalInt(oSpawn, "SpawnCount");
// Find Empty Child Slot
nEmptyChildSlot = 0;
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
// Check if this is Child Slot is Valid
if (GetIsObjectValid(oChild) == FALSE || GetIsDead(oChild))
{
// Empty Slot
if (nEmptyChildSlot == 0)
{
nEmptyChildSlot = nChildSlot;
sEmptyChildSlot = sChildSlot;
}
}
}
if (nEmptyChildSlot != 0)
{
// Assign Values to oSpawned
SetLocalObject(oSpawned, "ParentSpawn", oSpawn);
SetLocalFloat(oSpawned, "HomeX", GetPositionFromLocation(GetLocation(oSpawned)).x);
SetLocalFloat(oSpawned, "HomeY", GetPositionFromLocation(GetLocation(oSpawned)).y);
// Assign Child Slot
SetLocalObject(oSpawn, sEmptyChildSlot, oSpawned);
SetLocalString(oSpawned, "ParentChildSlot", sEmptyChildSlot);
// Assign Values to oSpawn
nChildrenSpawned++;
SetLocalInt(oSpawn, "ChildrenSpawned", nChildrenSpawned);
nSpawnCount++;
SetLocalInt(oSpawn, "SpawnCount", nSpawnCount);
}
}
//
void NESS_DeactivateSpawnByID(int nSpawnID, object oArea)
{
object oSpawn = NESS_GetSpawnByID(nSpawnID, oArea);
NESS_DeactivateSpawn(oSpawn);
}
// Identical to DeactivateSpawn, but included for interface consistency
void NESS_DeactivateSpawn(object oSpawn)
{
DeactivateSpawn(oSpawn);
}
// This Function Sets a Spawn to Deactivate
void DeactivateSpawn(object oSpawn)
{
SetLocalInt(oSpawn, "ForceDeactivateSpawn", TRUE);
NESS_ForceProcess(oSpawn);
}
void NESS_ActivateSpawnByID(int nSpawnID, object oArea)
{
object oSpawn = NESS_GetSpawnByID(nSpawnID, oArea);
NESS_ActivateSpawn(oSpawn);
}
// This Function Sets a Spawn to Activate
void NESS_ActivateSpawn(object oSpawn)
{
SetLocalInt(oSpawn, "SpawnDeactivated", FALSE);
NESS_ForceProcess(oSpawn);
}
void NESS_ForceProcess(object oSpawn)
{
SetLocalInt(oSpawn, "SpawnForceProcess", TRUE);
}
void NESS_TrackModuleSpawns(int flag=TRUE)
{
SetLocalInt(GetModule(), "TrackModuleSpawns", flag);
}
int NESS_IsModuleSpawnTracking()
{
return GetLocalInt(GetModule(), "TrackModuleSpawns");
}
//
void NESS_DumpModuleSpawns(int flag=TRUE)
{
SetLocalInt(GetModule(), "DumpModuleSpawns", flag);
}
int NESS_IsModuleSpawnDumping()
{
return GetLocalInt(GetModule(), "DumpModuleSpawns");
}
//
// This Function Sets all Spawns by Tag to Deactivate
void DeactivateSpawnsByTag(string sSpawnTag)
{
int nNth;
object oSpawn;
string sSpawnNum;
int nSpawns = GetLocalInt(GetArea(OBJECT_SELF), "Spawns");
for (nNth = 1; nNth <= nSpawns; nNth++)
{
// Retrieve Spawn
sSpawnNum = "Spawn" + PadIntToString(nNth, 2);
oSpawn = GetLocalObject(OBJECT_SELF, sSpawnNum);
if (GetTag(oSpawn) == sSpawnTag)
{
SetLocalInt(oSpawn, "ForceDeactivateSpawn", TRUE);
}
}
}
//
// This Function Sets all Spawns to Deactivate
void DeactivateAllSpawns()
{
int nNth;
object oSpawn;
string sSpawnNum;
int nSpawns = GetLocalInt(GetArea(OBJECT_SELF), "Spawns");
for (nNth = 1; nNth <= nSpawns; nNth++)
{
// Retrieve Spawn
sSpawnNum = "Spawn" + PadIntToString(nNth, 2);
oSpawn = GetLocalObject(OBJECT_SELF, sSpawnNum);
SetLocalInt(oSpawn, "ForceDeactivateSpawn", TRUE);
}
}
//
location GetRandomLocationInRadius(object oSpawn, float fWalkingRadius)
{
vector vCurrentLocation, vTargetLocation;
float fRadiusX, fRadiusY;
location lTargetLocation;
// Create our Random Location
fRadiusX = IntToFloat(Random(FloatToInt(fWalkingRadius)));
fRadiusY = IntToFloat(Random(FloatToInt(fWalkingRadius)));
if (d2() == 2)
{
fRadiusX = -fRadiusX;
}
if (d2() == 2)
{
fRadiusY = -fRadiusY;
}
vTargetLocation = Vector(fRadiusX, fRadiusY);
vCurrentLocation = GetPositionFromLocation(GetLocation(oSpawn));
lTargetLocation = Location(OBJECT_SELF, vCurrentLocation + vTargetLocation,
0.0);
return lTargetLocation;
}
// Random Walking with Range
void RandomWalk(object oSpawn, float fWalkingRadius, int nRun)
{
// Walk to the New Location
float fRadiusX, fRadiusY;
// Create our Random Location
fRadiusX = IntToFloat(Random(FloatToInt(fWalkingRadius)));
fRadiusY = IntToFloat(Random(FloatToInt(fWalkingRadius)));
if (d2() == 2)
{
fRadiusX = -fRadiusX;
}
if (d2() == 2)
{
fRadiusY = -fRadiusY;
}
location lSpawnLocation = GetLocation(oSpawn);
vector vNewPosition = GetPositionFromLocation(lSpawnLocation);
vNewPosition.x += fRadiusX;
vNewPosition.y += fRadiusY;
location lRandomWalkLocation = Location(GetArea(OBJECT_SELF), vNewPosition,
0.0);
ActionMoveToLocation(lRandomWalkLocation, nRun);
}
//
// This Function Finds aaSeatnd Sits in It
void FindSeat(object oSpawn, object oSpawned)
{
object oSeat;
string sSeatTag = GetLocalString(GetModule(), "df_SeatTag");
location lSeatLocation;
int nNth = 1;
object oSittable = GetNearestObjectByTag(sSeatTag, oSpawned, nNth);
while (oSittable != OBJECT_INVALID && oSeat == OBJECT_INVALID)
{
if (GetSittingCreature(oSittable) == OBJECT_INVALID)
{
oSeat = oSittable;
}
nNth++;
oSittable = GetNearestObjectByTag(sSeatTag, oSpawned, nNth);
}
if (GetIsObjectValid(oSeat))
{
lSeatLocation = GetLocation(oSeat);
AssignCommand(oSpawned, ClearAllActions());
AssignCommand(oSpawned, ActionMoveToLocation(lSeatLocation));
AssignCommand(oSpawned, ActionSit(oSeat));
}
}
//
// This Function Cleans an Object's Inventory
void NESS_CleanCorpse(object oSpawned)
{
NESS_CleanEquipped(oSpawned);
NESS_CleanInventory(oSpawned);
}
void NESS_CleanEquipped(object oSpawned)
{
int i = 0;
object oItem = OBJECT_INVALID;
for (i=0; i < NUM_INVENTORY_SLOTS; i++)
{
oItem = GetItemInSlot(i, oSpawned);
if (GetIsObjectValid(oItem))
{
// Why the delay? This is used to remove equipped items from corpses. If the
// corpse is still around, it do it's unequip animation...
DestroyObject(oItem, 1.0);
oItem = GetNextItemInInventory(oSpawned);
}
}
}
void NESS_CleanInventory(object oSpawned)
{
// Clean out oSpawned's Inventory
//debug("in clean inventory");
object oItem = GetFirstItemInInventory(oSpawned);
while (oItem != OBJECT_INVALID)
{
//debug("destroying " + GetName(oItem));
DestroyObject(oItem);
oItem = GetNextItemInInventory(oSpawned);
}
}
//
// This Functions Sets up the Patrol Route
void SetPatrolRoute(int nPatrolRoute, int nStartClosest=FALSE)
{
object oStop;
int nRouteNumber, nStopNumber, iCount, nNumStops;
string sStop;
// These 3 vars only used if nStartClosest is TRUE;
float fLeastDistance = 9999999.0;// any distance returned should be smaller
float fCurrentDistance;
int nClosestStopNum;
// Cycle through Available Patrol Route Stops
iCount = 0;
nNumStops = 0;
oStop = GetNearestObject(OBJECT_TYPE_WAYPOINT, OBJECT_SELF, iCount);
while (oStop != OBJECT_INVALID)
{
sStop = GetTag(oStop);
// Check Route Number
nRouteNumber = GetFlagValue(sStop, "PR", -1);
if (nRouteNumber == nPatrolRoute)
{
// Identical Route Number, Add this Stop to oSpawned
nNumStops++;
nStopNumber = GetFlagValue(sStop, "SN", 0);
SetLocalObject(OBJECT_SELF, "PR_SN" + PadIntToString(nStopNumber, 2), oStop);
if (nStartClosest)
{
fCurrentDistance = GetDistanceToObject(oStop);
if (fCurrentDistance < fLeastDistance)
{
nClosestStopNum = nStopNumber;
fLeastDistance = fCurrentDistance;
}
}
}
iCount++;
oStop = GetNearestObject(OBJECT_TYPE_WAYPOINT, OBJECT_SELF, iCount);
}
SetLocalInt(OBJECT_SELF, "PR_STOPS", nNumStops);
if (nStartClosest && (nClosestStopNum > 0))
{
SetLocalInt(OBJECT_SELF, "PR_LASTSTOP", nClosestStopNum - 1);
// Force it to go to a new waypoint
SetLocalInt(OBJECT_SELF, "PR_NEXTSTOP", -1);
}
}
//
// This Function Performs the Patrol Route
void DoPatrolRoute(int nPatrolRoute, int nRouteType)
{
int nNumStops, nDespawn;
int nNextPatrolStop = -1;
int nLastPatrolStop = -1;
int nReturnRoute = FALSE;
if (GetCurrentAction() != ACTION_INVALID)
return;
ClearAllActions();
// Retreive Stop Information
nNumStops = GetLocalInt(OBJECT_SELF, "PR_STOPS");
nNextPatrolStop = GetLocalInt(OBJECT_SELF, "PR_NEXTSTOP");
nLastPatrolStop = GetLocalInt(OBJECT_SELF, "PR_LASTSTOP");
nReturnRoute = GetLocalInt(OBJECT_SELF, "PR_RETURNROUTE");
// Add New Stop to Route
if (nNextPatrolStop == -1)
{
// Sequential Route
if (nRouteType == 0 || nRouteType == 3)
{
if (nReturnRoute == TRUE)
{
if (nLastPatrolStop == 0)
{
nReturnRoute = FALSE;
SetLocalInt(OBJECT_SELF, "PR_RETURNROUTE", nReturnRoute);
nNextPatrolStop = nLastPatrolStop + 1;
}
else
{
nNextPatrolStop = nLastPatrolStop - 1;
}
}
else
{
if (nLastPatrolStop == nNumStops)
{
if (nRouteType == 3)
{
// End of Line, Despawn
nDespawn = TRUE;
}
else
{
nReturnRoute = TRUE;
SetLocalInt(OBJECT_SELF, "PR_RETURNROUTE", nReturnRoute);
nNextPatrolStop = nLastPatrolStop - 2;
}
}
else
{
nNextPatrolStop = nLastPatrolStop + 1;
}
}
}
// Circular Route
if (nRouteType == 1)
{
if (nLastPatrolStop == nNumStops)
{
nNextPatrolStop = 0;
}
else
{
nNextPatrolStop = nLastPatrolStop + 1;
}
}
// Random Route
if (nRouteType == 2)
{
nNextPatrolStop = Random(nNumStops);
while (nNextPatrolStop == nLastPatrolStop)
{
nNextPatrolStop = Random(nNumStops);
}
}
}
if (nDespawn == TRUE)
{
ClearAllActions();
SetLocalInt(OBJECT_SELF, "ForceDespawn", TRUE);
}
else
{
// Set Next Stop
SetLocalInt(OBJECT_SELF, "PR_NEXTSTOP", nNextPatrolStop);
// Add Stop to Patrol
AddPatrolStop(nPatrolRoute, nNextPatrolStop);
// Repeat the Process
ActionDoCommand(DoPatrolRoute(nPatrolRoute, nRouteType));
}
}
//
// This Function adds a Stop to the Patrol Route
void AddPatrolStop(int nPatrolRoute, int nStopNumber, int bJump=FALSE)
{
object oStop;
int nRun, nScript, nFacing;
int nDayOnly, nNightOnly;
float fPause;
// Danmar: Added below for random pause setup
int nRandomPause;
int nRandomRoute;
// End Danmar changes
string sStop;
int nValid = TRUE;
// Gather Stop Information
oStop = GetLocalObject(OBJECT_SELF, "PR_SN" +
PadIntToString(nStopNumber, 2));
if (GetIsObjectValid( oStop ) )
{
sStop = GetTag(oStop);
nRun = IsFlagPresent(sStop, "RN");
fPause = IntToFloat(GetFlagValue(sStop, "PS", 1));
// Danmar: Added RP###/RR### flag to patrol points to allow randomization
// of the pause time and stops.
nRandomPause = GetFlagValue(sStop, "RP", 0);
nRandomRoute = GetFlagValue(sStop, "RR", 0);
// End Danmar changes.
nScript = GetFlagValue(sStop, "SC", -1);
nFacing = IsFlagPresent(sStop, "SF");
nDayOnly = IsFlagPresent(sStop, "DO");
nNightOnly = IsFlagPresent(sStop, "NO");
// Day Only
if (nDayOnly == TRUE && (GetIsDay() == FALSE && GetIsDawn() == FALSE))
{
nValid = FALSE;
}
// Night Only
if (nNightOnly == TRUE && (GetIsNight() == FALSE && GetIsDusk() == FALSE))
{
nValid = FALSE;
}
// Check if Valid
if (nValid == TRUE)
{
// Move to Stop
// Modified by Danmar
// ActionMoveToObject(oStop, nRun); // Original NESS line.
// if d% is less than nRandomRoute (RRxxx) then we move to the next stop.
// If its not then we skip that one and move to the next.
if ((nRandomRoute == 0) || ((Random(100) + 1) < nRandomRoute))
{
if (bJump)
{
ActionJumpToLocation(GetLocation(oStop));
}
else
{
ActionMoveToObject(oStop, nRun);
}
}
// End Danmar Changes
if (nFacing == TRUE)
{
ActionDoCommand(SetFacing(GetFacingFromLocation(GetLocation(oStop))));
}
// Execute Script
if (nScript > -1)
{
SetLocalInt(OBJECT_SELF, "PatrolScript", nScript);
ActionDoCommand(SetLocalInt(OBJECT_SELF, "PatrolScriptRunning", TRUE));
ExecuteScript("spawn_sc_patrol", OBJECT_SELF);
ActionDoCommand(SetLocalInt(OBJECT_SELF, "PatrolScriptRunning", FALSE));
}
// Pause
/* Danmar: If fRandomPause!=0 then let's pick a random pause length and
add it to the existing fpause. This way you can use PS to set the
minimum pause and RP to set the maximum pause.
Example: PR01_SN01_PS010_RR011 would cause the creature to pause between
10 to 20 seconds. */
if (nRandomPause != 0)
{
fPause = fPause + IntToFloat(Random(nRandomPause));
}
// End Danmar Changes
ActionWait(fPause);
}
}
// Record this Stop and Clear Next Stop
ActionDoCommand(SetLocalInt(OBJECT_SELF, "PR_LASTSTOP", nStopNumber));
ActionDoCommand(SetLocalInt(OBJECT_SELF, "PR_NEXTSTOP", -1));
}
void CheckForStuckPatrol(object oCreature, int nPatrolRoute, int nRouteType)
{
// are we at the same location as last time?
location lLast = GetLocalLocation(oCreature, "NESSLastLoc");
location lCurrent = GetLocation(oCreature);
if (lLast != lCurrent)
{
SetLocalLocation(oCreature, "NESSLastLoc", lCurrent);
SetLocalInt(oCreature, "NESSStuckCount", 0);
return;
}
int nStuckCount = GetLocalInt(oCreature, "NESSStuckCount");
nStuckCount += 1;
if (nStuckCount < 3)
{
SetLocalInt(oCreature, "NESSStuckCount", nStuckCount);
return;
}
AssignCommand(oCreature, ClearAllActions());
// unstuck 'im
int nLastStop = GetLocalInt(OBJECT_SELF, "PR_LASTSTOP");
// force a move
AssignCommand(oCreature, AddPatrolStop(nPatrolRoute, nLastStop, TRUE));
// reset
SetLocalInt(oCreature, "NESSStuckCount", 0);
}
//
// This Function Checks Camp State
int ProcessCamp(object oCamp)
{
int iCount;
int nIsAlive = FALSE;
int nCampNumC, nCampNumP, nPlaceableType, nDeathScript;
float fCorpseDecay;
object oSpawned, oCampTrigger, oItem;
string sObject, sFlags, sCampTrigger;
// Check Creatures
nCampNumC = GetLocalInt(oCamp, "CampNumC");
// Suppress despawning on creatureless camps
if ( nCampNumC == 0 )
{
nIsAlive = TRUE;
}
for (iCount = 1; iCount <= nCampNumC; iCount++)
{
sObject = "CampC" + IntToString(iCount - 1);
sFlags = GetLocalString(oCamp, sObject + "_Flags");
fCorpseDecay = IntToFloat(GetFlagValue(sFlags, "CD", 0));
nDeathScript = GetFlagValue(sFlags, "DT", -1);
oSpawned = GetLocalObject(oCamp, sObject);
if (oSpawned != OBJECT_INVALID)
{
if (GetIsDead(oSpawned) == FALSE)
{
nIsAlive = TRUE;
int nIsBusy = FALSE;
if (GetIsInCombat(oSpawned) || IsInConversation(oSpawned) ||
(GetCurrentAction(oSpawned) != ACTION_INVALID))
{
nIsBusy = TRUE;
}
if (! nIsBusy)
{
// Do return home processing
int nReturnHome = GetLocalInt(oSpawned, "f_ReturnHome");
if (nReturnHome)
{
// retrieve lHome and fReturnRange
float fReturnHomeRange = GetLocalFloat(oSpawned,
"f_ReturnHomeRange");
float fHomeX = GetLocalFloat(oSpawned, "HomeX");
float fHomeY = GetLocalFloat(oSpawned, "HomeY");
vector vHome = Vector(fHomeX, fHomeY, 0.0);
location lHome = Location(OBJECT_SELF, vHome, 0.0);
if (GetDistanceBetweenLocations(lHome, GetLocation(oSpawned))
> fReturnHomeRange)
{
AssignCommand(oSpawned, ReturnHome(lHome));
nIsBusy = TRUE;
}
}
}
// Do random walk
if (! nIsBusy)
{
int nRandomWalk = GetLocalInt(oSpawned, "f_RandomWalk");
if (nRandomWalk &&
GetCurrentAction(oSpawned) != ACTION_WAIT &&
GetCurrentAction(oSpawned) != ACTION_CASTSPELL &&
(d2(1) == 2))
{
AssignCommand(oSpawned, ClearAllActions());
AssignCommand(oSpawned, ActionRandomWalk());
}
}
}
else
{
NESS_ProcessDeadCreature(oSpawned);
DeleteLocalObject(oCamp, sObject);
}
}
}
// Check Camp Trigger
if (nIsAlive)
{
sCampTrigger = GetLocalString(oCamp, "CampTrigger");
if (sCampTrigger != "")
{
oCampTrigger = GetLocalObject(oCamp, "Camp" + sCampTrigger);
if (oCampTrigger == OBJECT_INVALID || GetIsDead(oCampTrigger) == TRUE)
{
// Run Trigger Script
ExecuteScript("spawn_sc_cmptrig", oCamp);
}
}
}
// Check Placeable
nCampNumP = GetLocalInt(oCamp, "CampNumP");
for (iCount = 1; iCount <= nCampNumP; iCount++)
{
sObject = "CampP" + IntToString(iCount - 1);
sFlags = GetLocalString(oCamp, sObject + "_Flags");
nPlaceableType = GetFlagValue(sFlags, "PL", 0);
if (nPlaceableType == 1)
{
// Despawn if Empty
oSpawned = GetLocalObject(oCamp, sObject);
if (GetFirstItemInInventory(oSpawned) == OBJECT_INVALID)
{
DestroyObject(oSpawned);
}
}
}
return nIsAlive;
}
//
// This Function will Despawn a Camp
void DestroyCamp(object oCamp, float fCampDecay, int nSaveState)
{
int iCount;
object oSpawned;
string sObject;
int nCampNumP = GetLocalInt(oCamp, "CampNumP");
int nCampNumC = GetLocalInt(oCamp, "CampNumC");
// Destroy Placeables
for (iCount = 1; iCount <= nCampNumP; iCount++)
{
sObject = "CampP" + IntToString(iCount - 1);
oSpawned = GetLocalObject(oCamp, sObject);
if (nSaveState)
{
//debug("Saving " + sObject);
SaveStateOnDespawn(oSpawned, oCamp, TRUE);
}
SpawnCountDebug(oCamp, "despawning camp object " + ObjectToString(oSpawned));
DestroyObject(oSpawned, fCampDecay);
}
// Destroy Creatures
for (iCount = 1; iCount <= nCampNumC; iCount++)
{
sObject = "CampC" + IntToString(iCount - 1);
oSpawned = GetLocalObject(oCamp, sObject);
if (nSaveState)
{
//debug("Saving " + sObject);
SaveStateOnDespawn(oSpawned, oCamp, TRUE);
}
AssignCommand(oSpawned, ClearAllActions());
if (oSpawned != OBJECT_INVALID)
{
NESS_CleanInventory(oSpawned);
AssignCommand(oSpawned, SetIsDestroyable(TRUE));
SpawnCountDebug(oCamp, "despawning camp creature " + ObjectToString(oSpawned));
DestroyObject(oSpawned);
}
// remove from camp object
DeleteLocalObject(oCamp, sObject);
}
}
//
object GetSpawnLocationObject(object oSpawn, int nSpawnLocationMin,
int nSpawnLocation, int nSpawnLocationInd)
{
string sSpawnLocation;
object oSpawnLocation;
if (nSpawnLocationInd)
{
int nNextEmptySlot;
nNextEmptySlot = FindNextEmptyChildSlot(oSpawn);
if (nNextEmptySlot > 0)
{
sSpawnLocation = "SL" + PadIntToString(nSpawnLocation + nNextEmptySlot - 1,
2);
}
else
{
// no empty slots? Just use base, I guess
sSpawnLocation = "SL" + PadIntToString(nSpawnLocation, 2);
}
oSpawnLocation = GetNearestObjectByTag(sSpawnLocation, oSpawn);
}
else
{
int nRndSpawnLocation;
if (nSpawnLocationMin > -1)
{
nRndSpawnLocation = Random(nSpawnLocation + 1);
while (nRndSpawnLocation < nSpawnLocationMin)
{
nRndSpawnLocation = Random(nSpawnLocation + 1);
}
nSpawnLocation = nRndSpawnLocation;
}
sSpawnLocation = "SL" + PadIntToString(nSpawnLocation, 2);
oSpawnLocation = GetNearestObjectByTag(sSpawnLocation, oSpawn);
}
return oSpawnLocation;
}
vector GetSpawnRadiusPosition(vector vSpawnPos, float fSpawnRadius,
float fSpawnRadiusMin, int nRadialDistribution=FALSE)
{
float fX, fY;
vector vRadius;
if (nRadialDistribution)
{
float fSpawnAngle, fRadius;
fSpawnAngle = IntToFloat(Random(361));
if (fSpawnRadiusMin == fSpawnRadius)
{
fX = fSpawnRadius * cos(fSpawnAngle);
fY = fSpawnRadius * sin(fSpawnAngle);
}
else
{
fRadius = IntToFloat(Random(FloatToInt(fSpawnRadius) + 1));
while (fRadius < fSpawnRadiusMin)
{
fRadius = IntToFloat(Random(FloatToInt(fSpawnRadius) + 1));
}
fX = fRadius * cos(fSpawnAngle);
fY = fRadius * sin(fSpawnAngle);
}
}
else
{
float fTestDistSquared, fMaxRadiusSquared, fMinRadiusSquared;
int nSpawnRadius = FloatToInt(fSpawnRadius);
// Set up comparators
fMaxRadiusSquared = fSpawnRadius * fSpawnRadius;
fMinRadiusSquared = fSpawnRadiusMin * fSpawnRadiusMin;
// Calculate first attempt
fX = IntToFloat(Random((2 * nSpawnRadius) + 1) -
nSpawnRadius + 1);
fY = IntToFloat(Random((2 * nSpawnRadius) + 1) -
nSpawnRadius + 1);
fTestDistSquared = (fX * fX) + (fY * fY);
while (fTestDistSquared < fMinRadiusSquared ||
fTestDistSquared > fMaxRadiusSquared)
{
fX = IntToFloat(Random((2 * nSpawnRadius) + 1) -
nSpawnRadius + 1);
fY = IntToFloat(Random((2 * nSpawnRadius) + 1) -
nSpawnRadius + 1);
fTestDistSquared = (fX * fX) + (fY * fY);
}
}
vRadius = Vector(vSpawnPos.x + fX, vSpawnPos.y + fY);
return vRadius;
}
int CheckPositionUnseen(vector vSpawnPos, float fUnseenRadius)
{
location lSpawn = Location(OBJECT_SELF, vSpawnPos, 0.0);
object oCreature = GetFirstObjectInShape(SHAPE_SPHERE, fUnseenRadius,
lSpawn, FALSE, OBJECT_TYPE_CREATURE);
while (oCreature != OBJECT_INVALID)
{
if (GetIsPC(oCreature) == TRUE)
{
return FALSE;
}
oCreature = GetNextObjectInShape(SHAPE_SPHERE, fUnseenRadius,
lSpawn, FALSE, OBJECT_TYPE_CREATURE);
}
return TRUE;
}
void ReportSpawns(int nAreaSpawns, int nModuleSpawns)
{
SendMessageToAllDMs("New creature count in " +
GetName(OBJECT_SELF) + ": " + IntToString(nAreaSpawns) +
" Module spawn count: " + IntToString(nModuleSpawns) +
(SPAWN_DELAY_DEBUG ? " (sd+)" : " (sd-)") +
(SPAWN_COUNT_DEBUG ? " (sc+)" : " (sc-)"));
}
void TrackModuleSpawns(int nAreaSpawnCount, int nTrackModuleSpawns)
{
int nNewAreaSpawnCount = GetLocalInt(OBJECT_SELF, SPAWN_AREA_COUNT );
int nSpawnDifference = nNewAreaSpawnCount - nAreaSpawnCount;
if (nSpawnDifference)
{
int nModuleSpawns = GetLocalInt(GetModule(), "ModuleSpawnCount");
nModuleSpawns += nSpawnDifference;
SetLocalInt(GetModule(), "ModuleSpawnCount", nModuleSpawns);
if (nTrackModuleSpawns)
{
ReportSpawns(nNewAreaSpawnCount, nModuleSpawns);
}
}
}
void DumpModuleSpawns()
{
int nAreaSpawnCount = GetLocalInt(OBJECT_SELF, SPAWN_AREA_COUNT );
if (nAreaSpawnCount > 0)
{
SendMessageToAllDMs("Area " + GetName(OBJECT_SELF) + ": " +
IntToString(nAreaSpawnCount) +
(SPAWN_DELAY_DEBUG ? " (sd+)" : " (sd-)") +
(SPAWN_COUNT_DEBUG ? " (sc+)" : " (sc-)"));
}
}
void NESS_ReturnHome(object oCreature, int bRun=FALSE)
{
float fHomeX = GetLocalFloat(oCreature, "HomeX");
float fHomeY = GetLocalFloat(oCreature, "HomeY");
vector vHome = Vector(fHomeX, fHomeY, 0.0);
location lHome = Location(GetArea(oCreature), vHome, 0.0);
ClearAllActions();
ActionMoveToLocation(lHome, bRun);
}
void ReturnHome(location lHome)
{
if (GetCurrentAction() != ACTION_INVALID)
return;
ClearAllActions();
ActionMoveToLocation(lHome);
}
void DestroyIfNonDrop(object oItem)
{
if(GetIsObjectValid(oItem))
{
if (! GetDroppableFlag(oItem))
{
//debug("Destroying non-drop item named " + GetName(oItem));
DestroyObject(oItem);
}
}
}
void StripNonDroppables(object oSpawned)
{
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_ARMS, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_ARROWS, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_BELT, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_BOLTS, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_BOOTS, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_BULLETS, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_CHEST, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_CLOAK, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_HEAD, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_LEFTRING, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_NECK, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oSpawned));
DestroyIfNonDrop(GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oSpawned));
object oItem = GetFirstItemInInventory(oSpawned);
while (oItem != OBJECT_INVALID)
{
DestroyIfNonDrop(oItem);
oItem = GetNextItemInInventory(oSpawned);
}
}
void NESS_ProcessDeadCreature(object oCreature, object oSpawn=OBJECT_INVALID)
{
int nCampCreature;
// Only do once per creature. Since this may be called from onDeath
// or within a NESS HB, check/mark for having been processed
int nProcessedDeath = GetLocalInt(oCreature, "ProcessedDeath");
if (nProcessedDeath)
{
return;
}
SetLocalInt(oCreature, "ProcessedDeath", TRUE);
// Find parent if not passed in
if (oSpawn == OBJECT_INVALID)
{
oSpawn = GetLocalObject(oCreature, "ParentSpawn");
}
object oArea = GetArea(oCreature);
SPAWN_DELAY_DEBUG = GetLocalInt(oArea, "SpawnDelayDebug");
SPAWN_COUNT_DEBUG = GetLocalInt(oArea, "SpawnCountDebug");
SpawnDelayDebug(oSpawn, "creature " + ObjectToString(oCreature) + " died");
// Remove non-drop items
// StripNonDroppables(oCreature);
// Initialize DeathScripts
int nDeathScript;
float fCorpseDecay;
if (oSpawn == OBJECT_INVALID)
{
//debug("camp creature died");
string sCampFlags;
nCampCreature = TRUE;
sCampFlags = GetLocalString(oCreature, "CreatureFlags");
//debug("in process dead with flags " + sCampFlags);
fCorpseDecay = IntToFloat(GetFlagValue(sCampFlags, "CD", 0));
nDeathScript = GetFlagValue(sCampFlags, "DT", -1);
//debug("camp creature: cd = " + FloatToString(fCorpseDecay));
}
else
{
//debug("non-camp creature died");
nCampCreature = FALSE;
nDeathScript = GetLocalInt(oSpawn, "f_DeathScript");
fCorpseDecay = GetLocalFloat(oSpawn, "f_CorpseDecay");
//debug("not a camp creature: cd = " + FloatToString(fCorpseDecay));
}
// Run Death Script
if (nDeathScript > -1 && GetLocalInt(oCreature, "DeathScriptRan") == FALSE)
{
SetLocalInt(oCreature, "DeathScript", nDeathScript);
ExecuteScript("spawn_sc_death", oCreature);
}
// Spawn Corpse if Dead and No Corpse
if (fCorpseDecay > 0.0)
{
if (GetLocalObject(oCreature, "Corpse") == OBJECT_INVALID)
{
//debug("calling spawn_corpse_dth");
ExecuteScript("spawn_corpse_dth", oCreature);
}
}
else
{
if (GetLocalInt(GetModule(), "AlwaysDestroyCorpses"))
{
AssignCommand(oCreature, SetIsDestroyable(TRUE, FALSE, FALSE));
}
}
}
void ResetSpawn(object oSpawn, int nTimeNow)
{
// Reset the Spawn
SetLocalInt(oSpawn, "NextSpawnTime", nTimeNow);
//debug("set next spawn time on reset: " + IntToString(nTimeNow));
SetLocalInt(oSpawn, "SpawnDeactivated", FALSE);
SetLocalInt(oSpawn, "ChildrenSpawned", 0);
SetLocalInt(oSpawn, "CurrentProcessTick", 0);
SetLocalInt(oSpawn, "SpawnAgeTime", 0);
//debug("PC reset");
}
//
void SaveStateOnDespawn(object oSpawned, object oSpawn, int nCamp=FALSE)
{
string sSaveVarName;
// These are the values needed to recreate the spawned object where
// it was when it despawned
int nObjectType = 0;
string sTemplate;
location lLastLocation;
float fLastFacing;
float fHomeX;
float fHomeY;
int nReturnHome;
if (nCamp && !GetIsObjectValid(oSpawned))
{
SpawnCountDebug(oSpawn, "creating slot for dead camp object" +
ObjectToString(oSpawned));
sTemplate = "";
}
else
{
nObjectType = GetObjectType(oSpawned);
sTemplate = GetResRef(oSpawned);
lLastLocation = GetLocation(oSpawned);
fLastFacing = GetFacing(oSpawned);
fHomeX = GetLocalFloat(oSpawned, "HomeX");
fHomeY = GetLocalFloat(oSpawned, "HomeY");
// if the return home flag is on, respawn at the home point
if (nCamp)
{
nReturnHome = GetLocalInt(oSpawned, "f_ReturnHome");
}
else
{
nReturnHome = GetLocalInt(oSpawn, "f_ReturnHome");
}
if (nReturnHome)
{
vector vHome = Vector(fHomeX, fHomeY, 0.0);
location lHome = Location(GetArea(oSpawned), vHome, fLastFacing);
lLastLocation = lHome;
}
}
int nNumberSaveStates = GetLocalInt(oSpawn, "SpawnNumSavedStates");
SetLocalInt(oSpawn, "SpawnNumSavedStates", ++nNumberSaveStates);
string sSaveVarNameBase = "SpawnedSaveState" + IntToString(nNumberSaveStates);
SpawnCountDebug(oSpawn, "PC despawn save count: " + IntToString(nNumberSaveStates));
// Save the stuff needed to respawn
sSaveVarName = sSaveVarNameBase + "ObjectType";
SetLocalInt(oSpawn, sSaveVarName, nObjectType);
sSaveVarName = sSaveVarNameBase + "Template";
SetLocalString(oSpawn, sSaveVarName, sTemplate);
sSaveVarName = sSaveVarNameBase + "LastLocation";
SetLocalLocation(oSpawn, sSaveVarName, lLastLocation);
sSaveVarName = sSaveVarNameBase + "HomeX";
SetLocalFloat(oSpawn, sSaveVarName, fHomeX);
sSaveVarName = sSaveVarNameBase + "HomeY";
SetLocalFloat(oSpawn, sSaveVarName, fHomeY);
// These need to be preserved so they can be rewritten to the respawned
// object; they may be used in ProcessSpawn
if (! nCamp)
{
float fSpawnFacing = GetLocalFloat(oSpawned, "SpawnFacing");
float fEntranceExitX = GetLocalFloat(oSpawned, "EntranceExitX");
float fEntranceExitY = GetLocalFloat(oSpawned, "EntranceExitY");
int iExpireTime = GetLocalInt(oSpawned, "LifespanExpireTime");
// Save the stuff we need to rewrite onto the spawn
sSaveVarName = sSaveVarNameBase + "SpawnFacing";
SetLocalFloat(oSpawn, sSaveVarName, fSpawnFacing);
sSaveVarName = sSaveVarNameBase + "EntranceExitX";
SetLocalFloat(oSpawn, sSaveVarName, fEntranceExitX);
sSaveVarName = sSaveVarNameBase + "EntranceExitY";
SetLocalFloat(oSpawn, sSaveVarName, fEntranceExitY);
sSaveVarName = sSaveVarNameBase + "LifeSpanExpireTime";
SetLocalInt(oSpawn, sSaveVarName, iExpireTime);
}
}
//
void SaveCampStateOnDespawn(object oCamp, object oSpawn)
{
// Note that most of what needs to be saved is on the camp object itself.
// This saves the camp object onto oSpawn
int nNumSavedCampStates = GetLocalInt(oSpawn,"SpawnNumSavedCampStates");
SetLocalInt(oSpawn, "SpawnNumSavedCampStates",++nNumSavedCampStates);
SpawnCountDebug(oSpawn, "PC despawn camp save count: " + IntToString(nNumSavedCampStates));
string sSaveCampVarName = "SpawnedSaveCampState" +
IntToString(nNumSavedCampStates);
SetLocalObject(oSpawn, sSaveCampVarName, oCamp);
}
//
void RestorePCDespawns(object oSpawn, int nTimeNow)
{
int nSpawnNumSavedStates = GetLocalInt(oSpawn, "SpawnNumSavedStates");
string sSaveVarNameBase;
string sSaveVarName;
int nChildNum;
object oSpawned;
int nObjectType;
string sTemplate;
location lLastLocation;
location lEntranceExit;
float fHomeX;
float fHomeY;
location lHome;
int iExpireTime;
int i;
SpawnCountDebug(oSpawn, "restoring " + IntToString(nSpawnNumSavedStates) + " objects");
for (i = 0; i < nSpawnNumSavedStates; i++)
{
nChildNum = i + 1;
sSaveVarNameBase = "SpawnedSaveState" + IntToString(nChildNum);
sSaveVarName = sSaveVarNameBase + "ObjectType";
nObjectType = GetLocalInt(oSpawn, sSaveVarName);
DeleteLocalInt(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "Template";
sTemplate = GetLocalString(oSpawn, sSaveVarName);
DeleteLocalString (oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "LastLocation";
lLastLocation = GetLocalLocation(oSpawn, sSaveVarName);
DeleteLocalLocation(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "SpawnFacing";
float fSpawnFacing = GetLocalFloat(oSpawn, sSaveVarName);
DeleteLocalFloat(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "HomeX";
fHomeX = GetLocalFloat(oSpawn, sSaveVarName);
DeleteLocalFloat(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "HomeY";
fHomeY = GetLocalFloat(oSpawn, sSaveVarName);
DeleteLocalFloat(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "EntranceExitX";
float fEntranceExitX = GetLocalFloat(oSpawn, sSaveVarName);
DeleteLocalFloat(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "EntranceExitY";
float fEntranceExitY = GetLocalFloat(oSpawn, sSaveVarName);
DeleteLocalFloat(oSpawn, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "LifeSpanExpireTime";
iExpireTime = GetLocalInt(oSpawn, sSaveVarName);
DeleteLocalInt(oSpawn, sSaveVarName);
if (! IsRestoreBlocked(oSpawn, lLastLocation, iExpireTime, nTimeNow))
{
object oSpawned = CreateObject(nObjectType, sTemplate, lLastLocation);
SpawnCountDebug(oSpawn, "restored " + sSaveVarNameBase + "object id: " +
ObjectToString(oSpawned));
lHome = Location(OBJECT_SELF, Vector(fHomeX, fHomeY, 0.), fSpawnFacing);
lEntranceExit = Location(OBJECT_SELF, Vector(fEntranceExitX,
fEntranceExitY, 0.), fSpawnFacing);
RecordSpawned(oSpawn, oSpawned, lHome, lEntranceExit, fSpawnFacing);
SetupSpawned(oSpawn, oSpawned, lHome, nTimeNow, FALSE);
// Lifespan expire time needs to be rewritten the the spawned object,
// since SetupSpawned generated a new one based on the current time...
SetLocalInt(oSpawned, "LifespanExpireTime", iExpireTime);
}
else
{
SpawnCountDebug(oSpawn, "restore blocked: " + sSaveVarNameBase);
}
}
int nNumSavedCampStates = GetLocalInt(oSpawn, "SpawnNumSavedCampStates");
// restore camps
for (i = 0; i < nNumSavedCampStates; i++)
{
int j;
int nCampNum = i + 1;
string sSaveCampVarName = "SpawnedSaveCampState" +
IntToString(nCampNum);
object oCamp = GetLocalObject(oSpawn, sSaveCampVarName);
DeleteLocalObject(oSpawn, sSaveCampVarName);
// respawn camp objects
//debug("restoring " + sSaveCampVarName);
nSpawnNumSavedStates = GetLocalInt(oCamp, "SpawnNumSavedStates");
int nPlaceableCount = 0;
int nCreatureCount = 0;
for (j = 0; j < nSpawnNumSavedStates; j++)
{
nChildNum = j + 1;
sSaveVarNameBase = "SpawnedSaveState" + IntToString(nChildNum);
//debug("restoring " + sSaveVarNameBase);
sSaveVarName = sSaveVarNameBase + "ObjectType";
//debug("Getting objtype with var name " + sSaveVarName);
nObjectType = GetLocalInt(oCamp, sSaveVarName);
DeleteLocalInt(oCamp, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "Template";
sTemplate = GetLocalString(oCamp, sSaveVarName);
//debug("template: " + sTemplate);
DeleteLocalString (oCamp, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "LastLocation";
lLastLocation = GetLocalLocation(oCamp, sSaveVarName);
DeleteLocalLocation(oCamp, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "HomeX";
fHomeX = GetLocalFloat(oCamp, sSaveVarName);
DeleteLocalFloat(oCamp, sSaveVarName);
sSaveVarName = sSaveVarNameBase + "HomeY";
fHomeY = GetLocalFloat(oCamp, sSaveVarName);
DeleteLocalFloat(oCamp, sSaveVarName);
lHome = Location(OBJECT_SELF, Vector(fHomeX, fHomeY, 0.), 0.);
sSaveVarName = sSaveVarNameBase + "LifeSpanExpireTime";
iExpireTime = GetLocalInt(oSpawn, sSaveVarName);
DeleteLocalInt(oSpawn, sSaveVarName);
string sObject;
if (nObjectType == OBJECT_TYPE_CREATURE)
{
sObject = "CampC" + IntToString(nCreatureCount++);
}
else if (nObjectType == OBJECT_TYPE_PLACEABLE)
{
sObject = "CampP"+ IntToString(nPlaceableCount++);
}
if (sTemplate != "")
{
if (! IsRestoreBlocked(oCamp, lLastLocation, iExpireTime, nTimeNow))
{
oSpawned = CreateObject(nObjectType, sTemplate, lLastLocation);
SetLocalObject(oCamp, sObject, oSpawned);
vector vCamp = GetPositionFromLocation(GetLocation(oSpawn));
string sFlags = GetLocalString(oCamp, sObject + "_Flags");
SetupCampSpawned(oSpawn, oSpawned, vCamp, lHome, sFlags);
// Lifespan expire time needs to be rewritten the the spawned object,
// since SetupSpawned generated a new one based on the current time...
SetLocalInt(oSpawned, "LifespanExpireTime", iExpireTime);
}
else
{
SetLocalObject(oCamp, sObject, OBJECT_INVALID);
}
}
else
{
SetLocalObject(oCamp, sObject, OBJECT_INVALID);
}
}
location lCampLocation = GetLocation(oSpawn);
float fCampFacing = GetFacing(oSpawn);
RecordSpawned(oSpawn, oCamp, lCampLocation, lCampLocation, fCampFacing);
}
SetLocalInt(oSpawn, "SpawnNumSavedStates", 0);
SetLocalInt(oSpawn, "SpawnNumSavedCampStates", 0);
}
//
void RecordSpawned(object oSpawn, object oSpawned, location lHome,
location lEntranceExit, float fSpawnedFacing)
{
int nChildrenSpawned;
int nSpawnCount;
int nChildSlot;
int nEmptyChildSlot;
object oChild;
string sChildSlot, sEmptyChildSlot;
string sCustomFlag = GetLocalString(oSpawn, "f_CustomFlag");
int nSpawnNumber = GetLocalInt(oSpawn, "f_SpawnNumber");
// Assign Values to oSpawned
SetLocalObject(oSpawned, "ParentSpawn", oSpawn);
SetLocalFloat(oSpawned, "SpawnFacing", fSpawnedFacing);
SetLocalFloat(oSpawned, "HomeX", GetPositionFromLocation(lHome).x);
SetLocalFloat(oSpawned, "HomeY", GetPositionFromLocation(lHome).y);
SetLocalFloat(oSpawned, "EntranceExitX", GetPositionFromLocation(lEntranceExit).x);
SetLocalFloat(oSpawned, "EntranceExitY", GetPositionFromLocation(lEntranceExit).y);
SetLocalString(oSpawned, "CustomFlag", sCustomFlag);
// Assign Values to oSpawn
nChildrenSpawned = GetLocalInt(oSpawn, "ChildrenSpawned");
nChildrenSpawned++;
SetLocalInt(oSpawn, "ChildrenSpawned", nChildrenSpawned);
nSpawnCount = GetLocalInt(oSpawn, "SpawnCount");
nSpawnCount++;
SetLocalInt(oSpawn, "SpawnCount", nSpawnCount);
// Find Empty Child Slot
nChildSlot = 1;
nEmptyChildSlot = 0;
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
// Check if this is Child Slot is Valid
if (GetIsObjectValid(oChild) == FALSE || GetIsDead(oChild))
{
// Empty Slot
if (nEmptyChildSlot == 0)
{
nEmptyChildSlot = nChildSlot;
sEmptyChildSlot = sChildSlot;
}
}
}
// Assign Child Slot
SpawnCountDebug(oSpawn, "recorded spawn " + GetTag(oSpawned) + " (" +
ObjectToString(oSpawned) + ") as " + sEmptyChildSlot);
SetLocalObject(oSpawn, sEmptyChildSlot, oSpawned);
SetLocalString(oSpawned, "ParentChildSlot", sEmptyChildSlot);
object oIdiot = GetLocalObject(oSpawn, sEmptyChildSlot);
string sValid = GetIsObjectValid(oIdiot) ? "valid" : "invalid";
}
//
// Returns 0 if no empty slots
int FindNextEmptyChildSlot(object oSpawn)
{
int nChildSlot;
int nEmptyChildSlot;
object oChild;
string sChildSlot;
int nSpawnNumber = GetLocalInt(oSpawn, "f_SpawnNumber");
nChildSlot = 1;
nEmptyChildSlot = 0;
for (nChildSlot = 1; nChildSlot <= nSpawnNumber; nChildSlot++)
{
// Retrieve Child
sChildSlot = "ChildSlot" + PadIntToString(nChildSlot, 2);
oChild = GetLocalObject(oSpawn, sChildSlot);
// Check if this is Child Slot is Valid
if (GetIsObjectValid(oChild) == FALSE || GetIsDead(oChild))
{
// Empty Slot
nEmptyChildSlot = nChildSlot;
break;
}
}
return nEmptyChildSlot;
}
void SetupSpawned(object oSpawn, object oSpawned, location lHome,
int nTimeNow, int nWalkToHome = FALSE)
{
object oFaction;
int nChildLifespanExpireTime;
int nGoldAmount;
effect eObject;
int nSpawnFaction = GetLocalInt(oSpawn, "f_SpawnFaction");
int nSpawnSit = GetLocalInt(oSpawn, "f_SpawnSit");
int nSpawnPlot = GetLocalInt(oSpawn, "f_SpawnPlot");
int nSpawnAlignment = GetLocalInt(oSpawn, "f_SpawnAlignment");
int nAlignmentShift = GetLocalInt(oSpawn, "f_AlignmentShift");
int nChildLifespanMax = GetLocalInt(oSpawn, "f_ChildLifespanMax");
int nChildLifespanMin = GetLocalInt(oSpawn, "f_ChildLifespanMin");
int nRandomGold = GetLocalInt(oSpawn, "f_RandomGold");
int nRandomGoldMin = GetLocalInt(oSpawn, "f_RandomGoldMin");
int nGoldChance = GetLocalInt(oSpawn, "f_GoldChance");
int nLootTable = GetLocalInt(oSpawn, "f_LootTable");
int nTrapDisabled = GetLocalInt(oSpawn, "f_TrapDisabled");
float fCorpseDecay = GetLocalFloat(oSpawn, "f_CorpseDecay");
int nCorpseDecayType = GetLocalInt(oSpawn, "f_CorpseDecayType");
int bDropWielded = GetLocalInt(oSpawn, "f_CorpseDropWielded");
int bDeleteLootOnDecay = GetLocalInt(oSpawn, "f_CorpseDeleteLootOnDecay");
string sCorpseRemainsResRef = GetLocalString(oSpawn, "f_CorpseRemainsResRef");
int nDeathScript = GetLocalInt(oSpawn, "f_DeathScript");
int nSpawnScript = GetLocalInt(oSpawn, "f_SpawnScript");
int nSpawnAreaEffect = GetLocalInt(oSpawn, "f_SpawnAreaEffect");
float fAreaEffectDuration = GetLocalFloat(oSpawn, "f_AreaEffectDuration");
int nObjectEffect = GetLocalInt(oSpawn, "f_ObjectEffect");
float fObjectEffectDuration = GetLocalFloat(oSpawn, "f_ObjectEffectDuration");
string sSpawnTag = GetLocalString(oSpawn, "f_Template");
int nPatrolRoute = GetLocalInt(oSpawn, "f_PatrolRoute");
int nPatrolStartAtClosest = GetLocalInt(oSpawn, "f_PatrolStartAtClosest");
int nRouteType = GetLocalInt(oSpawn, "f_RouteType");
int nRandomWalk = GetLocalInt(oSpawn, "f_RandomWalk");
float fWanderRange = GetLocalFloat(oSpawn, "f_WanderRange");
int nSuppressLooting = GetLocalInt(oSpawn, "f_SuppressLooting");
int nSubdualMode = GetLocalInt(oSpawn, "f_SubdualMode");
int nEncounterLevel = GetLocalInt(oSpawn, "f_EncounterLevel");
if (nWalkToHome)
{
AssignCommand(oSpawned, ActionMoveToLocation(lHome));
}
// Spawn it in with the right facing, and you don't need this; and
// then it works for placeables as well!
// AssignCommand(oSpawned, ActionDoCommand(SetFacing(fSpawnedFacing)));
// Set up SpawnPlot
if (nSpawnPlot == TRUE)
{
SetPlotFlag(oSpawned, TRUE);
}
// Set up Faction
if (nSpawnFaction > -1)
{
switch (nSpawnFaction)
{
case 0:
ChangeToStandardFaction(oSpawned, STANDARD_FACTION_COMMONER);
break;
case 1:
ChangeToStandardFaction(oSpawned, STANDARD_FACTION_DEFENDER);
break;
case 2:
ChangeToStandardFaction(oSpawned, STANDARD_FACTION_MERCHANT);
break;
case 3:
ChangeToStandardFaction(oSpawned, STANDARD_FACTION_HOSTILE);
break;
case 4:
oFaction = GetNearestObjectByTag("SpawnFaction", oSpawned);
if (oFaction != OBJECT_INVALID)
{
ChangeFaction(oSpawned, oFaction);
}
break;
}
}
// Set up Alignment
if (nSpawnAlignment > -1)
{
switch (nSpawnAlignment)
{
case 0:
AdjustAlignment(oSpawned, ALIGNMENT_NEUTRAL, nAlignmentShift);
break;
case 1:
AdjustAlignment(oSpawned, ALIGNMENT_LAWFUL, nAlignmentShift);
break;
case 2:
AdjustAlignment(oSpawned, ALIGNMENT_CHAOTIC, nAlignmentShift);
break;
case 3:
AdjustAlignment(oSpawned, ALIGNMENT_GOOD, nAlignmentShift);
break;
case 4:
AdjustAlignment(oSpawned, ALIGNMENT_EVIL, nAlignmentShift);
break;
case 5:
AdjustAlignment(oSpawned, ALIGNMENT_ALL, nAlignmentShift);
break;
}
}
// Set up Lifespan
if (nChildLifespanMax > -1)
{
if (nChildLifespanMin > -1)
{
nChildLifespanExpireTime = -1;
while (nChildLifespanExpireTime < nChildLifespanMin)
{
nChildLifespanExpireTime = nTimeNow + Random(nChildLifespanMax) + 1;
}
}
else
{
nChildLifespanExpireTime = nTimeNow + nChildLifespanMax;
}
SetLocalInt(oSpawned, "LifespanExpireTime", nChildLifespanExpireTime);
}
// Give Creature Loot
if (nLootTable > -1)
{
DelayCommand(1.0, LootTable(oSpawn, oSpawned, nLootTable));
}
// Give RandomGold
if (nRandomGold > 0)
{
// One in Four Creatures give Gold
if (d100(1) <= nGoldChance)
{
// Calculate Gold to Drop
nGoldAmount = Random(nRandomGold + 1);
while (nGoldAmount < nRandomGoldMin)
{
nGoldAmount = Random(nRandomGold + 1);
}
// Give Gold
CreateItemOnObject("nw_it_gold001", oSpawned, nGoldAmount);
}
}
// Set up Trap on Placeable
if (GetIsTrapped(oSpawned))
{
if (d100(1) <= nTrapDisabled)
{
SetTrapDisabled(oSpawned);
}
}
// Set up Corpse Decay
if (fCorpseDecay > 0.0)
{
SetLocalFloat(oSpawned, "CorpseDecay", fCorpseDecay);
SetLocalInt(oSpawned, "CorpseDecayType", nCorpseDecayType);
SetLocalString(oSpawned, "CorpseRemainsResRef", sCorpseRemainsResRef);
SetLocalInt(oSpawned, "CorpseDropWielded", bDropWielded);
SetLocalInt(oSpawned, "CorpseDeleteLootOnDecay", bDeleteLootOnDecay);
AssignCommand(oSpawned, SetIsDestroyable(FALSE, FALSE, FALSE));
}
// Set up Death Script
if (nDeathScript > -1)
{
AssignCommand(oSpawned, SetIsDestroyable(FALSE, FALSE, FALSE));
}
// Set up Object Effects
if (nObjectEffect > 0)
{
eObject = ObjectEffect(oSpawn);
if (fObjectEffectDuration == -1.0)
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eObject, oSpawned, 0.0);
}
else
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eObject, oSpawned, fObjectEffectDuration);
}
}
// Set up Area Effect
if (nSpawnAreaEffect > 0 && sSpawnTag == "AE" && fAreaEffectDuration > 0.0)
{
DestroyObject(oSpawned, fAreaEffectDuration);
}
// Run the Spawn Script
if (nSpawnScript > -1)
{
SetLocalInt(oSpawned, "SpawnScript", nSpawnScript);
ExecuteScript("spawn_sc_spawn", oSpawned);
}
// Set up Random Walking
if (nRandomWalk == TRUE)
{
if (fWanderRange > 0.0)
{
AssignCommand(oSpawned, RandomWalk(oSpawn, fWanderRange, FALSE));
}
else
{
AssignCommand(oSpawned, ActionRandomWalk());
}
}
// Set up the Patrol Route
if (nPatrolRoute > -1)
{
AssignCommand(oSpawned, SetPatrolRoute(nPatrolRoute,
nPatrolStartAtClosest));
AssignCommand(oSpawned, DoPatrolRoute(nPatrolRoute, nRouteType));
}
// Set up Spawn Sit
if (nSpawnSit == TRUE)
{
FindSeat(oSpawn, oSpawned);
}
// Set up loot suppression
if (nSuppressLooting)
{
SetLocalInt(oSpawned, "DoNotLoot", TRUE);
}
// Set up subdual mode
if (nSubdualMode)
{
SetLocalInt(oSpawned, "SubdualMode", TRUE);
}
// Set up encounter level
if (nEncounterLevel > 0)
{
SetLocalInt(oSpawned, "AlfaEncounterLevel", nEncounterLevel);
}
SetupCustomFlags(oSpawn, oSpawned);
}
//
void SetupCampSpawned(object oSpawn, object oSpawned, vector vCampPosition,
location lHome, string sFlags)
{
//debug("in setupCampSpawned");
// This is the closest we get to an "InitFlags" call for camp creatures
// write the flags onto the spawned creature
SetLocalString(oSpawned, "CreatureFlags", sFlags);
int nSpawnFacing = IsFlagPresent(sFlags, "SF");
int nLootTable = GetFlagValue(sFlags, "LT", -1);
int nTrapDisabled = GetSubFlagValue(sFlags, "PL", "T", 100);
int nRandomWalk = IsFlagPresent(sFlags, "RW");
SetLocalInt(oSpawned, "f_RandomWalk", nRandomWalk);
float fCorpseDecay = IntToFloat(GetFlagValue(sFlags, "CD", 0));
int nCorpseDecayType = GetSubFlagValue(sFlags, "CD", "T", 0);
int nCorpseRemainsType = GetSubFlagValue(sFlags, "CD", "R", 0);
int bDropWielded = IsSubFlagPresent(sFlags, "CD", "D");
int nDeathScript = GetFlagValue(sFlags, "DT", -1);
int nReturnHome = IsFlagPresent(sFlags, "RH");
SetLocalInt(oSpawned, "f_ReturnHome", nReturnHome);
if (nReturnHome)
{
int dfReturnHomeRange = GetLocalInt(GetModule(), "df_ReturnHomeRange");
float fReturnHomeRange = IntToFloat(GetFlagValue(sFlags, "RH",
dfReturnHomeRange));
SetLocalFloat(oSpawned, "f_ReturnHomeRange", fReturnHomeRange);
SetLocalFloat(oSpawned, "HomeX", GetPositionFromLocation(lHome).x);
SetLocalFloat(oSpawned, "HomeY", GetPositionFromLocation(lHome).y);
}
// Spawn Facing
if (nSpawnFacing == TRUE)
{
AssignCommand(oSpawned, SetFacingPoint(vCampPosition));
}
else
{
AssignCommand(oSpawned, SetFacing(IntToFloat(Random(360))));
}
// Loot Table
if (nLootTable > -1)
{
LootTable(oSpawn, oSpawned, nLootTable);
}
// Trap Disabled
if (GetIsTrapped(oSpawned))
{
if (d100(1) <= nTrapDisabled)
{
SetTrapDisabled(oSpawned);
}
}
// RandomWalk
if (nRandomWalk == TRUE)
{
AssignCommand(oSpawned, ActionRandomWalk());
}
// Corpse Decay
if (fCorpseDecay > 0.0)
{
string sCorpseRemainsResRef;
int bDeleteLootOnDecay = FALSE;
switch (nCorpseRemainsType)
{
case 0: sCorpseRemainsResRef = "invis_corpse_obj"; break;
case 1: sCorpseRemainsResRef = "invis_corpse_bdy"; break;
case 2: sCorpseRemainsResRef = "invis_corpse_bon"; break;
case 3: sCorpseRemainsResRef = "invis_corpse_pot"; break;
case 4: sCorpseRemainsResRef = "invis_corpse_pch"; break;
case 5: sCorpseRemainsResRef = "invis_corpse_scr"; break;
case 6: sCorpseRemainsResRef = "invis_corpse_tre"; break;
case 7:
sCorpseRemainsResRef = "invis_corpse_obj";
bDeleteLootOnDecay = TRUE;
break;
}
// Record CorpseDecay
SetLocalString(oSpawned, "CorpseRemainsResRef", sCorpseRemainsResRef);
SetLocalInt(oSpawned, "CorpseDropWielded", bDropWielded);
SetLocalInt(oSpawned, "CorpseDeleteLootOnDecay", bDeleteLootOnDecay);
SetLocalFloat(oSpawned, "CorpseDecay", fCorpseDecay);
SetLocalInt(oSpawned, "CorpseDecayType", nCorpseDecayType);
AssignCommand(oSpawned, SetIsDestroyable(FALSE, FALSE, FALSE));
}
// Death Script
if (nDeathScript > -1)
{
AssignCommand(oSpawned, SetIsDestroyable(FALSE, FALSE, FALSE));
}
}
int SetupSpawnDelay(int nSpawnDelay, int nDelayRandom, int nDelayMinimum,
int nTimeNow)
{
int nNextSpawnTime;
if (nDelayRandom == TRUE)
{
// Setup Next Spawn Randomly
nNextSpawnTime = Random(nSpawnDelay) + 1;
while (nNextSpawnTime < nDelayMinimum)
{
nNextSpawnTime = Random(nSpawnDelay) + 1;
}
nNextSpawnTime += nTimeNow;
}
else
{
// Setup Next Spawn
nNextSpawnTime = nTimeNow + nSpawnDelay;
}
return nNextSpawnTime;
}
int IsRestoreBlocked(object oSpawn, location lChildLoc, int iExpireTime,
int nTimeNow)
{
int nSpawnBlock = FALSE;
// Initialize Day/Night Only
int nDayOnly = GetLocalInt(oSpawn, "f_DayOnly");
int nDayOnlyDespawn = GetLocalInt(oSpawn, "f_DayOnlyDespawn");
int nNightOnly = GetLocalInt(oSpawn, "f_NightOnly");
int nNightOnlyDespawn = GetLocalInt(oSpawn, "f_NightOnlyDespawn");
// Initialize Day/Hour Spawns
int nDay, nHour;
int nSpawnDayStart = GetLocalInt(oSpawn, "f_SpawnDayStart");
int nSpawnDayEnd = GetLocalInt(oSpawn, "f_SpawnDayEnd");
int nSpawnHourStart = GetLocalInt(oSpawn, "f_SpawnHourStart");
int nSpawnHourEnd = GetLocalInt(oSpawn, "f_SpawnHourEnd");
// Initialize Child Lifespan
int nChildLifespanMax = GetLocalInt(oSpawn, "f_ChildLifespanMax");
// Initialize SpawnUnseen
float fSpawnUnseen = GetLocalFloat(oSpawn, "f_SpawnUnseen");
int nUnseenIndividual = GetLocalInt(oSpawn, "f_UnseenIndividual");
// Check Against Spawn Unseen (_SUnn|I_)
if (fSpawnUnseen > 0.0)
{
if (nUnseenIndividual)
{
vector vChildPos = GetPositionFromLocation(lChildLoc);
if (CheckPositionUnseen(vChildPos, fSpawnUnseen) == FALSE)
{
nSpawnBlock = TRUE;
}
}
else
{
vector vSpawnPos = GetPositionFromLocation(GetLocation(oSpawn));
if (CheckPositionUnseen(vSpawnPos, fSpawnUnseen) == FALSE)
{
nSpawnBlock = TRUE;
}
}
}
// Check Against Night Only. Since this is a restore of something already
// spawned, it should only be blocked if despawn has been specified for the
// creature (_NOD_)
if (nNightOnly && nNightOnlyDespawn)
{
if (GetIsDay() || GetIsDawn())
{
nSpawnBlock = TRUE;
}
}
// Check Against Day Only (_DOD_)
if (nDayOnly && nDayOnlyDespawn)
{
if (GetIsDay() == FALSE && GetIsDawn() == FALSE)
{
nSpawnBlock = TRUE;
}
}
// Check Against Specific Day(s) (_DYnn_)
if (nSpawnDayStart > -1)
{
nDay = GetCalendarDay();
if (IsBetweenDays(nDay, nSpawnDayStart, nSpawnDayEnd) == FALSE)
{
nSpawnBlock = TRUE;
}
}
// Check Against Specific Hour(s) (_HRnn_)
if (nSpawnHourStart > -1)
{
nHour = GetTimeHour();
if (IsBetweenHours(nHour, nSpawnHourStart, nSpawnHourEnd) == FALSE)
{
nSpawnBlock = TRUE;
}
}
// Check Lifespan (_CLnn_)
if (nChildLifespanMax > -1)
{
if (nTimeNow >= iExpireTime)
{
//debug("restore: lifespawn exceeded");
nSpawnBlock = TRUE;
}
}
return nSpawnBlock;
}
int NeedPseudoHeartbeat( object oArea )
{
int bPCsInArea = GetLocalInt( oArea, SPAWN_PCS_IN_AREA );
int nAreaSpawnCount = GetLocalInt( oArea, SPAWN_AREA_COUNT );
int bHeartbeatScheduled = GetLocalInt( oArea, SPAWN_HEARTBEAT_SCHEDULED );
int bLeftoversForceProcessing = GetLocalInt( GetModule(),
"LeftoversForceProcessing");
// Do a heartbeat if there are PCs in the area or any spawns up, and we
// don't already have a heartbeat scheduled
if (bLeftoversForceProcessing)
{
return ( (bPCsInArea || nAreaSpawnCount) && ! bHeartbeatScheduled );
}
return ( bPCsInArea && ! bHeartbeatScheduled );
}
void Spawn_OnAreaEnter( string sHeartbeatScript = "spawn_sample_hb",
float fHeartbeatInterval = 6.0, float fFirstDelay = 0.0 )
{
object oPC = GetEnteringObject();
object oArea = OBJECT_SELF;
SetLocalString( oArea, SPAWN_HEARTBEAT_SCRIPT, sHeartbeatScript );
SetLocalFloat( oArea, SPAWN_INTERVAL, fHeartbeatInterval );
if ( GetIsPC( oPC ) )
{
SetLocalInt(oPC, "NESS_Player", TRUE);
int nPCsInArea = GetLocalInt( oArea, SPAWN_PCS_IN_AREA );
int nAreaSpawnCount = GetLocalInt( oArea, SPAWN_AREA_COUNT );
nPCsInArea++;
SetLocalInt( oArea, SPAWN_PCS_IN_AREA, nPCsInArea );
if ( NeedPseudoHeartbeat( oArea ) )
{
if ( fFirstDelay > 0.0 )
{
DelayCommand( fFirstDelay, ExecuteScript( "spawn_pseudohb", oArea ) );
}
else
{
ExecuteScript( "spawn_pseudohb", oArea );
}
}
}
}
void Spawn_OnAreaExit()
{
object oPC = GetExitingObject();
object oArea = OBJECT_SELF;
int bIsPC = GetLocalInt(oPC, "NESS_Player");
if ( bIsPC )
{
int nPCsInArea = GetLocalInt( oArea, SPAWN_PCS_IN_AREA );
nPCsInArea--;
SetLocalInt( oArea, SPAWN_PCS_IN_AREA, nPCsInArea );
}
}
void ScheduleNextPseudoHeartbeat( object oArea )
{
float fInterval = GetLocalFloat( oArea, SPAWN_INTERVAL );
if ( fInterval == 0.0 )
{
fInterval = 6.0;
}
DelayCommand( fInterval, ExecuteScript( "spawn_pseudohb", oArea ) );
SetLocalInt( oArea, SPAWN_HEARTBEAT_SCHEDULED, TRUE );
}