//::///////////////////////////////////////////////
//:: Name re_rndenc
//:: FileName re_rndenc.nss
//:: Copyright (c) 2002 Raymond Miller
//:://////////////////////////////////////////////
/*
This script creates functions called RandomEncounter(),
CleanHouse(), and SetRndEncProperties() for use in the NWN
scripting language.  This script is meant to be used as an #include
and is part of the BESIE Random Encounter package by Ray Miller
*/
//:://////////////////////////////////////////////
//:: Created By: Ray Miller
//:: Created On: 7/6/2002
//:://////////////////////////////////////////////

// Encounter Type Constants
int ENCOUNTER_TYPE_AREA = 0;
int ENCOUNTER_TYPE_PARTY = 1;
int ENCOUNTER_TYPE_IND = 2;

// PRIVATE FUNCTION DECLARATIONS

// Sets properties for random encounters that are likely to seldom change
// - iDifficulty 1 to 10
// - bConsiderCR: If true takes CR of creature into consideration when
//   choosing an encounter.
// - sCreatureTable: "re_***" - where *** is a string of letter and/or numbers to indicate to the function what type
//   of creatures to spawn.  They are as follows:
//      a - animals
//      c - construct
//      d - dragon
//      e - elemental
//      g - giant
//      h - humanoid
//      i - insect
//      m - miscellaneous
//      p - planar
//      u - undead
//      b - bandit
//      0 through 9 - These are for custom encounter tables (see Custom Encounter Tables, later in this section.)
// - iLifeTime: Time in seconds before unengaged encounters decay.
// - Mph: Should equal the Minutes Per Hour setting of the Module.
// - iEncountertype:
//      ENCOUNTER_TYPE_PARTY (default) - Takes into consideration the average level of the entire party of the PC who is to
//      receive the encounter when choosing an encounter of appropriate difficulty level.
//      ENCOUNTER_TYPE_AREA - Takes into consideration the levels off all PCs and henchmen within a 20m radius of the PC
//      who is to receive the encounter.
//      ENCOUNTER_TYPE_IND - Takes into consideration only the levels of the individual PC who is to receive the encounter.
// - bLOSCheck: Dependant upon a broken scripting function.  (future use!)
// Note:  This function is best called by the OnModuleLoad or OnAreaLoad handler.
void SetRndEncProperties(int iDifficulty = 4, int bConsiderCR = TRUE, string sCreatureTable = "re_ceghimpub", int iLifeTime = 180, int iMph = 2, int iEncounterType = 1, int bLOSCheck = FALSE);


// Generates the likelihood of a random encounter.
// - fChanceOfEncounter: Odds of encounter spawning when funciton is called.  Accurate to two
//   decimal places.  .01 to 100.00 percent chance.
// - oEncounterObject: The object about which the encounter will spawn, whose levels, party
//   or area is considered when determining an appropriate creature.
// - sTemplate: When used as the sCreatureTable parameter in the SetRndEncProperties()
//   function this parameter has higher priority.  It can also be set to the tag of a
//   specific creature, or to "random" to use the default table set by SetRndEncProperties()
// - iMinNumberOfCreatures: If > 1, a random number of creatures between this and iMaxNumberOfCreatures
//   will spawn.  If set to 0, then exactly the number of creatures set by iMaxNumberOfCreatures will
//   spawn.
// - iMaxNumberOfCreatures: If this and iMinNumberOfCreatures is set to 0 then the number of Creatures
//   spawned will be determined by the CR of the creature spawned compared to the levels of the player(s).
// - iMinEncounterDistance: If set to 0, encounter distance will always be at the number set by iMaxEncounterDistance.
// - iMaxEncounterDistance: Farthest distance the encounter can be from oEncounterObject.
// - iOrientation: 0 to 360.  Counterclockwise representing the angle from facing where the encounter will spawn.
//   a value of 0 will spawn the encounter directly in front of oEncounterObject.  360 will generate a random angle.
// - iTolerance: The number of degrees by which the angle can randomly be off from iOrientation.
// - iLevelOverride: Use this to force the function to base the encounter on a character level other than that
//   determined by oEncounterObject.
// - iDifficulty: Overrides the difficulty setting determined by the SetRndEncProperties() function.
object RandomEncounter(float fChanceOfEncounter = 100.0, object oEncounterObject = OBJECT_SELF, string sTemplate = "random", int iMinNumberOfCreatures = 0, int iMaxNumberOfCreatures = 0, int iMinEncounterDistance = 1, int iMaxEncounterDistance = 15, int iOrientation = 360, int iTolerance = 0, int iLevelOverride = 0, int iDifficulty = 0);

