Author Sticky: Post Working Scripts Here
Rhone11 Posted: Friday, 19 July 06:01AM
1. Name: Hour-based Waypoint Walker

2. What it does: This is a complete rewrite of WalkWayPoints with many features, the most notable being the ability to create daily schedules for NPCs by using waypoints and posts for different hours of the day. You can assign scripts for each waypoint (they all go in the NPC's OnUserDefined script, so you don't have to make a script for every waypoint/post). You can also use circular waypoints, and terminal waypoints (i.e. NPC goes through his waypoints once and then stops at a post). It currently uses a GetFacingCorrectly function to wrap GetFacing as a workaround for the latter function's bug, so NPCs will face the right direction at posts. See the introductory comments for more details, including instructions for setting it up in your module.

3. Notes: I've also included an OnHeartbeat script which is the same as the default OnHeartbeat, with the exception that the previous waypoint-related code is changed with code for my waypoint system.

NWScript:
/*

Name:      Rhone's Hour-based WayPoint Walker

Author:    Thomas J. Hamman (Rhone)

E-Mail:    hammant@panther.adelphi.edu

Filename:  RH_INC_HRWPOINTS

Version:   1.0

This is a complete rewrite of the waypoint walking system in NW_I0_GENERIC,

using the original as a rough guide.  Here are its advantages:

1.  Hour-based waypoints--the main feature.  It allows for NPCs to easily be

    given daily schedules.  The tags for hour-based waypoints and posts

    (respectively) use this format:

        WP_XX_NPCTag_YY

        POST_XX_NPCTag

    Where XX is the hour -- 01 through 24 -- and YY is the order number for the

    waypoint.  NPCTag is, of course, the tag of the NPC who uses the waypoint.

    24-hour waypoints can still be used, with "00" in place of XX, and Day/Night

    waypoints can still be used with DY (for day) and NT (for night) in place of

    XX.  You must choose one system for each NPC, though--if Bob has the waypoint

    WP_00_Bob_01 then the script will never check for day/night or hour-based

    waypoints for Bob, since that wouldn't make sense.  Likewise, if Bob has

    POST_DY_Bob then the script will not check for hour-based waypoints for

    him.

2.  Circular waypoints--follow the waypoints as, for example, 1 2 3 4 1 2 3 4,

    instead of 1 2 3 4 3 2 1.  To use this, have any script for the NPC that

    runs HourWayPoints call it with the nCircle parameter TRUE, e.g.:

        HourWayPoints(FALSE, 1.0, TRUE);

3.  Terminal waypoints--i.e. follow the waypoints through to the end once, and

    then stop.  This is done by having waypoints and a post for the same time;

    the NPC will go through the waypoints once, ending and stopping at the post.

4.  The ability to run a script at each waypoint.  This is done by putting

    a script in the NPC's OnUserDefined event, with event numbers in this format:

        9XXYY

    XX is the hour of the waypoint (01 through 24 -- or 00 for 24-hour waypoints,

    25 for day waypoints, and 26 for night waypoints), and YY is the order

    number for the waypoint (use 00 for posts).  Here are some examples:

        91200   A noon post.

        90503   The third waypoint at 5am.

        90005   The fifth 24-hour waypoint.

        92501   The first day waypoint.

        92600   An all-night post.

    This opens up a world of possibilities, starting with very simple but fun

    things like having Bob go to POST_16_Bob, which triggers his 91600 event

    that has him sit in a chair.

    Note that only "actions" should go in the userdefined events, so they will

    properly fit into the action queue.  It is often useful to write the commands

    in a separate function and wrap it inside an ActionDoCommand().

5.  A workaround for the current bug in the GetFacing function, which allows NPC's

    to face the correct direction at their posts.  The workaround will be harmless

    when GetFacing is fixed.

Current Possible Bugs/Problems:

I spent a lot of time testing and debugging it, but I doubt this is necessarily

coded in the most efficient way possible.  My testing has been with small numbers

of NPCs, so I don't yet know whether having dozens of NPCs with hour-based

waypoints will slow things down.

There are some issues that exist with the current WalkWayPoints as well, since

they aren't related directly to WalkWayPoints.  For example, NPCs aren't as

active when there is no PC in the area.  Their ActionMoveTo commands often don't

kick in until a PC enters the area.  ActionForceMoveTo (which is used for going

to posts but not waypoints, in both the original function and in mine) alleviates

this a little bit, as it will jump the NPC to its post after a certain amount of

time.  If you wish to try this with the waypoints as well, it can be done with

a small change in HourRunCircuit.  Replace...

    ActionMoveToObject(oWP, nRun);

with...

    ActionForceMoveToObject(oWP, nRun, 1.0, 60.0);

The 60.0 is how many seconds to wait before giving up the NPC and just jumping

him to the destination.  Change it if you like, keeping in mind that time is

passing slower in areas with no PC.

There's also a friendly little bug I can take no credit for which causes NPCs

walking waypoints to sometimes head southwest after an area transition until they

bump into something, at which point they _then_ head to a waypoint/post.  One

workaround is to use an OnEnter script for your areas which checks to see if the

entering object isn't the PC, and if so, to run HourWayPoints() for the NPC to

send it in the right direction.

Now, instructions for putting this code to use:

Considering this has to replace a function in a standard include file that is

included by many default scripts (several of which call the WalkWayPoints function

which we're trying to replace), the instructions unfortunately cannot be as

simple as "just put this script in this place and you're all set."  If you're

trying this in an existing module you're working on, consider making a backup

copy first.  With that aside, here is a set of steps to follow:

1.  Save this script in the script editor with whatever name you like.  For the

    rest of these instructions I'll assume you saved it as rh_inc_hrwpoints.

2.  Open nw_i0_generic in the script editor (you'll have to click on All Resources

    for it to show up).  Yes, we must tamper with this very important include file.

    After the comments and before any of the code, put in this line:

//        #include "RH_INC_HRWPOINTS"

    (Don't include the slashes--for some reason when I try saving this the

    compiler reads the #include as if it's not commented unless I use a C++ style

    comment with it.)



3.  Still in nw_i0_generic, scroll down to the end of the DetermineCombatRounds

    function, right before the SetListeningPatterns function, and look for code

    that looks like this:

        ClearAllActions();

        SetLocalObject(OBJECT_SELF, "NW_GENERIC_LAST_ATTACK_TARGET", OBJECT_INVALID);

        WalkWayPoints();

    The line numbers where this is should be in the 750's.  Running a Find on

    "WalkWayPoints()" (without the quotes) should find it.  What you need to

    do there is change the WalkWayPoints(); line to this:

        HourWayPoints();

    Now DetermineCombatRound will use the new function to return NPCs to their

    waypoints/posts after they finish combat.

4.  Save the edited nw_i0_generic under a new name--for the rest of these

    instructions I'll assume you saved it as my_i0_generic.

5.  Now what's important is that any script which calls WalkWayPoints() needs to

    be changed so that it calls HourWayPoints() instead, and includes my_i0_generic

    instead of nw_i0_generic.  In particular you need to edit these default NPC

    scripts:

    nw_c2_default9:  This is the default OnSpawn script for NPCs.

                     Just change WalkWayPoints() (near the end) to HourWayPoints(),

                     and replace the include line for NW_I0_GENERIC with one that

                     includes MY_I0_GENERIC instead.  Put the new include line

                     before the CONINCLUDE line instead of after; for some reason,

                     the compiler gives me a "DECLARATION DOES NOT MATCH

                     PARAMETERS" error if I run HourWayPoints() with the include

                     line after the one that includes the CONINCLUDE.

                     (This applies to any script in which you include both

                     MY_I0_GENERIC and NW_O2_CONINCLUDE, by the way.)

    nw_c2_default3:  This is the default OnCombatRoundEnd script.  Just change

                     the include from NW_I0_GENERIC to MY_I0_GENERIC.

6.  Save those files.  If you are going to use the new waypoint script for just

    a few NPCs and want to use the default WalkWayPoints for the rest, then save

    those files under a new name and use those in place of the defaults for the

    appropriate NPCs.  If you want all NPCs with waypoints to use the new waypoint

    script then don't be shy about saving those files with the default names so that

    they are used automatically when you create new NPCs.  This WILL NOT hurt the

    original scripts.  The toolset's built-in scripts are kept separate from your

    own scripts, and you can easily revert to the original scripts by deleting the

    new ones of the same name.  Your "overriding" scripts also don't affect other

    modules.

7.  The OnHeartbeat script for NPCs needs some added code.  A modified OnHeartbeat

    script should be included in the Post/Archive/Whatever where you found this.

8.  Don't forget that NPCs need an End Conversation Script that calls

    HourWayPoints() to make them continue their waypoints after the PC talks to

    them.

Have fun with the script!  I hope it helps you bring the denizens of your world to

life. :) 

*/

