//YEngine:lsl yoptions; //=================== //Version: 0.1.3 //Datum: 30.01.2021 //UpdateRAW: https://clatza.dev/Christopher/OpenSim.Script.Chris.MultiNPC/raw/branch/master/Chris.MultiNPC.lsl //Made by: Chris Resident @ inc.li:8002 //Dependencies: // - https://github.com/Sahrea/Chris.OS.Additions //Bescheibung: // Create and controll a hord of npc at once. // Read the readme at https://clatza.dev/Christopher/OpenSim.Script.Chris.MultiNPC/src/branch/master/README.md //=================== list m_npcdata = []; integer m_lastTimeCheck = 0; default { state_entry() { m_lastTimeCheck = llGetUnixTime(); checkOSPermissions(); 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); } timer() { if((m_lastTimeCheck + 2) <= llGetUnixTime()) hardReset(); m_lastTimeCheck = llGetUnixTime(); if(getRealAgentCount() == 0) hardReset(); doNextScriptStep(); } changed(integer change) { if (change & CHANGED_INVENTORY) hardReset(); if (change & CHANGED_REGION_START) hardReset(); } } //Script commands integer script_create(integer slot, key npc, list command) { if(npc != NULL_KEY) osNpcRemove(npc); list objects = osGetSearchableObjectList(llList2String(command, 4)); if(llGetListLength(objects) == 0) { llSay(0, "Cant find the position for an object with the name '" + llList2String(command, 4) + "'."); return FALSE; } if(llGetInventoryType(llList2String(command, 3) + ".appearance") != INVENTORY_NOTECARD) { llSay(0, "Cant find appearance '" + llList2String(command, 3) + "'."); return FALSE; } npc = osNpcCreate(llList2String(command, 1), llList2String(command, 2), llList2Vector(llGetObjectDetails(llList2Key(objects, 0), [OBJECT_POS]), 0), llList2String(command, 3) + ".appearance"); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot, npc); return TRUE; } integer script_remove(integer slot, key npc, list command) { if(npc != NULL_KEY) osNpcRemove(npc); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot, NULL_KEY); return TRUE; } integer script_say(integer slot, key npc, list command) { osNpcSay(npc, 0, llList2String(command, 1)); return TRUE; } integer script_sit(integer slot, key npc, list command) { list objects = osGetSearchableObjectList(llList2String(command, 1)); if(llGetListLength(objects) == 0) { llSay(0, "Cant find the sit target '" + llList2String(command, 1) + "'."); return FALSE; } osNpcSit(npc, llList2Key(objects, 0), OS_NPC_SIT_NOW); return TRUE; } integer script_stand(integer slot, key npc, list command) { osNpcStand(npc); return TRUE; } integer script_wait(integer slot, key npc, list command) { m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".state", "wait"); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".waittime", llGetUnixTime() + (integer)llList2String(command, 1)); return TRUE; } integer script_walk(integer slot, key npc, list command) { list objects = osGetSearchableObjectList(llList2String(command, 1)); if(llGetListLength(objects) == 0) { llSay(0, "Cant find the walk target '" + llList2String(command, 1) + "'."); return FALSE; } list targetDataList = llGetObjectDetails(llList2Key(objects, 0), [OBJECT_POS]); vector targetPosition = llList2Vector(targetDataList, 0); osNpcMoveToTarget(npc, targetPosition, OS_NPC_NO_FLY); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".state", "walk"); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".targetPosition", targetPosition); return TRUE; } integer script_touch(integer slot, key npc, list command) { list objects = osGetSearchableObjectList(llList2String(command, 1)); if(llGetListLength(objects) == 0) { llSay(0, "Cant find the touch target '" + llList2String(command, 1) + "'."); return FALSE; } osNpcTouch(npc, llList2Key(objects, 0), LINK_THIS); return TRUE; } integer script_goto(integer slot, key npc, list command) { m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".line", (integer)llList2String(command, 1) - 1); return TRUE; } integer script_appearance(integer slot, key npc, list command) { if(llGetInventoryType(llList2String(command, 1) + ".appearance") != INVENTORY_NOTECARD) { llSay(0, "Cant find appearance '" + llList2String(command, 1) + "'."); return FALSE; } osNpcLoadAppearance(npc, llList2String(command, 1) + ".appearance"); return TRUE; } integer script_include(integer slot, key npc, list command) { if(llGetInventoryType(llList2String(command, 1) + ".path") != INVENTORY_NOTECARD) { llSay(0, "Cant find path '" + llList2String(command, 1) + "'."); return FALSE; } integer newLine = llList2Integer(command, 2); string newnc = osStringReplace(osGetNotecard(llList2String(command, 1) + ".path"), "\n", ""); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".path", newnc); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".line", newLine); m_npcdata = setDataEntryInDataList(m_npcdata, "npc." + slot + ".ncname", llList2String(command, 1) + ".path"); 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, ["=", "|"], []); 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"); list currentNPCDataList = llGetObjectDetails(currentNPCKey, [OBJECT_POS]); if(llGetListLength(currentNPCDataList) == 0) hardReset(); vector currentNPCPosition = llList2Vector(currentNPCDataList, 0); 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); 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 "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; 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) { llSay(0, "You need to enable osNpcCreate in your ossl configuration."); } try{ osNpcRemove(tempnpc); }catch(exception ex) { llSay(0, "You need to enable osNpcRemove in your ossl configuration."); } try{ osMakeNotecard("Test" + llGetKey(), "Test"); }catch(exception ex) { llSay(0, "You need to enable osMakeNotecard in your ossl configuration."); } try{ osGetNotecard("Test" + llGetKey()); }catch(exception ex) { llSay(0, "You need to enable osGetNotecard in your ossl configuration."); } try{ osOwnerSaveAppearance("OwnerAppearance" + llGetKey()); }catch(exception ex) { llSay(0, "You need to enable osOwnerSaveAppearance in your ossl configuration."); } llRemoveInventory("Test" + llGetKey()); llRemoveInventory("OwnerAppearance" + llGetKey()); } hardReset() { llSetTimerEvent(0); integer dataListCount = llGetListLength(m_npcdata); while(dataListCount--) if(checkDataEntryInDataList(m_npcdata, "npc." + dataListCount)) osNpcRemove((key)getDataEntryFromDataList(m_npcdata, "npc." + dataListCount)); llResetScript(); } //Generic Helpers integer getRealAgentCount() { list users = llGetAgentList(AGENT_LIST_EXCLUDENPC, []); return llGetListLength(users); } integer checkDataEntryInDataList(list _dataList, string _key) { integer _inListPosition = llListFindList(_dataList, [_key]); if(_inListPosition == -1)return FALSE; return TRUE; } string getDataEntryFromDataList(list _dataList, string _key) { integer _inListPosition = llListFindList(_dataList, [_key]); if(_inListPosition == -1)return ""; return llList2String(_dataList, _inListPosition + 1); } list setDataEntryInDataList(list _dataList, string _key, string _value) { integer _inListPosition = llListFindList(_dataList, [_key]); if(_inListPosition == -1){ _dataList += [_key, _value]; return _dataList; } return llListReplaceList(_dataList, [_value], _inListPosition + 1, _inListPosition + 1); }