// Used to "clean up" an area that has become littered by random encounters.
// - bDestroyPlotItems - Tells the function whether or not to destroy items with their plot flags set.  If set to TRUE,
//   plot items will be destroyed just like any other item.
// - oArea - The area to clean up.
// - iSpawnOverride - Overrides the default (set by the SetRndEncProperties() function) time to destroy random encounter
//   creatures who are not engaged by PCs.
// - iItemOverride - Overrides the default time of 30 minutes after which to destroy items dropped by PCs
//   Note: Only works if the "re_moditemdrop" script included with the BESIE Random Encounter package
//   is placed in the module OnItemUnacquire handler.
// - iBodyBagOverride - Overrides the default time of 5 minutes after which to destroy loot that was dropped by creatures
//   who were killed.
// NOTE: If there is bDestroyPlotItems is FALSE and there is a plot item or items inside a container or body bag, the container
// and all non-plot items will decay but the plot item(s) will be left.
// NOTE: A value of zero assigned to the override parameters will cause the function to use the default value for that parameter.
void CleanHouse(int bDestroyPlotItems = FALSE, object oArea = OBJECT_SELF, int iSpawnOverride = 0, int iItemOverride = 0, int iBodyBagOverride = 0);





void SetRndEncProperties(int iDifficulty = 4, int bConsiderCR = TRUE, string sCreatureTable = "re_ceghimpub", int iLifeTime = 180, int iMph = 2, int iEncounterType = 1, int bLOSCheck = FALSE)
{
// INITIALIZE SOME GLOBAL VARIABLES
    object oMod = GetModule();
    object oPC;
    if(GetIsObjectValid(oMod))
        {
        SetLocalInt(oMod, "bInitialized", TRUE);
        SetLocalInt(oMod, "bConsiderCR", bConsiderCR);
        SetLocalInt(oMod, "iMph", iMph);
        SetLocalInt(oMod, "iLifeTime", iLifeTime);
        SetLocalInt(oMod, "bLOSCheck", bLOSCheck);
        SetLocalInt(oMod, "iDifficulty", iDifficulty);
        SetLocalInt(oMod, "iEncounterType", iEncounterType);
        SetLocalString(oMod, "sCreatureTable", sCreatureTable);
        SetLocalInt(oMod, "iMinNumberOfCreatures", 0);
        SetLocalInt(oMod, "iMaxNumberOfCreatures", 0);
        }
}
#include "re_table"
object RandomEncounter(float fChanceOfEncounter = 100.0, object oEncounterObject = OBJECT_SELF, string sTemplate = "random", int iMinNumberOfCreatures = 0, int iMaxNumberOfCreatures = 0, int iMinEncounterDistance = 1, int iMaxEncounterDistance = 15, int iOrientation = 360, int iTolerance = 0, int iLevelOverride = 0, int iDifficulty = 0)
{
// IF PROPERTIES ARE NOT SET THEN SET THEM WITH DEFAULTS
    if(!GetLocalInt(GetModule(), "bInitialized"))
        {
        SetRndEncProperties();
        }

// DETERMINE IF ENCOUNTER HAPPENS
    // The following two lines allow for a chance of encounter with a precision of up to
    // two decimal places.  ie. 100.00.  An encounter can have as little as a 0.01 chance
    // of occuring.
    int iHappens = Random(10000)+1;
    int iChanceOfEncounter = FloatToInt(fChanceOfEncounter * 100);
    if(iChanceOfEncounter < iHappens)
        {
        return OBJECT_INVALID;
        }

// DECLARE AND INITIALIZE VARIABLES
    object oMod = GetModule();
    int iLifeTime = GetLocalInt(oMod, "iLifeTime");
    int bLOSCheck = GetLocalInt(oMod, "bLOSCheck");
    if(!iDifficulty) iDifficulty = GetLocalInt(oMod, "iDifficulty") * 2;
    int iEncounterType = GetLocalInt(oMod, "iEncounterType");
    int iCounter1 = 1; // Used to count the creatures when spawning them.
    int iCounter2 = 1; // Used in loop to set difficulty level.
    int iCounter3 = 1; // Used in loop to check line of sight float fEncounterDistance (future use!);
    int iCounter4;
    int iNumberOfCreatures;
    int iEncounterDistance;
    int iFacingSameWay;
    int iLevels;
    int bNumberByLevel = FALSE;
    int bNoEncounter = FALSE;
    int bComplete1 = FALSE;
    int bComplete2 = FALSE;
    int iMph;
    float fMinCR;
    float fMaxCR;
    float fEncounterDistance;
    float fNewEncounterDistance;
    float fCreatureFacing;
    float fEncounterAngle;
    float fEncounterVector;
    float fAngleOffset;
    float fLevels;
    float fDifficulty = 0.167;
    vector vEncounterVector;
    vector vVectorOffset;
    vector vCreatureVector;
    object oAmIAPC;
    object oCreature;
    object oArea;
    if(oEncounterObject == GetModule())
        {
        oAmIAPC = GetFirstPC();
        while(GetIsObjectValid(oAmIAPC))
            {
            SetLocalObject(oMod, "oEncounterObject" + IntToString(iCounter4), oAmIAPC);
            iCounter4++;
            oAmIAPC = GetNextPC();
            }
        oEncounterObject = GetLocalObject(oMod, "oEncounterObject" + IntToString(Random(iCounter4)));
        }
    else if(GetObjectType(oEncounterObject) == 0 && oEncounterObject != GetModule())
        {
        oArea = oEncounterObject;
        oAmIAPC = GetFirstObjectInArea(oArea);
        while(GetIsObjectValid(oAmIAPC))
            {
            if(GetIsPC(oAmIAPC))
                {
                SetLocalObject(oArea, "oEncounterObject" + IntToString(iCounter4), oAmIAPC);
                iCounter4++;
                }
            oAmIAPC = GetNextObjectInArea(oArea);
            }
        oEncounterObject = GetLocalObject(oArea, "oEncounterObject" + IntToString(Random(iCounter4)));
        }
    else
        {
        oArea = GetArea(oEncounterObject);
        }
    if(!GetIsPC(oEncounterObject))
        iEncounterType = ENCOUNTER_TYPE_AREA;
    location lCreatureLocation;
    vector vEncounterObjectVector = GetPosition(oEncounterObject);
    if(!GetLocalInt(GetModule(), "iMph"))
        {
        iMph = 2;
        }
    else
        {
        iMph = GetLocalInt(GetModule(), "iMph");
        }
    int iMin = 60;
    int iHr = iMin * iMph;
    int iDay = iHr * 24;
    int iMth = iDay * 28;
    int iYr = iMth * 12;
    if(iDifficulty > 10)
        {
        iDifficulty = 10;
        }
    if(iDifficulty == 0)
        {
        iDifficulty = GetGameDifficulty() * 2;
        }
    while(iCounter2 <= iDifficulty)
        {
        fDifficulty = fDifficulty * 1.5;
        iCounter2++;
        }

// FURTHER CHECKS TO DETERMINE IF ENCOUNTER HAPPENS
    oAmIAPC = GetFirstObjectInShape(SHAPE_SPHERE, 35.0, GetLocation(oEncounterObject), FALSE, OBJECT_TYPE_CREATURE);
    if(GetIsObjectValid(oAmIAPC))
        {
        while(GetIsObjectValid(oAmIAPC))
            {
            if(GetIsPC(oAmIAPC))
                {
                if(IsInConversation(oAmIAPC))
                    {
                    return OBJECT_INVALID;
                    }
                }
            oAmIAPC = GetNextObjectInShape(SHAPE_SPHERE, 25.0, GetLocation(oEncounterObject), FALSE, OBJECT_TYPE_CREATURE);
            }
        }

// ERROR CORRECTION
    if(iMaxNumberOfCreatures < iMinNumberOfCreatures)
        {
        iMaxNumberOfCreatures = iMinNumberOfCreatures;
        }
    if(iMaxEncounterDistance < iMinEncounterDistance)
        {
        iMaxEncounterDistance = iMinEncounterDistance;
        }
    if(!GetIsPC(oEncounterObject))
        {
        iEncounterType = ENCOUNTER_TYPE_AREA;
        }

// DETERMINE THE ANGLE OFFSET OF THE SPAWN
    if(iOrientation == 360)
        {
        fEncounterAngle = IntToFloat(Random(360));
        }
    else
        {
        fEncounterAngle = GetFacingFromLocation(GetLocation(oEncounterObject)) + IntToFloat(iOrientation);
        fEncounterAngle = (fEncounterAngle + (IntToFloat(iTolerance) * 0.5)) - (IntToFloat(Random(iTolerance)));
        }

// DETERMINE THE DISTANCE FROM THE SPAWNING OBJECT
    if(iMinEncounterDistance == 0)
        {
        iMinEncounterDistance = iMaxEncounterDistance;
        fEncounterDistance = IntToFloat(iMaxEncounterDistance);
        }
    else
        {
        fEncounterDistance = IntToFloat(iMinEncounterDistance + Random((iMaxEncounterDistance - iMinEncounterDistance) + 1));
        }
    iEncounterDistance = FloatToInt(fEncounterDistance);

// DETERMINE THE FACING OF THE SPAWN
    fCreatureFacing = IntToFloat(Random(360));
    iFacingSameWay = Random(2); // Note: If there is more than one creature there is a 50% chance they will all be facing the same direction

// DETERMINE TOTAL CHARACTER LEVELS TO CONSIDER WHEN CHOOSING A CREATURE
// AND/OR DETERMINING THE NUMBER OF CREATURES TO SPAWN.
    // If the variable iEncounterType is AREA, this routine
    // determines the total character levels
    // based upon the character levels of all PCs
    // in a 20 meter radius around the object that spawned
    // the encounter.
    // Later on the total character levels will be compared to
    // the challenge rating of the creature spawned, and a number
    // of creatures will be determined from that comparison.
    if(iEncounterType == ENCOUNTER_TYPE_AREA)
        {
        oAmIAPC = GetFirstObjectInShape(SHAPE_SPHERE, 20.0, GetLocation(oEncounterObject), FALSE, OBJECT_TYPE_CREATURE);
        while(GetIsObjectValid(oAmIAPC))
            {
            if(GetIsPC(oAmIAPC))
                {
                iLevels = iLevels + GetLevelByPosition(1, oAmIAPC) + GetLevelByPosition(2, oAmIAPC) + GetLevelByPosition(3, oAmIAPC);
                if(GetIsObjectValid(GetHenchman(oAmIAPC)))
                    {
                    iLevels = iLevels + GetLevelByPosition(1, GetHenchman(oAmIAPC)) + GetLevelByPosition(2, GetHenchman(oAmIAPC)) + GetLevelByPosition(3, GetHenchman(oAmIAPC));
                    }
                }
            oAmIAPC = GetNextObjectInShape(SHAPE_SPHERE, 20.0, GetLocation(oEncounterObject), FALSE, OBJECT_TYPE_CREATURE);
            }
        }
    else if(iEncounterType == ENCOUNTER_TYPE_PARTY)
        {
        iLevels = GetFactionAverageLevel(oEncounterObject);
        }
    else
        {
        // If the variable iEncounterType is set to IND, this
        // routine determines the total character levels based upon the
        // character level of the object that spawned the encounter.
        // if the object that spawned the encounter is NOT a PC then
        // the number of creatures spawned will be one.  This shouldn't
        // happen since the the encounter type sets itself to AREA if
        // the encounter object is a placeable.
        if(GetIsPC(oEncounterObject))
            {
            iLevels = GetLevelByPosition(1, oEncounterObject) + GetLevelByPosition(2, oEncounterObject) + GetLevelByPosition(3, oEncounterObject);
            }
        }
    // Modify the float representing the total levels by the difficulty level.
    if(iLevelOverride)
        {
        iLevels = iLevelOverride;
        }
    fLevels = IntToFloat(iLevels) * fDifficulty;

// CHOOSE A CREATURE TO SPAWN
    if(GetStringLowerCase(sTemplate) == "random" || GetStringLowerCase(GetStringLeft(sTemplate, 3)) == "re_")
        {
        if(GetStringLowerCase(GetStringLeft(sTemplate, 3)) == "re_")
            {
            sTemplate = GetStringRight(sTemplate, GetStringLength(sTemplate) - 3);
            }
        if(fLevels < 0.25)
            {
            fMaxCR = 0.25;
            }
        else
            {
            fMaxCR = fLevels;
            }
        fMinCR = IntToFloat(FloatToInt(fMaxCR * 0.2));
        //If there is a definative number of creatures to spawn passed to
        //the RandomEncounter function when it is called, then do not
        //allow as much play in the low end, and a little more in the
        // high end challange ratings.
        if(iMinNumberOfCreatures == 0 && iMaxNumberOfCreatures > 1)
        {
        fMinCR = IntToFloat(FloatToInt(fMaxCR * 0.4));
        fMaxCR = fMaxCR * 1.2;
        }
        if(iMinNumberOfCreatures == 0 && iMaxNumberOfCreatures == 1)
        {
        fMinCR = IntToFloat(FloatToInt(fMaxCR * 0.6));
        fMaxCR = fMinCR * 1.2;
        }
        if(GetLocalInt(oMod, "bConsiderCR") == FALSE)
            {
            fMaxCR = 9999.0;
            fMinCR = 0.0;
            }
        sTemplate = GetRndEncCreature(fMinCR, fMaxCR, sTemplate);
        }

// DETERMINE LOCATION AND SPAWN ONE CREATURE
    // NOTE: Line Of Sight checks have a bug.  Bioware says they are looking
    // into the bug.  I have spent an ungodly amount of hours trying to come
    // up with an acceptable work-around to the Line Of Sight functionality
    // of Get**ObjectInShape().  Unless somebody else can come up with a working
    // LOS check, I have no choice but to disregard LOS checks until they are
    // fixed.
    //
    // if(LOSCheck = TRUE)
    //     {
    //     <LOS code goes here>
    //     }
    //
    // note: one creature is spawned in now so its challange rating can be
    // used to determine if more are needed. (if that option is set)
        vEncounterVector = AngleToVector(fEncounterAngle);
        vVectorOffset = vEncounterVector * fEncounterDistance;
        vCreatureVector = vEncounterObjectVector + vVectorOffset;
        lCreatureLocation = Location(oArea, vCreatureVector, fCreatureFacing);
        oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lCreatureLocation, TRUE);

