// // 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 ); }