diff --git a/Chris.MultiNPC.lsl b/Chris.MultiNPC.lsl index 7f28ff2..6ed244d 100644 --- a/Chris.MultiNPC.lsl +++ b/Chris.MultiNPC.lsl @@ -16,68 +16,213 @@ yoptions; list m_npcdata = []; integer m_lastTimeCheck = 0; -default +readNPCPathNC(string ncName) { - state_entry() - { - removeOldNPC(); - - m_lastTimeCheck = llGetUnixTime(); - checkOSPermissions(); - readAllNPCPathNC(); + string nc = osStringReplace(osGetNotecard(ncName), "\n", ""); + integer npcslot = getNextFreeNPCSlot(); - state waitingForPlayers; + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot, NULL_KEY); + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot + ".path", nc); + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot + ".ncname", ncName); +} + +integer getNextFreeNPCSlot() +{ + integer currentNPCSlot = 0; + + for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) + { + if(!checkDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot)) + return currentNPCSlot; + } + + return 0; +} + +readAllNPCPathNC() +{ + list fullInventoryItemList = osGetInventoryList(); + integer fullInventoryItemListCount = llGetListLength(fullInventoryItemList); + + while(fullInventoryItemListCount--) + { + string itemElementName = llList2String(fullInventoryItemList, fullInventoryItemListCount); + + if(osStringEndsWith(llToLower(itemElementName), ".path", 1)) + readNPCPathNC(itemElementName); } } -state waitingForPlayers +createNPCTempStorage() { - state_entry() + list npcKeys = []; + + integer currentNPCSlot = 0; + for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) { - llSetTimerEvent(0.1); + key currentNPCKey = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot); + npcKeys += [currentNPCKey]; } - timer() - { - llSetTimerEvent(2); - m_lastTimeCheck = llGetUnixTime(); - if(getRealAgentCount() != 0) - state running; - } + osSetPrivateDataValue("tmpNPCList." + llGetKey(), llList2CSV(npcKeys)); } -state running +removeOldNPC() { - state_entry() - { - llSetTimerEvent(0.3); - } + list npcdata = llCSV2List(osGetPrivateDataValue("tmpNPCList." + llGetKey())); + integer count = llGetListLength(npcdata); - timer() - { - if((m_lastTimeCheck + 2) <= llGetUnixTime()) - hardReset("script timeout"); + while(count--)osNpcRemove(llList2Key(npcdata, count)); +} - m_lastTimeCheck = llGetUnixTime(); - - if(getRealAgentCount() == 0) - hardReset("region empty"); - - doNextScriptStep(); - } - - changed(integer change) - { - if (change & CHANGED_INVENTORY) - hardReset(""); - - if (change & CHANGED_REGION_START) - hardReset(""); - } +hardReset(string message) +{ + if(message != "") + llSay(0, "Hard reset: " + message); - on_rez(integer start_param) + llSetTimerEvent(0); + integer dataListCount = llGetListLength(m_npcdata); + while(dataListCount--) + if(checkDataEntryInDataList(m_npcdata, "npc." + dataListCount)) + osNpcRemove((key)getDataEntryFromDataList(m_npcdata, "npc." + dataListCount)); + + llResetScript(); +} + +//Script Engine +doNextScriptStep() +{ + integer currentNPCSlot = 0; + + for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) { - hardReset(""); + if(!checkDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot)) + continue; + + key currentNPCKey = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot); + integer currentLine = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".line"); + string currentPath = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".path"); + string currentState = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".state"); + string currentncname = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".ncname"); + + list pathLineData = llParseString2List(currentPath, [";"], []); + string currentCommand = llList2String(pathLineData, currentLine); + list lineCommandData = llParseString2List(currentCommand, ["=", "|"], []); + + list currentNPCDataList = llGetObjectDetails(currentNPCKey, [OBJECT_POS]); + + vector currentNPCPosition = llList2Vector(currentNPCDataList, 0); + + if(currentState == "wait") + { + integer waitTime = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".waittime"); + + if(llGetUnixTime() < waitTime) + continue; + + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".state", ""); + } + + if(currentState == "walk") + { + vector targetPosition = (vector)getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".targetPosition"); + + if(llGetListLength(currentNPCDataList) == 0) + hardReset("NPC not found"); + + if(llVecDist(currentNPCPosition, targetPosition) >= 1) + continue; + + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".state", ""); + } + + currentLine = currentLine + 1; + if(currentLine >= llGetListLength(pathLineData)) + { + currentLine = 0; + } + + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".line", currentLine); + + if(llGetSubString(llList2String(lineCommandData, 0), 0, 0) == "%") + { + string storageKey = llMD5String(llList2String(lineCommandData, 0), 0); + string data = lineCommandData; + + m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".data." + storageKey, data); + continue; + } + + switch(llList2String(lineCommandData, 0)) + { + case "create": + if(!script_create(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "remove": + if(!script_remove(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "say": + if(!script_say(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "sit": + if(!script_sit(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "wait": + if(!script_wait(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "stand": + if(!script_stand(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "walk": + if(!script_walk(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "fly": + if(!script_fly(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "include": + if(!script_include(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "touch": + if(!script_touch(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + currentNPCSlot--; + break; + case "goto": + if(script_goto(currentNPCSlot, currentNPCKey, lineCommandData)) + currentNPCSlot--; + break; + case "appearance": + if(script_appearance(currentNPCSlot, currentNPCKey, lineCommandData)) + currentNPCSlot--; + break; + case "animation": + if(!script_animation(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "stopAnimation": + if(!script_StopAnimation(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "profileImage": + if(!script_profileImage(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + case "profileText": + if(!script_profileText(currentNPCSlot, currentNPCKey, lineCommandData)) + llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + break; + default: + llSay(0, "Unknown command '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); + } } } @@ -290,230 +435,6 @@ integer script_include(integer slot, key npc, list command) return TRUE; } -//Internal functions -doNextScriptStep() -{ - integer currentNPCSlot = 0; - - for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) - { - if(!checkDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot)) - continue; - - key currentNPCKey = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot); - integer currentLine = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".line"); - string currentPath = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".path"); - string currentState = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".state"); - string currentncname = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".ncname"); - - list pathLineData = llParseString2List(currentPath, [";"], []); - string currentCommand = llList2String(pathLineData, currentLine); - list lineCommandData = llParseString2List(currentCommand, ["=", "|"], []); - - list currentNPCDataList = llGetObjectDetails(currentNPCKey, [OBJECT_POS]); - - vector currentNPCPosition = llList2Vector(currentNPCDataList, 0); - - if(currentState == "wait") - { - integer waitTime = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".waittime"); - - if(llGetUnixTime() < waitTime) - continue; - - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".state", ""); - } - - if(currentState == "walk") - { - vector targetPosition = (vector)getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot + ".targetPosition"); - - if(llGetListLength(currentNPCDataList) == 0) - hardReset("NPC not found"); - - if(llVecDist(currentNPCPosition, targetPosition) >= 1) - continue; - - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".state", ""); - } - - currentLine = currentLine + 1; - if(currentLine >= llGetListLength(pathLineData)) - { - currentLine = 0; - } - - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".line", currentLine); - - if(llGetSubString(llList2String(lineCommandData, 0), 0, 0) == "%") - { - string storageKey = llMD5String(llList2String(lineCommandData, 0), 0); - string data = lineCommandData; - - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot + ".data." + storageKey, data); - continue; - } - - switch(llList2String(lineCommandData, 0)) - { - case "create": - if(!script_create(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "remove": - if(!script_remove(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "say": - if(!script_say(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "sit": - if(!script_sit(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "wait": - if(!script_wait(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "stand": - if(!script_stand(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "walk": - if(!script_walk(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "fly": - if(!script_fly(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "include": - if(!script_include(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "touch": - if(!script_touch(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - currentNPCSlot--; - break; - case "goto": - if(script_goto(currentNPCSlot, currentNPCKey, lineCommandData)) - currentNPCSlot--; - break; - case "appearance": - if(script_appearance(currentNPCSlot, currentNPCKey, lineCommandData)) - currentNPCSlot--; - break; - case "animation": - if(!script_animation(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "stopAnimation": - if(!script_StopAnimation(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "profileImage": - if(!script_profileImage(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - case "profileText": - if(!script_profileText(currentNPCSlot, currentNPCKey, lineCommandData)) - llSay(0, "Script execution in '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - break; - default: - llSay(0, "Unknown command '" + llList2String(lineCommandData, 0) + "' in nc '"+ currentncname +"' on line '" + currentLine + "' failed."); - } - } -} - -readNPCPathNC(string ncName) -{ - string nc = osStringReplace(osGetNotecard(ncName), "\n", ""); - integer npcslot = getNextFreeNPCSlot(); - - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot, NULL_KEY); - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot + ".path", nc); - m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + npcslot + ".ncname", ncName); -} - -integer getNextFreeNPCSlot() -{ - integer currentNPCSlot = 0; - - for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) - { - if(!checkDataEntryInDataList(m_npcdata, "npc." + currentNPCSlot)) - return currentNPCSlot; - } - - return 0; -} - -readAllNPCPathNC() -{ - list fullInventoryItemList = osGetInventoryList(); - integer fullInventoryItemListCount = llGetListLength(fullInventoryItemList); - - while(fullInventoryItemListCount--) - { - string itemElementName = llList2String(fullInventoryItemList, fullInventoryItemListCount); - - if(osStringEndsWith(llToLower(itemElementName), ".path", 1)) - readNPCPathNC(itemElementName); - } -} - -checkOSPermissions() -{ - key tempnpc = NULL_KEY; - try{ tempnpc = osNpcCreate("Testi", "Test", llGetPos(), llGetOwner()); }catch(exception ex) { llOwnerSay("You need to enable osNpcCreate in your ossl configuration."); } - try{ osNpcRemove(tempnpc); }catch(exception ex) { llOwnerSay("You need to enable osNpcRemove in your ossl configuration."); } - - try{ osMakeNotecard("Test" + llGetKey(), "Test"); }catch(exception ex) { llOwnerSay("You need to enable osMakeNotecard in your ossl configuration."); } - try{ osGetNotecard("Test" + llGetKey()); }catch(exception ex) { llOwnerSay("You need to enable osGetNotecard in your ossl configuration."); } - try{ osOwnerSaveAppearance("OwnerAppearance" + llGetKey()); }catch(exception ex) { llOwnerSay("You need to enable osOwnerSaveAppearance in your ossl configuration."); } - - llRemoveInventory("Test" + llGetKey()); - llRemoveInventory("OwnerAppearance" + llGetKey()); -} - -hardReset(string message) -{ - if(message != "") - llSay(0, "Hard reset: " + message); - - llSetTimerEvent(0); - integer dataListCount = llGetListLength(m_npcdata); - while(dataListCount--) - if(checkDataEntryInDataList(m_npcdata, "npc." + dataListCount)) - osNpcRemove((key)getDataEntryFromDataList(m_npcdata, "npc." + dataListCount)); - - llResetScript(); -} - -createNPCTempStorage() -{ - list npcKeys = []; - - integer currentNPCSlot = 0; - for (currentNPCSlot = 0; currentNPCSlot < llGetListLength(m_npcdata); currentNPCSlot++) - { - key currentNPCKey = getDataEntryFromDataList(m_npcdata, "npc." + currentNPCSlot); - npcKeys += [currentNPCKey]; - } - - osSetPrivateDataValue("tmpNPCList." + llGetKey(), llList2CSV(npcKeys)); -} - -removeOldNPC() -{ - list npcdata = llCSV2List(osGetPrivateDataValue("tmpNPCList." + llGetKey())); - integer count = llGetListLength(npcdata); - - while(count--)osNpcRemove(llList2Key(npcdata, count)); -} - //Generic Helpers integer getRealAgentCount() { @@ -543,4 +464,95 @@ list setDataEntryInDataList(list _dataList, string _key, string _value) return _dataList; } return llListReplaceList(_dataList, [_value], _inListPosition + 1, _inListPosition + 1); +} + +default +{ + state_entry() + { + removeOldNPC(); + + m_lastTimeCheck = llGetUnixTime(); + readAllNPCPathNC(); + + state waitingForPlayers; + } +} + +state waitingForPlayers +{ + state_entry() + { + llSetTimerEvent(0.1); + } + + timer() + { + llSetTimerEvent(2); + m_lastTimeCheck = llGetUnixTime(); + if(getRealAgentCount() != 0) + state running; + } +} + +state running +{ + state_entry() + { + llSetTimerEvent(0.3); + } + + touch_start(integer i) + { + if(llDetectedKey(0) != llGetOwner()) + return; + + osEasyDialog(llDetectedKey(0), "", ["Stop all", "Restart", "Start all"]); + } + + listen( integer channel, string name, key id, string message) + { + if(message == "Stop all") + { + llSetTimerEvent(0); + } + + if(message == "Start all") + { + m_lastTimeCheck = llGetUnixTime(); + llSetTimerEvent(0.3); + } + + if(message == "Restart") + { + hardReset(""); + } + } + + timer() + { + if((m_lastTimeCheck + 2) <= llGetUnixTime()) + hardReset("script timeout"); + + m_lastTimeCheck = llGetUnixTime(); + + if(getRealAgentCount() == 0) + hardReset("region empty"); + + doNextScriptStep(); + } + + changed(integer change) + { + if (change & CHANGED_INVENTORY) + hardReset(""); + + if (change & CHANGED_REGION_START) + hardReset(""); + } + + on_rez(integer start_param) + { + hardReset(""); + } } \ No newline at end of file