generated from Jaysyn/ModuleTemplate
1117 lines
31 KiB
Plaintext
1117 lines
31 KiB
Plaintext
#include "jw_register_mobs"
|
|
|
|
// Returns TRUE if oArea has been turned off, otherwise returns false
|
|
int GetIsAreaTurnedOff(object oArea);
|
|
// Turns this area off. Set nTurnoff to FALSE to turn the area back on
|
|
void TurnOffArea(object oArea, int nTurnoff=TRUE);
|
|
// Removes blight effects from this area
|
|
void CleanUpBlight(object oArea);
|
|
// oArea should be an area which is already blighted. On a one in 60 basis (once every 12 hours)
|
|
// It will look at its neighbouring areas and spread blight to one of them randomly
|
|
// changing the databse entry if needed
|
|
void SpreadBlight(object oArea);
|
|
// Gets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
// From the database, only needs doing on module load
|
|
int GetBlightedStatusFromDatabase(object oArea);
|
|
// Saves the blight status of this area to the database, only needs, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
// Doing when the status changes
|
|
void SaveBlightedStatusToDatabase(object oArea, int nBlighted);
|
|
// Sets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
void SetBlightStatus(object oArea, int nBlight);
|
|
// Gets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
int GetBlightStatus(object oArea);
|
|
// Gets what type of area this is, eg AREA_ICE, AREA_PERMANENT_BLIGHT
|
|
int GetAreaType(object oArea);
|
|
// Sets what type of area this is, eg AREA_ICE, AREA_PERMANENT_BLIGHT
|
|
// However it is simply set using the reflex save of the area box
|
|
void SetAreaType(object oArea, int nAreaType);
|
|
// Sets oNeighbouringArea to be the neighbouring area number nCount of oArea
|
|
void SetNeighbouringArea(object oArea, int nCount, object oNeighbouringArea);
|
|
// Gets neighbouring area number nCount for oArea. Check how many neighbours oArea has with GetNeighbouringAreaNumber
|
|
object GetNeighbouringArea(object oArea, int nCount);
|
|
// Sets oArea to have nNumber of neighbouring areas
|
|
void SetNeighbouringAreaNumber(object oArea, int nNumber);
|
|
// Gives the amount of neighbouring areas next to the oArea
|
|
int GetNeighbouringAreaNumber(object oArea);
|
|
// Make the placeablebox spawn a single placeable
|
|
void SpawnPlaceable(object oBox);
|
|
// Returns TRUE if the placeable box has a placeable already, otherwise returns false
|
|
int HasPlaceableAlready(object oObject);
|
|
// Returns true of a PC is in the area, otherwise returns false
|
|
// DMs are not counted as PCs
|
|
int GetPCInArea(object oArea);
|
|
// Reset traps and hidden doors, remove mobs and remove body bags
|
|
void CleanUpArea(object oArea);
|
|
// Spawn mobs in this area
|
|
void SpawnArea(object oArea);
|
|
/// Use this to check if the spawn boxes have a mob spawned
|
|
int HasMobsAlready(object oObject);
|
|
// Make the spawnbox spawn some mobs
|
|
void SpawnMobs(object oBox);
|
|
// Gets the current time, using nCurrentMinute = GetCalendarYear()-1)*12*28*24*60 +
|
|
// (GetCalendarMonth()-1)*28*24*60 +
|
|
// (GetCalendarDay()-1)*24 *60+
|
|
// GetTimeHour()*60+GetTimeMinute();
|
|
int GetCurrentTime();
|
|
// Use this to set the latest time the area spawned mobs and placeables
|
|
// if nTime is left at 0 it will automatically set the current time, otherwise
|
|
// it will set it as nTime
|
|
void SetSpawnTime(object oArea, int nTime=0);
|
|
// Gets the last time the area spawned mobs and placeables
|
|
int GetSpawnTime(object oArea);
|
|
// Cycles through all the relevant areas and resets mobs if needed
|
|
// Areas are checked by looking for a placeable with
|
|
// the tag jw_area_marker.
|
|
// The WILL SAVE of this object is the mob set number of the area -
|
|
// ie, it determines which sets spawn in the area .
|
|
// A will save of 0 means mobs do not spawn
|
|
// Every area MUST have a unique tag
|
|
void CheckAreas();
|
|
// Returns the status of an area
|
|
// AREA_ACTIVE means a player is in there, AREA_VACATED means no players are in there
|
|
// and players recently left, which means it is time to clean it up
|
|
// and change the status to AREA_INACTIVE, and AREA_INACTIVE means there is nobody there
|
|
// and it is cleaned up
|
|
int GetAreaStatus(object oArea);
|
|
// Set the status of this area.
|
|
// AREA_ACTIVE means a player is in there, AREA_VACATED means no players are in there
|
|
// and players recently left, and AREA_INACTIVE means there is nobody there
|
|
// and it is cleaned up
|
|
void SetAreaStatus(object oArea, int nStatus);
|
|
// Goes through all the areas and checks the databse to see what they should be spawning
|
|
// if nothing has been stored in the database, randomly gets a new set for them
|
|
void InitiateAreas();
|
|
|
|
const int SPAWN_DELAY = 10;
|
|
|
|
const string SPAWN_BOX="jw_spawn_box";
|
|
const string PLACEABLES_BOX="jw_place_box";
|
|
|
|
const int AREA_ACTIVE = 1;
|
|
const int AREA_VACATED = 2;
|
|
const int AREA_INACTIVE = 3;
|
|
|
|
const int RARE_SPAWN_CHANCE = 200;
|
|
const int CHANGE_SPAWN_CHANCE = 240;
|
|
|
|
const int RARE_SPAWN_INACTIVE = 1;
|
|
const int RARE_SPAWN_PENDING = 2;
|
|
const int RARE_SPAWN_SPAWNED = 3;
|
|
|
|
const int AREA_TYPE_PLAIN = 1;
|
|
const int AREA_TYPE_FOREST = 2;
|
|
const int AREA_TYPE_DESERT = 3;
|
|
const int AREA_TYPE_BEACH = 4;
|
|
const int AREA_TYPE_ICE = 5;
|
|
const int AREA_TYPE_SWAMP = 6;
|
|
const int AREA_TYPE_PERMANENT_BLIGHT = 7;
|
|
const int AREA_TYPE_DUNGEON_LEVEL1 = 8;
|
|
const int AREA_TYPE_DUNGEON_LEVEL2 = 9;
|
|
const int AREA_TYPE_DUNGEON_LEVEL3 = 10;
|
|
const int AREA_TYPE_DUNGEON_LEVEL4 = 11;
|
|
|
|
const int BLIGHT_STATUS_OFF = 0;
|
|
const int BLIGHT_STATUS_ON = 1;
|
|
|
|
|
|
// Returns TRUE if oArea has been turned off, otherwise returns false
|
|
int GetIsAreaTurnedOff(object oArea)
|
|
{
|
|
int nTurnedoff=GetLocalInt(oArea,"turnedoff");
|
|
if (nTurnedoff==TRUE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
// Turns this area off. Set nTurnoff to FALSE to turn the area back on
|
|
void TurnOffArea(object oArea, int nTurnoff=TRUE)
|
|
{
|
|
if (nTurnoff==TRUE)
|
|
{
|
|
SetLocalInt(oArea,"turnedoff",TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetLocalInt(oArea,"turnedoff",FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
void InitiateAreas()
|
|
{
|
|
int nIdx=0;
|
|
object oArea;
|
|
int nAreaNumber;
|
|
//int nRareGroupNumber;
|
|
int nPlaceableSetNumber;
|
|
int nAreaType;
|
|
object oMarker=GetObjectByTag("jw_area_marker",nIdx);
|
|
|
|
// Instead of using the database to save weather, we just
|
|
// choose at random on module load
|
|
int nWeatherType=Random(3);
|
|
|
|
while (GetIsObjectValid(oMarker))
|
|
{
|
|
|
|
oArea=GetArea(oMarker);
|
|
nAreaType=GetReflexSavingThrow(oMarker);
|
|
|
|
// Set the area to be nAreaType
|
|
SetAreaType(oArea,nAreaType);
|
|
|
|
nAreaNumber=GetWillSavingThrow(oMarker);
|
|
nPlaceableSetNumber=GetFortitudeSavingThrow(oMarker);
|
|
|
|
// Start basic spawn routine
|
|
if (nAreaNumber!=0)
|
|
{
|
|
// Organise standard spawns
|
|
int nSet=GetSpawnSetFromDatabase(oArea);
|
|
// if nSet is 0 then this is probably a new module
|
|
if (nSet==0)
|
|
{
|
|
// Make a new spawn set
|
|
SetNewSpawnSet(oArea, nAreaNumber);
|
|
}
|
|
else
|
|
{
|
|
// Set the spawn set to be what we just got from teh databse
|
|
SetSpawnSet(oArea,nSet);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This is what we do when nAreaNumber==0
|
|
// In this case, the area does not spawn
|
|
SetSpawnSet(oArea,0);
|
|
}
|
|
|
|
// Start rare spawn routine
|
|
|
|
if (nAreaNumber!=0)
|
|
{
|
|
// Now organise rare spawns
|
|
int nRareStatus=GetRareSpawnStatusFromDatabase(oArea);
|
|
// Start new module routine
|
|
if (nRareStatus==0)
|
|
{
|
|
// This means it is probably a new module
|
|
// Choose whether to make this a rarespawn area. We only do this if nRareGroupNumber !=0
|
|
|
|
if (Random(RARE_SPAWN_CHANCE)==1)
|
|
{
|
|
// We have decided to do one
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnStatusToDatabase(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnTypeToDatabase(oArea,GetRareSpawn(nAreaNumber));
|
|
}
|
|
else
|
|
{
|
|
// We have decided not to do one
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_INACTIVE);
|
|
SaveRareSpawnStatusToDatabase(oArea,RARE_SPAWN_INACTIVE);
|
|
}
|
|
}
|
|
// ended new module routine
|
|
// Rare spawn status was not 0, so we need now just to set the status on to the area
|
|
else
|
|
{
|
|
SetRareSpawnStatus(oArea,nRareStatus);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// This is what we do if nRareGroupNumber==0
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_INACTIVE);
|
|
}
|
|
// ended rare spawn routine
|
|
|
|
// Do placeable routine
|
|
if (nPlaceableSetNumber!=0)
|
|
{
|
|
// Organise standard placeable
|
|
int nSet=GetPlaceableSetFromDatabase(oArea);
|
|
// if nSet is 0 then this is probably a new module
|
|
if (nSet==0)
|
|
{
|
|
// Make a new spawn set
|
|
SetNewPlaceableSet(oArea, nPlaceableSetNumber);
|
|
}
|
|
else
|
|
{
|
|
// Set the spawn set to be what we just got from teh databse
|
|
SetPlaceableSet(oArea,nSet);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This is what we do when nPlaceableSetNumber==0
|
|
// In this case, the area does not spawn placeables
|
|
SetPlaceableSet(oArea,0);
|
|
}
|
|
|
|
// Set the correct blight status on this area
|
|
int nBlight;
|
|
if (nAreaType==AREA_TYPE_PERMANENT_BLIGHT)
|
|
{
|
|
nBlight=BLIGHT_STATUS_ON;
|
|
}
|
|
else
|
|
{
|
|
nBlight=GetBlightedStatusFromDatabase(oArea);
|
|
}
|
|
SetBlightStatus(oArea,nBlight);
|
|
// Save fog settings it nBlight is on and change fog
|
|
if (nBlight==BLIGHT_STATUS_ON)
|
|
{
|
|
SetLocalInt(oArea,"fog_day_colour",GetFogColor(FOG_TYPE_SUN,oArea));
|
|
SetLocalInt(oArea,"fog_night_colour",GetFogColor(FOG_TYPE_MOON,oArea));
|
|
SetLocalInt(oArea,"fog_day_amount",GetFogAmount(FOG_TYPE_SUN,oArea));
|
|
SetLocalInt(oArea,"fog_night_amount",GetFogAmount(FOG_TYPE_MOON,oArea));
|
|
// Then change to new fog settings
|
|
SetFogColor(FOG_TYPE_SUN,FOG_COLOR_BROWN_DARK,oArea);
|
|
SetFogColor(FOG_TYPE_MOON,FOG_COLOR_RED_DARK,oArea);
|
|
SetFogAmount(FOG_TYPE_SUN,30,oArea);
|
|
SetFogAmount(FOG_TYPE_MOON,30,oArea);
|
|
}
|
|
|
|
// set the weather
|
|
if (nAreaType==AREA_TYPE_DUNGEON_LEVEL1||nAreaType==AREA_TYPE_DUNGEON_LEVEL2||
|
|
nAreaType==AREA_TYPE_DUNGEON_LEVEL3||nAreaType==AREA_TYPE_DUNGEON_LEVEL4||nAreaType==AREA_TYPE_DESERT)
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_ICE&&nWeatherType==WEATHER_RAIN)
|
|
{
|
|
SetWeather(oArea,WEATHER_SNOW);
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_SWAMP&&nWeatherType==WEATHER_SNOW)
|
|
{
|
|
SetWeather(oArea,WEATHER_RAIN);
|
|
}
|
|
else
|
|
if ((nAreaType==AREA_TYPE_FOREST||nAreaType==AREA_TYPE_PLAIN)&&nWeatherType==WEATHER_SNOW)
|
|
{
|
|
//SetSkyBox(SKYBOX_GRASS_CLEAR,oArea);
|
|
SetWeather(oArea,WEATHER_CLEAR);
|
|
}
|
|
else
|
|
{
|
|
SetWeather(oArea,nWeatherType);
|
|
}
|
|
|
|
// Start on next area
|
|
nIdx=nIdx+1;
|
|
oMarker=GetObjectByTag("jw_area_marker",nIdx);
|
|
}
|
|
|
|
// End of going through area boxes
|
|
|
|
// Now do the neighbouring areas stuff
|
|
string sName;
|
|
int nCount;
|
|
nIdx=0;
|
|
oMarker=GetObjectByTag("jw_neighbour_wp",nIdx);
|
|
while (GetIsObjectValid(oMarker))
|
|
{
|
|
oArea=GetArea(oMarker);
|
|
sName=GetName(oMarker);
|
|
// The name of the WP should be area_tagofnextdoorarea
|
|
// This gives us the name without area_
|
|
//sName=GetStringRight(sName,GetStringLength(sName)-5);
|
|
// if the name of the area is the same as the area it is in, just ignore it
|
|
if (GetTag(oArea)!=sName)
|
|
{
|
|
// We are looking at a different area - ok
|
|
nCount=GetNeighbouringAreaNumber(oArea);
|
|
nCount=nCount+1;
|
|
SetNeighbouringAreaNumber(oArea,nCount);
|
|
SetNeighbouringArea(oArea,nCount,GetObjectByTag(sName));
|
|
}
|
|
// Start on next area
|
|
nIdx=nIdx+1;
|
|
oMarker=GetObjectByTag("jw_neighbour_wp",nIdx);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CheckAreas()
|
|
{
|
|
int nIdx=0;
|
|
object oArea;
|
|
int nAreaNumber;
|
|
//int nRareGroupNumber;
|
|
int nPlaceableSetNumber;
|
|
object oMarker=GetObjectByTag("jw_area_marker",nIdx);
|
|
|
|
// will we change the weather?
|
|
int nChangeWeather=FALSE;
|
|
int nWeatherType;
|
|
/*
|
|
int WEATHER_CLEAR = 0;
|
|
int WEATHER_RAIN = 1;
|
|
int WEATHER_SNOW = 2;
|
|
*/
|
|
if (Random(3)==1)
|
|
{
|
|
nChangeWeather=TRUE;
|
|
nWeatherType=Random(3);
|
|
}
|
|
|
|
|
|
while (GetIsObjectValid(oMarker))
|
|
{
|
|
oArea=GetArea(oMarker);
|
|
nAreaNumber=GetWillSavingThrow(oMarker);
|
|
//nRareGroupNumber=GetReflexSavingThrow(oMarker);
|
|
nPlaceableSetNumber=GetFortitudeSavingThrow(oMarker);
|
|
// We are doing this once every 12 minutes. 5 times an hour
|
|
// We want areas to change every 3.4 days, that's around 1 in 340
|
|
// Start basic spawn routine
|
|
if (Random(CHANGE_SPAWN_CHANCE)==1 && (nAreaNumber!=0))
|
|
{
|
|
// Changes the spawn set of the area
|
|
SetNewSpawnSet(oArea, nAreaNumber);
|
|
}
|
|
// ended basic spawn routine
|
|
|
|
// Start rare spawn routine
|
|
if ((Random(RARE_SPAWN_CHANCE)==1) && (nAreaNumber!=0))
|
|
{
|
|
if (GetRareSpawnStatus(oArea)==RARE_SPAWN_INACTIVE)
|
|
{
|
|
// We have decided to do one
|
|
int nRareSpawn=GetRareSpawn(nAreaNumber);
|
|
if (nRareSpawn!=0)
|
|
{
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnStatusToDatabase(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnTypeToDatabase(oArea,nRareSpawn);
|
|
}
|
|
}
|
|
else if ((GetRareSpawnStatus(oArea)==RARE_SPAWN_PENDING))
|
|
{
|
|
// We have decided to do cancel one that was here
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_INACTIVE);
|
|
SaveRareSpawnStatusToDatabase(oArea,RARE_SPAWN_INACTIVE);
|
|
|
|
}
|
|
// if the rare spawn is spawned we just leave it
|
|
}
|
|
// end rare spawn routine
|
|
|
|
|
|
// Start basic placeable routine
|
|
if (Random(CHANGE_SPAWN_CHANCE)==1 && (nPlaceableSetNumber!=0))
|
|
{
|
|
// Changes the spawn set of the area
|
|
SetNewPlaceableSet(oArea, nPlaceableSetNumber);
|
|
}
|
|
// ended basic placeable routine
|
|
|
|
// Ok now we just need to do the clean up
|
|
|
|
if (GetAreaStatus(oArea)==AREA_ACTIVE)
|
|
{
|
|
if (GetPCInArea(oArea))
|
|
{
|
|
// If the area is active we may respawn things depending on how long it has been
|
|
// SendMessageToAllDMs("Area "+GetName(oArea)+" is active and we are doing spawn");
|
|
//SendMessageToPC(GetFirstPC(),"Area "+GetName(oArea)+" is active and we are doing spawn");
|
|
//SpawnArea(oArea);
|
|
// Make the area do USD 80 to spawn it
|
|
SignalEvent(oArea,EventUserDefined(80));
|
|
}
|
|
else
|
|
{
|
|
SetAreaStatus(oArea,AREA_VACATED);
|
|
}
|
|
}
|
|
if (GetAreaStatus(oArea)==AREA_VACATED)
|
|
{
|
|
// Make the area run our cleanup script
|
|
// Note that this will kill all mobs that are encounter mobs
|
|
// CleanUpArea(oArea);
|
|
// Have the area execute the script instead
|
|
// ExecuteScript("jw_area_cleanup",oArea);
|
|
// Signal area event so it cleans up itself
|
|
SignalEvent(oArea,EventUserDefined(70));
|
|
//SendMessageToAllDMs("Area "+GetName(oArea)+" is vacated and we are doing cleanup");
|
|
//SendMessageToPC(GetFirstPC(),"Area "+GetName(oArea)+" is vacated and we are doing cleanup");
|
|
// Set the area to inactive
|
|
SetAreaStatus(oArea,AREA_INACTIVE);
|
|
}
|
|
int nAreaType=GetAreaType(oArea);
|
|
// Now possibly change the weather
|
|
if (nChangeWeather=TRUE)
|
|
{
|
|
// set the weather
|
|
if (nAreaType==AREA_TYPE_DUNGEON_LEVEL1||nAreaType==AREA_TYPE_DUNGEON_LEVEL2||
|
|
nAreaType==AREA_TYPE_DUNGEON_LEVEL3||nAreaType==AREA_TYPE_DUNGEON_LEVEL4||nAreaType==AREA_TYPE_DESERT)
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_ICE&&nWeatherType==WEATHER_RAIN)
|
|
{
|
|
SetWeather(oArea,WEATHER_SNOW);
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_SWAMP&&nWeatherType==WEATHER_SNOW)
|
|
{
|
|
SetWeather(oArea,WEATHER_RAIN);
|
|
}
|
|
else
|
|
if ((nAreaType==AREA_TYPE_FOREST||nAreaType==AREA_TYPE_PLAIN)&&nWeatherType==WEATHER_SNOW)
|
|
{
|
|
//SetSkyBox(SKYBOX_GRASS_CLEAR,oArea);
|
|
SetWeather(oArea,WEATHER_CLEAR);
|
|
}
|
|
else
|
|
{
|
|
SetWeather(oArea,nWeatherType);
|
|
}
|
|
}
|
|
|
|
// Check if it is blighted
|
|
if (GetBlightStatus(oArea)==BLIGHT_STATUS_ON)
|
|
{
|
|
// Do this as a separate function
|
|
SpreadBlight(oArea);
|
|
}
|
|
|
|
// Start on next area
|
|
nIdx=nIdx+1;
|
|
oMarker=GetObjectByTag("jw_area_marker",nIdx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
int GetSpawnTime(object oArea)
|
|
{
|
|
int nLastSpawnMinute = GetLocalInt(oArea,"LAST_SPAWN_MINUTE");
|
|
return nLastSpawnMinute;
|
|
}
|
|
|
|
void SetSpawnTime(object oArea, int nTime=0)
|
|
{
|
|
|
|
int nCurrentMinute;
|
|
if (nTime==0)
|
|
{
|
|
nCurrentMinute = GetCurrentTime();
|
|
}
|
|
else
|
|
{
|
|
nCurrentMinute = nTime;
|
|
}
|
|
SetLocalInt(oArea,"LAST_SPAWN_MINUTE",nCurrentMinute);
|
|
}
|
|
|
|
|
|
int GetAreaStatus(object oArea)
|
|
{
|
|
int nStatus=GetLocalInt(oArea,"areastatus");
|
|
return nStatus;
|
|
}
|
|
|
|
void SetAreaStatus(object oArea, int nStatus)
|
|
{
|
|
SetLocalInt(oArea,"areastatus",nStatus);
|
|
}
|
|
|
|
int GetCurrentTime()
|
|
{
|
|
int nCurrentMinute = (GetCalendarYear()-1)*12*28*24*60 +
|
|
(GetCalendarMonth()-1)*28*24*60 +
|
|
(GetCalendarDay()-1)*24 *60+
|
|
GetTimeHour()*60+GetTimeMinute();
|
|
|
|
return nCurrentMinute;
|
|
|
|
}
|
|
|
|
void SpawnArea(object oArea)
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Starting jw_area_spawn");
|
|
int nSet=GetSpawnSet(oArea);
|
|
// If nSet==0 then NOTHING will spawn
|
|
// Areas must have area numbers (will saves) even if they do not spawn mobs
|
|
// if they are supposed to spawn placeables or indivudial mobs
|
|
if (nSet==0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If it is not long enough since our last spawn, just stop
|
|
if (GetCurrentTime() < (GetSpawnTime(oArea) + SPAWN_DELAY))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (GetIsAreaTurnedOff(oArea))
|
|
{
|
|
SendMessageToAllDMs(GetName(oArea)+" would normally spawn now but it has been turned off");
|
|
return;
|
|
}
|
|
|
|
// We are going to spawn - set our new spawn time
|
|
SetSpawnTime(oArea,GetCurrentTime());
|
|
|
|
// nIdx is needed here only for debug purposes
|
|
int nIdx=1;
|
|
|
|
object oObject = GetFirstObjectInArea(oArea);
|
|
while (GetIsObjectValid(oObject))
|
|
{
|
|
// We are looking for our spawn boxes
|
|
if (GetTag(oObject)==SPAWN_BOX)
|
|
{
|
|
// This next section is for spawning mobs
|
|
|
|
if (!HasMobsAlready(oObject))
|
|
{
|
|
// No mobs exist - therefore we make some
|
|
//SendMessageToPC(GetFirstPC(),"Doing SpawnMobs number "+IntToString(nIdx)+" because of object name "+GetName(oObject));
|
|
SpawnMobs(oObject);
|
|
}
|
|
|
|
}
|
|
|
|
// We are looking for our placeable boxes
|
|
if (GetTag(oObject)==PLACEABLES_BOX)
|
|
{
|
|
// This next section is for spawning placeables
|
|
//SendMessageToPC(GetFirstPC(),"we found a placeable box");
|
|
if (!HasPlaceableAlready(oObject))
|
|
{
|
|
// No placeable exists - therefore we make one
|
|
//SendMessageToPC(GetFirstPC(),"Doing Spawnplaceable on a box we found as it has no placeable");
|
|
SpawnPlaceable(oObject);
|
|
}
|
|
}
|
|
oObject=GetNextObjectInArea(oArea);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int HasMobsAlready(object oObject)
|
|
{
|
|
string sMob="sMob";
|
|
string sCheckstring;
|
|
int nIdx;
|
|
int nNumber;
|
|
int nMobsexist;
|
|
//nNumber is the number of mobs spawned last time;
|
|
nNumber=GetLocalInt(oObject,"nNumber");
|
|
// Start off by assuming mobs do not exist
|
|
nMobsexist=FALSE;
|
|
// if this is not the first time we have done it, check if any of our mobs are there
|
|
if (nNumber>0)
|
|
|
|
{
|
|
// start counting through the mobs
|
|
for (nIdx=1; nIdx<=nNumber; nIdx++)
|
|
{
|
|
sCheckstring=sMob+IntToString(nIdx);
|
|
|
|
// cycle through the local objects
|
|
if (GetIsObjectValid(GetLocalObject(oObject,sCheckstring)))
|
|
|
|
{
|
|
// if one is valid, set nMobsexist to 1
|
|
nMobsexist=TRUE;
|
|
}
|
|
|
|
}
|
|
}
|
|
return nMobsexist;
|
|
}
|
|
|
|
int HasPlaceableAlready(object oObject)
|
|
{
|
|
int nReturn=FALSE;
|
|
object oPlace=GetLocalObject(oObject,"placeable");
|
|
if (GetIsObjectValid(oPlace))
|
|
{
|
|
|
|
nReturn=TRUE;
|
|
|
|
}
|
|
return nReturn;
|
|
}
|
|
|
|
|
|
void SpawnMobs(object oBox)
|
|
{
|
|
|
|
|
|
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oBox);
|
|
if ((GetIsObjectValid(oPC))&&(GetDistanceBetween(oBox,oPC)<20.0))
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
string sResRef;
|
|
object oMob;
|
|
string sCheckstring;
|
|
string sMob="sMob";
|
|
location lLoc=GetLocation(oBox);
|
|
int nIdx=1;
|
|
int nBlightStatus=GetBlightStatus(GetArea(oBox));
|
|
|
|
|
|
// Check if the box has a specific spawn
|
|
if ((GetName(oBox)!="jw_spawn_box")&&(nBlightStatus==BLIGHT_STATUS_OFF))
|
|
{
|
|
// Make a specific mob
|
|
sResRef=GetName(oBox);
|
|
// create the mob
|
|
oMob=CreateObject(OBJECT_TYPE_CREATURE,sResRef,lLoc,FALSE);
|
|
// make the mob act like an encounter creature
|
|
SetLocalInt(oMob,"norw",2);
|
|
// make the mob our box's local object
|
|
sCheckstring=sMob+IntToString(1);
|
|
SetLocalObject(oBox,sCheckstring,oMob);
|
|
// Only one rare spawn
|
|
SetLocalInt(oBox,"nNumber",1);
|
|
return;
|
|
}
|
|
|
|
// We may make a rare spawn here
|
|
if ((GetRareSpawnStatus(GetArea(oBox))==RARE_SPAWN_PENDING)&&(d4()==1)&&(nBlightStatus==BLIGHT_STATUS_OFF))
|
|
{
|
|
sResRef=GetRareSpawnResRef(GetRareSpawnTypeFromDatabase(GetArea(oBox)));
|
|
// create the mob
|
|
oMob=CreateObject(OBJECT_TYPE_CREATURE,sResRef,lLoc,FALSE);
|
|
// make the mob act like an encounter creature
|
|
SetLocalInt(oMob,"norw",2);
|
|
// make the mob our box's local object
|
|
sCheckstring=sMob+IntToString(1);
|
|
SetLocalObject(oBox,sCheckstring,oMob);
|
|
// Only one rare spawn
|
|
SetLocalInt(oBox,"nNumber",1);
|
|
// Set that the mob has spawned in this area
|
|
SetRareSpawnStatus(GetArea(oBox),RARE_SPAWN_SPAWNED);
|
|
// Set the mob is a rare spawn
|
|
SetIsRareSpawn(oMob);
|
|
return;
|
|
}
|
|
|
|
// No rare mob, so move on to standard mobs
|
|
|
|
int nSet=GetSpawnSet(GetArea(oBox));
|
|
//SendMessageToPC(GetFirstPC(),"We have stablished that our current spawn set is "+IntToString(nSet));
|
|
|
|
// if nSet is 0, we return
|
|
if (nSet==0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int nGroup;
|
|
|
|
// If the area is blighted we get a blight set instead
|
|
if (nBlightStatus==BLIGHT_STATUS_OFF)
|
|
{
|
|
nGroup=GetSpawnGroupFromSet(nSet);
|
|
}
|
|
else
|
|
{
|
|
nGroup=GetBlightSpawnGroupFromSet(nSet);
|
|
}
|
|
//SendMessageToPC(GetFirstPC(),"We have chosen to spawn in group "+IntToString(nGroup));
|
|
|
|
// if nGroup is 0, we return
|
|
if (nGroup==0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetGroupDetails(nGroup, oBox);
|
|
|
|
string sMobtype=GetLocalString(oBox, "GroupResRef");
|
|
//SendMessageToPC(GetFirstPC(),"The res ref of this group is "+sMobtype);
|
|
|
|
int nMobMax=GetLocalInt(oBox, "MaxMobs");
|
|
//SendMessageToPC(GetFirstPC(),"Maximum number of mobs in this group is "+IntToString(nMobMax));
|
|
|
|
int nMobMin=GetLocalInt(oBox, "MinMobs");
|
|
//SendMessageToPC(GetFirstPC(),"Minimum number of mobs in this group is "+IntToString(nMobMin));
|
|
|
|
// Debug check
|
|
if (nMobMin>nMobMax)
|
|
{
|
|
nMobMax=nMobMin;
|
|
}
|
|
|
|
// do a custom group
|
|
if (GetStringLeft(sMobtype,5)=="group")
|
|
{ // this is the section for making groups
|
|
//SendMessageToPC(GetFirstPC(),"We have established that this group is a custom group");
|
|
int nMobnumber=0;
|
|
nIdx=1;
|
|
|
|
// We find out our group number by checking the
|
|
// three letters at the end of the group name
|
|
string sGroupname=GetStringRight(sMobtype,3);
|
|
|
|
//SendMessageToPC(GetFirstPC(),"The name of our custom group is "+sGroupname);
|
|
|
|
int nGroupNumber=StringToInt(sGroupname);
|
|
|
|
//SendMessageToPC(GetFirstPC(),"The name of our custom group in an interger is "+IntToString(nGroupNumber));
|
|
|
|
// Set our local ints
|
|
SetCustomGroup(nGroupNumber, oBox);
|
|
|
|
nMobMax=GetLocalInt(oBox,"group_number");
|
|
|
|
//SendMessageToPC(GetFirstPC(),"The total number of mobs we are making is "+IntToString(nMobMax));
|
|
|
|
|
|
for (nIdx=1; nIdx<=nMobMax; nIdx++)
|
|
{
|
|
|
|
//SendMessageToPC(GetFirstPC(),"Cycling through mobs to make - currently on "+IntToString(nIdx));
|
|
|
|
sMobtype="group_"+IntToString(nIdx);
|
|
//SendMessageToPC(GetFirstPC(),"Checking the res ref of the mob by looking at the local string "+"group_"+IntToString(nIdx));
|
|
|
|
sResRef=GetLocalString(oBox,sMobtype);
|
|
//SendMessageToPC(GetFirstPC(),"The res ref we got, and are about to make, is "+sResRef);
|
|
// create the mob
|
|
oMob=CreateObject(OBJECT_TYPE_CREATURE,sResRef,lLoc,FALSE);
|
|
if (nBlightStatus==BLIGHT_STATUS_ON)
|
|
{
|
|
// Tell this mob it is blighted
|
|
SetLocalInt(oMob,"blighted",TRUE);
|
|
}
|
|
// make the mob act like an encounter creature
|
|
SetLocalInt(oMob,"norw",2);
|
|
// make the mob our box's local object
|
|
sCheckstring=sMob+IntToString(nIdx);
|
|
SetLocalObject(oBox,sCheckstring,oMob);
|
|
|
|
//SendMessageToPC(GetFirstPC(),"That should have worked and now on to the next one");
|
|
}
|
|
|
|
SetLocalInt(oBox,"nNumber",nMobMax);
|
|
}
|
|
|
|
else // do a standard group
|
|
{
|
|
// this is the section for making individual mobs
|
|
// choose how many mobs to create
|
|
int nRandomnumber=Random((nMobMax-nMobMin)+1);
|
|
int nMobnumber=nMobMin+nRandomnumber;
|
|
|
|
//SendMessageToPC(GetFirstPC(),"We have established that this group is a standard group");
|
|
//SendMessageToPC(GetFirstPC(),"We are going to make "+IntToString(nMobnumber)+" of these");
|
|
|
|
SetLocalInt(oBox,"nNumber",nMobnumber);
|
|
|
|
|
|
|
|
// start making the mobs
|
|
for (nIdx=1; nIdx<=nMobnumber; nIdx++)
|
|
{
|
|
// create the mob
|
|
oMob=CreateObject(OBJECT_TYPE_CREATURE,sMobtype,lLoc,FALSE);
|
|
|
|
//SendMessageToPC(GetFirstPC(),"We have made mob number "+IntToString(nIdx));
|
|
|
|
if (nBlightStatus==BLIGHT_STATUS_ON)
|
|
{
|
|
// Tell this mob it is blighted
|
|
SetLocalInt(oMob,"blighted",TRUE);
|
|
}
|
|
|
|
// make the mob act like an encounter creature
|
|
SetLocalInt(oMob,"norw",2);
|
|
|
|
// make the mob our new local object
|
|
|
|
sCheckstring=sMob+IntToString(nIdx);
|
|
SetLocalObject(oBox,sCheckstring,oMob);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void SpawnPlaceable(object oBox)
|
|
{
|
|
|
|
|
|
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oBox);
|
|
if ((GetIsObjectValid(oPC))&&(GetDistanceBetween(oBox,oPC)<20.0))
|
|
{
|
|
return;//do not spawn in sight of PC
|
|
}
|
|
|
|
int nBlighted=GetBlightStatus(GetArea(oBox));
|
|
|
|
|
|
// Get our placeable set
|
|
int nSet=GetPlaceableSet(GetArea(oBox));
|
|
// if nSet is 0, we return
|
|
if (nSet==0)
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Returning from place spawn as nSet==0");
|
|
return;
|
|
}
|
|
|
|
string sResRef;
|
|
|
|
// If we have blight, just ignore all this and get a placeable from the blight set (fog)
|
|
if (nBlighted==BLIGHT_STATUS_ON)
|
|
{
|
|
sResRef=GetPlaceableResRefFromBlightSet();
|
|
}
|
|
else if (GetName(oBox)!="jw_place_box")
|
|
{
|
|
sResRef=GetName(oBox);
|
|
}
|
|
else
|
|
{
|
|
sResRef=GetPlaceableResRefFromSet(nSet);
|
|
}
|
|
|
|
// if sResRef is "", we return
|
|
if (sResRef=="")
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Returning from place spawn as sResRef=empty");
|
|
return;
|
|
}
|
|
location lLoc=GetLocation(oBox);
|
|
object oPlaceable=CreateObject(OBJECT_TYPE_PLACEABLE,sResRef,lLoc,FALSE);
|
|
// if blight is on, set anti light to it
|
|
if (nBlighted==BLIGHT_STATUS_ON)
|
|
{
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectVisualEffect(VFX_DUR_ANTI_LIGHT_10),oPlaceable);
|
|
SetLocalInt(oPlaceable,"blighted",TRUE);
|
|
}
|
|
//SendMessageToPC(GetFirstPC(),"placeable is spawning "+sResRef);
|
|
SetLocalObject(oBox,"placeable",oPlaceable);
|
|
// Although our placeable will not be hidden, we set it as hidden so the clean
|
|
// up script will destroy it
|
|
SetLocalInt(oPlaceable,"jw_hidden_int",TRUE);
|
|
// Make the placeable do its on spawn event
|
|
SignalEvent(oPlaceable,EventUserDefined(50));
|
|
// Possibly lock the placeable
|
|
if ((d3()==1)&&(GetLockLockable(oPlaceable)))
|
|
{
|
|
SetLocked(oPlaceable,TRUE);
|
|
}
|
|
}
|
|
|
|
void CleanUpArea(object oArea)
|
|
{
|
|
// Set the last spawn time to be the current time - 60
|
|
// This is to ensure the area will spawn again if someone walks in
|
|
|
|
SetSpawnTime(oArea,GetCurrentTime()-60);
|
|
// If the area currently has a rare mob spawned, put it back to pending
|
|
if (GetRareSpawnStatus(oArea)==RARE_SPAWN_SPAWNED)
|
|
{
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_PENDING);
|
|
}
|
|
|
|
object oItem;
|
|
object oObject = GetFirstObjectInArea(oArea);
|
|
while (GetIsObjectValid(oObject) == TRUE)
|
|
{
|
|
// Check if it is a custom encounter creature
|
|
if (GetLocalInt(oObject,"norw")==2||GetIsEncounterCreature(oObject))
|
|
{
|
|
//SetPlotFlag(oObject,FALSE);
|
|
DestroyObject(oObject);
|
|
}
|
|
|
|
if (GetObjectType(oObject)==OBJECT_TYPE_DOOR)
|
|
{
|
|
if(!GetLocalInt(oObject, "destroyed")) //stops destroyed doors from having the door re-appear
|
|
{
|
|
AssignCommand(oObject,ActionCloseDoor(oObject));
|
|
if (GetLockLockable(oObject))
|
|
SetLocked(oObject,TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
if (GetTag(oObject) == "BodyBag"||GetLocalInt(oObject,"jw_hidden_int")==TRUE)
|
|
{
|
|
if (GetHasInventory(oObject))
|
|
{
|
|
oItem = GetFirstItemInInventory(oObject);
|
|
while (GetIsObjectValid(oItem) == TRUE)
|
|
{
|
|
|
|
|
|
DestroyObject(oItem);
|
|
|
|
oItem=GetNextItemInInventory(oObject);
|
|
}
|
|
}
|
|
//SetPlotFlag(oObject,FALSE);
|
|
|
|
DestroyObject(oObject);
|
|
}
|
|
|
|
if (GetObjectType(oObject)==OBJECT_TYPE_TRIGGER)
|
|
{
|
|
SetLocalInt(oObject,"done",0);
|
|
SetLocalInt(oObject,"triggered",FALSE);
|
|
}
|
|
|
|
|
|
if (GetResRef(oObject)=="jw_mobstransf_tr")
|
|
{
|
|
SignalEvent(oObject,EventUserDefined(50));
|
|
}
|
|
|
|
oObject=GetNextObjectInArea(oArea);
|
|
}
|
|
|
|
}
|
|
|
|
int GetPCInArea(object oArea)
|
|
{
|
|
int nPCinArea = FALSE;
|
|
// Cycle through our PCs and see if any of them are still in the area
|
|
object oTest=GetFirstPC();
|
|
|
|
while (GetIsObjectValid(oTest))
|
|
{
|
|
if (GetArea(oTest) == oArea)
|
|
{
|
|
nPCinArea = TRUE;
|
|
return nPCinArea;
|
|
}
|
|
oTest=GetNextPC();
|
|
}
|
|
return nPCinArea;
|
|
}
|
|
|
|
|
|
void SetNeighbouringAreaNumber(object oArea, int nNumber)
|
|
{
|
|
SetLocalInt(oArea,"neighbours",nNumber);
|
|
}
|
|
|
|
int GetNeighbouringAreaNumber(object oArea)
|
|
{
|
|
return GetLocalInt(oArea,"neighbours");
|
|
}
|
|
|
|
object GetNeighbouringArea(object oArea, int nCount)
|
|
{
|
|
return GetLocalObject(oArea,"neighbour"+IntToString(nCount));
|
|
}
|
|
|
|
void SetNeighbouringArea(object oArea, int nCount, object oNeighbouringArea)
|
|
{
|
|
SetLocalObject(oArea,"neighbour"+IntToString(nCount),oNeighbouringArea);
|
|
}
|
|
|
|
// Gets what type of area this is, eg AREA_ICE, AREA_PERMANENT_BLIGHT
|
|
int GetAreaType(object oArea)
|
|
{
|
|
return GetLocalInt(oArea,"areatype");
|
|
}
|
|
// Sets what type of area this is, eg AREA_ICE, AREA_PERMANENT_BLIGHT
|
|
// However it is simply set using the reflex save of the area box
|
|
void SetAreaType(object oArea, int nAreaType)
|
|
{
|
|
SetLocalInt(oArea,"areatype",nAreaType);
|
|
}
|
|
|
|
// Sets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
void SetBlightStatus(object oArea, int nBlight)
|
|
{
|
|
SetLocalInt(oArea,"blighted",nBlight);
|
|
int nRandom=d6();
|
|
SetLocalInt(oArea,"blightotal",nRandom+2);
|
|
}
|
|
// Gets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
int GetBlightStatus(object oArea)
|
|
{
|
|
return GetLocalInt(oArea,"blighted");
|
|
}
|
|
|
|
// Gets the blight status of this area, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
// From the database, only needs doing on module load
|
|
int GetBlightedStatusFromDatabase(object oArea)
|
|
{
|
|
int nSet=GetCampaignInt("NEW_WORLD","blighted"+GetTag(oArea));
|
|
return nSet;
|
|
}
|
|
|
|
// Saves the blight status of this area to the database, only needs, BLIGHT_STATUS_ON or BLIGHT_STATUS_OFF
|
|
// Doing when the status changes
|
|
void SaveBlightedStatusToDatabase(object oArea, int nBlighted)
|
|
{
|
|
SetCampaignInt("NEW_WORLD","blighted"+GetTag(oArea),nBlighted);
|
|
}
|
|
|
|
void SpreadBlight(object oArea)
|
|
{
|
|
// only one in 60 chance of spreading blight
|
|
if (Random(60)!=1)
|
|
{
|
|
return;
|
|
}
|
|
int nNumberNeighbours=GetNeighbouringAreaNumber(oArea);
|
|
int nRandom=Random(nNumberNeighbours)+1;
|
|
object oNeighbour=GetNeighbouringArea(oArea,nRandom);
|
|
if (GetBlightStatus(oNeighbour)!=BLIGHT_STATUS_ON)
|
|
{
|
|
SetBlightStatus(oNeighbour,BLIGHT_STATUS_ON);
|
|
SaveBlightedStatusToDatabase(oNeighbour,BLIGHT_STATUS_ON);
|
|
SetLocalInt(oNeighbour,"fog_day_colour",GetFogColor(FOG_TYPE_SUN,oNeighbour));
|
|
SetLocalInt(oNeighbour,"fog_night_colour",GetFogColor(FOG_TYPE_MOON,oNeighbour));
|
|
SetLocalInt(oNeighbour,"fog_day_amount",GetFogAmount(FOG_TYPE_SUN,oNeighbour));
|
|
SetLocalInt(oNeighbour,"fog_night_amount",GetFogAmount(FOG_TYPE_MOON,oNeighbour));
|
|
// Then change to new fog settings
|
|
SetFogColor(FOG_TYPE_SUN,FOG_COLOR_BROWN_DARK,oNeighbour);
|
|
SetFogColor(FOG_TYPE_MOON,FOG_COLOR_RED_DARK,oNeighbour);
|
|
SetFogAmount(FOG_TYPE_SUN,30,oNeighbour);
|
|
SetFogAmount(FOG_TYPE_MOON,30,oNeighbour);
|
|
}
|
|
|
|
}
|
|
|
|
void CleanUpBlight(object oArea)
|
|
{
|
|
object oObject=GetFirstObjectInArea(oArea);
|
|
while (GetIsObjectValid(oObject))
|
|
{
|
|
if (GetLocalInt(oObject,"blighted")==TRUE)
|
|
{
|
|
//SetPlotFlag(oObject,0);
|
|
DestroyObject(oObject);
|
|
}
|
|
oObject=GetNextObjectInArea(oArea);
|
|
}
|
|
// Reset fog levels to what they should be
|
|
SetFogColor(FOG_TYPE_SUN,GetLocalInt(oArea,"fog_day_colour"),oArea);
|
|
SetFogColor(FOG_TYPE_MOON,GetLocalInt(oArea,"fog_night_colour"),oArea);
|
|
SetFogAmount(FOG_TYPE_SUN,GetLocalInt(oArea,"fog_day_amount"),oArea);
|
|
SetFogAmount(FOG_TYPE_MOON,GetLocalInt(oArea,"fog_night_amount"),oArea);
|
|
}
|
|
|