void HourWayPoints(int nRun = FALSE, float fPause = 1.0, int nCircle = FALSE);

void HourRunCircuit(string sPrefix, int nWPStart = 1, int nReverse = FALSE, int nRun=FALSE, float fPause = 1.0, int nCircle = FALSE);

void HourGoToPost(object oPost, int nRun = FALSE);

int GetEventForWP(object oWP, int nNum);

int FindNearestWPNum(string sWPPrefix, string sPostPrefix);

string PosIntTo2DigitString(int nNum);

float GetFacingCorrectly(object oTarget);

//This should be called in place of WalkWayPoints.  There is one extra parameter

//(nCircle), which allows NPCs to walk in a circle instead of back and forth.

void HourWayPoints(int nRun = FALSE, float fPause = 1.0, int nCircle = 0)

{

    //nDontWalkWP can be set in scripts to temporarily disable waypoint walking

    //for a particular NPC.

    if (GetLocalInt(OBJECT_SELF, "nDontWalkWP"))

        return;

    string sWalker = GetTag(OBJECT_SELF);

    string sWPPrefix;

    string sPostPrefix;

    int nWPStart;

    int nDay;

    object oWP;

    object oPost;

    ClearAllActions();

    //Before we start checking the hour and day/night status, let's see if the

    //NPC uses "00" (24-hour) waypoints/post.

    sWPPrefix = "WP_00_";

    sPostPrefix = "POST_00_";

    oWP = GetObjectByTag(sWPPrefix + sWalker + "_01");

    oPost = GetObjectByTag(sPostPrefix + sWalker);

    //If the NPC has a "00" WP, find the closest and send him on his way.

    if (GetIsObjectValid(oWP)) {

        nWPStart = FindNearestWPNum(sWPPrefix, sPostPrefix);

        if (nWPStart == 0)

            HourGoToPost(oPost);

        else

            HourRunCircuit(sWPPrefix, nWPStart, FALSE, nRun, fPause, nCircle);

        return;

    }

    //If the NPC has no WP but a "00" Post, send him to it.

    if (GetIsObjectValid(oPost)) {

        HourGoToPost(oPost, nRun);

        return;

    }

    //No "00" waypoints or posts, so let's try night/day.

    if (GetIsDay() || GetIsDawn()) {

        sWPPrefix = "WP_DY_";

        sPostPrefix = "POST_DY_";

        nDay = 1;

    } else {

        sWPPrefix = "WP_NT_";

        sPostPrefix = "POST_NT_";

        nDay = 2;

    }

    oWP = GetObjectByTag(sWPPrefix + sWalker + "_01");

    oPost = GetObjectByTag(sPostPrefix + sWalker);

    //If NPC has day/night wayposts, find current one and send him on his way.

    if (GetIsObjectValid(oWP)) {

        nWPStart = FindNearestWPNum(sWPPrefix, sPostPrefix);

        if (nWPStart == 0) {

            SetLocalInt(OBJECT_SELF, "nDayPoints", nDay);

            HourGoToPost(oPost);

        } else {

            SetLocalInt(OBJECT_SELF, "nDayPoints", nDay);

            HourRunCircuit(sWPPrefix, nWPStart, FALSE, nRun, fPause, nCircle);

        }

        return;

    }

    //If the NPC has no waypoints but a day/night post, send him to it.

    if (GetIsObjectValid(oPost)) {

        SetLocalInt(OBJECT_SELF, "nDayPoints", nDay);

        HourGoToPost(oPost);

        return;

    }

    //Code for hour-based waypoints starts here.

    int nHour = GetTimeHour();

    sWPPrefix = "WP_" + PosIntTo2DigitString(nHour) + "_";

    sPostPrefix = "POST_" + PosIntTo2DigitString(nHour) + "_";

    oWP = GetObjectByTag(sWPPrefix + sWalker + "_01");

    oPost = GetObjectByTag(sPostPrefix + sWalker);

    //The important thing we're doing in the following loop is checking every hour,

    //starting with the current hour and counting backwards, until we either find

    //an hour for which the NPC has waypoints to walk (so an NPC with 8am waypoints

    //will keep walking them for every hour until the next hour he has waypoints

    //set for) or we reach nLastHourWalked (at which point we don't need to look

    //back any further).

    //

    //If the NPC is running HourWayPoints for the first time (e.g. he just spawned)

    //then nLastHourWalked isn't set yet, so we set it to an hour ahead of the

    //current time--that way, every hour can be checked for waypoints.

    //

    //nLastHourChecked is being set for use in the OnHeartbeat script.

    if (!GetLocalInt(OBJECT_SELF, "nLastHourWalked"))

        SetLocalInt(OBJECT_SELF, "nLastHourWalked", nHour + 1);

    while (nHour != GetLocalInt(OBJECT_SELF, "nLastHourWalked")) {

        if (GetIsObjectValid(oWP)) {

            nWPStart = FindNearestWPNum(sWPPrefix, sPostPrefix);

            SetLocalInt(OBJECT_SELF, "nLastHourWalked", nHour);

            SetLocalInt(OBJECT_SELF, "nLastHourChecked", GetTimeHour());

            if (nWPStart == 0)

                HourGoToPost(oPost, nRun);

            else

                HourRunCircuit(sWPPrefix, nWPStart, FALSE, nRun, fPause, nCircle);

            return;

        } else if (GetIsObjectValid(oPost)) {

            SetLocalInt(OBJECT_SELF, "nLastHourWalked", nHour);

            SetLocalInt(OBJECT_SELF, "nLastHourChecked", GetTimeHour());

            HourGoToPost(oPost, nRun);

            return;

        } else {

            nHour--;

            if (nHour == 0)

                nHour = 24;

            sWPPrefix = "WP_" + PosIntTo2DigitString(nHour) + "_";

            sPostPrefix = "POST_" + PosIntTo2DigitString(nHour) + "_";

            oWP = GetObjectByTag(sWPPrefix + sWalker + "_01");

            oPost = GetObjectByTag(sPostPrefix + sWalker);

        }

    }

    //If we reach nLastHourWalked before finding waypoints for later hours, we

    //check to make sure that there are valid waypoints/posts for that hour and

    //send the NPC to them if so.

    if (GetIsObjectValid(oWP)) {

        nWPStart = FindNearestWPNum(sWPPrefix, sPostPrefix);

        SetLocalInt(OBJECT_SELF, "nLastHourWalked", nHour);

        SetLocalInt(OBJECT_SELF, "nLastHourChecked", GetTimeHour());

        if (nWPStart == 0)

            HourGoToPost(oPost, nRun);

        else

            HourRunCircuit(sWPPrefix, nWPStart, FALSE, nRun, fPause, nCircle);

        return;

    }

    if (GetIsObjectValid(oPost)) {

        SetLocalInt(OBJECT_SELF, "nLastHourWalked", nHour);

        SetLocalInt(OBJECT_SELF, "nLastHourChecked", GetTimeHour());

        HourGoToPost(oPost, nRun);

        return;

    }

}

