The NPC general1 script makes NPCs enter and exit their homes, lock their doors, close their doors, and sit somewhere inside their home. They might even talk to other NPCs.

Script Notes[edit | edit source]

  • This script is very easy to use. Simply assign it to the USER_DEFINED script of the NPC, place the NPC in front of the door to his house, and put a waypoint next to the NPC. The waypoint does not need a specific name or tag.
  • The NPC must start outside: don't assign this script to an NPC who already is inside his house.
  • The script will find the closest door and the closest waypoint to the NPC; inside, it will find the transition destination of the door.
  • The NPC locks the outer door, so a PC will not get trapped inside

The Script[edit | edit source]

// This script makes an NPC enter and exit his own house.
// Just assign this script to the USER DEFINED script of the NPC.
// Place the NPC in front of his own house and put a
// waypoint very close to the NPC. Give the waypoint an unique name.
// It does not realy matter what name.
// Features:
// - The NPC will enter his house between 20:00 and 8:00.
// - The NPC will exit his house between 8:30 and 19:30.
// - The NPC will close the door if someone left it open for about 15 seconds.
// - The NPC will lock his door after 22:00.
// - Inside the NPC will go sit somewhere.
// - NPC interacts with other NPCs
// Remarks:
// - The NPC MUST start outside of his house not inside.
// - the game time MUST be 1 hour per 2 minutes (default).
void main()
{
    int nUser = GetUserDefinedEventNumber();
    if(nUser == 1001) //HEARTBEAT
    {
        // skip this entire part if in combat or in conversation
        if ((!GetIsInCombat()) && (!IsInConversation(OBJECT_SELF)))
        {
            // get the outdoor area tag
            string sOutsideTag = GetLocalString(OBJECT_SELF,"OutsideAreaTag");
            if (sOutsideTag == "")
            {
                // first time here, assume the NPC started outside
                sOutsideTag = GetTag(GetArea(OBJECT_SELF));
                SetLocalString(OBJECT_SELF,"OutsideAreaTag",sOutsideTag);
            }
            // get the time (asuming that 2 minutes is 1 hour)
            // this is a bit strange, the functions GetTimeMinute and
            // GetTimeSecond return real values instead of game values.
            int TheTime = GetTimeHour()*60;
            TheTime = TheTime + (GetTimeMinute()*30); // returns real minute instead of game minute
            TheTime = TheTime + (GetTimeSecond()/2); // returns real second instead of game second
            // check if the NPC is inside or outside
            if (sOutsideTag == GetTag(GetArea(OBJECT_SELF)))
            {
                // the NPC is outside
                // get the outside waypoint
                string sOutsideWPTag = GetLocalString(OBJECT_SELF,"OutsideWPTag");
                if (sOutsideWPTag == "")
                {
                    // first time here, find the nearest waypoint
                    sOutsideWPTag = GetTag(GetNearestObject(OBJECT_TYPE_WAYPOINT));
                    SetLocalString(OBJECT_SELF,"OutsideWPTag",sOutsideWPTag);
                }
                // get the outside door
                string sOutsideDoorTag = GetLocalString(OBJECT_SELF,"OutsideDoorTag");
                if (sOutsideDoorTag == "")
                {
                    // first time here, find the nearest door
                    object oOutsideDoor = GetNearestObject(OBJECT_TYPE_DOOR);
                    sOutsideDoorTag = GetTag(oOutsideDoor);
                    SetLocalString(OBJECT_SELF,"OutsideDoorTag",sOutsideDoorTag);
                    // find the inside door
                    string sTargetDoor = GetTag(GetTransitionTarget(oOutsideDoor));
                    SetLocalString(OBJECT_SELF,"InsideDoorTag",sTargetDoor);
                }
                // time to go inside?
                // go inside somewhere between 20:00 and 8:00
                if ((TheTime > 1200+Random(29)) || (TheTime <480+Random(29)))
                {
                    if (GetCurrentAction() == ACTION_INVALID)
                    {
                        object oOutsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"OutsideDoorTag"));
                        object oInsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"InsideDoorTag"));
                        string sGoInside;
                        int nRnd = Random(4);
                        if (nRnd==0) sGoInside = "It's getting late.";
                        if (nRnd==1) sGoInside = "I'm going inside.";
                        if (nRnd==2) sGoInside = "Time to go inside.";
                        if (nRnd==3) sGoInside = "I have to go inside now.";
                        AssignCommand(OBJECT_SELF,ClearAllActions());
                        AssignCommand(OBJECT_SELF,ActionSpeakString(sGoInside));
                        AssignCommand(OBJECT_SELF,ActionOpenDoor(oOutsideDoor));
                        AssignCommand(OBJECT_SELF,ActionCloseDoor(oInsideDoor));
                        SetLocalInt(OBJECT_SELF,"TryToGetInside",0);
                    } else
                    {
                        // sometimes the NPC keeps himself a little to bussy.
                        int nTry = GetLocalInt(OBJECT_SELF,"TryToGetInside");
                        nTry = nTry + 1;
                        SetLocalInt(OBJECT_SELF,"TryToGetInside",nTry);
                        if (nTry>4)
                            AssignCommand(OBJECT_SELF,ClearAllActions());
                    }
                } else
                {
                    // walk random or return to the waypoint
                    // must be a waypoint, if you let someone walk to a door, he will open it.
                    object oOutsideWP = GetObjectByTag(GetLocalString(OBJECT_SELF,"OutsideWPTag"));
                    if (GetDistanceBetween(oOutsideWP,OBJECT_SELF)>10.0)
                    {
                        // dont walk to far
                        AssignCommand(OBJECT_SELF,ClearAllActions());
                        AssignCommand(OBJECT_SELF,ActionMoveToObject(oOutsideWP));
                    } else
                    {
                        // do something random or clear the action que
                        int nRnd = Random(4);
                        if (nRnd==0)
                            AssignCommand(OBJECT_SELF,ClearAllActions());
                        if (nRnd==1)
                            AssignCommand(OBJECT_SELF,ActionRandomWalk());
                        if (nRnd==2)
                        {
                            AssignCommand(OBJECT_SELF,ClearAllActions());
                            AssignCommand(OBJECT_SELF,ActionMoveToObject(oOutsideWP));
                        }
                        if (nRnd==3)
                        {
                            // interact with other NPCs
                            object oNearest = GetNearestObject(OBJECT_TYPE_CREATURE);
                            if ((!GetIsPC(oNearest)) && (GetDistanceBetween(oNearest,OBJECT_SELF)<5.0))
                            {
                                AssignCommand(OBJECT_SELF,ClearAllActions());
                                if (GetLocalInt(OBJECT_SELF,"Know"+GetTag(oNearest))==1)
                                {
                                    AssignCommand(OBJECT_SELF,ActionSpeakString("Hello "+GetName(oNearest)+"."));
                                } else
                                {
                                    AssignCommand(OBJECT_SELF,ActionSpeakString("Hi, I am "+GetName(OBJECT_SELF)+". Who are you?"));
                                    if (!GetIsPC(oNearest))
                                    {
                                        SetLocalInt(OBJECT_SELF,"Know"+GetTag(oNearest),1);
                                        SetLocalInt(oNearest,"Know"+GetTag(OBJECT_SELF),1);
                                        AssignCommand(oNearest,ClearAllActions());
                                        AssignCommand(oNearest,ActionSpeakString("My name is "+GetName(oNearest)+"."));
                                    }
                                }
                            }
                        }
                    }
                }
            } else
            {
                // the NPC is inside
                // time to go outside?
                // go outside between 8:30 and 19:30
                if ((TheTime > 510+Random(29)) && (TheTime <1170+Random(29)))
                {
                    if ((GetCurrentAction() == ACTION_INVALID) ||
                        (GetCurrentAction() == ACTION_SIT))
                    {
                        object oOutsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"OutsideDoorTag"));
                        object oInsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"InsideDoorTag"));
                        string sGoOutside;
                        int nRnd = Random(4);
                        if (nRnd==0) sGoOutside = "I'm going to check the weather.";
                        if (nRnd==1) sGoOutside = "I'm going outside.";
                        if (nRnd==2) sGoOutside = "Time to go outside.";
                        if (nRnd==3) sGoOutside = "I want to go outside now.";
                        SetLocked(oOutsideDoor,FALSE);
                        AssignCommand(OBJECT_SELF,ClearAllActions());
                        AssignCommand(OBJECT_SELF,ActionSpeakString(sGoOutside));
                        AssignCommand(OBJECT_SELF,ActionOpenDoor(oInsideDoor));
                        AssignCommand(OBJECT_SELF,ActionCloseDoor(oOutsideDoor));
                        SetLocalInt(OBJECT_SELF,"TryToGetOutside",0);
                    } else
                    {
                        // sometimes the NPC keeps himself a little to bussy.
                        int nTry = GetLocalInt(OBJECT_SELF,"TryToGetOutside");
                        nTry = nTry + 1;
                        SetLocalInt(OBJECT_SELF,"TryToGetOutside",nTry);
                        if (nTry>4)
                            AssignCommand(OBJECT_SELF,ClearAllActions());
                    }
                } else
                {
                    // close the door if someone left it open
                    object oInsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"InsideDoorTag"));
                    if (GetIsOpen(oInsideDoor))
                    {
                        // check how long it is open
                        int nCloseTime = GetLocalInt(OBJECT_SELF,"CloseDoorTime");
                        if (nCloseTime == 0)
                        {
                            nCloseTime = TheTime;
                            SetLocalInt(OBJECT_SELF,"CloseDoorTime",nCloseTime);
                        }
                        if ((TheTime<nCloseTime) || (TheTime>nCloseTime+5))
                        {
                            if ((GetCurrentAction() == ACTION_INVALID) ||
                                (GetCurrentAction() == ACTION_SIT))
                            {
                                string sCloseDoor;
                                int nRnd = Random(4);
                                if (nRnd == 0) sCloseDoor = "I'd better close the door.";
                                if (nRnd == 1) sCloseDoor = "Who left the door open?";
                                if (nRnd == 2) sCloseDoor = "It's getting cold.";
                                if (nRnd == 3) sCloseDoor = "Why is that door open again?";
                                AssignCommand(OBJECT_SELF,ClearAllActions());
                                AssignCommand(OBJECT_SELF,ActionSpeakString(sCloseDoor));
                                AssignCommand(OBJECT_SELF,ActionCloseDoor(oInsideDoor));
                                SetLocalInt(OBJECT_SELF,"CloseDoorTime",0);
                            }
                        }
                    } else
                    {
                        // go sit somewhere
                        if (GetCurrentAction() == ACTION_INVALID)
                        {
                            int nNth = 1;
                            object oChair;
                            oChair = GetNearestObject(OBJECT_TYPE_PLACEABLE,OBJECT_SELF,nNth);
                            while ((oChair != OBJECT_INVALID) && (nNth != 0))
                            {
                                // Chairs are bugged.
                                // An NPC sitting in a chair only executes his script
                                // if a PC is in the same area. Bench and Stool work ok.
                                //if ((GetTag(oChair) == "Chair") ||
                                if ((GetTag(oChair) == "Stool") ||
                                    (GetTag(oChair) == "Couch") ||
                                    (GetTag(oChair) == "Bench"))
                                {
                                    AssignCommand(OBJECT_SELF,ClearAllActions());
                                    AssignCommand(OBJECT_SELF,ActionSit(oChair));
                                    nNth = 0;
                                }
                                if (nNth != 0)
                                {
                                    nNth = nNth + 1;
                                    oChair = GetNearestObject(OBJECT_TYPE_PLACEABLE,OBJECT_SELF,nNth);
                                }
                            } // end go sit somewhere
                        }
                        // lock the door if its later than 22:00
                        object oOutsideDoor = GetObjectByTag(GetLocalString(OBJECT_SELF,"OutsideDoorTag"));
                        if ((!GetLocked(oOutsideDoor)) && (TheTime>=1320))
                        {
                            // close the inside door, lock the outside door
                            AssignCommand(OBJECT_SELF,ClearAllActions());
                            AssignCommand(OBJECT_SELF,ActionSpeakString("I'm going to lock the door now."));
                            AssignCommand(OBJECT_SELF,ActionCloseDoor(oInsideDoor));
                            SetLocked(oOutsideDoor,TRUE);
                        } // end lock door
                    }
                }
            } // end inside
        } // end check for combat and conversation
    } // end heartbeat
}
Community content is available under CC-BY-SA unless otherwise noted.