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.
952 lines
26 KiB
Plaintext
952 lines
26 KiB
Plaintext
#include "jw_register_mobs"
|
|
|
|
// Removes blight effects from this area
|
|
void CleanUpBlight(object oArea);
|
|
// oArea should be an area which is already blighted. On a one in 5 basis (once an hour)
|
|
// 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 +
|
|
// (GetCalendarMonth()-1)*28*24 +
|
|
// (GetCalendarDay()-1)*24 +
|
|
// GetTimeHour();
|
|
int GetCurrentTime();
|
|
// Use this to set the current minute as the latest timt the area spawned mobs and placeables
|
|
void SetSpawnTime(object oArea);
|
|
// 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 = 1;
|
|
|
|
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 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_DUNGEON = 6;
|
|
const int AREA_TYPE_PERMANENT_BLIGHT = 7;
|
|
|
|
const int BLIGHT_STATUS_OFF = 0;
|
|
const int BLIGHT_STATUS_ON = 1;
|
|
|
|
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 (1)
|
|
// CHANGE THIS BACK
|
|
//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(GetSpawnSet(oArea)));
|
|
}
|
|
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);
|
|
|
|
// set the weather
|
|
if (nAreaType==AREA_TYPE_DUNGEON||nAreaType==AREA_TYPE_DESERT)
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_ICE&&nWeatherType==WEATHER_RAIN)
|
|
{
|
|
SetWeather(oArea,WEATHER_SNOW);
|
|
}
|
|
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(440)==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
|
|
SetRareSpawnStatus(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnStatusToDatabase(oArea,RARE_SPAWN_PENDING);
|
|
SaveRareSpawnTypeToDatabase(oArea,GetRareSpawn(GetSpawnSet(oArea)));
|
|
}
|
|
else if ((GetRareSpawnStatus(oArea)==RARE_SPAWN_PENDING)&&(d2()==1)) // This is half as likely as making a new one
|
|
{
|
|
// 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(440)==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);
|
|
// Do placeable spawn
|
|
}
|
|
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);
|
|
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)
|
|
{
|
|
if (nAreaType==AREA_TYPE_DUNGEON||nAreaType==AREA_TYPE_DESERT)
|
|
{
|
|
// do nothing
|
|
}
|
|
else
|
|
if (nAreaType==AREA_TYPE_ICE&&nWeatherType==WEATHER_RAIN)
|
|
{
|
|
SetWeather(oArea,WEATHER_SNOW);
|
|
}
|
|
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 nCurrentMinute = (GetCalendarYear()-1)*12*28*24 +
|
|
(GetCalendarMonth()-1)*28*24 +
|
|
(GetCalendarDay()-1)*24 +
|
|
GetTimeHour();
|
|
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 +
|
|
(GetCalendarMonth()-1)*28*24 +
|
|
(GetCalendarDay()-1)*24 +
|
|
GetTimeHour();
|
|
|
|
return nCurrentMinute;
|
|
|
|
}
|
|
|
|
void SpawnArea(object oArea)
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Starting jw_area_spawn");
|
|
|
|
// nIdx is needed here only for debug purposes
|
|
int nIdx=1;
|
|
int nSet=GetSpawnSet(oArea);
|
|
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)
|
|
{
|
|
if (GetCurrentTime() < (GetSpawnTime(oBox) + SPAWN_DELAY))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set that the box is about to spawn
|
|
SetSpawnTime(oBox);
|
|
|
|
string sResRef;
|
|
object oMob;
|
|
string sCheckstring;
|
|
string sMob="sMob";
|
|
location lLoc=GetLocation(oBox);
|
|
int nIdx=1;
|
|
int nBlightStatus=GetBlightStatus(GetArea(oBox));
|
|
|
|
// We may make a rare spawn here
|
|
if ((GetRareSpawnStatus(GetArea(oBox))==RARE_SPAWN_PENDING)&&(d2()==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)
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Starting spawnplaceable routine");
|
|
if (GetCurrentTime() < (GetSpawnTime(oBox) + SPAWN_DELAY))
|
|
{
|
|
//SendMessageToPC(GetFirstPC(),"Returning from place spawn as spawndelay hasn't been done");
|
|
return;
|
|
}
|
|
int nBlighted=GetBlightStatus(GetArea(oBox));
|
|
// Set that the box is about to spawn
|
|
SetSpawnTime(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_OFF)
|
|
{
|
|
sResRef=GetPlaceableResRefFromSet(nSet);
|
|
}
|
|
else
|
|
{
|
|
sResRef=GetPlaceableResRefFromBlightSet();
|
|
}
|
|
|
|
// 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));
|
|
}
|
|
|
|
void CleanUpArea(object oArea)
|
|
{
|
|
|
|
// 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))
|
|
{
|
|
DestroyObject(oObject);
|
|
}
|
|
|
|
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 (GetResRef(oObject)=="jw_trap_trigger")
|
|
{
|
|
SetLocalInt(oObject,"done",0);
|
|
SetLocalInt(oObject,"triggered",FALSE);
|
|
}
|
|
if (GetTag(oObject) == "jw_trap_1_plate"||GetTag(oObject) == "jw_trap_2_plate"||GetTag(oObject) == "jw_trap_3_plate"||GetTag(oObject) == "jw_trap_4_plate"||GetTag(oObject) == "jw_trap_5_plate")
|
|
{
|
|
SetPlotFlag(oObject,0);
|
|
DestroyObject(oObject);
|
|
}
|
|
|
|
|
|
|
|
if (GetResRef(oObject)=="secretitemtrigge"||GetResRef(oObject)=="secretitemtri001"||GetResRef(oObject)=="jw_secret_dr_tri")
|
|
{
|
|
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)&&(!GetIsDM(oTest))&&(!GetIsDMPossessed(oTest)))
|
|
{
|
|
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=d20();
|
|
SetLocalInt(oArea,"blightotal",nRandom+10);
|
|
}
|
|
// 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)
|
|
{
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
void CleanUpBlight(object oArea)
|
|
{
|
|
object oObject=GetFirstObjectInArea(oArea);
|
|
while (GetIsObjectValid(oObject))
|
|
{
|
|
if (GetLocalInt(oObject,"blighted")==TRUE)
|
|
{
|
|
SetPlotFlag(oObject,0);
|
|
DestroyObject(oObject);
|
|
}
|
|
oObject=GetNextObjectInArea(oArea);
|
|
}
|
|
}
|
|
|