//This is the replacement for the original RunCircuit (it does not use a

//RunNextCircuit equivalent), which sends the NPC to his waypoints in order.

//

//It was originally designed with a while loop to loop through the waypoints,

//but I had to change it to loop by recursion instead.  Using a while loop, I

//was unable to get the UserDefined actions (triggered by the SignalEvent at

//each waypoint) to fit in their correct place in the action queue.  No matter

//what I tried, the scripted actions for every waypoint would run at the end of

//the circuit (right before the function called itself again).  So, I made the

//function call itself again for every waypoint, and viola, the userdefined

//actions take place when they should.

//

//Note that this functions allows for circular waypoint walking through a function

//parameter (filtered down from HourWayPoints), and it also allows for waypoints

//and a post to be set for the same time--what happens then is that the NPC walks

//his waypoints once and then goes to his post, where he stays.

void HourRunCircuit(string sPrefix, int nNext = 1, int nReverse=FALSE, int nRun=FALSE, float fPause = 1.0, int nCircle = FALSE)

{

    string sWalker = GetTag(OBJECT_SELF);

    object oWP = GetWaypointByTag(sPrefix + sWalker + "_" + PosIntTo2DigitString(nNext));

    object oPost = GetWaypointByTag("POST_" + GetSubString(sPrefix, 3, 3) + sWalker);

    if (GetIsObjectValid(oWP)) {

        ActionMoveToObject(oWP, nRun);

        SignalEvent(OBJECT_SELF, EventUserDefined(GetEventForWP(oWP, nNext)));

        ActionWait(fPause);

        if (!nReverse)

            nNext++;

        else

            nNext--;

    } else if (GetIsObjectValid(oPost)) {

        ActionDoCommand(HourGoToPost(oPost, nRun));

        return;

    } else {

        if (nCircle) {

            nReverse = FALSE;

            nNext = 1;

        } else {

            nReverse = !nReverse;

            if (!nReverse)

                nNext += 2;

            else

                nNext -= 2;

        }

    }

    ActionDoCommand(HourRunCircuit(sPrefix, nNext, nReverse, nRun, fPause, nCircle));

}

