OSSL Script Library/Persist NPC
From OpenSimulator
(Rearranged to work better as a page for a single script.) |
m (User:Marcus Llewellyn/NPC Scripts moved to OSSL Script Library/Persist NPC: Moved on request of Fritigern to the OSSL Script Library.) |
Revision as of 21:27, 15 October 2011
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."); } } }