// DETERMINE THE NUMBER OF ADDITIONAL CREATURES TO SPAWN.
    // If the min and max number of creatures in the function call are zero
    // then get the min and max number from the local variables in the module
    // object.
    if(iMinNumberOfCreatures == 0 && iMaxNumberOfCreatures == 0)
        {
        iMinNumberOfCreatures = GetLocalInt(oMod, "iMinNumberOfCreatures");
        iMaxNumberOfCreatures = GetLocalInt(oMod, "iMaxNumberOfCreatures");
        }
    // Now that we are done with these local integers, we need to clean reset
    // them to their defaults so we don't accidentally use old numbers later.
    SetLocalInt(oMod, "iMinNumberOfCreatures", 0);
    SetLocalInt(oMod, "iMaxNumberOfCreatures", 0);
    if(iMinNumberOfCreatures == 0 && iMaxNumberOfCreatures != 0)
        {
        iNumberOfCreatures = iMaxNumberOfCreatures;
        }
    if(iMinNumberOfCreatures != 0 && iMaxNumberOfCreatures != 0)
        {
        iNumberOfCreatures = iMinNumberOfCreatures + Random((iMaxNumberOfCreatures - iMinNumberOfCreatures) + 1);
        }
    if(iMinNumberOfCreatures == 0 && iMaxNumberOfCreatures == 0)
        {
        // This is the routine that sets the number of creatures to spawn
        // based on their challenge rating and the total character levels.
        // It chooses a random number between one half (truncated) and 125
        // percent (1 for every 4) of the number of creatures ideal for the
        // difficulty level set.
        iMaxNumberOfCreatures = FloatToInt(fLevels / GetChallengeRating(oCreature));
        iMinNumberOfCreatures = FloatToInt(IntToFloat(iMaxNumberOfCreatures) * 0.75);
        iMaxNumberOfCreatures = FloatToInt(IntToFloat(iMaxNumberOfCreatures) * 1.25);
        iNumberOfCreatures = iMinNumberOfCreatures + Random((iMaxNumberOfCreatures - iMinNumberOfCreatures) + 1);
        if((iNumberOfCreatures < 1) && (iLevels > 0))
            {
            iNumberOfCreatures = 1;
            }
        }