//Go to a Post.

void HourGoToPost(object oPost, int nRun = FALSE)

{

    ActionForceMoveToObject(oPost, nRun, 1.0, 60.0);

    float fFacing = GetFacingCorrectly(oPost);

    ActionDoCommand(SetFacing(fFacing));

    SignalEvent(OBJECT_SELF, EventUserDefined(GetEventForWP(oPost, 0)));

}



//Convert 1, 2, 3 ... 9 into 01, 02, 03 ... 09.

string PosIntTo2DigitString(int nNum)

{

    string sString;

    if (nNum > 9)

        return IntToString(nNum);

    else if (nNum < 10 && nNum >= 0)

        return ("0" + IntToString(nNum));

    else

        return "This function is not for negative numbers.";

}

//A workaround for GetFacing, which is currently broken.  This will cease to

//be necessary when/if Bioware fixes GetFacing, but it won't break anything.

float GetFacingCorrectly(object oTarget)

{

    float fFacing;

    fFacing = GetFacing(oTarget);

    if (fFacing >= 360.0)

        fFacing = 720.0 - fFacing;

    return fFacing;

}

//Find the number of the closest appropriate waypoint.  This is always used

//before calling HourRunCircuit, so that the NPC can start at the closest

//waypoint instead of the first--this is important for resuming waypoints after

