| Author |
Sticky: Post
Working Scripts Here |
| Amarande
|
Posted: Monday, 29 July 01:11AM |
SCRIPT TITLE: inc_guards
SUMMARY: Functions to create a permanently respawning guard system for
one or more areas. Useful for persistent worlds, or large city areas
which should have a near-inexhaustible supply of guards. The script will
maintain a near-constant population of a preset number of guards, the
number being able to be set on an area-by-area basis.
HOW TO USE THIS SCRIPT:
1. This script is designed for use as an include, so must be saved
*without* compiling.
2. This script is taken from my upcoming module, Darkness of the Sun. As
I use the Baldur's Gate style ARxxxx system for my area tag names, these
functions are designed making the assumption that area tags will be in
this format. This means that when using this script, it is strongly
suggested that you also use this system for naming area tags. It has not
been tested with any other system of area tag names, so you have been
warned.
3. To install this script on an area, do the following:
a) Create a SINGLE waypoint in the area, with the tag
AreaTag_GuardSpawnPoint, where AreaTag should, of course, be replaced by
the area's actual tag. There should be exactly one of these waypoints
per area. Script behavior is undefined if more than one such waypoint is
present. If the spawn waypoint is not present, the spawning function
will do nothing. I usually place this spawnpoint in front of a door, to
give the impression that guards are coming out of a building.
b) Unless you have adjusted the chance of female guards to either 0% or
100% (defaults to 33%; see below for how to adjust this), or unless you
*want* badgers, you will need to create two guard templates for each
area using the script. These should have blueprint ResRefs of guardXXXXm
and guardXXXXf, where XXXX are the four digits at the end of your area
tag. It is designed for male and female guards, but you could have these
be any two types of creature you wanted, of course (though they will
still use the "m" and "f" designators to distinguish their ResRefs).
c) Either by modifying the OnDeath script, or by setting the OnSpawn
script to give a user defined event on death and modifying the
OnUserDefined script accordingly, these guard templates must be set to
call GuardDied(OBJECT_SELF) upon death of the guard. Don't forget to
#include this script, or it won't compile.
d) Unless you want your guards to just stand around the guardhouse door
doing nothing, you will want to set up a set of waypoints for creatures
of their tag.
e) Somewhere, probably in the OnModuleLoad script in the module
properties, set the local variable MAXGUARDS for the area. This should
be set to whatever number of guards you desire to be patrolling this
area under normal circumstances.
f) Include this include file, and add a call to CheckGuards() to the
OnHeartbeat script for the area. CheckGuards() needs no parameters and
returns nothing, and works correctly only if called by an area object.
4. If you have performed the instructions in step 3 correctly, guards
should gradually spawn into the area and begin patrolling, until the
number of guards you set in the local variable MAXGUARDS are present. At
this point no more guards will spawn until and unless one or more dies.
If any guards die, more will spawn until MAXGUARDS is again reached.
5. The following parameters are adjustable:
Delay between spawns; also the delay following a guard's death before a
new one spawns: To change this, find the line in CheckGuards() which
sets the local int GSPDELAY, and change the number (which will be
measured in area heartbeats). Note that since guards are all spawned off
the same one or two blueprints (and thus all share the same two (at
most) Tags), if you set this too low, you will find that the guards will
patrol -very- close together (since they are walking the same set of
waypoints). This cannot currently be changed on an area-by-area basis.
To allow such is not difficult - it would simply be necessary to have an
additional LocalInt initialized per area, and to reset GSPDELAY to that
instead of a fixed constant.
Percentage of female guards: To change this, find the line in
SpawnAreaGuard() which has "if (FemaleRoll <= 33)" and change the 33 to
some other number (between 0 and 100). Note that if you set it to 0 or
100 you will need only one gender template. Also note that this changes
the gender percentage for *ALL* areas that use the script (it is not
currently possible to set a gender percentage on an area-by-area basis,
though it is relatively simple to edit the script to do this - simply
have another LocalInt initialized for each area and compare the
FemaleRoll to that instead of to the fixed number).
Number of guards per area: Is set on an area-by-area basis by changing
the local variable MAXGUARDS. As mentioned above, this variable MUST be
set in order for the script to work (otherwise, CheckGuards() will see
that there are zero out of zero guards present, and naturally will exit,
seeing that the guard count is already adequate - thus the script will
do nothing). If it is increased during gameplay, more guards will begin
to spawn to fill the deficit; however, if it is reduced, existing
surplus guards will remain until death removes them from play.
6. The script is designed for area patrol guards who do not leave the
area once spawned (unless killed). Script behavior is undefined if
guards are permitted (through waypoint placement or otherwise) to leave
the area they are spawned in.
NWScript:
int SpawnAreaGuard ( object theArea);
void CheckGuards();
void GuardDied ( object Guard);
void CheckGuards()
{
int numGuards = GetLocalInt ( OBJECT_SELF, "NUMGUARDS");
int maxGuards = GetLocalInt ( OBJECT_SELF, "MAXGUARDS");
if (numGuards >= maxGuards)
return;
int spawnDelay = GetLocalInt ( OBJECT_SELF, "GSPDELAY");
if (spawnDelay > 0)
{
spawnDelay = spawnDelay - 1;
SetLocalInt ( OBJECT_SELF, "GSPDELAY", spawnDelay);
return;
}
int spawn = SpawnAreaGuard ( OBJECT_SELF);
if (spawn == -1)
return;
numGuards = numGuards + 1;
SetLocalInt ( OBJECT_SELF, "NUMGUARDS", numGuards);
SetLocalInt ( OBJECT_SELF, "GSPDELAY", 10);
}
int SpawnAreaGuard ( object theArea)
{
string areaNumber = GetStringRight ( GetTag(theArea), 4);
string guardTemplate;
string areaTag = GetTag(theArea);
if (areaNumber == "")
return -1;
int FemaleRoll = Random(100) + 1;
if (FemaleRoll <= 33)
{
guardTemplate = "guard" + areaNumber + "f";
}
else
{
guardTemplate = "guard" + areaNumber + "m";
}
object SpawnWaypoint = GetWaypointByTag (areaTag + "_GuardSpawnPoint");
if (SpawnWaypoint == OBJECT_INVALID)
return -1;
location SpawnSpot = GetLocation (SpawnWaypoint);
CreateObject (OBJECT_TYPE_CREATURE, guardTemplate, SpawnSpot, FALSE);
return 0;
}
void GuardDied(object Guard)
{
object Area = GetArea(Guard);
int GuardMax = GetLocalInt(Area, "MAXGUARDS");
if (GuardMax == 0)
return;
int GuardCount = GetLocalInt(Area, "NUMGUARDS");
GuardCount = GuardCount - 1;
SetLocalInt(Area, "NUMGUARDS", GuardCount);
}
|
|