OSSL Script Library/Persist NPC

From OpenSimulator

Jump to: navigation, search

When a simulator is restarted, any NPCs on that sim's regions will not automatically reappear. Much like dynamic textures, NPCs are a transient and non-persistant asset that is not stored in any database. So any scripts that controls an NPC will need to have a mechanism in place to detect wether an NPC is currently instantiated, and recreate it if it is not.

Implementing NPC Persistence

The llKey2Name function placed in a timer event is the tool I use to check whether an NPC is still present in-world. If this function returns an empty string, it can be assumed that the NPC is no longer rezzed, and must be recreated.

The following script is an example of the mechanism I make use of to accomplish this task. It has been kept to the bare minimum necessary to demonstrate the concept, and to manage the NPC it creates.


// NPC Persistance Example created by Marcus Llewellyn.
// This script is in the Public Domain.
 
key npc = NULL_KEY;
string firstname = "Dwight";
string lastname = "Smith";
integer dead = FALSE;
 
default
{
    state_entry() {
        // Setup and rez the NPC.
        key temp = (key)llGetObjectDesc();
        if (llKey2Name(temp) != "") {
            // An NPC matching the UUID stored in the object description
            // already exists, so just retrieve the UUID.
            npc = temp;
        } else if (dead == FALSE) {
            // Create a new instance of the NPC, record the UUID in the
            // object's description, and set starting rotation. NPC
            // rotation and location are inherited from the controlling
            // object with an offset.
            npc = osNpcCreate(firstname, lastname, llGetPos() + <1.0,0.0,0.0>, llGetOwner());
            llSetObjectDesc((string)npc);
            osNpcSetRot(npc, llGetRot() * (llEuler2Rot(<0, 0, 90> * DEG_TO_RAD)));
        }
        // Have the NPC say a greeting, and set up persistance timer and
        // listen for commands.
        osNpcSay(npc, firstname + " " + lastname + ", at your service.");
        llSetTimerEvent(10);
        llListen(0, "", NULL_KEY, "");
 
    }
 
    timer() {
        // Our NPC UUID stored in the object description should match the
        // UUID of our existing NPC. If it does not, we presume an untimely
        // demise, and initiate resurrection by simply reseting our script.
        key temp = (key)llGetObjectDesc();
        if (llKey2Name(temp) == "" && dead == FALSE) {
            llResetScript();
        }          
    }
 
    listen(integer channel, string name, key id, string msg) {
        if (llToLower(msg) == "kill") {
            // Kill the NPC, set a flag so it stays dead, and misquote
            // John Donne.
            osNpcSay(npc, "Send not to know for whom the bell tolls, it tolls for me!");
            osNpcRemove(npc);
            dead = TRUE;
        } else if (llToLower(msg) == "start" && dead == TRUE) {
            // Create a new instance of our NPC, and set flag for
            // persistance checks.
            npc = osNpcCreate(firstname, lastname, llGetPos() + <1.0,0.0,0.0>, llGetOwner());
            llSetObjectDesc((string)npc);
            osNpcSetRot(npc, llGetRot() * (llEuler2Rot(<0, 0, 90> * DEG_TO_RAD)));
            osNpcSay(npc, firstname + " " + lastname + ", at your service.");
            dead = FALSE;
        } else if (llToLower(msg) == "start" && dead == FALSE) {
            // Don't do anything significant if the NPC is still incarnate.
            osNpcSay(npc, "I'm already alive, boss.");
        }
    }
}
Personal tools
About This Wiki