// SPAWN THOSE SUCKERS!
    while(iCounter1 <= iNumberOfCreatures)
        {
        // Stick some labels on the creature for record keeping and reference (future use!)
        SetLocalInt(oCreature, "bRandomEncounter", TRUE);
        SetLocalObject(oCreature, "oRandomEncounterSpawner", oEncounterObject);
        SetLocalInt(oCreature, "iRandomEncounterCounter", 1);
        SetLocalInt(oCreature, "iRandomEncounterSpawnTime", (GetCalendarYear() * iYr) + (GetCalendarMonth() * iMth) + (GetCalendarDay()* iDay) + (GetTimeHour()* iHr) + (GetTimeMinute() * iMin) + GetTimeSecond());
        SetLocalInt(oCreature, "iRandomEncounterLifeTime", iLifeTime);
        if(iCounter1 < iNumberOfCreatures)
            {
            oCreature = CreateObject(OBJECT_TYPE_CREATURE, sTemplate, lCreatureLocation, TRUE);
            }
        iCounter1++;
        // Determine the facing of the next creature
        if(iFacingSameWay == FALSE)
            {
            fCreatureFacing = IntToFloat(Random(360));
            lCreatureLocation = Location(oArea, vCreatureVector, fCreatureFacing);
            }
        }
    // Stick a lable on the spawning object for record keeping and reference (future use?)
    SetLocalString(oEncounterObject, "sLastRandomEncounterSpawned", GetTag(oCreature));
    return oCreature;
}



