/*## # UO Style Spawn System v2.2 # Author: Palor # Description: # This script enables you to place "spawners" that can make # a location keep X number of creatures spawned, with delays # and even just at night or during the day. # # Features: # -Spawn up to 99 creatures. # -Spawn a random amount of creatures between 1 and 99. # -Spawn a group of creatures. # -Spawn random creatures from a group. # -Create your own groups or customize existing ones. # -Use a delay of up to 99 hours between each spawn. # -Use random delay of up to 99 hours. # -Spawn just at night or during the day. # -Spawn only at a specific hour or between certain hours. # -Spawn only on a specific day or between certain days. # -Spawn only if a PC is within up to 99 meters. # -Spawn creatures in random locations within a specified radius # of the spawn point. # -Spawn creatures in random locations around the players. # -Tell spawn point not to spawn if a player enters the radius # and are already in combat. # -Spawn treasure chests or any other valid Placeable. # -Use Effects when it spawns or kills the creatures. # -Setup radius based damage (traps) and have effects applied # to simulate poisonous fogs or other effect. # -Easily create "magic" amulets that can protect players # from the "traps". # -Have spawned creatures walk around randomly without editing # their OnSpawn scripts. # -Generate treasure on spawned creatures without editing # their OnSpawn scripts. # -Have the spawner wait until all creatures are killed before # spawning again. # -Tell the spawner to stop spawning after all the creatures # it spawns are killed. # -One script :) # ##* # Installation. # # 1. Create an invisible object and attach this script to # it's Heartbeat. (You only need the one object for all # your spawn points in the area). # 2. Decide what creature you want to spawn and make a note # of it's Tag or create a custom creature. # 3. Place a Waypoint and edit the properties to look like: # # Name: SP_SX01 # Tag : TagOfCreatureYouWantToSpawn # # The above would make a single spawn point which would # always keep one of your creatures spawned there. # # NOTE: # Waypoint and Post works with this script. # Example: # Name: SP_SX01 # Tag : POST_NW_DOG # # The above would keep one dog spawned at the waypoint and # the creature would return to it after combat. # ##* # Switches # # Switches are used in the Name of the Spawn Point (Waypoint) # and control how the Spawn Point spawns. # Example: # Name: SP_SX05_TM10_NT_RD05 # # Will keep 5 creatures spawned only at night, only if # a player is within 5 meters and will wait 10 seconds # before spawning and will wait 10 seconds after each # creature is killed before spawning a new one. # # Current Switches: # # SP_ Tells the Spawn Control Object that this Waypoint is # a Spawn Point. # # SRnn Spawn creatures in a random location within "nn" meters. # # NP When used with SR, it spawns in random locations near # the closest player to the spawn point. # # RDnn Only spawn creatures if a Player is within "nn" meters. # # IC Do not spawn when a player enters the radius and # is already in combat. # # NT Only spawn at night time and kill any creatures left # when it turns day. # # DT Only spawn during the day and kill any creatures left # when it turns night. # # SHnnTyy Spawn only at nn hour of the day. This is in 23 hour # format. If T is specified it will spawn between the # hours of nn and yy. # Example: # SH23 - Spawn only while it is 11pm. # SH00 - Spawn only while it is midnight. # SH01 - Spawn only while it is 1am. # SH01T03 - Spawn only between 1am and 3am. # # SDnnTyy Spawn only on nn day of the month. If T is specified # it will only spawn between the days of nn and yy. # Example: # SD01 - Spawn only the first day of the month. # SD01T03 - Spawn only between the first and third # days of the month. # # TR Spawns any valid Placeable (used for treasure chests). # Please read the section in the orginal post for this # release on how to make a treasure chest if you are # not familiar with creating treasure chests. # # RW If specified, the creature will walk randomly around # after spawning. If the creature moves to another zone # it will cease to randm walk unless you uncomment # the HeartBeat in the creatures OnSpawn script. # # SS Stops Spawn when all creatures are killed at spawn # point. NOTE: ALL creatures must be killed. The # spawn point will continue to spawn until it finds # no creatures at the spawn point. # # SXnnRyy Keep "nn" creatures spawned at this Spawn Point. # If R is specified, it spawns a random number of # creatures between nn and yy. # Examples: # SX02 - Keep 2 creatures spawned. # SX01R10 - Spawn a random amount between 1 and 10. # NOTE: nn is the MINIMUM you want. If you specify # 01 as the minimum, it will not spawn anymore until # they are ALL dead. # # TMxxRyy Delay spawns by "xx" seconds. Specify Minutes by adding # the M on the end or specify Hours by adding a H. # Use R to generate a random number between xx and yy. # Examples: # TM02 - Delay spawn for 2 seconds. # TM02M - Delay spawn for 2 minutes. # TM02H - Delay spawn for 2 hours. # TM10R30 - Random between 10 and 30 seconds. # TM10R30M - Random between 10 and 30 minutes. # TM10R30H - Random between 10 and 30 hours. # # DS Wait until all creatures are killed before spawning # any more. # # NF When used with the timers it tells the spawn system # to NOT bypass the timers on the very first spawn. # # VSnn Tells the spawner to use effect nn on the location # before spawning. Valid effects are: # 01 - VFX_FNF_SUMMON_MONSTER_1 # 02 - VFX_FNF_SUMMON_MONSTER_2 # 03 - VFX_FNF_SUMMON_MONSTER_3 # 04 - VFX_FNF_SUMMON_UNDEAD # 05 - VFX_FNF_SUNBEAM # 06 - VFX_FNF_WAIL_O_BANSHEES # 07 - VFX_FNF_STORM # 08 - VFX_FNF_STRIKE_HOLY # 09 - VFX_FNF_IMPLOSION # # VKnn Same as above, except it happens when the spawner # kills a creature due to it not being a valid # spawn time. Example would be if it turned night # and the creature is suppose to only spawn during # the day :) # # TPnnAyy Use trap nn at the spawn point. This works with # creature spawns. If A is specified and an amulet is # listed in the amulet section, whoever is wearing it # will not be affected. # Examples: # TP01 - Use trap 01. # TP01A01 - Amulet 01 protects against the trap. # TP01A02 - Amulet 02 protects against the trap. # Traps are "Damage Effects" with a visual effect # applied to the target. # # GTnn Generate treasure. If specified it will generate # treasure on the creatures that are spawned. This # uses the GenerateTreasure function found in the # default NW_O2_CONINCLUDE file. # Valid types are: # GT01 - Generate low treasure. # GT02 - Generate medium treasure. # GT03 - Generate high treasure. # GT04 - Generate boss treasure. # GT05 - Generate book treasure. # # CPnn Spawn a creature camp. # Example: # CP01 - Will place the objects listed in camp01 # in random locations around the site. # # GP Spawn a group of creatures using the default # group templates. These can be customized if you # so desire :) NOTE: The SX tag is not used when # spawning groups without the GR switch. # Example: # Name: SP_GP # Tag : Group01 # # GR Spawn a random creature from the specified group. # When used with the SX switch it will spawn up # to "nn" random creatures from the specified # group. # Example: # Name: SP_SX03_GP_GR # Tag : Group01 # ##* # Default Groups # # Group 01 # Creature 1 - NW_SKELETON # Creature 2 - NW_LICH003 # Creature 3 - NW_GHOUL # Creature 4 - NW_MUMMY # Creature 5 - NW_WRAITH # # Group 02 # Creature 1 - NW_ORCA # Creature 2 - NW_ORCB # Creature 3 - NW_OrcChiefA # Creature 4 - NW_ORCCHIEFB # Creature 5 - NW_ORCWIZA # ##* # Default Camps # # Object 1 - Corpse wagon. # ##* # Changes # # 2.2.2b # - Fixed bug with Traps. - Reported by keet # # 2.2.2 # - Modified minor functions to lessen CPU usage. # - Finished code structure support for Champions and Area Effects # # 2.2.1b # - Added RF feature which tells the creature to face a # random direction after spawning. - Requested by jwvanderbeck # - Added AE which is used to add an Area Effect to a location. # - Requested by Master_of_Magic # # 2.2.1a # - Added random spawn for Champions # # 2.2.1 # - Fixed bug with deleting creatures spawned using random # option. - Reported by jwvanderbeck # - Added support for Champion Spawns using CHnn. # # 2.2 # - Added DS for delaying spawn until are creatures are killed. # - Suggested by Michael L. Hoehne # - Added SH and SD for spawning only at a certain hour(s) of # the day or on a certain day(s) of the month. # - Suggested by MokahTGS # - Added TP for trap effects. - Suggested by Moose_Dude # - Added CP for spawning camp items. # # 2.1.9e # - Modified a few functions to use less CPU. # - Changed how the spawn points keep track of objects # due to a new feature being implemented in 2.2 # # 2.1.9d # - Fixed bug with default orc group. - Reported by Qobra # - Changed GP to spawn whole group and added GR for using # random creatures from the group. # # 2.1.9a - c # - Modified some code structure to lessen load on CPU. # - Fixed bug with RD. - Reported by Qobra # - Added GT function to generate treasure on creatures. # - Added default Orc group (Group02). # # 2.1.9 # - More code cleanup :) # - Added GP for use with spawning groups. # - Added default Undead group (Group01). # # 2.1.8 # - Major code changes to reduce CPU usage. Also made # modifications that will be used by version 2.2 # # 2.1.7b # - Fixed bug with Random when it was only 2 max :) # - Reported by Karthal # - Added S switch for SXnn. When used it spawns each # create seperate. It will use a delay if specified # with TM, but it will not work with random number # of creatures. # Examples: # SX05S - Will spawn 5 creatures, one at a time. # SX05S_TM10 - Will spawn 5 creatures, one at a time # and with a 10 second delay. # # 2.1.7a # - Fixed a bug with delay not working with radius. # - Reported by SebastianCain # # 2.1.7 # - Added NP, which when used with SR, spawns in random # locations around the nearest player. # - Suggested by Karthal # - Added NF, which tells the spawned to not spawn the first # batch bypassing the timers. - Suggested by Karthal # - Added IC, which when used with RD, tells the spawner # not to spawn when a player enters the radius and # is already in combat. - Suggested by Karthal # - Added SS, which stops the spawn after all creatures # are killed. - Suggested by -Mange- # # 2.1.6a # - Modified RW so that every check it will have the # creature random walk if it is not in combat or # in a conversation. - Suggested by Qobra # # 2.1.6 # - Modified random counter. - Reported by Dhoff # - Added Hours for delay. - Requested by multiple people # - Added Effect for when spawner kills creatures. # - Added RW (RandomWalk) # # 2.1.5b # - Fixed a bug with MIN not counting correctly. # - Reported by EVERYONE :) # # 2.1.5a # - Removed where it took 1 off the total of spawns when # used with the random option. - Reported by stefulia # # 2.1.5 # - Added effects for spawning. # # 2.1.4b # - Fixed a problem with WP_ tag where it would chop off # the last 2 numbers. - Reported by Noggy # # 2.1.4a # - Added Spawn Radius (SR), which will spawn in a random # location within specified radius. This is now # seperate from RD. - Requested by TooKool # # 2.1.4 # - Added ability to spawn any Placeable object. This # implemented in order to have it spawn treasure # chests, but could be used for any Placeable. # - Added random number of creature spawns. (SXnnRyy) # Examples: # SX02 - Keep 2 creatures spawned. # SX01R10 - Spawn a random amount between 1 and 10. # Requested by stefulia # - Fixed timer bug where minimum would stay seconds # even if Minutes was specified. - Reported by jRaskell # - Modified timer so that it is not used when a player # first enters an area IF a Radius is set. This means # that if you have a timer set for 20 minutes, there # will always be a creature when the player FIRST # enters the Radius. Timer takes effect AFTER they # enter the area. - Requested by someone?? # # 2.1.3 # - Creatures will now spawn at once the first time # it is a VALID time to spawn. This means that # when you first load the module, any spawn point # that is valid will spawn without a delay the first # time. If there is a delay, it will delay each time # thereafter. This was requested by multiple people :) # - Added Random Spawn Points (RDnnX) within a radius. # Example: # RD10 = Check if PC is within 10 meters and spawn # creatures at spawn point. # RD10X = Check if PC is within 10 meters and spawn # creatures at random places within that 10 # meter area. # **THE X WAS REMOVED 2.1.5** # 2.1.2 # - Added fix for POST_ so that creatures can return # back to spawn point. - Reported by stefulia # - Added Random option for timer - Suggested by stefulia # # 2.1.1 # - Modified code structure to account for future changes. # - Changed how it spawns and how it checks for creatures # to account for creatures it spawns. Meaning it will # only CHECK for creatures it spawns and it will only # kill creatures it spawns :) # # 2.1 (The real 2.0) # - Rewrote code # - Changed DY to DT - Suggested by Iceyflame # - Added an optional M for TMnn so you can specify Minutes # Example: # TM05M = 5 minutes # TM05 = 5 seconds # - Creatures who only spawn during the day#night will now not # be killed by the spawner if they are in combat and the time # of day changes. # - Changed Radius so that if one is specified and there are # no players left in area after a spawn, creatures are killed. # # 2.0 # - Added RD switch (Radius) - Suggested by Iceyflame # # 1.2 # - Added DY & NT switches (Day or Night) - Suggested by Iceyflame # - Fixed a bug with it taking of NW_ - Reported by Spike- # - Fixed other stuff # # 1.1 # - Added SX (Spawn multiple) # - Added TM (Timer) # ##*/ #include "NW_O2_CONINCLUDE" int iDebug = 0; void sp_DestroyObject(object oNearest, string sTagType); void sp_CheckVars(object oNearest, string sCurrentName); void sp_Spawn(object oNearest, string sTemplate, int iSpawnX); void sp_TagObject(object oNearest, string sCurrentTag, string sTagType); void sp_SpawnCamp(object oNearest, location lCurrentWP); void sp_CheckTrap(object oNearest, object oPC); void sp_AreaEffect(object oNearest); string sp_SpawnChamp(object oNearest); string sp_CleanString(object oNearest, string sType); string sp_GetGroupCreature(object oNearest, int iGroupTotal); int sp_GetValue(object oNearest, string sSwitch, string sCurrentName); int sp_CreaturesToSpawn(object oNearest, int iAlive); int sp_CheckDistance(object oNearest); int sp_CheckTimeOfDay(object oNearest); int sp_CreaturesAlive(object oNearest); int sp_GetGroupTotal(object oNearest, string sTagType); location sp_RandomLocation(object oNearest, int iRandArea); void main() { /* # Groups # # Undead 1 */ SetLocalString(OBJECT_SELF, "group01_1", "NW_SKELETON"); SetLocalString(OBJECT_SELF, "group01_2", "NW_LICH003"); SetLocalString(OBJECT_SELF, "group01_3", "NW_GHOUL"); SetLocalString(OBJECT_SELF, "group01_4", "NW_MUMMY"); SetLocalString(OBJECT_SELF, "group01_5", "NW_WRAITH"); /* # Orcs 1 */ SetLocalString(OBJECT_SELF, "group02_1", "NW_ORCA"); SetLocalString(OBJECT_SELF, "group02_2", "NW_ORCB"); SetLocalString(OBJECT_SELF, "group02_3", "NW_OrcChiefA"); SetLocalString(OBJECT_SELF, "group02_4", "NW_ORCCHIEFB"); SetLocalString(OBJECT_SELF, "group02_5", "NW_ORCWIZA"); SetLocalString(OBJECT_SELF, "group02_6", "NW_ORCWIZB"); /* # Camp Equipment # # Corpse Wagon */ SetLocalString(OBJECT_SELF, "camp01_tag_1", "FlyCladCorpseWagon"); SetLocalString(OBJECT_SELF, "camp01_resref_1", "plc_fcrpsewagon"); /* # Champions # */ SetLocalString(OBJECT_SELF, "champ01", "NW_ORCWIZB"); /* # ##*/ // Check if spawn sites are set and if not store their locations. int nNth = 1; object oNearest; if (!GetIsObjectValid(GetLocalObject(OBJECT_SELF, "SpawnSite1"))) { nNth = 1; int iSpawnSite = 1; oNearest = GetNearestObject( 32, OBJECT_SELF, nNth ); while (GetIsObjectValid(oNearest)) { if (GetStringLeft(GetName(oNearest), 3) == "SP_") { SetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(iSpawnSite), oNearest); iSpawnSite++; } nNth++; oNearest = GetNearestObject(32, OBJECT_SELF, nNth); } } // If spawn sites exist, start the process. nNth = 1; oNearest = GetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(nNth)); while (GetIsObjectValid(oNearest)) { // Check spawner and see if a timer is already running and if // the spawn site has been destroyed or not. if (!GetLocalInt(oNearest, "IsSpawning") && !GetLocalInt(oNearest, "SpawnDestroyed")) { // Get the Tag. if (GetLocalString(oNearest, "Tag") == "") { SetLocalString(oNearest, "Tag", sp_CleanString(oNearest, "Tag")); } // Get the Blueprint. string sBluePrint; if (GetLocalString(oNearest, "Blueprint") == "") { SetLocalString(oNearest, "Blueprint", sp_CleanString(oNearest, "Blueprint")); sBluePrint = GetLocalString(oNearest, "Blueprint"); if (iDebug) // Debug message SendMessageToAllDMs("Blueprint = " + sBluePrint); } else { sBluePrint = GetLocalString(oNearest, "Blueprint"); } // Check if variables are already set. if (!GetLocalInt(oNearest, "IsSpawner")) { sp_CheckVars(oNearest, GetName(oNearest)); } // Start of Main Procedure. // // We will use this to see if we should spawn or not. int iIsValid = 1; int iDontSpawn; if (sBluePrint == "" || sBluePrint == "effect") { iDontSpawn = 1; } // Check how many creatures are at the spawn point. int iAlive; if (!iDontSpawn) { iAlive = sp_CreaturesAlive(oNearest); } // Check for time of day. if (GetLocalInt(oNearest, "SpawnDay") || GetLocalInt(oNearest, "SpawnNight") || GetLocalInt(oNearest, "DaySpawn") || GetLocalInt(oNearest, "HourSpawn")) { if (sp_CheckTimeOfDay(oNearest) != 1) { iIsValid = 0; if (iAlive) { sp_DestroyObject(oNearest, "Creature"); if (GetLocalInt(oNearest, "Camp")) { sp_DestroyObject(oNearest, "Camp"); SetLocalInt(oNearest, "CampExists", 0); } } } } // Check for PC in radius (if a radius is used). if (GetLocalInt(oNearest, "PC_Radius")) { int iRD = sp_CheckDistance(oNearest); if (iRD != 1) { iIsValid = 0; if (iRD != 1 && iAlive) { sp_DestroyObject(oNearest, "Creature"); if (GetLocalInt(oNearest, "Camp")) { sp_DestroyObject(oNearest, "Camp"); SetLocalInt(oNearest, "CampExists", 0); } } } } // if (iIsValid && GetLocalInt(oNearest, "AreaEffect")) { sp_AreaEffect(oNearest); } // Check if the spawn is suppose to wait till all // creatures are dead. int iToSpawn; if (GetLocalInt(oNearest, "DelaySpawn") && iAlive >= 1) { iIsValid = 0; } // Check for Champion else if (iIsValid && !iDontSpawn && GetLocalInt(oNearest, "ChampSpawn") && GetLocalInt(oNearest, "HasSpawned") && !GetLocalInt(oNearest, "ChampHasSpawned")) { string sChamp = sp_SpawnChamp(oNearest); if (sChamp != "") { iToSpawn = 1; sBluePrint = sChamp; } } else if (GetLocalInt(oNearest, "ChampHasSpawned")) { DeleteLocalInt(oNearest, "ChampHasSpawned"); } // Check for missing creatures. if (!GetLocalInt(oNearest, "SpawnRandom") && !iDontSpawn) { if (iAlive == GetLocalInt(oNearest, "SpawnAmount")) { iIsValid = 0; } } if (iIsValid && !GetLocalInt(oNearest, "SpawnChamp") && !iDontSpawn) { iToSpawn = sp_CreaturesToSpawn(oNearest, iAlive); if (iToSpawn == 0) { iIsValid = 0; } else if (iToSpawn == GetLocalInt(oNearest, "SpawnAmount") && GetLocalInt(oNearest, "HasSpawned") && GetLocalInt(oNearest, "StopSpawn")) { SetLocalInt(oNearest, "SpawnDestroyed", 1); iIsValid = 0; } if (iDebug) { // Debug SendMessageToAllDMs("Missing " + IntToString(iToSpawn) + " at " + GetTag(oNearest)); } } // If everything is ok, spawn. if (iIsValid && iToSpawn && !iDontSpawn) { SetLocalInt(oNearest, "IsSpawning", 1); int iSpawnTime; float fSpawnTime; string sSpawnTimer; string sTimerRandom; if (GetLocalInt(oNearest, "SpawnTimer")) { sSpawnTimer = IntToString(GetLocalInt(oNearest, "SpawnTimer")); } if (GetLocalInt(oNearest, "TimerIsRandom")) { sTimerRandom = IntToString(GetLocalInt(oNearest, "TimerIsRandom")); } if (GetLocalInt(oNearest, "HasSpawned")) { if (iDebug) { // Debug message SendMessageToAllDMs("Timer " + sSpawnTimer + " Random " + sTimerRandom); } if (GetLocalInt(oNearest, "TimerIsRandom")) { iSpawnTime = StringToInt(sSpawnTimer) + Random(StringToInt(sTimerRandom)); fSpawnTime = IntToFloat(iSpawnTime); } else { fSpawnTime = StringToFloat(sSpawnTimer); } } else { SetLocalInt(oNearest, "HasSpawned", 1); fSpawnTime = 0.0; } if (iDebug) { // Debug message SendMessageToAllDMs("Spawning " + sBluePrint + " delayed for " + IntToString(FloatToInt(fSpawnTime))); } AssignCommand(OBJECT_SELF, DelayCommand( fSpawnTime, sp_Spawn(oNearest, sBluePrint, iToSpawn))); AssignCommand(OBJECT_SELF, DelayCommand( fSpawnTime, SetLocalInt(oNearest, "IsSpawning", 0))); } // // End of Main Procedure } nNth++; oNearest = GetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(nNth)); } } // No comments beyond this point :) void sp_DestroyObject(object oNearest, string sTagType) { if (iDebug) { // Debug SendMessageToAllDMs("Killing Creatures..."); } int iCurObject; object oCreatureToKill; int iNumObjects; if (sTagType == "Camp") { iNumObjects = sp_GetGroupTotal(oNearest, "Camp"); } else { iNumObjects = GetLocalInt(oNearest, "SpawnAmount") + GetLocalInt(oNearest, "SpawnRandomNumber"); } for (iCurObject = iNumObjects; iCurObject > 0; iCurObject--) { oCreatureToKill = GetLocalObject(oNearest, sTagType + IntToString(iCurObject)); if (GetIsObjectValid(oCreatureToKill)) { if (GetLocalObject(oCreatureToKill, "SpawnedBy") == oNearest) { if (!GetIsInCombat(oCreatureToKill) || sTagType == "Camp") { if (iDebug) { // Debug SendMessageToAllDMs("Killing " + sTagType); SendMessageToAllDMs("Tag - " + GetTag(oCreatureToKill)); } if (GetLocalInt(oNearest, "DeathEffect") && sTagType == "Creature") { effect eDeath; switch (GetLocalInt(oNearest, "DeathEffect")) { case 01: eDeath = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_1); break; case 02: eDeath = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_2); break; case 03: eDeath = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3); break; case 04: eDeath = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD); break; case 05: eDeath = EffectVisualEffect(VFX_FNF_SUNBEAM); break; case 06: eDeath = EffectVisualEffect(VFX_FNF_WAIL_O_BANSHEES); break; case 07: eDeath = EffectVisualEffect(VFX_FNF_STORM); break; case 08: eDeath = EffectVisualEffect(VFX_FNF_STRIKE_HOLY); break; case 09: eDeath = EffectVisualEffect(VFX_FNF_IMPLOSION); break; default: eDeath = EffectVisualEffect(VFX_NONE); break; } ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eDeath, GetLocation(oCreatureToKill)); } DestroyObject(oCreatureToKill, 0.0); } } } } } void sp_CheckVars(object oNearest, string sCurrentName) { if (iDebug) SendMessageToAllDMs("Checking Variables..."); // Debug SetLocalInt(oNearest, "GroupRandom", sp_GetValue(oNearest, "GR", sCurrentName)); SetLocalInt(oNearest, "GroupSpawn", sp_GetValue(oNearest, "GP", sCurrentName)); SetLocalInt(oNearest, "SpawnTimer", sp_GetValue(oNearest, "TM", sCurrentName)); SetLocalInt(oNearest, "SpawnAmount", sp_GetValue(oNearest, "SX", sCurrentName)); SetLocalInt(oNearest, "PC_Radius", sp_GetValue(oNearest, "RD", sCurrentName)); SetLocalInt(oNearest, "NPC_Radius", sp_GetValue(oNearest, "SR", sCurrentName)); SetLocalInt(oNearest, "SpawnDay", sp_GetValue(oNearest, "DT", sCurrentName)); SetLocalInt(oNearest, "SpawnNight", sp_GetValue(oNearest, "NT", sCurrentName)); SetLocalInt(oNearest, "IsTreasure", sp_GetValue(oNearest, "TR", sCurrentName)); SetLocalInt(oNearest, "SpawnEffect", sp_GetValue(oNearest, "VS", sCurrentName)); SetLocalInt(oNearest, "DeathEffect", sp_GetValue(oNearest, "VK", sCurrentName)); SetLocalInt(oNearest, "RandomWalk", sp_GetValue(oNearest, "RW", sCurrentName)); SetLocalInt(oNearest, "NearPlayer", sp_GetValue(oNearest, "NP", sCurrentName)); SetLocalInt(oNearest, "InCombat", sp_GetValue(oNearest, "IC", sCurrentName)); SetLocalInt(oNearest, "StopSpawn", sp_GetValue(oNearest, "SS", sCurrentName)); SetLocalInt(oNearest, "GenTreasure", sp_GetValue(oNearest, "GT", sCurrentName)); SetLocalInt(oNearest, "DelaySpawn", sp_GetValue(oNearest, "DS", sCurrentName)); SetLocalInt(oNearest, "Camp", sp_GetValue(oNearest, "CP", sCurrentName)); SetLocalInt(oNearest, "DaySpawn", sp_GetValue(oNearest, "SD", sCurrentName)); SetLocalInt(oNearest, "HourSpawn", sp_GetValue(oNearest, "SH", sCurrentName)); SetLocalInt(oNearest, "TrapType", sp_GetValue(oNearest, "TP", sCurrentName)); SetLocalInt(oNearest, "ChampSpawn", sp_GetValue(oNearest, "CH", sCurrentName)); SetLocalInt(oNearest, "RandomFacing", sp_GetValue(oNearest, "RF", sCurrentName)); SetLocalInt(oNearest, "AreaEffect", sp_GetValue(oNearest, "AE", sCurrentName)); SetLocalInt(oNearest, "DontZone", sp_GetValue(oNearest, "DZ", sCurrentName)); SetLocalInt(oNearest, "NoFirst", sp_GetValue(oNearest, "NF", sCurrentName)); if (GetLocalInt(oNearest, "NoFirst")) { SetLocalInt(oNearest, "HasSpawned", 1); } SetLocalInt(oNearest, "IsSpawner", 1); } void sp_Spawn(object oNearest, string sTemplate, int iSpawnX) { if (iDebug) SendMessageToAllDMs("Spawning..."); // Debug location lCurrentWP = GetLocation(oNearest); string sCurrentTag; if (GetLocalInt(oNearest, "SpawnChamp")) { sCurrentTag = GetLocalString(OBJECT_SELF, sTemplate); sTemplate = GetStringLowerCase(GetLocalString(OBJECT_SELF, sTemplate)); SetLocalInt(oNearest, "ChampHasSpawned", 1); DeleteLocalInt(oNearest, "SpawnChamp"); } else { sCurrentTag = GetLocalString(oNearest, "Tag"); } int iGroupTotal; int iValid; int iTotalX; for (iTotalX = 0; iTotalX < iSpawnX; iTotalX++) { iValid = 1; if (GetLocalInt(oNearest, "GroupSpawn")) { iGroupTotal = sp_GetGroupTotal(oNearest, "Creature"); sCurrentTag = sp_GetGroupCreature(oNearest, iGroupTotal); sTemplate = GetStringLowerCase(sCurrentTag); } if (GetLocalInt(oNearest, "NPC_Radius") && iValid) { if (GetLocalInt(oNearest, "NearPlayer")) { object oPlayer = GetNearestCreature( CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oNearest); if (GetIsObjectValid(oPlayer)) { lCurrentWP = sp_RandomLocation(oPlayer, GetLocalInt(oNearest, "NPC_Radius")); } else { iValid = 0; if (iDebug) SendMessageToAllDMs("Player is not valid..."); // Debug } } else { lCurrentWP = sp_RandomLocation(oNearest, GetLocalInt(oNearest, "NPC_Radius")); } } if (GetLocalInt(oNearest, "IsTreasure") && iValid) { object oTreasure = GetNearestObjectByTag(sTemplate, oNearest); if (GetIsObjectValid(oTreasure)) { if (iDebug) SendMessageToAllDMs("Found " + sTemplate + " ... respawning."); SetLocalInt(oTreasure, "NW_DO_ONCE",0); } else { if (iDebug) SendMessageToAllDMs("Found " + sTemplate + " not found ... creating"); CreateObject(OBJECT_TYPE_PLACEABLE, sTemplate, lCurrentWP, FALSE); } } else { if (GetLocalInt(oNearest, "SpawnEffect") && iValid) { effect eSpawn; switch (GetLocalInt(oNearest, "SpawnEffect")) { case 01: eSpawn = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_1); break; case 02: eSpawn = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_2); break; case 03: eSpawn = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3); break; case 04: eSpawn = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD); break; case 05: eSpawn = EffectVisualEffect(VFX_FNF_SUNBEAM); break; case 06: eSpawn = EffectVisualEffect(VFX_FNF_WAIL_O_BANSHEES); break; case 07: eSpawn = EffectVisualEffect(VFX_FNF_STORM); break; case 08: eSpawn = EffectVisualEffect(VFX_FNF_STRIKE_HOLY); break; case 09: eSpawn = EffectVisualEffect(VFX_FNF_IMPLOSION); break; default: eSpawn = EffectVisualEffect(VFX_NONE); break; } ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eSpawn, lCurrentWP); } CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lCurrentWP, TRUE); } if (GetLocalInt(oNearest, "Camp") && !GetLocalInt(oNearest, "CampExists")) { sp_SpawnCamp(oNearest, lCurrentWP); } sp_TagObject(oNearest, sCurrentTag, "Creature"); } } string sp_CleanString(object oNearest, string sType) { if (iDebug) SendMessageToAllDMs("Cleaning String..."); // Debug string sCurrentTag = GetTag(oNearest); if (GetStringLowerCase(GetStringLeft(sCurrentTag, 3)) == "wp_" && sType == "Tag") { sCurrentTag = GetStringRight(sCurrentTag, GetStringLength(sCurrentTag) - 3); if (StringToInt(GetStringRight(sCurrentTag, 2)) && GetSubString(sCurrentTag, GetStringLength(sCurrentTag) - 3, 1) == "_") { sCurrentTag = GetStringLeft(sCurrentTag, GetStringLength(sCurrentTag) - 3); } } else if (GetStringLowerCase( GetStringLeft(sCurrentTag, 5)) == "post_" && sType == "Tag") { sCurrentTag = GetStringRight(sCurrentTag, GetStringLength(sCurrentTag) - 5); } else if (sType == "Blueprint") { sCurrentTag = GetLocalString(oNearest, "Tag"); sCurrentTag = GetStringLowerCase(sCurrentTag); } return sCurrentTag; } int sp_CheckDistance(object oNearest) { if (iDebug) { // Debug SendMessageToAllDMs("Checking Distance..."); } int iRD = 0; int iSpawnDistance = GetLocalInt(oNearest, "PC_Radius"); if (iSpawnDistance >= 1) { object oArea = GetArea(oNearest); object oPC = GetFirstPC(); if (GetIsObjectValid(oPC)) { while (GetIsObjectValid(oPC)) { if (GetArea(oPC) == oArea) { if (GetDistanceBetween(oNearest, oPC) <= IntToFloat(iSpawnDistance)) { if (GetLocalInt(oNearest, "TrapType")) { sp_CheckTrap(oNearest, oPC); } if (GetLocalInt(oNearest, "InCombat") && GetIsInCombat(oPC)) { iRD = 2; } else { iRD = 1; } } } oPC = GetNextPC(); } } } else { iRD = 1; } return iRD; } int sp_CheckTimeOfDay(object oNearest) { if (iDebug) SendMessageToAllDMs("Checking Time of Day..."); // Debug int iValidTime = 0; if (GetIsDay() && GetLocalInt(oNearest, "SpawnDay") == 1) { iValidTime = 1; } else if (GetIsNight() && GetLocalInt(oNearest, "SpawnNight") == 1) { iValidTime = 1; } else if (GetLocalInt(oNearest, "DaySpawn")) { int iCalDay = GetCalendarDay(); int iStartDay = GetLocalInt(oNearest, "DaySpawn"); if (GetLocalInt(oNearest, "TimeThrough")) { int iStopDay = GetLocalInt(oNearest, "TimeThrough"); if (iStopDay > iStartDay) { int i; for (i = iStartDay; i <= iStopDay; i++) { if (i == iCalDay) { iValidTime = 1; } } } } else if (iCalDay == iStartDay) { iValidTime = 1; } } else if (GetLocalInt(oNearest, "HourSpawn")) { int iHour = GetTimeHour(); int iStartHour = GetLocalInt(oNearest, "HourSpawn"); if (GetLocalInt(oNearest, "TimeThrough")) { int iStopHour = GetLocalInt(oNearest, "TimeThrough"); if (iStopHour > iStartHour) { int i; for (i = iStartHour; i <= iStopHour; i++) { if (i == iHour) { iValidTime = 1; } } } } else if (iHour == iStartHour) { iValidTime = 1; } } return iValidTime; } int sp_CreaturesAlive(object oNearest) { if (iDebug) SendMessageToAllDMs("Counting Creatures..."); // Debug int iMin = GetLocalInt(oNearest, "SpawnAmount"); int iMaxXX = iMin; if (GetLocalInt(oNearest, "SpawnRandomNumber") > 0) { iMaxXX += GetLocalInt(oNearest, "SpawnRandomNumber"); } int iAlive = 0; int iCountSX_Dead = 0; int iCreature; object oCurrent; for (iCreature = iMaxXX; iCreature > 0; iCreature--) { oCurrent = GetLocalObject(oNearest, "Creature" + IntToString(iCreature)); if (GetIsObjectValid(oCurrent)) { if (GetLocalInt(oNearest, "IsTreasure")) { if (GetIsObjectValid(GetFirstItemInInventory(oCurrent))) iAlive++; } else { iAlive++; if (GetLocalInt(oNearest, "RandomWalk")) { if (GetCurrentAction(oCurrent) != 36) { if (!GetIsInCombat(oCurrent) && !IsInConversation(oCurrent)) { AssignCommand(oCurrent, ActionRandomWalk()); } } } } } } if (iDebug) SendMessageToAllDMs("Found " + IntToString(iAlive) + " " + GetLocalString(oNearest, "Tag")); return iAlive; } int sp_CreaturesToSpawn(object oNearest, int iAlive) { if (iDebug) SendMessageToAllDMs("Determining Number To Spawn..."); // Debug int iSpawnRandom = GetLocalInt(oNearest, "SpawnRandomNumber"); int iMin = GetLocalInt(oNearest, "SpawnAmount"); int iMaxXX = iMin; if (iSpawnRandom > 0) { iMaxXX += iSpawnRandom; } int iCountSX_Dead = iMaxXX - iAlive; if (iCountSX_Dead > 0 && iSpawnRandom > 0) { int iAlive = iMaxXX - iCountSX_Dead; if (iAlive < iMin) { int iRand = iMaxXX - iAlive; if (iRand == 2) { iRand = Random(30); if (iRand >= 16) { iCountSX_Dead = 2; } else { iCountSX_Dead = 1; } } else { iCountSX_Dead = Random(iRand); } if (iCountSX_Dead < iMin) { iCountSX_Dead = iMin + Random(iMaxXX - iMin); } } else { iCountSX_Dead = 0; } } if (GetLocalInt(oNearest, "SpawnSingle") && iCountSX_Dead > 1) { return 1; } else { return iCountSX_Dead; } } int sp_GetValue(object oNearest, string sSwitch, string sCurrentName) { if (iDebug) SendMessageToAllDMs("Getting Variable Values..."); // Debug int iSwitchValue = 0; int iIsMinutes = 0; int iIsHours = 0; if (FindSubString(sCurrentName, sSwitch) > 0) { if (sSwitch == "DT" || sSwitch == "NT" || sSwitch == "TR" || sSwitch == "RW" || sSwitch == "NP" || sSwitch == "NF" || sSwitch == "IC" || sSwitch == "SS" || sSwitch == "GP" || sSwitch == "GR" || sSwitch == "RF" || sSwitch == "DZ" || sSwitch == "DS") { iSwitchValue = 1; } else { int iNumberPos = FindSubString(sCurrentName, sSwitch); if (sSwitch == "TM") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "M") { iIsMinutes = 1; } else if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "H") { iIsHours = 1; } } else if (sSwitch == "SX") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "S") { SetLocalInt(oNearest, "SpawnSingle", 1); } } int iNumberLength = GetStringLength(sCurrentName) - iNumberPos; string sSwitchValue = GetSubString(sCurrentName, (iNumberPos + 2), 2); iSwitchValue = StringToInt(sSwitchValue); if (iIsMinutes == 1) { iSwitchValue = iSwitchValue * 60; } else if (iIsHours == 1) { iSwitchValue = (iSwitchValue * 60) * 60; } if ((sSwitch == "SD" || sSwitch == "SH") && GetSubString(sCurrentName, (iNumberPos + 4), 1) == "T") { SetLocalInt(oNearest, "TimeThrough", StringToInt(GetSubString( sCurrentName, (iNumberPos + 5), 2))); } if (sSwitch == "TP" && GetSubString(sCurrentName, (iNumberPos + 4), 1) == "A") { SetLocalInt(oNearest, "TrapAmulet", StringToInt(GetSubString( sCurrentName, (iNumberPos + 5), 2))); } if (sSwitch == "CH") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sFirstPass = GetStringLowerCase(GetSubString( sCurrentName,(iNumberPos + 5), (GetStringLength(sCurrentName) - iNumberPos + 5))); string sSecondPass = GetStringLeft(sFirstPass, FindSubString(sFirstPass, "_")); SetLocalInt(oNearest, "ChampNumDie", StringToInt(GetStringLeft( sSecondPass, FindSubString(sSecondPass, "d")))); SetLocalInt(oNearest, "ChampDie", StringToInt(GetStringRight( sSecondPass, (GetStringLength(sSecondPass) - FindSubString(sSecondPass, "d")) - 1))); } } else if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { int iMaxRand = StringToInt(GetSubString( sCurrentName, (iNumberPos + 5), 2)); if (sSwitch == "SX") { if (iSwitchValue < 1) { iSwitchValue = 1; } else if (iMaxRand < 1) { iMaxRand = 1; } SetLocalInt(oNearest, "SpawnRandomNumber", iMaxRand - iSwitchValue); } else if (sSwitch == "AE") { SetLocalInt(oNearest, "AreaEffectRadius", iMaxRand); } else { if (GetSubString(sCurrentName, (iNumberPos + 7), 1) == "M") { iIsMinutes = 1; iMaxRand = iMaxRand * 60; iSwitchValue = iSwitchValue * 60; } else if (GetSubString(sCurrentName, (iNumberPos + 7), 1) == "H") { iMaxRand = (iMaxRand * 60) * 60; iSwitchValue = (iSwitchValue * 60) * 60; } SetLocalInt(oNearest, "TimerIsRandom", iMaxRand - iSwitchValue); } } if (sSwitch == "SX" && GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "GroupRandom")) { iSwitchValue = sp_GetGroupTotal(oNearest, "Creature"); } } } else if (sSwitch == "SX") { if (GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "GroupRandom")) { iSwitchValue = sp_GetGroupTotal(oNearest, "Creature"); } else { iSwitchValue = 1; } } return iSwitchValue; } location sp_RandomLocation(object oNearest, int iRandArea) { if (iDebug) SendMessageToAllDMs("Choosing Random Location..."); // Debug vector vNewPos = GetPosition(oNearest); object oArea = GetArea(oNearest); float fX, fY; float fRadius = IntToFloat(iRandArea); int iValid = FALSE; while (iValid != TRUE) { fX = (Random(200)/100.0 - 1.0) * fRadius; fY = (Random(200)/100.0 - 1.0) * fRadius; if (fX * fX + fY * fY <= fRadius * fRadius) { iValid = TRUE; } } vNewPos += Vector(fX, fY, 0.0); location lNewLoc = Location(oArea, vNewPos, VectorToAngle(-1.0 * vNewPos)); return lNewLoc; } int sp_GetGroupTotal(object oNearest, string sTagType) { if (iDebug) SendMessageToAllDMs("Checking group total..."); // Debug int iGroupValid = 0; int iGroupTotal = 0; string sTemplate; if (sTagType == "Creature") { if (iDebug) SendMessageToAllDMs("Checking group Creature..."); // Debug sTemplate = GetLocalString(oNearest, "Tag"); } else if (sTagType == "Camp") { sTemplate = "camp"; if (iDebug) SendMessageToAllDMs("Checking group Camp..."); // Debug if (GetLocalInt(oNearest, "Camp") < 10) { sTemplate += "0" + IntToString(GetLocalInt(oNearest, "Camp")); } else { sTemplate += IntToString(GetLocalInt(oNearest, "Camp")); } } string sGroup; while (iGroupValid != 1) { iGroupTotal ++; if (sTagType == "Creature") { sGroup = GetStringLowerCase(sTemplate) + "_" + IntToString(iGroupTotal); } else if (sTagType == "Camp") { sGroup = GetStringLowerCase(sTemplate) + "_resref_" + IntToString(iGroupTotal); } if (GetLocalString(OBJECT_SELF, sGroup) == "") { iGroupValid = 1; iGroupTotal--; } } return iGroupTotal; } string sp_SpawnChamp(object oNearest) { int iChampValid; int iChampNumDie = GetLocalInt(oNearest, "ChampNumDie"); int iChampDie = GetLocalInt(oNearest, "ChampDie"); int iDieResult; if (!iChampNumDie) { iChampValid = 1; } else { switch (iChampDie) { case 2: iDieResult = d2(iChampNumDie); break; case 3: iDieResult = d3(iChampNumDie); break; case 4: iDieResult = d4(iChampNumDie); break; case 6: iDieResult = d6(iChampNumDie); break; case 8: iDieResult = d8(iChampNumDie); break; case 10: iDieResult = d10(iChampNumDie); break; case 12: iDieResult = d12(iChampNumDie); break; case 20: iDieResult = d20(iChampNumDie); break; case 100: iDieResult = d100(iChampNumDie); break; default:;break; } if (iDieResult == iChampDie / 2) { iChampValid = 1; } } string sChamp; if (iChampValid) { SetLocalInt(oNearest, "SpawnChamp", 1); int iChampNum = GetLocalInt(oNearest, "ChampSpawn"); sChamp = "champ"; if (iChampNum >= 10) { sChamp += IntToString(iChampNum); } else { sChamp += "0" + IntToString(iChampNum); } } return sChamp; } string sp_GetGroupCreature(object oNearest, int iGroupTotal) { int iSpawnRand; string sGroup; string sCurrentTag; string sTemplate; if (GetLocalInt(oNearest, "GroupRandom")) { iSpawnRand = Random(iGroupTotal); if (iSpawnRand == 0) { iSpawnRand = 1; } sGroup = GetStringLowerCase(GetLocalString(oNearest, "Tag")) + "_" + IntToString(iSpawnRand); sCurrentTag = GetLocalString(OBJECT_SELF, sGroup); sTemplate = sCurrentTag; return sTemplate; } else { object oCurrent; int iCreature = iGroupTotal; int iGroup; iGroup = iGroupTotal; while (iGroup > 0) { sGroup = GetStringLowerCase(GetLocalString(oNearest, "Tag")) + "_" + IntToString(iGroup); sCurrentTag = GetLocalString(OBJECT_SELF, sGroup); int iValid = 0; iCreature = iGroupTotal; while (iCreature > 0) { oCurrent = GetLocalObject(oNearest, "Creature" + IntToString(iCreature)); if (GetIsObjectValid(oCurrent)) { if (sCurrentTag == GetTag(oCurrent)) { iValid = 1; } } iCreature--; } if (iValid != 1) { sTemplate = sCurrentTag; return sTemplate; } iGroup--; } } if (sTemplate == "") { if (iDebug) SendMessageToAllDMs("Template is blank"); // Debug } else if (iDebug) { SendMessageToAllDMs("Template - " + sTemplate); // Debug } return sTemplate; } void sp_TagObject(object oNearest, string sCurrentTag, string sTagType) { int iNearest = 1; int iCountNearest = 0; int iCreature; object oCreature; object oLastSpawned = GetNearestObjectByTag( sCurrentTag, oNearest, iNearest); while (iCountNearest != 1) { if (!GetIsObjectValid(GetLocalObject(oLastSpawned, "SpawnedBy")) && GetIsObjectValid(oLastSpawned)) { if (iDebug) { // Debug SendMessageToAllDMs(GetTag(oLastSpawned) + " SpawnedBy is blank..."); } SetLocalObject(oLastSpawned, "SpawnedBy", oNearest); iCreature = 1; oCreature = GetLocalObject(oNearest, sTagType + IntToString(iCreature)); while (GetIsObjectValid(oCreature)) { iCreature++; oCreature = GetLocalObject(oNearest, sTagType + IntToString(iCreature)); } SetLocalObject(oNearest, sTagType + IntToString(iCreature), oLastSpawned); if (GetLocalInt(oNearest, "RandomFacing")) { int iRandomDir = Random(270); AssignCommand(oLastSpawned, SetFacing(IntToFloat(iRandomDir))); } if (GetLocalInt(oNearest, "RandomWalk") && sTagType == "Creature") { AssignCommand(oLastSpawned, ActionRandomWalk()); } if (GetLocalInt(oNearest, "GenTreasure") && sTagType == "Creature") { switch (GetLocalInt(oNearest, "GenTreasure")) { case 01:GenerateLowTreasure(oLastSpawned);break; case 02:GenerateMediumTreasure(oLastSpawned);break; case 03:GenerateHighTreasure(oLastSpawned);break; case 04:GenerateBossTreasure(oLastSpawned);break; case 05:GenerateBookTreasure(oLastSpawned);break; } } if (iDebug) { // Debug SendMessageToAllDMs("Owner of " + GetTag(oLastSpawned) + " is " + GetName(GetLocalObject( oLastSpawned, "SpawnedBy"))); } iCountNearest = 1; } iNearest++; oLastSpawned = GetNearestObjectByTag( sCurrentTag, oNearest, iNearest); if (!GetIsObjectValid(oLastSpawned)) { iCountNearest = 1; } } } void sp_SpawnCamp(object oNearest, location lCurrentWP) { location lMyLoc; location lObjectLoc; int iCampEquip = 0; int iItem = 1; int iCamp = GetLocalInt(oNearest, "Camp"); string sCamp; if (iCamp < 10) { sCamp = "camp0" + IntToString(iCamp); } else { sCamp = "camp" + IntToString(iCamp); } while (iCampEquip != 1) { lMyLoc = lCurrentWP; string sItemResRef = GetLocalString(OBJECT_SELF, sCamp + "_resref_" + IntToString(iItem)); string sItemTag = GetLocalString(OBJECT_SELF, sCamp + "_tag_" + IntToString(iItem)); if (sItemResRef != "") { lObjectLoc = GetLocation(GetNearestObjectToLocation( OBJECT_TYPE_PLACEABLE, lCurrentWP)); if (GetDistanceBetweenLocations(lMyLoc, lObjectLoc) < 2.0 ) { int iLocValid ; for (iLocValid = 0; iLocValid != 1; iLocValid++) { lMyLoc = sp_RandomLocation(oNearest, 1); lObjectLoc = GetLocation(GetNearestObjectToLocation( OBJECT_TYPE_PLACEABLE, lMyLoc)); if (GetDistanceBetweenLocations(lMyLoc, lObjectLoc) > 2.0 ) { iLocValid = 1; } } } CreateObject(OBJECT_TYPE_PLACEABLE, sItemResRef, lMyLoc, TRUE); sp_TagObject(oNearest, sItemTag, "Camp"); iItem++; } else { iCampEquip = 1; SetLocalInt(oNearest, "CampExists", 1); } } } void sp_CheckTrap(object oNearest, object oPC) { if (iDebug) SendMessageToAllDMs("Checking Trap..."); // Debug effect eDamage; effect eEffect; string sDamageCause; string sAmulet = "blank"; if (GetIsObjectValid(oPC)) { if (iDebug) SendMessageToAllDMs("PC is valid..."); // Debug switch (GetLocalInt(oNearest, "TrapType")) { case 01: eDamage = EffectDamage(d4(), DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_FIVE); eEffect = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_NATURE); sDamageCause = "You have stumbled into a poisonous fog."; break; case 02: eDamage = EffectDamage(d4(), DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_FIVE); eEffect = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_EVIL); sDamageCause = "You have stumbled into a poisonous fog."; break; default: eDamage = EffectDamage(d4(), DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_FIVE); eEffect = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_NATURE); sDamageCause = "You have stumbled into a poisonous fog."; break; } if (GetLocalInt(oNearest, "TrapAmulet")) { if (iDebug) SendMessageToAllDMs("Checking for Amulet..."); // Debug switch (GetLocalInt(oNearest, "TrapAmulet")) { case 01: sAmulet = "PalorsAmulet"; break; case 02: sAmulet = "PalorsOtherAmulet"; break; } } if (GetTag(GetItemInSlot(INVENTORY_SLOT_NECK, oPC)) != sAmulet) { if (iDebug) SendMessageToAllDMs("PC does not have Amulet..."); // Debug SendMessageToPC(oPC, sDamageCause); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect, GetLocation(oPC)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oPC); } } else { if (iDebug) SendMessageToAllDMs("PC is not valid..."); // Debug } } void sp_AreaEffect(object oNearest) { if (iDebug) SendMessageToAllDMs("Setting Area Effect..."); // Debug int iEffectRadius = GetLocalInt(oNearest, "AreaEffectRadius"); if (!iEffectRadius) { iEffectRadius = 5; } effect eAreaEffect; switch (GetLocalInt(oNearest, "AreaEffect")) { case 1: eAreaEffect = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);break; case 2: eAreaEffect = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_NATURE);break; default: eAreaEffect = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);break; } location lAreaLoc = sp_RandomLocation(oNearest, iEffectRadius); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eAreaEffect, lAreaLoc); }