Initial upload. PRC8 has been added. Module compiles, PRC's default AI & treasure scripts have been integrated. Started work on top hak for SLA / Ability / Scripting modifications.
1467 lines
52 KiB
Plaintext
1467 lines
52 KiB
Plaintext
/*##
|
|
# UO Style Spawn System v2.2
|
|
# Author: Palor <palor@truefear.net>
|
|
# 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);
|
|
}
|
|
|