//a conversation or combat.

int FindNearestWPNum(string sWPPrefix, string sPostPrefix)

{

    string sWalker = GetTag(OBJECT_SELF);

    int nWPStart = 1;

    int nNth = 1;

    object oNearest = GetNearestObject(OBJECT_TYPE_WAYPOINT, OBJECT_SELF, nNth);

    string sNearest = GetTag(oNearest);

    while (GetIsObjectValid(oNearest)) {

        if (GetStringLeft(sNearest, GetStringLength(sNearest) - 3) == (sWPPrefix + sWalker)) {

            nWPStart = StringToInt(GetStringRight(sNearest, 2));

            oNearest = OBJECT_INVALID;

        } else if (sNearest == sPostPrefix + sWalker) {

            nWPStart = 0;

            oNearest = OBJECT_INVALID;

        }

        else {

            nNth++;

            oNearest = GetNearestObject(OBJECT_TYPE_WAYPOINT, OBJECT_SELF, nNth);

            sNearest = GetTag(oNearest);

        }

    }

    return nWPStart;

}

//This is the function for putting together a number for an event to trigger in

//the NPC's OnUserDefined script.

int GetEventForWP(object oWP, int nNum)

{

    string sTime;

    string sNum;

    string sEventNum;

    int nEventNum;

    if (!nNum) {

        sNum = "00";

        sTime = GetSubString(GetTag(oWP), 5, 2);

    }

    else {

        sNum = GetStringRight(GetTag(oWP), 2);

        sTime = GetSubString(GetTag(oWP), 3, 2);

    }

    if (sTime == "DY")

        sTime = "25";

    else if (sTime == "NT")

        sTime = "26";

    sEventNum = "9" + sTime + sNum;

    nEventNum = StringToInt(sEventNum);

    return nEventNum;

}




