///////////////////////////////////////// //////// /*## # NWN Spawn System v2.4.2 # Author: Palor # Description: # Complete Spawn System, 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. # ##* # Changes # # 2.4.2 # - Added TD for Trap Disarm (DT was already taken). # - Requested by Erdo # - Modified functions to reduce CPU usage and TMIs. # # 2.4.1a # - Changed X for PI to D, since X already existed :) # - Reported by Karthal # # 2.4.1 # - Added X to PI which will destroy the object in the # players inventory. - Requested by Karthal # - Added SL and ML for StartLevel and MaxLevel. These # can be used with RD and PA. - Requested by Jelloman2K # - Added PV which will NOT kill a creature if a player # is within view. - Requested by Gloomveil # # 2.4 # - Fixed bug with SH. - Reported by Benjamin # # 2.3.7e # - Fixed bug with TR. - Reported by Kapell # # 2.3.7d # - Modified GP to ignore SX unless GR is used. # - Modified random function of SX. # - Modified timer function. # # 2.3.7c # - Added ID for controlling the spawn from triggers. # # 2.3.7b # - Modified code structure. # - Fixed minor unreported bugs :) # - Fixed CPU issues. - Reported by SolarflareX & Maska # # 2.3.7a # - Fixed several bugs with CH. # - Reported by forcrimanysakes # # 2.3.7 # - Removed creature tag requirement in Spawn Points tag. # A valid blueprint is still required though. # - Modified IG to use roll for random item. # - Modified IG to give entire group if no roll is given. # - Requested by razar77 # - Modified GT to accept a roll. - Requested by Wizzle # # 2.3.6f # - Fixed huge bobo with tagobject. # - Suggested by jwvanderbeck # # 2.3.6e # - Reduced overhead on heartbeats. # # 2.3.6d # - Worked on TMI errors. # # 2.3.6c # - Fixed yet another bug with champions. # - Reported by Mikey-Flies # # 2.3.6b # - Fixed champion bug. - Reported by Hotcarl44 # # 2.3.6a # - Added GetIsPC back into TagObject (taken out to test). # # 2.3.6 # - Fixed crash bug. # - Modified code to reduce CPU usage. # # 2.3.5h # - Fixed bug with PI. - Reported by der_drakken # # 2.3.5g # - Modified main loop so that it always checks the waypoint # and not just between timers. # # 2.3.5f # - Fixed bug with counting dead creatures. # - Added RT to reset timer. - Requested by SolarflareX # # 2.3.5e # - Added PA which will only spawn if a player is in # the area. # - Modified rolldice function. - Requested by Mikey-Flies # - Modified possible bug in object tagging. # - Reported by Hotcarl44 # - Modified RandomWalk to include IsInConversation # since a conversation was not showing up as an # an action. - Reported by FalloutBoy # # 2.3.5d # - Added PU for use with jwvanderbeck's Item Manager. # When used the creature has a percent chance to pick # up any items within 5 meters. # - Modified CU function. # # 2.3.5c # - Modified RW function. # - Modified dead creature tagging for compatability # with jwvanderbeck's Item Manager # # 2.3.5b # - Worked on a bug with To Many Instructions # # 2.3.5a # - Fixed bug with destroying creatures when CC is used. # - Reported by Ghost_SD & Hotcarl44 # # 2.3.5 # - Added CR which is used with CH and EX. If used it will # only spawn the Champion at the remote location. # - Added int for KillSpawn for use with controlling the # spawn from an outside source. # # 2.3.4 # - Fixed CPU issue with custom Random Walk. # - Reported by Damn Near Everyone # - Added AI switch for use with jwvanderbeck's Item Manager # # 2.3.3 # - Added IG for Item Group. Requested by Mikey-Flies # - Added chance roll to RD for creatures spawning. # - Requested by Ghost_SD # - Added EX for Remote Spawning. - Requested by Kraxis # - Fixed CPU usage with default RW. # # 2.3.2 # - Modified RW to use the same format as CI and CH (1d2) # - Suggested by Tovrin # - Modified DT and NT to kill creatures no matter what, if # a X is used on the switch. - Requested by Visike # - Modified RD to kill creatures no matter what, if a X # is used on the switch. - Requested by Malkavia # - Modified RD to NOT spawn if a player is within a radius # and a N is used. - Requested by Gandalf il Bianco # - Added PK for use with jwvanderbeck's Item Manager. If # set, creatures will only leave loot if killed by a # player. # # 2.3.1 # - Fixed bug with Champion not spawning with Groups. # - Reported by Qobra # - Fixed a bug with Group tag having to be correct case. # - Reported by Carey Durbin # - Fixed a bug with Spawn Hour and Spawn Day not working # if stop time was less than start time. # - Reported by InfiniteLoop # # 2.3 # - Changed name to NWN Spawn System. # # 2.2.3b # - Fixed Group Random random generator. # - Reported by Mikey-Flies # - Replaced sp_RandomLocation function with one written by # Mikey-Flies. # # 2.2.3a # - Modified RW to include optinal Radius into which to # walk to a random spot. # - Added AN for use with Random Walk so that when they # get to their destination they have a chance on # performing an animation. # - Modified RH so that the creatures do not by default # face the waypoint direction. Use RHF to get that effect. # - Requested by Gandalf il Bianco # - Modified RF to give a chance for facing a random # location every heartbeat. - Requested by jwvanderbeck # # 2.2.3 # - Added further support for jwvanderbeck's Item Manager # # 2.2.2f # - Fixed a bug with groups spawning badgers the first time. # - Reported by mmealman # - Modified RH to have all creatures face waypoint direction # upon returning. - Requested by mmealman # # 2.2.2e # - Added PI switch which tells the spawner to spawn or not # to spawn if a player has an item in the items list. # - Requested by Karthal # - Added check for if creature is dead for compatability # with Item Manager - Requested by jwvanderbeck # - Modified RW to give a 50/50 chance of being used per # heartbeat to lessen CPU usage if none of the following # are true: # -Creature is already walking. # -Creature is in combat. # -Creature is in a conversation. # The old way would do it if none of the above were true 100% # of the time. # # 2.2.2d # - Added CC switch for use with jwvanderbeck's Item Manager. # - Added RH, which will instruct the creature to return to # it's (Home) waypoint if it is not busy. - # - Requested by Gandalf il Bianco # - Added CI, which will create an item on the creature spawned. # - Requested by Gandalf il Bianco # # 2.2.2c # - Fixed a bug with Group Random. - Reported by mmealman # # 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) # ## # # Switches # # SP_ # Tells the Spawn Control Object that this Waypoint is a Spawn Point. # # CHnnRxxx # Tells the spawner to spawn Champion nn at the spawn point. If R is # specified and a valid roll is used, it will give the Champion a # random chance of appearing. # # Examples # # CH01 - Always spawn Champion 01 when all the creatures are dead. # CH01R1d4 - The Champion has a 1 in 4 chance of spawning when all the # creatures are dead. # CH01R2d8 - The Champion has a 1 in 16 chance of spawning when all # the creatures are dead. # # # Valid rolls are: # # nd2 # nd3 # nd4 # nd6 # nd8 # nd10 # nd12 # nd20 # nd100 # # # You can find the list around line 268 and it looks like: # # SetLocalString(OBJECT_SELF, "champ01", "NW_ORCWIZB"); # # So to add a Deer Champion you would make a new line: # # SetLocalString(OBJECT_SELF, "champ02", "NW_DEER"); # # 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. # # 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. # # 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. # # # CPnn # Spawn a creature camp. # # Example # # CP01 - Will place the objects listed in camp01 in random locations # around the site. # # # Camp items can be added by including them in the Camp List. The list # can be found around line 262 of the code and look like: # # SetLocalString(OBJECT_SELF, "camp01_tag_1", "FlyCladCorpseWagon"); # SetLocalString(OBJECT_SELF, "camp01_resref_1", "plc_fcrpsewagon"); # # To add a second object to Group 01 you would first place the object in # your area and get the Tag and Blueprint off the object, then delete it. # Now create a new entry like: # # SetLocalString(OBJECT_SELF, "camp01_tag_2", "MyObjectsTag"); # SetLocalString(OBJECT_SELF, "camp01_resref_2", "myobjectsblueprint"); # # Replace MyObjectsTag with the tag of your object. Replace the blueprint # as well. # # 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 # # # The Group List can be found around line 243 and looks like: # # SetLocalString(OBJECT_SELF, "group01_1", "NW_SKELETON"); # SetLocalString(OBJECT_SELF, "group01_2", "NW_LICH003"); # # To add new creatures to the groups, just use their Tag. You can # add as many groups and creatures as you like :) # ////////# 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. # # # # -=Item Related Switches=- # # # CI # Creates an item on creatures spawned. # # Examples # # CI01 - Creates Item 01 from the Item List and places it on all creatures. # CI01R1d2 - Each creature has a 50/50 chance of receiving the item. # # # The CI switch uses the same random call as the Champion Spawner. Please # see list in the description of the Champion switch. # # PI # Tells the spawner to spawn or not to spawn based on whether the player # has an item. PI must be used with RD. # # Examples # # PI01 - Player must have Item 01 in their inventory in order for this # spawn site to spawn. # PI01X - Player must NOT have Item 01 in their inventory in order for # this spawn site to spawn. # # # 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. # # # # # -=Random Switches=- # # # 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. # # 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 # # # # # -=Time Switches=- # # # 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 24 hour format. If T is # specified it will spawn between the hours of nn and yy. # # Examples # # 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. # # Examples # # SD01 - Spawn only the first day of the month. # SD01T03 - Spawn only between the first and third days of the month. # # # 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. # # # NF # When used with the timers it tells the spawn system to NOT bypass the timers # on the very first spawn. # # DS # Wait until all creatures are killed before spawning any more. # # # # -=Action Switches=- # # # RHF # RH tells all creatures to return home (to the waypoint) if they are # not in the middle of something. If an F is used, the creature will # face the direction of the waypoint when it returns. # # RWnn # If specified, the creature will walk randomly around after spawning. # # Examples # # RW - Defaults to a 5 meter radius. The creature will choose a location # within the radius and walk to it. # RW10 - Walk within a 10 meter radius of the spawn point. # # # ANnnLyy # Used with RW, this switch gives the creature a 50% chance to play an # animation when they are not walking. Using L will have it loop the # animation for yy seconds. # # Examples # # AN01 - The creature will play animation 01. # AN15L10 - The creature will loop animation 15 for 10 seconds. # # # A list of animations can be found around line 331 of the script. # # RF # This switch gives the creature a 50% chance of facing a random # direction every heartbeat. # # # # -=Effect Switches=- # # # AEnnRyy # This will produce the Area Effect nn throughout a 5 meter radius # of the spawn point. If R is used it will make the effect throughout # the radius yy. The location is random. # # Examples # # AE01 - Will produce Area Effect 01 throughout a 5 meter radius of # the spawn point. # AE01R10 - Will produce Area Effect 01 throughout a 10 meter radius. # # # Effects can be found around line 1215 of the script. This is work in # progress and I have not had a chance to go through all of the # effects in NWN :) # # 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 :) # # Effects for spawning can be found around line 677 of the script, effects # for killing can be found around line 565. # # 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. # # # Traps can be found around line 1173 and Amulets around line 1193. # # If a tag of effect is used for the waypoint, it will only do the effect. # # # # -=3rd-Party Switches=- # # # Jaga's Area Transition Script # # DZ # Tells the spawner not to zone any creatures spawned from this location. # # jwvanderbeck's Item Manager # # CC # This switch is to use creature corpses for loot rather than generic # loot bags upon creature death. # # CU # Used to determine whether to clean up items on the ground around the # spawn point. # # # -End of Switch List- # ##*/ #include "NW_O2_CONINCLUDE" #include "JW_REGISTERGROUP" int iDebug = 0; void sp_Main(object oNearest); 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 sTagType, object oNewObject); void sp_SpawnCamp(object oNearest, location lCurrentWP); void sp_CheckTrap(object oNearest, object oPC); void sp_AreaEffect(object oNearest); void sp_CreateItem(object oNearest, object oLastSpawned); void sp_PerformActions(object oNearest, object oCurrent); void sp_GetDiceValue(object oNearest, string sCurrentName, string sNumDice, string sDice); void sp_GetSpawnSites(); void sp_Debug(string sString); void sp_CreateObject(object oNearest, string sBluePrint, int iToSpawn); string sp_CheckSpawnSite(object oNearest); string sp_SpawnChamp(object oNearest); string sp_CleanString(object oNearest, string sType); string sp_GetGroupObject(object oNearest, int iGroupTotal, string sTagType, object oLastSpawned=OBJECT_SELF); 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_CheckObjects(object oNearest); int sp_RollDice(int iNumDice, int iDice, int ReturnValue=FALSE); int sp_GetIsPCInArea(object oArea, object oNearest); int sp_GetGroupTotal(object oNearest, string sTagType); int sp_CheckPlayerInventory(object oNearest, object oPC); int sp_CheckRules(int iDontSpawn, int iAlive, object oNearest); int sp_CheckLevel(object oNearest, object oPC); int sp_PlayerView(object oCreature); location sp_RandomLocation(object oNearest, int iRandArea); void sp_ModInit(); void sp_ModInit() { /* # Groups # # Undead 1 */ SetLocalString(OBJECT_SELF, "group01_1", "NW_SKELETON"); SetLocalString(OBJECT_SELF, "group01_2", "NW_GHOUL"); SetLocalString(OBJECT_SELF, "group01_3", "NW_MUMMY"); SetLocalString(OBJECT_SELF, "group01_4", "NW_WRAITH"); //SetLocalString(OBJECT_SELF, "group01_5", "NW_LICH003"); /* # 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"); SetLocalString(OBJECT_SELF, "champ02", "jw_ogre_mage"); /* # Single Items # */ SetLocalString(OBJECT_SELF, "item01", "NW_IT_BOOK018"); /* # Group Items # */ SetLocalString(OBJECT_SELF, "item01_1", "NW_IT_BOOK005"); SetLocalString(OBJECT_SELF, "item01_2", "NW_IT_BOOK018"); SetLocalString(OBJECT_SELF, "item01_3", "NW_IT_BOOK022"); /* # Animations # */ SetLocalInt(OBJECT_SELF, "anim01", ANIMATION_FIREFORGET_BOW); SetLocalInt(OBJECT_SELF, "anim02", ANIMATION_FIREFORGET_DRINK); SetLocalInt(OBJECT_SELF, "anim03", ANIMATION_FIREFORGET_GREETING); SetLocalInt(OBJECT_SELF, "anim04", ANIMATION_FIREFORGET_HEAD_TURN_LEFT); SetLocalInt(OBJECT_SELF, "anim05", ANIMATION_FIREFORGET_HEAD_TURN_RIGHT); SetLocalInt(OBJECT_SELF, "anim06", ANIMATION_FIREFORGET_PAUSE_BORED); SetLocalInt(OBJECT_SELF, "anim07", ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD); SetLocalInt(OBJECT_SELF, "anim08", ANIMATION_FIREFORGET_READ); SetLocalInt(OBJECT_SELF, "anim09", ANIMATION_FIREFORGET_STEAL); SetLocalInt(OBJECT_SELF, "anim11", ANIMATION_FIREFORGET_TAUNT); SetLocalInt(OBJECT_SELF, "anim12", ANIMATION_FIREFORGET_VICTORY1); SetLocalInt(OBJECT_SELF, "anim13", ANIMATION_FIREFORGET_VICTORY2); SetLocalInt(OBJECT_SELF, "anim14", ANIMATION_FIREFORGET_VICTORY3); SetLocalInt(OBJECT_SELF, "anim15", ANIMATION_LOOPING_MEDITATE); /* # ##*/ SetLocalInt(OBJECT_SELF, "ModInit", 1); } void main() { // Setup Group, Champion, Item and Camp vars // if (!GetLocalInt(OBJECT_SELF, "ModInit")) { sp_ModInit(); RegisterGroups(); } ////////////////////////////////////////////////////////////////////////////// // Check if spawn sites are set and if not store their locations. // if (GetLocalObject(OBJECT_SELF, "SpawnSite1") == OBJECT_INVALID) { sp_GetSpawnSites(); } ////////////////////////////////////////////////////////////////////////////// // If spawn sites exist, start the process. // int nNth = 1; object oNearest = GetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(nNth)); if (oNearest == OBJECT_INVALID) { return; } while (oNearest != OBJECT_INVALID) { // Check spawner and see if a timer is already running and if // the spawn site has been destroyed or not. // // Debug if (iDebug == 3) { sp_Debug(GetName(oNearest)); } if (!GetLocalInt(oNearest, "SpawnDestroyed")) { ActionDoCommand(sp_Main(oNearest)); } nNth++; oNearest = GetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(nNth)); } } // No comments beyond this point :) void sp_DestroyObject(object oNearest, string sTagType) { // Debug if (iDebug == 3) { sp_Debug("sp_DestroyObject"); } SetLocalInt(oNearest, "DestroyedBySpawner", 1); // Debug if (iDebug == 1) { sp_Debug("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 (oCreatureToKill != OBJECT_INVALID) { if (GetLocalObject(oCreatureToKill, "SpawnedBy") == oNearest) { int iKillObjects; if (GetLocalInt(oNearest, "PlayerView")) { if (sp_PlayerView(oCreatureToKill) != 1) { iKillObjects = 1; } } else { iKillObjects = 1; } if ((!GetIsInCombat(oCreatureToKill) || sTagType == "Camp" || GetLocalInt(oNearest, "KillCreatures")) && iKillObjects) { // Debug if (iDebug == 1) { sp_Debug("Killing " + sTagType); sp_Debug("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)); } if (GetLocalInt(oNearest, "CORPSE_PERSIST")) { AssignCommand(oCreatureToKill, SetIsDestroyable(TRUE, FALSE, FALSE)); } DestroyObject(oCreatureToKill, 0.0); } else if (GetLocalInt(oNearest, "IsTreasure") && iKillObjects) { DestroyObject(oCreatureToKill, 0.0); } } } } } void sp_CheckVars(object oNearest, string sCurrentName) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckVars"); } // Debug if (iDebug == 1) { sp_Debug("Checking Variables..."); } SetLocalInt(oNearest, "ID", sp_GetValue(oNearest, "ID", sCurrentName)); SetLocalInt(oNearest, "CreatureGroupRandom", 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, "ChampRemote", sp_GetValue(oNearest, "CR", sCurrentName)); SetLocalInt(oNearest, "RandomFacing", sp_GetValue(oNearest, "RF", sCurrentName)); SetLocalInt(oNearest, "AreaEffect", sp_GetValue(oNearest, "AE", sCurrentName)); SetLocalInt(oNearest, "ReturnHome", sp_GetValue(oNearest, "RH", sCurrentName)); SetLocalInt(oNearest, "CreateItem", sp_GetValue(oNearest, "CI", sCurrentName)); SetLocalInt(oNearest, "ItemGroup", sp_GetValue(oNearest, "IG", sCurrentName)); SetLocalInt(oNearest, "PlayerInventory", sp_GetValue(oNearest, "PI", sCurrentName)); SetLocalInt(oNearest, "PlayAnim", sp_GetValue(oNearest, "AN", sCurrentName)); SetLocalInt(oNearest, "SpawnRemote", sp_GetValue(oNearest, "EX", sCurrentName)); SetLocalInt(oNearest, "PCInArea", sp_GetValue(oNearest, "PA", sCurrentName)); SetLocalInt(oNearest, "ResetTimer", sp_GetValue(oNearest, "RT", sCurrentName)); SetLocalInt(oNearest, "StartLevel", sp_GetValue(oNearest, "SL", sCurrentName)); SetLocalInt(oNearest, "MaxLevel", sp_GetValue(oNearest, "ML", sCurrentName)); SetLocalInt(oNearest, "PlayerView", sp_GetValue(oNearest, "PV", sCurrentName)); SetLocalInt(oNearest, "TrapDisarm", sp_GetValue(oNearest, "TD", sCurrentName)); // Start - Companion Script Switches SetLocalInt(oNearest, "CORPSE_PERSIST", sp_GetValue(oNearest, "CC", sCurrentName)); SetLocalInt(oNearest, "PickupItems", sp_GetValue(oNearest, "PU", sCurrentName)); SetLocalInt(oNearest, "DontZone", sp_GetValue(oNearest, "DZ", sCurrentName)); SetLocalInt(oNearest, "PlayerKilled", sp_GetValue(oNearest, "PK", sCurrentName)); SetLocalInt(oNearest, "AutoEquip", sp_GetValue(oNearest, "AI", sCurrentName)); // End SetLocalInt(oNearest, "NoFirst", sp_GetValue(oNearest, "NF", sCurrentName)); if (GetLocalInt(oNearest, "NoFirst")) { SetLocalInt(oNearest, "HasSpawned", 1); } SetLocalInt(oNearest, "IsSpawner", 1); ////////////////////////////////////////////////////////////////////////////// // If any actions are specified, set a var if (GetLocalInt(oNearest, "RandomWalk") || GetLocalInt(oNearest, "ReturnHome") || GetLocalInt(oNearest, "RandomFacing") || GetLocalInt(oNearest, "PlayAnim")) { SetLocalInt(oNearest, "DoActions", 1); } } void sp_Spawn(object oNearest, string sTemplate, int iSpawnX) { // Debug if (iDebug == 3) { sp_Debug("sp_Spawn"); } if (!GetLocalInt(oNearest, "IsValid")) { // Debug if (iDebug == 1) sp_Debug("No longer valid. Stopping spawn."); SetLocalInt(oNearest, "Spawning", GetLocalInt(oNearest, "Spawning") - iSpawnX); return; } // Debug if (iDebug == 1) { sp_Debug("Spawning..."); } location lCurrentWP = GetLocation(oNearest); if (GetLocalInt(oNearest, "SpawnChamp")) { sTemplate = GetStringLowerCase(GetLocalString(OBJECT_SELF, sTemplate)); SetLocalInt(oNearest, "ChampHasSpawned", 1); DeleteLocalInt(oNearest, "SpawnChamp"); // Debug if (iDebug == 2) { sp_Debug("Spawning Champion " + sTemplate); } } int iGroupTotal; int iValid; int iTotalX; for (iTotalX = 0; iTotalX < iSpawnX; iTotalX++) { iValid = 1; if (GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "ChampHasSpawned")) { iGroupTotal = sp_GetGroupTotal(oNearest, "Creature"); sTemplate = GetStringLowerCase(sp_GetGroupObject(oNearest, iGroupTotal, "Creature")); // Debug if (iDebug == 2) { sp_Debug("Spawning Group Creature " + sTemplate); } } if (GetLocalInt(oNearest, "NPC_Radius") && iValid) { if (GetLocalInt(oNearest, "NearPlayer")) { object oPlayer = GetNearestCreature( CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oNearest); if (oPlayer != OBJECT_INVALID) { lCurrentWP = sp_RandomLocation(oPlayer, GetLocalInt(oNearest, "NPC_Radius")); } else { iValid = 0; // Debug if (iDebug == 1) { sp_Debug("Player is not valid..."); } } } else { lCurrentWP = sp_RandomLocation(oNearest, GetLocalInt(oNearest, "NPC_Radius")); } } if (GetLocalInt(oNearest, "SpawnRemote")) { int iSpawnRemote; if (GetLocalInt(oNearest, "ChampRemote")) { if (GetLocalInt(oNearest, "ChampHasSpawned")) { iSpawnRemote = 1; } } else { iSpawnRemote = 1; } if (iSpawnRemote) { lCurrentWP = GetLocation(GetLocalObject(OBJECT_SELF, "RemoteSite" + IntToString(GetLocalInt(oNearest, "SpawnRemote")))); } } object oNewObject; if (GetLocalInt(oNearest, "IsTreasure") && iValid) { oNewObject = CreateObject(OBJECT_TYPE_PLACEABLE, sTemplate, lCurrentWP, TRUE); SetLocalInt(oNearest, "Spawning", GetLocalInt(oNearest, "Spawning") - 1); sp_TagObject(oNearest, "Item", oNewObject); } 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); } oNewObject = CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lCurrentWP, TRUE); SetLocalInt(oNearest, "Spawning", GetLocalInt(oNearest, "Spawning") - 1); sp_TagObject(oNearest, "Creature", oNewObject); } if (GetLocalInt(oNearest, "Camp") && !GetLocalInt(oNearest, "CampExists")) { sp_SpawnCamp(oNearest, lCurrentWP); } } } string sp_CleanString(object oNearest, string sType) { // Debug if (iDebug == 3) { sp_Debug("sp_CleanString"); } // Debug else if (iDebug == 1) { sp_Debug("Cleaning String..."); } 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, 3)) == "wn_" && 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 (GetStringLowerCase( GetStringLeft(sCurrentTag, 6)) == "night_" && 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) { /// Debug if (iDebug == 3) { sp_Debug("sp_CheckDistance"); } else if (iDebug == 1) { sp_Debug("Checking Distance..."); } int iRD = 0; int iSpawnDistance = GetLocalInt(oNearest, "PC_Radius"); if (iSpawnDistance >= 1) { object oArea = GetArea(oNearest); object oPC = GetFirstPC(); if (oPC != OBJECT_INVALID) { while (oPC != OBJECT_INVALID) { if (GetArea(oPC) == oArea) { if (GetDistanceBetween(oNearest, oPC) <= IntToFloat(iSpawnDistance)) { if (GetLocalInt(oNearest, "TrapType")) { sp_CheckTrap(oNearest, oPC); } if (GetLocalInt(oNearest, "InCombat") && GetIsInCombat(oPC)) { if (GetLocalInt(oNearest, "ChampSpawn") && GetLocalInt(oNearest, "HasSpawned") && !GetLocalInt(oNearest, "ChampHasSpawned")) { iRD = 1; } else { iRD = 2; } } else { iRD = 1; } if (GetLocalInt(oNearest, "PlayerInventory")) { if (!sp_CheckPlayerInventory(oNearest, oPC)) { iRD = 2; } } if (GetLocalInt(oNearest, "CheckLevel")) { if (!sp_CheckLevel(oNearest, oPC)) { iRD = 2; } } } } oPC = GetNextPC(); } } } else { iRD = 1; } if (GetLocalInt(oNearest, "RD_DontSpawn")) { if (iRD == 1) { iRD = 0; } else { iRD = 1; } } if (iRD == 1 && GetLocalInt(oNearest, "RD_NumDice") && !GetLocalInt(oNearest, "RD_DiceRolled")) { iRD = sp_RollDice(GetLocalInt(oNearest, "RD_NumDice"), GetLocalInt(oNearest, "RD_Dice")); if (iRD == 1) { SetLocalInt(oNearest, "RD_DiceRolled", 1); } } else if (iRD == 0 && GetLocalInt(oNearest, "RD_DiceRolled")) { SetLocalInt(oNearest, "RD_DiceRolled", 0); } return iRD; } int sp_CheckTimeOfDay(object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckTimeOfDay"); } else if (iDebug == 1) { sp_Debug("Checking Time of Day..."); } 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 (iCalDay >= iStartDay && iCalDay <= iStopDay) { iValidTime = 1; } else if (iStopDay < iStartDay) { if (iCalDay >= iStartDay || iCalDay <= iStopDay) { iValidTime = 1; } } } else if (iCalDay == iStartDay) { iValidTime = 1; } } else if (GetLocalInt(oNearest, "HourSpawn")) { int iHour = GetTimeHour(); int iStartHour = GetLocalInt(oNearest, "HourSpawn"); if (GetLocalInt(oNearest, "StartMidnight")) { iStartHour = 0; } if (GetLocalInt(oNearest, "TimeThrough")) { int iStopHour = GetLocalInt(oNearest, "TimeThrough"); if (GetLocalInt(oNearest, "ThroughMidnight")) { iStopHour = 0; } if (iHour >= iStartHour && iHour <= iStopHour) { iValidTime = 1; } else if (iStopHour < iStartHour) { if (iHour >= iStartHour || iHour <= iStopHour) { iValidTime = 1; } } } else if (iHour == iStartHour) { iValidTime = 1; } } return iValidTime; } int sp_CheckObjects(object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckObjects"); } else if (iDebug == 1) { sp_Debug("Counting Creatures..."); } int iMaxXX = GetLocalInt(oNearest, "SpawnAmount"); if (GetLocalInt(oNearest, "SpawnRandomNumber") > 0) { iMaxXX += GetLocalInt(oNearest, "SpawnRandomNumber"); } if (GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "CreatureGroupRandom")) { iMaxXX = sp_GetGroupTotal(oNearest, "Creature"); } // Debug if (iDebug == 2) { sp_Debug("Max creatures is " + IntToString(iMaxXX)); } int iAlive = 0; int iCountSX_Dead = 0; int iCreature; object oCurrent; for (iCreature = iMaxXX; iCreature > 0; iCreature--) { oCurrent = GetLocalObject(oNearest, "Creature" + IntToString(iCreature)); if (oCurrent != OBJECT_INVALID && !GetIsDead(oCurrent)) { iAlive++; if (GetLocalInt(oNearest, "DoActions")) { ActionDoCommand(sp_PerformActions(oNearest, oCurrent)); } } else if (oCurrent != OBJECT_INVALID && GetIsDead(oCurrent)) { DeleteLocalObject(oNearest, "Creature" + IntToString(iCreature)); int iDeadCreatures = GetLocalInt(oNearest, "DeadCreatures") +1; if (iDeadCreatures >= 99) { iDeadCreatures = 1; } SetLocalInt(oNearest, "DeadCreatures", iDeadCreatures); SetLocalObject(oNearest, "DeadCreature" + IntToString(iDeadCreatures), oCurrent); } else if (GetLocalInt(oNearest, "IsTreasure")) { oCurrent = GetLocalObject(oNearest, "Item" + IntToString(iCreature)); if (oCurrent != OBJECT_INVALID && GetTag(oCurrent) != "") { iAlive++; } else { DeleteLocalObject(oNearest, "Item" + IntToString(iCreature)); } } } return iAlive; } int sp_CreaturesToSpawn(object oNearest, int iAlive) { // Debug if (iDebug == 3) { sp_Debug("sp_CreaturesToSpawn"); } else if (iDebug == 1) { sp_Debug("Determining Number To Spawn..."); } int iSpawnRandom = GetLocalInt(oNearest, "SpawnRandomNumber"); int iMin = GetLocalInt(oNearest, "SpawnAmount"); int iMaxXX = iMin; int iCountSX_Dead; if (iSpawnRandom > 0) { iMaxXX += iSpawnRandom; } if (GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "CreatureGroupRandom")) { iMaxXX = sp_GetGroupTotal(oNearest, "Creature"); return iMaxXX - iAlive; } iCountSX_Dead = iMaxXX - iAlive; if (iCountSX_Dead > 0 && iSpawnRandom > 0) { int iAlive = iMaxXX - iCountSX_Dead; if (iAlive < iMin) { int iRand = iMaxXX - iAlive; iCountSX_Dead = Random(iRand)+1; } 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) { // Debug if (iDebug == 3) { sp_Debug("sp_GetValue"); } else if (iDebug == 1) { sp_Debug("Getting Variable Values..."); } int iSwitchValue = 0; int iIsMinutes = 0; int iIsHours = 0; if (FindSubString(sCurrentName, sSwitch) > 0) { if (sSwitch == "TR" || // Treasure sSwitch == "NP" || // Spawn near player sSwitch == "NF" || // Skip the timer during module loading sSwitch == "IC" || // Do not spawn if in combat sSwitch == "SS" || // Stop spawn after all are dead sSwitch == "GP" || // Spawn a group sSwitch == "GR" || // Spawn random from group sSwitch == "RF" || // Face random direction sSwitch == "CR" || // Spawn champ remotely sSwitch == "PA" || // Spawn only if player is in the area sSwitch == "RT" || // Reset timer sSwitch == "PV" || // Player in view // Third party switches sSwitch == "DZ" || sSwitch == "PK" || sSwitch == "CC" || sSwitch == "AI" || 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")) { if (iSwitchValue == 0) { iSwitchValue = 1; SetLocalInt(oNearest, "StartMidnight", 1); } if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "T") { int iTime = StringToInt(GetSubString(sCurrentName, (iNumberPos + 5), 2)); if (iTime == 0) { iTime = 1; SetLocalInt(oNearest, "ThroughMidnight", 1); } SetLocalInt(oNearest, "TimeThrough", iTime); } } else if (sSwitch == "TP" && GetSubString(sCurrentName, (iNumberPos + 4), 1) == "A") { SetLocalInt(oNearest, "TrapAmulet", StringToInt(GetSubString( sCurrentName, (iNumberPos + 5), 2))); } else if (sSwitch == "CH") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "CH_NumDice", "CH_Dice"); } } else if (sSwitch == "CI") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "CI_NumDice", "CI_Dice"); } } else if (sSwitch == "GT") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "GT_NumDice", "GT_Dice"); } } else if (sSwitch == "IG") { iSwitchValue = 1; if (GetSubString(sCurrentName, (iNumberPos + 2), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "IG_NumDice", "IG_Dice"); } } else if (sSwitch == "PI") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "X") { SetLocalInt(oNearest, "InInventory", 1); } else if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "D") { SetLocalInt(oNearest, "DestroyItem", 1); } } else if (sSwitch == "TD") { iSwitchValue = 1; if (GetSubString(sCurrentName, (iNumberPos + 2), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "TD_NumDice", "TD_Dice"); } } else if (sSwitch == "RD") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "X") { SetLocalInt(oNearest, "KillCreatures", 1); } else if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "N") { SetLocalInt(oNearest, "RD_DontSpawn", 1); } else if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "RD_NumDice", "RD_Dice"); } } else if (sSwitch == "NT") { iSwitchValue = 1; if (GetSubString(sCurrentName, (iNumberPos + 2), 1) == "X") { SetLocalInt(oNearest, "KillCreatures", 1); } } else if (sSwitch == "DT") { iSwitchValue = 1; if (GetSubString(sCurrentName, (iNumberPos + 2), 1) == "X") { SetLocalInt(oNearest, "KillCreatures", 1); } } else if (sSwitch == "ML" || sSwitch == "SL") { SetLocalInt(oNearest, "CheckLevel", 1); } else if (sSwitch == "RW") { if (iSwitchValue < 1) { iSwitchValue = 1; } if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "R") { string sStringToParse = GetStringRight(sCurrentName, iNumberLength); sp_GetDiceValue(oNearest, sStringToParse, "RW_NumDice", "RW_Dice"); } } else if (sSwitch == "AN") { if (GetSubString(sCurrentName, (iNumberPos + 4), 1) == "L") { SetLocalInt(oNearest, "AnimLoop", StringToInt(GetSubString( sCurrentName, (iNumberPos + 5), 2))); } } else if (sSwitch == "RH") { if (GetSubString(sCurrentName, (iNumberPos + 2), 1) == "F") { SetLocalInt(oNearest, "AboutFace", 1); } iSwitchValue = 1; } else if (sSwitch == "ID") { SetLocalObject(GetModule(), "Spawner" + IntToString(iSwitchValue), oNearest); } 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); } } } } else if (sSwitch == "SX") { if (GetLocalInt(oNearest, "GroupSpawn") && !GetLocalInt(oNearest, "CreatureGroupRandom")) { iSwitchValue = sp_GetGroupTotal(oNearest, "Creature"); } else { iSwitchValue = 1; } } return iSwitchValue; } int sp_GetGroupTotal(object oNearest, string sTagType) { // Debug if (iDebug == 3) { sp_Debug("sp_GetGroupTotal"); } else if (iDebug == 1) { sp_Debug("Checking group total..."); } int iGroupValid = 0; int iGroupTotal = 1; string sTemplate; if (sTagType == "Creature") { // Debug if (iDebug == 1) { sp_Debug("Checking group Creature..."); } sTemplate = GetStringLowerCase(GetLocalString(oNearest, "Tag")); } else if (sTagType == "Camp") { sTemplate = "camp"; // Debug if (iDebug == 1) { sp_Debug("Checking group Camp..."); } if (GetLocalInt(oNearest, "Camp") < 10) { sTemplate += "0" + IntToString(GetLocalInt(oNearest, "Camp")); } else { sTemplate += IntToString(GetLocalInt(oNearest, "Camp")); } } else if (sTagType == "Item") { sTemplate = "item"; // Debug if (iDebug == 1) { sp_Debug("Checking group Item..."); } if (GetLocalInt(oNearest, "CreateItem") < 10) { sTemplate += "0" + IntToString(GetLocalInt(oNearest, "CreateItem")); } else { sTemplate += IntToString(GetLocalInt(oNearest, "CreateItem")); } } string sGroup; while (iGroupValid != 1) { if (sTagType == "Creature") { sGroup = GetStringLowerCase(sTemplate) + "_" + IntToString(iGroupTotal); } if (sTagType == "Item") { sGroup = GetStringLowerCase(sTemplate) + "_" + IntToString(iGroupTotal); } else if (sTagType == "Camp") { sGroup = GetStringLowerCase(sTemplate) + "_resref_" + IntToString(iGroupTotal); } if (GetLocalString(OBJECT_SELF, sGroup) == "") { iGroupValid = 1; iGroupTotal--; } else { iGroupTotal++; } } return iGroupTotal; } string sp_SpawnChamp(object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_SpawnChamp"); } int iChampValid; int iChampNumDie = GetLocalInt(oNearest, "CH_NumDice"); int iChampDie = GetLocalInt(oNearest, "CH_Dice"); int iDieResult; if (!iChampNumDie) { iChampValid = 1; } else { iChampValid = sp_RollDice(iChampNumDie, iChampDie); } 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_GetGroupObject(object oNearest, int iGroupTotal, string sTagType, object oLastSpawned=OBJECT_SELF) { // Debug if (iDebug == 3) { sp_Debug("sp_GetGroupObjectt"); } int iSpawnRand; string sGroup; string sCurrentTag; string sTemplate; // Check for creature group random if (GetLocalInt(oNearest, sTagType + "GroupRandom")) { iSpawnRand = Random(iGroupTotal)+1; if (sTagType == "Creature") { sGroup = GetStringLowerCase(GetLocalString(oNearest, "Tag")) + "_" + IntToString(iSpawnRand); } sCurrentTag = GetLocalString(OBJECT_SELF, sGroup); return sCurrentTag; } else if (GetLocalInt(oNearest, "IG_Dice")) { int iIGDice = GetLocalInt(oNearest, "IG_Dice"); int iIGNumDice = GetLocalInt(oNearest, "IG_NumDice"); int iGroupItem = sp_RollDice(iIGNumDice, iIGDice, TRUE); sGroup = "item"; if (GetLocalInt(oNearest, "CreateItem") < 10) { sGroup += "0"; } sGroup += IntToString(GetLocalInt(oNearest, "CreateItem")) + "_" + IntToString(iGroupItem); sCurrentTag = GetLocalString(OBJECT_SELF, sGroup); return sCurrentTag; } // Not random so get the whole group else { object oCurrent; int iCreature; int iGroup; for (iGroup = iGroupTotal; iGroup > 0; iGroup--) { if (sTagType == "Creature") { sGroup = GetStringLowerCase(GetLocalString(oNearest, "Tag")) + "_" + IntToString(iGroup); } else if (sTagType == "Item") { sGroup = "item"; if (GetLocalInt(oNearest, "CreateItem") < 10) { sGroup += "0"; } sGroup += IntToString(GetLocalInt(oNearest, "CreateItem")) + "_" + IntToString(iGroup); } sCurrentTag = GetLocalString(OBJECT_SELF, sGroup); int iValid = 0; if (sTagType == "Creature") { for (iCreature = iGroupTotal; iCreature >= 1; iCreature--) { oCurrent = GetLocalObject(oNearest, sTagType + IntToString(iCreature)); if (oCurrent != OBJECT_INVALID) { if (sCurrentTag == GetTag(oCurrent)) { iValid = 1; } } } } else if (sTagType == "Item") { object oCurItem = GetFirstItemInInventory(oLastSpawned); if (sCurrentTag == GetTag(oCurItem)) { iValid = 1; } else { if (oCurItem != OBJECT_INVALID) { while (oCurItem != OBJECT_INVALID && iValid != 1) { oCurItem = GetNextItemInInventory(oLastSpawned); if (sCurrentTag == GetTag(oCurItem)) { iValid = 1; } } } } } if (iValid != 1) { return sCurrentTag; } } } if (sTemplate == "") { // Debug if (iDebug == 1) { sp_Debug("Template is blank"); } } else if (iDebug == 1) { // Debug sp_Debug("Template - " + sTemplate); } return sCurrentTag; } void sp_TagObject(object oNearest, string sTagType, object oNewObject) { // Debug if (iDebug == 3) { sp_Debug("sp_TagObject"); } int iCreature; object oCreature; object oLastSpawned = oNewObject; SetLocalObject(oLastSpawned, "SpawnedBy", oNearest); iCreature = 1; oCreature = GetLocalObject(oNearest, sTagType + IntToString(iCreature)); while (oCreature != OBJECT_INVALID) { iCreature++; oCreature = GetLocalObject(oNearest, sTagType + IntToString(iCreature)); } SetLocalObject(oNearest, sTagType + IntToString(iCreature), oLastSpawned); if (GetLocalInt(oNearest, "CORPSE_PERSIST") && sTagType == "Creature") { SetLocalInt(oLastSpawned, "CORPSE_PERSIST", 1); AssignCommand(oLastSpawned, SetIsDestroyable(FALSE, FALSE, FALSE)); } if (GetLocalInt(oNearest, "GenTreasure") && sTagType == "Creature") { int iGTNumDie = GetLocalInt(oNearest, "CH_NumDice"); int iGTDice = GetLocalInt(oNearest, "CH_Dice"); int iGTValid; if (!iGTNumDie) { iGTValid = 1; } else { iGTValid = sp_RollDice(iGTNumDie, iGTDice); } if (iGTValid) { 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 (GetLocalInt(oNearest, "CreateItem")) { sp_CreateItem(oNearest, oLastSpawned); } if (sTagType == "Item" && GetLocalInt(oNearest, "TrapDisarm")) { if (GetIsTrapped(oLastSpawned) && GetTrapDisarmable(oLastSpawned)) { int iTrapNumDice = GetLocalInt(oNearest, "TD_NumDice"); int iTrapDice = GetLocalInt(oNearest, "TD_Dice"); int iTrapValid = sp_RollDice(iTrapNumDice, iTrapDice); if (iTrapValid) { SetTrapDisabled(oLastSpawned); } } } // Debug if (iDebug == 1) { sp_Debug("Owner of " + GetTag(oLastSpawned) + " is " + GetName(GetLocalObject( oLastSpawned, "SpawnedBy"))); } } void sp_SpawnCamp(object oNearest, location lCurrentWP) { // Debug if (iDebug == 3) { sp_Debug("sp_SpawnCamp"); } 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)); 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; } } } object oNewObject = CreateObject(OBJECT_TYPE_PLACEABLE, sItemResRef, lMyLoc, TRUE); sp_TagObject(oNearest, "Camp", oNewObject); iItem++; } else { iCampEquip = 1; SetLocalInt(oNearest, "CampExists", 1); } } } void sp_CheckTrap(object oNearest, object oPC) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckTrap"); } else if (iDebug == 1) { sp_Debug("Checking Trap..."); } effect eDamage; effect eEffect; string sDamageCause; string sAmulet = "blank"; if (oPC != OBJECT_INVALID) { // Debug if (iDebug == 1) { sp_Debug("PC is valid..."); } 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")) { // Debug if (iDebug == 1) { sp_Debug("Checking for Amulet..."); } switch (GetLocalInt(oNearest, "TrapAmulet")) { case 01: sAmulet = "PalorsAmulet"; break; case 02: sAmulet = "PalorsOtherAmulet"; break; } } if (GetTag(GetItemInSlot(INVENTORY_SLOT_NECK, oPC)) != sAmulet) { // Debug if (iDebug == 1) { sp_Debug("PC does not have Amulet..."); } SendMessageToPC(oPC, sDamageCause); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect, GetLocation(oPC)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oPC); } } else { // Debug if (iDebug == 1) { sp_Debug("PC is not valid..."); } } } void sp_AreaEffect(object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_AreaEffect"); } else if (iDebug == 1) { sp_Debug("Setting Area Effect..."); } 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); } int sp_RollDice(int iNumDice, int iDice, int ReturnValue=FALSE) { // Debug if (iDebug == 3) { sp_Debug("sp_RollDice"); } int iDieResult; switch (iDice) { case 2: iDieResult = d2(iNumDice); break; case 3: iDieResult = d3(iNumDice); break; case 4: iDieResult = d4(iNumDice); break; case 6: iDieResult = d6(iNumDice); break; case 8: iDieResult = d8(iNumDice); break; case 10: iDieResult = d10(iNumDice); break; case 12: iDieResult = d12(iNumDice); break; case 20: iDieResult = d20(iNumDice); break; case 100: iDieResult = d100(iNumDice); break; default:;break; } if (ReturnValue) { return iDieResult; } else if (iDieResult == iNumDice) { return TRUE; } else { return FALSE; } } void sp_GetDiceValue(object oNearest, string sCurrentName, string sNumDice, string sDice) { // Debug if (iDebug == 3) { sp_Debug("sp_GetDiceValue"); } if (FindSubString(sCurrentName, "_") >= 1) { sCurrentName = GetStringLeft(sCurrentName, FindSubString(sCurrentName, "_")); } while (!StringToInt(GetStringLeft(sCurrentName, 1))) { sCurrentName = GetStringRight(sCurrentName, GetStringLength(sCurrentName) - 1); } if (GetSubString(sCurrentName, 2, 1) == "R") { sCurrentName = GetStringRight(sCurrentName, GetStringLength(sCurrentName) - 3); } SetLocalInt(oNearest, sNumDice, StringToInt(GetStringLeft( sCurrentName, FindSubString(sCurrentName, "d")))); SetLocalInt(oNearest, sDice, StringToInt(GetStringRight( sCurrentName, (GetStringLength(sCurrentName) - FindSubString(sCurrentName, "d")) - 1))); } int sp_CheckPlayerInventory(object oNearest, object oPC) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckPlayerInventory"); } int iInInventory = GetLocalInt(oNearest, "InInventory"); int iPlayerHas; int iSpawnValid; int iItem = GetLocalInt(oNearest, "PlayerInventory"); string sItem = "item"; if (iItem < 10) { sItem += "0" + IntToString(iItem); } else { sItem += IntToString(iItem); } string sItemTag = GetLocalString(OBJECT_SELF, sItem); object oItem = GetFirstItemInInventory(oPC); while (oItem != OBJECT_INVALID && iPlayerHas != 1) { if (GetTag(oItem) == sItemTag) { iPlayerHas = 1; if (GetLocalInt(oNearest, "DestroyItem")) { DestroyObject(oItem); } } oItem = GetNextItemInInventory(oPC); } if (iInInventory && !iPlayerHas) { iSpawnValid = 1; } else if (!iInInventory && iPlayerHas) { iSpawnValid = 1; } return iSpawnValid; } location sp_RandomLocation(object oNearest, int iRandArea) { // Debug if (iDebug == 3) { sp_Debug("sp_RandomLocation"); } else if (iDebug == 1) { sp_Debug("Choosing Random Location..."); } vector vNewPos = GetPosition(oNearest); object oArea = GetArea(oNearest); float fX, fY; float fMaxY; float fRadius = IntToFloat(iRandArea); fX = (Random(200)/100.0 - 1.0) * fRadius; fMaxY=sqrt(fRadius*fRadius-fX*fX); fY = (Random(200)/100.0 - 1.0) * fMaxY; vNewPos += Vector(fX, fY, 0.0); location lNewLoc = Location(oArea, vNewPos, VectorToAngle(-1.0 * vNewPos)); return lNewLoc; } void sp_PerformActions(object oNearest, object oCurrent) { // Debug if (iDebug == 3) { sp_Debug("sp_PerformActions"); } if (GetLocalInt(oNearest, "RandomWalk") && GetCurrentAction(oCurrent) == 65535 && !IsInConversation(oCurrent)) { int iWalkRandom; int iNumDice = GetLocalInt(oNearest, "RW_NumDice"); int iDice = GetLocalInt(oNearest, "RW_Dice"); if (!iDice) { iWalkRandom = 1; } else { iWalkRandom = 0; iWalkRandom = sp_RollDice(iNumDice, iDice); } if (iWalkRandom) { int iRandWalk = GetLocalInt(oNearest, "RandomWalk"); object oCurLoc; if (GetLocalInt(oNearest, "SpawnRemote")) { oCurLoc = GetLocalObject(OBJECT_SELF, "RemoteSite" + IntToString(GetLocalInt(oNearest, "SpawnRemote"))); } else { oCurLoc = oNearest; } if (iRandWalk > 1 && GetDistanceToObject(oCurLoc) > IntToFloat(iRandWalk)) { location lRandWalk = sp_RandomLocation(oCurLoc, iRandWalk); AssignCommand(oCurrent, ActionMoveToLocation(lRandWalk)); } else { AssignCommand(oCurrent, ActionRandomWalk()); } } } if (GetLocalInt(oNearest, "PlayAnim")) { if (d2() == 1) { int iAnim = GetLocalInt(oNearest, "PlayAnim"); string sAnim = "anim"; if (iAnim >= 10) { sAnim += IntToString(iAnim); } else { sAnim += "0" + IntToString(iAnim); } int iAnimToPlay = GetLocalInt(OBJECT_SELF, sAnim); float fAnimLoop = 1.0; if (GetLocalInt(oNearest, "AnimLoop")) { fAnimLoop = IntToFloat(GetLocalInt(oNearest, "AnimLoop")); } AssignCommand(oCurrent, PlayAnimation(iAnimToPlay, 1.0, fAnimLoop)); } } if (GetLocalInt(oNearest, "ReturnHome") && GetCurrentAction(oCurrent) == 65535) { if (!GetIsInCombat(oCurrent) && !IsInConversation(oCurrent)) { if (GetDistanceBetween(oNearest, oCurrent) > 5.0) { AssignCommand(oCurrent, ActionMoveToObject(oNearest)); } else if (GetFacing(oNearest) != GetFacing(oCurrent) && GetLocalInt(oNearest, "AboutFace")) { AssignCommand(oCurrent, SetFacing(GetFacing(oNearest))); } } } if (GetLocalInt(oNearest, "RandomFacing") && GetCurrentAction(oCurrent) == 65535 && d2() == 1) { int iRandomDir = Random(270); AssignCommand(oCurrent, SetFacing(IntToFloat(iRandomDir))); } } int sp_GetIsPCInArea(object oArea, object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_GetIsPCInArea"); } int iPCInArea; object oPC = GetFirstPC(); if (oPC != OBJECT_INVALID) { while (oPC != OBJECT_INVALID && !iPCInArea) { if (GetArea(oPC) == oArea) { if (GetLocalInt(oNearest, "CheckLevel")) { if (!sp_CheckLevel(oNearest, oPC)) { iPCInArea = 1; } } else { iPCInArea = 1; } } oPC = GetNextPC(); } } return iPCInArea; } int sp_CheckRules(int iDontSpawn, int iAlive, object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckRules"); } else if (iDebug == 2) { sp_Debug("Found " + IntToString(iAlive) + " alive."); } // // Check for time of day. // Check how many creatures are at the spawn point. // int iIsValid = 1; // // 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, "IsTreasure")) { sp_DestroyObject(oNearest, "Item"); } 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, "IsTreasure")) { sp_DestroyObject(oNearest, "Item"); } if (GetLocalInt(oNearest, "Camp")) { sp_DestroyObject(oNearest, "Camp"); SetLocalInt(oNearest, "CampExists", 0); } } } } // // Check for PC in Area if (GetLocalInt(oNearest, "PCInArea")) { int iPCInArea = sp_GetIsPCInArea(GetArea(OBJECT_SELF), oNearest); if (!iPCInArea) { if (GetLocalInt(oNearest, "ResetTimer")) { SetLocalInt(oNearest, "HasSpawned", 0); } iIsValid = 0; if (iAlive) { sp_DestroyObject(oNearest, "Creature"); if (GetLocalInt(oNearest, "IsTreasure")) { sp_DestroyObject(oNearest, "Item"); } if (GetLocalInt(oNearest, "Camp") && GetLocalInt(oNearest, "CampExists")) { sp_DestroyObject(oNearest, "Camp"); SetLocalInt(oNearest, "CampExists", 0); } } } } // // Check for Area effect 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 missing creatures. // if (!GetLocalInt(oNearest, "SpawnRandomNumber") && !iDontSpawn) { if (iAlive == GetLocalInt(oNearest, "SpawnAmount")) { iIsValid = 0; } } if (iIsValid && !GetLocalInt(oNearest, "SpawnChamp") && !iDontSpawn && (GetLocalInt(oNearest, "Spawning") < GetLocalInt(oNearest, "SpawnAmount"))) { 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; } // Debug if (iDebug == 1) { sp_Debug("Missing " + IntToString(iToSpawn) + " at " + GetTag(oNearest)); } } // if (GetLocalInt(oNearest, "KillSpawn")) { iIsValid = 0; AssignCommand(OBJECT_SELF, sp_DestroyObject(oNearest, "Creature")); if (GetLocalInt(oNearest, "IsTreasure")) { AssignCommand(OBJECT_SELF, sp_DestroyObject(oNearest, "Item")); } SetLocalInt(oNearest, "ChampHasSpawned", 0); SetLocalInt(oNearest, "SpawnDestroyed", 1); } // // Checking spawn in queue if (iToSpawn > GetLocalInt(oNearest, "Spawning")) { iToSpawn = iToSpawn - GetLocalInt(oNearest, "Spawning"); if (iToSpawn <= 0) { iIsValid = 0; if (GetLocalInt(oNearest, "ToSpawn")) { DeleteLocalInt(oNearest, "ToSpawn"); } } else { SetLocalInt(oNearest, "ToSpawn", iToSpawn); } } else if (!GetLocalInt(oNearest, "Spawning")) { iIsValid = 0; if (GetLocalInt(oNearest, "ToSpawn")) { DeleteLocalInt(oNearest, "ToSpawn"); } } return iIsValid; } void sp_CreateItem(object oNearest, object oLastSpawned) { // Debug if (iDebug == 3) { sp_Debug("sp_CreateItem"); } else if (iDebug == 1) { sp_Debug("Checking Item..."); } string sItem = "item"; int iCreateItem; int iDice = GetLocalInt(oNearest, "CI_Dice"); int iNumDice = GetLocalInt(oNearest, "CI_NumDice"); int sItemNumber = GetLocalInt(oNearest, "CreateItem"); if (!GetLocalInt(oNearest, "ItemGroup")) { if (sItemNumber >= 10) { sItem += IntToString(sItemNumber); } else { sItem += "0" + IntToString(sItemNumber); } sItem = GetLocalString(OBJECT_SELF, sItem); } if (!iDice) { iCreateItem = 1; } else { iCreateItem = 0; iCreateItem = sp_RollDice(iNumDice, iDice); } if (iCreateItem) { // Debug if (iDebug == 1) sp_Debug("Creating Item " + sItem); if (GetLocalInt(oNearest, "ItemGroup") && !GetLocalInt(oNearest, "IG_Dice")) { int iTotalItems = sp_GetGroupTotal(oNearest, "Item"); int iItems; for (iItems = 0; iItems < iTotalItems; iItems++) { sItem = sp_GetGroupObject(oNearest, iTotalItems, "Item", oLastSpawned); CreateItemOnObject(sItem, oLastSpawned); } } else if (GetLocalInt(oNearest, "IG_Dice")) { int iTotalItems = sp_GetGroupTotal(oNearest, "Item"); sItem = sp_GetGroupObject(oNearest, iTotalItems, "Item", oLastSpawned); CreateItemOnObject(sItem, oLastSpawned); } else { CreateItemOnObject(sItem, oLastSpawned); } } } void sp_GetSpawnSites() { // Debug if (iDebug == 3) { sp_Debug("sp_GetSpawnSites"); } object oNearest; int iSS; int iSpawnSite = 1; oNearest = GetFirstObjectInArea(GetArea(OBJECT_SELF)); while (oNearest != OBJECT_INVALID) { if (GetObjectType(oNearest) == 32 && !GetLocalInt(oNearest, "SpawnSite")) { string sName = GetName(oNearest); if (GetStringLeft(sName, 3) == "SP_") { SetLocalObject(OBJECT_SELF, "SpawnSite" + IntToString(iSpawnSite), oNearest); iSpawnSite++; SetLocalInt(oNearest, "SpawnSite", 1); } else if (GetStringLeft(sName, 3) == "XX_") { iSS = StringToInt(GetSubString(sName, FindSubString(sName, "_") + 1, 2)); SetLocalObject(OBJECT_SELF, "RemoteSite" + IntToString(iSS), oNearest); SetLocalInt(oNearest, "SpawnSite", 1); } else if (GetStringLeft(sName, 2) == "XX") { iSS = StringToInt(GetSubString(sName, 3, 2)); SetLocalObject(OBJECT_SELF, "RemoteSite" + IntToString(iSS), oNearest); SetLocalInt(oNearest, "SpawnSite", 1); } } oNearest = GetNextObjectInArea(GetArea(OBJECT_SELF)); } } string sp_CheckSpawnSite(object oNearest) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckSpawnSite"); } if (iDebug == 2) { sp_Debug(GetName(oNearest)); } // Get the Tag. // string sBluePrint; if (GetLocalString(oNearest, "Tag") == "") { SetLocalString(oNearest, "Tag", sp_CleanString(oNearest, "Tag")); } // Get the Blueprint. // if (GetLocalString(oNearest, "Blueprint") == "") { SetLocalString(oNearest, "Blueprint", sp_CleanString(oNearest, "Blueprint")); sBluePrint = GetLocalString(oNearest, "Blueprint"); // Debug if (iDebug == 1) { sp_Debug("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 iDontSpawn; if (sBluePrint == "" || sBluePrint == "effect") { iDontSpawn = 1; } int iAlive; if (!iDontSpawn) { iAlive = sp_CheckObjects(oNearest); } int iIsValid = sp_CheckRules(iDontSpawn, iAlive, oNearest); // Check for Champion // if (iIsValid && !iDontSpawn && !iAlive && GetLocalInt(oNearest, "ChampSpawn") && GetLocalInt(oNearest, "HasSpawned") && !GetLocalInt(oNearest, "ChampHasSpawned") && !GetLocalInt(oNearest, "DestroyedBySpawner") && !GetLocalInt(oNearest, "Spawning")) { string sChamp = sp_SpawnChamp(oNearest); if (sChamp != "") { SetLocalInt(oNearest, "ToSpawn", 1); sBluePrint = sChamp; } } else if (iIsValid && GetLocalInt(oNearest, "ChampHasSpawned")) { DeleteLocalInt(oNearest, "ChampHasSpawned"); } // Debug if (iDebug == 2) { sp_Debug("Blueprint is " + sBluePrint); } if (iDontSpawn) { iIsValid = 0; if (GetLocalInt(oNearest, "IsValid")) { DeleteLocalInt(oNearest, "IsValid"); } } SetLocalInt(oNearest, "IsValid", iIsValid); return sBluePrint; } void sp_CreateObject(object oNearest, string sBluePrint, int iToSpawn) { // Debug if (iDebug == 3) { sp_Debug("sp_CreateObject"); } DeleteLocalInt(oNearest, "DestroyedBySpawner"); float fSpawnTime; SetLocalInt(oNearest, "IsSpawning", 1); int iSpawnTime; string sSpawnTimer; string sTimerRandom; int iDoSpawnChamp = GetLocalInt(oNearest, "SpawnChamp"); if (GetLocalInt(oNearest, "SpawnTimer") && !iDoSpawnChamp) { sSpawnTimer = IntToString(GetLocalInt(oNearest, "SpawnTimer")); } if (GetLocalInt(oNearest, "TimerIsRandom") && !iDoSpawnChamp) { sTimerRandom = IntToString(GetLocalInt(oNearest, "TimerIsRandom")); } if (GetLocalInt(oNearest, "HasSpawned")) { // Debug if (iDebug == 1) { sp_Debug("Timer " + sSpawnTimer + " Random " + sTimerRandom); } if (GetLocalInt(oNearest, "TimerIsRandom") && !iDoSpawnChamp) { iSpawnTime = StringToInt(sSpawnTimer) + Random(StringToInt(sTimerRandom)); fSpawnTime = IntToFloat(iSpawnTime); } else if (!iDoSpawnChamp) { fSpawnTime = StringToFloat(sSpawnTimer); } } else { SetLocalInt(oNearest, "HasSpawned", 1); } // Debug if (iDebug == 1) { sp_Debug("Spawning " + sBluePrint + " delayed for " + IntToString(FloatToInt(fSpawnTime))); } SetLocalInt(oNearest, "Spawning", GetLocalInt(oNearest, "Spawning") + iToSpawn); DeleteLocalInt(oNearest, "ToSpawn"); if (fSpawnTime >= 1.0) { AssignCommand(OBJECT_SELF, DelayCommand( fSpawnTime, sp_Spawn(oNearest, sBluePrint, iToSpawn))); } else { sp_Spawn(oNearest, sBluePrint, iToSpawn); } } int sp_CheckLevel(object oNearest, object oPC) { // Debug if (iDebug == 3) { sp_Debug("sp_CheckLevel"); } int iMinLevel = GetLocalInt(oNearest, "StartLevel"); int iMaxLevel = GetLocalInt(oNearest, "MaxLevel"); int iPCLevel1 = GetLevelByPosition(1, oPC); int iPCLevel2 = GetLevelByPosition(2, oPC); int iPCLevel3 = GetLevelByPosition(3, oPC); int iValid; if (iMinLevel) { if (iPCLevel1 >= iMinLevel || iPCLevel2 >= iMinLevel || iPCLevel3 >= iMinLevel) { iValid = 1; } } if (iMaxLevel) { if (iMaxLevel >= iPCLevel1 && iMaxLevel >= iPCLevel2 && iMaxLevel >= iPCLevel3) { iValid = 1; } } return iValid; } int sp_PlayerView(object oCreature) { // Debug if (iDebug == 3) { sp_Debug("sp_PlayerView"); } object oPC = GetFirstPC(); while (oPC != OBJECT_INVALID) { if (GetObjectSeen(oCreature, oPC)) { return 1; } oPC = GetNextPC(); } return 0; } void sp_Debug(string sString) { SendMessageToPC(GetFirstPC(), sString); } void sp_Main(object oNearest) { int iIsValid; int iToSpawn; string sBluePrint = sp_CheckSpawnSite(oNearest); if (sBluePrint == "") { iIsValid = 0; SetLocalInt(oNearest, "IsValid", 0); } else { iIsValid = GetLocalInt(oNearest, "IsValid"); iToSpawn = GetLocalInt(oNearest, "ToSpawn"); } // If everything is ok, spawn. // if (iIsValid && iToSpawn) { AssignCommand(OBJECT_SELF, sp_CreateObject(oNearest, sBluePrint, iToSpawn)); } }