Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
Ich selber habe GARKEINE Ahnung von Scripten. Umso mehr Ferd Frederix
Ich hatte mir vor langer Zeit dieses Link notiert für einen NPC - ist das noch State of the Art? - oder hoffnungslos veraltet?
Wollte auf meinem Castle mal sowas ausprobieren
Ohne das die Region dabei abstürzt!
Beiträge: 631
Themen: 100
Thanks Received: 833 in 397 posts
Thanks Given: 1.502
Registriert seit: Jun 2020
Für NPCs, glaube ich, kann man die Sachen von Áine Caoimhe empfehlen. Die bekommst du auf ihrer alten Sim; die ist online, auch wenn da was anderes steht.
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
09.12.2023, 13:00
(Dieser Beitrag wurde zuletzt bearbeitet: 09.12.2023, 13:04 von Leora Jacobus.)
Ich hatte im Inventar meiner OSGrid Leora noch eine alte Box - invisible - mit der sie früher, als mein Castle noch im OSGrid gewesen ist, einen NPC dort gerezzt hat, der sah aus wie sie, ging ein Stück bis in die große Halle und wieder zurück unf forderte die Besucher auf, ihr dorthin zu folgen.
Wenn ich den jetzt klicke - egal on in der Sandbox im OSGrid oder in Craft im Castle dann passiert NIX!
Man konnte mit dem Kasten damals das Aussehen seines Avatars aufnehmen, den Weg. den Text und dann später wieder abspielen. Damals hat das geklappt. Hab nur vergessen WIE. Muß man den Kasten klicken?, den Script resetten? auf irgendeinem Kanal zu ihm sprechen? Steht ja eijentlich alles da aber irgendwie funzt es nicht.
Code: // Script Name: AllinOne_NPC_Script.lsl
// CATEGORY: OpenSim NPC
// CREATED: 2013-09-08 18:30:11.293
// EDITED: 2013-08-16 17:29:32.757
// AUTHOR: Ferd Frederix
// COMPATIBILITY: OpenSim
// Recorder Script// Add animations named "Fly, Walk, Stand and Run, Click Prim to use. Should be worn as a HUD to record. Put it on the ground and click Sensor or Start NPC when done.
// Downloaded from : http://www.free-lsl-scripts.com/cgi/freescripts.plx?ID=27
// This program is free software; you can redistribute it and/or modify it.
// Additional Licenes may apply that prevent you from selling this code
// You must leave any author credits and any headers intact in any script you use or publish.
// If you don't like these restrictions and licenses, then don't use these scripts.
//////////////////////// ORIGINAL AUTHORS CODE BEGINS ////////////////////////////////////////////
// Recorder Script// Add animations named "Fly, Walk, Stand and Run, Click Prim to use. Should be worn as a HUD to record. Put it on the ground and click Sensor or Start NPC when done.
// 8-16-2014
// Instructions on how to use this is at http://www.free-lsl-scripts.com/opensim/posts/NPC/
// This is an OpenSim-only script.
// Author: Ferd Frederix
////////////////////////////////////////////////////////////////////////////////////////////
// Original code is Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////////////////////
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////////////////////
// The original NPC controller was from http://was.fm/opensim:npc
// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com
// llSensor had two params swapped
// @Wander would wander where it had rezzed, not where it was.
// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck
// The animation and walks always stopped old, then started new. It should be start new, then stop old so the default stand would be suppressed.
// New code:
// Merged with new Route recorder and notecard writer
// If the NPC failed to reach a destination it never moved on. Added WAIT global to tune this
// Exposed many tunable variables and ported the code to LSLEditor.
// Added floating point to times in notecard.
// Added @sound, @randsound, @whisper, @shout, and @cmd controls.
//
// notecards integers are not floats for better control
//
// Link Messages may be used to perform external control by injecting @commands into the stream of actions
// Example:
// To chat something, such as with a chat robot
// llMessageLinked(LINK_SET,0,"@npc_say=Hello","");
// This script assumes that NPCs and OSSl scripting is enabled in the OpenSim configuration.
// In order to enable them, the following changes must be made in the OpenSim.ini configuration file:
//
// ; Turn on OSSL
// AllowOSFunctions = true
// OSFunctionThreatLevel = Severe
//[NPC]
// ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false}
// Enabled = true
//
// and then the server has to be restarted.
// Commands: All commands begin with an @ sign. All other lines are ignored
// @commands may have optional parameters. The syntax is always:
// @cmd=parm1|parm2
// NaN in the table below meand Not a Number. This means there is no parameter
//Command First Parameter Second Parameter Description
//@spawn name location (vector) Rezzes an NPC with name at a location.
//@walk destination (vector) NaN Makes the NPC walk to destination.
//@fly destination (vector) NaN Makes the NPC fly to destination.
//@land destination (vector) NaN Makes the NPC land at destination.
//@say string NaN Makes the NPC speak a phrase.
//@whisper string NaN Makes the NPC whisper a phrase.
//@shout string NaN Makes the NPC shout a phrase.
//@pause seconds (float) NaN Makes the NPC wait for a multiple of seconds.
//@wander radius (float) cycles (integer) Makes the NPC wander in radius, for cycles seconds.
//@stop NaN NaN Halts the NPC script indefinitely. Can be started with a link message
//@delete NaN NaN Removes the NPC.
//@animate animation (string) time (float) Makes the NPC trigger the animation animation for time seconds.
//@goto label (string) NaN Jump to the label label in the script.
//@rotate degrees NaN Rotate the NPC degrees around the Z axis.
//@sit primitive name NaN Sit on a primitive with a given name.
//@stand NaN NaN If sitting on a primitive, stand up.
//@sound sound_name NaN plays a sound from inventory
//@randsound NaN NaN Plays a random sound from inventory
//@cmd channel (integer) string Says string on channel, for controlling external gadgets
//////////////////////////////////////////////////////////
// DEBUG //
//////////////////////////////////////////////////////////
integer debug = FALSE; // set to TRUE or FALSE for debug chat on various actions
integer Editor = FALSE; // set to to TRUE to working in LSLEditor, FALSE for in-world.
integer iTitleText = TRUE; // set to TRUE to see debug in text above the controller
//////////////////////////////////////////////////////////
// TUNABLE CONFIGURATION //
//////////////////////////////////////////////////////////
float MAXDIST = 2.0; // how close a NPC has to get to a dest pos to continue to next state. Do not lower this too much, will also need a faster TIMER
float TIMER = 0.5; // how often the system checks the distance traveled
integer WANDERRAND = TRUE; // set to TRUE and they will pause during wanders a random number of seconds
float WANDERTIME = 5.0; // how long they stand after each @wander,if WANDERRAND is FALSE. If WANDERRAND is TRUE, this is the max time
integer WAIT = 60; // wait for this number of seconds for the NPC to reach a destination (for safety)
float RANGE = 30.0; // 1 to 96.0 meters - anyone this close to the controller will start NPCS if Sensor button is clicked
float REZTIME = 10.0; // wait this lng for NPC to rez in, then start the process
string STAND = "Stand"; // the name of the default Stand animation
string WALK = "Walk"; // the name of the default Walk animation
string FLY = "Fly"; // the name of the default Fly animation
string RUN = "Run"; // the name of the default Run animation
float OffsetZ = 0.5; // appear 0.5 meter above ground, this is added to all destinations to keep them from sinking in.
// globals section
integer iChannel; // a listen channel, randomly assigned
integer iHandle; // the handle to it
// NPC
integer iWaitCounter ; // wait for this number of seconds for the NPC to reach a desrtination
string sNPCName; // the name of the NPC that may be in world. So we can remove it.
integer bNPC_STOP = FALSE; // boolean to reuse a listener
integer bForget = FALSE; // set to TRUE by link messages so we do not remember them
float fTimerVal ; // how long we wait when wandering (calculated)
// OS_NPC_CREATOR_OWNED will create an 'owned' NPC that will only respond to osNpc* commands issued from scripts that have the same owner as the one that created the NPC.
// OS_NPC_NOT_OWNEDwill create an 'unowned' NPC that will respond to any script that has OSSL permissions to call osNpc* commands.
integer NPCOptions = OS_NPC_NOT_OWNED;
integer NPCWalkOption;
// Just some notes for what happens to NPCWalkOption:
// OS_NPC_FLY - Fly the avatar to the given position. The avatar will not land unless the OS_NPC_LAND_AT_TARGET option is also given.
// OS_NPC_NO_FLY - Do not fly to the target. The NPC will attempt to walk to the location. If it's up in the air then the avatar will keep bouncing hopeless until another move target is given or the move is stopped
//OS_NPC_LAND_AT_TARGET - If given and the avatar is flying, then it will land when it reaches the target. If OS_NPC_NO_FLY is given then this option has no effect.
// OS_NPC_RUNNING - if given, NPC avatar moves at running/fast flying speed, otherwise moves at walking/slow flying speed.
// menus
integer showMenu = FALSE; // when we switch states, we need to bring up a menu
list lAtButtons = ["Menu","-", "More", "@run","@walk","@fly", "@land","@wander","@sit", "@stand","@animate","@rotate"];
list lMenu2 = ["<<", "@comment", "@stop", "@say","@whisper","@shout", "@sound","@randsound", "-", "@cmd", "@pause", "@stop" ];
string sCommand; // place to store a command for two-prompted ones
string sParam2; // place to store a prompt for two-prompted ones
string priPub = "Owner Only"; // Private or Group
key kUserKey; // the person who is controlling the avatar, not the Owner
// the command lists
list lCommands; // commands are stored here
list lNPCScript; // Storage for the NPC script.
string npcAction; // Storage for the next action. @cmd=0|hello, this becomes @cmd
string npcParams; // Storage for the param, @cmd=0|hello, this becomes 0|hello
// misc vars
string sNotecard; // commands are stored here temporarily for dumping
vector vWanderPos; // a place to wander to
string lastANIM ; // last animation run
// Sensor
integer avatarPresent = TRUE; // Sensor sets this flag when people are within Range.
integer Sensor; // set to true if we are running a Sensor for avatars
// Coordinate control
vector vInitialPos ; // Vector that will be filled by the script with the initial starting position in region coordinates.
vector vDestPos = ZERO_VECTOR; // Storage for destination position.
string relAbs = "Absolute"; // absolute vs relative positioning
///////////////////////////////////////////////////////////////////////////
// FUNCTIONS //
///////////////////////////////////////////////////////////////////////////
// DEBUG(string) will chat a string or display it as hovertext if debug == TRUE
DEBUG(string str)
{
if (debug)
llOwnerSay( str); // Send the owner debug info so you can chase NPCS
if (iTitleText)
{
llSleep(0.1);
llSetText(str,<1.0,1.0,1.0>,1.0); // show hovertext
}
}
// common subroutines
// return TRUE if the avatar is owner when private is set, or TRUE if the avatar is in th same group and GROUP is set.
integer checkPerms() {
if (priPub == "Private") {
if (llDetectedKey(0) == llGetOwner()){
kUserKey = llDetectedKey(0);
return TRUE;
}
} else {
if (llDetectedGroup(0)) {
kUserKey = llDetectedKey(0);
return TRUE;
}
}
kUserKey = NULL_KEY;
return FALSE;
}
NPCStart(string anim)
{
DEBUG(" Start Anim: " + anim);
if(llGetInventoryType(anim) == INVENTORY_ANIMATION)
osNpcPlayAnimation(KeyValueGet("key"), anim);
if(llStringLength(lastANIM) && llGetInventoryType(lastANIM) == INVENTORY_ANIMATION)
osNpcStopAnimation(KeyValueGet("key"), lastANIM);
lastANIM = anim;
}
TimerEvent(float timesent)
{
//DEBUG("Setting timer: " + (string) timesent);
llSetTimerEvent(timesent);
}
ProcessLink(string str)
{
// DEBUG("Processing exern cmd : " + str);
bForget = TRUE; // tell the NPCProcess state to forget this command after processing it.
lNPCScript = llListInsertList(lNPCScript,[str],0); // add this command to the beginning of the list of commands
NPCStart(STAND);
}
// Kill a NPC by Name
Kill(string sNPCName)
{
list avatars = osGetAvatarList(); // Returns a strided list of the UUID, position, and name of each avatar in the region except the owner.
//DEBUG(llDumpList2String(avatars,","));
integer i;
integer count;
integer j = llGetListLength(avatars);
for (; i < j; i++){
if (llList2String(avatars,i) == sNPCName){
vector v = llList2Vector(avatars,i-1);
key target = llList2Key(avatars,i-2); // get the UUID of the avatar
osNpcRemove(target);
llOwnerSay("Removed " + sNPCName + " at location " + (string) v);
count++;
}
}
if (count)
llOwnerSay("Removed " + (string) count + " NPC's");
else
llOwnerSay("Could not locate " + sNPCName);
}
// return a String for the position we are at. Strings used as the caller wants strings
string Pos()
{
vector where = llGetPos(); // find the box position
where.z += OffsetZ; // use the ground position + an offset
if (Editor)
where = <128,128,31 + llFrand(1)>; // center of sim for editing
// if attached the height will be too high by 1/2 the agent size
if (llGetAttached()) {
vector size = llGetAgentSize(llGetOwner());
float Z = size.z;
where.z -= Z/2;
}
// DEBUG("Pos= " + (string) where);
return (string) where;
}
Expire()
{
llOwnerSay("Menu expired");
iHandle = 0;
TimerEvent(0.0);
state default;
}
// setup a menu with a timer for timeouts, called by all make*()
menu()
{
llListenRemove(iHandle);
iChannel = llCeil(llFrand(100000) + 20000);
iHandle = llListen(iChannel,"","","");
TimerEvent(120.0);
}
// make a text box
makeText(string Param)
{
menu();
llTextBox(kUserKey, Param, iChannel);
}
// top level menu
makeMainMenu()
{
menu();
list buttons = ["Appearance","Recording","Save","Help","Reset","Erase RAM", priPub,relAbs,"-","Stop NPC","Sensor","Start NPC"];
llDialog(kUserKey,"Choose a command",buttons,iChannel);
}
// programmable menu for @commands
makeMenu(list buttons)
{
menu();
llDialog(kUserKey,"Choose a command",buttons,iChannel);
}
// make one or two text boxes with prompts
Text(string cmd, string p1, string p2)
{
sCommand = cmd;
sParam2 = "";
if (llStringLength(p2))
sParam2 = p2;
makeText(p1);
}
ProcessSensor(integer n)
{
if (Sensor && n)
avatarPresent = TRUE; // someone is here and we need to tell the system to run
else if (Sensor && !n)
avatarPresent = FALSE; // someone is not here and we need to tell the system to stop
else
avatarPresent = TRUE; // someone is effectivly always here
}
vector CirclePoint(float radius) {
float x = llFrand(radius *2) - radius; // +/- radius, randomized
float y = llFrand(radius *2) - radius; // +/- radius, randomized
return <x, y, 0>; // so this should always happen
}
string KeyValueGet(string var) {
list dVars = llParseString2List(llGetObjectDesc(), ["&"], []);
do {
list data = llParseString2List(llList2String(dVars, 0), ["="], []);
string k = llList2String(data, 0);
if(k != var) jump continue;
//DEBUG("got " + var + " = " + llList2String(data, 1));
return llList2String(data, 1);
@continue;
dVars = llDeleteSubList(dVars, 0, 0);
} while(llGetListLength(dVars));
return "";
}
KeyValueSet(string var, string val) {
//DEBUG("set " + var + " = " + val);
list dVars = llParseString2List(llGetObjectDesc(), ["&"], []);
if(llGetListLength(dVars) == 0)
{
llSetObjectDesc(var + "=" + val);
return;
}
list result = [];
do {
list data = llParseString2List(llList2String(dVars, 0), ["="], []);
string k = llList2String(data, 0);
if(k == "") jump continue;
if(k == var && val == "") jump continue;
if(k == var) {
result += k + "=" + val;
val = "";
jump continue;
}
string v = llList2String(data, 1);
if(v == "") jump continue;
result += k + "=" + v;
@continue;
dVars = llDeleteSubList(dVars, 0, 0);
} while(llGetListLength(dVars));
if(val != "") result += var + "=" + val;
llSetObjectDesc(llDumpList2String(result, "&"));
}
wasKeyValueDelete(string var) {
list dVars = llParseString2List(llGetObjectDesc(), ["&"], []);
list result = [];
list added = [];
do {
list data = llParseString2List(llList2String(dVars, 0), ["="], []);
string k = llList2String(data, 0);
if(k == var) jump continue;
string v = llList2String(data, 1);
if(v == "") jump continue;
if(llListFindList(added, (list)k) != -1) jump continue;
result += k + "=" + v;
added += k;
@continue;
dVars = llDeleteSubList(dVars, 0 ,0);
} while(llGetListLength(dVars));
//DEBUG("del " + var );
llSetObjectDesc(llDumpList2String(result, "&"));
}
// clear RAM
Clr() {
lCommands = [];
llOwnerSay("RAM Memory cleared. Notecards, if any, are not modified.");
makeMainMenu();
}
integer checkNoteCards()
{
// Check that they have saved an Appeaance and Path notecard
integer num = llGetInventoryNumber(INVENTORY_NOTECARD); // how many notecards overall
integer i;
integer count;
for (; i < num; i++){
if (llGetInventoryName(INVENTORY_NOTECARD,i) == "Path")
count++;
if (llGetInventoryName(INVENTORY_NOTECARD,i) == "Appearance")
count++;
}
// if we have both, run the NPC
return count;
}
// Notes:
// No llResetScript() used so we can retain memory between rezzes and sim restarts. NPC info and stateful info is held in the Description
//
// This state is the first main menu
default
{
state_entry()
{
osNpcRemove(KeyValueGet("key"));
string rA = KeyValueGet("co"); // Get the remembered menu setting for Abs Vs Relative
if (rA == "A")
relAbs = "Absolute";
else if (rA == "R")
relAbs = "Relative";
else
relAbs = "Absolute";
if (showMenu)
makeMainMenu();
llSetText("",<1,1,1>,1.0); // clr all hovertext in ase we are not using it.
}
on_rez(integer param) {
}
touch_start(integer n) { // if touched, make a menu
if (checkPerms())
makeMainMenu();
}
// no changed event needed
// menu listener
listen(integer iChannel, string name, key id, string message) {
TimerEvent(0.0); /// kill the menu expiration timer
if (message == "Stop NPC")
{
if (llStringLength(sNPCName)){
Kill(sNPCName);
} else {
bNPC_STOP = TRUE;
makeText("Enter name of an NPC to stop");
}
}
else if (message == "Erase RAM"){
Clr();
}
else if (message == "Relative"){
relAbs = "Absolute";
KeyValueSet("co","A"); // remember coordinates = A
Clr();
}
else if (message == "Absolute"){
relAbs = "Relative";
KeyValueSet("co","R"); // remember coordinates = R
Clr();
}
else if (message == "Recording"){
state Commands; // show them the recording menu
}
else if (message == "Owner Only") {
priPub = "Group";
llOwnerSay("Group members have control");
makeMainMenu();
}
else if (message == "Group") {
priPub = "Owner Only";
llOwnerSay("Only you have control");
makeMainMenu();
}
else if (message == "Reset"){
llResetScript();
}
else if (message == "Sensor") {
integer count = checkNoteCards();
if (count == 2) {
ProcessSensor(1); // fake 1 avatar to get it rezzed
Sensor = TRUE; // we need to scan for avatars
state NPCGo;
}
// lslEditor does not handle the above, so I hack it in
if (Editor) {
Sensor = TRUE; // we need to scan for avatars
state NPCGo;
}
llOwnerSay("You have not saved a recording and/or appearance, so we cannot start a NPC");
makeMainMenu();
}
else if (message == "Appearance") {
llRemoveInventory("Appearance"); // delete the notecard
osAgentSaveAppearance(kUserKey, "Appearance"); // make the ntecard
llOwnerSay("Your Appearance has been recorded in notecard 'Appearance'");
makeMainMenu();
}
else if (message == "Save") {
if (llGetAttached()) {
llOwnerSay("Detach the HUD and put it where you want the NPC to appear, then click Start");
return;
}
if (llGetListLength(lCommands) == 0) {
llOwnerSay("Nothing recorded, you need to make some Recodings first");
makeMainMenu();
return;
}
state Save;
}
else if (message == "Help"){
llLoadURL(kUserKey,"Click to view help","http://www.free-lsl-scripts.com/opensim/posts/NPC/");
makeMainMenu();
}
else if (message == "Start NPC") {
integer count = checkNoteCards();
if (Editor) state NPCGo;
if (count == 2)
state NPCGo;
llOwnerSay("You have not saved a either recording or and appearance, so we cannot start a NPC");
makeMainMenu();
}
else if (bNPC_STOP){
bNPC_STOP = FALSE;
Kill(message);
makeMainMenu();
}
}
timer(){
Expire();
}
}
// This state is used to save a Path notecard
state Save
{
state_entry(){
makeText("Stand where you want the NPC to appear, and enter the NPC Name");
}
listen(integer iChannel, string name, key id, string message) {
TimerEvent(0.0); /// kill the menu expiration timer
sNPCName = message; // in case we need to kill it.
vector vDest = Pos();
if (relAbs == "Relative")
{
vDest -= llGetPos(); // just an offset for relative
}
sNotecard = "@spawn=" + message + "|" + (string) vDest + "\n";
integer i;
integer j = llGetListLength(lCommands);
for (; i < j; i++){
// get the command to save to the notecard
string line = llList2String(lCommands,i);
if (relAbs == "Absolute") {
sNotecard += line; // add the un-modified string to the notecard
} else {
// since we have to record absolute coords since we do not know whwre the box goes until they press Save,
// we process the absolute to relative conversion for walks here
list parts = llParseString2List(line,["="],[]); //get the @command
if (llList2String(parts,0) == "@walk") {
vector vec = (vector) llList2String(parts,1) - llGetPos();
sNotecard += "@walk=" + (string) vec + "\n";
}
else {
sNotecard += line; // add the un-modified string to the notecard
}
}
}
llRemoveInventory("Path"); // delete the old notecard
osMakeNotecard("Path",sNotecard); // Makes the notecard.
llOwnerSay("'Path' notecard has been written");
state default;
}
timer(){
Expire();
}
}
// This state is used to record the path for the NPC
// Each command can take 0, 1, or 2 params
state Commands
{
state_entry() {
makeMenu(lAtButtons);
}
on_rez(integer p) {
llResetScript();
}
touch_start(integer n){
if (checkPerms())
makeMenu(lAtButtons);
}
listen(integer iChannel, string name, key id, string message)
{
TimerEvent(0.0); /// kill the menu expiration timer
if (message == "Menu"){
showMenu= TRUE;
state default;
}
else if (message == "More"){
makeMenu(lMenu2);
}
else if (message == "<<") {
makeMenu(lAtButtons);
}
else if (message == "@comment"){
Text("# ","Enter a comment","");
}
else if (message == "@stop"){
lCommands += "@stop"+ "\n";
makeMenu(lAtButtons);
}
else if (message == "@run"){
lCommands += "@run=" + Pos() + "\n";
llOwnerSay("Recorded position: " + Pos());
makeMenu(lAtButtons);
}
else if (message == "@fly"){
lCommands += "@fly=" + Pos() + "\n";
llOwnerSay("Recorded position: " + Pos());
makeMenu(lAtButtons);
}
else if (message == "@land"){
lCommands += "@land=" + Pos() + "\n";
llOwnerSay("Recorded position: " + Pos());
makeMenu(lAtButtons);
}
else if (message == "@walk") {
lCommands += "@walk=" + Pos() + "\n";
llOwnerSay("Recorded position: " + Pos());
makeMenu(lAtButtons);
}
else if (message == "@stop"){
lCommands += "@stop"+ "\n";
makeMenu(lAtButtons);
}
else if (message == "@sound"){
Text("@sound=","Enter a sound name or UUID to trigger","");
}
else if (message == "@randsound"){
lCommands += "@randsound"+ "\n";
makeMenu(lAtButtons);
}
else if (message == "@say") {
Text("@say=","Enter what the NPC will say","");
}
else if (message == "@whisper"){
Text("@whisper=","Enter what the NPC will whisper","");
}
else if (message == "@shout"){
Text("@shout=","Enter what the NPC will shout","");
}
else if (message == "@wander") {
Text("@wander=","Enter radius to wander","Enter Time to wander");
}
else if (message == "@pause") {
Text("@pause=","Enter time to pause","");
}
else if (message == "@rotate") {
Text("@rotate=","Enter degrees to rotate","");
}
else if (message == "@sit"){
Text("@sit=","Enter name of object to sit on","");
}
else if (message == "@cmd"){
Text("@cmd=","Enter cjhannel to speak on","Enter text to speak");
}
else if (message == "@stand"){
lCommands += "@stand\n";
llOwnerSay("Stand Recorded");
makeMenu(lAtButtons);
}
else if (message == "@animate"){
Text("@animate=","Enter animation name to play","Enter time to play the animation");
}
else if (! llStringLength(sParam2)) {
lCommands += sCommand + message + "\n";
llOwnerSay("Recorded");
makeMenu(lAtButtons);
}
else if (llStringLength(sParam2)){
sCommand = sCommand + message + "|";
llOwnerSay("Recorded");
makeText(sParam2);
sParam2 = "";
}
}
timer() {
Expire();
}
}
// This state will create an NPC in world
state NPCGo {
state_entry() {
// DEBUG("NPCGo");
ProcessSensor(1); // assert that someone is home so we can get rezzed.
osNpcRemove(KeyValueGet("key"));
TimerEvent(5);
}
timer() {
lNPCScript = llParseString2List(osGetNotecard("Path"), ["\n"], []);
if(llGetListLength(lNPCScript) == 0) {
llSay(DEBUG_CHANNEL, "No Path notecard found.");
TimerEvent(0.0);
return;
}
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state ProcessNPCLine;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
// This state loops over the notecard, processing each command
state ProcessNPCLine
{
state_entry()
{
// DEBUG("ProcessNPCLine");
@ignore;
string next = llList2String(lNPCScript, 0); // get the next command
// DEBUG("Cmd:" + next);
lNPCScript = llDeleteSubList(lNPCScript, 0, 0); // delete it
if (! bForget) {
lNPCScript += next; // put it on the end unless we are told to forget it from a Link Message
bForget = FALSE;
}
if(llGetSubString(next, 0, 0) != "@") jump ignore; // ignore non-@ commands
list data = llParseString2List(next, ["="], []);
npcAction = llToLower(llStringTrim(llList2String(data, 0), STRING_TRIM));
npcParams = llStringTrim(llList2String(data, 1), STRING_TRIM);
@commands;
if (! avatarPresent){
state nobodyHome;
}
if(npcAction == "@spawn") {
// DEBUG("Spawning");
integer lastIdx = llGetListLength(lNPCScript)-1;
lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx); // remove spawn commands, we do them only once
list spawnData = llParseString2List(npcParams, ["|"], []);
KeyValueSet("name", llList2String(spawnData, 0));
list spawnDest = llParseString2List(llList2String(spawnData, 1), ["<", ",", ">"], []);
vInitialPos.x = llList2Float(spawnDest, 0);
vInitialPos.y = llList2Float(spawnDest, 1);
vInitialPos.z = llList2Float(spawnDest, 2);
state spawn;
}
if(npcAction == "@stop") {
state stop;
}
if(npcAction == "@goto") {
// DEBUG("goto");
integer lastIdx = llGetListLength(lNPCScript)-1;
lNPCScript = llDeleteSubList(lNPCScript, lastIdx, lastIdx);
// Wind commands till goto label.
@wind;
string next1 = llList2String(lNPCScript, 0);
lNPCScript = llDeleteSubList(lNPCScript, 0, 0);
lNPCScript += next1;
if(next1 != npcParams) jump wind;
// Wind the label too.
next1 = llList2String(lNPCScript, 0);
lNPCScript = llDeleteSubList(lNPCScript, 0, 0);
lNPCScript += next1;
// Get next command.
list data1 = llParseString2List(next1, ["="], []);
npcAction = llToLower(llStringTrim(llList2String(data1, 0), STRING_TRIM));
npcParams = llStringTrim(llList2String(data1, 1), STRING_TRIM);
// Reschedule.
jump commands;
}
if(npcAction == "@sound") {
// DEBUG("sound");
llTriggerSound(npcParams,1.0);
jump ignore; // process next line
}
if(npcAction == "@randsound") {
// DEBUG("random sound");
integer N = llGetInventoryNumber(INVENTORY_SOUND);
integer rand = llCeil(llFrand(N)) -1; // pick a random sound
string toPlay = llGetInventoryName(INVENTORY_SOUND,rand);
llTriggerSound(toPlay,1.0);
jump ignore; // process next line
}
if(npcAction == "@walk") {
// DEBUG(WALK);
list dest = llParseString2List(npcParams, ["<", ",", ">"], []);
vDestPos.x = llList2Float(dest, 0);
vDestPos.y = llList2Float(dest, 1);
vDestPos.z = llList2Float(dest, 2);
if (vDestPos == ZERO_VECTOR) {
llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk");
state ProcessNPCLine;
}
NPCWalkOption = OS_NPC_NO_FLY ;
state walk;
}
if(npcAction == "@fly") {
list dest = llParseString2List(npcParams, ["<", ",", ">"], []);
vDestPos.x = llList2Float(dest, 0);
vDestPos.y = llList2Float(dest, 1);
vDestPos.z = llList2Float(dest, 2);
if (vDestPos == ZERO_VECTOR) {
llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk");
state ProcessNPCLine;
}
NPCWalkOption = OS_NPC_FLY ;
state walk;
}
if(npcAction == "@run") {
list dest = llParseString2List(npcParams, ["<", ",", ">"], []);
vDestPos.x = llList2Float(dest, 0);
vDestPos.y = llList2Float(dest, 1);
vDestPos.z = llList2Float(dest, 2);
if (vDestPos == ZERO_VECTOR) {
llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk");
state ProcessNPCLine;
}
NPCWalkOption = OS_NPC_NO_FLY | OS_NPC_RUNNING;
state walk;
}
if(npcAction == "@land") {
list dest = llParseString2List(npcParams, ["<", ",", ">"], []);
vDestPos.x = llList2Float(dest, 0);
vDestPos.y = llList2Float(dest, 1);
vDestPos.z = llList2Float(dest, 2);
if (vDestPos == ZERO_VECTOR) {
llSay(DEBUG_CHANNEL,"Bad (zeros) position for @walk");
state ProcessNPCLine;
}
NPCWalkOption= OS_NPC_FLY | OS_NPC_LAND_AT_TARGET ;
state walk;
}
// chat commands
// speak in white text
if(npcAction == "@say") {
// DEBUG("say");
osNpcSay(KeyValueGet("key"),0, npcParams);
jump ignore; // process next line
}
if(npcAction == "@shout") {
// DEBUG("shout");
osNpcShout(KeyValueGet("key"),0, npcParams);
jump ignore; // process next line
}
if(npcAction == "@whisper") {
// DEBUG("whisper");
osNpcWhisper(KeyValueGet("key"),0, npcParams);
jump ignore; // process next line
}
// speak a command on a channel, so you can open doors and control stuff.
if(npcAction == "@cmd") {
// DEBUG("cmd");
list dataToSpeak = llParseString2List(npcParams, ["|"], []);
integer iChannel = (integer) llList2String(dataToSpeak,0);
string stringToSpeak = llList2String(dataToSpeak,1);
osNpcSay(KeyValueGet("key"), iChannel, stringToSpeak);
jump ignore; // process next line
}
// stop everything
if(npcAction == "@pause") {
// DEBUG("pause");
KeyValueSet("pause", npcParams);
state pause;
}
if(npcAction == "@wander") {
// DEBUG("wander");
list wanderData = llParseString2List(npcParams, ["|"], []);
KeyValueSet("wd", llList2String(wanderData, 0));
KeyValueSet("wc", llList2String(wanderData, 1));
vDestPos = osNpcGetPos(KeyValueGet("key")); // set the wander start
state wander;
}
if(npcAction == "@rotate") {
// DEBUG("rotate");
KeyValueSet("rot", npcParams);
state rotate;
}
if(npcAction == "@sit") {
// DEBUG("sit");
KeyValueSet("sit", npcParams);
state sit;
}
if(npcAction == "@stand") {
// DEBUG("stand");
state stand;
}
if(npcAction == "@delete") {
state delete;
}
if(npcAction == "@animate") {
// DEBUG("animate");
list animateData = llParseString2List(npcParams, ["|"], []);
KeyValueSet("an", llList2String(animateData, 0));
KeyValueSet("at", llList2String(animateData, 1));
state animate;
}
llSay(DEBUG_CHANNEL, "ERROR: Unrecognized script line: " + npcAction + "=" + npcParams);
jump ignore;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
}
state nobodyHome
{
state_entry() {
// DEBUG("Removing NPC");
osNpcRemove(KeyValueGet("key"));
llSensorRepeat("","",AGENT,RANGE,TWO_PI, 5);
}
sensor(integer n) {
llSensorRemove();
state NPCGo;
}
}
state spawn
{
state_entry() {
// DEBUG("state spawn");
list name = llParseString2List(KeyValueGet("name"), [" "], []);
// notecard is stored as offsets from this box with relative addressing. Convert to absolute
if (relAbs == "Relative"){
vInitialPos += llGetPos();
}
// DEBUG("rez:" + (string) vInitialPos);
KeyValueSet("key", osNpcCreate(llList2String(name, 0), llList2String(name, 1), vInitialPos, "Appearance", NPCOptions)); // no OS_NPC_SENSE_AS_AGENT allowed due to llSensor Use
osNpcLoadAppearance(KeyValueGet("key"), "Appearance");
TimerEvent(REZTIME);
NPCStart(STAND);
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
timer() {
wasKeyValueDelete("name");
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit(){
TimerEvent(0.0);
}
}
state rotate {
state_entry() {
// DEBUG("state rotate");
osNpcSetRot(KeyValueGet("key"), llEuler2Rot(<0,0,(float)KeyValueGet("rot")> * DEG_TO_RAD));
TimerEvent(TIMER);
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
timer() {
wasKeyValueDelete("rot");
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
state sit {
state_entry() {
// DEBUG ("state sit");
llSensorRepeat(KeyValueGet("sit"), "", PASSIVE|ACTIVE, 96, TWO_PI, 1);
}
sensor(integer num) {
llSensorRemove();
osNpcSit(KeyValueGet("key"), llDetectedKey(0), OS_NPC_SIT_NOW);
TimerEvent(TIMER);
}
no_sensor(){
wasKeyValueDelete("sit");
state ProcessNPCLine;
}
timer() {
wasKeyValueDelete("sit");
state ProcessNPCLine;
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit(){
TimerEvent(0.0);
}
}
state stand {
state_entry() {
// DEBUG("state stand");
osNpcStand(KeyValueGet("key"));
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
}
state animate {
state_entry() {
// DEBUG("state animate");
if(llGetInventoryType(KeyValueGet("an")) == INVENTORY_ANIMATION) osNpcPlayAnimation(KeyValueGet("key"), KeyValueGet("an"));
TimerEvent((float) KeyValueGet("at"));
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
timer() {
if(llGetInventoryType(KeyValueGet("an")) == INVENTORY_ANIMATION) osNpcStopAnimation(KeyValueGet("key"), KeyValueGet("an"));
wasKeyValueDelete("an");
wasKeyValueDelete("at");
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
state delete {
state_entry() {
// DEBUG("state delete");
osNpcRemove(KeyValueGet("key"));
}
link_message(integer sender, integer num, string str, key id) {
if(str == "@npc_start")
{
state NPCGo;
}
}
// No on_rez or changed event needed, the only way out is a link message
}
state walk {
state_entry() {
if (NPCWalkOption & OS_NPC_LAND_AT_TARGET ) {
NPCStart(FLY);
} else if (NPCWalkOption & OS_NPC_RUNNING ) {
NPCStart(RUN);
} else {
NPCStart(WALK);
}
if (Sensor) {
// DEBUG("Sensor on");
llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches.
}
// notecard is stored as offsets from this box with relative addressing. Convert to absolute
if (relAbs == "Relative"){
vDestPos += llGetPos();
}
// DEBUG("rez:" + (string) vDestPos);
iWaitCounter = WAIT; // wait 60 seconds to get to a destination.
osNpcMoveToTarget(KeyValueGet("key"), vDestPos, NPCWalkOption);
TimerEvent(TIMER);
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
state ProcessNPCLine;
}
timer() {
if (--iWaitCounter)
if (llVecDist(osNpcGetPos(KeyValueGet("key")), vDestPos) > MAXDIST) return;
if (NPCWalkOption & OS_NPC_LAND_AT_TARGET ) {
NPCStart(STAND);
} else if (NPCWalkOption & OS_NPC_RUNNING ) {
NPCStart(STAND);
} else {
NPCStart(STAND);
}
state ProcessNPCLine;
}
sensor(integer n) {
ProcessSensor(n);
}
no_sensor(){
ProcessSensor(0);
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
state wander
{
state_entry() {
// DEBUG("state wander");
if (Sensor)
{
// DEBUG("Sensor on");
llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches.
}
// !!! what sets vDestPos to start with?
vWanderPos = vDestPos + CirclePoint((float)KeyValueGet("wd"));
// notecard is stored as offsets from this box with relative addressing. Convert to absolute
if (relAbs == "Relative"){
vWanderPos += llGetPos();
}
fTimerVal = WANDERTIME; // default time to pause after each wander
if (WANDERRAND)
fTimerVal = llFrand(WANDERTIME); // override, they want random times
NPCStart(WALK);
// DEBUG("Wander to:" + (string) vWanderPos);
osNpcMoveToTarget(KeyValueGet("key"), vWanderPos, NPCWalkOption);
iWaitCounter = WAIT; // wait 60 seconds to get to a destination.
TimerEvent(TIMER); // first time we wait for the short timer.
}
link_message(integer sender, integer num, string str, key id) {
ProcessLink(str);
NPCStart(STAND);
state ProcessNPCLine;
}
timer() {
if (--iWaitCounter) // wait 60 seconds to get to a destination.
if (llVecDist(osNpcGetPos(KeyValueGet("key")), vWanderPos) > MAXDIST) return;
// see if wander counter == 0, if so, stop walking, go to stand and process next line
if(KeyValueGet("wc") == "0") {
wasKeyValueDelete("wc");
wasKeyValueDelete("wd");
NPCStart(STAND);
state ProcessNPCLine;
}
// subtract 1 from the wander counter
KeyValueSet("wc", (string)((integer)KeyValueGet("wc")-1));
NPCStart(STAND);
state wanderhold;
}
sensor(integer n) {
ProcessSensor(n);
}
no_sensor() {
ProcessSensor(0);
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
state wanderhold
{
state_entry(){
// now that we have reached a wander spot, slow the timer down to the desired value
TimerEvent(fTimerVal);
if (Sensor)
{
// DEBUG("Sensor on");
llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches.
}
}
timer() {
state wander;
}
sensor(integer n){
ProcessSensor(n);
}
no_sensor(){
ProcessSensor(0);
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit() {
TimerEvent(0.0);
}
}
// @pause=10 will stand for 10 seconds
state pause {
state_entry() {
// DEBUG("state pause");
NPCStart(STAND);
if (Sensor)
{
// DEBUG("Sensor on");
llSensor("","",AGENT,RANGE,TWO_PI); // sensor survive state switches.
}
TimerEvent((float)KeyValueGet("pause"));
}
link_message(integer sender, integer num, string str, key id){
ProcessLink(str);
state ProcessNPCLine;
}
timer() {
NPCStart(STAND);
wasKeyValueDelete("pause");
state ProcessNPCLine;
}
sensor(integer n)
{
ProcessSensor(n);
}
no_sensor()
{
ProcessSensor(0);
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
state_exit()
{
TimerEvent(0.0);
}
}
// @stop makes the NPC stand there. You have to linkmessage to get moving again
state stop {
state_entry() {
NPCStart(STAND);
}
link_message(integer sender, integer num, string str, key id){
ProcessLink(str);
state ProcessNPCLine;
}
changed(integer change) {
if(change & CHANGED_REGION_START)
state NPCGo;
}
on_rez(integer num) {
llResetScript();
}
}
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
09.12.2023, 13:29
(Dieser Beitrag wurde zuletzt bearbeitet: 09.12.2023, 13:38 von Leora Jacobus.)
Suchet so werdet ihr finden! Uff das hat gedauert! und das zu LESEN und zu KAPIEREN wird nochmal dauern!
https://www.outworldz.com/Opensim/posts/NPC/Notes.htm
Und je mehr ich lese, desto weniger verstehe ich! - Vielleicht wird DIES mehr bringen?
https://sl.governormarley.com/?p=5062
Arbeitet von Euch denn keiner mit NPCs?
Gibt es nirgendwo eine Anleitung für DUMMIES?
Beiträge: 1.547
Themen: 74
Thanks Received: 786 in 337 posts
Thanks Given: 377
Registriert seit: May 2013
09.12.2023, 16:54
(Dieser Beitrag wurde zuletzt bearbeitet: 09.12.2023, 17:13 von Mareta Dagostino.)
Dein erster Link die Anleitung für ein Script, was beim Steuern von NPC helfen soll. Falls du das Script hast, schön. Dein zweiter Link enthält Links zu einem vierteiligen YouTube-Tutorial. Englischsprachig eingesprochene Filme als "Online-Schulungen" ignoriere ich beruflich, dann tue ich mir das privat erst recht nicht an => über die Qualität möchte ich mich daher hier nicht äußern. Beim stichprobenweisen Anklicken habe ich Quellcode gesehen, es scheint also eher ein Programmier-Tutorial zu sein. (Klar, die Motivation der Tutorial-Ersteller ist nachvollziehbar: Geschriebene Blogs erzeugen weniger finanziellen Rücklauf als vielgeklickte YouTube-Filmchen...)
Die Frage stellt sich für dich, was willst du erreichen? Willst du lernen NPC zu programmieren? Wohl vermutlich eher nicht. Dann wird dir nur bleiben, ein gut dokumentiertes Fertigscript zu finden, um die NPC zu bewegen. Und wenn sie mehr können sollen, als mit den Default-Animationen von einem Koordinatenpunkt zum nächsten zu laufen/fliegen/sitzen, dann braucht es zusätzlich passende Animationen. Wie die Tanzpartner in dem in OpenSim weit verbreiteten Tanzball von Áine Caoimhe.
EDIT1: Hier sind zwei Links mit u.a. vielen NPC Scripten von Ferd Frederix. Vielleicht ist ja das Script dabei, was in der Anleitung aus deinem ersten Link erklärt wird.
https://www.outworldz.com/cgi/freescript...tegory=NPC
https://www.outworldz.com/cgi/freescript...nSim%20NPC
EDIT2: Einstiegsseite der Anleitung aus deinem ersten Link: https://www.outworldz.com/Opensim/posts/NPC/
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
09.12.2023, 18:02
(Dieser Beitrag wurde zuletzt bearbeitet: 09.12.2023, 18:05 von Leora Jacobus.)
Danke Mareta!!
Natürlich will ich nix programmieren lernen. Es soll nur ein NPC in MEINEM Outfit ein paar Schritte gehgen, pausieren und was im Textchat sagen. That's all! Und es hatte ja schonmal geklappt so etwa vor 10 Jahren. Ich habe nach endlosem Stöbern auch noch etwas gefunden, wo es endlich mal für Doofies wie mich erklärt wird:
Wie man den Recirder/Player BAUT
https://www.outworldz.com/Opensim/posts/...roller.htm
und wie man ihn BENUTZT
https://www.outworldz.com/Opensim/posts/NPC/default.htm
anschaulich mit vielen Bildern. ... nun muß es nur noch klappen!
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
09.12.2023, 19:40
(Dieser Beitrag wurde zuletzt bearbeitet: 09.12.2023, 19:42 von Leora Jacobus.)
Und es klappt NICHT! Es ist zum Haare-Ausraufen!
Der Script der drin war - und ja mal funktioniert hatte - NIX!
Dann hab ich den reingesetzt auf den das Link zeigte (davon den obersten) - nix!
Now download this script and save it to disk. ...
https://www.outworldz.com/cgi/freescripts.plx?ID=27
Das Dumme ist das Link zeigt auf eine ganze Seite voller Scrifts aber im Artikel wird im Beispiel einer vom 16.08.2014 gezeigt und die auf der Seite sind alle älter.
Ich kann mir nur vorstellen daß irgendwie die OpenSimVersion die Craft verwendet keine NPCs zuläßt und daß in OSGriod in der Sandbox solche Scripts auch nicht erlaubt sind.
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
(05.12.2023, 22:43)Jupiter Rowland schrieb: Für NPCs, glaube ich, kann man die Sachen von Áine Caoimhe empfehlen. Die bekommst du auf ihrer alten Sim; die ist online, auch wenn da was anderes steht.
Da bin ich gerade mal hingeflogen.
Da gibt es gute Animationen aber in Sachen NPC nur eine Kugel mit der man sie killen kann.
Beiträge: 1.547
Themen: 74
Thanks Received: 786 in 337 posts
Thanks Given: 377
Registriert seit: May 2013
(09.12.2023, 19:40)Leora Jacobus schrieb: Der Script der drin war - und ja mal funktioniert hatte - NIX!
Dann hab ich den reingesetzt auf den das Link zeigte (davon den obersten) - nix!
https://www.outworldz.com/cgi/freescripts.plx?ID=27
Das Dumme ist das Link zeigt auf eine ganze Seite voller Scrifts aber im Artikel wird im Beispiel einer vom 16.08.2014 gezeigt und die auf der Seite sind alle älter.
Das oberste (# 6) ist das älteste. Das neueste am verlinkten Ort ist "file # 26. NPC Recorder Script V5.2.lsl" von 2015 oder 2016, je nachdem welchen Kommentarzeilen du glauben willst.
https://www.outworldz.com/lib/All%20In%2...20V5.2.lsl
Jetzt ist 2016 auch nicht gerade vorgestern, vielleicht braucht man in einer aktuelleren OpenSim Version 9.x auch eine aktualisierte Script-Version, die anderswo liegt oder inworld erfragt werden muss.
Zitat:Ich kann mir nur vorstellen daß irgendwie die OpenSimVersion die Craft verwendet keine NPCs zuläßt und daß in OSGriod in der Sandbox solche Scripts auch nicht erlaubt sind.
Das kann natürlich durchaus sein, in der OpenSim Konfiguration kann man NPC erlauben oder verbieten. Oder nur den Region-Ownern erlauben usw...
Beiträge: 616
Themen: 54
Thanks Received: 145 in 83 posts
Thanks Given: 359
Registriert seit: Jan 2012
(09.12.2023, 22:48)Mareta Dagostino schrieb: ...
Jetzt ist 2016 auch nicht gerade vorgestern, vielleicht braucht man in einer aktuelleren OpenSim Version 9.x auch eine aktualisierte Script-Version, die anderswo liegt oder inworld erfragt werden muss.
Zitat:Ich kann mir nur vorstellen daß irgendwie die OpenSimVersion die Craft verwendet keine NPCs zuläßt und daß in OSGriod in der Sandbox solche Scripts auch nicht erlaubt sind.
Das kann natürlich durchaus sein, in der OpenSim Konfiguration kann man NPC erlauben oder verbieten. Oder nur den Region-Ownern erlauben usw...
Du hast Recht! Ich werde mal versuchen, den gr0ßen Meister Ferd Frederix zi kontaktieren. Das hab ich irgendwann schonmal gemacht und fand ihn sehr nett und hilfsbereit. Wenn das auch nix nützt kontaktier ich mal den Obermufti von Craftworld. Dem zahle ich immerhin alle 6 Moinate 50 €
|