void CleanHouse(int bDestroyPlotItems = FALSE, object oArea = OBJECT_SELF, int iSpawnOverride = 0, int iItemOverride = 0, int iBodyBagOverride = 0)
{
// IF NOT INITIALIZED THEN DO SO
    if(!GetLocalInt(GetModule(), "bInitialized"))
        {
        SetRndEncProperties();
        }
    int iMph;
    if(!GetLocalInt(GetModule(), "iMph"))
        {
        iMph = 2;
        }
    else
        {
        iMph = GetLocalInt(GetModule(), "iMph");
        }

// DECLARE AND INTIALIZE VARIABLES
    int iMin = 60;
    int iHr = iMin * iMph;
    int iDay = iHr * 24;
    int iMth = iDay * 28;
    int iYr = iMth * 12;
    int bShouldIKillHim = TRUE;
    int iLifeTime;
    int iItemLifeTime;
    int iBodyBagLifeTime;
    int iPresentTime = (GetCalendarYear() * iYr) + (GetCalendarMonth() * iMth) + (GetCalendarDay() * iDay) + (GetTimeHour() * iHr) + (GetTimeMinute() * iMin) + GetTimeSecond();
    object oObject;


// GET EACH OBJECT IN THE AREA AND TEST FOR VALIDITY
    object oAmIASpawn = GetFirstObjectInArea();
    while(GetIsObjectValid(oAmIASpawn))
        {
        // IS IT A BODY BAG?
        if(GetTag(oAmIASpawn) == "Body Bag" && !GetLocalInt(oAmIASpawn, "bDroppedItem"))
            {
            SetLocalInt(oAmIASpawn, "bDroppedItem", TRUE);
            SetLocalInt(oAmIASpawn, "iDropTime", iPresentTime);
            }
        // IS IT A DROPPED ITEM?
        if(GetLocalInt(oAmIASpawn, "bDroppedItem"))
            {
            // HAS IT BEEN AROUND TOO LONG?
            if(iItemOverride)
                {
                iItemLifeTime = iItemOverride;
                }
            else
                {
                iItemLifeTime = 1800;
                }
            if(iBodyBagOverride)
                {
                iBodyBagLifeTime = iBodyBagOverride;
                }
            else
                {
                iBodyBagLifeTime = 300;
                }
            if((iPresentTime - GetLocalInt(oAmIASpawn, "iDropTime") > iItemLifeTime && GetTag(oAmIASpawn) != "Body Bag") || (iPresentTime - GetLocalInt(oAmIASpawn, "iDropTime") > iBodyBagLifeTime && GetTag(oAmIASpawn) == "Body Bag"))// && !GetPlotFlag(oAmIASpawn))
                {
                if(GetHasInventory(oAmIASpawn))
                    {
                    oObject = GetFirstItemInInventory(oAmIASpawn);
                    while(GetIsObjectValid(oObject))
                        {
                        if(!GetPlotFlag(oObject) || bDestroyPlotItems)
                            {
                            DestroyObject(oObject, 0.0);
                            }
                        oObject = GetNextItemInInventory(oAmIASpawn);
                        }
                    }
                if(!GetPlotFlag(oAmIASpawn) || bDestroyPlotItems)
                    {
                    DestroyObject(oAmIASpawn, 0.0);
                    }
                }
            }
        // IS HE IS A RANDOM ENCOUNTER?
        if(GetLocalInt(oAmIASpawn, "bRandomEncounter"))
            {
            // HAS HE BEEN AROUND TOO LONG?
            if(iSpawnOverride)
                {
                iLifeTime = iSpawnOverride;
                }
            else
                {
                iLifeTime = GetLocalInt(oAmIASpawn, "iRandomEncounterLifeTime");
                }
            if(iPresentTime - GetLocalInt(oAmIASpawn, "iRandomEncounterSpawnTime") > iLifeTime)
                {
                // IS HE IN COMBAT?
                if(!GetIsInCombat(oAmIASpawn))
                    {
                    // GET EACH PC AND TEST IF THE CREATURE SEES HIM
                    // Note: this is because the creature might be charmed
                    // or influenced not to attack the PCs by other means.
                    object oPC = GetFirstPC();
                    if(GetIsObjectValid(oPC))
                        {
                        while(GetIsObjectValid(oPC))
                            {
                            if(GetObjectSeen(oPC, oAmIASpawn))
                                {
                                bShouldIKillHim = FALSE;
                                }
                            oPC = GetNextPC();
                            }
                        }
                    // IF THE CREATURE HAS PASSED ALL OF THESE CHECKS, DESTROY HIM.
                    if(bShouldIKillHim)
                        {
                        DestroyObject(oAmIASpawn, 0.0);
                        }
                    }
                }
            }
        oAmIASpawn = GetNextObjectInArea();
        }
}