And here is the OnHeartbeat script:


NWScript:
//::///////////////////////////////////////////////

//:: Default On Heartbeat

//:: NW_C2_DEFAULT1

//:: Copyright (c) 2001 Bioware Corp.

//:://////////////////////////////////////////////

/*

    This script will have people perform default

    animations.

*/

//:://////////////////////////////////////////////

//:: Created By: Preston Watamaniuk

//:: Created On: Nov 23, 2001

//:://////////////////////////////////////////////

//This script has been altered for use with Rhone's Hour-Based Waypoint Walker.

//Default WalkWayPoints-related code has been removed and replaced with new

//code for HourWayPoints.

//

//The new code handles rerunning HourWayPoints() at the appropriate times for

//NPCs with day/night waypoints or hour-based waypoints.

//--Rhone

#include "MY_I0_GENERIC"  //Change MY_I0_GENERIC to the appropriate name, if necessary

void main()

{

    if(GetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY))

    {

        if(TalentAdvancedBuff(40.0))

        {

            SetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY, FALSE);

            return;

        }

    }

    //If nDay has been set, and it's not equal to the current day/night status,

    //check to see if the NPC has new waypoints/posts to walk.

    if (GetLocalInt(OBJECT_SELF, "nDayPoints")) {

        int nDay;

        if (GetIsDay() || GetIsDawn())

            nDay = 1;

        else

            nDay = 2;

        if (GetLocalInt(OBJECT_SELF, "nDayPoints") != nDay)

            HourWayPoints();

    }

    //If nLastHourChecked hasn't been set for the NPC, then he's probably not

    //walking hour-based waypoints and we don't do anything else.  If it is

    //checked, and it's not equal to the current hour, we check to see if there

    //are new waypoints.  nLastHourChecked will end up being set to the current

    //hour so OnHearbeat knows not to bother checking for new waypoints again

    //until the next hour.

    int nHour = GetTimeHour();

    int nLastHourChecked = GetLocalInt(OBJECT_SELF, "nLastHourChecked");

    if (nLastHourChecked && nHour != nLastHourChecked) {

        string sWalker = GetTag(OBJECT_SELF);

        object oNewWP;

        object oNewPost;

        while (nHour != nLastHourChecked) {

            oNewWP = GetObjectByTag("WP_" + PosIntTo2DigitString(nHour) + "_" + sWalker + "_01");

            oNewPost = GetObjectByTag("POST_" + PosIntTo2DigitString(nHour) + "_" + sWalker);

            if (GetIsObjectValid(oNewWP) || GetIsObjectValid(oNewPost)) {

                nHour = GetTimeHour();

                nLastHourChecked = nHour;

            }

            else {

                nHour--;

                if (nHour == 0)

                    nHour = 24;

            }

        }

        if (GetIsObjectValid(oNewWP) || GetIsObjectValid(oNewPost))

            HourWayPoints();

        else

            SetLocalInt(OBJECT_SELF, "nLastHourChecked", GetTimeHour());

    }

    if(!GetHasEffect(EFFECT_TYPE_SLEEP))

    {

        if(!GetIsPostOrWalking())

        {

            if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))

            {

                if(!GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))

                {

                    if(!GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL) && !IsInConversation(OBJECT_SELF))

                    {

                        if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN))

                        {

                            PlayMobileAmbientAnimations();

                        }

                        else if(GetIsEncounterCreature() &&

                        !GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))

                        {

                            PlayMobileAmbientAnimations();

                        }

                        else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS) &&

                           !GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))

                        {

                            PlayImmobileAmbientAnimations();

                        }

                    }

                    else

                    {

                        DetermineSpecialBehavior();

                    }

                }

                else

                {

                    //DetermineCombatRound();

                }

            }

        }

    }

    else

    {

        if(GetSpawnInCondition(NW_FLAG_SLEEPING_AT_NIGHT))

        {

            effect eVis = EffectVisualEffect(VFX_IMP_SLEEP);

            if(d10() > 6)

            {

                ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF);

            }

        }

    }

    if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT))

    {

        SignalEvent(OBJECT_SELF, EventUserDefined(1001));

    }

}