From: Chris Koeritz Date: Mon, 14 May 2012 03:13:05 +0000 (-0400) Subject: fixed names back to .txt, since we cannot get second inventory to X-Git-Tag: 2.140.90~1343 X-Git-Url: https://feistymeow.org/gitweb/?a=commitdiff_plain;h=cb9011b7dd78ac93d48a871a9fdda062c9181138;p=feisty_meow.git fixed names back to .txt, since we cannot get second inventory to generate the script names with lsl endings. too much work to only rename lsl scripts without accidentally renaming some notecards, and to do it every time there's a huffotronic updater being updated? yuck. --- diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.lsl deleted file mode 100755 index b7be286c..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.lsl +++ /dev/null @@ -1,156 +0,0 @@ - -// huffware script: FPS color changer, by fred huffhines -// -// a freebie script by eltee statosky supplied inspiration for this script. -// we have re-used his color scheme, but rewritten this for our needs. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer SHOW_TITLE = FALSE; - // if this is true, a title is set above the object. - -//hmmm: this max fps value used to compute a percentage may be totally bogus. -// highest i've seen is 55 or so in opensim. used to be highest in second life -// was 45 or something. seems unknowable so far. -float MAX_SIM_FPS = 60.0; - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. - llSetTimerEvent(4.0); - } - - timer() { - float fps = llGetRegionFPS(); - vector sim_color; - if (fps > 50) sim_color = <0.5, 1.0, 0.5>; - else if (fps > 40) sim_color = <0.75, 0.75, 0>; - else if (fps > 30) sim_color = <1.0, 0.5, 0.5>; - else sim_color = <0.5, 0.0, 0.0>; - llSetColor(sim_color, ALL_SIDES); - if (SHOW_TITLE) { - integer left_part = (integer)fps; // left of decimal point. - integer right_part = (integer)(llRound((fps - (integer)fps) * 10.0)); - float simplified_fps = (float)left_part + ((float)right_part / 10.0); - llSetText(llGetRegionName() + " " - + (string)left_part + "." + (string)right_part - + " FPS (" - + (string)llRound(simplified_fps / MAX_SIM_FPS * 100.0) - + "%)", - sim_color, 1.0); - } else { - llSetText("--", <0.0, 0.0, 0.0>, 0.0); - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.txt new file mode 100755 index 00000000..b7be286c --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/FPS_color_changer_v2.4.txt @@ -0,0 +1,156 @@ + +// huffware script: FPS color changer, by fred huffhines +// +// a freebie script by eltee statosky supplied inspiration for this script. +// we have re-used his color scheme, but rewritten this for our needs. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer SHOW_TITLE = FALSE; + // if this is true, a title is set above the object. + +//hmmm: this max fps value used to compute a percentage may be totally bogus. +// highest i've seen is 55 or so in opensim. used to be highest in second life +// was 45 or something. seems unknowable so far. +float MAX_SIM_FPS = 60.0; + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. + llSetTimerEvent(4.0); + } + + timer() { + float fps = llGetRegionFPS(); + vector sim_color; + if (fps > 50) sim_color = <0.5, 1.0, 0.5>; + else if (fps > 40) sim_color = <0.75, 0.75, 0>; + else if (fps > 30) sim_color = <1.0, 0.5, 0.5>; + else sim_color = <0.5, 0.0, 0.0>; + llSetColor(sim_color, ALL_SIDES); + if (SHOW_TITLE) { + integer left_part = (integer)fps; // left of decimal point. + integer right_part = (integer)(llRound((fps - (integer)fps) * 10.0)); + float simplified_fps = (float)left_part + ((float)right_part / 10.0); + llSetText(llGetRegionName() + " " + + (string)left_part + "." + (string)right_part + + " FPS (" + + (string)llRound(simplified_fps / MAX_SIM_FPS * 100.0) + + "%)", + sim_color, 1.0); + } else { + llSetText("--", <0.0, 0.0, 0.0>, 0.0); + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.lsl deleted file mode 100755 index bb809fd4..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.lsl +++ /dev/null @@ -1,834 +0,0 @@ - -// huffware script: freeview modified by fred huffhines (see original license below). -// -// my changes are licensed this way: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// -// fred's changes include: -// + assorted tweaks that i have since forgotten the details about. -// + set the freeview to startup as a picture viewer, since that's my most common usage. - -////////////// -// original author info and licensing: -//FreeView 1.2 WebGuide (revision 4) - By CrystalShard Foo -//Multifunctional Picture viewer and Video control script with webguide support -//This script is distributed for free and must stay that way. -// *** If you wish to give/sell a product using this script, *** -// *** THEN THE SCRIPT MUST REMAIN FULL-PERM AND FREE. *** -// *** Failure to do so will REVOKE your right to use it! *** -//Help for using this script can be obtained at: http://www.slguide.com/help -//Feel free to modify this script and post your improvement. Leave the credits intact but feel free to add your name at its bottom. -//Whats new: -//- Now using FULL_BRIGHT instead of PRIM_MATERIAL_LIGHT for the screen display -//- Added an ownership-change code to handle cases where FreeView gets deeded to group post Video Init. -//- Renamed WebGuide to TV-Guide to reflect what this thing does better. -//- Added a 'Fix Scale' button to Picture mode to help against user texture-scale changes. -//- Additional minor help-tips and code improvements -//Enjoy! -////////////// - - -//Constants -integer PICTURE_ROTATION_TIMER = 30; //In whole seconds - -integer DISPLAY_ON_SIDE = ALL_SIDES; //Change this to change where the image will be displayed - -key VIDEO_DEFAULT = "71b8ff26-087d-5f44-285b-d38df2e11a81"; //Test pattern - Used as default video texture when one is missing in parcel media -key BLANK = "5748decc-f629-461c-9a36-a35a221fe21f"; //Blank texture - Used when there are no textures to display in Picture mode -string NOTECARD = "bookmarks"; //Used to host URL bookmarks for video streams - -integer VIDEO_BRIGHT = TRUE; //FULL_BRIGHT status for Video -integer PICTURE_BRIGHT = TRUE; //FULL_BRIGHT status for Picture - -integer REMOTE_CHANNEL = 9238742; - -integer EXTERNAL_TOUCH_CHANNEL = 1327; - // used by other prims to tell the viewer prim that the avatar has clicked on them. - -integer mode = 0; //Freeview mode. - //Mode 0 - Power off - //Mode 1 - Picture viewer - //Mode 2 - Video - -integer listenHandle = -1; //Dialog menu listen handler -integer listenUrl = -1; //listen handler for channel 1 for when a URL is being added -integer listenTimer = -1; //Timer variable for removing all listeners after 2 minutes of listener inactivity -integer listenRemote = -1; //listen handler for the remote during initial setup -integer encryption = 0; -integer numberofnotecardlines = 0; //Stores the current number of detected notecard lines. -integer notecardline = 0; //Current notecard line - -integer loop_image = FALSE; //Are we looping pictures with a timer? (picture mode) -integer current_texture = 0; //Current texture number in inventory being displayed (picture mode) -integer chan; //llDialog listen channel -integer notecardcheck = 0; -key video_texture; //Currently used video display texture for parcel media stream - -string moviename; -string tempmoviename; -key notecardkey = NULL_KEY; -key tempuser; //Temp key storge variable -string tempurl; //Temp string storge variable - -integer isGroup = TRUE; -key groupcheck = NULL_KEY; -key last_owner; -key XML_channel; - -pictures() //Change mode to Picture Viewer -{ - //Initilize variables - - //Change prim to Light material while coloring face 0 black to prevent light-lag generation. - llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_NONE, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <1,1,1>, 1.0, PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, PICTURE_BRIGHT]); - - integer check = llGetInventoryNumber(INVENTORY_TEXTURE); - - if(check == 0) - { - report("No pictures found."); - llSetTexture(BLANK,DISPLAY_ON_SIDE); - return; - } - else - if(current_texture > check) - //Set to first texture if available - current_texture = 0; - - display_texture(current_texture); -} - -video() //Change mode to Video -{ - //Change prim to Light material while coloring face 0 black to prevent light-lag generation. - llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_NONE, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <1,1,1>, 1.0, PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, VIDEO_BRIGHT, PRIM_TEXTURE, DISPLAY_ON_SIDE, "62dc73ca-265f-7ca0-0453-e2a6aa60bb6f", llGetTextureScale(DISPLAY_ON_SIDE), llGetTextureOffset(DISPLAY_ON_SIDE), llGetTextureRot(DISPLAY_ON_SIDE)]); - - report("Video mode"+moviename+": Stopped"); - if(finditem(NOTECARD) != -1) - tempuser = llGetNumberOfNotecardLines(NOTECARD); - video_texture = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]),0); - if(video_texture == NULL_KEY) - { - video_texture = VIDEO_DEFAULT; - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE,VIDEO_DEFAULT]); - llSay(0,"No parcel media texture found. Setting texture to default: "+(string)VIDEO_DEFAULT); - if(llGetLandOwnerAt(llGetPos()) != llGetOwner()) - llSay(0,"Error: Cannot modify parcel media settings. "+llGetObjectName()+" is not owned by parcel owner."); - } - - llSetTexture(video_texture,DISPLAY_ON_SIDE); -} - -off() -{ - report("Click to power on."); - llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_LOW, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <0.1,0.1,0.1>, 1.0,PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, FALSE, PRIM_TEXTURE, DISPLAY_ON_SIDE, BLANK, llGetTextureScale(DISPLAY_ON_SIDE), llGetTextureOffset(DISPLAY_ON_SIDE), llGetTextureRot(DISPLAY_ON_SIDE)]); -} - -integer finditem(string name) //Finds and returns an item's inventory number -{ - integer i; - for(i=0;i 0) - header = "("+(string)(current_texture+1)+"/"+(string)check+") "+llGetInventoryName(INVENTORY_TEXTURE,current_texture); - else - header = "No pictures found."; - llDialog(id,"** Monitor Control **\n Picture Viewer mode\n- Image browser\n- "+header,["Back","Next","Menu"],chan); - extendtimer(); -} - -report(string str) -{ - llSetObjectDesc(str); -} - -extendtimer() //Add another 2 minute to the Listen Removal timer (use when a Listen event is triggered) -{ - if(listenHandle == -1) - listenHandle = llListen(chan,"","",""); - listenTimer = (integer)llGetTime() + 120; - if(loop_image == FALSE) - llSetTimerEvent(45); -} - -config(key id) //Configuration menu -{ - extendtimer(); - llDialog(id,"Current media URL:\n"+llList2String(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL]),0)+"\nTip: If the picture is abit off, try 'Align ON'",["Set URL","Align ON","Align OFF","Menu","Set Remote"],chan); -} - -tell_remote(string str) -{ - llShout(REMOTE_CHANNEL,llXorBase64Strings(llStringToBase64((string)encryption + str), llStringToBase64((string)encryption))); -} - -menu(key id) //Dialog menus for all 3 modes -{ - list buttons = []; - string title = "** Monitor control **"; - - extendtimer(); - - if(mode != 0) - { - if(mode == 1) //Pictures menu - { - title+="\n Picture Viewer mode"; - buttons+=["Browse"]; - if(loop_image == FALSE) - buttons+=["Loop"]; - else - buttons+=["Unloop"]; - buttons+=["Video","Power off","Help","Fix scale"]; - } - else //Video menu - { - title+="\n Video display mode\n"+moviename+"\nTip:\nClick 'TV Guide' to view the Online bookmarks."; - buttons+=["Pictures","Configure","Power off","Loop","Unload","Help","Play","Stop","Pause","TV Guide","Bookmarks","Set URL"]; - } - } - else - buttons += ["Pictures","Video","Help"]; - - llDialog(id,title,buttons,chan); -} - -display_texture(integer check) //Display texture and set name in description (picture mode) -{ //"Check" holds the number of textures in contents. The function uses "current_texture" to display. - string name = llGetInventoryName(INVENTORY_TEXTURE,current_texture); - llSetTexture(name,DISPLAY_ON_SIDE); - report("Showing picture: "+name+" ("+(string)(current_texture+1)+"/"+(string)check+")"); -} - - -next() //Change to next texture (picture mode) -{ //This function is used twice - by the menu and timer. Therefor, it is a dedicated function. - current_texture++; - integer check = llGetInventoryNumber(INVENTORY_TEXTURE); - if(check == 0) - { - llSetTexture(BLANK,DISPLAY_ON_SIDE); - current_texture = 0; - report("No pictures found."); - return; - } - if(check == current_texture) - current_texture = 0; - - display_texture(check); - return; -} - -////////////// -// from hufflets... - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - llListen(EXTERNAL_TOUCH_CHANNEL, "", NULL_KEY, ""); - // we listen on our touch channel in all cases and in all states. this allows us - // to always pass along the user's touch from other prims to run the menus. - chan = (integer)llFrand(1000) + 1000; //Pick a random listen channel for the listener - if(PICTURE_ROTATION_TIMER <= 0) //Ensure the value is no less or equal 0 - PICTURE_ROTATION_TIMER = 1; - llListenRemove(listenHandle); - listenHandle = -1; - last_owner = llGetOwner(); - groupcheck = llRequestAgentData(llGetOwner(),DATA_NAME); - off(); - llOpenRemoteDataChannel(); - // fred's changes to start up in picture viewing looper. - mode = 1; // picture viewing. - pictures(); // show the pictures. - loop_image = TRUE; - llSetTimerEvent(PICTURE_ROTATION_TIMER); // keep showing new pics. - } - - on_rez(integer i) - { - llSay(0,"Welcome to FreeView - your free, open-source television!"); - llResetScript(); - } - - touch_start(integer total_number) - { - //------------------------------------------------------------------------------- - //Listen only to owner or group member. Edit this code to change access controls. - if(llDetectedKey(0) != llGetOwner() && llDetectedGroup(0) == FALSE) - return; - //------------------------------------------------------------------------------- - - menu(llDetectedKey(0)); - } - - changed(integer change) - { - if(change == CHANGED_INVENTORY) //If inventory change - { - if(mode == 1) //If picture mode - { - integer check = llGetInventoryNumber(INVENTORY_TEXTURE); - if(check != 0) - { - current_texture = 0; - display_texture(check); - } - else - { - llSetTexture(BLANK,DISPLAY_ON_SIDE); - report("No pictures found."); - } - } - else - if(mode == 2) //If video mode - if(finditem(NOTECARD) != -1) //And bookmarks notecard present - if(notecardkey != llGetInventoryKey(NOTECARD)) - tempuser = llGetNumberOfNotecardLines(NOTECARD); //Reload number of lines - } - else if(change == CHANGED_OWNER) - { - isGroup = TRUE; - last_owner = llGetOwner(); - groupcheck = llRequestAgentData(llGetOwner(),DATA_NAME); - - if(mode == 2) - { - llSay(0,"Detected change in ownership. Attempting to obtain current parcel media texture..."); - video(); - } - } - } - - listen(integer channel, string name, key id, string message) - { - if ( (channel == EXTERNAL_TOUCH_CHANNEL) && is_prefix(message, "touched")) { - // pretend we got touched by the av. - message = llDeleteSubString(message, 0, 6); - menu((key)message); - return; - } - if(message == "Pictures") - { - if(mode == 2) - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); - pictures(); - mode = 1; - menu(id); - return; - } - if(message == "Video") - { - video(); - mode = 2; - menu(id); - return; - } - if(message == "Power off") - { - if(mode == 2) - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_UNLOAD]); - off(); - mode = 0; - return; - } - if(message == "Help") - { - llSay(0,"Help documentation is available at: http://www.slguide.com/help"); - if(isGroup) - { - if(id == NULL_KEY) - { - llSay(0,"FreeView cannot load help pages while set to group without the remote."); - llSay(0,"For further assistance, please consult: http://slguide.com/help"); - } - else - tell_remote("HELP"+(string)id+(string)XML_channel); - } - else - llLoadURL(id,"Help pages for FreeView","http://www.slguide.com?c="+(string)XML_channel+"&help=1"); - } - if(mode == 1) - { - if(message == "Browse") - { - loop_image = FALSE; - browse(id); - return; - } - if(message == "Next") - { - extendtimer(); - next(); - browse(id); - } - if(message == "Back") - { - extendtimer(); - current_texture--; - integer check = llGetInventoryNumber(INVENTORY_TEXTURE); - if(check == 0) - { - llSetTexture(BLANK,DISPLAY_ON_SIDE); - current_texture = 0; - report("No pictures found."); - return; - } - if(current_texture < 0) - current_texture = check - 1; - - display_texture(check); - - browse(id); - return; - } - if(message == "Menu") - { - menu(id); - return; - } - if(message == "Loop") - { - llSetTimerEvent(PICTURE_ROTATION_TIMER); - loop_image = TRUE; - llOwnerSay("Picture will change every "+(string)PICTURE_ROTATION_TIMER+" seconds."); - return; - } - if(message == "Unloop") - { - loop_image = FALSE; - llOwnerSay("Picture loop disabled."); - return; - } - if(message == "Fix scale") - { - llSay(0,"Setting display texture to 1,1 repeats and 0,0 offset."); - llScaleTexture(1, 1, DISPLAY_ON_SIDE); - llOffsetTexture(0, 0, DISPLAY_ON_SIDE); - return; - } - } - if(mode == 2) - { - if(channel == REMOTE_CHANNEL) - { - if(encryption == 0) - encryption = (integer)message; - llListenRemove(listenRemote); - listenRemote = -1; - llSay(0,"Remote configured ("+(string)id+")"); - } - - if(message == "TV Guide") - { - if(isGroup) - { - if(!encryption) - { - llSay(0,"** Error - This FreeView object has been deeded to group. You must use a Remote control to open the TV Guide."); - llSay(0,"You can set up the remote control from the Video -> Configuration menu. Please refer to the notecard for further assistance."); - return; - } - tell_remote((string)id+(string)XML_channel+(string)llGetOwner()); - } - else - llLoadURL(id, "Come to the Guide to Start Your Viewer Playing!", "http://slguide.com/index.php?v=" + (string)llGetKey() + "&c=" + (string)XML_channel + "&o=" + (string)llGetOwner() + "&"); - return; - } - - string header = "Video mode"+moviename+": "; - - if(message == "<< Prev") - { - notecardline--; - if(notecardline < 0) - notecardline = numberofnotecardlines - 1; - tempuser = id; - llGetNotecardLine(NOTECARD,notecardline); - return; - } - if(message == "Next >>") - { - notecardline++; - if(notecardline >= numberofnotecardlines) - notecardline = 0; - tempuser = id; - llGetNotecardLine(NOTECARD,notecardline); - return; - } - if(message == "Use") - { - if(tempurl == "** No URL specified! **") - tempurl = ""; - seturl(tempurl,id); - return; - } - - if(message == "Menu") - { - menu(id); - return; - } - if(message == "Configure") - { - config(id); - return; - } - if(message == "Bookmarks") - { - if(notecardcheck != -1) - { - llDialog(id,"Error: No valid bookmark data found in notecard '"+NOTECARD+"'.",["Menu"],chan); - return; - } - if(finditem(NOTECARD) != -1) - { - tempuser = id; - if(numberofnotecardlines < notecardline) - notecardline = 0; - llGetNotecardLine(NOTECARD,notecardline); - } - else - llDialog(id,"Error: No notecard named "+NOTECARD+" found in contents.",["Menu"],chan); - return; - } - - if(llGetLandOwnerAt(llGetPos()) != llGetOwner()) //If we do not have permissions to actually do the following functions - { - llSay(0,"Error: Cannot modify parcel media settings. "+llGetObjectName()+" is not owned by parcel owner."); - menu(id); - return; //Abort - } - - if(listenUrl != -1 && channel == 1) //Incoming data from "Set URL" command (user spoke on channel 1) - { - llListenRemove(listenUrl); - listenUrl = -1; - tempmoviename = ""; - seturl(message,id); - } - if(message == "Play") - { - report(header+"Playing"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PLAY]); - return; - } - if(message == "Stop") - { - report(header+"Stopped"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); - return; - } - if(message == "Pause") - { - report(header+"Paused"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PAUSE]); - return; - } - if(message == "Unload") - { - report(header+"Stopped"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_UNLOAD]); - return; - } - if(message == "Loop") - { - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_LOOP]); - return; - } - //URL , Auto-Scale, - if(message == "Set URL") - { - report(header+"Stopped"); - listenUrl = llListen(1,"",id,""); - llDialog(id,"Please type the URL of your choice with /1 in thebegining. For example, /1 www.google.com",["Ok"],938); - return; - } - if(message == "Align ON") - { - report(header+"Stopped"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AUTO_ALIGN,TRUE]); - menu(id); - return; - } - if(message == "Align OFF") - { - report(header+"Stopped"); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AUTO_ALIGN,FALSE]); - menu(id); - return; - } - if(message == "Set Remote") - { - llSay(0,"Configuring remote..."); - encryption = 0; - llListenRemove(listenRemote); - listenRemote = llListen(REMOTE_CHANNEL,"","",""); - llSay(REMOTE_CHANNEL,"SETUP"); - } - } - } - - dataserver(key queryid, string data) - { - if(queryid == groupcheck) //Test if object is deeded to group - { - groupcheck = NULL_KEY; - isGroup = FALSE; - return; - } - - if(queryid == tempuser) //If just checking number of notecard lines - { - numberofnotecardlines = (integer)data; - notecardkey = llGetInventoryKey(NOTECARD); - notecardcheck = 0; - llGetNotecardLine(NOTECARD,notecardcheck); - return; - } - if(notecardcheck != -1) - { - if(data != EOF) - { - if(data == "") - { - notecardcheck++; - llGetNotecardLine(NOTECARD,notecardcheck); - } - else - { - notecardcheck = -1; - return; - } - } - else - return; - } - - if(data == "" && notecardline < numberofnotecardlines) //If user just pressed "enter" in bookmarks, skip - { - notecardline++; - llGetNotecardLine(NOTECARD,notecardline); - return; - } - - if(data == EOF) - { - notecardline = 0; - llGetNotecardLine(NOTECARD,notecardline); - return; - } - list parsed = llParseString2List(data,["|","| "," |"," | "],[]); //Ensure no blank spaces before "http://". - string name = llList2String(parsed,0); - tempurl = llList2String(parsed,1); - if(tempurl == "") - tempurl = "** No URL specified! **"; - - tempmoviename = name; - - llDialog(tempuser,"Bookmarks notecard ("+(string)(notecardline+1)+"/"+(string)numberofnotecardlines+")\n"+name+" ("+mediatype(llList2String(llParseString2List(tempurl,["."],[]),-1))+")\n"+tempurl,["<< Prev","Use","Next >>","Menu"],chan); - } - - remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) - { - if (type == REMOTE_DATA_CHANNEL) - { - XML_channel = channel; - } - else if(type == REMOTE_DATA_REQUEST) - { - list media_info = llParseString2List(sval, ["|"], []); - tempmoviename = llList2String(media_info,0); - seturl(llList2String(media_info,1),NULL_KEY); - llRemoteDataReply(channel, message_id, sval, 1); - } - } - - timer() - { - if(llGetTime() > listenTimer) //If listener time expired... - { - llListenRemove(listenHandle); //Remove listeneres. - llListenRemove(listenUrl); - llListenRemove(listenRemote); - listenHandle = -1; - listenUrl = -1; - listenRemote = -1; - listenTimer = -1; - if(loop_image == FALSE || mode != 1) //If we're not looping pictures or are in picture mode at all - llSetTimerEvent(0.0); //Remove timer - } - - if(loop_image == TRUE && mode == 1) //If we're looping pictures and and we're in picture mode... - next(); //Next picture - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.txt new file mode 100755 index 00000000..bb809fd4 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/FreeView_v1.8.txt @@ -0,0 +1,834 @@ + +// huffware script: freeview modified by fred huffhines (see original license below). +// +// my changes are licensed this way: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// +// fred's changes include: +// + assorted tweaks that i have since forgotten the details about. +// + set the freeview to startup as a picture viewer, since that's my most common usage. + +////////////// +// original author info and licensing: +//FreeView 1.2 WebGuide (revision 4) - By CrystalShard Foo +//Multifunctional Picture viewer and Video control script with webguide support +//This script is distributed for free and must stay that way. +// *** If you wish to give/sell a product using this script, *** +// *** THEN THE SCRIPT MUST REMAIN FULL-PERM AND FREE. *** +// *** Failure to do so will REVOKE your right to use it! *** +//Help for using this script can be obtained at: http://www.slguide.com/help +//Feel free to modify this script and post your improvement. Leave the credits intact but feel free to add your name at its bottom. +//Whats new: +//- Now using FULL_BRIGHT instead of PRIM_MATERIAL_LIGHT for the screen display +//- Added an ownership-change code to handle cases where FreeView gets deeded to group post Video Init. +//- Renamed WebGuide to TV-Guide to reflect what this thing does better. +//- Added a 'Fix Scale' button to Picture mode to help against user texture-scale changes. +//- Additional minor help-tips and code improvements +//Enjoy! +////////////// + + +//Constants +integer PICTURE_ROTATION_TIMER = 30; //In whole seconds + +integer DISPLAY_ON_SIDE = ALL_SIDES; //Change this to change where the image will be displayed + +key VIDEO_DEFAULT = "71b8ff26-087d-5f44-285b-d38df2e11a81"; //Test pattern - Used as default video texture when one is missing in parcel media +key BLANK = "5748decc-f629-461c-9a36-a35a221fe21f"; //Blank texture - Used when there are no textures to display in Picture mode +string NOTECARD = "bookmarks"; //Used to host URL bookmarks for video streams + +integer VIDEO_BRIGHT = TRUE; //FULL_BRIGHT status for Video +integer PICTURE_BRIGHT = TRUE; //FULL_BRIGHT status for Picture + +integer REMOTE_CHANNEL = 9238742; + +integer EXTERNAL_TOUCH_CHANNEL = 1327; + // used by other prims to tell the viewer prim that the avatar has clicked on them. + +integer mode = 0; //Freeview mode. + //Mode 0 - Power off + //Mode 1 - Picture viewer + //Mode 2 - Video + +integer listenHandle = -1; //Dialog menu listen handler +integer listenUrl = -1; //listen handler for channel 1 for when a URL is being added +integer listenTimer = -1; //Timer variable for removing all listeners after 2 minutes of listener inactivity +integer listenRemote = -1; //listen handler for the remote during initial setup +integer encryption = 0; +integer numberofnotecardlines = 0; //Stores the current number of detected notecard lines. +integer notecardline = 0; //Current notecard line + +integer loop_image = FALSE; //Are we looping pictures with a timer? (picture mode) +integer current_texture = 0; //Current texture number in inventory being displayed (picture mode) +integer chan; //llDialog listen channel +integer notecardcheck = 0; +key video_texture; //Currently used video display texture for parcel media stream + +string moviename; +string tempmoviename; +key notecardkey = NULL_KEY; +key tempuser; //Temp key storge variable +string tempurl; //Temp string storge variable + +integer isGroup = TRUE; +key groupcheck = NULL_KEY; +key last_owner; +key XML_channel; + +pictures() //Change mode to Picture Viewer +{ + //Initilize variables + + //Change prim to Light material while coloring face 0 black to prevent light-lag generation. + llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_NONE, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <1,1,1>, 1.0, PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, PICTURE_BRIGHT]); + + integer check = llGetInventoryNumber(INVENTORY_TEXTURE); + + if(check == 0) + { + report("No pictures found."); + llSetTexture(BLANK,DISPLAY_ON_SIDE); + return; + } + else + if(current_texture > check) + //Set to first texture if available + current_texture = 0; + + display_texture(current_texture); +} + +video() //Change mode to Video +{ + //Change prim to Light material while coloring face 0 black to prevent light-lag generation. + llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_NONE, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <1,1,1>, 1.0, PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, VIDEO_BRIGHT, PRIM_TEXTURE, DISPLAY_ON_SIDE, "62dc73ca-265f-7ca0-0453-e2a6aa60bb6f", llGetTextureScale(DISPLAY_ON_SIDE), llGetTextureOffset(DISPLAY_ON_SIDE), llGetTextureRot(DISPLAY_ON_SIDE)]); + + report("Video mode"+moviename+": Stopped"); + if(finditem(NOTECARD) != -1) + tempuser = llGetNumberOfNotecardLines(NOTECARD); + video_texture = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]),0); + if(video_texture == NULL_KEY) + { + video_texture = VIDEO_DEFAULT; + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE,VIDEO_DEFAULT]); + llSay(0,"No parcel media texture found. Setting texture to default: "+(string)VIDEO_DEFAULT); + if(llGetLandOwnerAt(llGetPos()) != llGetOwner()) + llSay(0,"Error: Cannot modify parcel media settings. "+llGetObjectName()+" is not owned by parcel owner."); + } + + llSetTexture(video_texture,DISPLAY_ON_SIDE); +} + +off() +{ + report("Click to power on."); + llSetPrimitiveParams([PRIM_BUMP_SHINY, DISPLAY_ON_SIDE, PRIM_SHINY_LOW, PRIM_BUMP_NONE, PRIM_COLOR, DISPLAY_ON_SIDE, <0.1,0.1,0.1>, 1.0,PRIM_MATERIAL, PRIM_MATERIAL_PLASTIC, PRIM_FULLBRIGHT, DISPLAY_ON_SIDE, FALSE, PRIM_TEXTURE, DISPLAY_ON_SIDE, BLANK, llGetTextureScale(DISPLAY_ON_SIDE), llGetTextureOffset(DISPLAY_ON_SIDE), llGetTextureRot(DISPLAY_ON_SIDE)]); +} + +integer finditem(string name) //Finds and returns an item's inventory number +{ + integer i; + for(i=0;i 0) + header = "("+(string)(current_texture+1)+"/"+(string)check+") "+llGetInventoryName(INVENTORY_TEXTURE,current_texture); + else + header = "No pictures found."; + llDialog(id,"** Monitor Control **\n Picture Viewer mode\n- Image browser\n- "+header,["Back","Next","Menu"],chan); + extendtimer(); +} + +report(string str) +{ + llSetObjectDesc(str); +} + +extendtimer() //Add another 2 minute to the Listen Removal timer (use when a Listen event is triggered) +{ + if(listenHandle == -1) + listenHandle = llListen(chan,"","",""); + listenTimer = (integer)llGetTime() + 120; + if(loop_image == FALSE) + llSetTimerEvent(45); +} + +config(key id) //Configuration menu +{ + extendtimer(); + llDialog(id,"Current media URL:\n"+llList2String(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL]),0)+"\nTip: If the picture is abit off, try 'Align ON'",["Set URL","Align ON","Align OFF","Menu","Set Remote"],chan); +} + +tell_remote(string str) +{ + llShout(REMOTE_CHANNEL,llXorBase64Strings(llStringToBase64((string)encryption + str), llStringToBase64((string)encryption))); +} + +menu(key id) //Dialog menus for all 3 modes +{ + list buttons = []; + string title = "** Monitor control **"; + + extendtimer(); + + if(mode != 0) + { + if(mode == 1) //Pictures menu + { + title+="\n Picture Viewer mode"; + buttons+=["Browse"]; + if(loop_image == FALSE) + buttons+=["Loop"]; + else + buttons+=["Unloop"]; + buttons+=["Video","Power off","Help","Fix scale"]; + } + else //Video menu + { + title+="\n Video display mode\n"+moviename+"\nTip:\nClick 'TV Guide' to view the Online bookmarks."; + buttons+=["Pictures","Configure","Power off","Loop","Unload","Help","Play","Stop","Pause","TV Guide","Bookmarks","Set URL"]; + } + } + else + buttons += ["Pictures","Video","Help"]; + + llDialog(id,title,buttons,chan); +} + +display_texture(integer check) //Display texture and set name in description (picture mode) +{ //"Check" holds the number of textures in contents. The function uses "current_texture" to display. + string name = llGetInventoryName(INVENTORY_TEXTURE,current_texture); + llSetTexture(name,DISPLAY_ON_SIDE); + report("Showing picture: "+name+" ("+(string)(current_texture+1)+"/"+(string)check+")"); +} + + +next() //Change to next texture (picture mode) +{ //This function is used twice - by the menu and timer. Therefor, it is a dedicated function. + current_texture++; + integer check = llGetInventoryNumber(INVENTORY_TEXTURE); + if(check == 0) + { + llSetTexture(BLANK,DISPLAY_ON_SIDE); + current_texture = 0; + report("No pictures found."); + return; + } + if(check == current_texture) + current_texture = 0; + + display_texture(check); + return; +} + +////////////// +// from hufflets... + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + llListen(EXTERNAL_TOUCH_CHANNEL, "", NULL_KEY, ""); + // we listen on our touch channel in all cases and in all states. this allows us + // to always pass along the user's touch from other prims to run the menus. + chan = (integer)llFrand(1000) + 1000; //Pick a random listen channel for the listener + if(PICTURE_ROTATION_TIMER <= 0) //Ensure the value is no less or equal 0 + PICTURE_ROTATION_TIMER = 1; + llListenRemove(listenHandle); + listenHandle = -1; + last_owner = llGetOwner(); + groupcheck = llRequestAgentData(llGetOwner(),DATA_NAME); + off(); + llOpenRemoteDataChannel(); + // fred's changes to start up in picture viewing looper. + mode = 1; // picture viewing. + pictures(); // show the pictures. + loop_image = TRUE; + llSetTimerEvent(PICTURE_ROTATION_TIMER); // keep showing new pics. + } + + on_rez(integer i) + { + llSay(0,"Welcome to FreeView - your free, open-source television!"); + llResetScript(); + } + + touch_start(integer total_number) + { + //------------------------------------------------------------------------------- + //Listen only to owner or group member. Edit this code to change access controls. + if(llDetectedKey(0) != llGetOwner() && llDetectedGroup(0) == FALSE) + return; + //------------------------------------------------------------------------------- + + menu(llDetectedKey(0)); + } + + changed(integer change) + { + if(change == CHANGED_INVENTORY) //If inventory change + { + if(mode == 1) //If picture mode + { + integer check = llGetInventoryNumber(INVENTORY_TEXTURE); + if(check != 0) + { + current_texture = 0; + display_texture(check); + } + else + { + llSetTexture(BLANK,DISPLAY_ON_SIDE); + report("No pictures found."); + } + } + else + if(mode == 2) //If video mode + if(finditem(NOTECARD) != -1) //And bookmarks notecard present + if(notecardkey != llGetInventoryKey(NOTECARD)) + tempuser = llGetNumberOfNotecardLines(NOTECARD); //Reload number of lines + } + else if(change == CHANGED_OWNER) + { + isGroup = TRUE; + last_owner = llGetOwner(); + groupcheck = llRequestAgentData(llGetOwner(),DATA_NAME); + + if(mode == 2) + { + llSay(0,"Detected change in ownership. Attempting to obtain current parcel media texture..."); + video(); + } + } + } + + listen(integer channel, string name, key id, string message) + { + if ( (channel == EXTERNAL_TOUCH_CHANNEL) && is_prefix(message, "touched")) { + // pretend we got touched by the av. + message = llDeleteSubString(message, 0, 6); + menu((key)message); + return; + } + if(message == "Pictures") + { + if(mode == 2) + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); + pictures(); + mode = 1; + menu(id); + return; + } + if(message == "Video") + { + video(); + mode = 2; + menu(id); + return; + } + if(message == "Power off") + { + if(mode == 2) + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_UNLOAD]); + off(); + mode = 0; + return; + } + if(message == "Help") + { + llSay(0,"Help documentation is available at: http://www.slguide.com/help"); + if(isGroup) + { + if(id == NULL_KEY) + { + llSay(0,"FreeView cannot load help pages while set to group without the remote."); + llSay(0,"For further assistance, please consult: http://slguide.com/help"); + } + else + tell_remote("HELP"+(string)id+(string)XML_channel); + } + else + llLoadURL(id,"Help pages for FreeView","http://www.slguide.com?c="+(string)XML_channel+"&help=1"); + } + if(mode == 1) + { + if(message == "Browse") + { + loop_image = FALSE; + browse(id); + return; + } + if(message == "Next") + { + extendtimer(); + next(); + browse(id); + } + if(message == "Back") + { + extendtimer(); + current_texture--; + integer check = llGetInventoryNumber(INVENTORY_TEXTURE); + if(check == 0) + { + llSetTexture(BLANK,DISPLAY_ON_SIDE); + current_texture = 0; + report("No pictures found."); + return; + } + if(current_texture < 0) + current_texture = check - 1; + + display_texture(check); + + browse(id); + return; + } + if(message == "Menu") + { + menu(id); + return; + } + if(message == "Loop") + { + llSetTimerEvent(PICTURE_ROTATION_TIMER); + loop_image = TRUE; + llOwnerSay("Picture will change every "+(string)PICTURE_ROTATION_TIMER+" seconds."); + return; + } + if(message == "Unloop") + { + loop_image = FALSE; + llOwnerSay("Picture loop disabled."); + return; + } + if(message == "Fix scale") + { + llSay(0,"Setting display texture to 1,1 repeats and 0,0 offset."); + llScaleTexture(1, 1, DISPLAY_ON_SIDE); + llOffsetTexture(0, 0, DISPLAY_ON_SIDE); + return; + } + } + if(mode == 2) + { + if(channel == REMOTE_CHANNEL) + { + if(encryption == 0) + encryption = (integer)message; + llListenRemove(listenRemote); + listenRemote = -1; + llSay(0,"Remote configured ("+(string)id+")"); + } + + if(message == "TV Guide") + { + if(isGroup) + { + if(!encryption) + { + llSay(0,"** Error - This FreeView object has been deeded to group. You must use a Remote control to open the TV Guide."); + llSay(0,"You can set up the remote control from the Video -> Configuration menu. Please refer to the notecard for further assistance."); + return; + } + tell_remote((string)id+(string)XML_channel+(string)llGetOwner()); + } + else + llLoadURL(id, "Come to the Guide to Start Your Viewer Playing!", "http://slguide.com/index.php?v=" + (string)llGetKey() + "&c=" + (string)XML_channel + "&o=" + (string)llGetOwner() + "&"); + return; + } + + string header = "Video mode"+moviename+": "; + + if(message == "<< Prev") + { + notecardline--; + if(notecardline < 0) + notecardline = numberofnotecardlines - 1; + tempuser = id; + llGetNotecardLine(NOTECARD,notecardline); + return; + } + if(message == "Next >>") + { + notecardline++; + if(notecardline >= numberofnotecardlines) + notecardline = 0; + tempuser = id; + llGetNotecardLine(NOTECARD,notecardline); + return; + } + if(message == "Use") + { + if(tempurl == "** No URL specified! **") + tempurl = ""; + seturl(tempurl,id); + return; + } + + if(message == "Menu") + { + menu(id); + return; + } + if(message == "Configure") + { + config(id); + return; + } + if(message == "Bookmarks") + { + if(notecardcheck != -1) + { + llDialog(id,"Error: No valid bookmark data found in notecard '"+NOTECARD+"'.",["Menu"],chan); + return; + } + if(finditem(NOTECARD) != -1) + { + tempuser = id; + if(numberofnotecardlines < notecardline) + notecardline = 0; + llGetNotecardLine(NOTECARD,notecardline); + } + else + llDialog(id,"Error: No notecard named "+NOTECARD+" found in contents.",["Menu"],chan); + return; + } + + if(llGetLandOwnerAt(llGetPos()) != llGetOwner()) //If we do not have permissions to actually do the following functions + { + llSay(0,"Error: Cannot modify parcel media settings. "+llGetObjectName()+" is not owned by parcel owner."); + menu(id); + return; //Abort + } + + if(listenUrl != -1 && channel == 1) //Incoming data from "Set URL" command (user spoke on channel 1) + { + llListenRemove(listenUrl); + listenUrl = -1; + tempmoviename = ""; + seturl(message,id); + } + if(message == "Play") + { + report(header+"Playing"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PLAY]); + return; + } + if(message == "Stop") + { + report(header+"Stopped"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); + return; + } + if(message == "Pause") + { + report(header+"Paused"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PAUSE]); + return; + } + if(message == "Unload") + { + report(header+"Stopped"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_UNLOAD]); + return; + } + if(message == "Loop") + { + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_LOOP]); + return; + } + //URL , Auto-Scale, + if(message == "Set URL") + { + report(header+"Stopped"); + listenUrl = llListen(1,"",id,""); + llDialog(id,"Please type the URL of your choice with /1 in thebegining. For example, /1 www.google.com",["Ok"],938); + return; + } + if(message == "Align ON") + { + report(header+"Stopped"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AUTO_ALIGN,TRUE]); + menu(id); + return; + } + if(message == "Align OFF") + { + report(header+"Stopped"); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AUTO_ALIGN,FALSE]); + menu(id); + return; + } + if(message == "Set Remote") + { + llSay(0,"Configuring remote..."); + encryption = 0; + llListenRemove(listenRemote); + listenRemote = llListen(REMOTE_CHANNEL,"","",""); + llSay(REMOTE_CHANNEL,"SETUP"); + } + } + } + + dataserver(key queryid, string data) + { + if(queryid == groupcheck) //Test if object is deeded to group + { + groupcheck = NULL_KEY; + isGroup = FALSE; + return; + } + + if(queryid == tempuser) //If just checking number of notecard lines + { + numberofnotecardlines = (integer)data; + notecardkey = llGetInventoryKey(NOTECARD); + notecardcheck = 0; + llGetNotecardLine(NOTECARD,notecardcheck); + return; + } + if(notecardcheck != -1) + { + if(data != EOF) + { + if(data == "") + { + notecardcheck++; + llGetNotecardLine(NOTECARD,notecardcheck); + } + else + { + notecardcheck = -1; + return; + } + } + else + return; + } + + if(data == "" && notecardline < numberofnotecardlines) //If user just pressed "enter" in bookmarks, skip + { + notecardline++; + llGetNotecardLine(NOTECARD,notecardline); + return; + } + + if(data == EOF) + { + notecardline = 0; + llGetNotecardLine(NOTECARD,notecardline); + return; + } + list parsed = llParseString2List(data,["|","| "," |"," | "],[]); //Ensure no blank spaces before "http://". + string name = llList2String(parsed,0); + tempurl = llList2String(parsed,1); + if(tempurl == "") + tempurl = "** No URL specified! **"; + + tempmoviename = name; + + llDialog(tempuser,"Bookmarks notecard ("+(string)(notecardline+1)+"/"+(string)numberofnotecardlines+")\n"+name+" ("+mediatype(llList2String(llParseString2List(tempurl,["."],[]),-1))+")\n"+tempurl,["<< Prev","Use","Next >>","Menu"],chan); + } + + remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) + { + if (type == REMOTE_DATA_CHANNEL) + { + XML_channel = channel; + } + else if(type == REMOTE_DATA_REQUEST) + { + list media_info = llParseString2List(sval, ["|"], []); + tempmoviename = llList2String(media_info,0); + seturl(llList2String(media_info,1),NULL_KEY); + llRemoteDataReply(channel, message_id, sval, 1); + } + } + + timer() + { + if(llGetTime() > listenTimer) //If listener time expired... + { + llListenRemove(listenHandle); //Remove listeneres. + llListenRemove(listenUrl); + llListenRemove(listenRemote); + listenHandle = -1; + listenUrl = -1; + listenRemote = -1; + listenTimer = -1; + if(loop_image == FALSE || mode != 1) //If we're not looping pictures or are in picture mode at all + llSetTimerEvent(0.0); //Remove timer + } + + if(loop_image == TRUE && mode == 1) //If we're looping pictures and and we're in picture mode... + next(); //Next picture + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.lsl deleted file mode 100755 index 21b4842b..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.lsl +++ /dev/null @@ -1,367 +0,0 @@ - -// jukebox script. unknown provenance. -// modified for use in opensim by fred huffhines. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -float INTERVAL = 9.00; - -integer IS_OPENSIM = TRUE; - // this must be set to true to turn off the sound queuing. opensim does not currently implement it. - -float SOUND_OFFSET_PERIOD = 1.1; // number of seconds to start the sound in advance. - -integer LISTEN_CHAN = 2000; -integer SEND_CHAN = 2001; -float VOLUME = 1.0; - -integer g_iSound; -integer total_tracks; -integer g_iListenCtrl = -1; -integer g_iPlaying; -integer g_iLinked; -integer g_iStop; -integer g_iPod; -string g_sLink; - -// DEBUG -integer g_iWasLinked; -integer g_iFinished; - -list song_names; - // hold onto the names of all the songs so we don't need to keep - // going back to inventory. - -Initialize() -{ - llSetText(llGetObjectName(), <0, 100, 100>, 10); - - // reset listeners - if ( g_iListenCtrl != -1 ) - { - llListenRemove(g_iListenCtrl); - } - g_iListenCtrl = llListen(LISTEN_CHAN,"","",""); - g_iPlaying = 0; - g_iLinked = 0; - - integer i; - total_tracks = llGetInventoryNumber(INVENTORY_SOUND); - for ( i = 0; i < total_tracks; i++ ) { - string name = llGetInventoryName(INVENTORY_SOUND, i); - song_names += [ name ]; - llPreloadSound(name); - } -//llOwnerSay("got song names list: " + (string)song_names); -} - - - -PlaySong() -{ - integer i; - - g_iPlaying = 1; - llWhisper(0, "Playing..."); - if (!IS_OPENSIM) { - llSetSoundQueueing(TRUE); - } - llAdjustSoundVolume(1.0); - llPlaySound(llList2String(song_names, 0), VOLUME); - llPreloadSound(llList2String(song_names, 1)); - // set the timer interval for just before the track chunk ends. - llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD); - g_iSound = 1; -} - - -StopSong() -{ - g_iPlaying = 0; - llWhisper(0, "Stopping..."); - llStopSound(); - llAdjustSoundVolume(0); - llSetTimerEvent(0.0); -} - - -integer CheckLink() -{ - string sLink; - - sLink = llGetLinkName(1); - g_sLink = sLink; - if ( llGetSubString(sLink,0,6) == "Jukebox" ) - { - return TRUE; - } - return FALSE; -} - - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - Initialize(); - } - - on_rez(integer start_param) - { - Initialize(); - if ( start_param ) - { - g_iPod = start_param - 1; - if ( g_iPod ) - { - llRequestPermissions(llGetOwner(),PERMISSION_ATTACH); - } else { - // Tell the controller what the CD key is so it can link - llWhisper(SEND_CHAN,"LINK " + (string)llGetKey()); - } - } - } - - changed(integer change) - { - if ( change == CHANGED_LINK ) - { - if ( llGetLinkNumber() == 0 ) - { - StopSong(); - llDie(); - } else { - if ( g_iStop ) - { - llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); - } else { - llMessageLinked(1,llGetLinkNumber(),"LINKID",""); - g_iWasLinked = 1; - } - } - } - } - - attach(key id) - { - if ( id == NULL_KEY ) - { - llDie(); - } else { - PlaySong(); - } - } - - run_time_permissions(integer perm) - { - if ( perm == PERMISSION_ATTACH ) - { - llAttachToAvatar(ATTACH_LSHOULDER); - llSetTexture("clear",ALL_SIDES); - } - } - - touch_start(integer total_number) - { - integer i; - - for ( i = 0; i < total_number; i++ ) - { - if ( llDetectedKey(i) == llGetOwner() ) - { -//llWhisper(0,"DEBUG: g_iPlaying=" + (string)g_iPlaying); -//llWhisper(0,"DEBUG: Link=" + (string)llGetLinkNumber()); -//llWhisper(0,"DEBUG: g_iWasLinked=" + (string)g_iWasLinked); -//llWhisper(0,"DEBUG: g_iFinished=" + (string)g_iFinished); - if ( g_iPlaying ) StopSong(); - else PlaySong(); - } - } - } - - listen(integer channel, string name, key id, string message) - { - if ( message == "RESET" ) - { - if ( llGetLinkNumber() == 0 ) - { - llDie(); - } else { - llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); - } - } - - if ( message == "STOP" ) - { - if ( g_iPod ) - { - StopSong(); - llDetachFromAvatar(); - } - } - } - - link_message(integer sender_num, integer num, string str, key id) - { - if ( str == "PLAY" ) - { - if ( !g_iPlaying ) - { - PlaySong(); - } - return; - } - - if ( str == "STOP" ) - { - g_iStop = 1; - StopSong(); - llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); - } - - if ( str == "VOLUME" ) - { - VOLUME = (float)num / 10.0; - llAdjustSoundVolume(VOLUME); - } - } - - timer() - { - if ( g_iPlaying ) - { -//llWhisper(0, "playing song #" + (string)(g_iSound+1) + ": " + llList2String(song_names, g_iSound)); - llPlaySound(llList2String(song_names, g_iSound),VOLUME); - if ( g_iSound < (total_tracks - 1) ) - { - llPreloadSound(llList2String(song_names, g_iSound + 1)); - } - g_iSound++; - if ( g_iSound >= total_tracks ) - { - llSetTimerEvent(INTERVAL + 5.0); - g_iPlaying = 0; - } else { - llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD); - } - } else { - if ( llGetLinkNumber() != 0 ) - { - llSetTimerEvent(0.0); - if ( g_iPod ) - { - llWhisper(SEND_CHAN,"FINISH"); - llDetachFromAvatar(); - } else { - llMessageLinked(1,0,"FINISH",""); - g_iFinished = 1; - } - } - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.txt new file mode 100755 index 00000000..21b4842b --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/JukeBox_v1.6.txt @@ -0,0 +1,367 @@ + +// jukebox script. unknown provenance. +// modified for use in opensim by fred huffhines. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +float INTERVAL = 9.00; + +integer IS_OPENSIM = TRUE; + // this must be set to true to turn off the sound queuing. opensim does not currently implement it. + +float SOUND_OFFSET_PERIOD = 1.1; // number of seconds to start the sound in advance. + +integer LISTEN_CHAN = 2000; +integer SEND_CHAN = 2001; +float VOLUME = 1.0; + +integer g_iSound; +integer total_tracks; +integer g_iListenCtrl = -1; +integer g_iPlaying; +integer g_iLinked; +integer g_iStop; +integer g_iPod; +string g_sLink; + +// DEBUG +integer g_iWasLinked; +integer g_iFinished; + +list song_names; + // hold onto the names of all the songs so we don't need to keep + // going back to inventory. + +Initialize() +{ + llSetText(llGetObjectName(), <0, 100, 100>, 10); + + // reset listeners + if ( g_iListenCtrl != -1 ) + { + llListenRemove(g_iListenCtrl); + } + g_iListenCtrl = llListen(LISTEN_CHAN,"","",""); + g_iPlaying = 0; + g_iLinked = 0; + + integer i; + total_tracks = llGetInventoryNumber(INVENTORY_SOUND); + for ( i = 0; i < total_tracks; i++ ) { + string name = llGetInventoryName(INVENTORY_SOUND, i); + song_names += [ name ]; + llPreloadSound(name); + } +//llOwnerSay("got song names list: " + (string)song_names); +} + + + +PlaySong() +{ + integer i; + + g_iPlaying = 1; + llWhisper(0, "Playing..."); + if (!IS_OPENSIM) { + llSetSoundQueueing(TRUE); + } + llAdjustSoundVolume(1.0); + llPlaySound(llList2String(song_names, 0), VOLUME); + llPreloadSound(llList2String(song_names, 1)); + // set the timer interval for just before the track chunk ends. + llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD); + g_iSound = 1; +} + + +StopSong() +{ + g_iPlaying = 0; + llWhisper(0, "Stopping..."); + llStopSound(); + llAdjustSoundVolume(0); + llSetTimerEvent(0.0); +} + + +integer CheckLink() +{ + string sLink; + + sLink = llGetLinkName(1); + g_sLink = sLink; + if ( llGetSubString(sLink,0,6) == "Jukebox" ) + { + return TRUE; + } + return FALSE; +} + + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + Initialize(); + } + + on_rez(integer start_param) + { + Initialize(); + if ( start_param ) + { + g_iPod = start_param - 1; + if ( g_iPod ) + { + llRequestPermissions(llGetOwner(),PERMISSION_ATTACH); + } else { + // Tell the controller what the CD key is so it can link + llWhisper(SEND_CHAN,"LINK " + (string)llGetKey()); + } + } + } + + changed(integer change) + { + if ( change == CHANGED_LINK ) + { + if ( llGetLinkNumber() == 0 ) + { + StopSong(); + llDie(); + } else { + if ( g_iStop ) + { + llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); + } else { + llMessageLinked(1,llGetLinkNumber(),"LINKID",""); + g_iWasLinked = 1; + } + } + } + } + + attach(key id) + { + if ( id == NULL_KEY ) + { + llDie(); + } else { + PlaySong(); + } + } + + run_time_permissions(integer perm) + { + if ( perm == PERMISSION_ATTACH ) + { + llAttachToAvatar(ATTACH_LSHOULDER); + llSetTexture("clear",ALL_SIDES); + } + } + + touch_start(integer total_number) + { + integer i; + + for ( i = 0; i < total_number; i++ ) + { + if ( llDetectedKey(i) == llGetOwner() ) + { +//llWhisper(0,"DEBUG: g_iPlaying=" + (string)g_iPlaying); +//llWhisper(0,"DEBUG: Link=" + (string)llGetLinkNumber()); +//llWhisper(0,"DEBUG: g_iWasLinked=" + (string)g_iWasLinked); +//llWhisper(0,"DEBUG: g_iFinished=" + (string)g_iFinished); + if ( g_iPlaying ) StopSong(); + else PlaySong(); + } + } + } + + listen(integer channel, string name, key id, string message) + { + if ( message == "RESET" ) + { + if ( llGetLinkNumber() == 0 ) + { + llDie(); + } else { + llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); + } + } + + if ( message == "STOP" ) + { + if ( g_iPod ) + { + StopSong(); + llDetachFromAvatar(); + } + } + } + + link_message(integer sender_num, integer num, string str, key id) + { + if ( str == "PLAY" ) + { + if ( !g_iPlaying ) + { + PlaySong(); + } + return; + } + + if ( str == "STOP" ) + { + g_iStop = 1; + StopSong(); + llMessageLinked(1,llGetLinkNumber(),"UNLINK",""); + } + + if ( str == "VOLUME" ) + { + VOLUME = (float)num / 10.0; + llAdjustSoundVolume(VOLUME); + } + } + + timer() + { + if ( g_iPlaying ) + { +//llWhisper(0, "playing song #" + (string)(g_iSound+1) + ": " + llList2String(song_names, g_iSound)); + llPlaySound(llList2String(song_names, g_iSound),VOLUME); + if ( g_iSound < (total_tracks - 1) ) + { + llPreloadSound(llList2String(song_names, g_iSound + 1)); + } + g_iSound++; + if ( g_iSound >= total_tracks ) + { + llSetTimerEvent(INTERVAL + 5.0); + g_iPlaying = 0; + } else { + llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD); + } + } else { + if ( llGetLinkNumber() != 0 ) + { + llSetTimerEvent(0.0); + if ( g_iPod ) + { + llWhisper(SEND_CHAN,"FINISH"); + llDetachFromAvatar(); + } else { + llMessageLinked(1,0,"FINISH",""); + g_iFinished = 1; + } + } + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.lsl deleted file mode 100755 index 0255c6c2..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.lsl +++ /dev/null @@ -1,697 +0,0 @@ - -// fred huffhines mods: -// -// took away the universal skeleton key that was lodged in this script. -// -// stopped considering door's scale; this is not usually needed, plus we were blowing -// past the SL limit on object names. -// -// moved to only storing a couple digits after the decimal point; this is another -// crucial thing to limit the size of the object name. -// -// added a "toggle" command that behaves like touch, in that the door will be opened -// or closed based on current state. -// -// made the sensor distance required before the door will listen to someone into a -// configurable parameter, instead of the woefully tiny, hard-coded 5 meters. -// -// added debugging flag and switchable logging for debugging mode. -// -// *original license and author info below...* -// -// plus, timeless prototype said this about using the script in osgrid and elsewhere: -// "hi, thanks for asking, yes you may use the door script in other grids." -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// -// more fred huffhines mods: (circa march 2012) -// added PASS_COMMANDS flag, which can be used to pass along any commands we -// hear to anyone else on our same channel within the object. -// added stifling of commands heard so they don't get re-sent, causing endless -// loops of door openings. - - -//------------------------------------------------------ -// Timeless Linked Door Script by Timeless Prototype -//------------------------------------------------------ -// The latest version of this script can always be found -// in the Library section of the wiki: -// http://www.secondlife.com/badgeo/ -// This script is free to use, but whereever it is used -// the SCRIPT's permissions MUST be set to: -// [x] Next owner can modify -// [x] Next owner can copy -// [x] Next owner can transfer -// [x] Allow anyone to copy -// [x] Share with group - -//------------------------------------------------------ -// USAGE INSTRUCTIONS FOR EVERYDAY USE: -//------------------------------------------------------ -// Say the following commands on channel 0: -// 'unlock' - Unlocks all doors in range. -// 'lock' - Locks all doors in range and allows -// only the permitted users to open it. -// To open the door, either Touch it, Walk into it or -// say 'open' or say 'close'. - -//------------------------------------------------------ -// USAGE INSTRUCTIONS FOR BUILDERS: -//------------------------------------------------------ -// 1. Copy and paste this script into the door prim and -// change the settings (see further down). -// 2. The door prim must be linked to at least one other -// prim (could be linked to the house for example). -// 3. The door prim MUST NOT be the root prim. -// 4. Use Edit Linked Parts to move, rotate and size the -// door prim for the closed state. -// 5. When ready, stand close to the door and say -// '/door closed' (this records the closed door -// position, rotation and size to the object's -// name and description). -// 6. Use the Edit Linked parts to move, rotate and size -// the door prim for the opened state. -// 7. When ready, stand close to the door and say -// '/door opened' (this records the opened door -// position, rotation and size). -// 8. Once recorded it will not accept these commands -// again. If you do need to redo the settings then -// delete the Name and Description of the door prim -// (these are where the position information is -// stored), and then follow the steps above again. -// Note: deleting the object name won't save, so set -// the object name to 'Object' to reset the object -// name. - -//------------------------------------------------------ -// Change these settings to suit your needs. -//------------------------------------------------------ -// To mute any/all of the sounds set the sound string(s) -// to "" (empty string). -// To get the UUID of a sound, right click on the sound -// in your inventory and choose "Copy Asset UUID", then -// paste the UUID in here. -string doorOpenSound = "Door open"; -string doorCloseSound = "Door close"; -string confirmedSound = "69743cb2-e509-ed4d-4e52-e697dc13d7ac"; -string accessDeniedSound = "58da0f9f-42e5-8a8f-ee51-4fac6c247c98"; -string doorBellSound = ""; // Setting to empty stops door announcements too. -float autoCloseTime = 120.0; // 0 seconds to disable auto close. -integer allowGroupToo = TRUE; // Set to FALSE to disallow same group access to door. -list allowedAgentUUIDs = []; // Comma-separated, quoted list of avatar UUIDs who are allowed access to this door. -// was allowing this sneaky guy: "8efecbac-35de-4f40-89c1-2c772b83cafa" -integer listenChannel = 10106; -float RESPONSE_DISTANCE = 120.0; // how far to allow a command from users with permission. -integer DEBUGGING = FALSE; -integer PASS_COMMANDS = TRUE; - // if true, then we will order other doors to open when we do. - // we use the listenChannel as the id to pass commands on, so that only the doors listening to - // the same place will hear our commands. -integer command_is_a_response = FALSE; - // if this is true, then the door open and close must not re-echo their actions. - -//------------------------------------------------------ -// Leave the rest of the settings alone, these are -// handled by the script itself. -//------------------------------------------------------ -integer isLocked = FALSE; // Only when the door is locked do the permissions apply. -integer isOpen = TRUE; -vector openPos = ZERO_VECTOR; -rotation openRot = ZERO_ROTATION; -vector closedPos = ZERO_VECTOR; -rotation closedRot = ZERO_ROTATION; -key openerKey = NULL_KEY; -key closerKey = NULL_KEY; -integer isSetup = FALSE; -integer listenHandle = 0; -string avatarName = ""; - -// zooms the sub-prim to a new rotation and position. -jump_to_position(vector position, rotation new_rot) -{ - list config_blast = [ - PRIM_SIZE, llGetScale(), ///???? - // first jump away from where we started, trying to get past an opensim bug. -// PRIM_POSITION, ZERO_VECTOR, -// PRIM_POSITION, ZERO_VECTOR, -// PRIM_POSITION, ZERO_VECTOR, -// PRIM_POSITION, ZERO_VECTOR, -// PRIM_POSITION, ZERO_VECTOR, - PRIM_ROTATION, ZERO_ROTATION * new_rot / llGetRootRotation(), -// PRIM_POSITION, position, -// PRIM_POSITION, position, -// PRIM_POSITION, position, -// PRIM_POSITION, position, -// PRIM_POSITION, position, - PRIM_POSITION, position - ]; - llSetLinkPrimitiveParams(llGetLinkNumber(), config_blast); -if (DEBUGGING) llOwnerSay("want pos=" + (string)position + ", got=" + (string)llGetLocalPos() -+ ", and want rot=" + (string)new_rot + ", got=" + (string)llGetLocalRot()); -} - -mySayName(integer channel, string objectName, string message) -{ - string name = llGetObjectName(); - llSetObjectName(objectName); - llSay(0, "/me " + message); - llSetObjectName(name); -} - -mySay(integer channel, string message) -{ - string name = llGetObjectName(); - llSetObjectName("Door"); - llSay(0, message); - llSetObjectName(name); -} - -myOwnerSay(string message) -{ - string name = llGetObjectName(); - llSetObjectName("Door"); - llOwnerSay(message); - llSetObjectName(name); -} - -mySoundConfirmed() -{ - if (confirmedSound != "") - { - llTriggerSound(confirmedSound, 1.0); - } -} - -mySoundAccessDenied() -{ - if (accessDeniedSound != "") - { - llTriggerSound(accessDeniedSound, 1.0); - } -} - -myGetDoorParams() -{ - isSetup = FALSE; - if (llSubStringIndex(llGetObjectDesc(), "D;") == 0 && llSubStringIndex(llGetObjectName(), "D;") == 0) - { - list nameWords = llParseString2List(llGetObjectName(), [";"], []); - list descWords = llParseString2List(llGetObjectDesc(), [";"], []); - if (llGetListLength(nameWords) != 3 || llGetListLength(descWords) != 3) - { - myOwnerSay("The door prim's name and/or description has invalid syntax and/or number of parameters. Delete the door prim's name and description and setup the door prim again."); - } - else - { - openPos = (vector)llList2String(nameWords, 1); - openRot = (rotation)llList2String(nameWords, 2); - closedPos = (vector)llList2String(descWords, 1); - closedRot = (rotation)llList2String(descWords, 2); - isSetup = TRUE; - } -//llSay(0, "got open pos=" + (string)(openPos) + " rot=" + (string)(openRot)); -//llSay(0, "got close pos=" + (string)(closedPos) + " rot=" + (string)(closedRot)); - - } -} - -// if open_state is true, the parms are for an open door. -mySetDoorParams(integer open_state, vector Pos, rotation Rot) -{ - if (open_state) { - // parms for open state. - llSetObjectName("D;" + vector_chop(Pos) + ";" + rotation_chop(Rot)); - } else { - // parms for closed state. - llSetObjectDesc("D;" + vector_chop(Pos) + ";" + rotation_chop(Rot)); - } - isSetup = TRUE; -} - -integer myPermissionCheck(key id) -{ - integer hasPermission = FALSE; - if (isLocked == FALSE) { - if (DEBUGGING) llOwnerSay("perm--unlocked: okay"); - hasPermission = TRUE; - } else if (llGetOwnerKey(id) == llGetOwner()) { - if (DEBUGGING) llOwnerSay("perm--is owner: okay"); - hasPermission = TRUE; - } else if (allowGroupToo == TRUE && llSameGroup(id)) { - if (DEBUGGING) llOwnerSay("perm--same group: okay"); - hasPermission = TRUE; - } else if (llListFindList(allowedAgentUUIDs, [(string)id]) != -1) { - if (DEBUGGING) llOwnerSay("perm--in list: okay"); - hasPermission = TRUE; - } else { - if (DEBUGGING) llOwnerSay("perm--not found anywhere: bad perms"); - } - return hasPermission; -} - -myOpenDoor() -{ - isOpen = FALSE; - myToggleDoor(); -} - -myCloseDoor() -{ - isOpen = TRUE; - myToggleDoor(); -} - -myToggleDoor() -{ - if (isSetup == FALSE) - { - myOwnerSay("The door prim has not been configured yet. Please read the usage instructions in the door script."); - } - else if (llGetLinkNumber() == 0 || llGetLinkNumber() == 1) - { - myOwnerSay("The door prim must be linked to at least one other prim and the door prim must not be the root prim"); - } - else - { - isOpen = !isOpen; -if (DEBUGGING) llOwnerSay("door open state is now=" + (string)isOpen); - if (isOpen) - { -if (DEBUGGING) llOwnerSay("opening the door."); - if (doorBellSound != "") - { - llTriggerSound(doorBellSound, 1.0); - if (avatarName != "") - { - mySayName(0, avatarName, "is at the door."); - avatarName = ""; - } - } - if (doorOpenSound != "") - { - llTriggerSound(doorOpenSound, 1.0); - } - jump_to_position(openPos, openRot); -// list config_blast = [ PRIM_POSITION, llGetLocalPos() + <4, 4, 4>, -// PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation(), -// PRIM_POSITION, openPos -//// PRIM_SIZE, llGetScale() -// ]; -// llSetPrimitiveParams(config_blast); -//if (DEBUGGING) llOwnerSay("want pos=" + (string)openPos + ", got=" + (string)llGetLocalPos() -//+ ", and want rot=" + (string)openRot + ", got=" + (string)llGetLocalRot()); - - if (PASS_COMMANDS && !command_is_a_response) { - // Door API. - llMessageLinked(LINK_SET, listenChannel, "cmd|door|open", llGetKey()); - } - command_is_a_response = FALSE; // took care of that one. - } - else - { -if (DEBUGGING) llOwnerSay("closing the door."); - if (doorCloseSound != "") - { - llTriggerSound(doorCloseSound, 1.0); - } - jump_to_position(closedPos, closedRot); -// list config_blast = [ -// PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation(), -// PRIM_POSITION, closedPos -//// PRIM_SIZE, llGetScale() -// ]; -// llSetPrimitiveParams(config_blast); -//if (DEBUGGING) llOwnerSay("want pos=" + (string)closedPos + ", got=" + (string)llGetLocalPos() -//+ ", and want rot=" + (string)closedRot + ", got=" + (string)llGetLocalRot()); - if (PASS_COMMANDS && !command_is_a_response) { - // Door API. - llMessageLinked(LINK_SET, listenChannel, "cmd|door|close", llGetKey()); - } - command_is_a_response = FALSE; // took care of that one. - } - - llSetTimerEvent(0.0); - if (isOpen == TRUE && autoCloseTime != 0.0) - { - llSetTimerEvent(autoCloseTime); - } - } -} - -////////////// -// from hufflets... - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns text for a floating point number, but includes only -// three digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 1000.0) / 1000); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// similarly, for a rotation. -string rotation_chop(rotation to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + "," - + float_chop(to_show.s) + ">"; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - listenHandle = llListen(listenChannel, "", NULL_KEY, ""); - myGetDoorParams(); - myCloseDoor(); - } - - on_rez(integer parm) { llResetScript(); } - - touch_start(integer total_number) - { - command_is_a_response = FALSE; - if (myPermissionCheck(llDetectedKey(0)) == TRUE) - { - avatarName = llDetectedName(0); - myToggleDoor(); - } - else - { - mySoundAccessDenied(); - } - } - - timer() - { - myCloseDoor(); - } - - link_message(integer sender_num, integer num, string str, key id) - { - // Door API. The API is here in case you want to create PIN entry keypads or whatever. - if (num == listenChannel) { - if (id == llGetKey()) return; // don't listen to our own commands. - command_is_a_response = TRUE; - if (str == "cmd|door|open") myOpenDoor(); - else if (str == "cmd|door|close") myCloseDoor(); - else if (str == "cmd|door|discover") - llMessageLinked(LINK_SET, listenChannel, "cmd|door|discovered|" + (string)llGetKey(), - llGetKey()); - else command_is_a_response = FALSE; -//hmmm: above protocol seems redundant, but sending back the original id (like this did before) -// in the id field does not fit in with our usual schemes very well. - } - } - - listen(integer channel, string name, key id, string message) - { -// if (DEBUGGING) llOwnerSay("heard: " + message); - command_is_a_response = FALSE; // don't get involved with the link message checking. - - // Performance note: it's quicker to compare the strings than to compare permissions each time anyone says anything on this channel. - if (message == "open") - { - if (myPermissionCheck(id) == TRUE) - { - // Only open the door if the person is quite close to this door. - openerKey = id; - closerKey = NULL_KEY; - avatarName = name; - llSensor(name, id, AGENT, RESPONSE_DISTANCE, TWO_PI); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "close") - { - if (myPermissionCheck(id) == TRUE) - { - openerKey = NULL_KEY; - closerKey = id; - avatarName = name; - // Only close the door if the person is quite close to this door. - llSensor(name, id, AGENT, RESPONSE_DISTANCE, TWO_PI); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "lock") - { - if (myPermissionCheck(id) == TRUE) - { - isLocked = TRUE; - mySoundConfirmed(); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "unlock") - { - if (myPermissionCheck(id) == TRUE) - { - isLocked = FALSE; - mySoundConfirmed(); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "toggle") - { - if (myPermissionCheck(id) == TRUE) - { - avatarName = name; - myToggleDoor(); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "/door opened" && llSubStringIndex(llGetObjectName(), "D;") == -1) - { - if (llGetOwnerKey(id) == llGetOwner()) - { - mySoundConfirmed(); - openPos = llGetLocalPos(); - openRot = llGetLocalRot(); - isOpen = TRUE; - mySetDoorParams(TRUE, openPos, openRot); -//llSay(0, "set open pos=" + (string)(openPos) + " rot=" + (string)(openRot)); - } - else - { - mySoundAccessDenied(); - } - } - else if (message == "/door closed" && llSubStringIndex(llGetObjectDesc(), "D;") == -1) - { - if (llGetOwnerKey(id) == llGetOwner()) - { - mySoundConfirmed(); - closedPos = llGetLocalPos(); - closedRot = llGetLocalRot(); - isOpen = FALSE; - mySetDoorParams(FALSE, closedPos, closedRot); -//llSay(0, "set close pos=" + (string)(closedPos) + " rot=" + (string)(closedRot)); - } - else - { - mySoundAccessDenied(); - } - } - } - - sensor(integer num_detected) - { - if (openerKey != NULL_KEY) - { - integer i; - for (i = 0; i < num_detected; i++) - { - if (llDetectedKey(i) == openerKey && myPermissionCheck(llDetectedKey(i)) == TRUE) - { - myOpenDoor(); - } - } - openerKey = NULL_KEY; - } - else - { - integer i; - for (i = 0; i < num_detected; i++) - { - if (llDetectedKey(i) == closerKey && myPermissionCheck(llDetectedKey(i)) == TRUE) - { - myCloseDoor(); - } - } - closerKey = NULL_KEY; - } - } - -//------------------------------------------------------ -// Uncomment the following code if you particularly want -// collisions to affect the door state. -//------------------------------------------------------ - -// collision_start(integer num_detected) -// { -// integer i; -// for (i = 0; i < num_detected; i++) -// { -// if (myPermissionCheck(llDetectedKey(i)) == TRUE) -// { -// avatarName = llDetectedName(i); -// myOpenDoor(); -// } -// else if (llDetectedType(i) & AGENT) -// { -// mySoundAccessDenied(); -// } -// } -// } - -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.txt new file mode 100755 index 00000000..0255c6c2 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/TL_Door_fredmod_v4.4.txt @@ -0,0 +1,697 @@ + +// fred huffhines mods: +// +// took away the universal skeleton key that was lodged in this script. +// +// stopped considering door's scale; this is not usually needed, plus we were blowing +// past the SL limit on object names. +// +// moved to only storing a couple digits after the decimal point; this is another +// crucial thing to limit the size of the object name. +// +// added a "toggle" command that behaves like touch, in that the door will be opened +// or closed based on current state. +// +// made the sensor distance required before the door will listen to someone into a +// configurable parameter, instead of the woefully tiny, hard-coded 5 meters. +// +// added debugging flag and switchable logging for debugging mode. +// +// *original license and author info below...* +// +// plus, timeless prototype said this about using the script in osgrid and elsewhere: +// "hi, thanks for asking, yes you may use the door script in other grids." +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// +// more fred huffhines mods: (circa march 2012) +// added PASS_COMMANDS flag, which can be used to pass along any commands we +// hear to anyone else on our same channel within the object. +// added stifling of commands heard so they don't get re-sent, causing endless +// loops of door openings. + + +//------------------------------------------------------ +// Timeless Linked Door Script by Timeless Prototype +//------------------------------------------------------ +// The latest version of this script can always be found +// in the Library section of the wiki: +// http://www.secondlife.com/badgeo/ +// This script is free to use, but whereever it is used +// the SCRIPT's permissions MUST be set to: +// [x] Next owner can modify +// [x] Next owner can copy +// [x] Next owner can transfer +// [x] Allow anyone to copy +// [x] Share with group + +//------------------------------------------------------ +// USAGE INSTRUCTIONS FOR EVERYDAY USE: +//------------------------------------------------------ +// Say the following commands on channel 0: +// 'unlock' - Unlocks all doors in range. +// 'lock' - Locks all doors in range and allows +// only the permitted users to open it. +// To open the door, either Touch it, Walk into it or +// say 'open' or say 'close'. + +//------------------------------------------------------ +// USAGE INSTRUCTIONS FOR BUILDERS: +//------------------------------------------------------ +// 1. Copy and paste this script into the door prim and +// change the settings (see further down). +// 2. The door prim must be linked to at least one other +// prim (could be linked to the house for example). +// 3. The door prim MUST NOT be the root prim. +// 4. Use Edit Linked Parts to move, rotate and size the +// door prim for the closed state. +// 5. When ready, stand close to the door and say +// '/door closed' (this records the closed door +// position, rotation and size to the object's +// name and description). +// 6. Use the Edit Linked parts to move, rotate and size +// the door prim for the opened state. +// 7. When ready, stand close to the door and say +// '/door opened' (this records the opened door +// position, rotation and size). +// 8. Once recorded it will not accept these commands +// again. If you do need to redo the settings then +// delete the Name and Description of the door prim +// (these are where the position information is +// stored), and then follow the steps above again. +// Note: deleting the object name won't save, so set +// the object name to 'Object' to reset the object +// name. + +//------------------------------------------------------ +// Change these settings to suit your needs. +//------------------------------------------------------ +// To mute any/all of the sounds set the sound string(s) +// to "" (empty string). +// To get the UUID of a sound, right click on the sound +// in your inventory and choose "Copy Asset UUID", then +// paste the UUID in here. +string doorOpenSound = "Door open"; +string doorCloseSound = "Door close"; +string confirmedSound = "69743cb2-e509-ed4d-4e52-e697dc13d7ac"; +string accessDeniedSound = "58da0f9f-42e5-8a8f-ee51-4fac6c247c98"; +string doorBellSound = ""; // Setting to empty stops door announcements too. +float autoCloseTime = 120.0; // 0 seconds to disable auto close. +integer allowGroupToo = TRUE; // Set to FALSE to disallow same group access to door. +list allowedAgentUUIDs = []; // Comma-separated, quoted list of avatar UUIDs who are allowed access to this door. +// was allowing this sneaky guy: "8efecbac-35de-4f40-89c1-2c772b83cafa" +integer listenChannel = 10106; +float RESPONSE_DISTANCE = 120.0; // how far to allow a command from users with permission. +integer DEBUGGING = FALSE; +integer PASS_COMMANDS = TRUE; + // if true, then we will order other doors to open when we do. + // we use the listenChannel as the id to pass commands on, so that only the doors listening to + // the same place will hear our commands. +integer command_is_a_response = FALSE; + // if this is true, then the door open and close must not re-echo their actions. + +//------------------------------------------------------ +// Leave the rest of the settings alone, these are +// handled by the script itself. +//------------------------------------------------------ +integer isLocked = FALSE; // Only when the door is locked do the permissions apply. +integer isOpen = TRUE; +vector openPos = ZERO_VECTOR; +rotation openRot = ZERO_ROTATION; +vector closedPos = ZERO_VECTOR; +rotation closedRot = ZERO_ROTATION; +key openerKey = NULL_KEY; +key closerKey = NULL_KEY; +integer isSetup = FALSE; +integer listenHandle = 0; +string avatarName = ""; + +// zooms the sub-prim to a new rotation and position. +jump_to_position(vector position, rotation new_rot) +{ + list config_blast = [ + PRIM_SIZE, llGetScale(), ///???? + // first jump away from where we started, trying to get past an opensim bug. +// PRIM_POSITION, ZERO_VECTOR, +// PRIM_POSITION, ZERO_VECTOR, +// PRIM_POSITION, ZERO_VECTOR, +// PRIM_POSITION, ZERO_VECTOR, +// PRIM_POSITION, ZERO_VECTOR, + PRIM_ROTATION, ZERO_ROTATION * new_rot / llGetRootRotation(), +// PRIM_POSITION, position, +// PRIM_POSITION, position, +// PRIM_POSITION, position, +// PRIM_POSITION, position, +// PRIM_POSITION, position, + PRIM_POSITION, position + ]; + llSetLinkPrimitiveParams(llGetLinkNumber(), config_blast); +if (DEBUGGING) llOwnerSay("want pos=" + (string)position + ", got=" + (string)llGetLocalPos() ++ ", and want rot=" + (string)new_rot + ", got=" + (string)llGetLocalRot()); +} + +mySayName(integer channel, string objectName, string message) +{ + string name = llGetObjectName(); + llSetObjectName(objectName); + llSay(0, "/me " + message); + llSetObjectName(name); +} + +mySay(integer channel, string message) +{ + string name = llGetObjectName(); + llSetObjectName("Door"); + llSay(0, message); + llSetObjectName(name); +} + +myOwnerSay(string message) +{ + string name = llGetObjectName(); + llSetObjectName("Door"); + llOwnerSay(message); + llSetObjectName(name); +} + +mySoundConfirmed() +{ + if (confirmedSound != "") + { + llTriggerSound(confirmedSound, 1.0); + } +} + +mySoundAccessDenied() +{ + if (accessDeniedSound != "") + { + llTriggerSound(accessDeniedSound, 1.0); + } +} + +myGetDoorParams() +{ + isSetup = FALSE; + if (llSubStringIndex(llGetObjectDesc(), "D;") == 0 && llSubStringIndex(llGetObjectName(), "D;") == 0) + { + list nameWords = llParseString2List(llGetObjectName(), [";"], []); + list descWords = llParseString2List(llGetObjectDesc(), [";"], []); + if (llGetListLength(nameWords) != 3 || llGetListLength(descWords) != 3) + { + myOwnerSay("The door prim's name and/or description has invalid syntax and/or number of parameters. Delete the door prim's name and description and setup the door prim again."); + } + else + { + openPos = (vector)llList2String(nameWords, 1); + openRot = (rotation)llList2String(nameWords, 2); + closedPos = (vector)llList2String(descWords, 1); + closedRot = (rotation)llList2String(descWords, 2); + isSetup = TRUE; + } +//llSay(0, "got open pos=" + (string)(openPos) + " rot=" + (string)(openRot)); +//llSay(0, "got close pos=" + (string)(closedPos) + " rot=" + (string)(closedRot)); + + } +} + +// if open_state is true, the parms are for an open door. +mySetDoorParams(integer open_state, vector Pos, rotation Rot) +{ + if (open_state) { + // parms for open state. + llSetObjectName("D;" + vector_chop(Pos) + ";" + rotation_chop(Rot)); + } else { + // parms for closed state. + llSetObjectDesc("D;" + vector_chop(Pos) + ";" + rotation_chop(Rot)); + } + isSetup = TRUE; +} + +integer myPermissionCheck(key id) +{ + integer hasPermission = FALSE; + if (isLocked == FALSE) { + if (DEBUGGING) llOwnerSay("perm--unlocked: okay"); + hasPermission = TRUE; + } else if (llGetOwnerKey(id) == llGetOwner()) { + if (DEBUGGING) llOwnerSay("perm--is owner: okay"); + hasPermission = TRUE; + } else if (allowGroupToo == TRUE && llSameGroup(id)) { + if (DEBUGGING) llOwnerSay("perm--same group: okay"); + hasPermission = TRUE; + } else if (llListFindList(allowedAgentUUIDs, [(string)id]) != -1) { + if (DEBUGGING) llOwnerSay("perm--in list: okay"); + hasPermission = TRUE; + } else { + if (DEBUGGING) llOwnerSay("perm--not found anywhere: bad perms"); + } + return hasPermission; +} + +myOpenDoor() +{ + isOpen = FALSE; + myToggleDoor(); +} + +myCloseDoor() +{ + isOpen = TRUE; + myToggleDoor(); +} + +myToggleDoor() +{ + if (isSetup == FALSE) + { + myOwnerSay("The door prim has not been configured yet. Please read the usage instructions in the door script."); + } + else if (llGetLinkNumber() == 0 || llGetLinkNumber() == 1) + { + myOwnerSay("The door prim must be linked to at least one other prim and the door prim must not be the root prim"); + } + else + { + isOpen = !isOpen; +if (DEBUGGING) llOwnerSay("door open state is now=" + (string)isOpen); + if (isOpen) + { +if (DEBUGGING) llOwnerSay("opening the door."); + if (doorBellSound != "") + { + llTriggerSound(doorBellSound, 1.0); + if (avatarName != "") + { + mySayName(0, avatarName, "is at the door."); + avatarName = ""; + } + } + if (doorOpenSound != "") + { + llTriggerSound(doorOpenSound, 1.0); + } + jump_to_position(openPos, openRot); +// list config_blast = [ PRIM_POSITION, llGetLocalPos() + <4, 4, 4>, +// PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation(), +// PRIM_POSITION, openPos +//// PRIM_SIZE, llGetScale() +// ]; +// llSetPrimitiveParams(config_blast); +//if (DEBUGGING) llOwnerSay("want pos=" + (string)openPos + ", got=" + (string)llGetLocalPos() +//+ ", and want rot=" + (string)openRot + ", got=" + (string)llGetLocalRot()); + + if (PASS_COMMANDS && !command_is_a_response) { + // Door API. + llMessageLinked(LINK_SET, listenChannel, "cmd|door|open", llGetKey()); + } + command_is_a_response = FALSE; // took care of that one. + } + else + { +if (DEBUGGING) llOwnerSay("closing the door."); + if (doorCloseSound != "") + { + llTriggerSound(doorCloseSound, 1.0); + } + jump_to_position(closedPos, closedRot); +// list config_blast = [ +// PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation(), +// PRIM_POSITION, closedPos +//// PRIM_SIZE, llGetScale() +// ]; +// llSetPrimitiveParams(config_blast); +//if (DEBUGGING) llOwnerSay("want pos=" + (string)closedPos + ", got=" + (string)llGetLocalPos() +//+ ", and want rot=" + (string)closedRot + ", got=" + (string)llGetLocalRot()); + if (PASS_COMMANDS && !command_is_a_response) { + // Door API. + llMessageLinked(LINK_SET, listenChannel, "cmd|door|close", llGetKey()); + } + command_is_a_response = FALSE; // took care of that one. + } + + llSetTimerEvent(0.0); + if (isOpen == TRUE && autoCloseTime != 0.0) + { + llSetTimerEvent(autoCloseTime); + } + } +} + +////////////// +// from hufflets... + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns text for a floating point number, but includes only +// three digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 1000.0) / 1000); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// similarly, for a rotation. +string rotation_chop(rotation to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + "," + + float_chop(to_show.s) + ">"; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + listenHandle = llListen(listenChannel, "", NULL_KEY, ""); + myGetDoorParams(); + myCloseDoor(); + } + + on_rez(integer parm) { llResetScript(); } + + touch_start(integer total_number) + { + command_is_a_response = FALSE; + if (myPermissionCheck(llDetectedKey(0)) == TRUE) + { + avatarName = llDetectedName(0); + myToggleDoor(); + } + else + { + mySoundAccessDenied(); + } + } + + timer() + { + myCloseDoor(); + } + + link_message(integer sender_num, integer num, string str, key id) + { + // Door API. The API is here in case you want to create PIN entry keypads or whatever. + if (num == listenChannel) { + if (id == llGetKey()) return; // don't listen to our own commands. + command_is_a_response = TRUE; + if (str == "cmd|door|open") myOpenDoor(); + else if (str == "cmd|door|close") myCloseDoor(); + else if (str == "cmd|door|discover") + llMessageLinked(LINK_SET, listenChannel, "cmd|door|discovered|" + (string)llGetKey(), + llGetKey()); + else command_is_a_response = FALSE; +//hmmm: above protocol seems redundant, but sending back the original id (like this did before) +// in the id field does not fit in with our usual schemes very well. + } + } + + listen(integer channel, string name, key id, string message) + { +// if (DEBUGGING) llOwnerSay("heard: " + message); + command_is_a_response = FALSE; // don't get involved with the link message checking. + + // Performance note: it's quicker to compare the strings than to compare permissions each time anyone says anything on this channel. + if (message == "open") + { + if (myPermissionCheck(id) == TRUE) + { + // Only open the door if the person is quite close to this door. + openerKey = id; + closerKey = NULL_KEY; + avatarName = name; + llSensor(name, id, AGENT, RESPONSE_DISTANCE, TWO_PI); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "close") + { + if (myPermissionCheck(id) == TRUE) + { + openerKey = NULL_KEY; + closerKey = id; + avatarName = name; + // Only close the door if the person is quite close to this door. + llSensor(name, id, AGENT, RESPONSE_DISTANCE, TWO_PI); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "lock") + { + if (myPermissionCheck(id) == TRUE) + { + isLocked = TRUE; + mySoundConfirmed(); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "unlock") + { + if (myPermissionCheck(id) == TRUE) + { + isLocked = FALSE; + mySoundConfirmed(); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "toggle") + { + if (myPermissionCheck(id) == TRUE) + { + avatarName = name; + myToggleDoor(); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "/door opened" && llSubStringIndex(llGetObjectName(), "D;") == -1) + { + if (llGetOwnerKey(id) == llGetOwner()) + { + mySoundConfirmed(); + openPos = llGetLocalPos(); + openRot = llGetLocalRot(); + isOpen = TRUE; + mySetDoorParams(TRUE, openPos, openRot); +//llSay(0, "set open pos=" + (string)(openPos) + " rot=" + (string)(openRot)); + } + else + { + mySoundAccessDenied(); + } + } + else if (message == "/door closed" && llSubStringIndex(llGetObjectDesc(), "D;") == -1) + { + if (llGetOwnerKey(id) == llGetOwner()) + { + mySoundConfirmed(); + closedPos = llGetLocalPos(); + closedRot = llGetLocalRot(); + isOpen = FALSE; + mySetDoorParams(FALSE, closedPos, closedRot); +//llSay(0, "set close pos=" + (string)(closedPos) + " rot=" + (string)(closedRot)); + } + else + { + mySoundAccessDenied(); + } + } + } + + sensor(integer num_detected) + { + if (openerKey != NULL_KEY) + { + integer i; + for (i = 0; i < num_detected; i++) + { + if (llDetectedKey(i) == openerKey && myPermissionCheck(llDetectedKey(i)) == TRUE) + { + myOpenDoor(); + } + } + openerKey = NULL_KEY; + } + else + { + integer i; + for (i = 0; i < num_detected; i++) + { + if (llDetectedKey(i) == closerKey && myPermissionCheck(llDetectedKey(i)) == TRUE) + { + myCloseDoor(); + } + } + closerKey = NULL_KEY; + } + } + +//------------------------------------------------------ +// Uncomment the following code if you particularly want +// collisions to affect the door state. +//------------------------------------------------------ + +// collision_start(integer num_detected) +// { +// integer i; +// for (i = 0; i < num_detected; i++) +// { +// if (myPermissionCheck(llDetectedKey(i)) == TRUE) +// { +// avatarName = llDetectedName(i); +// myOpenDoor(); +// } +// else if (llDetectedType(i) & AGENT) +// { +// mySoundAccessDenied(); +// } +// } +// } + +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.lsl deleted file mode 100755 index ef201cf7..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.lsl +++ /dev/null @@ -1,940 +0,0 @@ - -// huffware script: huff-update server, by fred huffhines. -// -// this script is the server side of the update process. it should reside in an object that -// has all the newest versions of scripts and objects that will be updated. when rezzed, and -// at periodic intervals, it announces on a private chat channel that updates are available. -// when objects respond that they might like an update, it tells them the scripts that it has -// stored inside of it. if any of those scripts are an older version inside the client -// (update requesting) object, then the client will request the newer versions. the server -// object will stuff them into it and tell them to start running. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. - -integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. - - - -// updater dependency section: -// should be moved to a notecard!!! -// -// format is a list of strings, where each string has a pair wrapped by the -// huffware item separators. the pair contains (1) the basename of a script -// that has a new dependency and (2) the basename of that new dependency. -list known_script_dependencies; - - - - -load_script_deps() -{ - known_script_dependencies = [ - llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), - llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), - llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), - llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), - - -//special purpose -- removes the updater from the elevator buttons... -//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), -// => do not uncomment unless you want your elevators to shed their ability to update. - - - // this allows us to add or remove items above at will without complaints about comma. - llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) - ]; -} - - - - -// global constants... - -integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. - -float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. -string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. -string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. - -integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. - -integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. - -float LONGEST_SLACK_PER_CLIENT = 84.0; - // we allow a client to be out of touch with us for this many seconds. after that, - // we decide it's deceased and remove it from our list. - -integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). - -float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. - -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -float CHANGED_INVENTORY_SNOOZER = 7.0; - // the number of seconds we sleep once we see an inventory change. we don't want to - // react to this immediately. this overrides the normal announcement cycle until it's - // dealt with by the timer. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string UPDATER_BASE_NAME = "huff-update client"; - // the name of the updater script that keeps everything in sync. - -////////////// - -// global variables... - -list scripts_available; // the list of scripts we have in our inventory for distribution. -list objects_available; // list of objects for handing out. - -list active_clients; // list of keys for clients that are updating currently. -list active_update_channels; // active conversations on client chosen channels. -list active_listen_ids; // the ids for the listener on those channels. -list active_timestamps; // tracks when the client was last active. - -integer inventory_request_channel; // our personal channel that the update client should talk with. - -integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. - -// displays the status of the update server. -show_status(key who_says) -{ - string title = "[mem free=" + (string)llGetFreeMemory() + "]"; - title = "Listening for requests on channel " + (string)inventory_request_channel; - if (llGetListLength(active_update_channels)) - title += "\nactive channels=" - + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); - else - title += "\nNo channels active."; - - if (llGetListLength(active_clients)) - title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); - else - title += "\nNo clients active."; - - if (llGetOwner() == who_says) { - string addition = " "; - if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; - title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " - + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " - + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; - } - - llWhisper(0, title); -} - -// plink a quietous string of resonance... -squonk(integer indy) -{ - string snd = llGetInventoryName(INVENTORY_SOUND, indy); - if (snd != "") llTriggerSound(snd, 1.0); -} - -// list out the scripts that the server's object contains. -show_scripts() -{ - string title = (string)llGetListLength(scripts_available) + " scripts available:"; - show_list(title, scripts_available); - title = (string)llGetListLength(objects_available) + " objects available:"; - show_list(title, objects_available); -} - -// lets the client know that we're here and have some scripts available. -announce_presence() -{ - if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { - // only announce if we're not already booked up. - llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); - } -} - -// lifted from "clear text and effects" script; should be nearly identical -// to that, except that we set the texture animation. -reset_all_effects() -{ - llSetText("", <0,0,0>, 0); // clear any text above object. - llSetSitText("Sit Here"); // reset sit text to default state. - llSetTouchText("Touch"); // similarly for touch. - llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. - llParticleSystem([]); // turn off all particles. - llSensorRemove(); // stop any running sensors. - llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. - llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. - // keep it from being physical and from disapparating. - llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, - PRIM_PHANTOM, TRUE]); - llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. - - // - // the following are specific to the huffotronic update server. - // - - // we re-assert our special texture set here, in case some wayward scripts have - // messed with us. - integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); - integer indy; - for (indy = 0; indy < textures_held; indy++) { - string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); - // we have a simple scheme for putting textures on the updater. - // we have an inside, an outside and the ends. - if (is_prefix(curr_tex, "~~s0")) { - llSetTexture(curr_tex, ALL_SIDES); - } else if (is_prefix(curr_tex, "~~s1")) { - llSetTexture(curr_tex, 1); - } else if (is_prefix(curr_tex, "~~s2")) { - llSetTexture(curr_tex, 0); - llSetTexture(curr_tex, 3); - } - } - - // re-assert our texture animation also. - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, - ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); -} - -// set up the update server object. -initialize_root() -{ - // set up our particular "look". - reset_all_effects(); - - // shut down any competing scripts in this object. - // we try to swat any other script that's been added before we let them do weird - // stuff. for example, a pet script might start acting like one. this - // function is not guaranteed to run before that bad stuff can happen, - // and that's maybe the one major issue with this approach. as long as - // the contained scripts aren't evil (like if they jump someplace else - // as soon as they start), then there shouldn't be any serious problems. - knock_down_other_scripts(); - - // reset our variables. - active_update_channels = []; - active_listen_ids = []; - active_clients = []; - active_timestamps = []; - scripts_available = []; - objects_available = []; - dealing_with_change = FALSE; // not handling any inventory changes. - - // make sure we know about any scripts that have new dependencies. - load_script_deps(); - - // clean out any older versions of the scripts before we make our - // inventory. - destroy_older_versions(); - - // now accumulate the list of scripts in our inventory. - integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); - integer indy; - for (indy = 0; indy < items_held; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - // we don't provide our own script for updating; it must be kept from - // floating around, like into other objects that are not updaters. -//// if (curr_script != llGetScriptName()) - scripts_available += curr_script; - } - items_held = llGetInventoryNumber(INVENTORY_OBJECT); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); -//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); - } - items_held = llGetInventoryNumber(INVENTORY_NOTECARD); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); -//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); - } - - // listen to the owner. - llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); - // listen for any requests from our loyal clients. - inventory_request_channel = random_channel(); - llListen(inventory_request_channel, "", NULL_KEY, ""); - // listen for older clients too. - llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); - - // set up the periodic announcements. - llSetTimerEvent(ANNOUNCEMENT_PERIOD); -} - -handle_timer() -{ - if (dealing_with_change) { - dealing_with_change = FALSE; - state rerun; // zoom back to the starting point. - } - integer indy; - integer timecheck = llGetUnixTime(); // use for whole loop. - for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { - integer last_time = llList2Integer(active_timestamps, indy); - if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { - // we need to clear out this item. we know we can whack the client - // at the same index and that will take care of this slacker. - key curr_key = llList2Key(active_clients, indy); - log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); - remove_client(curr_key); - } - } - - // let the objects nearby know that we are open for business by - // announcing the script inventory. - announce_presence(); -} - -// turns a list into a nicely formatted string. -string dump_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string cursc = llList2String(to_show, indy); - msg += cursc; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// similar to dump_keyed_list, but only shows the names, each on their own line. -string dump_names_for_keys(list to_show) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we only line break after the first entry. - if (indy > 0) msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr); - } - return msg; -} - -// similar to dump_list -string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr) + " (" + keystr + ")"; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// shows the list specified in a compact manner. -show_list(string title, list to_show) -{ - string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); - // flush some memory. - title = ""; - to_show = []; - integer indy; - // say the output in pieces to avoid over-clogging chat. - for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { - integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; - string addition; - if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; - llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); - } -} - -// stops all the scripts besides this one. -knock_down_other_scripts() -{ - // set all scripts but this to not be running. - integer indy; - string self_script = llGetScriptName(); - list split = compute_basename_and_version(self_script); - string self_base = llList2String(split, 0); - self_script = ""; split = []; // free memory. - integer count = llGetInventoryNumber(INVENTORY_SCRIPT); - // we set all other scripts that are not versions of this script to not be running. - for (indy = 0; indy < count; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if (!is_prefix(curr_script, self_base) - && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { - llSetScriptState(curr_script, FALSE); - } - } -} - -// set a text label on the updater with the list of clients. -set_our_label() -{ - string label = ""; - if (llGetListLength(active_clients) > 0) label = "[updating]\n"; - llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); -} - -// clean out a client that we should be done with. -remove_client(key id) -{ - // locate said client of deceased nature... - integer indy = find_in_list(active_clients, id); - if (indy < 0) { -// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); - return; - } - active_clients = llDeleteSubList(active_clients, indy, indy); - // also clean out the channel and stop listening to it. -integer act_chan = llList2Integer(active_update_channels, indy); - active_update_channels = llDeleteSubList(active_update_channels, indy, indy); - integer listen_to_remove = llList2Integer(active_listen_ids, indy); -//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); - llListenRemove(listen_to_remove); - active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); - active_timestamps = llDeleteSubList(active_timestamps, indy, indy); - set_our_label(); -} - -// fix a partial match to a script name if we can't find the exact item. -string backpatch_script_name(string partial) -{ - if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. - integer dep_indy; - for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { - string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); - if (is_prefix(curr_name, partial)) { -// log_it("found real name " + curr_name + " for part: " + partial); - return curr_name; - } - } -// log_it("no matches for partial script name!"); - return ""; // no matches! -} - -// moves the upgrade process with "id" along to the next step given the request in -// the message. -propel_upgrade_process(integer channel, key id, string message) -{ - if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); - if (message == REQUEST_SCRIPT_UPDATE) { - // begins the update process with the client. - llSay(channel, SHUT_THEM_DOWN); - } else if (is_prefix(message, READY_TO_UPDATE)) { - // whack the prefix so we can get the list they want. - message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); - list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); - message = ""; - // send over the scripts the client asked for, since it seems to be ready for them. - if (llGetListLength(requests)) { - show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); - integer indy; - for (indy = 0; indy < llGetListLength(requests); indy++) { - string curr = llList2String(requests, indy); - if (find_in_list(objects_available, curr) >= 0) { -//log_it("handing object over: " + curr); - // it's an object, so treat it that way. - llGiveInventory(id, curr); - } else { -//log_it("handing script over: " + curr); - // assume it's a script, and use script pin to stuff it. - curr = backpatch_script_name(curr); - if (curr != "") { -// integer starting_state = FALSE; -// second life was okay with scripts being plugged in unstarted. opensim is not. -// and second life appears to be unhappy with scripts plugged in as started. so we -// have an impasse. -// this should be: true for opensim, and false for second life. - integer starting_state = IS_OPENSIM; -// if (DEBUGGING) log_it("installing script using updater pin."); - llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); - } - } - } - } - } else if (message == SCRIPTS_ARE_CURRENT) { - // the client thinks it's ready to get back up and running. -//log_it("heard client is ready!"); - llSay(channel, START_THEM_UP); - // kludge for older clients (pre 10.4 version) to try to help them start up. -//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); - remove_client(id); - } else if (message == DONE_UPDATING) { - // this client has nothing to do for now. -//log_it("heard client is done: " + (string)id); - remove_client(id); - } else { -//log_it("weird note from client: " + message); - return; // not used. - } - -} - -// blasts out the inventory list to a curious client. -spew_inventory_list(integer channel, string message, key id) -{ - if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { - - // this is an old style update alert that we still use at startup of the client - // to ensure that finishing replacement of the updater script is never unnoticed. - if (is_prefix(message, DONE_UPDATING)) { -// if (DEBUGGING) log_it("found very special message from startup of updater."); - propel_upgrade_process(channel, id, message); - } - - // argh, this is not the right kind of message on our channel. - return; - } - string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); - integer new_update_channel = (integer)chan_str; - if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { - // got to tell them "not right now". we'll pretend we have no - // scripts; they'll know what we mean if the update client is - // recent enough. really old clients will just go to sleep until later. - if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); - llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); - return; - } - - // looks like we're going to try to handle the request for them. - if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); - -//log_it("add client convo chan " + (string)new_update_channel); - integer existing_indy = find_in_list(active_clients, id); - if (existing_indy < 0) { - active_clients += id; - active_update_channels += new_update_channel; - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); - active_listen_ids += new_listen_id; - active_timestamps += llGetUnixTime(); - set_our_label(); - } else { -// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); - // delete old listener so we don't leave it dangling. - integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); -//log_it("remove old listen " + (string)old_listen_id); - llListenRemove(old_listen_id); - // update the channel and listener id for the new registration. - active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) - + [ new_update_channel ] - + chop_list(active_update_channels, existing_indy + 1, - llGetListLength(active_update_channels) - 1); - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add new listen " + (string)new_listen_id); - active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_listen_ids, existing_indy + 1, - llGetListLength(active_listen_ids) - 1); - active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_timestamps, existing_indy + 1, - llGetListLength(active_timestamps) - 1); - } - - // our report name is always called available scripts, but it can actually have - // script dependency definitions, script names and object names. - string msg = REPORT_AVAILABLE_SCRIPTS; - string curr; // temp. - - // add in the huff updater, since that's the most crucial that they know we have. - integer posn; - string UPDATE_CLIENT_SCRIPT = "huff-update client"; - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - == UPDATE_CLIENT_SCRIPT) { -//log_it("found " + curr); - msg += curr + UPDATER_PARM_SEPARATOR; - posn = 99999; // jump out. - } - if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { - log_it("epic fail, found no updater client script."); - } - } - - // speak about the dependencies that we know. - for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { - msg += SCRIPT_DEPENDENCY_MARK - + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // tell this new client what scripts we have. - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - != UPDATE_CLIENT_SCRIPT) { - // add in the next item, along with the parameter separator. - msg += curr + UPDATER_PARM_SEPARATOR; -//log_it("adding " + curr); - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { - // stop sending the list to them since they may not know how - // to interpret a multiple part update list. - return; - } - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - } - // mention any objects that are available. - for (posn = 0; posn < llGetListLength(objects_available); posn++) { - // add in the next item, along with the parameter separator. - msg += llList2String(objects_available, posn) - + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // say final bit, even if it's mostly blank. we need to let them know - // that we're done and not adding that continuation flag string. - llSay(new_update_channel, msg); -} - -// handles verbal commands from objects that want updates. -process_verbal_requests(integer channel, string name, key id, string message) -{ - if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { - spew_inventory_list(channel, message, id); - return; - } else if (channel == USER_COMMAND_CHANNEL) { -if (DEBUGGING) log_it("heard orders: " + message); - // simple verbal commands. - if (message == RESTART_UPDATER_COMMAND) { - log_it("Restarting now."); - llResetScript(); - } else if (message == SHOW_SCRIPTS_COMMAND) { - show_scripts(); - } else if (message == SHUTDOWN_COMMAND) { - // we will de-rez now (i.e., die) if we are not one of the special names that is undying. - if (!matches_substring(llGetObjectName(), "keeper")) { -// log_it("server " + (string)inventory_request_channel + " now disintegrating."); - squonk(1); - llDie(); - } - } - return; - } - - integer indy; - // see if the channel is for one of our valid updates that's in progress. - for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { - integer cur_chan = llList2Integer(active_update_channels, indy); - if (cur_chan == channel) { - // yes, this is really for that guy. - propel_upgrade_process(channel, id, message); - return; - } - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. -// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// a random channel for the first interaction with the client. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } - - if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { - log_it("now restarting to avoid opensim late updating change event."); - llResetScript(); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() - { - auto_retire(); - initialize_root(); // get set up to start answering requests. - llWhisper(0, llGetScriptName() + " started... touch for more info."); - squonk(0); - } - - state_exit() { llSetTimerEvent(0); } - - on_rez(integer parm) { - state rerun; - } - - timer() { handle_timer(); } - - touch_start(integer count) { - show_status(llDetectedKey(0)); - } - - listen(integer channel, string name, key id, string message) { - // make sure that the object is something we should even talk to. - if (llGetOwnerKey(id) != llGetOwner()) { - return; - } - // looks okay, let's see if this is useful communication. - process_verbal_requests(channel, name, id, message); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - log_it("inventory changed, scheduled a restart."); - // sleep a little bit; otherwise we get SL noise about scripts not being - // there when it told us they were there. this can lead to some scripts - // doing bizarre things if they are running when added. - dealing_with_change = TRUE; - llSetTimerEvent(0.0); // kludge to get around second life bug. - llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); - } - } -} - -state rerun { state_entry() { state default; } } - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.txt new file mode 100755 index 00000000..ef201cf7 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/a_huffotronic_update_server_v23.2.txt @@ -0,0 +1,940 @@ + +// huffware script: huff-update server, by fred huffhines. +// +// this script is the server side of the update process. it should reside in an object that +// has all the newest versions of scripts and objects that will be updated. when rezzed, and +// at periodic intervals, it announces on a private chat channel that updates are available. +// when objects respond that they might like an update, it tells them the scripts that it has +// stored inside of it. if any of those scripts are an older version inside the client +// (update requesting) object, then the client will request the newer versions. the server +// object will stuff them into it and tell them to start running. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. + +integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. + + + +// updater dependency section: +// should be moved to a notecard!!! +// +// format is a list of strings, where each string has a pair wrapped by the +// huffware item separators. the pair contains (1) the basename of a script +// that has a new dependency and (2) the basename of that new dependency. +list known_script_dependencies; + + + + +load_script_deps() +{ + known_script_dependencies = [ + llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), + llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), + llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), + llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), + + +//special purpose -- removes the updater from the elevator buttons... +//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), +// => do not uncomment unless you want your elevators to shed their ability to update. + + + // this allows us to add or remove items above at will without complaints about comma. + llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) + ]; +} + + + + +// global constants... + +integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. + +float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. +string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. +string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. + +integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. + +integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. + +float LONGEST_SLACK_PER_CLIENT = 84.0; + // we allow a client to be out of touch with us for this many seconds. after that, + // we decide it's deceased and remove it from our list. + +integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). + +float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. + +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +float CHANGED_INVENTORY_SNOOZER = 7.0; + // the number of seconds we sleep once we see an inventory change. we don't want to + // react to this immediately. this overrides the normal announcement cycle until it's + // dealt with by the timer. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string UPDATER_BASE_NAME = "huff-update client"; + // the name of the updater script that keeps everything in sync. + +////////////// + +// global variables... + +list scripts_available; // the list of scripts we have in our inventory for distribution. +list objects_available; // list of objects for handing out. + +list active_clients; // list of keys for clients that are updating currently. +list active_update_channels; // active conversations on client chosen channels. +list active_listen_ids; // the ids for the listener on those channels. +list active_timestamps; // tracks when the client was last active. + +integer inventory_request_channel; // our personal channel that the update client should talk with. + +integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. + +// displays the status of the update server. +show_status(key who_says) +{ + string title = "[mem free=" + (string)llGetFreeMemory() + "]"; + title = "Listening for requests on channel " + (string)inventory_request_channel; + if (llGetListLength(active_update_channels)) + title += "\nactive channels=" + + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); + else + title += "\nNo channels active."; + + if (llGetListLength(active_clients)) + title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); + else + title += "\nNo clients active."; + + if (llGetOwner() == who_says) { + string addition = " "; + if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; + title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " + + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " + + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; + } + + llWhisper(0, title); +} + +// plink a quietous string of resonance... +squonk(integer indy) +{ + string snd = llGetInventoryName(INVENTORY_SOUND, indy); + if (snd != "") llTriggerSound(snd, 1.0); +} + +// list out the scripts that the server's object contains. +show_scripts() +{ + string title = (string)llGetListLength(scripts_available) + " scripts available:"; + show_list(title, scripts_available); + title = (string)llGetListLength(objects_available) + " objects available:"; + show_list(title, objects_available); +} + +// lets the client know that we're here and have some scripts available. +announce_presence() +{ + if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { + // only announce if we're not already booked up. + llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); + } +} + +// lifted from "clear text and effects" script; should be nearly identical +// to that, except that we set the texture animation. +reset_all_effects() +{ + llSetText("", <0,0,0>, 0); // clear any text above object. + llSetSitText("Sit Here"); // reset sit text to default state. + llSetTouchText("Touch"); // similarly for touch. + llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. + llParticleSystem([]); // turn off all particles. + llSensorRemove(); // stop any running sensors. + llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. + llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. + // keep it from being physical and from disapparating. + llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, + PRIM_PHANTOM, TRUE]); + llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. + + // + // the following are specific to the huffotronic update server. + // + + // we re-assert our special texture set here, in case some wayward scripts have + // messed with us. + integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); + integer indy; + for (indy = 0; indy < textures_held; indy++) { + string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); + // we have a simple scheme for putting textures on the updater. + // we have an inside, an outside and the ends. + if (is_prefix(curr_tex, "~~s0")) { + llSetTexture(curr_tex, ALL_SIDES); + } else if (is_prefix(curr_tex, "~~s1")) { + llSetTexture(curr_tex, 1); + } else if (is_prefix(curr_tex, "~~s2")) { + llSetTexture(curr_tex, 0); + llSetTexture(curr_tex, 3); + } + } + + // re-assert our texture animation also. + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, + ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); +} + +// set up the update server object. +initialize_root() +{ + // set up our particular "look". + reset_all_effects(); + + // shut down any competing scripts in this object. + // we try to swat any other script that's been added before we let them do weird + // stuff. for example, a pet script might start acting like one. this + // function is not guaranteed to run before that bad stuff can happen, + // and that's maybe the one major issue with this approach. as long as + // the contained scripts aren't evil (like if they jump someplace else + // as soon as they start), then there shouldn't be any serious problems. + knock_down_other_scripts(); + + // reset our variables. + active_update_channels = []; + active_listen_ids = []; + active_clients = []; + active_timestamps = []; + scripts_available = []; + objects_available = []; + dealing_with_change = FALSE; // not handling any inventory changes. + + // make sure we know about any scripts that have new dependencies. + load_script_deps(); + + // clean out any older versions of the scripts before we make our + // inventory. + destroy_older_versions(); + + // now accumulate the list of scripts in our inventory. + integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); + integer indy; + for (indy = 0; indy < items_held; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + // we don't provide our own script for updating; it must be kept from + // floating around, like into other objects that are not updaters. +//// if (curr_script != llGetScriptName()) + scripts_available += curr_script; + } + items_held = llGetInventoryNumber(INVENTORY_OBJECT); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); +//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); + } + items_held = llGetInventoryNumber(INVENTORY_NOTECARD); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); +//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); + } + + // listen to the owner. + llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); + // listen for any requests from our loyal clients. + inventory_request_channel = random_channel(); + llListen(inventory_request_channel, "", NULL_KEY, ""); + // listen for older clients too. + llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); + + // set up the periodic announcements. + llSetTimerEvent(ANNOUNCEMENT_PERIOD); +} + +handle_timer() +{ + if (dealing_with_change) { + dealing_with_change = FALSE; + state rerun; // zoom back to the starting point. + } + integer indy; + integer timecheck = llGetUnixTime(); // use for whole loop. + for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { + integer last_time = llList2Integer(active_timestamps, indy); + if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { + // we need to clear out this item. we know we can whack the client + // at the same index and that will take care of this slacker. + key curr_key = llList2Key(active_clients, indy); + log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); + remove_client(curr_key); + } + } + + // let the objects nearby know that we are open for business by + // announcing the script inventory. + announce_presence(); +} + +// turns a list into a nicely formatted string. +string dump_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string cursc = llList2String(to_show, indy); + msg += cursc; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// similar to dump_keyed_list, but only shows the names, each on their own line. +string dump_names_for_keys(list to_show) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we only line break after the first entry. + if (indy > 0) msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr); + } + return msg; +} + +// similar to dump_list +string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr) + " (" + keystr + ")"; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// shows the list specified in a compact manner. +show_list(string title, list to_show) +{ + string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); + // flush some memory. + title = ""; + to_show = []; + integer indy; + // say the output in pieces to avoid over-clogging chat. + for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { + integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; + string addition; + if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; + llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); + } +} + +// stops all the scripts besides this one. +knock_down_other_scripts() +{ + // set all scripts but this to not be running. + integer indy; + string self_script = llGetScriptName(); + list split = compute_basename_and_version(self_script); + string self_base = llList2String(split, 0); + self_script = ""; split = []; // free memory. + integer count = llGetInventoryNumber(INVENTORY_SCRIPT); + // we set all other scripts that are not versions of this script to not be running. + for (indy = 0; indy < count; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if (!is_prefix(curr_script, self_base) + && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { + llSetScriptState(curr_script, FALSE); + } + } +} + +// set a text label on the updater with the list of clients. +set_our_label() +{ + string label = ""; + if (llGetListLength(active_clients) > 0) label = "[updating]\n"; + llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); +} + +// clean out a client that we should be done with. +remove_client(key id) +{ + // locate said client of deceased nature... + integer indy = find_in_list(active_clients, id); + if (indy < 0) { +// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); + return; + } + active_clients = llDeleteSubList(active_clients, indy, indy); + // also clean out the channel and stop listening to it. +integer act_chan = llList2Integer(active_update_channels, indy); + active_update_channels = llDeleteSubList(active_update_channels, indy, indy); + integer listen_to_remove = llList2Integer(active_listen_ids, indy); +//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); + llListenRemove(listen_to_remove); + active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); + active_timestamps = llDeleteSubList(active_timestamps, indy, indy); + set_our_label(); +} + +// fix a partial match to a script name if we can't find the exact item. +string backpatch_script_name(string partial) +{ + if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. + integer dep_indy; + for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { + string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); + if (is_prefix(curr_name, partial)) { +// log_it("found real name " + curr_name + " for part: " + partial); + return curr_name; + } + } +// log_it("no matches for partial script name!"); + return ""; // no matches! +} + +// moves the upgrade process with "id" along to the next step given the request in +// the message. +propel_upgrade_process(integer channel, key id, string message) +{ + if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); + if (message == REQUEST_SCRIPT_UPDATE) { + // begins the update process with the client. + llSay(channel, SHUT_THEM_DOWN); + } else if (is_prefix(message, READY_TO_UPDATE)) { + // whack the prefix so we can get the list they want. + message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); + list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); + message = ""; + // send over the scripts the client asked for, since it seems to be ready for them. + if (llGetListLength(requests)) { + show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); + integer indy; + for (indy = 0; indy < llGetListLength(requests); indy++) { + string curr = llList2String(requests, indy); + if (find_in_list(objects_available, curr) >= 0) { +//log_it("handing object over: " + curr); + // it's an object, so treat it that way. + llGiveInventory(id, curr); + } else { +//log_it("handing script over: " + curr); + // assume it's a script, and use script pin to stuff it. + curr = backpatch_script_name(curr); + if (curr != "") { +// integer starting_state = FALSE; +// second life was okay with scripts being plugged in unstarted. opensim is not. +// and second life appears to be unhappy with scripts plugged in as started. so we +// have an impasse. +// this should be: true for opensim, and false for second life. + integer starting_state = IS_OPENSIM; +// if (DEBUGGING) log_it("installing script using updater pin."); + llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); + } + } + } + } + } else if (message == SCRIPTS_ARE_CURRENT) { + // the client thinks it's ready to get back up and running. +//log_it("heard client is ready!"); + llSay(channel, START_THEM_UP); + // kludge for older clients (pre 10.4 version) to try to help them start up. +//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); + remove_client(id); + } else if (message == DONE_UPDATING) { + // this client has nothing to do for now. +//log_it("heard client is done: " + (string)id); + remove_client(id); + } else { +//log_it("weird note from client: " + message); + return; // not used. + } + +} + +// blasts out the inventory list to a curious client. +spew_inventory_list(integer channel, string message, key id) +{ + if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { + + // this is an old style update alert that we still use at startup of the client + // to ensure that finishing replacement of the updater script is never unnoticed. + if (is_prefix(message, DONE_UPDATING)) { +// if (DEBUGGING) log_it("found very special message from startup of updater."); + propel_upgrade_process(channel, id, message); + } + + // argh, this is not the right kind of message on our channel. + return; + } + string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); + integer new_update_channel = (integer)chan_str; + if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { + // got to tell them "not right now". we'll pretend we have no + // scripts; they'll know what we mean if the update client is + // recent enough. really old clients will just go to sleep until later. + if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); + llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); + return; + } + + // looks like we're going to try to handle the request for them. + if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); + +//log_it("add client convo chan " + (string)new_update_channel); + integer existing_indy = find_in_list(active_clients, id); + if (existing_indy < 0) { + active_clients += id; + active_update_channels += new_update_channel; + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); + active_listen_ids += new_listen_id; + active_timestamps += llGetUnixTime(); + set_our_label(); + } else { +// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); + // delete old listener so we don't leave it dangling. + integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); +//log_it("remove old listen " + (string)old_listen_id); + llListenRemove(old_listen_id); + // update the channel and listener id for the new registration. + active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) + + [ new_update_channel ] + + chop_list(active_update_channels, existing_indy + 1, + llGetListLength(active_update_channels) - 1); + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add new listen " + (string)new_listen_id); + active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_listen_ids, existing_indy + 1, + llGetListLength(active_listen_ids) - 1); + active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_timestamps, existing_indy + 1, + llGetListLength(active_timestamps) - 1); + } + + // our report name is always called available scripts, but it can actually have + // script dependency definitions, script names and object names. + string msg = REPORT_AVAILABLE_SCRIPTS; + string curr; // temp. + + // add in the huff updater, since that's the most crucial that they know we have. + integer posn; + string UPDATE_CLIENT_SCRIPT = "huff-update client"; + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + == UPDATE_CLIENT_SCRIPT) { +//log_it("found " + curr); + msg += curr + UPDATER_PARM_SEPARATOR; + posn = 99999; // jump out. + } + if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { + log_it("epic fail, found no updater client script."); + } + } + + // speak about the dependencies that we know. + for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { + msg += SCRIPT_DEPENDENCY_MARK + + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // tell this new client what scripts we have. + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + != UPDATE_CLIENT_SCRIPT) { + // add in the next item, along with the parameter separator. + msg += curr + UPDATER_PARM_SEPARATOR; +//log_it("adding " + curr); + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { + // stop sending the list to them since they may not know how + // to interpret a multiple part update list. + return; + } + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + } + // mention any objects that are available. + for (posn = 0; posn < llGetListLength(objects_available); posn++) { + // add in the next item, along with the parameter separator. + msg += llList2String(objects_available, posn) + + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // say final bit, even if it's mostly blank. we need to let them know + // that we're done and not adding that continuation flag string. + llSay(new_update_channel, msg); +} + +// handles verbal commands from objects that want updates. +process_verbal_requests(integer channel, string name, key id, string message) +{ + if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { + spew_inventory_list(channel, message, id); + return; + } else if (channel == USER_COMMAND_CHANNEL) { +if (DEBUGGING) log_it("heard orders: " + message); + // simple verbal commands. + if (message == RESTART_UPDATER_COMMAND) { + log_it("Restarting now."); + llResetScript(); + } else if (message == SHOW_SCRIPTS_COMMAND) { + show_scripts(); + } else if (message == SHUTDOWN_COMMAND) { + // we will de-rez now (i.e., die) if we are not one of the special names that is undying. + if (!matches_substring(llGetObjectName(), "keeper")) { +// log_it("server " + (string)inventory_request_channel + " now disintegrating."); + squonk(1); + llDie(); + } + } + return; + } + + integer indy; + // see if the channel is for one of our valid updates that's in progress. + for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { + integer cur_chan = llList2Integer(active_update_channels, indy); + if (cur_chan == channel) { + // yes, this is really for that guy. + propel_upgrade_process(channel, id, message); + return; + } + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. +// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// a random channel for the first interaction with the client. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } + + if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { + log_it("now restarting to avoid opensim late updating change event."); + llResetScript(); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() + { + auto_retire(); + initialize_root(); // get set up to start answering requests. + llWhisper(0, llGetScriptName() + " started... touch for more info."); + squonk(0); + } + + state_exit() { llSetTimerEvent(0); } + + on_rez(integer parm) { + state rerun; + } + + timer() { handle_timer(); } + + touch_start(integer count) { + show_status(llDetectedKey(0)); + } + + listen(integer channel, string name, key id, string message) { + // make sure that the object is something we should even talk to. + if (llGetOwnerKey(id) != llGetOwner()) { + return; + } + // looks okay, let's see if this is useful communication. + process_verbal_requests(channel, name, id, message); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + log_it("inventory changed, scheduled a restart."); + // sleep a little bit; otherwise we get SL noise about scripts not being + // there when it told us they were there. this can lead to some scripts + // doing bizarre things if they are running when added. + dealing_with_change = TRUE; + llSetTimerEvent(0.0); // kludge to get around second life bug. + llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); + } + } +} + +state rerun { state_entry() { state default; } } + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.lsl deleted file mode 100755 index 6a7b67cc..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.lsl +++ /dev/null @@ -1,189 +0,0 @@ - -// huffware script: anti-idler mojo, by fred huffhines -// -// original version was by kwipper manimal. that script has been augmented with -// a better anti-idle animation and some other additions. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -float TIMER_INTERVAL = 28.0; // number of seconds between checks on avatar health. - -float JUMP_AROUND_INTERVAL = 241.0; // how often (in seconds) to move around a bit. - -float JUMP_AROUND_RUN_TIME = 4.0; // number of seconds to do the animation. - -integer last_jumped = 0; // when did we last jump jump jump around. - -integer animation_is_running = FALSE; // is there an animation playing right now? - -get_perms() -{ - llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); - llSetTimerEvent(TIMER_INTERVAL); // always set a timer, so we can check on state. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - get_perms(); - } - - changed(integer change){ - if (change & 128){ -//ugly use of constant - llResetScript(); - } - } - - attach(key id) { - if (id != NULL_KEY) { - get_perms(); - } - } - - run_time_permissions(integer perm) { - if (perm & PERMISSION_TRIGGER_ANIMATION) { -////not here. llSetTimerEvent(TIMER_INTERVAL); - // anything we do want to do here? - } - } - - timer() { - if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { - // turn off the away animation, just in case. - llStopAnimation("away"); - // were we doing an animation in the previous loop cycle? - if (animation_is_running) { - animation_is_running = FALSE; - llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION, 0)); - // back to normal timing now. - llSetTimerEvent(TIMER_INTERVAL); - } - if (llAbs(last_jumped - llGetUnixTime()) >= JUMP_AROUND_INTERVAL) { - // time to jump around with our expected animation. - // hopefully this makes the avatar seem more awake to sl. - if (llGetInventoryNumber(INVENTORY_ANIMATION) > 0) { -//llOwnerSay("found animation to play: " + llGetInventoryName(INVENTORY_ANIMATION, 0)); - llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION, 0)); - } - last_jumped = llGetUnixTime(); - animation_is_running = TRUE; - // only let the animation play for our specified timing. - llSetTimerEvent(JUMP_AROUND_RUN_TIME); - } - } else { -llOwnerSay("croaking in timer because we don't have animation permissions; resetting."); - llResetScript(); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.txt new file mode 100755 index 00000000..6a7b67cc --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/anti-idler_mojo_v1.4.txt @@ -0,0 +1,189 @@ + +// huffware script: anti-idler mojo, by fred huffhines +// +// original version was by kwipper manimal. that script has been augmented with +// a better anti-idle animation and some other additions. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +float TIMER_INTERVAL = 28.0; // number of seconds between checks on avatar health. + +float JUMP_AROUND_INTERVAL = 241.0; // how often (in seconds) to move around a bit. + +float JUMP_AROUND_RUN_TIME = 4.0; // number of seconds to do the animation. + +integer last_jumped = 0; // when did we last jump jump jump around. + +integer animation_is_running = FALSE; // is there an animation playing right now? + +get_perms() +{ + llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); + llSetTimerEvent(TIMER_INTERVAL); // always set a timer, so we can check on state. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + get_perms(); + } + + changed(integer change){ + if (change & 128){ +//ugly use of constant + llResetScript(); + } + } + + attach(key id) { + if (id != NULL_KEY) { + get_perms(); + } + } + + run_time_permissions(integer perm) { + if (perm & PERMISSION_TRIGGER_ANIMATION) { +////not here. llSetTimerEvent(TIMER_INTERVAL); + // anything we do want to do here? + } + } + + timer() { + if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { + // turn off the away animation, just in case. + llStopAnimation("away"); + // were we doing an animation in the previous loop cycle? + if (animation_is_running) { + animation_is_running = FALSE; + llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION, 0)); + // back to normal timing now. + llSetTimerEvent(TIMER_INTERVAL); + } + if (llAbs(last_jumped - llGetUnixTime()) >= JUMP_AROUND_INTERVAL) { + // time to jump around with our expected animation. + // hopefully this makes the avatar seem more awake to sl. + if (llGetInventoryNumber(INVENTORY_ANIMATION) > 0) { +//llOwnerSay("found animation to play: " + llGetInventoryName(INVENTORY_ANIMATION, 0)); + llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION, 0)); + } + last_jumped = llGetUnixTime(); + animation_is_running = TRUE; + // only let the animation play for our specified timing. + llSetTimerEvent(JUMP_AROUND_RUN_TIME); + } + } else { +llOwnerSay("croaking in timer because we don't have animation permissions; resetting."); + llResetScript(); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.lsl deleted file mode 100755 index 9c960281..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.lsl +++ /dev/null @@ -1,111 +0,0 @@ - -//////////////[copy starting here...]////////////// -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// -//////////////[end of area to copy]////////////// - -////////////// -// this is how a user of the auto_retire script gets the retirement process -// to work. whenever the script goes into its default state, such as when dropped -// into an object, this function invocation makes sure that no earlier versions -// of our script are left in inventory. -default -{ - state_entry() { - auto_retire(); - } -} -////////////// diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.txt new file mode 100755 index 00000000..9c960281 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/auto-retire_v2.8.txt @@ -0,0 +1,111 @@ + +//////////////[copy starting here...]////////////// +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// +//////////////[end of area to copy]////////////// + +////////////// +// this is how a user of the auto_retire script gets the retirement process +// to work. whenever the script goes into its default state, such as when dropped +// into an object, this function invocation makes sure that no earlier versions +// of our script are left in inventory. +default +{ + state_entry() { + auto_retire(); + } +} +////////////// diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.lsl deleted file mode 100755 index 9653ec0d..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.lsl +++ /dev/null @@ -1,499 +0,0 @@ - -// huffware script: card configurator, by fred huffhines. -// -// processes a notecard with configuration info, then sends the information as packages of -// configuration nuggest to a consuming script. this is one level above the noteworthy script, -// which simply reads the notecard. this script keeps the config parsing out of higher-level -// scripts. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -integer MAXIMUM_ITEMS_PER_BURST = 6; - // try this out as a good limit for the size of the sends. - -// global variables... - -string signature_required; - // sent to us when the request for configuration info is made. - -list good_prefixes; - // similarly, a set of prefixes for notecard lines that the calling script - // cares about. if this is empty, then anything will match. - -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -list global_responses; // the items we want to send back to the requestor. - -// card configurator link message API: -////////////// -// do not redefine these constants. -integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; - // the unique id within the huffware system for the card configurator script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string BAD_NOTECARD_TEXT = "*badcrd*"; - // the sign that we hated the notecards we found, or there were none. -string FINISHED_READING_NOTECARDS = "**finished**"; - // the sign that we are done plowing through the card we found. -string BEGIN_READING_NOTECARD_COMMAND = "#read-cfg#"; - // requests that the configurator find a good notecard and read its contents. - // it should send the contents via the alert below. first parm is the signature and - // second is the wrapped list of valid item prefixes. -string READ_PARTICULAR_NOTECARD_COMMAND = "#read-note#"; - // requests that the configurator find a good notecard and read its contents. - // it should send the contents via the alert below. first two parms are the same as - // begin reading notecard, and the third parameter is the name of the specific notecard. -string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; - // this message is sent when the configurator has found some data updates or has finished - // reading the configuration file. -////////////// - -// imported interfaces below... - -// requires noteworthy library v8.5 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -// commands available via the noteworthy library: -string BUSY_READING_INDICATOR = "busy_already"; - // this return value indicates that the script is already in use by some other script. - // the calling script should try again later. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - global_notecard_name = ""; // reset any previous card. - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([signature_required, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -request_specific_configuration() -{ - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([signature_required, response_code, global_notecard_name]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_SPECIFIC_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from the noteworthy library. -process_notecard(integer which, integer num, string msg, key id) -{ - if (msg != READ_NOTECARD_COMMAND) return; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return; // oops, this isn't for us. - if (notecard_name != BAD_NOTECARD_TEXT) { - // a valid notecard has been found. - global_notecard_name = notecard_name; // record its name for later use. - // snag all but the first two elements for our config now. - global_config_list = llList2List(parms, 2, -1); - parms = []; // toss the old copy. - // and process the file as a set of definitions. - process_ini_config(); - send_data_burst(); // send any pending configs out. - if (notecard_name != NOTECARD_READ_CONTINUATION) { -//log_it("sending final sentinel at end of card."); - // blast out a fake data burst that means we're done reading. - global_notecard_name = FINISHED_READING_NOTECARDS; - global_responses += [ FINISHED_READING_NOTECARDS ]; - send_data_burst(); - } -//log_it("after config read, memory left=" + (string)llGetFreeMemory()); - } else { - // we hated the notecards we found, or there were none. - // send a failure response. - llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, - CARD_CONFIG_RECEIVED_ALERT, wrap_parameters([BAD_NOTECARD_TEXT])); - } -} - -/////////////// - -// sends the currently held data out to whoever requested it. -send_data_burst() -{ - if (!llGetListLength(global_responses)) return; // nothing to send. -//log_it("sending " + (string)llGetListLength(global_responses) + " items"); - llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, CARD_CONFIG_RECEIVED_ALERT, - wrap_parameters([global_notecard_name] + global_responses)); - global_responses = []; // reset any items held. -} - -// consumes the notecard in a very application specific way to retrieve our configuration items. -// the example script only looks for two variables: name and description. if those are found in -// the sample card, then they are proudly shown. -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - list x_y = separate_variable_definition(to_parse); - string x = llList2String(x_y, 0); - if (!llGetListLength(good_prefixes)) { - global_responses += x_y; - } else { - integer indy; - for (indy = 0; indy < llGetListLength(good_prefixes); indy++) { - // if it's one of our desired prefixes, then we add it. - if (is_prefix(x, llList2String(good_prefixes, indy))) { - global_responses += x_y; - indy = llGetListLength(good_prefixes) + 5; // skip rest of loop. - } - } - } - - if (llGetListLength(global_responses) > MAXIMUM_ITEMS_PER_BURST) { - send_data_burst(); - } -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ -// log_it("scanning notecard for variable definitions..."); - integer indy; - integer count = llGetListLength(global_config_list); - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = 0; indy < count; indy++) { - string line = llList2String(global_config_list, indy); -//log_it("ini proc: " + line); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. -// log_it("reading section: " + llGetSubString(line, 1, -2)); -// global_responses += [ line, "e" ]; - indy++; // skip the section line. - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - if (sec_indy == count) indy = count + 3; // skip out of loop now. - } - global_config_list = []; // we ate it! -} - -initialize_specific(string specific_card) -{ - // reset our relevant variables. - global_notecard_name = specific_card; - global_config_list = []; - global_responses = []; - - // request that the noteworthy library start looking for our notecard. - request_specific_configuration(); -} - -initialize() -{ - // reset our relevant variables. - global_notecard_name = ""; - global_config_list = []; - global_responses = []; - - // request that the noteworthy library start looking for our notecard. - request_configuration(); -} - -////////////// -// from hufflets... -// -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -////////////// - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. -///log_it("got x = " + x + " and y = " + y); - return [ strip_spaces(x), strip_spaces(y) ]; -} -// -// end hufflets -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - } - - on_rez(integer parm) { state rerun; } - - link_message(integer sender, integer num, string msg, key id) { - if (num == NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) { - if (msg == READ_NOTECARD_COMMAND) { - process_notecard(sender, num, msg, id); - } - return; - } - - if (num != CARD_CONFIGURATOR_HUFFWARE_ID) return; // not even slightly for us. - - if (msg == BEGIN_READING_NOTECARD_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - signature_required = llList2String(parms, 0); - string prefixes_wrap = llList2String(parms, 1); -//log_it("pref raw is: " + prefixes_wrap); - good_prefixes = llParseString2List(prefixes_wrap, [HUFFWARE_ITEM_SEPARATOR], []); -//log_it("signature to find: " + signature_required); - initialize(); -//log_it("prefixes are: " + (string)good_prefixes); -//log_it("began reading, memory left=" + (string)llGetFreeMemory()); - return; - } - if (msg == READ_PARTICULAR_NOTECARD_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - signature_required = llList2String(parms, 0); - string prefixes_wrap = llList2String(parms, 1); - string specific_card = llList2String(parms, 2); -//log_it("pref raw is: " + prefixes_wrap); - good_prefixes = llParseString2List(prefixes_wrap, [HUFFWARE_ITEM_SEPARATOR], []); -//log_it("signature to find: " + signature_required); - initialize_specific(specific_card); -//log_it("prefixes are: " + (string)good_prefixes); -//log_it("notecard is: " + specific_card); -//log_it("began reading, memory left=" + (string)llGetFreeMemory()); - return; - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.txt new file mode 100755 index 00000000..9653ec0d --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/card_configurator_v8.1.txt @@ -0,0 +1,499 @@ + +// huffware script: card configurator, by fred huffhines. +// +// processes a notecard with configuration info, then sends the information as packages of +// configuration nuggest to a consuming script. this is one level above the noteworthy script, +// which simply reads the notecard. this script keeps the config parsing out of higher-level +// scripts. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +integer MAXIMUM_ITEMS_PER_BURST = 6; + // try this out as a good limit for the size of the sends. + +// global variables... + +string signature_required; + // sent to us when the request for configuration info is made. + +list good_prefixes; + // similarly, a set of prefixes for notecard lines that the calling script + // cares about. if this is empty, then anything will match. + +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +list global_responses; // the items we want to send back to the requestor. + +// card configurator link message API: +////////////// +// do not redefine these constants. +integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; + // the unique id within the huffware system for the card configurator script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string BAD_NOTECARD_TEXT = "*badcrd*"; + // the sign that we hated the notecards we found, or there were none. +string FINISHED_READING_NOTECARDS = "**finished**"; + // the sign that we are done plowing through the card we found. +string BEGIN_READING_NOTECARD_COMMAND = "#read-cfg#"; + // requests that the configurator find a good notecard and read its contents. + // it should send the contents via the alert below. first parm is the signature and + // second is the wrapped list of valid item prefixes. +string READ_PARTICULAR_NOTECARD_COMMAND = "#read-note#"; + // requests that the configurator find a good notecard and read its contents. + // it should send the contents via the alert below. first two parms are the same as + // begin reading notecard, and the third parameter is the name of the specific notecard. +string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; + // this message is sent when the configurator has found some data updates or has finished + // reading the configuration file. +////////////// + +// imported interfaces below... + +// requires noteworthy library v8.5 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +// commands available via the noteworthy library: +string BUSY_READING_INDICATOR = "busy_already"; + // this return value indicates that the script is already in use by some other script. + // the calling script should try again later. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + global_notecard_name = ""; // reset any previous card. + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([signature_required, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +request_specific_configuration() +{ + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([signature_required, response_code, global_notecard_name]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_SPECIFIC_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from the noteworthy library. +process_notecard(integer which, integer num, string msg, key id) +{ + if (msg != READ_NOTECARD_COMMAND) return; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return; // oops, this isn't for us. + if (notecard_name != BAD_NOTECARD_TEXT) { + // a valid notecard has been found. + global_notecard_name = notecard_name; // record its name for later use. + // snag all but the first two elements for our config now. + global_config_list = llList2List(parms, 2, -1); + parms = []; // toss the old copy. + // and process the file as a set of definitions. + process_ini_config(); + send_data_burst(); // send any pending configs out. + if (notecard_name != NOTECARD_READ_CONTINUATION) { +//log_it("sending final sentinel at end of card."); + // blast out a fake data burst that means we're done reading. + global_notecard_name = FINISHED_READING_NOTECARDS; + global_responses += [ FINISHED_READING_NOTECARDS ]; + send_data_burst(); + } +//log_it("after config read, memory left=" + (string)llGetFreeMemory()); + } else { + // we hated the notecards we found, or there were none. + // send a failure response. + llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, + CARD_CONFIG_RECEIVED_ALERT, wrap_parameters([BAD_NOTECARD_TEXT])); + } +} + +/////////////// + +// sends the currently held data out to whoever requested it. +send_data_burst() +{ + if (!llGetListLength(global_responses)) return; // nothing to send. +//log_it("sending " + (string)llGetListLength(global_responses) + " items"); + llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, CARD_CONFIG_RECEIVED_ALERT, + wrap_parameters([global_notecard_name] + global_responses)); + global_responses = []; // reset any items held. +} + +// consumes the notecard in a very application specific way to retrieve our configuration items. +// the example script only looks for two variables: name and description. if those are found in +// the sample card, then they are proudly shown. +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + list x_y = separate_variable_definition(to_parse); + string x = llList2String(x_y, 0); + if (!llGetListLength(good_prefixes)) { + global_responses += x_y; + } else { + integer indy; + for (indy = 0; indy < llGetListLength(good_prefixes); indy++) { + // if it's one of our desired prefixes, then we add it. + if (is_prefix(x, llList2String(good_prefixes, indy))) { + global_responses += x_y; + indy = llGetListLength(good_prefixes) + 5; // skip rest of loop. + } + } + } + + if (llGetListLength(global_responses) > MAXIMUM_ITEMS_PER_BURST) { + send_data_burst(); + } +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ +// log_it("scanning notecard for variable definitions..."); + integer indy; + integer count = llGetListLength(global_config_list); + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = 0; indy < count; indy++) { + string line = llList2String(global_config_list, indy); +//log_it("ini proc: " + line); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. +// log_it("reading section: " + llGetSubString(line, 1, -2)); +// global_responses += [ line, "e" ]; + indy++; // skip the section line. + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + if (sec_indy == count) indy = count + 3; // skip out of loop now. + } + global_config_list = []; // we ate it! +} + +initialize_specific(string specific_card) +{ + // reset our relevant variables. + global_notecard_name = specific_card; + global_config_list = []; + global_responses = []; + + // request that the noteworthy library start looking for our notecard. + request_specific_configuration(); +} + +initialize() +{ + // reset our relevant variables. + global_notecard_name = ""; + global_config_list = []; + global_responses = []; + + // request that the noteworthy library start looking for our notecard. + request_configuration(); +} + +////////////// +// from hufflets... +// +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +////////////// + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. +///log_it("got x = " + x + " and y = " + y); + return [ strip_spaces(x), strip_spaces(y) ]; +} +// +// end hufflets +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + } + + on_rez(integer parm) { state rerun; } + + link_message(integer sender, integer num, string msg, key id) { + if (num == NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) { + if (msg == READ_NOTECARD_COMMAND) { + process_notecard(sender, num, msg, id); + } + return; + } + + if (num != CARD_CONFIGURATOR_HUFFWARE_ID) return; // not even slightly for us. + + if (msg == BEGIN_READING_NOTECARD_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + signature_required = llList2String(parms, 0); + string prefixes_wrap = llList2String(parms, 1); +//log_it("pref raw is: " + prefixes_wrap); + good_prefixes = llParseString2List(prefixes_wrap, [HUFFWARE_ITEM_SEPARATOR], []); +//log_it("signature to find: " + signature_required); + initialize(); +//log_it("prefixes are: " + (string)good_prefixes); +//log_it("began reading, memory left=" + (string)llGetFreeMemory()); + return; + } + if (msg == READ_PARTICULAR_NOTECARD_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + signature_required = llList2String(parms, 0); + string prefixes_wrap = llList2String(parms, 1); + string specific_card = llList2String(parms, 2); +//log_it("pref raw is: " + prefixes_wrap); + good_prefixes = llParseString2List(prefixes_wrap, [HUFFWARE_ITEM_SEPARATOR], []); +//log_it("signature to find: " + signature_required); + initialize_specific(specific_card); +//log_it("prefixes are: " + (string)good_prefixes); +//log_it("notecard is: " + specific_card); +//log_it("began reading, memory left=" + (string)llGetFreeMemory()); + return; + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.lsl deleted file mode 100755 index 76cbc3aa..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.lsl +++ /dev/null @@ -1,151 +0,0 @@ - -// huffware script: change click action, by fred huffhines. -// -// a simple script for sub-prims in an object where you want the whole object's -// click action to change. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// change click action's link message API... -////////////// -integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -////////////// -// -// the API only supports the service number; there are no commands to pass in the "msg" -// parameter. the id does accept a parameter, which is the type of click action to begin -// using for this prim. -// -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - } - - link_message(integer which, integer num, string msg, key id) - { - // we only allow this action change on sub-prims. - if ( (num == CHANGE_CLICK_ACTION_HUFFWARE_ID) && (llGetLinkNumber() != 1) ) { - llSetClickAction((integer)((string)id)); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.txt new file mode 100755 index 00000000..76cbc3aa --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/change_click_action_v1.0.txt @@ -0,0 +1,151 @@ + +// huffware script: change click action, by fred huffhines. +// +// a simple script for sub-prims in an object where you want the whole object's +// click action to change. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// change click action's link message API... +////////////// +integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +////////////// +// +// the API only supports the service number; there are no commands to pass in the "msg" +// parameter. the id does accept a parameter, which is the type of click action to begin +// using for this prim. +// +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + } + + link_message(integer which, integer num, string msg, key id) + { + // we only allow this action change on sub-prims. + if ( (num == CHANGE_CLICK_ACTION_HUFFWARE_ID) && (llGetLinkNumber() != 1) ) { + llSetClickAction((integer)((string)id)); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.lsl deleted file mode 100755 index d550a277..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.lsl +++ /dev/null @@ -1,150 +0,0 @@ - -// huffware script: clear text and effects, by fred huffhines -// -// a simple helper for cleaning the text off of objects after a script has -// set the sit text or main text. it also stops any particle systems that -// had been running previously and stops any sensors. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - - llSetText("", <0,0,0>, 0); // clear any text above object. - llSetSitText("Sit Here"); // reset sit text to default state. - llSetTouchText("Touch"); // similarly for touch. - llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. - - llParticleSystem([]); // turn off all particles. - - llSensorRemove(); // stop any running sensors. - - llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. - - llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); // stop texture animations. - - llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. - llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. - - // keep it from being physical and from disapparating. - llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE]); - } - - // make sure that we apply these settings when the object is rezzed, if it - // had been stored with annoying text or whatever and needs to be cleared. - on_rez(integer parm) { llResetScript(); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.txt new file mode 100755 index 00000000..d550a277 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/clear_text_and_effects_v2.2.txt @@ -0,0 +1,150 @@ + +// huffware script: clear text and effects, by fred huffhines +// +// a simple helper for cleaning the text off of objects after a script has +// set the sit text or main text. it also stops any particle systems that +// had been running previously and stops any sensors. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + + llSetText("", <0,0,0>, 0); // clear any text above object. + llSetSitText("Sit Here"); // reset sit text to default state. + llSetTouchText("Touch"); // similarly for touch. + llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. + + llParticleSystem([]); // turn off all particles. + + llSensorRemove(); // stop any running sensors. + + llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. + + llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); // stop texture animations. + + llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. + llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. + + // keep it from being physical and from disapparating. + llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE]); + } + + // make sure that we apply these settings when the object is rezzed, if it + // had been stored with annoying text or whatever and needs to be cleared. + on_rez(integer parm) { llResetScript(); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.lsl deleted file mode 100755 index dc4b0293..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.lsl +++ /dev/null @@ -1,256 +0,0 @@ - -// huffware script: color smoove clock, by fred huffhines -// -// A clock with rotating color text, adjustable for your time zone. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants you might want to modify... - -integer TIME_ZONE = -5; - // the time zone you want the clock to display, measured as an offset from GMT. - -float TIMER_INTERVAL = 0.1; - // how frequently timer is hit to adjust color and possibly change time text. - -float MAX_RANDOM_COLOR_JUMP = 0.07; - // how much the color might change in one timer hit for one R/G/B component. - -// global variables... - -// remembers the last time string we printed, since we want to be modifying the -// colors more frequently than we're changing the clock. -string global_time_string = ""; - -// track how many ticks have hit the timer. only updates the time when a whole -// second has gone by. -integer global_tick_counter = 0; - -// the current color for clock text; the default is just a starting point. -vector global_text_color = <0.3, 0.6, 0.8>; - -// records whether the value is going up (positive) or down (negative). -float global_elevator_x = -1.0; -float global_elevator_y = 1.0; -float global_elevator_z = 1.0; - -// do not change the following constants... - -integer PST_TIME_ZONE = -8; // this constant for the pacific time zone's offset from GMT. - -// makes sure components of the color don't go out of range. if they do, then -// the elevator direction is reversed. -normalize_color() -{ - if (global_text_color.x > 1.0) { global_text_color.x = 1.0; global_elevator_x *= -1.0; } - if (global_text_color.x < 0.0) { global_text_color.x = 0.0; global_elevator_x *= -1.0; } - if (global_text_color.y > 1.0) { global_text_color.y = 1.0; global_elevator_y *= -1.0; } - if (global_text_color.y < 0.0) { global_text_color.y = 0.0; global_elevator_y *= -1.0; } - if (global_text_color.z > 1.0) { global_text_color.z = 1.0; global_elevator_z *= -1.0; } - if (global_text_color.z < 0.0) { global_text_color.z = 0.0; global_elevator_z *= -1.0; } -} - -// show the current time string in our current color. -display_colored_text() -{ - llSetText(global_time_string, global_text_color, 1.0); -} - -rotate_text_color() -{ - // gnarly version is totally random. merely an example now. -//yuck; flashy global_text_color = ; - - // better; rotates the colors as slow as you like, but somewhat randomly - // for an interesting color glide effect. - global_text_color.x += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_x; - global_text_color.y += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_y; - global_text_color.z += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_z; - - normalize_color(); // make sure we didn't go out of bounds. - - display_colored_text(); // update to the new color. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - // state_entry() is an event handler, it executes whenever a state is entered. - state_entry() - { - auto_retire(); - llSetTimerEvent(TIMER_INTERVAL); - } - - timer() - { - // calculate our current rate of timer hits. - float ticks_per_second = 1.0 / TIMER_INTERVAL; - - rotate_text_color(); // spin the text color every timer hit. - - // check whether the clock time has changed since last updated. - global_tick_counter++; - if (global_tick_counter < ticks_per_second) { - return; - } - // yep, we need to update the text of the time. - global_tick_counter = 0; // reset for rollover. - - // get the number of seconds off of the clock on the wall... - integer full_seconds = llFloor(llGetWallclock()); - - // switch to the chosen time zone. - full_seconds += -(PST_TIME_ZONE - TIME_ZONE) * 60 * 60; - - // a constant for how many seconds exist in a day. - integer DAY_OF_SECONDS = 24 * 60 * 60; - - // correct any tendency of the seconds to be below zero or above the maximum - // due to wacky time zones. - while (full_seconds < 0) full_seconds += DAY_OF_SECONDS; - while (full_seconds > DAY_OF_SECONDS) full_seconds -= DAY_OF_SECONDS; - - // calculate all the components of the time. - integer seconds = full_seconds; - integer minutes = llFloor(seconds / 60); - seconds -= minutes * 60; - integer hour = llFloor(minutes / 60); - minutes -= hour * 60; -//llOwnerSay("fs=" + (string)full_seconds + " h=" + (string)hour + " m=" + (string)minutes); - - integer is_am = hour < 12; - if (hour > 12) hour -= 12; // convert down to 12 hour time. - if (hour == 0) hour = 12; // don't show a zero in 12 hour time. - - // prepare the time update message... - string minutes_text = (string)minutes; - if (minutes < 10) minutes_text = "0" + minutes_text; - string seconds_text = (string)seconds; - if (seconds < 10) seconds_text = "0" + seconds_text; - - string meridian_string = "am"; - if (!is_am) meridian_string = "pm"; - - // update our time string now that we know all the pieces. - global_time_string = (string)hour + ":" + minutes_text + ":" - + seconds_text + meridian_string; - // flip the text up above the object to show the time. - display_colored_text(); - } - -} - -//credits: -// parts from lsl wiki originally? -// Enables an object to display the time for the time zone of your choosing. -// Thanks to Ben Linden for insight into timers, time and text setting. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.txt new file mode 100755 index 00000000..dc4b0293 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/color_smoove_clock_v3.2.txt @@ -0,0 +1,256 @@ + +// huffware script: color smoove clock, by fred huffhines +// +// A clock with rotating color text, adjustable for your time zone. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants you might want to modify... + +integer TIME_ZONE = -5; + // the time zone you want the clock to display, measured as an offset from GMT. + +float TIMER_INTERVAL = 0.1; + // how frequently timer is hit to adjust color and possibly change time text. + +float MAX_RANDOM_COLOR_JUMP = 0.07; + // how much the color might change in one timer hit for one R/G/B component. + +// global variables... + +// remembers the last time string we printed, since we want to be modifying the +// colors more frequently than we're changing the clock. +string global_time_string = ""; + +// track how many ticks have hit the timer. only updates the time when a whole +// second has gone by. +integer global_tick_counter = 0; + +// the current color for clock text; the default is just a starting point. +vector global_text_color = <0.3, 0.6, 0.8>; + +// records whether the value is going up (positive) or down (negative). +float global_elevator_x = -1.0; +float global_elevator_y = 1.0; +float global_elevator_z = 1.0; + +// do not change the following constants... + +integer PST_TIME_ZONE = -8; // this constant for the pacific time zone's offset from GMT. + +// makes sure components of the color don't go out of range. if they do, then +// the elevator direction is reversed. +normalize_color() +{ + if (global_text_color.x > 1.0) { global_text_color.x = 1.0; global_elevator_x *= -1.0; } + if (global_text_color.x < 0.0) { global_text_color.x = 0.0; global_elevator_x *= -1.0; } + if (global_text_color.y > 1.0) { global_text_color.y = 1.0; global_elevator_y *= -1.0; } + if (global_text_color.y < 0.0) { global_text_color.y = 0.0; global_elevator_y *= -1.0; } + if (global_text_color.z > 1.0) { global_text_color.z = 1.0; global_elevator_z *= -1.0; } + if (global_text_color.z < 0.0) { global_text_color.z = 0.0; global_elevator_z *= -1.0; } +} + +// show the current time string in our current color. +display_colored_text() +{ + llSetText(global_time_string, global_text_color, 1.0); +} + +rotate_text_color() +{ + // gnarly version is totally random. merely an example now. +//yuck; flashy global_text_color = ; + + // better; rotates the colors as slow as you like, but somewhat randomly + // for an interesting color glide effect. + global_text_color.x += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_x; + global_text_color.y += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_y; + global_text_color.z += llFrand(MAX_RANDOM_COLOR_JUMP) * global_elevator_z; + + normalize_color(); // make sure we didn't go out of bounds. + + display_colored_text(); // update to the new color. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + // state_entry() is an event handler, it executes whenever a state is entered. + state_entry() + { + auto_retire(); + llSetTimerEvent(TIMER_INTERVAL); + } + + timer() + { + // calculate our current rate of timer hits. + float ticks_per_second = 1.0 / TIMER_INTERVAL; + + rotate_text_color(); // spin the text color every timer hit. + + // check whether the clock time has changed since last updated. + global_tick_counter++; + if (global_tick_counter < ticks_per_second) { + return; + } + // yep, we need to update the text of the time. + global_tick_counter = 0; // reset for rollover. + + // get the number of seconds off of the clock on the wall... + integer full_seconds = llFloor(llGetWallclock()); + + // switch to the chosen time zone. + full_seconds += -(PST_TIME_ZONE - TIME_ZONE) * 60 * 60; + + // a constant for how many seconds exist in a day. + integer DAY_OF_SECONDS = 24 * 60 * 60; + + // correct any tendency of the seconds to be below zero or above the maximum + // due to wacky time zones. + while (full_seconds < 0) full_seconds += DAY_OF_SECONDS; + while (full_seconds > DAY_OF_SECONDS) full_seconds -= DAY_OF_SECONDS; + + // calculate all the components of the time. + integer seconds = full_seconds; + integer minutes = llFloor(seconds / 60); + seconds -= minutes * 60; + integer hour = llFloor(minutes / 60); + minutes -= hour * 60; +//llOwnerSay("fs=" + (string)full_seconds + " h=" + (string)hour + " m=" + (string)minutes); + + integer is_am = hour < 12; + if (hour > 12) hour -= 12; // convert down to 12 hour time. + if (hour == 0) hour = 12; // don't show a zero in 12 hour time. + + // prepare the time update message... + string minutes_text = (string)minutes; + if (minutes < 10) minutes_text = "0" + minutes_text; + string seconds_text = (string)seconds; + if (seconds < 10) seconds_text = "0" + seconds_text; + + string meridian_string = "am"; + if (!is_am) meridian_string = "pm"; + + // update our time string now that we know all the pieces. + global_time_string = (string)hour + ":" + minutes_text + ":" + + seconds_text + meridian_string; + // flip the text up above the object to show the time. + display_colored_text(); + } + +} + +//credits: +// parts from lsl wiki originally? +// Enables an object to display the time for the time zone of your choosing. +// Thanks to Ben Linden for insight into timers, time and text setting. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.lsl deleted file mode 100755 index 202c58f7..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.lsl +++ /dev/null @@ -1,882 +0,0 @@ - -// huffware script: comfortable sitting, by fred huffhines. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -// global constants... - -string NOTEWORTHY_SIGNATURE = "#sitting"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -////////////// - -// global variables that are loaded from a notecard. - -vector AVATAR_ROTATION = <0, 0, -90>; // star chair. -//vector AVATAR_ROTATION = <0, 0, 0>; - // the euler vector for rotation of the avatar after sitting, in degrees. - // the rotation vector should be tailored to the object. - -vector AVATAR_POSITION = <-0.1, -0.28, -0.1>; // star chair. -//vector AVATAR_POSITION = <0.34, 0, 0>; - // the position of the sitting offset from the object center. also needs to be - // tailored to the particular object. - -integer GOTO_WHICH_FLOOR = 1; - // when serving as an elevator, this is a way to cause the teleport offset - // to go to a particular floor. the real z position is calculated from - // this times the floor size in meters. note that floors are numbered - // starting at 1 (one). - -float FLOOR_SIZE_IN_METERS = 0.0; - // when the script is used in an elevator, this specifies the height of the - // floors. our current scheme will only work if that is constant between - // the floors. - -float BASE_FLOOR_HEIGHT = 0.0; - // the position of the first floor in meters. this will not affect the - // position calculations unless floor size is non-zero. - -integer UNSEAT_AFTERWARDS = FALSE; - // if this is true, then the avatar is unseated just after sitting down. - -float PAUSE_BEFORE_EVICTION = 0.28; - // the number of seconds that the avatars get to sit before we pop them - // out of the chair/teleporter/whatever. - -vector CAMERA_EYE_OFFSET = <3, 2, 1.5>; // star chair. - // the offset for the camera after the avatar sits down. -//relative to the avatar? - -vector CAMERA_TARGET = <-3, 0, 1>; // star chair. - // the location where the camera is looking at once the avatar sits down. -//relative to the avatar? - -////////////// - -// global variables used in processing notecards... - -integer pending_response_id; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -////////////// - -// interfaces for library scripts we rely on... - -// requires noteworthy library. -// in this odd case, where we are trying to shrink script count, the noteworthy library -// is embedded inside here. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// establishes the sitting parameters including camera offsets. -setup_seating_arrangements() -{ - llUnSit(llAvatarOnSitTarget()); // no one gets to ignore a script change. - vector new_rot = AVATAR_ROTATION; - new_rot *= DEG_TO_RAD; // convert to radians. - rotation quat = llEuler2Rot(new_rot); // convert to quaternion. - // get our position set up and take into account the elevator position. - vector position = AVATAR_POSITION; -//rename that variable to be "which floor to go to" - if (FLOOR_SIZE_IN_METERS != 0) { - vector temp = llGetPos(); - integer my_floor = (integer) ((temp.z - BASE_FLOOR_HEIGHT ) / FLOOR_SIZE_IN_METERS) + 1; -//log_it("my floor is " + (string)my_floor); - float add_in = (float)(GOTO_WHICH_FLOOR - my_floor) * FLOOR_SIZE_IN_METERS; -//log_it("decided to add in z: " + (string)add_in); - position += <0, 0, add_in>; - } - // also we make this absolute by taking out the object's own rotation. - // it's hard enough in life for z components to not mean z axis. - position /= llGetRot(); - llSitTarget(position, quat / llGetRot()); -//hmmm: do we need same rot treatment on camera things? -//hmmm: trying it. - // now set the camera position to avoid having random viewpoint. - llSetCameraEyeOffset(CAMERA_EYE_OFFSET / llGetRot()); - llSetCameraAtOffset(CAMERA_TARGET / llGetRot()); -} - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - // try to find a notecard with our configuration. - pending_response_id = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([NOTEWORTHY_SIGNATURE, pending_response_id]); -//call direct into noteworthy. -noteworthy_handle_link_message(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, parms_sent); - -// llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, -// parms_sent); -} - -// processes link messages received from the noteworthy library. -handle_link_message(integer which, integer num, string msg, key id) -{ - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) - return; // not for us. -//log_it("handl: msg=" + msg + " id=" + id); - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); -//log_it("raw is " + llList2String(parms, 1)); - integer response_for = llList2Integer(parms, 1); -//log_it("resp cod=" + pending_response_id + " but this for=" + response_for); -//if (response_for != pending_response_id) log_it("bad response code???"); - if (response_for != pending_response_id) return; // oops, this isn't for us. - if (notecard_name == BAD_NOTECARD_INDICATOR) { - // we hated the notecards we found, or there were none. - log_it("We apologize; there seem to be no notecards with a first line of '" - + NOTEWORTHY_SIGNATURE - + "'. We can't read any configuration until that situation improves."); - } else { -//log_it("got to handle link"); - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - // make sure we shouldn't keep going. - if (notecard_name != NOTECARD_READ_CONTINUATION) { - // a valid notecard has been found. - global_config_index = 0; // we are starting over in the config list. -// log_it("read notecard \"" + notecard_name + "\":"); - // and process the file as a set of definitions. - process_ini_config(); - // now that we have a new set of parameters, use them. - setup_seating_arrangements(); - } - } -} - -/////////////// - -// consumes the notecard in a very application specific way to retrieve our configuration items. -// the example script only looks for two variables: name and description. if those are found in -// the sample card, then they are proudly shown. -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - if ( (content = get_variable_value(to_parse, "avatar_rotation")) != "") { - AVATAR_ROTATION = (vector)content; -// log_it("** got avatar_rotation of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "avatar_position")) != "") { - AVATAR_POSITION = (vector)content; -// log_it("** got avatar_position of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "goto_which_floor")) != "") { - GOTO_WHICH_FLOOR = (integer)content; -// log_it("** got GOTO_WHICH_FLOOR of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "floor_size_in_meters")) != "") { - FLOOR_SIZE_IN_METERS = (float)content; -// log_it("** got FLOOR_SIZE_IN_METERS of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "base_floor_height")) != "") { - BASE_FLOOR_HEIGHT = (float)content; -// log_it("** got BASE_FLOOR_HEIGHT of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "unseat_afterwards")) != "") { - UNSEAT_AFTERWARDS = (integer)content; -// log_it("** got unseat_afterwards of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "pause_before_eviction")) != "") { - PAUSE_BEFORE_EVICTION = (float)content; -// log_it("** got pause_before_eviction of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "camera_eye_offset")) != "") { - CAMERA_EYE_OFFSET = (vector)content; -// log_it("** got camera_eye_offset of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "camera_target")) != "") { - CAMERA_TARGET = (vector)content; -// log_it("** got camera_target of '" + content + "'"); -// } else { -// log_it("unknown variable seen: " + to_parse); - } -} - -initialize() -{ - // reset our relevant variables. - global_config_list = []; - global_config_index = 0; - - // announce that we're open for business. -/// log_it("started, free mem=" + (string)llGetFreeMemory()); - - // request that the noteworthy library start looking for our notecard. - request_configuration(); - - integer indy = 32; - while (indy >= 0) { - indy = find_in_inventory_partial("noteworthy", INVENTORY_SCRIPT); - if (indy >= 0) { - llRemoveInventory(llGetInventoryName(INVENTORY_SCRIPT, indy)); - } - } - -} - -////////////// -// from hufflets... -// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ strip_spaces(x), strip_spaces(y) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ -// log_it("scanning notecard for variable definitions..."); - integer indy; - integer count = llGetListLength(global_config_list); - string section_name; // set later if we see one. - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - section_name = llGetSubString(line, 1, -2); - log_it("reading section: " + section_name); - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - indy = sec_indy; // track that we've passed this line. - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory_partial(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) - return inv; - } - return -2; // failed to find it. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 1.9. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// -// example usage of the auto-retirement script: -// -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - if ((float)inv_version_string < (float)version_string) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. - - string basename = to_chop_up; // script name with no version attached. - - integer posn; - // minimum script name is 2 characters plus version. - for (posn = llStringLength(to_chop_up) - 1; - (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); - posn--) { - // find the space. do nothing else. - } - if (posn < 2) return []; // no space found. - string full_suffix = llGetSubString(to_chop_up, posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets -////////////// - -////////////// -// from noteworthy: - -// huffware script: noteworthy library, by fred huffhines. -// -// a handy approach to reading a notecard. this version supports requiring -// a 'signature' in the notecard's first line, so that multiple notecards can -// exist in an object without being misinterpreted. the script is accessed via -// its link message API, so it can be used in an object without all this code -// needing to be embedded in another script. it also supports queuing up requests -// to read notecards, so multiple scripts can use it to read their specific -// notecards without any special handling (besides waiting a bit longer). -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants that can be adapted to your needs... - -integer DEBUGGING = FALSE; - // if this is true, then a lot of extra noise is generated when notecards are read. - -float TIME_OUT_ON_ONE_NOTECARD = 120.0; - // we allow one line of a notecard this long to be read before we decide it's hosed. - // some sims are very very slow, and a time-out of one minute has been found lacking; - // we saw at least one case where the first notecard line to be read took longer than - // 60 seconds. that's why we keep cranking this time-out up... - -// constants that should not be changed... - -// outcomes from handling a line in a notecard. -integer STILL_READING = -8; // the notecard seems good, but isn't finished. -integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. -integer DONE_READING = -10; // the notecard is finished being read. - -integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. - -integer MAXIMUM_LINES_USED = 4; - // we will read this many lines at a time from the appropriate notecard. -// global variables... - -string requested_signature = ""; - // if this is non-empty, then it must be found in the first line of the script. - -integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. - -string global_notecard_name; // the name of the card we're reading now. -key global_query_id = NULL_KEY; // the identifier of our data query. -integer current_response_code = 0; // the code that our client uses for its reading. -list global_query_contents; // the lines we have read from the notecard. - -integer line_number = 0; // which line are we at in notecard? - -integer found_signature_line = FALSE; // did we find our first line in a notecard yet? - -integer trying_notecard_at = -1; // where we are currently looking for a good notecard. - -list pending_signatures; // signatures from queued requests for reading. -list pending_response_codes; // response codes for the queued requests. -list pending_notecard_names; // card names if it's a specific request. - -////////////// - -startup_initialize() -{ - llSetTimerEvent(0.0); - pending_signatures = []; - pending_response_codes = []; - pending_notecard_names = []; - current_response_code = 0; -} - -reset_for_reading(string signature, integer response_code_in) -{ - requested_signature = signature; - current_response_code = response_code_in; - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. - global_query_contents = []; - global_notecard_name = ""; - line_number = 0; - found_signature_line = FALSE; - trying_notecard_at = -1; - global_query_id = NULL_KEY; -} - -// use the existing global notecard setting to start reading. -select_specific_notecard() -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - line_number = 0; // reset line number again. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// picks the notecard at the "index" (from 0 to num_notecards - 1) and -// starts reading it. -select_notecard(integer index) -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); - if (card_specified == "") return; // not good. bad index. - global_notecard_name = card_specified; - line_number = 0; // reset line number again. - // we have a new file name, so load up the destinations, hopefully. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// increments our index in the count of notecards that the object has, and start -// reading the next notecard (at the index). -integer try_next_notecard() -{ - if (only_read_one_notecard) { - return FALSE; // we were only going to try one. - } - // reset some values that might have applied before. - global_notecard_name = ""; - // skip to the next card. - trying_notecard_at++; - // make sure we're not over the count of cards. - if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { - // this is a problem. we didn't find anything suitable. - return FALSE; - } - // so, now we'll try the next notecard to look for our signature. - select_notecard(trying_notecard_at); - return TRUE; -} - -// process a line of text that we received from the current notecard. -integer handle_notecard_line(key query_id, string data) -{ - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - // there's more to read in the notecard still. - if (data != "") { - // make sure we even have a signature to look for. - if (!found_signature_line && (requested_signature == "")) { - // no signature means that we always find it. - found_signature_line = TRUE; - } - // did we already get our signature? if not, see if this is it. - if (!found_signature_line && (data != requested_signature) ) { - // this is a bad notecard. skip it. - if (!try_next_notecard()) { - // we have no more to work with. - return BAD_NOTECARD; - } - return STILL_READING; // we'll keep going. - } else if (!found_signature_line && (data == requested_signature) ) { - // this is a good signature line, so record that and then skip it. - found_signature_line = TRUE; - } else { - if (DEBUGGING - && ( ( (requested_signature == "") && (line_number == 0) ) - || ( (requested_signature != "") && (line_number == 1) ) ) ) { - log_it("started reading " + global_notecard_name + "..."); - } - // don't record any lines that are comments. - if ( (llGetSubString(data, 0, 0) != "#") - && (llGetSubString(data, 0, 0) != ";") ) { - // add the non-blank line to our list. - global_query_contents += data; - // make sure we still have enough space to keep going. - if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { - // ooh, make sure we pause before blowing our heap&stack. - send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, - current_response_code ], READ_NOTECARD_COMMAND, TRUE); - } - } - } - } - line_number++; // increase the line count. - // reset the timer rather than timing out, if we actually got some data. - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); - // request the next line from the notecard. - global_query_id = llGetNotecardLine(global_notecard_name, line_number); - if (global_query_id == NULL_KEY) { -//log_it("failed to restart notecard reading."); - return DONE_READING; -//is that the best outcome? - } - return STILL_READING; - } else { - // that's the end of the notecard. we need some minimal verification that it - // wasn't full of garbage. - if (!found_signature_line) { - if (DEBUGGING) log_it("never found signature in " + global_notecard_name); - if (!try_next_notecard()) { - return BAD_NOTECARD; // we failed to find a good line? - } else { - // the next notecard's coming through now. - return STILL_READING; - } - } else { -// if (DEBUGGING) log_it("found signature."); - // saw the signature line, so this is a good one. - return DONE_READING; - } - } -} - -// only sends reply; does not reset notecard process. -send_reply(integer destination, list parms, string command, - integer include_query) -{ -//log_it("froyo: curre code=" + current_response_code); -//integer items = llGetListLength(parms); -//if (include_query) items += llGetListLength(global_query_contents); -//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); - - if (!include_query) { - handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - } else { - handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, - llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); - } - global_query_contents = []; -//log_it("post-sending, mem=" + (string)llGetFreeMemory()); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply_and_reset(integer destination, list parms, string command, - integer include_query) -{ - llSetTimerEvent(0.0); // stop the timer, since we're about to reply. - send_reply(destination, parms, command, include_query); -//log_it("about to reset response code"); - current_response_code = 0; // reset back to default so we can start another read. - global_query_id = NULL_KEY; // reset so we accept no more data. -} - -// if there are other pending notecard reads, this goes to the next one listed. -dequeue_next_request() -{ - if (llGetListLength(pending_signatures)) { - // get the info from the next pending item. - string sig = llList2String(pending_signatures, 0); - integer response_code_temp = llList2Integer(pending_response_codes, 0); - string notecard = llList2String(pending_notecard_names, 0); - // whack the head of the queue since we grabbed the info. - pending_signatures = llDeleteSubList(pending_signatures, 0, 0); - pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); - pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); - if (llStringLength(notecard)) { - global_notecard_name = notecard; - select_specific_notecard(); - } else { - reset_for_reading(sig, response_code_temp); - } - } -} - -// deals with one data server answer from the notecard. -process_notecard_line(key query_id, string data) -{ - // try to consume a line from the notecard. - integer outcome = handle_notecard_line(query_id, data); - if (outcome == DONE_READING) { - // that was a valid notecard and we read all of it. - if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); - // send back the results. - send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], - READ_NOTECARD_COMMAND, TRUE); - } else if (outcome == BAD_NOTECARD) { - // bail; this problem must be addressed by other means. - if (DEBUGGING) log_it("failed to find an appropriate notecard"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } else if (outcome == STILL_READING) { - // we have a good card and are still processing it. - return; - } else { - if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); - // again, bail out. we have no idea what happened with this. - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } - // if we have reached here, we should crank up the next queued notecard reading. - dequeue_next_request(); -} - -// processes requests from our users. -noteworthy_handle_link_message(integer which, integer num, string msg, key id) -{ - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - - if (msg == READ_NOTECARD_COMMAND) { - only_read_one_notecard = FALSE; // general inquiry for any card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read notecard--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code_temp = llList2Integer(parms, 1); -//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code_temp); - if (!try_next_notecard()) { - if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code_temp ], - READ_NOTECARD_COMMAND, FALSE); - return; - } -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code_temp; -//holding: pending_notecard_names += ""; -//holding: } - } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { - only_read_one_notecard = TRUE; // they want one particular card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read specific--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code_temp = llList2Integer(parms, 1); - string notecard_name = llList2String(parms, 2); -//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code_temp); - global_notecard_name = notecard_name; // set our global. - select_specific_notecard(); -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code_temp; -//holding: pending_notecard_names += notecard_name; -//holding: } - } -} - - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. -/////not needed now llSleep(1.0); // snooze just a bit to let noteworthy start up? - startup_initialize(); - initialize(); // start asking about the notecards. - setup_seating_arrangements(); // use our current defaults for sitting posn. - } - - on_rez(integer parm) { llResetScript(); } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { -// llSleep(3.14159265358); // delay to avoid interfering with upgrade. - llResetScript(); - } - if (!(change & CHANGED_LINK)) return; // don't care. - if (!UNSEAT_AFTERWARDS) return; // nothing else below is needed. - if (llAvatarOnSitTarget() == NULL_KEY) return; // no one there, so ditto. - // now give them a bit of time to rest before dumping them. - llSetTimerEvent(PAUSE_BEFORE_EVICTION); - } - - timer() { - if (current_response_code != 0) { - llSetTimerEvent(0.0); // stop any timer now. - // let the caller know this has failed out. - if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - current_response_code = 0; // we gave up on that one. - dequeue_next_request(); // get next reading started if we have anything to read. - } else { - // perform short range teleport, effectively... - llUnSit(llAvatarOnSitTarget()); // ha, got that guy back up. - llSetTimerEvent(0.0); // reset timer. - } - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - dataserver(key query_id, string data) { - // make sure this data is for us. - if (global_query_id != query_id) return; - // yep, seems to be. - process_notecard_line(query_id, data); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.txt new file mode 100755 index 00000000..202c58f7 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/comfortable_sitting_v7.5.txt @@ -0,0 +1,882 @@ + +// huffware script: comfortable sitting, by fred huffhines. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +// global constants... + +string NOTEWORTHY_SIGNATURE = "#sitting"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +////////////// + +// global variables that are loaded from a notecard. + +vector AVATAR_ROTATION = <0, 0, -90>; // star chair. +//vector AVATAR_ROTATION = <0, 0, 0>; + // the euler vector for rotation of the avatar after sitting, in degrees. + // the rotation vector should be tailored to the object. + +vector AVATAR_POSITION = <-0.1, -0.28, -0.1>; // star chair. +//vector AVATAR_POSITION = <0.34, 0, 0>; + // the position of the sitting offset from the object center. also needs to be + // tailored to the particular object. + +integer GOTO_WHICH_FLOOR = 1; + // when serving as an elevator, this is a way to cause the teleport offset + // to go to a particular floor. the real z position is calculated from + // this times the floor size in meters. note that floors are numbered + // starting at 1 (one). + +float FLOOR_SIZE_IN_METERS = 0.0; + // when the script is used in an elevator, this specifies the height of the + // floors. our current scheme will only work if that is constant between + // the floors. + +float BASE_FLOOR_HEIGHT = 0.0; + // the position of the first floor in meters. this will not affect the + // position calculations unless floor size is non-zero. + +integer UNSEAT_AFTERWARDS = FALSE; + // if this is true, then the avatar is unseated just after sitting down. + +float PAUSE_BEFORE_EVICTION = 0.28; + // the number of seconds that the avatars get to sit before we pop them + // out of the chair/teleporter/whatever. + +vector CAMERA_EYE_OFFSET = <3, 2, 1.5>; // star chair. + // the offset for the camera after the avatar sits down. +//relative to the avatar? + +vector CAMERA_TARGET = <-3, 0, 1>; // star chair. + // the location where the camera is looking at once the avatar sits down. +//relative to the avatar? + +////////////// + +// global variables used in processing notecards... + +integer pending_response_id; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +////////////// + +// interfaces for library scripts we rely on... + +// requires noteworthy library. +// in this odd case, where we are trying to shrink script count, the noteworthy library +// is embedded inside here. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// establishes the sitting parameters including camera offsets. +setup_seating_arrangements() +{ + llUnSit(llAvatarOnSitTarget()); // no one gets to ignore a script change. + vector new_rot = AVATAR_ROTATION; + new_rot *= DEG_TO_RAD; // convert to radians. + rotation quat = llEuler2Rot(new_rot); // convert to quaternion. + // get our position set up and take into account the elevator position. + vector position = AVATAR_POSITION; +//rename that variable to be "which floor to go to" + if (FLOOR_SIZE_IN_METERS != 0) { + vector temp = llGetPos(); + integer my_floor = (integer) ((temp.z - BASE_FLOOR_HEIGHT ) / FLOOR_SIZE_IN_METERS) + 1; +//log_it("my floor is " + (string)my_floor); + float add_in = (float)(GOTO_WHICH_FLOOR - my_floor) * FLOOR_SIZE_IN_METERS; +//log_it("decided to add in z: " + (string)add_in); + position += <0, 0, add_in>; + } + // also we make this absolute by taking out the object's own rotation. + // it's hard enough in life for z components to not mean z axis. + position /= llGetRot(); + llSitTarget(position, quat / llGetRot()); +//hmmm: do we need same rot treatment on camera things? +//hmmm: trying it. + // now set the camera position to avoid having random viewpoint. + llSetCameraEyeOffset(CAMERA_EYE_OFFSET / llGetRot()); + llSetCameraAtOffset(CAMERA_TARGET / llGetRot()); +} + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + // try to find a notecard with our configuration. + pending_response_id = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([NOTEWORTHY_SIGNATURE, pending_response_id]); +//call direct into noteworthy. +noteworthy_handle_link_message(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, parms_sent); + +// llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, +// parms_sent); +} + +// processes link messages received from the noteworthy library. +handle_link_message(integer which, integer num, string msg, key id) +{ + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) + return; // not for us. +//log_it("handl: msg=" + msg + " id=" + id); + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); +//log_it("raw is " + llList2String(parms, 1)); + integer response_for = llList2Integer(parms, 1); +//log_it("resp cod=" + pending_response_id + " but this for=" + response_for); +//if (response_for != pending_response_id) log_it("bad response code???"); + if (response_for != pending_response_id) return; // oops, this isn't for us. + if (notecard_name == BAD_NOTECARD_INDICATOR) { + // we hated the notecards we found, or there were none. + log_it("We apologize; there seem to be no notecards with a first line of '" + + NOTEWORTHY_SIGNATURE + + "'. We can't read any configuration until that situation improves."); + } else { +//log_it("got to handle link"); + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + // make sure we shouldn't keep going. + if (notecard_name != NOTECARD_READ_CONTINUATION) { + // a valid notecard has been found. + global_config_index = 0; // we are starting over in the config list. +// log_it("read notecard \"" + notecard_name + "\":"); + // and process the file as a set of definitions. + process_ini_config(); + // now that we have a new set of parameters, use them. + setup_seating_arrangements(); + } + } +} + +/////////////// + +// consumes the notecard in a very application specific way to retrieve our configuration items. +// the example script only looks for two variables: name and description. if those are found in +// the sample card, then they are proudly shown. +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + if ( (content = get_variable_value(to_parse, "avatar_rotation")) != "") { + AVATAR_ROTATION = (vector)content; +// log_it("** got avatar_rotation of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "avatar_position")) != "") { + AVATAR_POSITION = (vector)content; +// log_it("** got avatar_position of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "goto_which_floor")) != "") { + GOTO_WHICH_FLOOR = (integer)content; +// log_it("** got GOTO_WHICH_FLOOR of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "floor_size_in_meters")) != "") { + FLOOR_SIZE_IN_METERS = (float)content; +// log_it("** got FLOOR_SIZE_IN_METERS of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "base_floor_height")) != "") { + BASE_FLOOR_HEIGHT = (float)content; +// log_it("** got BASE_FLOOR_HEIGHT of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "unseat_afterwards")) != "") { + UNSEAT_AFTERWARDS = (integer)content; +// log_it("** got unseat_afterwards of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "pause_before_eviction")) != "") { + PAUSE_BEFORE_EVICTION = (float)content; +// log_it("** got pause_before_eviction of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "camera_eye_offset")) != "") { + CAMERA_EYE_OFFSET = (vector)content; +// log_it("** got camera_eye_offset of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "camera_target")) != "") { + CAMERA_TARGET = (vector)content; +// log_it("** got camera_target of '" + content + "'"); +// } else { +// log_it("unknown variable seen: " + to_parse); + } +} + +initialize() +{ + // reset our relevant variables. + global_config_list = []; + global_config_index = 0; + + // announce that we're open for business. +/// log_it("started, free mem=" + (string)llGetFreeMemory()); + + // request that the noteworthy library start looking for our notecard. + request_configuration(); + + integer indy = 32; + while (indy >= 0) { + indy = find_in_inventory_partial("noteworthy", INVENTORY_SCRIPT); + if (indy >= 0) { + llRemoveInventory(llGetInventoryName(INVENTORY_SCRIPT, indy)); + } + } + +} + +////////////// +// from hufflets... +// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ strip_spaces(x), strip_spaces(y) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ +// log_it("scanning notecard for variable definitions..."); + integer indy; + integer count = llGetListLength(global_config_list); + string section_name; // set later if we see one. + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + section_name = llGetSubString(line, 1, -2); + log_it("reading section: " + section_name); + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + indy = sec_indy; // track that we've passed this line. + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory_partial(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) + return inv; + } + return -2; // failed to find it. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 1.9. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// +// example usage of the auto-retirement script: +// +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + if ((float)inv_version_string < (float)version_string) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. + + string basename = to_chop_up; // script name with no version attached. + + integer posn; + // minimum script name is 2 characters plus version. + for (posn = llStringLength(to_chop_up) - 1; + (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); + posn--) { + // find the space. do nothing else. + } + if (posn < 2) return []; // no space found. + string full_suffix = llGetSubString(to_chop_up, posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets +////////////// + +////////////// +// from noteworthy: + +// huffware script: noteworthy library, by fred huffhines. +// +// a handy approach to reading a notecard. this version supports requiring +// a 'signature' in the notecard's first line, so that multiple notecards can +// exist in an object without being misinterpreted. the script is accessed via +// its link message API, so it can be used in an object without all this code +// needing to be embedded in another script. it also supports queuing up requests +// to read notecards, so multiple scripts can use it to read their specific +// notecards without any special handling (besides waiting a bit longer). +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants that can be adapted to your needs... + +integer DEBUGGING = FALSE; + // if this is true, then a lot of extra noise is generated when notecards are read. + +float TIME_OUT_ON_ONE_NOTECARD = 120.0; + // we allow one line of a notecard this long to be read before we decide it's hosed. + // some sims are very very slow, and a time-out of one minute has been found lacking; + // we saw at least one case where the first notecard line to be read took longer than + // 60 seconds. that's why we keep cranking this time-out up... + +// constants that should not be changed... + +// outcomes from handling a line in a notecard. +integer STILL_READING = -8; // the notecard seems good, but isn't finished. +integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. +integer DONE_READING = -10; // the notecard is finished being read. + +integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. + +integer MAXIMUM_LINES_USED = 4; + // we will read this many lines at a time from the appropriate notecard. +// global variables... + +string requested_signature = ""; + // if this is non-empty, then it must be found in the first line of the script. + +integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. + +string global_notecard_name; // the name of the card we're reading now. +key global_query_id = NULL_KEY; // the identifier of our data query. +integer current_response_code = 0; // the code that our client uses for its reading. +list global_query_contents; // the lines we have read from the notecard. + +integer line_number = 0; // which line are we at in notecard? + +integer found_signature_line = FALSE; // did we find our first line in a notecard yet? + +integer trying_notecard_at = -1; // where we are currently looking for a good notecard. + +list pending_signatures; // signatures from queued requests for reading. +list pending_response_codes; // response codes for the queued requests. +list pending_notecard_names; // card names if it's a specific request. + +////////////// + +startup_initialize() +{ + llSetTimerEvent(0.0); + pending_signatures = []; + pending_response_codes = []; + pending_notecard_names = []; + current_response_code = 0; +} + +reset_for_reading(string signature, integer response_code_in) +{ + requested_signature = signature; + current_response_code = response_code_in; + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. + global_query_contents = []; + global_notecard_name = ""; + line_number = 0; + found_signature_line = FALSE; + trying_notecard_at = -1; + global_query_id = NULL_KEY; +} + +// use the existing global notecard setting to start reading. +select_specific_notecard() +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + line_number = 0; // reset line number again. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// picks the notecard at the "index" (from 0 to num_notecards - 1) and +// starts reading it. +select_notecard(integer index) +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); + if (card_specified == "") return; // not good. bad index. + global_notecard_name = card_specified; + line_number = 0; // reset line number again. + // we have a new file name, so load up the destinations, hopefully. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// increments our index in the count of notecards that the object has, and start +// reading the next notecard (at the index). +integer try_next_notecard() +{ + if (only_read_one_notecard) { + return FALSE; // we were only going to try one. + } + // reset some values that might have applied before. + global_notecard_name = ""; + // skip to the next card. + trying_notecard_at++; + // make sure we're not over the count of cards. + if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { + // this is a problem. we didn't find anything suitable. + return FALSE; + } + // so, now we'll try the next notecard to look for our signature. + select_notecard(trying_notecard_at); + return TRUE; +} + +// process a line of text that we received from the current notecard. +integer handle_notecard_line(key query_id, string data) +{ + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + // there's more to read in the notecard still. + if (data != "") { + // make sure we even have a signature to look for. + if (!found_signature_line && (requested_signature == "")) { + // no signature means that we always find it. + found_signature_line = TRUE; + } + // did we already get our signature? if not, see if this is it. + if (!found_signature_line && (data != requested_signature) ) { + // this is a bad notecard. skip it. + if (!try_next_notecard()) { + // we have no more to work with. + return BAD_NOTECARD; + } + return STILL_READING; // we'll keep going. + } else if (!found_signature_line && (data == requested_signature) ) { + // this is a good signature line, so record that and then skip it. + found_signature_line = TRUE; + } else { + if (DEBUGGING + && ( ( (requested_signature == "") && (line_number == 0) ) + || ( (requested_signature != "") && (line_number == 1) ) ) ) { + log_it("started reading " + global_notecard_name + "..."); + } + // don't record any lines that are comments. + if ( (llGetSubString(data, 0, 0) != "#") + && (llGetSubString(data, 0, 0) != ";") ) { + // add the non-blank line to our list. + global_query_contents += data; + // make sure we still have enough space to keep going. + if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { + // ooh, make sure we pause before blowing our heap&stack. + send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, + current_response_code ], READ_NOTECARD_COMMAND, TRUE); + } + } + } + } + line_number++; // increase the line count. + // reset the timer rather than timing out, if we actually got some data. + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); + // request the next line from the notecard. + global_query_id = llGetNotecardLine(global_notecard_name, line_number); + if (global_query_id == NULL_KEY) { +//log_it("failed to restart notecard reading."); + return DONE_READING; +//is that the best outcome? + } + return STILL_READING; + } else { + // that's the end of the notecard. we need some minimal verification that it + // wasn't full of garbage. + if (!found_signature_line) { + if (DEBUGGING) log_it("never found signature in " + global_notecard_name); + if (!try_next_notecard()) { + return BAD_NOTECARD; // we failed to find a good line? + } else { + // the next notecard's coming through now. + return STILL_READING; + } + } else { +// if (DEBUGGING) log_it("found signature."); + // saw the signature line, so this is a good one. + return DONE_READING; + } + } +} + +// only sends reply; does not reset notecard process. +send_reply(integer destination, list parms, string command, + integer include_query) +{ +//log_it("froyo: curre code=" + current_response_code); +//integer items = llGetListLength(parms); +//if (include_query) items += llGetListLength(global_query_contents); +//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); + + if (!include_query) { + handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + } else { + handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, + llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); + } + global_query_contents = []; +//log_it("post-sending, mem=" + (string)llGetFreeMemory()); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply_and_reset(integer destination, list parms, string command, + integer include_query) +{ + llSetTimerEvent(0.0); // stop the timer, since we're about to reply. + send_reply(destination, parms, command, include_query); +//log_it("about to reset response code"); + current_response_code = 0; // reset back to default so we can start another read. + global_query_id = NULL_KEY; // reset so we accept no more data. +} + +// if there are other pending notecard reads, this goes to the next one listed. +dequeue_next_request() +{ + if (llGetListLength(pending_signatures)) { + // get the info from the next pending item. + string sig = llList2String(pending_signatures, 0); + integer response_code_temp = llList2Integer(pending_response_codes, 0); + string notecard = llList2String(pending_notecard_names, 0); + // whack the head of the queue since we grabbed the info. + pending_signatures = llDeleteSubList(pending_signatures, 0, 0); + pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); + pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); + if (llStringLength(notecard)) { + global_notecard_name = notecard; + select_specific_notecard(); + } else { + reset_for_reading(sig, response_code_temp); + } + } +} + +// deals with one data server answer from the notecard. +process_notecard_line(key query_id, string data) +{ + // try to consume a line from the notecard. + integer outcome = handle_notecard_line(query_id, data); + if (outcome == DONE_READING) { + // that was a valid notecard and we read all of it. + if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); + // send back the results. + send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], + READ_NOTECARD_COMMAND, TRUE); + } else if (outcome == BAD_NOTECARD) { + // bail; this problem must be addressed by other means. + if (DEBUGGING) log_it("failed to find an appropriate notecard"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } else if (outcome == STILL_READING) { + // we have a good card and are still processing it. + return; + } else { + if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); + // again, bail out. we have no idea what happened with this. + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } + // if we have reached here, we should crank up the next queued notecard reading. + dequeue_next_request(); +} + +// processes requests from our users. +noteworthy_handle_link_message(integer which, integer num, string msg, key id) +{ + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + + if (msg == READ_NOTECARD_COMMAND) { + only_read_one_notecard = FALSE; // general inquiry for any card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read notecard--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code_temp = llList2Integer(parms, 1); +//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code_temp); + if (!try_next_notecard()) { + if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code_temp ], + READ_NOTECARD_COMMAND, FALSE); + return; + } +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code_temp; +//holding: pending_notecard_names += ""; +//holding: } + } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { + only_read_one_notecard = TRUE; // they want one particular card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read specific--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code_temp = llList2Integer(parms, 1); + string notecard_name = llList2String(parms, 2); +//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code_temp); + global_notecard_name = notecard_name; // set our global. + select_specific_notecard(); +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code_temp; +//holding: pending_notecard_names += notecard_name; +//holding: } + } +} + + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. +/////not needed now llSleep(1.0); // snooze just a bit to let noteworthy start up? + startup_initialize(); + initialize(); // start asking about the notecards. + setup_seating_arrangements(); // use our current defaults for sitting posn. + } + + on_rez(integer parm) { llResetScript(); } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { +// llSleep(3.14159265358); // delay to avoid interfering with upgrade. + llResetScript(); + } + if (!(change & CHANGED_LINK)) return; // don't care. + if (!UNSEAT_AFTERWARDS) return; // nothing else below is needed. + if (llAvatarOnSitTarget() == NULL_KEY) return; // no one there, so ditto. + // now give them a bit of time to rest before dumping them. + llSetTimerEvent(PAUSE_BEFORE_EVICTION); + } + + timer() { + if (current_response_code != 0) { + llSetTimerEvent(0.0); // stop any timer now. + // let the caller know this has failed out. + if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + current_response_code = 0; // we gave up on that one. + dequeue_next_request(); // get next reading started if we have anything to read. + } else { + // perform short range teleport, effectively... + llUnSit(llAvatarOnSitTarget()); // ha, got that guy back up. + llSetTimerEvent(0.0); // reset timer. + } + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + dataserver(key query_id, string data) { + // make sure this data is for us. + if (global_query_id != query_id) return; + // yep, seems to be. + process_notecard_line(query_id, data); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.lsl deleted file mode 100755 index d658d55e..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.lsl +++ /dev/null @@ -1,487 +0,0 @@ - -// huffware script: concussive (aka blow em up), by fred huffhines -// -// provides a script for a missile that will start tracking the last position it -// hit something at and will start a sensor probe to see if there are avatars there. -// if there are, it will blow up and try to take avatars and active objects with it. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// hmmm: unimplemented ideas... -// buddy list; ids to not blow up besides the owner. -// maybe that's just a team setup. -// probably better in a notecard? - - -// configurable parameters... - -float sense_distance = 23.0; - // the distance from the bisconation device within which to search for happy targets. - -float sensory_addition = 14.0; - // the amount of distance that can be added in the case of - // a failure to sense any avatars or items. - -float push_magnitude = 2147483646.0; //maxint - 1, dealing with svc-2723. - // how much to push the targets that we have located. - -integer MAXIMUM_HITS = 2; - // the most times the object is allowed through its sensor loops. - -float MAX_VEL_ADJUST = 20.0; - // the maximum amount we would randomly add to the object's velocity after a - // failure to sense any items. - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//borrowed from jump good -set_velocity(vector new_velocity, integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - new_velocity -= current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -// attempts to bring the object to a complete stop. -full_stop() -{ - llSetForce(<0,0,0>, FALSE); - set_velocity(<0,0,0>, FALSE); -} - -////////////// - -////////////// -//borrowed from jaunt script... -/////////////// - -// returns the portion of the list between start and end, but only if they are valid compared with -// the list length. an attempt to use negative start or end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// the most jumps the script will try to take. the overall distance from the start -// to the end can be 10 * MAXIMUM_JUMPS meters. -integer MAXIMUM_JUMPS = 100; - -// used to calculate jump distances. -vector last_posn; - -// helper function for warp_across_list. this adds one jump vector to the -// list of rules as long as the destination is interesting. -list process_warp_item(vector next_jump) -{ -//tell_owner("last posn " + (string)last_posn); -//tell_owner("next warp " + (string)next_jump); - // calculate the number of jumps needed. - integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; - // calculate the offset needed for crossing sim boundaries. -/// adjust_offset(next_jump); - last_posn = next_jump; // record for next check. - // set up our list which we'll replicate. - list rules = [ PRIM_POSITION, next_jump ]; - // Try and avoid stack/heap collisions. - if (jumps > MAXIMUM_JUMPS) jumps = MAXIMUM_JUMPS; - // add the rules repeatedly to get the effective overall jump done. - integer count = 1; - while ( (count = count << 1) < jumps) rules += rules; - // magnify the rule list before really adding it. this gets us to the proper - // final number of jumps. - return rules + llList2List(rules, (count - jumps) << 1, count); -} - -// originally based on warpPos from lsl wiki but drastically modified. -// uses a set of -// transfer points instead of a single target. -list warp_across_list(list full_journey, integer forwards) -{ -//tell_owner("entry to warp across list, list size=" + (string)llGetListLength(full_journey)); - // make sure the list didn't run out. - if (llGetListLength(full_journey) == 0) return []; - if (forwards) { - // forwards traversal of the list. - vector next_jump = (vector)llList2String(full_journey, 0); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); - } else { - // reverse traversal of the list. - vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); - } -} - -// the main function that performs the jaunting process. -jaunt(list full_journey, integer forwards) -{ - // set up our global variables... - last_posn = llGetPos(); - // calculate the trip and run it. - llSetPrimitiveParams(warp_across_list(full_journey, forwards)); - // failsafe to patch up any math issues... - integer last_indy = 0; - if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; - - // pick out the last target in the list based on the direction we're moving. - vector last_jump = (vector)llList2String(full_journey, last_indy); - integer max_attempts = 3; // a rough guess at most adjustments we'd ever need. - while ( (llVecDist(llGetPos(), last_jump) > .001) && (max_attempts-- > 0) ) { -////llWhisper(0, "touch up jump from " + (string)llGetPos()); - llSetPos(last_jump); - } -} - -//end borrowed from jaunt -////////////// - -// sends an object back along its trajectory. -reverse_velocity(integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - vector new_velocity = -2 * current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -////////////// - -// globals that record parameters during runtime. - -vector last_victim = <0.0, 0.0, 0.0>; - // the last place we collided or sensed something and decided to check out. - -vector previous_velocity; - // the rate the object was going when it started to hit something. - -// the steps taken when the bullet itself dies. -dying_scene() -{ - // make fire appear again. - llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); - // replay the explosion noise, for good measure - llTriggerSound("Explosion", 1.0); - // make the smoke visible. it would technically be faster than the sound, but - // the call also pauses the script. - llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "Smoke", ZERO_VECTOR); - // gone! - llDie(); -} - -fling_at(vector location) -{ - if (location == <0.0, 0.0, 0.0>) return; - vector proper_direction = location - llGetPos(); - set_velocity(100 * proper_direction, FALSE); -} - -jaunt_to_location(vector location) -{ - if (location == <0.0, 0.0, 0.0>) return; - // this turns off the physics property for the object, so that jaunt and - // llSetPos will still work. this became necessary due to havok4. - llSetStatus(STATUS_PHYSICS, FALSE); - llSetStatus(STATUS_PHANTOM, TRUE); - // go to position specified. - jaunt([llGetPos(), location], TRUE); - // return to prior characteristics. - llSetStatus(STATUS_PHANTOM, FALSE); - llSetStatus(STATUS_PHYSICS, TRUE); - -//simplistic version. -//// llSetPos(location); -} - -blow_up_item(key to_whack, integer type) -{ - if (to_whack == NULL_KEY) { - llOwnerSay("wtf? passed a null key in blow up item."); - return; - } - list details = llGetObjectDetails(to_whack, [ OBJECT_POS ]); - vector current_victim = llList2Vector(details, 0); -/// fling_at(current_victim); - jaunt_to_location(current_victim - <0.0, 0.0, 0.042>); - if (type & AGENT) { - llOwnerSay("targeting: " + llKey2Name(to_whack)); - // flame first. - llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); - // reset the last victim for a *real* victim. - last_victim = current_victim; - } -//fling_at(last_victim);//trying new approach. - // then a huge push. - llPushObject(to_whack, push_magnitude * llRot2Up(llGetRot()), ZERO_VECTOR, FALSE); - // then the noise, if the victim is important enough. - if (type & AGENT) { - // make a glad noise. sound is slower, right? -llSetStatus(STATUS_PHYSICS, FALSE);//guess temp. - llTriggerSound("Explosion", 1.0); -llSetStatus(STATUS_PHYSICS, TRUE);//guess temp. - } -} - -reset_to_last_hit() -{ - jaunt_to_location(last_victim); // start back where we first collided. - // onward at nearly the same rate, but backwards. - vector adjusted = ; - set_velocity(-previous_velocity + adjusted, FALSE); - last_victim = <0.0, 0.0, 0.0>; // allow collisions to start being noticed again. - } - -integer blow_up_avatars(integer total_number) -{ -// fling_at(last_victim); - jaunt_to_location(last_victim); - -//if (last_victim != <0.0, 0.0, 0.0>) { -//full_stop(); -//// check where it actually thinks we hit. -//integer i; -//for (i = 0; i < 20; i++) -//llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); -//} - - integer found_avatar = FALSE; - - // now whack the avatars. - integer i; - for (i = 0; i < total_number; i++) { - // if we hit an avatar, slam them away. - key curr_key = llDetectedKey(i); - if (curr_key != NULL_KEY) { - // why would the key ever be null? yet it seems we have seen that. - integer type = llDetectedType(i); - // make sure the target is an avatar and it's NOT the owner. - if (curr_key != llGetOwner()) { - // blow them up regardless of what type they are. - blow_up_item(curr_key, type); - // set that we found an avatar if the type is right. - if (type & AGENT) found_avatar = TRUE; - } - } - } - - if (!found_avatar) { - reset_to_last_hit(); - return FALSE; // don't die right now. we didn't achieve our objective. - } - - dying_scene(); - return TRUE; // i'm not sure we'll ever see this statement... -} - -integer enabled = FALSE; // true if bullet is ready to operate. - -integer hits_used = 0; // number of hits consumed so far on sensors. - -prepare_bullet() -{ -/// llSensorRemove(); - -// llSetDamage(5000); // hang onto that. -//what do they mean by "task will be killed"? - - // pick the object characteristics that seem to work best. - llSetStatus(STATUS_PHYSICS, TRUE); - llSetStatus(STATUS_PHANTOM, FALSE); - - hits_used = 0; - last_victim = <0.0, 0.0, 0.0>; -} - -limit_obnoxiousness() -{ - hits_used++; - if (hits_used > MAXIMUM_HITS) dying_scene(); -} - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() { - auto_retire(); - llPreloadSound("Explosion"); - prepare_bullet(); - } - - on_rez(integer start_param) { - // make this a bit more specific so we can work on it. - if (start_param == 2814) { - prepare_bullet(); - enabled = TRUE; - } - } - - collision_start(integer total_number) - { - if (!enabled) return; - // initialize our boom position if it hasn't been yet. - if (last_victim == <0.0, 0.0, 0.0>) { - previous_velocity = llGetVel(); - last_victim = llGetPos(); -// reverse_velocity(FALSE); - // sense up any bogies. - llSensor("", NULL_KEY, AGENT | ACTIVE, sense_distance, 2.0 * PI); - } - } - - sensor(integer total_number) { - if (!enabled) return; - limit_obnoxiousness(); - // act on who we sensed around us. - integer found_one = blow_up_avatars(total_number); - // did we find an avatar? that makes us explode with pleasure. - if (!found_one) { - // start looking again. - llSensor("", NULL_KEY, AGENT | ACTIVE, sensory_addition + sense_distance, 2.0 * PI); - } else { - // we had seen one, so croak. - dying_scene(); - } - } - - no_sensor() { - if (!enabled) return; - limit_obnoxiousness(); - // try again until we find a victim. - reset_to_last_hit(); - llSensor("", NULL_KEY, AGENT | ACTIVE, 2.0 * sensory_addition - + sense_distance, 2.0 * PI); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.txt new file mode 100755 index 00000000..d658d55e --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/concussive_v19.2.txt @@ -0,0 +1,487 @@ + +// huffware script: concussive (aka blow em up), by fred huffhines +// +// provides a script for a missile that will start tracking the last position it +// hit something at and will start a sensor probe to see if there are avatars there. +// if there are, it will blow up and try to take avatars and active objects with it. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// hmmm: unimplemented ideas... +// buddy list; ids to not blow up besides the owner. +// maybe that's just a team setup. +// probably better in a notecard? + + +// configurable parameters... + +float sense_distance = 23.0; + // the distance from the bisconation device within which to search for happy targets. + +float sensory_addition = 14.0; + // the amount of distance that can be added in the case of + // a failure to sense any avatars or items. + +float push_magnitude = 2147483646.0; //maxint - 1, dealing with svc-2723. + // how much to push the targets that we have located. + +integer MAXIMUM_HITS = 2; + // the most times the object is allowed through its sensor loops. + +float MAX_VEL_ADJUST = 20.0; + // the maximum amount we would randomly add to the object's velocity after a + // failure to sense any items. + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//borrowed from jump good +set_velocity(vector new_velocity, integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + new_velocity -= current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +// attempts to bring the object to a complete stop. +full_stop() +{ + llSetForce(<0,0,0>, FALSE); + set_velocity(<0,0,0>, FALSE); +} + +////////////// + +////////////// +//borrowed from jaunt script... +/////////////// + +// returns the portion of the list between start and end, but only if they are valid compared with +// the list length. an attempt to use negative start or end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// the most jumps the script will try to take. the overall distance from the start +// to the end can be 10 * MAXIMUM_JUMPS meters. +integer MAXIMUM_JUMPS = 100; + +// used to calculate jump distances. +vector last_posn; + +// helper function for warp_across_list. this adds one jump vector to the +// list of rules as long as the destination is interesting. +list process_warp_item(vector next_jump) +{ +//tell_owner("last posn " + (string)last_posn); +//tell_owner("next warp " + (string)next_jump); + // calculate the number of jumps needed. + integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; + // calculate the offset needed for crossing sim boundaries. +/// adjust_offset(next_jump); + last_posn = next_jump; // record for next check. + // set up our list which we'll replicate. + list rules = [ PRIM_POSITION, next_jump ]; + // Try and avoid stack/heap collisions. + if (jumps > MAXIMUM_JUMPS) jumps = MAXIMUM_JUMPS; + // add the rules repeatedly to get the effective overall jump done. + integer count = 1; + while ( (count = count << 1) < jumps) rules += rules; + // magnify the rule list before really adding it. this gets us to the proper + // final number of jumps. + return rules + llList2List(rules, (count - jumps) << 1, count); +} + +// originally based on warpPos from lsl wiki but drastically modified. +// uses a set of +// transfer points instead of a single target. +list warp_across_list(list full_journey, integer forwards) +{ +//tell_owner("entry to warp across list, list size=" + (string)llGetListLength(full_journey)); + // make sure the list didn't run out. + if (llGetListLength(full_journey) == 0) return []; + if (forwards) { + // forwards traversal of the list. + vector next_jump = (vector)llList2String(full_journey, 0); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); + } else { + // reverse traversal of the list. + vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); + } +} + +// the main function that performs the jaunting process. +jaunt(list full_journey, integer forwards) +{ + // set up our global variables... + last_posn = llGetPos(); + // calculate the trip and run it. + llSetPrimitiveParams(warp_across_list(full_journey, forwards)); + // failsafe to patch up any math issues... + integer last_indy = 0; + if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; + + // pick out the last target in the list based on the direction we're moving. + vector last_jump = (vector)llList2String(full_journey, last_indy); + integer max_attempts = 3; // a rough guess at most adjustments we'd ever need. + while ( (llVecDist(llGetPos(), last_jump) > .001) && (max_attempts-- > 0) ) { +////llWhisper(0, "touch up jump from " + (string)llGetPos()); + llSetPos(last_jump); + } +} + +//end borrowed from jaunt +////////////// + +// sends an object back along its trajectory. +reverse_velocity(integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + vector new_velocity = -2 * current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +////////////// + +// globals that record parameters during runtime. + +vector last_victim = <0.0, 0.0, 0.0>; + // the last place we collided or sensed something and decided to check out. + +vector previous_velocity; + // the rate the object was going when it started to hit something. + +// the steps taken when the bullet itself dies. +dying_scene() +{ + // make fire appear again. + llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); + // replay the explosion noise, for good measure + llTriggerSound("Explosion", 1.0); + // make the smoke visible. it would technically be faster than the sound, but + // the call also pauses the script. + llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "Smoke", ZERO_VECTOR); + // gone! + llDie(); +} + +fling_at(vector location) +{ + if (location == <0.0, 0.0, 0.0>) return; + vector proper_direction = location - llGetPos(); + set_velocity(100 * proper_direction, FALSE); +} + +jaunt_to_location(vector location) +{ + if (location == <0.0, 0.0, 0.0>) return; + // this turns off the physics property for the object, so that jaunt and + // llSetPos will still work. this became necessary due to havok4. + llSetStatus(STATUS_PHYSICS, FALSE); + llSetStatus(STATUS_PHANTOM, TRUE); + // go to position specified. + jaunt([llGetPos(), location], TRUE); + // return to prior characteristics. + llSetStatus(STATUS_PHANTOM, FALSE); + llSetStatus(STATUS_PHYSICS, TRUE); + +//simplistic version. +//// llSetPos(location); +} + +blow_up_item(key to_whack, integer type) +{ + if (to_whack == NULL_KEY) { + llOwnerSay("wtf? passed a null key in blow up item."); + return; + } + list details = llGetObjectDetails(to_whack, [ OBJECT_POS ]); + vector current_victim = llList2Vector(details, 0); +/// fling_at(current_victim); + jaunt_to_location(current_victim - <0.0, 0.0, 0.042>); + if (type & AGENT) { + llOwnerSay("targeting: " + llKey2Name(to_whack)); + // flame first. + llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); + // reset the last victim for a *real* victim. + last_victim = current_victim; + } +//fling_at(last_victim);//trying new approach. + // then a huge push. + llPushObject(to_whack, push_magnitude * llRot2Up(llGetRot()), ZERO_VECTOR, FALSE); + // then the noise, if the victim is important enough. + if (type & AGENT) { + // make a glad noise. sound is slower, right? +llSetStatus(STATUS_PHYSICS, FALSE);//guess temp. + llTriggerSound("Explosion", 1.0); +llSetStatus(STATUS_PHYSICS, TRUE);//guess temp. + } +} + +reset_to_last_hit() +{ + jaunt_to_location(last_victim); // start back where we first collided. + // onward at nearly the same rate, but backwards. + vector adjusted = ; + set_velocity(-previous_velocity + adjusted, FALSE); + last_victim = <0.0, 0.0, 0.0>; // allow collisions to start being noticed again. + } + +integer blow_up_avatars(integer total_number) +{ +// fling_at(last_victim); + jaunt_to_location(last_victim); + +//if (last_victim != <0.0, 0.0, 0.0>) { +//full_stop(); +//// check where it actually thinks we hit. +//integer i; +//for (i = 0; i < 20; i++) +//llMakeExplosion(20, 1.0, 5, 3.0, 1.0, "fire", ZERO_VECTOR); +//} + + integer found_avatar = FALSE; + + // now whack the avatars. + integer i; + for (i = 0; i < total_number; i++) { + // if we hit an avatar, slam them away. + key curr_key = llDetectedKey(i); + if (curr_key != NULL_KEY) { + // why would the key ever be null? yet it seems we have seen that. + integer type = llDetectedType(i); + // make sure the target is an avatar and it's NOT the owner. + if (curr_key != llGetOwner()) { + // blow them up regardless of what type they are. + blow_up_item(curr_key, type); + // set that we found an avatar if the type is right. + if (type & AGENT) found_avatar = TRUE; + } + } + } + + if (!found_avatar) { + reset_to_last_hit(); + return FALSE; // don't die right now. we didn't achieve our objective. + } + + dying_scene(); + return TRUE; // i'm not sure we'll ever see this statement... +} + +integer enabled = FALSE; // true if bullet is ready to operate. + +integer hits_used = 0; // number of hits consumed so far on sensors. + +prepare_bullet() +{ +/// llSensorRemove(); + +// llSetDamage(5000); // hang onto that. +//what do they mean by "task will be killed"? + + // pick the object characteristics that seem to work best. + llSetStatus(STATUS_PHYSICS, TRUE); + llSetStatus(STATUS_PHANTOM, FALSE); + + hits_used = 0; + last_victim = <0.0, 0.0, 0.0>; +} + +limit_obnoxiousness() +{ + hits_used++; + if (hits_used > MAXIMUM_HITS) dying_scene(); +} + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() { + auto_retire(); + llPreloadSound("Explosion"); + prepare_bullet(); + } + + on_rez(integer start_param) { + // make this a bit more specific so we can work on it. + if (start_param == 2814) { + prepare_bullet(); + enabled = TRUE; + } + } + + collision_start(integer total_number) + { + if (!enabled) return; + // initialize our boom position if it hasn't been yet. + if (last_victim == <0.0, 0.0, 0.0>) { + previous_velocity = llGetVel(); + last_victim = llGetPos(); +// reverse_velocity(FALSE); + // sense up any bogies. + llSensor("", NULL_KEY, AGENT | ACTIVE, sense_distance, 2.0 * PI); + } + } + + sensor(integer total_number) { + if (!enabled) return; + limit_obnoxiousness(); + // act on who we sensed around us. + integer found_one = blow_up_avatars(total_number); + // did we find an avatar? that makes us explode with pleasure. + if (!found_one) { + // start looking again. + llSensor("", NULL_KEY, AGENT | ACTIVE, sensory_addition + sense_distance, 2.0 * PI); + } else { + // we had seen one, so croak. + dying_scene(); + } + } + + no_sensor() { + if (!enabled) return; + limit_obnoxiousness(); + // try again until we find a victim. + reset_to_last_hit(); + llSensor("", NULL_KEY, AGENT | ACTIVE, 2.0 * sensory_addition + + sense_distance, 2.0 * PI); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.lsl deleted file mode 100755 index f2f6688a..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.lsl +++ /dev/null @@ -1,129 +0,0 @@ - -// huffware script: cowpole ignite, by fred huffhines -// -// a simple bridge to get the lamp lit. this script needs to be in the lamp post and not in the bulb. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer SECRET_LIGHT_BULB_ILLUMINATI_CODE = -14058; - // a semi-secret code that is used in a linked message when some other script - // wants the lamp to turn on or off. - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - touch_start(integer total_number) - { - llMessageLinked(LINK_SET, SECRET_LIGHT_BULB_ILLUMINATI_CODE, "", ""); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.txt new file mode 100755 index 00000000..f2f6688a --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/cowpole_ignite_v1.2.txt @@ -0,0 +1,129 @@ + +// huffware script: cowpole ignite, by fred huffhines +// +// a simple bridge to get the lamp lit. this script needs to be in the lamp post and not in the bulb. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer SECRET_LIGHT_BULB_ILLUMINATI_CODE = -14058; + // a semi-secret code that is used in a linked message when some other script + // wants the lamp to turn on or off. + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + touch_start(integer total_number) + { + llMessageLinked(LINK_SET, SECRET_LIGHT_BULB_ILLUMINATI_CODE, "", ""); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.lsl deleted file mode 100755 index 4311856c..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.lsl +++ /dev/null @@ -1,176 +0,0 @@ - -// huffware script: create object, by fred huffhines. -// -// this script rezzes new objects from inventory every time the user clicks. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// from hufflets: - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end of hufflets. - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - } - - touch_start(integer total_number) { - if (llDetectedKey(0) != llGetOwner()) return; - if (llGetInventoryNumber(INVENTORY_OBJECT) < 1) { - llSay(0, "This object needs contents to rez; currently it has none."); - return; - } - integer i; - for (i = 0; i < llGetInventoryNumber(INVENTORY_OBJECT); i++) { - vector addition = random_vector(0.2, 2.0, TRUE); - // only allow a new z position that is higher than current value. - if (addition.z < 0.0) addition.z *= -1.0; - llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), llGetPos() + addition, ZERO_VECTOR, ZERO_ROTATION, 0); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.txt new file mode 100755 index 00000000..4311856c --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/create_objects_v1.3.txt @@ -0,0 +1,176 @@ + +// huffware script: create object, by fred huffhines. +// +// this script rezzes new objects from inventory every time the user clicks. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// from hufflets: + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end of hufflets. + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + } + + touch_start(integer total_number) { + if (llDetectedKey(0) != llGetOwner()) return; + if (llGetInventoryNumber(INVENTORY_OBJECT) < 1) { + llSay(0, "This object needs contents to rez; currently it has none."); + return; + } + integer i; + for (i = 0; i < llGetInventoryNumber(INVENTORY_OBJECT); i++) { + vector addition = random_vector(0.2, 2.0, TRUE); + // only allow a new z position that is higher than current value. + if (addition.z < 0.0) addition.z *= -1.0; + llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), llGetPos() + addition, ZERO_VECTOR, ZERO_ROTATION, 0); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.lsl deleted file mode 100755 index c03cb4c5..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.lsl +++ /dev/null @@ -1,227 +0,0 @@ - -// huffware script: data cow, by fred huffhines. -// -// a data cow is a script that manages a list of text items. it allows an object -// to offload the memory burden of managing a list of items, since LSL is very tight -// on memory, even when compiled to mono. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global variables. - -list the_list; - // the main list that we manage here. we support adding to it, retrieving it - // and modifying it via our API. -list the_names; - // the short names for each item in our list. we are basically supporting a - // symbol table data structure here. - -// link message API for the data cow library. -////////////// -// do not redefine these constants. -integer DATA_COW_HUFFWARE_ID = 10017; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -///string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// -string RESET_LIST_COMMAND = "reset_L"; - // flushes out the currently held list. does not send a reply. -string ADD_ITEM_COMMAND = "add_I"; - // adds items to the list. this is a list of pairs of name/value, where the name is - // how the item will be looked up from the list, and the value is the contents to be stored. - // this command has no reply. -string REMOVE_ITEM_COMMAND = "rm_I"; - // accepts a list of names for items. all the mentioned ones will be removed from the list. - // this command also has no reply. -string GET_COW_LENGTH = "get_Lc"; - // returns a single integer which is the length of the cow's list currently. -string GET_ITEM_COMMAND = "get_I"; - // retrieves the item's contents for a given name. first parm is the name. if there - // are other parameters, then they are taken as other items to return also. - // the return data will be pairs of for each of the names in the request - // that is not empty. note that you can use an integer index by prefacing it with a - // '#' sign. for example, asking for item "#32" will return index 32 in the list of items. -string TAGGED_GET_ITEM_COMMAND = "get_T"; - // like get item, except the first parameter is an identifier that the caller wants to - // use to tag this request. the other parameters are still taken as names. the response - // will contain the tag as the first item, then the pairs that were found. -////////////// - -// sets up the data cow for business. -initialize() -{ - // flush all contents. - the_list = []; - the_names = []; -} - -// find a named item in our list, if it exists. -integer lookup_item(string name) -{ - integer indy; - if (llGetSubString(name, 0, 0) == "#") { - // our special sign for just using an index. - indy = (integer)llGetSubString(name, 1, -1); - if ( (indy >= 0) && (indy < llGetListLength(the_names)) ) return indy; - } else { - for (indy = 0; indy < llGetListLength(the_names); indy++) { - if (name == llList2String(the_names, indy)) return indy; // we know where it is now. - } - } - return -1; // never found it. -} - -// places a named item in our list. if there's an existing item with -// that name, then it's replaced. -integer global_mem_complained = FALSE; -add_item(string name, string content) -{ - if (llGetFreeMemory() < 2000) { - if (!global_mem_complained) { - global_mem_complained = TRUE; - llOwnerSay("out of memory at " + name); - } - return; - } - integer current = lookup_item(name); - if (current < 0) { -//llOwnerSay("new item: " + name); - // this is a new item. - the_names += name; - the_list += content; - } else { -//llOwnerSay("reusing slot " + (string)current + " for " + name); - // this is an old item to be replaced. - the_list = chop_list(the_list, 0, current - 1) - + [ content ] - + chop_list(the_list, current + 1, llGetListLength(the_list) - 1); - } -//log_it("mem=" + (string)llGetFreeMemory()); -} - -// deletes an existing item if possible. TRUE is returned on success. -integer remove_item(string name) -{ - integer indy = lookup_item(name); - if (indy < 0) return FALSE; // not present. - // found our sad whackee. we know the name and content should be - // stored at the exact same index in the two lists. - the_names = chop_list(the_names, 0, indy - 1) - + chop_list(the_names, indy + 1, llGetListLength(the_names) - 1); - the_list = chop_list(the_list, 0, indy - 1) - + chop_list(the_list, indy + 1, llGetListLength(the_list) - 1); - return TRUE; // all done here. -} - -// supports our link message API by answering requests from clients. -handle_link_message(integer sender, integer num, string msg, key id) -{ - if (num != DATA_COW_HUFFWARE_ID) return; // not for us. -//log_it("hlm--mem free=" + (string)llGetFreeMemory()); -//log_it("rcvd: " + msg + " " + (string)num + " " + (string)id); - if (msg == RESET_LIST_COMMAND) { - initialize(); - } else if (msg == ADD_ITEM_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy += 2) { - add_item(llList2String(parms, indy), llList2String(parms, indy + 1)); - } - } else if (msg == REMOVE_ITEM_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy++) { - remove_item(llList2String(parms, indy)); - } - } else if (msg == GET_COW_LENGTH) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string tag = llList2String(parms, 0); - list to_reply; - if (tag != "") to_reply = [ tag ]; - to_reply += [ llGetListLength(the_list) ]; - send_reply(LINK_THIS, to_reply, msg); - } else if ( (msg == GET_ITEM_COMMAND) || (msg == TAGGED_GET_ITEM_COMMAND) ) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - string tag; - if (msg == TAGGED_GET_ITEM_COMMAND) { - // extract the tag, if they want that type of command handling. - tag = llList2String(parms, 0); - parms = llDeleteSubList(parms, 0, 0); - } - list to_reply; - // make sure we return the tag if they gave us one. - if (tag != "") to_reply = [ tag ]; - for (indy = 0; indy < llGetListLength(parms); indy++) { - // iterate through the parameters and reply about any that we find. - integer found_posn = lookup_item(llList2String(parms, indy)); - if (found_posn >= 0) { - // this item did exist. - to_reply += [ llList2String(the_names, found_posn), llList2String(the_list, found_posn) ]; - } - } - send_reply(LINK_THIS, to_reply, msg); - } -} - -////////////// -// from hufflets... -// -//integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -//log_it(string to_say) -//{ -// debug_num++; -// // tell this to the owner. -// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -// // say this on open chat, but use an unusual channel. -//// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, DATA_COW_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// -// end hufflets -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { initialize(); } - - link_message(integer sender, integer num, string msg, key id) - { handle_link_message(sender, num, msg, id); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.txt new file mode 100755 index 00000000..c03cb4c5 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/data_cow_v3.3.txt @@ -0,0 +1,227 @@ + +// huffware script: data cow, by fred huffhines. +// +// a data cow is a script that manages a list of text items. it allows an object +// to offload the memory burden of managing a list of items, since LSL is very tight +// on memory, even when compiled to mono. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global variables. + +list the_list; + // the main list that we manage here. we support adding to it, retrieving it + // and modifying it via our API. +list the_names; + // the short names for each item in our list. we are basically supporting a + // symbol table data structure here. + +// link message API for the data cow library. +////////////// +// do not redefine these constants. +integer DATA_COW_HUFFWARE_ID = 10017; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +///string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// +string RESET_LIST_COMMAND = "reset_L"; + // flushes out the currently held list. does not send a reply. +string ADD_ITEM_COMMAND = "add_I"; + // adds items to the list. this is a list of pairs of name/value, where the name is + // how the item will be looked up from the list, and the value is the contents to be stored. + // this command has no reply. +string REMOVE_ITEM_COMMAND = "rm_I"; + // accepts a list of names for items. all the mentioned ones will be removed from the list. + // this command also has no reply. +string GET_COW_LENGTH = "get_Lc"; + // returns a single integer which is the length of the cow's list currently. +string GET_ITEM_COMMAND = "get_I"; + // retrieves the item's contents for a given name. first parm is the name. if there + // are other parameters, then they are taken as other items to return also. + // the return data will be pairs of for each of the names in the request + // that is not empty. note that you can use an integer index by prefacing it with a + // '#' sign. for example, asking for item "#32" will return index 32 in the list of items. +string TAGGED_GET_ITEM_COMMAND = "get_T"; + // like get item, except the first parameter is an identifier that the caller wants to + // use to tag this request. the other parameters are still taken as names. the response + // will contain the tag as the first item, then the pairs that were found. +////////////// + +// sets up the data cow for business. +initialize() +{ + // flush all contents. + the_list = []; + the_names = []; +} + +// find a named item in our list, if it exists. +integer lookup_item(string name) +{ + integer indy; + if (llGetSubString(name, 0, 0) == "#") { + // our special sign for just using an index. + indy = (integer)llGetSubString(name, 1, -1); + if ( (indy >= 0) && (indy < llGetListLength(the_names)) ) return indy; + } else { + for (indy = 0; indy < llGetListLength(the_names); indy++) { + if (name == llList2String(the_names, indy)) return indy; // we know where it is now. + } + } + return -1; // never found it. +} + +// places a named item in our list. if there's an existing item with +// that name, then it's replaced. +integer global_mem_complained = FALSE; +add_item(string name, string content) +{ + if (llGetFreeMemory() < 2000) { + if (!global_mem_complained) { + global_mem_complained = TRUE; + llOwnerSay("out of memory at " + name); + } + return; + } + integer current = lookup_item(name); + if (current < 0) { +//llOwnerSay("new item: " + name); + // this is a new item. + the_names += name; + the_list += content; + } else { +//llOwnerSay("reusing slot " + (string)current + " for " + name); + // this is an old item to be replaced. + the_list = chop_list(the_list, 0, current - 1) + + [ content ] + + chop_list(the_list, current + 1, llGetListLength(the_list) - 1); + } +//log_it("mem=" + (string)llGetFreeMemory()); +} + +// deletes an existing item if possible. TRUE is returned on success. +integer remove_item(string name) +{ + integer indy = lookup_item(name); + if (indy < 0) return FALSE; // not present. + // found our sad whackee. we know the name and content should be + // stored at the exact same index in the two lists. + the_names = chop_list(the_names, 0, indy - 1) + + chop_list(the_names, indy + 1, llGetListLength(the_names) - 1); + the_list = chop_list(the_list, 0, indy - 1) + + chop_list(the_list, indy + 1, llGetListLength(the_list) - 1); + return TRUE; // all done here. +} + +// supports our link message API by answering requests from clients. +handle_link_message(integer sender, integer num, string msg, key id) +{ + if (num != DATA_COW_HUFFWARE_ID) return; // not for us. +//log_it("hlm--mem free=" + (string)llGetFreeMemory()); +//log_it("rcvd: " + msg + " " + (string)num + " " + (string)id); + if (msg == RESET_LIST_COMMAND) { + initialize(); + } else if (msg == ADD_ITEM_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy += 2) { + add_item(llList2String(parms, indy), llList2String(parms, indy + 1)); + } + } else if (msg == REMOVE_ITEM_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy++) { + remove_item(llList2String(parms, indy)); + } + } else if (msg == GET_COW_LENGTH) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string tag = llList2String(parms, 0); + list to_reply; + if (tag != "") to_reply = [ tag ]; + to_reply += [ llGetListLength(the_list) ]; + send_reply(LINK_THIS, to_reply, msg); + } else if ( (msg == GET_ITEM_COMMAND) || (msg == TAGGED_GET_ITEM_COMMAND) ) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + string tag; + if (msg == TAGGED_GET_ITEM_COMMAND) { + // extract the tag, if they want that type of command handling. + tag = llList2String(parms, 0); + parms = llDeleteSubList(parms, 0, 0); + } + list to_reply; + // make sure we return the tag if they gave us one. + if (tag != "") to_reply = [ tag ]; + for (indy = 0; indy < llGetListLength(parms); indy++) { + // iterate through the parameters and reply about any that we find. + integer found_posn = lookup_item(llList2String(parms, indy)); + if (found_posn >= 0) { + // this item did exist. + to_reply += [ llList2String(the_names, found_posn), llList2String(the_list, found_posn) ]; + } + } + send_reply(LINK_THIS, to_reply, msg); + } +} + +////////////// +// from hufflets... +// +//integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +//log_it(string to_say) +//{ +// debug_num++; +// // tell this to the owner. +// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +// // say this on open chat, but use an unusual channel. +//// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, DATA_COW_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// +// end hufflets +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { initialize(); } + + link_message(integer sender, integer num, string msg, key id) + { handle_link_message(sender, num, msg, id); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.lsl deleted file mode 100755 index 1a4e1a30..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.lsl +++ /dev/null @@ -1,76 +0,0 @@ -=================================== -info about the searchbert seeker robot -=================================== - -### -version 46.4 -released February 26 2012 -### - -author=fred huffhines (osgrid and second life avatar) -source=eepaw shop (see below) -price=*free* -** note: if you paid for this, someone ripped you off. please let fred huffhines in osgrid or second life know about this. -license = gpl [ http://www.gnu.org/licenses/gpl.html ] within metaverse (osgrid, opensims, second life, etc). - - searchbert is a full-perm second life search engine that i created for the free scripts library (which used to be in the Solvo region of second life, but which no longer exists, sadly). - - this device can find matches for nearby objects given just a part of the object's name. after doings its scan, searchbert points out all the objects with multi-colored particle beams. - - the objects can be scattered at different heights and distances, even fairly far away from searchbert, and still be accurately located. avatars will also be found if their names match the search. searchbert can point out up to 17 objects and avatars. - - if you 'Touch' searchbert, then it will tell you its usage info. here is a more detailed version of the help information. - you can speak these commands near searchbert in open chat to give it some orders: - - #find X - looks for any object nearby with "X" in its name. - try this one out: "#find primitive" (in osgrid) or "#find object" (in second life) - that will find any items that have been left with their respective default names. - and this is a nice one: "#find e" - finds any object whose name contains the letter 'e'. that's usually very many things. - - #reset - clears any existing search matches that had been found. the matches will eventually time-out and be forgotten anyhow, but this makes searchbert forget the search immediately. - if this command is used by the owner of searchbert while a search is active, it stops the search immediately, but doesn't clear any matches that may already have been found. #reset can only be used this way by the owner, which avoids random people stopping each other's searches. - - #initialize - hard core brain-clearing command for the searchbert; makes it fully clear out and restart its scripts. - - #skew - *bonus* a debugging command that makes searchbert point its arms in all directions. - - #channel - allows the listening channel for searchbert to be changed. example: - #channel 42 - this makes searchbert listen for any commands on channel 42, a fact which should be reflected - in the menus and chat after this.. - -that's about it for the basics... enjoy! ---fred huffhines - -==== -more detailed and nutty searchbert notes... - -* searchbert builds upon original scripts by christopher omega and ama omega, which gave me a starting point for the particle system and link message communication. i have put quite a lot of time into the searchbert also, to make it zoom around in a spiral and so forth. - -* searchbert gets around second life's limitations on the number of search matches by moving around and looking at things from different angles. it uses a spiral search pattern to traverse the area. it has multiple "seeker rods" to find matches, and these are aimed in different directions to increase the likelihood of finding matches. further, during the search, searchbert is gradually rotated to different orientations to cover even more area. - -* you can rip all of searchbert's arms off and it won't feel a thing! rez a searchbert on land where you have permissions, right-click on it and select "Edit". when the editing dialog has popped up, hit this key combination: "ctrl-shift-L". that is the "remove all links" shortcut command, and it will separate all the arms from searchbert's main body (the sphere). the arms will take this very poorly and all die, but the sphere will survive. after that ugliness, clicking on searchbert will make it perform its "putting my arms back on" schtick for about 17 seconds. it needs permission to attach objects, and will ask for it. after the arms are finished being snapped back on, searchbert will be fully functional again. - -* release 46.0 sees the arm reattachment code in a separate script. we were doing fine with version 42.0 in open simulator, but second life had other ideas about how much space a script is allowed to occupy when compiled. this forced us to separate out the code for the arm reattachment procedures in a 'searchbert armature' script. this script also takes care of synchronizing content with the seeker arms. fracturing searchbert's code in this way actually led to a few simplifications, so maybe it's now better overall, but being _forced_ to refactor is not exactly the ideal process for optimal software development. - -* as of searchbert 42.0, there is a notecard configuration system and a menuing system. the options available in the notecards for configuration are broader than what is available in the menu interface, so far. -due to how scripts work, if you reset the scripts, then any items configured from the menu are forgotten and searchbert will fall back to whatever is specified in the notecard. - -* the search range at which objects will be found can be re-configured inside searchbert's "searchbert config vX.Y" notecard. there are two parts to this. the max_spiral_radius variable is the maximum distance searchbert will travel away from its starting point. the sensor_max_range variable is the maximum distance used for a sensor scan. so the maximum distance from its starting point that searchbert will ever be able to find an object at is max_spiral_radius + sensor_max_range. - -* as of searchbert 32.5, searchbert is low lag: - old searchbert 31.3 crushed performance of densely packed and also second life's "openspace sims" before, eating up to 10% of the sim's recommended cpu. - that was then, version 32.5 is now (or was "now" when i wrote this screed); it uses about 10% of its former resources (so more like 1% or less of sim cpu) when it's active. thanks very much to eren padar for measuring its performance with elf clan's estate tools. - also this version doesn't ask for link permissions unless it needs to put its arms back on. thanks to hippyjim starbrook for that suggestion. - -* searchbert is the freebie mascot for our store, Eclectic Electric Patterns and Widgets (eepaw). - check out the licensing notecard for our store locations. - -* thanks for reading the extended notes. you are a patient, patient person. --fred huffhines. - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.txt new file mode 100755 index 00000000..1a4e1a30 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/docs_for_searchbert_v2.2.txt @@ -0,0 +1,76 @@ +=================================== +info about the searchbert seeker robot +=================================== + +### +version 46.4 +released February 26 2012 +### + +author=fred huffhines (osgrid and second life avatar) +source=eepaw shop (see below) +price=*free* +** note: if you paid for this, someone ripped you off. please let fred huffhines in osgrid or second life know about this. +license = gpl [ http://www.gnu.org/licenses/gpl.html ] within metaverse (osgrid, opensims, second life, etc). + + searchbert is a full-perm second life search engine that i created for the free scripts library (which used to be in the Solvo region of second life, but which no longer exists, sadly). + + this device can find matches for nearby objects given just a part of the object's name. after doings its scan, searchbert points out all the objects with multi-colored particle beams. + + the objects can be scattered at different heights and distances, even fairly far away from searchbert, and still be accurately located. avatars will also be found if their names match the search. searchbert can point out up to 17 objects and avatars. + + if you 'Touch' searchbert, then it will tell you its usage info. here is a more detailed version of the help information. + you can speak these commands near searchbert in open chat to give it some orders: + + #find X + looks for any object nearby with "X" in its name. + try this one out: "#find primitive" (in osgrid) or "#find object" (in second life) + that will find any items that have been left with their respective default names. + and this is a nice one: "#find e" + finds any object whose name contains the letter 'e'. that's usually very many things. + + #reset + clears any existing search matches that had been found. the matches will eventually time-out and be forgotten anyhow, but this makes searchbert forget the search immediately. + if this command is used by the owner of searchbert while a search is active, it stops the search immediately, but doesn't clear any matches that may already have been found. #reset can only be used this way by the owner, which avoids random people stopping each other's searches. + + #initialize + hard core brain-clearing command for the searchbert; makes it fully clear out and restart its scripts. + + #skew + *bonus* a debugging command that makes searchbert point its arms in all directions. + + #channel + allows the listening channel for searchbert to be changed. example: + #channel 42 + this makes searchbert listen for any commands on channel 42, a fact which should be reflected + in the menus and chat after this.. + +that's about it for the basics... enjoy! +--fred huffhines + +==== +more detailed and nutty searchbert notes... + +* searchbert builds upon original scripts by christopher omega and ama omega, which gave me a starting point for the particle system and link message communication. i have put quite a lot of time into the searchbert also, to make it zoom around in a spiral and so forth. + +* searchbert gets around second life's limitations on the number of search matches by moving around and looking at things from different angles. it uses a spiral search pattern to traverse the area. it has multiple "seeker rods" to find matches, and these are aimed in different directions to increase the likelihood of finding matches. further, during the search, searchbert is gradually rotated to different orientations to cover even more area. + +* you can rip all of searchbert's arms off and it won't feel a thing! rez a searchbert on land where you have permissions, right-click on it and select "Edit". when the editing dialog has popped up, hit this key combination: "ctrl-shift-L". that is the "remove all links" shortcut command, and it will separate all the arms from searchbert's main body (the sphere). the arms will take this very poorly and all die, but the sphere will survive. after that ugliness, clicking on searchbert will make it perform its "putting my arms back on" schtick for about 17 seconds. it needs permission to attach objects, and will ask for it. after the arms are finished being snapped back on, searchbert will be fully functional again. + +* release 46.0 sees the arm reattachment code in a separate script. we were doing fine with version 42.0 in open simulator, but second life had other ideas about how much space a script is allowed to occupy when compiled. this forced us to separate out the code for the arm reattachment procedures in a 'searchbert armature' script. this script also takes care of synchronizing content with the seeker arms. fracturing searchbert's code in this way actually led to a few simplifications, so maybe it's now better overall, but being _forced_ to refactor is not exactly the ideal process for optimal software development. + +* as of searchbert 42.0, there is a notecard configuration system and a menuing system. the options available in the notecards for configuration are broader than what is available in the menu interface, so far. +due to how scripts work, if you reset the scripts, then any items configured from the menu are forgotten and searchbert will fall back to whatever is specified in the notecard. + +* the search range at which objects will be found can be re-configured inside searchbert's "searchbert config vX.Y" notecard. there are two parts to this. the max_spiral_radius variable is the maximum distance searchbert will travel away from its starting point. the sensor_max_range variable is the maximum distance used for a sensor scan. so the maximum distance from its starting point that searchbert will ever be able to find an object at is max_spiral_radius + sensor_max_range. + +* as of searchbert 32.5, searchbert is low lag: + old searchbert 31.3 crushed performance of densely packed and also second life's "openspace sims" before, eating up to 10% of the sim's recommended cpu. + that was then, version 32.5 is now (or was "now" when i wrote this screed); it uses about 10% of its former resources (so more like 1% or less of sim cpu) when it's active. thanks very much to eren padar for measuring its performance with elf clan's estate tools. + also this version doesn't ask for link permissions unless it needs to put its arms back on. thanks to hippyjim starbrook for that suggestion. + +* searchbert is the freebie mascot for our store, Eclectic Electric Patterns and Widgets (eepaw). + check out the licensing notecard for our store locations. + +* thanks for reading the extended notes. you are a patient, patient person. --fred huffhines. + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.lsl deleted file mode 100755 index d637d22d..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.lsl +++ /dev/null @@ -1,20 +0,0 @@ -Dateline: 2011 07 02 -Location: eepaw shop [Eclectic Electric Patterns And Widgets] - -Greetings Fellow Slackers, - -Let it be known that the eepaw freebie store location is in the osgrid in the Wright Plaza region: - osgrid.org -- Wright Plaza <228, 22, 21> - (there is lots of info about osgrid at: http://osgrid.org/ and you can get a free account here: http://www.osgrid.org/index.php/auth/register). - -And our old shop in Second Life is still hanging in there in the Smoky region: - http://slurl.com/secondlife/Smoky/14/84/404 - -Plus we have a twitter feed now provided by a helpful hamster: - http://twitter.com/#!/fred_hamster - -Please do come and visit the eepaw shop for fun times and to see our weird gadgets and widgets, and furthur for surreal and psychedelic textures. We are awaiting your arrival with hot beverages and a pleasant attitude. The beverages are virtual, but the attitude is real. - -Thanks Folks, -Fred Huffhines, -eepaw shop proprietor. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.txt new file mode 100755 index 00000000..d637d22d --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/eepaw_shop_note_v0.8.txt @@ -0,0 +1,20 @@ +Dateline: 2011 07 02 +Location: eepaw shop [Eclectic Electric Patterns And Widgets] + +Greetings Fellow Slackers, + +Let it be known that the eepaw freebie store location is in the osgrid in the Wright Plaza region: + osgrid.org -- Wright Plaza <228, 22, 21> + (there is lots of info about osgrid at: http://osgrid.org/ and you can get a free account here: http://www.osgrid.org/index.php/auth/register). + +And our old shop in Second Life is still hanging in there in the Smoky region: + http://slurl.com/secondlife/Smoky/14/84/404 + +Plus we have a twitter feed now provided by a helpful hamster: + http://twitter.com/#!/fred_hamster + +Please do come and visit the eepaw shop for fun times and to see our weird gadgets and widgets, and furthur for surreal and psychedelic textures. We are awaiting your arrival with hot beverages and a pleasant attitude. The beverages are virtual, but the attitude is real. + +Thanks Folks, +Fred Huffhines, +eepaw shop proprietor. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.lsl deleted file mode 100755 index 1671e5a3..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.lsl +++ /dev/null @@ -1,201 +0,0 @@ - -// huffware script: fade opacity, by fred huffhines, bsd-style license. -// -// when the object is touched, the opacity changes towards either -// totally transparent or totally opaque. when touch stops, the -// changes stop. the next time the objects is touched, the opacity -// changes in the opposite direction. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// modifiable parameters for the fading... - -integer SWITCH_ONLY = FALSE; // if true, does not fade, just switches on and off. - -float pace_increment = 0.02; // how much we change transparency in one timer call. - -float timer_interval = 0.1; // how frequently timer is hit. - -float highest_opacity = 1.0; // the most visible an object can be. - -float lowest_opacity = 0.0; // the least visible an object can be. - -//integer FADE_TARGETS = LINK_THIS; // affect only the prim this script is in. -integer FADE_TARGETS = LINK_SET; // fade the entire object, all prims. -//integer FADE_TARGETS = 3; // fade just the second prim, not the root. - -// globals... - -float global_direction = -1.0; - // tells us whether we are making the object more transparent - // (positive numbers) or less transparent (negative numbers). - -integer last_update; - // unix time of last mention of the opacity. - -// displays the current opaqueness of the object. -show_opacity() -{ - float opacity = llGetAlpha(ALL_SIDES) / (float)llGetNumberOfSides() * 100.0; - string message = (string)((integer)opacity) + "% opacity"; - llSetText(message, <.2, .8, .6>, 1.0); - // whisper the setting if we haven't in a bit. - if (llGetUnixTime() - last_update >= 2) { - llWhisper(0, message); - last_update = llGetUnixTime(); - } -} - -// get rid of the text label. -show_nothing() { llSetText("", <0.0, 0.0, 0.0>, 0.0); } - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - show_nothing(); // clean out any existing text. - last_update = llGetUnixTime(); - } - - touch_start(integer total_number) { - global_direction *= -1.0; // change the direction for next time. - if (SWITCH_ONLY) { - if (global_direction > 0.0) - llSetLinkAlpha(FADE_TARGETS, highest_opacity, ALL_SIDES); - else - llSetLinkAlpha(FADE_TARGETS, lowest_opacity, ALL_SIDES); - } else { - // do the full fade routine. start the timer to change the - // opacity while the avatar keeps touching the object. - llSetTimerEvent(timer_interval); - } - } - - touch_end(integer total_number) { - llSetTimerEvent(0); // stop the timer. - show_nothing(); // clear the text out. - } - - timer() { - float current = llGetAlpha(ALL_SIDES) / (float)llGetNumberOfSides() - + pace_increment * global_direction; - if (current > highest_opacity) { current = highest_opacity; } - if (current < lowest_opacity) { current = lowest_opacity; } - // change transparency on all links, including root prim. - llSetLinkAlpha(FADE_TARGETS, current, ALL_SIDES); - show_opacity(); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.txt new file mode 100755 index 00000000..1671e5a3 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_opacity_v3.7.txt @@ -0,0 +1,201 @@ + +// huffware script: fade opacity, by fred huffhines, bsd-style license. +// +// when the object is touched, the opacity changes towards either +// totally transparent or totally opaque. when touch stops, the +// changes stop. the next time the objects is touched, the opacity +// changes in the opposite direction. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// modifiable parameters for the fading... + +integer SWITCH_ONLY = FALSE; // if true, does not fade, just switches on and off. + +float pace_increment = 0.02; // how much we change transparency in one timer call. + +float timer_interval = 0.1; // how frequently timer is hit. + +float highest_opacity = 1.0; // the most visible an object can be. + +float lowest_opacity = 0.0; // the least visible an object can be. + +//integer FADE_TARGETS = LINK_THIS; // affect only the prim this script is in. +integer FADE_TARGETS = LINK_SET; // fade the entire object, all prims. +//integer FADE_TARGETS = 3; // fade just the second prim, not the root. + +// globals... + +float global_direction = -1.0; + // tells us whether we are making the object more transparent + // (positive numbers) or less transparent (negative numbers). + +integer last_update; + // unix time of last mention of the opacity. + +// displays the current opaqueness of the object. +show_opacity() +{ + float opacity = llGetAlpha(ALL_SIDES) / (float)llGetNumberOfSides() * 100.0; + string message = (string)((integer)opacity) + "% opacity"; + llSetText(message, <.2, .8, .6>, 1.0); + // whisper the setting if we haven't in a bit. + if (llGetUnixTime() - last_update >= 2) { + llWhisper(0, message); + last_update = llGetUnixTime(); + } +} + +// get rid of the text label. +show_nothing() { llSetText("", <0.0, 0.0, 0.0>, 0.0); } + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + show_nothing(); // clean out any existing text. + last_update = llGetUnixTime(); + } + + touch_start(integer total_number) { + global_direction *= -1.0; // change the direction for next time. + if (SWITCH_ONLY) { + if (global_direction > 0.0) + llSetLinkAlpha(FADE_TARGETS, highest_opacity, ALL_SIDES); + else + llSetLinkAlpha(FADE_TARGETS, lowest_opacity, ALL_SIDES); + } else { + // do the full fade routine. start the timer to change the + // opacity while the avatar keeps touching the object. + llSetTimerEvent(timer_interval); + } + } + + touch_end(integer total_number) { + llSetTimerEvent(0); // stop the timer. + show_nothing(); // clear the text out. + } + + timer() { + float current = llGetAlpha(ALL_SIDES) / (float)llGetNumberOfSides() + + pace_increment * global_direction; + if (current > highest_opacity) { current = highest_opacity; } + if (current < lowest_opacity) { current = lowest_opacity; } + // change transparency on all links, including root prim. + llSetLinkAlpha(FADE_TARGETS, current, ALL_SIDES); + show_opacity(); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.lsl deleted file mode 100755 index 95e89026..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.lsl +++ /dev/null @@ -1,158 +0,0 @@ - -// huffware script: fade prim, by fred huffhines -// -// makes an object fade in and out of visibility. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -float OPACITY_MIN = 0.4; // the lowest value to allow the transparency to reach. -float OPACITY_MAX = 1.0; // the highest value to allow the transparent - // if you set this above the max of 1.0, it keeps the object solid for longer. - -float TIMER_INTERVAL = 1.5; // how often do we adjust our appearance? - -// variables... - -float current_opacity = 0.42; // what is our current opacity? -float current_adjustment = 0.2; // amount added/removed each time. - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} -// -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - llSetTimerEvent(TIMER_INTERVAL); - } - - timer() { - llSetTimerEvent(0); - llSetLinkAlpha(LINK_SET, current_opacity, ALL_SIDES); - current_opacity += current_adjustment; - if (current_opacity < OPACITY_MIN) { current_opacity = OPACITY_MIN; current_adjustment *= -1.0; } - if (current_opacity > OPACITY_MAX) { current_opacity = OPACITY_MAX; current_adjustment *= -1.0; } - llSetTimerEvent(TIMER_INTERVAL); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.txt new file mode 100755 index 00000000..95e89026 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/fade_prim_v3.2.txt @@ -0,0 +1,158 @@ + +// huffware script: fade prim, by fred huffhines +// +// makes an object fade in and out of visibility. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +float OPACITY_MIN = 0.4; // the lowest value to allow the transparency to reach. +float OPACITY_MAX = 1.0; // the highest value to allow the transparent + // if you set this above the max of 1.0, it keeps the object solid for longer. + +float TIMER_INTERVAL = 1.5; // how often do we adjust our appearance? + +// variables... + +float current_opacity = 0.42; // what is our current opacity? +float current_adjustment = 0.2; // amount added/removed each time. + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} +// +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + llSetTimerEvent(TIMER_INTERVAL); + } + + timer() { + llSetTimerEvent(0); + llSetLinkAlpha(LINK_SET, current_opacity, ALL_SIDES); + current_opacity += current_adjustment; + if (current_opacity < OPACITY_MIN) { current_opacity = OPACITY_MIN; current_adjustment *= -1.0; } + if (current_opacity > OPACITY_MAX) { current_opacity = OPACITY_MAX; current_adjustment *= -1.0; } + llSetTimerEvent(TIMER_INTERVAL); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.lsl deleted file mode 100755 index ca481916..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.lsl +++ /dev/null @@ -1,669 +0,0 @@ - -// huffware script: fredboxmux (no rotation), by fred huffhines. -// -// a memory saving kludge script; it is the combination of the canonical huffware -// scripts: (1) non-script giver, (2) rotanium rotato, (3) text label. -// our theory is that by having only two scripts per display object (this script and -// the updater client) instead of four, we'll save some cpu on our overburdened but -// beloved server (serene). -// given that this script is intended to replace those three scripts, it will eat them -// on startup to avoid having redundant services in the object. -// update for april 24 2011: added a question menu before doing the copying to user's -// inventory, since opensim can do a weird thing that sets all folders to "loading...". -// this now keeps the objects from being super annoying when one didn't mean to click it. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// non-script giver: -// -// gives all objects, notecards, etc contained in an object when that object is touched. -// does not give out scripts, since these are generally not something that should be handed -// to the customer. -// -// rotanium rotato: -// -// causes the object to rotate according to the parameters set below. -// this can use herky-jerky timed rotation with llSetRot or it can use -// smooth rotation with llTargetOmega. -// -// text label: -// -// a super simple script for giving an object readable text. - -integer DEBUGGING = FALSE; // set to true for noisier runs. - -integer DO_ROTATION = FALSE; // is this the rotating version or not? - -integer USE_SENSORS = TRUE; // should we look for avatars so we can display the label? - -float SMOOTH_TIMER_FREQUENCY = 7.0; - // fastest possible rate of change for the smooth rotater, in seconds. the smooth - // rotater doesn't need to hit the timer all that often, but this is faster than it - // needs to be for rotation, since it is also used as the rate at which the avatar sensor - // fires. - -float TIME_TO_CLEAR_TITLE = 8.0; - // how many seconds before the title that was set for an avatar or due to a touch will - // disappear again. - -vector LABEL_COLOR = <0.3, 0.9, 0.4>; - // color of the text above object. - -float ACTIVE_LABEL_DISTANCE = 5.0; - // how far away can avatars cause the label to light up? - -integer ONLY_GIVE_TO_OWNER = TRUE; - // if this is true, then only the owner will receive a copy of the items. - -integer GIVE_UNCOPYABLES = FALSE; - // this flag is dangerous when true, because it means that uncopyable objects will still - // be handed to the target. if that target refuses the non-copyable items, then the items - // will be lost forever. that is not so good if you've sold the person a non-copy item. - -string EXCLUDED_NOTECARD = "product description"; - // a special case; if there is a giftorse configuration card, we won't hand that out. - -float SMOOTH_CHANCE_FOR_ADJUSTING = 0.28; - // we won't always change the smooth rotation, even though our timer is pretty slow. - // this value is the percentage of the time that we do actually change rotation (divided - // by 100). - -float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; - // the gain is how fast we will rotate in radians per second. - // PI / 2 is about 90 degrees per second, which seems way too fast. - // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, - // and 0.0490873852122 is about PI / 64. - -string object_label = "default"; // change this if you want a specific name. - -string old_name; // tracks the last known name so we know if we need to update title. -float old_opacity = 3.14; // tracks the last opacity setting for the label. - -integer label_changed = TRUE; - // this remembers if the label has stayed put or not. we use it to decide - // whether we need to check the label for carriage returns. - -vector current_add_in = <0.0, 0.0, 0.4>; - // randomly assigned to if RANDOMIZE_ROTATION is true. - -float current_gain = -0.05; - // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. - -float MIN_ADDITION = 0.01; - // smallest amount of change we will ever have. -float MAX_ADDITION = 7.0; - // largest amount of change we will ever have. - -key first_toucher; // tracks who clicked on the object to get contents. - -float label_opacity = 1.0; // how opaque should text be? 1.0 is solid, 0.0 transparent. - -// takes out the 3 scripts that have been combined into the mux. otherwise, it's -// more of a pain to update all the boxes with this thing when it's ready to go. -remove_redundant_scripts() -{ - integer posn; - string self = llGetScriptName(); - // zoom across the scripts to see if we have any in the inventory that - // are slated for removal. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if (curr_script != self) { - if ( (llSubStringIndex(curr_script, "non-script giver") == 0) - || (llSubStringIndex(curr_script, "rotanium rotato") == 0) - || (llSubStringIndex(curr_script, "text label") == 0) ) { - // this one is a match! zap it. - llRemoveInventory(curr_script); - } - - } - } -} - -// the avatar has said it's okay to hand out all the stuff to her/him. -really_give_contents() { give_out_contents(first_toucher); } - -// give out pictures, notecards, objects, etc. that are hiding in the object. -give_out_contents(key give_to) -{ - list all_to_give = []; // the set we will hand over in a batch. - list uncopyables = []; // the list we have to do individually. - // find out how many items there are. - integer count = llGetInventoryNumber(INVENTORY_ALL); - // iterate across all the items and add them to the gift list if appropriate. - integer indy; - for (indy = 0; indy < count; indy++) { - string item_name = llGetInventoryName(INVENTORY_ALL, indy); - integer type = llGetInventoryType(item_name); - if ( (type != INVENTORY_SCRIPT) - && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { - // it's okay to add this item; it's not a script and we are not skipping the special notecard. - integer mask = MASK_OWNER; - if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; - integer perms = llGetInventoryPermMask(item_name, mask); - if (perms & PERM_COPY) { - // a normal object that we can hand out. - all_to_give += item_name; - } else { - uncopyables += item_name; - } - } - } - // hand the customer the whole set as one big chunk, named after the object. - llGiveInventoryList(give_to, llGetObjectName(), all_to_give); - - // handle any problematic items. we cannot copy these objects into a category folder, - // so we can either not try to copy them (a lot safer) or we can try to deliver them - // normally as individual items. the latter choice is more dangerous, because if the - // owner discards these items rather than keeping them, the items will be lost forever! - if (llGetListLength(uncopyables) > 0) { - string plural = " "; - string is_verb = "is "; - string third_noun_subj = "it "; - string third_noun_obj = "it "; - if (llGetListLength(uncopyables) > 1) { - plural = "s "; - is_verb = "are "; - third_noun_subj = "they "; - third_noun_obj = "them "; - } - - string uncopyable_message = "will be left inside the object. To get " + third_noun_obj - + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; - if (GIVE_UNCOPYABLES) { - uncopyable_message = "will be moved over to your inventory." - + "\nPlease look in your main folders for " - + third_noun_obj + "(e.g., in Objects or Textures)."; - } - - string failure_message = "The item" + plural - + "[" + llDumpList2String(uncopyables, "; ") + "]\n" - + is_verb + "not copyable; " + third_noun_subj - + uncopyable_message; - - if (llGetOwner() == give_to) { - // the object can be moved to inventory, but not with the category method. - llOwnerSay(failure_message); - } else { - // this seems like a weird case; it will probably just fail anyhow? - // if the item's not copyable and you're not the owner of this object, - // how can we give it to you? - llInstantMessage(give_to, failure_message); - } - - // now that we've announced this weird situation, handle it appropriately. - if (GIVE_UNCOPYABLES) { - for (indy = 0; indy < llGetListLength(uncopyables); indy++) { - string item_name = llList2String(uncopyables, indy); - llGiveInventory(give_to, item_name); - } - } // otherwise leave them be. - } -} - -// causes the object to rotate using whatever the current settings are. -smooth_rotate_using_our_settings() -{ - // make sure we are using the rotational values we were asked to. - llTargetOmega(current_add_in, current_gain, 1.0); -} - -// sets the gain and add in to random choices. -randomize_values() -{ - current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); - current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); -} - -// performs the timed rotation that has been configured for us. -rotate_as_requested() -{ - // our slack timer went off, so randomize the rotation if requested. - if (llFrand(1.0) >= (1.0 - SMOOTH_CHANCE_FOR_ADJUSTING) ) { - randomize_values(); - smooth_rotate_using_our_settings(); - } -} - -initialize_fredboxmux() -{ - // make sure we pick a good random channel. - menu_system_channel = -1 * (integer)randomize_within_range(200, 10000000, FALSE); - - // if needed, we will set our initial random rotation. - randomize_values(); - - // do a first rotate, so we move right at startup. otherwise we won't move - // until after our first timer hits. - if (DO_ROTATION) rotate_as_requested(); - - // now set the timer for our mode. - llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); - if (DO_ROTATION) smooth_rotate_using_our_settings(); -} - -set_text() -{ -//log_it("old name " + old_name + " -- curr name " + llGetObjectName()); - if (old_name != llGetObjectName()) { - // we're out of synch on the object name. - label_changed = TRUE; - } - if (old_opacity != label_opacity) { - // here we're out of synch on last opacity used. - label_changed = TRUE; - } - if (label_changed) { - // reset the object title to a decorated version of object name if it says "default". - string new_label = object_label; - if (new_label == "default") new_label = llGetObjectName(); - - integer indy; - integer keep_going = TRUE; - while (keep_going) { - indy = find_substring(new_label, "\\n"); - if (indy < 0) { - keep_going = FALSE; - } else { - new_label = llGetSubString(new_label, 0, indy - 1) - + "\n" + llGetSubString(new_label, indy + 2, -1); - } - } - old_name = llGetObjectName(); - old_opacity = label_opacity; - label_changed = FALSE; // we have dealt with it now. -//log_it("setting text: " + new_label); - llSetText(new_label, LABEL_COLOR, label_opacity); - } - if (label_opacity != 0) { - // if we set a lit-up title, clear it again pretty soon. - llSetTimerEvent(TIME_TO_CLEAR_TITLE); - } -} - -////////////// -// code borrowed from menutini to raise a menu asking if they actually meant to get all -// the contents. an opensim inventory bug makes all the folders look foolish if we -// do any inventory giving accidentally. -////////////// - -// global variables... - -list _private_global_buttons; // holds onto the active set of menu options. -string _private_global_av_key; // the key for the avatar who clicks the menu. -string _private_global_title; // holds onto current title text. - -integer _menu_base_start = 0; // position in the items of the current menu. - -integer listening_id = 0; - // the current id of our listening for the menu. it's an id returned by LSL - // that we need to track so we can cancel the listen. - -integer menu_system_channel = -123; - // messages come back to us from this channel when user clicks the dialog. - // this is set later and the default is meaningless. - -string global_menu_name = ""; - // hangs onto the current menu's name. - -//hmmm: note; to manage multiple concurrent menus on different channels, -// we must make these into lists. then the timeouts should apply -// individually to these instead of overall (if we even do timeouts; -// it's nicer if menus never stop being active). - -string NEXT_MENU_TEXT = "Next >>"; - // what the next item will say for showing next menu page. - -//integer TIMEOUT_FOR_MENU = 42; - // timeout for the menu in seconds. - -// displays the menu requested. it's "menu_name" is an internal name that is -// not displayed to the user. the "title" is the content shown in the main area -// of the menu. "commands_in" is the list of menu items to show as buttons. -// the "menu_channel" is where the user's clicked response will be sent. the -// "listen_to" key is the avatar expected to click the menu, which is needed to -// listen to his response. -show_menu(string menu_name, string title, list buttons, - integer menu_channel, key listen_to) -{ - // save our new parms. - global_menu_name = menu_name; - _private_global_title = title; - _private_global_buttons = buttons; - menu_system_channel = menu_channel; - _private_global_av_key = listen_to; - if (DEBUGGING) { - log_it("menu name: " + global_menu_name); - log_it("title: " + _private_global_title); - log_it("buttons: " + (string)buttons); - log_it("channel: " + (string)menu_system_channel); - log_it("listen key: " + (string)listen_to); - } - - integer add_next = FALSE; // true if we should add a next menu item. - - // the math here incorporates current button position. - integer current = _menu_base_start; - integer max_buttons = llGetListLength(buttons) - current; - - if (max_buttons > 12) { - // limitation of SL: menus have a max of 12 buttons. - max_buttons = 12; - add_next = TRUE; - } else if (llGetListLength(buttons) > 12) { - // we already have been adding next. let's make sure this gets - // a wrap-around next button. - add_next = TRUE; - } - // chop out what we can use in a menu. - list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); - if (add_next) { - // we were asked to add a menu item for the next screen. - trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; - } - - listening_id = llListen(menu_channel, "", listen_to, ""); - list commands; - integer i; - // take only the prefix of the string, to avoid getting a length complaint. - for (i = 0; i < llGetListLength(trunc_buttons); i++) { - string curr = llList2String(trunc_buttons, i); - integer last_pos = 23; // default maximum, highest possible is 24. - if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; - curr = llGetSubString(curr, 0, last_pos); - commands += curr; - } - llDialog(listen_to, title, commands, menu_channel); -} - -// shuts down any connection we might have had with any active menu. we will not -// send any responses after this point (although we might already have responded when -// the user clicked the menu). -clear_menu() -{ - llListenRemove(listening_id); -} - -// process the response when the user chooses a menu item. -process_menu_response(integer channel, string name, key id, string message) -{ - if (channel != menu_system_channel) return; // not for us. - - if (message == NEXT_MENU_TEXT) { - // this is the special choice, so we need to go to the next page. - _menu_base_start += 11; - if (_menu_base_start > llGetListLength(_private_global_buttons)) { - // we have wrapped around the list. go to the start again. - _menu_base_start = 0; - } - show_menu(global_menu_name, _private_global_title, - _private_global_buttons, menu_system_channel, - _private_global_av_key); - return; // handled by opening a new menu. - } - - string calculated_name; - integer indy; - // first try for an exact match. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (curr == message) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - if (calculated_name == "") { - // try an imprecise match if the exact matching didn't work. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (is_prefix(curr, message)) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - } - if (calculated_name == "yes") { - // only send a response if that menu choice made sense to us. - really_give_contents(); - clear_menu(); - } -} - -// end from menutini. -////////////// - -////////////// -// start of hufflets... - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -////////////// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//end hufflets... -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - remove_redundant_scripts(); - initialize_fredboxmux(); - label_opacity = 1; // start out showing the label. - set_text(); - } - - on_rez(integer start_parm) { state default; } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - // we show the label at least a bit when the contents change. - label_opacity = 1; - set_text(); - } - } - - touch_start(integer num) { - label_opacity = 1.0; - set_text(); - first_toucher = llDetectedKey(0); - // are we only supposed to give stuff to the owner? - if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { - first_toucher = NULL_KEY; - return; // bail out. - } - show_menu("askreally", "Would you like a copy of this object's contents?", - ["yes", "no"], -18264, first_toucher); - } - - listen(integer channel, string name, key id, string message) - { process_menu_response(channel, name, id, message); } - - timer() { - llSetTimerEvent(0); - if (DO_ROTATION) rotate_as_requested(); - if (USE_SENSORS) { - llSensor("", NULL_KEY, AGENT, ACTIVE_LABEL_DISTANCE, PI); - } else { - if (label_opacity != 0.0) { - label_opacity = 0.0; - set_text(); - } - } - llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); - } - - sensor(integer count) { - if (label_opacity != 1.0) { - label_opacity = 1.0; - set_text(); - } - } - - no_sensor() { - if (label_opacity != 0.0) { - label_opacity = 0.0; - set_text(); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.txt new file mode 100755 index 00000000..ca481916 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_no_rot_v3.0.txt @@ -0,0 +1,669 @@ + +// huffware script: fredboxmux (no rotation), by fred huffhines. +// +// a memory saving kludge script; it is the combination of the canonical huffware +// scripts: (1) non-script giver, (2) rotanium rotato, (3) text label. +// our theory is that by having only two scripts per display object (this script and +// the updater client) instead of four, we'll save some cpu on our overburdened but +// beloved server (serene). +// given that this script is intended to replace those three scripts, it will eat them +// on startup to avoid having redundant services in the object. +// update for april 24 2011: added a question menu before doing the copying to user's +// inventory, since opensim can do a weird thing that sets all folders to "loading...". +// this now keeps the objects from being super annoying when one didn't mean to click it. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// non-script giver: +// +// gives all objects, notecards, etc contained in an object when that object is touched. +// does not give out scripts, since these are generally not something that should be handed +// to the customer. +// +// rotanium rotato: +// +// causes the object to rotate according to the parameters set below. +// this can use herky-jerky timed rotation with llSetRot or it can use +// smooth rotation with llTargetOmega. +// +// text label: +// +// a super simple script for giving an object readable text. + +integer DEBUGGING = FALSE; // set to true for noisier runs. + +integer DO_ROTATION = FALSE; // is this the rotating version or not? + +integer USE_SENSORS = TRUE; // should we look for avatars so we can display the label? + +float SMOOTH_TIMER_FREQUENCY = 7.0; + // fastest possible rate of change for the smooth rotater, in seconds. the smooth + // rotater doesn't need to hit the timer all that often, but this is faster than it + // needs to be for rotation, since it is also used as the rate at which the avatar sensor + // fires. + +float TIME_TO_CLEAR_TITLE = 8.0; + // how many seconds before the title that was set for an avatar or due to a touch will + // disappear again. + +vector LABEL_COLOR = <0.3, 0.9, 0.4>; + // color of the text above object. + +float ACTIVE_LABEL_DISTANCE = 5.0; + // how far away can avatars cause the label to light up? + +integer ONLY_GIVE_TO_OWNER = TRUE; + // if this is true, then only the owner will receive a copy of the items. + +integer GIVE_UNCOPYABLES = FALSE; + // this flag is dangerous when true, because it means that uncopyable objects will still + // be handed to the target. if that target refuses the non-copyable items, then the items + // will be lost forever. that is not so good if you've sold the person a non-copy item. + +string EXCLUDED_NOTECARD = "product description"; + // a special case; if there is a giftorse configuration card, we won't hand that out. + +float SMOOTH_CHANCE_FOR_ADJUSTING = 0.28; + // we won't always change the smooth rotation, even though our timer is pretty slow. + // this value is the percentage of the time that we do actually change rotation (divided + // by 100). + +float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; + // the gain is how fast we will rotate in radians per second. + // PI / 2 is about 90 degrees per second, which seems way too fast. + // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, + // and 0.0490873852122 is about PI / 64. + +string object_label = "default"; // change this if you want a specific name. + +string old_name; // tracks the last known name so we know if we need to update title. +float old_opacity = 3.14; // tracks the last opacity setting for the label. + +integer label_changed = TRUE; + // this remembers if the label has stayed put or not. we use it to decide + // whether we need to check the label for carriage returns. + +vector current_add_in = <0.0, 0.0, 0.4>; + // randomly assigned to if RANDOMIZE_ROTATION is true. + +float current_gain = -0.05; + // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. + +float MIN_ADDITION = 0.01; + // smallest amount of change we will ever have. +float MAX_ADDITION = 7.0; + // largest amount of change we will ever have. + +key first_toucher; // tracks who clicked on the object to get contents. + +float label_opacity = 1.0; // how opaque should text be? 1.0 is solid, 0.0 transparent. + +// takes out the 3 scripts that have been combined into the mux. otherwise, it's +// more of a pain to update all the boxes with this thing when it's ready to go. +remove_redundant_scripts() +{ + integer posn; + string self = llGetScriptName(); + // zoom across the scripts to see if we have any in the inventory that + // are slated for removal. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if (curr_script != self) { + if ( (llSubStringIndex(curr_script, "non-script giver") == 0) + || (llSubStringIndex(curr_script, "rotanium rotato") == 0) + || (llSubStringIndex(curr_script, "text label") == 0) ) { + // this one is a match! zap it. + llRemoveInventory(curr_script); + } + + } + } +} + +// the avatar has said it's okay to hand out all the stuff to her/him. +really_give_contents() { give_out_contents(first_toucher); } + +// give out pictures, notecards, objects, etc. that are hiding in the object. +give_out_contents(key give_to) +{ + list all_to_give = []; // the set we will hand over in a batch. + list uncopyables = []; // the list we have to do individually. + // find out how many items there are. + integer count = llGetInventoryNumber(INVENTORY_ALL); + // iterate across all the items and add them to the gift list if appropriate. + integer indy; + for (indy = 0; indy < count; indy++) { + string item_name = llGetInventoryName(INVENTORY_ALL, indy); + integer type = llGetInventoryType(item_name); + if ( (type != INVENTORY_SCRIPT) + && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { + // it's okay to add this item; it's not a script and we are not skipping the special notecard. + integer mask = MASK_OWNER; + if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; + integer perms = llGetInventoryPermMask(item_name, mask); + if (perms & PERM_COPY) { + // a normal object that we can hand out. + all_to_give += item_name; + } else { + uncopyables += item_name; + } + } + } + // hand the customer the whole set as one big chunk, named after the object. + llGiveInventoryList(give_to, llGetObjectName(), all_to_give); + + // handle any problematic items. we cannot copy these objects into a category folder, + // so we can either not try to copy them (a lot safer) or we can try to deliver them + // normally as individual items. the latter choice is more dangerous, because if the + // owner discards these items rather than keeping them, the items will be lost forever! + if (llGetListLength(uncopyables) > 0) { + string plural = " "; + string is_verb = "is "; + string third_noun_subj = "it "; + string third_noun_obj = "it "; + if (llGetListLength(uncopyables) > 1) { + plural = "s "; + is_verb = "are "; + third_noun_subj = "they "; + third_noun_obj = "them "; + } + + string uncopyable_message = "will be left inside the object. To get " + third_noun_obj + + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; + if (GIVE_UNCOPYABLES) { + uncopyable_message = "will be moved over to your inventory." + + "\nPlease look in your main folders for " + + third_noun_obj + "(e.g., in Objects or Textures)."; + } + + string failure_message = "The item" + plural + + "[" + llDumpList2String(uncopyables, "; ") + "]\n" + + is_verb + "not copyable; " + third_noun_subj + + uncopyable_message; + + if (llGetOwner() == give_to) { + // the object can be moved to inventory, but not with the category method. + llOwnerSay(failure_message); + } else { + // this seems like a weird case; it will probably just fail anyhow? + // if the item's not copyable and you're not the owner of this object, + // how can we give it to you? + llInstantMessage(give_to, failure_message); + } + + // now that we've announced this weird situation, handle it appropriately. + if (GIVE_UNCOPYABLES) { + for (indy = 0; indy < llGetListLength(uncopyables); indy++) { + string item_name = llList2String(uncopyables, indy); + llGiveInventory(give_to, item_name); + } + } // otherwise leave them be. + } +} + +// causes the object to rotate using whatever the current settings are. +smooth_rotate_using_our_settings() +{ + // make sure we are using the rotational values we were asked to. + llTargetOmega(current_add_in, current_gain, 1.0); +} + +// sets the gain and add in to random choices. +randomize_values() +{ + current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); + current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); +} + +// performs the timed rotation that has been configured for us. +rotate_as_requested() +{ + // our slack timer went off, so randomize the rotation if requested. + if (llFrand(1.0) >= (1.0 - SMOOTH_CHANCE_FOR_ADJUSTING) ) { + randomize_values(); + smooth_rotate_using_our_settings(); + } +} + +initialize_fredboxmux() +{ + // make sure we pick a good random channel. + menu_system_channel = -1 * (integer)randomize_within_range(200, 10000000, FALSE); + + // if needed, we will set our initial random rotation. + randomize_values(); + + // do a first rotate, so we move right at startup. otherwise we won't move + // until after our first timer hits. + if (DO_ROTATION) rotate_as_requested(); + + // now set the timer for our mode. + llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); + if (DO_ROTATION) smooth_rotate_using_our_settings(); +} + +set_text() +{ +//log_it("old name " + old_name + " -- curr name " + llGetObjectName()); + if (old_name != llGetObjectName()) { + // we're out of synch on the object name. + label_changed = TRUE; + } + if (old_opacity != label_opacity) { + // here we're out of synch on last opacity used. + label_changed = TRUE; + } + if (label_changed) { + // reset the object title to a decorated version of object name if it says "default". + string new_label = object_label; + if (new_label == "default") new_label = llGetObjectName(); + + integer indy; + integer keep_going = TRUE; + while (keep_going) { + indy = find_substring(new_label, "\\n"); + if (indy < 0) { + keep_going = FALSE; + } else { + new_label = llGetSubString(new_label, 0, indy - 1) + + "\n" + llGetSubString(new_label, indy + 2, -1); + } + } + old_name = llGetObjectName(); + old_opacity = label_opacity; + label_changed = FALSE; // we have dealt with it now. +//log_it("setting text: " + new_label); + llSetText(new_label, LABEL_COLOR, label_opacity); + } + if (label_opacity != 0) { + // if we set a lit-up title, clear it again pretty soon. + llSetTimerEvent(TIME_TO_CLEAR_TITLE); + } +} + +////////////// +// code borrowed from menutini to raise a menu asking if they actually meant to get all +// the contents. an opensim inventory bug makes all the folders look foolish if we +// do any inventory giving accidentally. +////////////// + +// global variables... + +list _private_global_buttons; // holds onto the active set of menu options. +string _private_global_av_key; // the key for the avatar who clicks the menu. +string _private_global_title; // holds onto current title text. + +integer _menu_base_start = 0; // position in the items of the current menu. + +integer listening_id = 0; + // the current id of our listening for the menu. it's an id returned by LSL + // that we need to track so we can cancel the listen. + +integer menu_system_channel = -123; + // messages come back to us from this channel when user clicks the dialog. + // this is set later and the default is meaningless. + +string global_menu_name = ""; + // hangs onto the current menu's name. + +//hmmm: note; to manage multiple concurrent menus on different channels, +// we must make these into lists. then the timeouts should apply +// individually to these instead of overall (if we even do timeouts; +// it's nicer if menus never stop being active). + +string NEXT_MENU_TEXT = "Next >>"; + // what the next item will say for showing next menu page. + +//integer TIMEOUT_FOR_MENU = 42; + // timeout for the menu in seconds. + +// displays the menu requested. it's "menu_name" is an internal name that is +// not displayed to the user. the "title" is the content shown in the main area +// of the menu. "commands_in" is the list of menu items to show as buttons. +// the "menu_channel" is where the user's clicked response will be sent. the +// "listen_to" key is the avatar expected to click the menu, which is needed to +// listen to his response. +show_menu(string menu_name, string title, list buttons, + integer menu_channel, key listen_to) +{ + // save our new parms. + global_menu_name = menu_name; + _private_global_title = title; + _private_global_buttons = buttons; + menu_system_channel = menu_channel; + _private_global_av_key = listen_to; + if (DEBUGGING) { + log_it("menu name: " + global_menu_name); + log_it("title: " + _private_global_title); + log_it("buttons: " + (string)buttons); + log_it("channel: " + (string)menu_system_channel); + log_it("listen key: " + (string)listen_to); + } + + integer add_next = FALSE; // true if we should add a next menu item. + + // the math here incorporates current button position. + integer current = _menu_base_start; + integer max_buttons = llGetListLength(buttons) - current; + + if (max_buttons > 12) { + // limitation of SL: menus have a max of 12 buttons. + max_buttons = 12; + add_next = TRUE; + } else if (llGetListLength(buttons) > 12) { + // we already have been adding next. let's make sure this gets + // a wrap-around next button. + add_next = TRUE; + } + // chop out what we can use in a menu. + list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); + if (add_next) { + // we were asked to add a menu item for the next screen. + trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; + } + + listening_id = llListen(menu_channel, "", listen_to, ""); + list commands; + integer i; + // take only the prefix of the string, to avoid getting a length complaint. + for (i = 0; i < llGetListLength(trunc_buttons); i++) { + string curr = llList2String(trunc_buttons, i); + integer last_pos = 23; // default maximum, highest possible is 24. + if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; + curr = llGetSubString(curr, 0, last_pos); + commands += curr; + } + llDialog(listen_to, title, commands, menu_channel); +} + +// shuts down any connection we might have had with any active menu. we will not +// send any responses after this point (although we might already have responded when +// the user clicked the menu). +clear_menu() +{ + llListenRemove(listening_id); +} + +// process the response when the user chooses a menu item. +process_menu_response(integer channel, string name, key id, string message) +{ + if (channel != menu_system_channel) return; // not for us. + + if (message == NEXT_MENU_TEXT) { + // this is the special choice, so we need to go to the next page. + _menu_base_start += 11; + if (_menu_base_start > llGetListLength(_private_global_buttons)) { + // we have wrapped around the list. go to the start again. + _menu_base_start = 0; + } + show_menu(global_menu_name, _private_global_title, + _private_global_buttons, menu_system_channel, + _private_global_av_key); + return; // handled by opening a new menu. + } + + string calculated_name; + integer indy; + // first try for an exact match. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (curr == message) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + if (calculated_name == "") { + // try an imprecise match if the exact matching didn't work. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (is_prefix(curr, message)) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + } + if (calculated_name == "yes") { + // only send a response if that menu choice made sense to us. + really_give_contents(); + clear_menu(); + } +} + +// end from menutini. +////////////// + +////////////// +// start of hufflets... + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +////////////// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//end hufflets... +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + remove_redundant_scripts(); + initialize_fredboxmux(); + label_opacity = 1; // start out showing the label. + set_text(); + } + + on_rez(integer start_parm) { state default; } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + // we show the label at least a bit when the contents change. + label_opacity = 1; + set_text(); + } + } + + touch_start(integer num) { + label_opacity = 1.0; + set_text(); + first_toucher = llDetectedKey(0); + // are we only supposed to give stuff to the owner? + if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { + first_toucher = NULL_KEY; + return; // bail out. + } + show_menu("askreally", "Would you like a copy of this object's contents?", + ["yes", "no"], -18264, first_toucher); + } + + listen(integer channel, string name, key id, string message) + { process_menu_response(channel, name, id, message); } + + timer() { + llSetTimerEvent(0); + if (DO_ROTATION) rotate_as_requested(); + if (USE_SENSORS) { + llSensor("", NULL_KEY, AGENT, ACTIVE_LABEL_DISTANCE, PI); + } else { + if (label_opacity != 0.0) { + label_opacity = 0.0; + set_text(); + } + } + llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); + } + + sensor(integer count) { + if (label_opacity != 1.0) { + label_opacity = 1.0; + set_text(); + } + } + + no_sensor() { + if (label_opacity != 0.0) { + label_opacity = 0.0; + set_text(); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.lsl deleted file mode 100755 index c41662c5..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.lsl +++ /dev/null @@ -1,669 +0,0 @@ - -// huffware script: fredboxmux (with rotation), by fred huffhines. -// -// a memory saving kludge script; it is the combination of the canonical huffware -// scripts: (1) non-script giver, (2) rotanium rotato, (3) text label. -// our theory is that by having only two scripts per display object (this script and -// the updater client) instead of four, we'll save some cpu on our overburdened but -// beloved server (serene). -// given that this script is intended to replace those three scripts, it will eat them -// on startup to avoid having redundant services in the object. -// update for april 24 2011: added a question menu before doing the copying to user's -// inventory, since opensim can do a weird thing that sets all folders to "loading...". -// this now keeps the objects from being super annoying when one didn't mean to click it. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// non-script giver: -// -// gives all objects, notecards, etc contained in an object when that object is touched. -// does not give out scripts, since these are generally not something that should be handed -// to the customer. -// -// rotanium rotato: -// -// causes the object to rotate according to the parameters set below. -// this can use herky-jerky timed rotation with llSetRot or it can use -// smooth rotation with llTargetOmega. -// -// text label: -// -// a super simple script for giving an object readable text. - -integer DEBUGGING = FALSE; // set to true for noisier runs. - -integer DO_ROTATION = TRUE; // is this the rotating version or not? - -integer USE_SENSORS = TRUE; // should we look for avatars so we can display the label? - -float SMOOTH_TIMER_FREQUENCY = 7.0; - // fastest possible rate of change for the smooth rotater, in seconds. the smooth - // rotater doesn't need to hit the timer all that often, but this is faster than it - // needs to be for rotation, since it is also used as the rate at which the avatar sensor - // fires. - -float TIME_TO_CLEAR_TITLE = 8.0; - // how many seconds before the title that was set for an avatar or due to a touch will - // disappear again. - -vector LABEL_COLOR = <0.3, 0.9, 0.4>; - // color of the text above object. - -float ACTIVE_LABEL_DISTANCE = 5.0; - // how far away can avatars cause the label to light up? - -integer ONLY_GIVE_TO_OWNER = TRUE; - // if this is true, then only the owner will receive a copy of the items. - -integer GIVE_UNCOPYABLES = FALSE; - // this flag is dangerous when true, because it means that uncopyable objects will still - // be handed to the target. if that target refuses the non-copyable items, then the items - // will be lost forever. that is not so good if you've sold the person a non-copy item. - -string EXCLUDED_NOTECARD = "product description"; - // a special case; if there is a giftorse configuration card, we won't hand that out. - -float SMOOTH_CHANCE_FOR_ADJUSTING = 0.28; - // we won't always change the smooth rotation, even though our timer is pretty slow. - // this value is the percentage of the time that we do actually change rotation (divided - // by 100). - -float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; - // the gain is how fast we will rotate in radians per second. - // PI / 2 is about 90 degrees per second, which seems way too fast. - // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, - // and 0.0490873852122 is about PI / 64. - -string object_label = "default"; // change this if you want a specific name. - -string old_name; // tracks the last known name so we know if we need to update title. -float old_opacity = 3.14; // tracks the last opacity setting for the label. - -integer label_changed = TRUE; - // this remembers if the label has stayed put or not. we use it to decide - // whether we need to check the label for carriage returns. - -vector current_add_in = <0.0, 0.0, 0.4>; - // randomly assigned to if RANDOMIZE_ROTATION is true. - -float current_gain = -0.05; - // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. - -float MIN_ADDITION = 0.01; - // smallest amount of change we will ever have. -float MAX_ADDITION = 7.0; - // largest amount of change we will ever have. - -key first_toucher; // tracks who clicked on the object to get contents. - -float label_opacity = 1.0; // how opaque should text be? 1.0 is solid, 0.0 transparent. - -// takes out the 3 scripts that have been combined into the mux. otherwise, it's -// more of a pain to update all the boxes with this thing when it's ready to go. -remove_redundant_scripts() -{ - integer posn; - string self = llGetScriptName(); - // zoom across the scripts to see if we have any in the inventory that - // are slated for removal. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if (curr_script != self) { - if ( (llSubStringIndex(curr_script, "non-script giver") == 0) - || (llSubStringIndex(curr_script, "rotanium rotato") == 0) - || (llSubStringIndex(curr_script, "text label") == 0) ) { - // this one is a match! zap it. - llRemoveInventory(curr_script); - } - - } - } -} - -// the avatar has said it's okay to hand out all the stuff to her/him. -really_give_contents() { give_out_contents(first_toucher); } - -// give out pictures, notecards, objects, etc. that are hiding in the object. -give_out_contents(key give_to) -{ - list all_to_give = []; // the set we will hand over in a batch. - list uncopyables = []; // the list we have to do individually. - // find out how many items there are. - integer count = llGetInventoryNumber(INVENTORY_ALL); - // iterate across all the items and add them to the gift list if appropriate. - integer indy; - for (indy = 0; indy < count; indy++) { - string item_name = llGetInventoryName(INVENTORY_ALL, indy); - integer type = llGetInventoryType(item_name); - if ( (type != INVENTORY_SCRIPT) - && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { - // it's okay to add this item; it's not a script and we are not skipping the special notecard. - integer mask = MASK_OWNER; - if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; - integer perms = llGetInventoryPermMask(item_name, mask); - if (perms & PERM_COPY) { - // a normal object that we can hand out. - all_to_give += item_name; - } else { - uncopyables += item_name; - } - } - } - // hand the customer the whole set as one big chunk, named after the object. - llGiveInventoryList(give_to, llGetObjectName(), all_to_give); - - // handle any problematic items. we cannot copy these objects into a category folder, - // so we can either not try to copy them (a lot safer) or we can try to deliver them - // normally as individual items. the latter choice is more dangerous, because if the - // owner discards these items rather than keeping them, the items will be lost forever! - if (llGetListLength(uncopyables) > 0) { - string plural = " "; - string is_verb = "is "; - string third_noun_subj = "it "; - string third_noun_obj = "it "; - if (llGetListLength(uncopyables) > 1) { - plural = "s "; - is_verb = "are "; - third_noun_subj = "they "; - third_noun_obj = "them "; - } - - string uncopyable_message = "will be left inside the object. To get " + third_noun_obj - + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; - if (GIVE_UNCOPYABLES) { - uncopyable_message = "will be moved over to your inventory." - + "\nPlease look in your main folders for " - + third_noun_obj + "(e.g., in Objects or Textures)."; - } - - string failure_message = "The item" + plural - + "[" + llDumpList2String(uncopyables, "; ") + "]\n" - + is_verb + "not copyable; " + third_noun_subj - + uncopyable_message; - - if (llGetOwner() == give_to) { - // the object can be moved to inventory, but not with the category method. - llOwnerSay(failure_message); - } else { - // this seems like a weird case; it will probably just fail anyhow? - // if the item's not copyable and you're not the owner of this object, - // how can we give it to you? - llInstantMessage(give_to, failure_message); - } - - // now that we've announced this weird situation, handle it appropriately. - if (GIVE_UNCOPYABLES) { - for (indy = 0; indy < llGetListLength(uncopyables); indy++) { - string item_name = llList2String(uncopyables, indy); - llGiveInventory(give_to, item_name); - } - } // otherwise leave them be. - } -} - -// causes the object to rotate using whatever the current settings are. -smooth_rotate_using_our_settings() -{ - // make sure we are using the rotational values we were asked to. - llTargetOmega(current_add_in, current_gain, 1.0); -} - -// sets the gain and add in to random choices. -randomize_values() -{ - current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); - current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); -} - -// performs the timed rotation that has been configured for us. -rotate_as_requested() -{ - // our slack timer went off, so randomize the rotation if requested. - if (llFrand(1.0) >= (1.0 - SMOOTH_CHANCE_FOR_ADJUSTING) ) { - randomize_values(); - smooth_rotate_using_our_settings(); - } -} - -initialize_fredboxmux() -{ - // make sure we pick a good random channel. - menu_system_channel = -1 * (integer)randomize_within_range(200, 10000000, FALSE); - - // if needed, we will set our initial random rotation. - randomize_values(); - - // do a first rotate, so we move right at startup. otherwise we won't move - // until after our first timer hits. - if (DO_ROTATION) rotate_as_requested(); - - // now set the timer for our mode. - llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); - if (DO_ROTATION) smooth_rotate_using_our_settings(); -} - -set_text() -{ -//log_it("old name " + old_name + " -- curr name " + llGetObjectName()); - if (old_name != llGetObjectName()) { - // we're out of synch on the object name. - label_changed = TRUE; - } - if (old_opacity != label_opacity) { - // here we're out of synch on last opacity used. - label_changed = TRUE; - } - if (label_changed) { - // reset the object title to a decorated version of object name if it says "default". - string new_label = object_label; - if (new_label == "default") new_label = llGetObjectName(); - - integer indy; - integer keep_going = TRUE; - while (keep_going) { - indy = find_substring(new_label, "\\n"); - if (indy < 0) { - keep_going = FALSE; - } else { - new_label = llGetSubString(new_label, 0, indy - 1) - + "\n" + llGetSubString(new_label, indy + 2, -1); - } - } - old_name = llGetObjectName(); - old_opacity = label_opacity; - label_changed = FALSE; // we have dealt with it now. -//log_it("setting text: " + new_label); - llSetText(new_label, LABEL_COLOR, label_opacity); - } - if (label_opacity != 0) { - // if we set a lit-up title, clear it again pretty soon. - llSetTimerEvent(TIME_TO_CLEAR_TITLE); - } -} - -////////////// -// code borrowed from menutini to raise a menu asking if they actually meant to get all -// the contents. an opensim inventory bug makes all the folders look foolish if we -// do any inventory giving accidentally. -////////////// - -// global variables... - -list _private_global_buttons; // holds onto the active set of menu options. -string _private_global_av_key; // the key for the avatar who clicks the menu. -string _private_global_title; // holds onto current title text. - -integer _menu_base_start = 0; // position in the items of the current menu. - -integer listening_id = 0; - // the current id of our listening for the menu. it's an id returned by LSL - // that we need to track so we can cancel the listen. - -integer menu_system_channel = -123; - // messages come back to us from this channel when user clicks the dialog. - // this is set later and the default is meaningless. - -string global_menu_name = ""; - // hangs onto the current menu's name. - -//hmmm: note; to manage multiple concurrent menus on different channels, -// we must make these into lists. then the timeouts should apply -// individually to these instead of overall (if we even do timeouts; -// it's nicer if menus never stop being active). - -string NEXT_MENU_TEXT = "Next >>"; - // what the next item will say for showing next menu page. - -//integer TIMEOUT_FOR_MENU = 42; - // timeout for the menu in seconds. - -// displays the menu requested. it's "menu_name" is an internal name that is -// not displayed to the user. the "title" is the content shown in the main area -// of the menu. "commands_in" is the list of menu items to show as buttons. -// the "menu_channel" is where the user's clicked response will be sent. the -// "listen_to" key is the avatar expected to click the menu, which is needed to -// listen to his response. -show_menu(string menu_name, string title, list buttons, - integer menu_channel, key listen_to) -{ - // save our new parms. - global_menu_name = menu_name; - _private_global_title = title; - _private_global_buttons = buttons; - menu_system_channel = menu_channel; - _private_global_av_key = listen_to; - if (DEBUGGING) { - log_it("menu name: " + global_menu_name); - log_it("title: " + _private_global_title); - log_it("buttons: " + (string)buttons); - log_it("channel: " + (string)menu_system_channel); - log_it("listen key: " + (string)listen_to); - } - - integer add_next = FALSE; // true if we should add a next menu item. - - // the math here incorporates current button position. - integer current = _menu_base_start; - integer max_buttons = llGetListLength(buttons) - current; - - if (max_buttons > 12) { - // limitation of SL: menus have a max of 12 buttons. - max_buttons = 12; - add_next = TRUE; - } else if (llGetListLength(buttons) > 12) { - // we already have been adding next. let's make sure this gets - // a wrap-around next button. - add_next = TRUE; - } - // chop out what we can use in a menu. - list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); - if (add_next) { - // we were asked to add a menu item for the next screen. - trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; - } - - listening_id = llListen(menu_channel, "", listen_to, ""); - list commands; - integer i; - // take only the prefix of the string, to avoid getting a length complaint. - for (i = 0; i < llGetListLength(trunc_buttons); i++) { - string curr = llList2String(trunc_buttons, i); - integer last_pos = 23; // default maximum, highest possible is 24. - if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; - curr = llGetSubString(curr, 0, last_pos); - commands += curr; - } - llDialog(listen_to, title, commands, menu_channel); -} - -// shuts down any connection we might have had with any active menu. we will not -// send any responses after this point (although we might already have responded when -// the user clicked the menu). -clear_menu() -{ - llListenRemove(listening_id); -} - -// process the response when the user chooses a menu item. -process_menu_response(integer channel, string name, key id, string message) -{ - if (channel != menu_system_channel) return; // not for us. - - if (message == NEXT_MENU_TEXT) { - // this is the special choice, so we need to go to the next page. - _menu_base_start += 11; - if (_menu_base_start > llGetListLength(_private_global_buttons)) { - // we have wrapped around the list. go to the start again. - _menu_base_start = 0; - } - show_menu(global_menu_name, _private_global_title, - _private_global_buttons, menu_system_channel, - _private_global_av_key); - return; // handled by opening a new menu. - } - - string calculated_name; - integer indy; - // first try for an exact match. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (curr == message) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - if (calculated_name == "") { - // try an imprecise match if the exact matching didn't work. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (is_prefix(curr, message)) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - } - if (calculated_name == "yes") { - // only send a response if that menu choice made sense to us. - really_give_contents(); - clear_menu(); - } -} - -// end from menutini. -////////////// - -////////////// -// start of hufflets... - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -////////////// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//end hufflets... -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - remove_redundant_scripts(); - initialize_fredboxmux(); - label_opacity = 1; // start out showing the label. - set_text(); - } - - on_rez(integer start_parm) { state default; } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - // we show the label at least a bit when the contents change. - label_opacity = 1; - set_text(); - } - } - - touch_start(integer num) { - label_opacity = 1.0; - set_text(); - first_toucher = llDetectedKey(0); - // are we only supposed to give stuff to the owner? - if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { - first_toucher = NULL_KEY; - return; // bail out. - } - show_menu("askreally", "Would you like a copy of this object's contents?", - ["yes", "no"], -18264, first_toucher); - } - - listen(integer channel, string name, key id, string message) - { process_menu_response(channel, name, id, message); } - - timer() { - llSetTimerEvent(0); - if (DO_ROTATION) rotate_as_requested(); - if (USE_SENSORS) { - llSensor("", NULL_KEY, AGENT, ACTIVE_LABEL_DISTANCE, PI); - } else { - if (label_opacity != 0.0) { - label_opacity = 0.0; - set_text(); - } - } - llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); - } - - sensor(integer count) { - if (label_opacity != 1.0) { - label_opacity = 1.0; - set_text(); - } - } - - no_sensor() { - if (label_opacity != 0.0) { - label_opacity = 0.0; - set_text(); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.txt new file mode 100755 index 00000000..c41662c5 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/fredboxmux_v3.0.txt @@ -0,0 +1,669 @@ + +// huffware script: fredboxmux (with rotation), by fred huffhines. +// +// a memory saving kludge script; it is the combination of the canonical huffware +// scripts: (1) non-script giver, (2) rotanium rotato, (3) text label. +// our theory is that by having only two scripts per display object (this script and +// the updater client) instead of four, we'll save some cpu on our overburdened but +// beloved server (serene). +// given that this script is intended to replace those three scripts, it will eat them +// on startup to avoid having redundant services in the object. +// update for april 24 2011: added a question menu before doing the copying to user's +// inventory, since opensim can do a weird thing that sets all folders to "loading...". +// this now keeps the objects from being super annoying when one didn't mean to click it. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// non-script giver: +// +// gives all objects, notecards, etc contained in an object when that object is touched. +// does not give out scripts, since these are generally not something that should be handed +// to the customer. +// +// rotanium rotato: +// +// causes the object to rotate according to the parameters set below. +// this can use herky-jerky timed rotation with llSetRot or it can use +// smooth rotation with llTargetOmega. +// +// text label: +// +// a super simple script for giving an object readable text. + +integer DEBUGGING = FALSE; // set to true for noisier runs. + +integer DO_ROTATION = TRUE; // is this the rotating version or not? + +integer USE_SENSORS = TRUE; // should we look for avatars so we can display the label? + +float SMOOTH_TIMER_FREQUENCY = 7.0; + // fastest possible rate of change for the smooth rotater, in seconds. the smooth + // rotater doesn't need to hit the timer all that often, but this is faster than it + // needs to be for rotation, since it is also used as the rate at which the avatar sensor + // fires. + +float TIME_TO_CLEAR_TITLE = 8.0; + // how many seconds before the title that was set for an avatar or due to a touch will + // disappear again. + +vector LABEL_COLOR = <0.3, 0.9, 0.4>; + // color of the text above object. + +float ACTIVE_LABEL_DISTANCE = 5.0; + // how far away can avatars cause the label to light up? + +integer ONLY_GIVE_TO_OWNER = TRUE; + // if this is true, then only the owner will receive a copy of the items. + +integer GIVE_UNCOPYABLES = FALSE; + // this flag is dangerous when true, because it means that uncopyable objects will still + // be handed to the target. if that target refuses the non-copyable items, then the items + // will be lost forever. that is not so good if you've sold the person a non-copy item. + +string EXCLUDED_NOTECARD = "product description"; + // a special case; if there is a giftorse configuration card, we won't hand that out. + +float SMOOTH_CHANCE_FOR_ADJUSTING = 0.28; + // we won't always change the smooth rotation, even though our timer is pretty slow. + // this value is the percentage of the time that we do actually change rotation (divided + // by 100). + +float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; + // the gain is how fast we will rotate in radians per second. + // PI / 2 is about 90 degrees per second, which seems way too fast. + // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, + // and 0.0490873852122 is about PI / 64. + +string object_label = "default"; // change this if you want a specific name. + +string old_name; // tracks the last known name so we know if we need to update title. +float old_opacity = 3.14; // tracks the last opacity setting for the label. + +integer label_changed = TRUE; + // this remembers if the label has stayed put or not. we use it to decide + // whether we need to check the label for carriage returns. + +vector current_add_in = <0.0, 0.0, 0.4>; + // randomly assigned to if RANDOMIZE_ROTATION is true. + +float current_gain = -0.05; + // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. + +float MIN_ADDITION = 0.01; + // smallest amount of change we will ever have. +float MAX_ADDITION = 7.0; + // largest amount of change we will ever have. + +key first_toucher; // tracks who clicked on the object to get contents. + +float label_opacity = 1.0; // how opaque should text be? 1.0 is solid, 0.0 transparent. + +// takes out the 3 scripts that have been combined into the mux. otherwise, it's +// more of a pain to update all the boxes with this thing when it's ready to go. +remove_redundant_scripts() +{ + integer posn; + string self = llGetScriptName(); + // zoom across the scripts to see if we have any in the inventory that + // are slated for removal. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if (curr_script != self) { + if ( (llSubStringIndex(curr_script, "non-script giver") == 0) + || (llSubStringIndex(curr_script, "rotanium rotato") == 0) + || (llSubStringIndex(curr_script, "text label") == 0) ) { + // this one is a match! zap it. + llRemoveInventory(curr_script); + } + + } + } +} + +// the avatar has said it's okay to hand out all the stuff to her/him. +really_give_contents() { give_out_contents(first_toucher); } + +// give out pictures, notecards, objects, etc. that are hiding in the object. +give_out_contents(key give_to) +{ + list all_to_give = []; // the set we will hand over in a batch. + list uncopyables = []; // the list we have to do individually. + // find out how many items there are. + integer count = llGetInventoryNumber(INVENTORY_ALL); + // iterate across all the items and add them to the gift list if appropriate. + integer indy; + for (indy = 0; indy < count; indy++) { + string item_name = llGetInventoryName(INVENTORY_ALL, indy); + integer type = llGetInventoryType(item_name); + if ( (type != INVENTORY_SCRIPT) + && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { + // it's okay to add this item; it's not a script and we are not skipping the special notecard. + integer mask = MASK_OWNER; + if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; + integer perms = llGetInventoryPermMask(item_name, mask); + if (perms & PERM_COPY) { + // a normal object that we can hand out. + all_to_give += item_name; + } else { + uncopyables += item_name; + } + } + } + // hand the customer the whole set as one big chunk, named after the object. + llGiveInventoryList(give_to, llGetObjectName(), all_to_give); + + // handle any problematic items. we cannot copy these objects into a category folder, + // so we can either not try to copy them (a lot safer) or we can try to deliver them + // normally as individual items. the latter choice is more dangerous, because if the + // owner discards these items rather than keeping them, the items will be lost forever! + if (llGetListLength(uncopyables) > 0) { + string plural = " "; + string is_verb = "is "; + string third_noun_subj = "it "; + string third_noun_obj = "it "; + if (llGetListLength(uncopyables) > 1) { + plural = "s "; + is_verb = "are "; + third_noun_subj = "they "; + third_noun_obj = "them "; + } + + string uncopyable_message = "will be left inside the object. To get " + third_noun_obj + + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; + if (GIVE_UNCOPYABLES) { + uncopyable_message = "will be moved over to your inventory." + + "\nPlease look in your main folders for " + + third_noun_obj + "(e.g., in Objects or Textures)."; + } + + string failure_message = "The item" + plural + + "[" + llDumpList2String(uncopyables, "; ") + "]\n" + + is_verb + "not copyable; " + third_noun_subj + + uncopyable_message; + + if (llGetOwner() == give_to) { + // the object can be moved to inventory, but not with the category method. + llOwnerSay(failure_message); + } else { + // this seems like a weird case; it will probably just fail anyhow? + // if the item's not copyable and you're not the owner of this object, + // how can we give it to you? + llInstantMessage(give_to, failure_message); + } + + // now that we've announced this weird situation, handle it appropriately. + if (GIVE_UNCOPYABLES) { + for (indy = 0; indy < llGetListLength(uncopyables); indy++) { + string item_name = llList2String(uncopyables, indy); + llGiveInventory(give_to, item_name); + } + } // otherwise leave them be. + } +} + +// causes the object to rotate using whatever the current settings are. +smooth_rotate_using_our_settings() +{ + // make sure we are using the rotational values we were asked to. + llTargetOmega(current_add_in, current_gain, 1.0); +} + +// sets the gain and add in to random choices. +randomize_values() +{ + current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); + current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); +} + +// performs the timed rotation that has been configured for us. +rotate_as_requested() +{ + // our slack timer went off, so randomize the rotation if requested. + if (llFrand(1.0) >= (1.0 - SMOOTH_CHANCE_FOR_ADJUSTING) ) { + randomize_values(); + smooth_rotate_using_our_settings(); + } +} + +initialize_fredboxmux() +{ + // make sure we pick a good random channel. + menu_system_channel = -1 * (integer)randomize_within_range(200, 10000000, FALSE); + + // if needed, we will set our initial random rotation. + randomize_values(); + + // do a first rotate, so we move right at startup. otherwise we won't move + // until after our first timer hits. + if (DO_ROTATION) rotate_as_requested(); + + // now set the timer for our mode. + llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); + if (DO_ROTATION) smooth_rotate_using_our_settings(); +} + +set_text() +{ +//log_it("old name " + old_name + " -- curr name " + llGetObjectName()); + if (old_name != llGetObjectName()) { + // we're out of synch on the object name. + label_changed = TRUE; + } + if (old_opacity != label_opacity) { + // here we're out of synch on last opacity used. + label_changed = TRUE; + } + if (label_changed) { + // reset the object title to a decorated version of object name if it says "default". + string new_label = object_label; + if (new_label == "default") new_label = llGetObjectName(); + + integer indy; + integer keep_going = TRUE; + while (keep_going) { + indy = find_substring(new_label, "\\n"); + if (indy < 0) { + keep_going = FALSE; + } else { + new_label = llGetSubString(new_label, 0, indy - 1) + + "\n" + llGetSubString(new_label, indy + 2, -1); + } + } + old_name = llGetObjectName(); + old_opacity = label_opacity; + label_changed = FALSE; // we have dealt with it now. +//log_it("setting text: " + new_label); + llSetText(new_label, LABEL_COLOR, label_opacity); + } + if (label_opacity != 0) { + // if we set a lit-up title, clear it again pretty soon. + llSetTimerEvent(TIME_TO_CLEAR_TITLE); + } +} + +////////////// +// code borrowed from menutini to raise a menu asking if they actually meant to get all +// the contents. an opensim inventory bug makes all the folders look foolish if we +// do any inventory giving accidentally. +////////////// + +// global variables... + +list _private_global_buttons; // holds onto the active set of menu options. +string _private_global_av_key; // the key for the avatar who clicks the menu. +string _private_global_title; // holds onto current title text. + +integer _menu_base_start = 0; // position in the items of the current menu. + +integer listening_id = 0; + // the current id of our listening for the menu. it's an id returned by LSL + // that we need to track so we can cancel the listen. + +integer menu_system_channel = -123; + // messages come back to us from this channel when user clicks the dialog. + // this is set later and the default is meaningless. + +string global_menu_name = ""; + // hangs onto the current menu's name. + +//hmmm: note; to manage multiple concurrent menus on different channels, +// we must make these into lists. then the timeouts should apply +// individually to these instead of overall (if we even do timeouts; +// it's nicer if menus never stop being active). + +string NEXT_MENU_TEXT = "Next >>"; + // what the next item will say for showing next menu page. + +//integer TIMEOUT_FOR_MENU = 42; + // timeout for the menu in seconds. + +// displays the menu requested. it's "menu_name" is an internal name that is +// not displayed to the user. the "title" is the content shown in the main area +// of the menu. "commands_in" is the list of menu items to show as buttons. +// the "menu_channel" is where the user's clicked response will be sent. the +// "listen_to" key is the avatar expected to click the menu, which is needed to +// listen to his response. +show_menu(string menu_name, string title, list buttons, + integer menu_channel, key listen_to) +{ + // save our new parms. + global_menu_name = menu_name; + _private_global_title = title; + _private_global_buttons = buttons; + menu_system_channel = menu_channel; + _private_global_av_key = listen_to; + if (DEBUGGING) { + log_it("menu name: " + global_menu_name); + log_it("title: " + _private_global_title); + log_it("buttons: " + (string)buttons); + log_it("channel: " + (string)menu_system_channel); + log_it("listen key: " + (string)listen_to); + } + + integer add_next = FALSE; // true if we should add a next menu item. + + // the math here incorporates current button position. + integer current = _menu_base_start; + integer max_buttons = llGetListLength(buttons) - current; + + if (max_buttons > 12) { + // limitation of SL: menus have a max of 12 buttons. + max_buttons = 12; + add_next = TRUE; + } else if (llGetListLength(buttons) > 12) { + // we already have been adding next. let's make sure this gets + // a wrap-around next button. + add_next = TRUE; + } + // chop out what we can use in a menu. + list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); + if (add_next) { + // we were asked to add a menu item for the next screen. + trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; + } + + listening_id = llListen(menu_channel, "", listen_to, ""); + list commands; + integer i; + // take only the prefix of the string, to avoid getting a length complaint. + for (i = 0; i < llGetListLength(trunc_buttons); i++) { + string curr = llList2String(trunc_buttons, i); + integer last_pos = 23; // default maximum, highest possible is 24. + if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; + curr = llGetSubString(curr, 0, last_pos); + commands += curr; + } + llDialog(listen_to, title, commands, menu_channel); +} + +// shuts down any connection we might have had with any active menu. we will not +// send any responses after this point (although we might already have responded when +// the user clicked the menu). +clear_menu() +{ + llListenRemove(listening_id); +} + +// process the response when the user chooses a menu item. +process_menu_response(integer channel, string name, key id, string message) +{ + if (channel != menu_system_channel) return; // not for us. + + if (message == NEXT_MENU_TEXT) { + // this is the special choice, so we need to go to the next page. + _menu_base_start += 11; + if (_menu_base_start > llGetListLength(_private_global_buttons)) { + // we have wrapped around the list. go to the start again. + _menu_base_start = 0; + } + show_menu(global_menu_name, _private_global_title, + _private_global_buttons, menu_system_channel, + _private_global_av_key); + return; // handled by opening a new menu. + } + + string calculated_name; + integer indy; + // first try for an exact match. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (curr == message) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + if (calculated_name == "") { + // try an imprecise match if the exact matching didn't work. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (is_prefix(curr, message)) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + } + if (calculated_name == "yes") { + // only send a response if that menu choice made sense to us. + really_give_contents(); + clear_menu(); + } +} + +// end from menutini. +////////////// + +////////////// +// start of hufflets... + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +////////////// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//end hufflets... +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + remove_redundant_scripts(); + initialize_fredboxmux(); + label_opacity = 1; // start out showing the label. + set_text(); + } + + on_rez(integer start_parm) { state default; } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + // we show the label at least a bit when the contents change. + label_opacity = 1; + set_text(); + } + } + + touch_start(integer num) { + label_opacity = 1.0; + set_text(); + first_toucher = llDetectedKey(0); + // are we only supposed to give stuff to the owner? + if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { + first_toucher = NULL_KEY; + return; // bail out. + } + show_menu("askreally", "Would you like a copy of this object's contents?", + ["yes", "no"], -18264, first_toucher); + } + + listen(integer channel, string name, key id, string message) + { process_menu_response(channel, name, id, message); } + + timer() { + llSetTimerEvent(0); + if (DO_ROTATION) rotate_as_requested(); + if (USE_SENSORS) { + llSensor("", NULL_KEY, AGENT, ACTIVE_LABEL_DISTANCE, PI); + } else { + if (label_opacity != 0.0) { + label_opacity = 0.0; + set_text(); + } + } + llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); + } + + sensor(integer count) { + if (label_opacity != 1.0) { + label_opacity = 1.0; + set_text(); + } + } + + no_sensor() { + if (label_opacity != 0.0) { + label_opacity = 0.0; + set_text(); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.lsl deleted file mode 100755 index 047c7121..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.lsl +++ /dev/null @@ -1,451 +0,0 @@ - -// huffware script: giftorse, by fred huffhines -// -// this script advertises a product in a store. -// how to configure this script: the object name is known automatically, but the seller -// and store names are not. also the cost is not currently automatic, since there seems -// to be no way to figure it out. all of the variable data can be stored in a notecard -// in the following format: -// -// #giftorse -// cost = N -// creator = X -// shop = S -// label = L -// -// where N is a numerical cost for the item in linden dollars, X is the name of the creator -// of the object, S is the name of the shop where the object is being sold, and L is a label -// to show above the object. -// -// this script supports a sales paradigm, where normally it just shows the -// appropriate title, but once the customer has bought it, it will permanently set -// it's last title and exit, but not before telling the user how to get the contents. -// this script depends on the "non-script giver" script also being in the same object. -// that's what let's it promise that the stuff will be given out on touch. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - - -// every product has a different cost. -string DEFAULT_COST = "**UNSET**"; -string OBJ_COST; - -// these are hard-coded for my own shop, since it's more convenient for me. -// remember to change these to your name and store name. -string SCRIPT_CREATOR = "Fred Huffhines"; // uber-default, do not change. -string CREATOR = "Fred Huffhines"; // change this if you are not me. -string SHOP_NAME = "eepaw shop (Eclectic Electric Patterns and Widgets)"; - -// if this is anything other than "default", then the text is used as the label. -// if left as "default", then the object's own name is used as the label. -string OBJECT_LABEL = "default"; - -// the color of the text above the object. -vector TEXT_COLOR = <0.6, 0.7, 0.8>; - -// how long should the text stay on the object after a potential customer clicks it? -float DELAY_BEFORE_CLEARING_TEXT = 10.0; - // a fairly liberal allowance for how long it might take to read the object. - // we are trying to balance information flow with how obnoxious people feel text labels are. - -////////////// - -// constants that should really stay constant, like they are now... - -string GIFTORSE_SIGNATURE = "#giftorse"; // the expected first line of our notecards. - -////////////// - -// global variables... - -string global_notecard_name; // name of our notecard in the object's inventory. - -integer response_code; // set to uniquely identify the notecard read in progress. - -// programmer friendly variables... - -integer DEBUGGING = FALSE; - // if true, then the code will be noisy during its processing. - -// requires noteworthy library v3.3 or higher. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -////////////// -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the only parameter. the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // an embedded list that was read from the notecard. this necessarily limits the - // size of the notecards that we can read and return. -// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -///////////// - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - // clean initial spaces. - while (llGetSubString(to_check, 0, 0) == " ") - to_check = llDeleteSubString(to_check, 0, 0); - if (!is_prefix(to_check, variable_name)) return ""; - to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); - // clean any spaces or valid assignment characters. - while ( (llGetSubString(to_check, 0, 0) == " ") - || (llGetSubString(to_check, 0, 0) == "=") - || (llGetSubString(to_check, 0, 0) == ",") ) - to_check = llDeleteSubString(to_check, 0, 0); - if (DEBUGGING) - log_it("set " + variable_name + " = " + to_check); - string chewed_content = to_check; - integer indy; - for (indy = 0; indy < llStringLength(chewed_content); indy++) { - if (llGetSubString(chewed_content, indy, indy) == "\\") { - if (llGetSubString(chewed_content, indy+1, indy+1) == "n") { - chewed_content = llGetSubString(chewed_content, 0, indy - 1) - + "\n" - + llGetSubString(chewed_content, indy + 2, - llStringLength(chewed_content) - 1); - } - } - } - // return what's left of the string. - return chewed_content; -} - -///////////// - -// is the merchant/shop guy still the owner? -integer merchant_owns() -{ - string owner_now = llToLower(llKey2Name(llGetOwner())); - if ( (owner_now != "") && (owner_now != llToLower(CREATOR)) - && (owner_now != llToLower(SCRIPT_CREATOR) ) ) { - // we're not able to compare the owner to what we expect. - return FALSE; - } - return TRUE; -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// applies a text label above the object. -set_text(integer enabled) -{ - if (enabled) { - string object_label = OBJECT_LABEL; - // reset the label to a decorated version of object name if it was default. - if (object_label == "default") { - list name_bits = compute_basename_and_version(llGetObjectName()); - string name = llList2String(name_bits, 0); - if (name == "") name = llGetObjectName(); // didn't split, use the full name. - object_label = "[ " + name + " ]"; - } -//hmmm: retired, since it's an untruth to people nearby who don't own it. -// if (!merchant_owns()) object_label += "\n-\nClick on this object to get its contents."; - llSetText(object_label, TEXT_COLOR, 1.0); - } else { - // no label, no how. - llSetText("", TEXT_COLOR, 0.0); - } -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - if ( (content = get_variable_value(to_parse, "cost")) != "") - OBJ_COST = content; - else if ( (content = get_variable_value(to_parse, "creator")) != "") - CREATOR = content; - else if ( (content = get_variable_value(to_parse, "shop")) != "") - SHOP_NAME = content; - else if ( (content = get_variable_value(to_parse, "label")) != "") - OBJECT_LABEL = content; - else if ( (content = get_variable_value(to_parse, "text_color")) != "") - TEXT_COLOR = (vector)content; -} - -// handles a set of information from the notecard about this product. -process_product_definition(list lines) -{ - integer indy; - for (indy = 0; indy < llGetListLength(lines); indy++) { - string line = llList2String(lines, indy); - // try to interpret that as a variable setting. - parse_variable_definition(line); - } -} - -// display information about the product in open chat. -show_product_info() -{ - string product_name = llGetObjectName(); - string cost_string = "L$" + OBJ_COST + "."; - if (OBJ_COST == "0") cost_string = "free!"; - llSay(0, " is available for " + cost_string + "\n" - + "[Created by " + CREATOR + ", Sold by " + SHOP_NAME + "]"); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - set_text(FALSE); // no label to start out. - global_notecard_name = ""; - response_code = 0; - OBJ_COST = DEFAULT_COST; // reset in opensim friendly way. - - // see if we can load a notecard for product info. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([GIFTORSE_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); - llSetTimerEvent(32); // make sure that if we don't get a config, we try again. - } - - // processes link messages received from support libraries. - link_message(integer which, integer num, string msg, key id) { - if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. - if (msg == READ_NOTECARD_COMMAND) { - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) { - // oops, this isn't for us. stop looking at it. - return; - } - - integer done_reading = TRUE; - if (notecard_name == NOTECARD_READ_CONTINUATION) done_reading = FALSE; - if (notecard_name != BAD_NOTECARD_INDICATOR) { - global_notecard_name = notecard_name; - list lines = llDeleteSubList(parms, 0, 1); - process_product_definition(lines); - } else { - // we hated the notecards we found, or there were none. -// log_it("There is no product definition found. We will proceed with defaults."); -// state describe_product_and_neigh; - } - if (done_reading) { - // since we got our final response for config, stop the timer. - llSetTimerEvent(0); - state describe_product_and_neigh; - } - } - } - - on_rez(integer parm) { llResetScript(); } - - timer() { - log_it("failed to read configuration; retrying."); - llResetScript(); - } - -} - -// this is the active state, once we have read our product configuration from -// a notecard. -state describe_product_and_neigh -{ - state_entry() { - set_text(FALSE); // clear our text label just in case. - if (OBJ_COST == DEFAULT_COST) { - log_it("resetting due to missing configuration."); - llResetScript(); - } - show_product_info(); - if (!merchant_owns()) { -//hmmm: potentially might want to allow for multiple merchants so your partners don't go nuts hearing this. - // rip this script out, since it's not intended for other folks. - llSay(0, "\n\nThanks for your purchase from " + SHOP_NAME - + "!\nTo get your product's contents, just click this package."); - } - } - - on_rez(integer parm) { llResetScript(); } - - touch_start(integer total_number) { - set_text(TRUE); // let them see our name. - show_product_info(); - llSetTimerEvent(DELAY_BEFORE_CLEARING_TEXT); - } - - timer() { - // the only reason we should be here is if we are trying to clear up our text. - set_text(FALSE); - llSetTimerEvent(0); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(3.14159265358); - // snooze to ensure that we don't reset before a new version gets a - // chance to remove this. - llResetScript(); // start over. - } - } -} - -//eternal questions... - -//hmmm: why can't we automatically get the object's sale price? diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.txt new file mode 100755 index 00000000..047c7121 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/giftorse_v7.6.txt @@ -0,0 +1,451 @@ + +// huffware script: giftorse, by fred huffhines +// +// this script advertises a product in a store. +// how to configure this script: the object name is known automatically, but the seller +// and store names are not. also the cost is not currently automatic, since there seems +// to be no way to figure it out. all of the variable data can be stored in a notecard +// in the following format: +// +// #giftorse +// cost = N +// creator = X +// shop = S +// label = L +// +// where N is a numerical cost for the item in linden dollars, X is the name of the creator +// of the object, S is the name of the shop where the object is being sold, and L is a label +// to show above the object. +// +// this script supports a sales paradigm, where normally it just shows the +// appropriate title, but once the customer has bought it, it will permanently set +// it's last title and exit, but not before telling the user how to get the contents. +// this script depends on the "non-script giver" script also being in the same object. +// that's what let's it promise that the stuff will be given out on touch. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + + +// every product has a different cost. +string DEFAULT_COST = "**UNSET**"; +string OBJ_COST; + +// these are hard-coded for my own shop, since it's more convenient for me. +// remember to change these to your name and store name. +string SCRIPT_CREATOR = "Fred Huffhines"; // uber-default, do not change. +string CREATOR = "Fred Huffhines"; // change this if you are not me. +string SHOP_NAME = "eepaw shop (Eclectic Electric Patterns and Widgets)"; + +// if this is anything other than "default", then the text is used as the label. +// if left as "default", then the object's own name is used as the label. +string OBJECT_LABEL = "default"; + +// the color of the text above the object. +vector TEXT_COLOR = <0.6, 0.7, 0.8>; + +// how long should the text stay on the object after a potential customer clicks it? +float DELAY_BEFORE_CLEARING_TEXT = 10.0; + // a fairly liberal allowance for how long it might take to read the object. + // we are trying to balance information flow with how obnoxious people feel text labels are. + +////////////// + +// constants that should really stay constant, like they are now... + +string GIFTORSE_SIGNATURE = "#giftorse"; // the expected first line of our notecards. + +////////////// + +// global variables... + +string global_notecard_name; // name of our notecard in the object's inventory. + +integer response_code; // set to uniquely identify the notecard read in progress. + +// programmer friendly variables... + +integer DEBUGGING = FALSE; + // if true, then the code will be noisy during its processing. + +// requires noteworthy library v3.3 or higher. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +////////////// +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the only parameter. the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // an embedded list that was read from the notecard. this necessarily limits the + // size of the notecards that we can read and return. +// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +///////////// + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + // clean initial spaces. + while (llGetSubString(to_check, 0, 0) == " ") + to_check = llDeleteSubString(to_check, 0, 0); + if (!is_prefix(to_check, variable_name)) return ""; + to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); + // clean any spaces or valid assignment characters. + while ( (llGetSubString(to_check, 0, 0) == " ") + || (llGetSubString(to_check, 0, 0) == "=") + || (llGetSubString(to_check, 0, 0) == ",") ) + to_check = llDeleteSubString(to_check, 0, 0); + if (DEBUGGING) + log_it("set " + variable_name + " = " + to_check); + string chewed_content = to_check; + integer indy; + for (indy = 0; indy < llStringLength(chewed_content); indy++) { + if (llGetSubString(chewed_content, indy, indy) == "\\") { + if (llGetSubString(chewed_content, indy+1, indy+1) == "n") { + chewed_content = llGetSubString(chewed_content, 0, indy - 1) + + "\n" + + llGetSubString(chewed_content, indy + 2, + llStringLength(chewed_content) - 1); + } + } + } + // return what's left of the string. + return chewed_content; +} + +///////////// + +// is the merchant/shop guy still the owner? +integer merchant_owns() +{ + string owner_now = llToLower(llKey2Name(llGetOwner())); + if ( (owner_now != "") && (owner_now != llToLower(CREATOR)) + && (owner_now != llToLower(SCRIPT_CREATOR) ) ) { + // we're not able to compare the owner to what we expect. + return FALSE; + } + return TRUE; +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// applies a text label above the object. +set_text(integer enabled) +{ + if (enabled) { + string object_label = OBJECT_LABEL; + // reset the label to a decorated version of object name if it was default. + if (object_label == "default") { + list name_bits = compute_basename_and_version(llGetObjectName()); + string name = llList2String(name_bits, 0); + if (name == "") name = llGetObjectName(); // didn't split, use the full name. + object_label = "[ " + name + " ]"; + } +//hmmm: retired, since it's an untruth to people nearby who don't own it. +// if (!merchant_owns()) object_label += "\n-\nClick on this object to get its contents."; + llSetText(object_label, TEXT_COLOR, 1.0); + } else { + // no label, no how. + llSetText("", TEXT_COLOR, 0.0); + } +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + if ( (content = get_variable_value(to_parse, "cost")) != "") + OBJ_COST = content; + else if ( (content = get_variable_value(to_parse, "creator")) != "") + CREATOR = content; + else if ( (content = get_variable_value(to_parse, "shop")) != "") + SHOP_NAME = content; + else if ( (content = get_variable_value(to_parse, "label")) != "") + OBJECT_LABEL = content; + else if ( (content = get_variable_value(to_parse, "text_color")) != "") + TEXT_COLOR = (vector)content; +} + +// handles a set of information from the notecard about this product. +process_product_definition(list lines) +{ + integer indy; + for (indy = 0; indy < llGetListLength(lines); indy++) { + string line = llList2String(lines, indy); + // try to interpret that as a variable setting. + parse_variable_definition(line); + } +} + +// display information about the product in open chat. +show_product_info() +{ + string product_name = llGetObjectName(); + string cost_string = "L$" + OBJ_COST + "."; + if (OBJ_COST == "0") cost_string = "free!"; + llSay(0, " is available for " + cost_string + "\n" + + "[Created by " + CREATOR + ", Sold by " + SHOP_NAME + "]"); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + set_text(FALSE); // no label to start out. + global_notecard_name = ""; + response_code = 0; + OBJ_COST = DEFAULT_COST; // reset in opensim friendly way. + + // see if we can load a notecard for product info. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([GIFTORSE_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); + llSetTimerEvent(32); // make sure that if we don't get a config, we try again. + } + + // processes link messages received from support libraries. + link_message(integer which, integer num, string msg, key id) { + if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. + if (msg == READ_NOTECARD_COMMAND) { + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) { + // oops, this isn't for us. stop looking at it. + return; + } + + integer done_reading = TRUE; + if (notecard_name == NOTECARD_READ_CONTINUATION) done_reading = FALSE; + if (notecard_name != BAD_NOTECARD_INDICATOR) { + global_notecard_name = notecard_name; + list lines = llDeleteSubList(parms, 0, 1); + process_product_definition(lines); + } else { + // we hated the notecards we found, or there were none. +// log_it("There is no product definition found. We will proceed with defaults."); +// state describe_product_and_neigh; + } + if (done_reading) { + // since we got our final response for config, stop the timer. + llSetTimerEvent(0); + state describe_product_and_neigh; + } + } + } + + on_rez(integer parm) { llResetScript(); } + + timer() { + log_it("failed to read configuration; retrying."); + llResetScript(); + } + +} + +// this is the active state, once we have read our product configuration from +// a notecard. +state describe_product_and_neigh +{ + state_entry() { + set_text(FALSE); // clear our text label just in case. + if (OBJ_COST == DEFAULT_COST) { + log_it("resetting due to missing configuration."); + llResetScript(); + } + show_product_info(); + if (!merchant_owns()) { +//hmmm: potentially might want to allow for multiple merchants so your partners don't go nuts hearing this. + // rip this script out, since it's not intended for other folks. + llSay(0, "\n\nThanks for your purchase from " + SHOP_NAME + + "!\nTo get your product's contents, just click this package."); + } + } + + on_rez(integer parm) { llResetScript(); } + + touch_start(integer total_number) { + set_text(TRUE); // let them see our name. + show_product_info(); + llSetTimerEvent(DELAY_BEFORE_CLEARING_TEXT); + } + + timer() { + // the only reason we should be here is if we are trying to clear up our text. + set_text(FALSE); + llSetTimerEvent(0); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(3.14159265358); + // snooze to ensure that we don't reset before a new version gets a + // chance to remove this. + llResetScript(); // start over. + } + } +} + +//eternal questions... + +//hmmm: why can't we automatically get the object's sale price? diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.lsl deleted file mode 100755 index 1397e17c..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.lsl +++ /dev/null @@ -1,963 +0,0 @@ - -// huffware script: huff-pet, by fred huffhines -// -// this is yet another implementation of a pet script in LSL. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -//to-do zone: - -//hmmm: for attack mode, adjust timers and ranges. -// probably just define the default set and mirror that with the attack set. -// switch between them during mode change. -// reset timer and sensor for mode change! - -// end to-do zone. - -// constants for the pet that one might want to change. - -integer PET_CHAT_CHANNEL = 28; - // the channel on which the pet will listen for commands from the owner. - -//integer DEFAULT_PANIC_DISTANCE = 28; -integer DEFAULT_PANIC_DISTANCE = 5;//short leash version for opensim. - // multiplied by the sensor range to get the distance allowed from the - // pet to the person it's following before a teleport is invoked. -integer ATTACK_PANIC_DISTANCE = 13; - // multiplied by the sensor range to get the distance allowed from the - // enraged pet to the attack target before a teleport is invoked. - -float DEFAULT_HEIGHT_ABOVE_FOLLOWED_OBJECT = 1.6; - // the height that the pet will float at above whoever it's following. -float ATTACK_HEIGHT_ABOVE_FOLLOWED_OBJECT = 0.0; - // the height that the pet will float at above the attack target. - -float DEFAULT_BASE_VELOCITY = 0.1; - // the velocity of the pet when just cavorting around. -float ATTACK_BASE_VELOCITY = 0.6; - // the velocity of the pet when in "angry" mode. - -integer DEFAULT_BUMP_SIZE = 48; - // the default size in meters of the displacement caused by up, down, etc commands. - -// the margin values below are the range of motion that the pet is allowed -// on each axis. -float DEFAULT_X_MARGIN = 3.0; -float DEFAULT_Y_MARGIN = 3.0; -float DEFAULT_Z_MARGIN = 1.0; -// the margin for when the pet is attacking. -float ATTACK_X_MARGIN = 0.1; -float ATTACK_Y_MARGIN = 0.1; -float ATTACK_Z_MARGIN = 0.2; - -float MAXIMUM_TARGETING_DISTANCE = 2.0; - // the amount of basic deviation allowed for the pet from its target spot. - // this is how far it's allowed to roam from the target. -//is that right? - -float ATTACK_PUSH_DIST_THRESHOLD = 2.0; - // how close the pet should be to an attack target before trying to push. -float ATTACK_PUSH_MAGNITUDE = 2147483646.0; //maxint - 1, dealing with svc-2723. - // how much the critter should push an attack target. -float ATTACK_PUSH_CHANCE = 0.1; - // how often (probability from 0.0 to 1.0) an attack target gets pushed. - -// other constants that are more advanced and should generally not change... - -float TARGETING_SENSOR_RANGE = 96.0; - // the maximum distance the pet will try to see the target at. - -float SENSOR_INTERVAL = 0.4; - // how often the sensor scan will fire off. this is the fastest we will - // check for our follow target, in seconds. - -float PERIODIC_INTERVAL = 0.42; - // how frequently our timer event fires. - -integer MAXIMUM_SLACKNESS = 28; - // how many timer hits we'll allow before reverting to the default state. - -float VELOCITY_MULTIPLIER = 1.2; - // the total velocity comes from the base plus an equation that multiplies - // this value by some function of the distance. - -string PET_MENU_NAME = "#woof"; // name for our menu. -string PET_REPLY_MENU = "#aroo"; // replies with data. - -// symbolic labels for the different states of pet 'being'. -integer STATE_STAY = 0; -integer STATE_FREE = 1; // go home. -integer STATE_FOLLOW = 2; -integer STATE_COME = 3; -integer STATE_WANDER = 4; -integer STATE_ATTACK = 9; - -list SUPPORTED_COMMANDS = [ "go home", "come", "stay", - "wander", "follow", "attack", - "set home", "set name", "status" ]; - // attack = follow an avatar in a menacing way. - // come = follow owner. - // follow = follow an avatar. - // go home = return home, then move about freely. - // set home = set the home position based on owner location. - // set name = change the object's name. - // stay = sit right there. - // wander = roam a greater distance while following owner. - -// requires: jaunting library v3.4 or higher. -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -string REVERSE_VELOCITY_COMMAND = "#reverse#"; - // makes the object reverse its velocity and travel back from whence it came. -string SET_VELOCITY_COMMAND = "#setvelocity#"; - // makes the velocity equal to the vector passed as the first parameter. -string JAUNT_UP_COMMAND = "#jauntup#"; -string JAUNT_DOWN_COMMAND = "#jauntdown#"; - // commands for height adjustment. pass a float for number of meters to move. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a list of vectors as the first parameter; this list - // should be in the jaunter notecard format (separated by pipe characters). - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// - -//requires menutini library v4.2 or better. -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -// commands available via the menu system: -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. - // the reply will include: the menu name, the choice made and the key for - // the avatar. -// -////////////// - - -request_full_stop() -{ - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); -} - -request_jaunt_up(integer distance) -{ - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_UP_COMMAND, (string)distance); -} - -// global variables... - -key _OWNER; -integer current_state; -vector home_position; // the location where the pet lives. - -integer pending_target = FALSE; // is a target still being sought. - -integer _COMMAND_CHANNEL; -string _COMMAND_MESSAGE = "How may I assist you?"; - -integer _TARGET_ID; -vector TARGET_POSITION; - -float _FREE_RANGE = 10.0; - -string SIT_TEXT = "Meditate"; - -string SIT_ANIMATION = "yoga_float"; - -vector SIT_POSITION = <0.2, 0.2, 0.4>; - -vector SIT_ROTATION = <0.0, 0.0, 0.0>; - -key SITTING_AVATAR_KEY = NULL_KEY; - -// options for follow menu that pops up when pet is told to follow someone. -list _FOLLOW_KEY; -list _FOLLOW_NAME; // filled in with nearby avatars. -integer _FOLLOW_CHANNEL; -string _FOLLOW_MESSAGE = "Who should I follow?"; - -integer seeking_avatars = FALSE; -key KEY_OF_TARGET; - -////////////// - -// from hufflets... - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -/////////////// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay((string)debug_num + "- " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -/////////////// - -// info... - -// returns a string version of the state 's'. -string name_for_state(integer s) { - if (s == STATE_STAY) return "stay"; - if (s == STATE_FREE) return "go home"; - if (s == STATE_FOLLOW) return "follow"; - if (s == STATE_COME) return "come"; - if (s == STATE_WANDER) return "wander"; - if (s == STATE_ATTACK) return "attack"; - return "unknown"; -} - -// menu methods... - -list current_buttons; // holds onto the set of menu options. - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -string stringize_list(list to_flatten) { - return llDumpList2String(to_flatten, HUFFWARE_ITEM_SEPARATOR); -} - -// pops up a menu to interact with the pet's owner. -show_menu(string menu_name, string title, list buttons, integer channel) -{ - current_buttons = buttons; - key listen_to = _OWNER; - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR + stringize_list(current_buttons) - + HUFFWARE_PARM_SEPARATOR + (string)channel - + HUFFWARE_PARM_SEPARATOR + (string)listen_to); -} - -// causes a state change to make the pet stay. -enter_stay_state() -{ - current_state = STATE_STAY; - llSensorRemove(); - stop_pet(); -} - -// handle the response message when the user chooses a button. -react_to_menu(integer sender, integer num, string msg, key id) -{ -log_it("react menu: " + msg + " parm=" + (string)id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string choice = llList2String(parms, 1); - - if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) || (msg != SHOW_MENU_COMMAND) ) { -log_it("why here in react to menu, not for us?"); - return; - } - - if (menu_name == PET_MENU_NAME) { -log_it("react: snd=" + (string)sender + " num=" + (string)num + " msg=" + msg + " key=" + (string)id); - if (find_in_list(SUPPORTED_COMMANDS, choice) < 0) { - llOwnerSay("i don't know what you mean..."); - return; - } -llOwnerSay("i heard you tell me: menu=" + menu_name + " choice=" + choice); - - // handle commands that are major changes in state... - - if (choice == "come") { - llOwnerSay("coming to find you now..."); - current_state = STATE_COME; - llSetPrimitiveParams([PRIM_PHYSICS, TRUE, - //]); - PRIM_PHANTOM, TRUE]); - llSensorRemove(); - llSensorRepeat("", _OWNER, AGENT, TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); - } - - if (choice == "stay") { - llOwnerSay("i will stay right here..."); - enter_stay_state(); - } - - if (choice == "wander") { - current_state = STATE_WANDER; - llOwnerSay("i'm going to wander around and kind of vaguely follow you..."); - llSetPrimitiveParams([PRIM_PHYSICS, TRUE, - //]); - PRIM_PHANTOM, TRUE]); - llSensorRemove(); - llSensorRepeat("", _OWNER, AGENT, TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); - } - - if ( (choice == "follow") || (choice == "attack") ) { - seeking_avatars = TRUE; - stop_pet(); - llSensorRemove(); - if (choice == "attack") { - // we only attack avatars. - //or not. since that's boring. watching a pet attack a physical object is fun. - llSensor("", NULL_KEY, AGENT | ACTIVE, TARGETING_SENSOR_RANGE, PI); - current_state = STATE_ATTACK; - } else { - // look for both objects and avatars to follow. - llSensor("", NULL_KEY, AGENT | ACTIVE, TARGETING_SENSOR_RANGE, PI); - current_state = STATE_FOLLOW; - } - } - - if (choice == "go home") { - current_state = STATE_FREE; // free to roam about the cabin, or wherever home is. - llOwnerSay("i'm going home now."); - jaunt_to_location(home_position); - } - - // commands that don't lead to state changes... - - if (choice == "status") { - string seek_addition; - if (KEY_OF_TARGET != "") - seek_addition = "was last seeking " + llKey2Name(KEY_OF_TARGET); - llOwnerSay("my name is " + llGetObjectName() + " and state is '" - + name_for_state(current_state) + "'.\n" - + seek_addition); - } - - if (choice == "set home") { - list pos_list = llGetObjectDetails(llGetOwner(), [OBJECT_POS]); - home_position = llList2Vector(pos_list, 0); - llOwnerSay("i'm setting my home to " + (string)home_position); - //hmmm: use a rounding print to show the position. - } - if (choice == "set name") { - llOwnerSay("to change my name from " + llGetObjectName() + ",\ntell me my new name by typing:\n/" + (string)PET_CHAT_CHANNEL + " name My Cool New Name"); - } - - } else if (menu_name == PET_REPLY_MENU) { -log_it("menu-act follow: snd=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); - llSetPrimitiveParams([PRIM_PHYSICS, TRUE, - //]); - PRIM_PHANTOM, !(current_state == STATE_ATTACK)]); - integer choice_indy = find_in_list(_FOLLOW_NAME, choice); - if (choice_indy < 0) { -//log_it("choice was not found in list"); -//log_it("followname list is: " + (string)_FOLLOW_NAME); - } else { - string action = "follow"; - if (current_state == STATE_ATTACK) action = "attack"; - llOwnerSay("now " + action + "ing " - + llList2String(_FOLLOW_NAME, choice_indy) + "..."); - seeking_avatars = FALSE; - KEY_OF_TARGET = llList2Key(_FOLLOW_KEY, choice_indy); - llSensorRemove(); - llSensorRepeat("", KEY_OF_TARGET, AGENT | ACTIVE, - TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); - } - } -} - -// processes the hits that we get back from the sensor. the information we receive -// is needed for most of the pet states. -handle_sensor(integer num_detected) -{ - if (current_state == STATE_COME) { - go_to_target(_OWNER, llDetectedPos(0)); - motivate(); - } - - if ( (current_state == STATE_FOLLOW) || (current_state == STATE_ATTACK) ) { - if (seeking_avatars) { - // reset the list of keys and names that were found previously. - _FOLLOW_KEY = []; - _FOLLOW_NAME = []; - // show the full set found if it will fit, otherwise just 12. - integer num_to_show = num_detected; - if (num_to_show > 12) num_to_show = 12; - // examine each of the avatars found and put them on the list. - integer i; - for (i = 0 ; i < num_to_show; i++) { - key to_follow = llDetectedKey(i); - if (to_follow != NULL_KEY) { - _FOLLOW_KEY += [to_follow]; - string str = llDetectedName(i); - // trim the menu item if it has hit the maximum limit. - if (llStringLength(str) > 24) str = llGetSubString(str, 0, 23); - integer name_try = 0; - while (find_in_list(_FOLLOW_NAME, str) >= 0) { - // this guy is already listed under that name, so change it a bit. - str = llGetSubString(str, 0, 22) + (string)name_try++; - } - _FOLLOW_NAME += [str]; - } - } - // now ask who to follow. - if (llGetListLength(_FOLLOW_KEY)) { - show_menu(PET_REPLY_MENU, _FOLLOW_MESSAGE, _FOLLOW_NAME, _FOLLOW_CHANNEL); - } - } else { - // not seeking the avatar any more; follow who was chosen. - go_to_target(KEY_OF_TARGET, llDetectedPos(0)); - motivate(); - } - } - - if (current_state == STATE_WANDER) { - if (jaunt_responses_awaited) return; // skip doing anything while we're still waiting. - vector pos = llDetectedPos(0); - float omg = llFrand(1) * PI * 2; - float t_r = llFrand(1) * _FREE_RANGE; - float t_x = t_r * llCos(omg); - float t_y = t_r * llSin(omg); - go_to_target(NULL_KEY, pos + ); - motivate(); - } - -} - -handle_timer() { - if (current_state != STATE_STAY) { - // make sure a bad jaunt didn't break our physics. - llSetStatus(STATUS_PHYSICS, TRUE); - } - - if (jaunt_responses_awaited) { - // we are not quite there yet. - if (slackness_counter++ > MAXIMUM_SLACKNESS) { - // go back to the main state. we took too long. -log_it("waiting for jaunt timed out."); -///argh? jaunt_responses_awaited--; - slackness_counter = 0; - } else return; // not time yet for rest of timed actions. - } - - // handle the free state, since we need may to readjust the target. - if (current_state == STATE_FREE) { - if (pending_target) return; // haven't arrived at previous yet. - vector pos = home_position; - float omg = llFrand(1) * PI * 2; -//hmmm: make free range settable - float t_r = llFrand(1) * _FREE_RANGE; - float t_x = t_r * llCos(omg); - float t_y = t_r * llSin(omg); - go_to_target(NULL_KEY, pos + ); - motivate(); - } -} - -handle_hearing_voices(integer channel, string name, key id, string message) -{ - if (channel != PET_CHAT_CHANNEL) return; // not our channel. -//log_it("into handle voice, msg=" + message); - if (id != llGetOwner()) return; // not authorized. - // we found a command. which specific one? - if (is_prefix(message, "up")) { - // upwards bump. - enter_stay_state(); - string dist = llDeleteSubString(message, 0, 2); - if (dist == "") dist = (string)DEFAULT_BUMP_SIZE; - request_jaunt_up((integer)dist); -llOwnerSay("bumping up by " + dist); - } else if (is_prefix(message, "down")) { - // downwards bump. - enter_stay_state(); - string dist = llDeleteSubString(message, 0, 4); - if (dist == "") dist = (string)DEFAULT_BUMP_SIZE; - request_jaunt_up(-(integer)dist); -llOwnerSay("bumping down by " + dist); - } else if (is_prefix(message, "jaunt")) { - // zip to a specific place in the sim. - enter_stay_state(); - string where = llDeleteSubString(message, 0, 5); - if (where == "") { - llOwnerSay("i can't jaunt to like nowhere dude."); - return; - } - vector loc = (vector)where; - if (loc == <0.0, 0.0, 0.0>) { - llOwnerSay("jaunt locations should be in the vector format, and jaunting to <0, 0, 0> is unsupported."); - return; - } -llOwnerSay("jaunting to " + (string)loc); - jaunt_to_location(loc); - } else if (is_prefix(message, "name")) { - // toss the command portion to get our new name. - string new_name = llDeleteSubString(message, 0, 4); - if (llStringLength(new_name) > 0) { - llOwnerSay("wheeee! my new name is: " + new_name); - llSetObjectName(new_name); - show_title(); - } else { - // no data was given for the name. - llOwnerSay("my name is still " + llGetObjectName()); - } - } else { - // we support a simple translation for a few orders. - if (message == "free") message = "go home"; - - // see if we can just flip this into a menu command instead. we don't - // really care whether that works or not, since anything that doesn't work is - // a bogus command. - llMessageLinked(LINK_THIS, _COMMAND_CHANNEL, SHOW_MENU_COMMAND, - PET_MENU_NAME + HUFFWARE_PARM_SEPARATOR + message); - } -} - -////////////// - -stop_pet() -{ -//log_it("stopping pet from moving..."); - llSetPrimitiveParams([PRIM_PHYSICS, FALSE, - //]); - PRIM_PHANTOM, TRUE]); -} - -go_to_target(key av, vector pos) -{ -//log_it("told to go to target: key=" + (string)av + " pos=" + (string)pos); - TARGET_POSITION = pos; - if (av != NULL_KEY) { - vector av_size = llGetAgentSize(av); - - // if it's an object, use a different method to find its height. - if (av_size.z == 0.0) { - // use the object's height. - list box = llGetBoundingBox(KEY_OF_TARGET); - float object_height = llVecDist(llList2Vector(box, 0), llList2Vector(box, 1)); - av_size.z = object_height; - } - // adding to get pet above target. - TARGET_POSITION += < 0.0, 0.0, av_size.z / 2.0>; -//log_it("adjusted targposn: " + (string)TARGET_POSITION); - } - if (current_state == STATE_ATTACK) { - TARGET_POSITION += < 0.0, 0.0, ATTACK_HEIGHT_ABOVE_FOLLOWED_OBJECT>; - TARGET_POSITION += ; - } else { -//log_it("normal target calc"); - TARGET_POSITION += < 0.0, 0.0, DEFAULT_HEIGHT_ABOVE_FOLLOWED_OBJECT>; - TARGET_POSITION += ; - } - // trim the height a bit to keep the pet on-world. - if (TARGET_POSITION.z > 4095.0) - TARGET_POSITION.z = 4095.0; -} - -integer jaunt_responses_awaited = 0; - // the number of pending jumps that we are hoping will happen. - -integer slackness_counter; - // how many snoozes we've had waiting for our destination. - -jaunt_to_location(vector target) -{ - // send jaunt request to get us to the specified place. - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, (string)target); - // add one to our counter so we know a jaunt is in progress. - jaunt_responses_awaited++; - // reset the overflow counter to recognize a new jaunt. - slackness_counter = 0; -} - -vector previous_position; - // how far away target was last time. - -motivate() -{ - // first, let's get into the right state of existence. - llSetStatus(STATUS_PHYSICS, TRUE); // we need to be able to move around here. - if (current_state == STATE_ATTACK) { - llSetStatus(STATUS_PHANTOM, FALSE); // we can bonk into things now. - } else { - llSetStatus(STATUS_PHANTOM, TRUE); // there are no obstructive contacts. - } - - vector current_pos = llGetPos(); - float distance = llVecDist(TARGET_POSITION, current_pos); - // a simple linear velocity calculation based on the object's distance. - float velocity; - if (current_state == STATE_ATTACK) { - velocity = ATTACK_BASE_VELOCITY + VELOCITY_MULTIPLIER * (distance / 10.0); - // beef the velocity up for attack mode. - velocity *= 10.0; - } else { - velocity = DEFAULT_BASE_VELOCITY + VELOCITY_MULTIPLIER * (distance / 10.0); - } - -//hmmm: make that 20 a constant - integer jump_regardless = FALSE; - if (llVecDist(current_pos, previous_position) >= 20) { - // we will always re-target when the distances have changed that much; this could mean - // the avatar is falling away. - jump_regardless = TRUE; - } -float IN_RANGE_CHANCE_TO_BAIL = 0.9; -float ATTACK_IN_RANGE_CHANCE_TO_BAIL = 0.5; - -float NEAR_RANGE_CHANCE_TO_BAIL = 0.5; -float ATTACK_NEAR_RANGE_CHANCE_TO_BAIL = 0.1; - - if (distance <= MAXIMUM_TARGETING_DISTANCE) { - // damp out the equation if the target is close enough. - if (current_state == STATE_ATTACK) velocity = ATTACK_BASE_VELOCITY; - else velocity = DEFAULT_BASE_VELOCITY; - float within_range_chance = IN_RANGE_CHANCE_TO_BAIL; - if (current_state == STATE_ATTACK) within_range_chance = ATTACK_IN_RANGE_CHANCE_TO_BAIL; - if (llFrand(1.0) <= within_range_chance) return; // do nothing; close enough. - } else if (distance <= 2.0 * MAXIMUM_TARGETING_DISTANCE) { - // we have a bit larger chance of setting a new target if the - // distance is pretty close still. - float near_range_chance = NEAR_RANGE_CHANCE_TO_BAIL; - if (current_state == STATE_ATTACK) near_range_chance = ATTACK_NEAR_RANGE_CHANCE_TO_BAIL; - if (llFrand(1.0) <= near_range_chance) return; - } - previous_position = current_pos; -//log_it("dist=" + (string)distance + " vel=" + (string)velocity); - float time = distance / velocity; - _TARGET_ID = llTarget(TARGET_POSITION, MAXIMUM_TARGETING_DISTANCE); - pending_target = TRUE; - // make sure we're in a physics mode before attempting physics changes... - llSetStatus(STATUS_PHYSICS, TRUE); - if (SITTING_AVATAR_KEY == NULL_KEY) { - // when we have nobody riding, we can look wherever we want. - llLookAt(TARGET_POSITION, 0.7, 0.5); - } else { - // if we're holding onto an avatar, we keep them pointed in a reasonable way. - vector curr_pos = llGetPos(); - vector new_lookat = ; - llLookAt(new_lookat, 0.7, 0.5); - } -//log_it("setting move to target: " + (string)TARGET_POSITION); - llMoveToTarget(TARGET_POSITION, time); - - integer panic_dist = DEFAULT_PANIC_DISTANCE; - if (current_state == STATE_ATTACK) { - panic_dist = ATTACK_PANIC_DISTANCE; - } - - // don't try to jump if we're still awaiting a jump response. - if (!jaunt_responses_awaited && (distance > panic_dist) ) { - // we need to shorten the distance to our buddy now. - jaunt_to_location(TARGET_POSITION); - } else if (jump_regardless || (distance > TARGETING_SENSOR_RANGE - 10)) { - // we are double our panic point, so jump even if still waiting for a reply. - // however, we don't want to queue up too many jaunts at a time either. - if (jaunt_responses_awaited <= 2) { - jaunt_to_location(TARGET_POSITION); - } - } - - // push the attack target if we're close enough. - if ( (current_state == STATE_ATTACK) && (distance < ATTACK_PUSH_DIST_THRESHOLD) ) { - // only decide to push if they win the lottery here. - if (llFrand(1.0) < ATTACK_PUSH_CHANCE) { - llPushObject(KEY_OF_TARGET, ATTACK_PUSH_MAGNITUDE * llRot2Up(llGetRot()), ZERO_VECTOR, FALSE); - } - } - -} - -show_title() -{ - llSetText(llGetObjectName(), <0.6, 0.3, 0.8>, 1.0); -} - -// processes a link message from some other script. -handle_link_message(integer which, integer num, string msg, key id) -{ -//log_it("got msg=" + msg + " id=" + (string)id); - if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { -//log_it("link jaunt reply"); - if (msg == JAUNT_COMMAND) { - jaunt_responses_awaited--; // one less response being awaited. - if (jaunt_responses_awaited < 0) { - log_it("erroneously went below zero for jaunt responses!"); - jaunt_responses_awaited = 0; - } - // unpack the reply. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer last_jaunt_was_success = (integer)llList2String(parms, 0); - vector posn = (vector)llList2String(parms, 1); -//log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); - } - return; - } - if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. -//log_it("menu reply"); - react_to_menu(which, num, msg, id); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -initialize() -{ - show_title(); - llSetPrimitiveParams([PRIM_PHYSICS, FALSE, - //]); - PRIM_PHANTOM, TRUE]); - llSitTarget(SIT_POSITION, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD)); - llSetSitText(SIT_TEXT); - llSetBuoyancy(1.0); - _OWNER = llGetOwner(); - _FOLLOW_KEY = []; - _FOLLOW_NAME = []; - current_state = STATE_FREE; - TARGET_POSITION = llGetPos(); - llSetTimerEvent(PERIODIC_INTERVAL); - slackness_counter = 0; - _COMMAND_CHANNEL = random_channel(); - _FOLLOW_CHANNEL = random_channel(); - _COMMAND_CHANNEL = random_channel(); - llListen(PET_CHAT_CHANNEL, "", llGetOwner(), ""); - home_position = llGetPos(); // start in a known place. -} - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize(); - } - - on_rez(integer param) { llResetScript(); } - - touch_start(integer num_detected) { - show_title(); -//change title to show menuing state? - if (_OWNER == llDetectedKey(0)) { - // show our menu here. - show_menu(PET_MENU_NAME, _COMMAND_MESSAGE, SUPPORTED_COMMANDS, _COMMAND_CHANNEL); - } - } - - link_message(integer sender, integer num, string msg, key id) { - handle_link_message(sender, num, msg, id); - } - - sensor(integer num_detected) { -//log_it("sensor found " + llDetectedName(0)); - handle_sensor(num_detected); - } - - no_sensor() { -//use another means to find the avatar? - } - - at_target(integer number, vector targetpos, vector ourpos) { -//log_it("at target"); - llTargetRemove(_TARGET_ID); - pending_target = FALSE; - llStopMoveToTarget(); - } - - not_at_target() { -//log_it("not at target"); - - } - - changed(integer change) { - if (change & CHANGED_LINK) { - key av = llAvatarOnSitTarget(); - if (SITTING_AVATAR_KEY != NULL_KEY) { - if (av == NULL_KEY) { - llStopAnimation(SIT_ANIMATION); - SITTING_AVATAR_KEY = NULL_KEY; - } - } else { - if (av != NULL_KEY) { - SITTING_AVATAR_KEY = av; - llRequestPermissions(SITTING_AVATAR_KEY, PERMISSION_TRIGGER_ANIMATION); -// we wish we could make the avatar a phantom here, but that's not allowed. - } - } - } - } - - run_time_permissions(integer perm) { - key perm_key = llGetPermissionsKey(); - if (perm_key == SITTING_AVATAR_KEY) { - if (perm & PERMISSION_TRIGGER_ANIMATION) { - list anms = llGetAnimationList(SITTING_AVATAR_KEY); - integer i; - for (i = 0 ; i < llGetListLength(anms) ; i++) { - llStopAnimation(llList2Key(anms, i)); - } - llStartAnimation(SIT_ANIMATION); - } - } - } - - timer() { - handle_timer(); - } - - listen(integer channel, string name, key id, string message) { - handle_hearing_voices(channel, name, id, message); - } - -} - -// attributions: -// this script is based (a lot!) on the "pet" script that might -// have been written by kazumasa loon. there was no attribution -// of author in the script, but the creator was kazumasa. thanks dude! -// -// that being said, the script was redone a lot by fred huffhines, -// mainly in the following areas: -// -// march or april 2008: added teleport capability to script. pet will now attempt -// to keep up with the owner during follow mode by teleporting to her. -// -// may 2008: added ipc menu system. now menus are dealt with by the huffware -// menu system, removing a lot of code from this script. - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.txt new file mode 100755 index 00000000..1397e17c --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-pet_v18.6.txt @@ -0,0 +1,963 @@ + +// huffware script: huff-pet, by fred huffhines +// +// this is yet another implementation of a pet script in LSL. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +//to-do zone: + +//hmmm: for attack mode, adjust timers and ranges. +// probably just define the default set and mirror that with the attack set. +// switch between them during mode change. +// reset timer and sensor for mode change! + +// end to-do zone. + +// constants for the pet that one might want to change. + +integer PET_CHAT_CHANNEL = 28; + // the channel on which the pet will listen for commands from the owner. + +//integer DEFAULT_PANIC_DISTANCE = 28; +integer DEFAULT_PANIC_DISTANCE = 5;//short leash version for opensim. + // multiplied by the sensor range to get the distance allowed from the + // pet to the person it's following before a teleport is invoked. +integer ATTACK_PANIC_DISTANCE = 13; + // multiplied by the sensor range to get the distance allowed from the + // enraged pet to the attack target before a teleport is invoked. + +float DEFAULT_HEIGHT_ABOVE_FOLLOWED_OBJECT = 1.6; + // the height that the pet will float at above whoever it's following. +float ATTACK_HEIGHT_ABOVE_FOLLOWED_OBJECT = 0.0; + // the height that the pet will float at above the attack target. + +float DEFAULT_BASE_VELOCITY = 0.1; + // the velocity of the pet when just cavorting around. +float ATTACK_BASE_VELOCITY = 0.6; + // the velocity of the pet when in "angry" mode. + +integer DEFAULT_BUMP_SIZE = 48; + // the default size in meters of the displacement caused by up, down, etc commands. + +// the margin values below are the range of motion that the pet is allowed +// on each axis. +float DEFAULT_X_MARGIN = 3.0; +float DEFAULT_Y_MARGIN = 3.0; +float DEFAULT_Z_MARGIN = 1.0; +// the margin for when the pet is attacking. +float ATTACK_X_MARGIN = 0.1; +float ATTACK_Y_MARGIN = 0.1; +float ATTACK_Z_MARGIN = 0.2; + +float MAXIMUM_TARGETING_DISTANCE = 2.0; + // the amount of basic deviation allowed for the pet from its target spot. + // this is how far it's allowed to roam from the target. +//is that right? + +float ATTACK_PUSH_DIST_THRESHOLD = 2.0; + // how close the pet should be to an attack target before trying to push. +float ATTACK_PUSH_MAGNITUDE = 2147483646.0; //maxint - 1, dealing with svc-2723. + // how much the critter should push an attack target. +float ATTACK_PUSH_CHANCE = 0.1; + // how often (probability from 0.0 to 1.0) an attack target gets pushed. + +// other constants that are more advanced and should generally not change... + +float TARGETING_SENSOR_RANGE = 96.0; + // the maximum distance the pet will try to see the target at. + +float SENSOR_INTERVAL = 0.4; + // how often the sensor scan will fire off. this is the fastest we will + // check for our follow target, in seconds. + +float PERIODIC_INTERVAL = 0.42; + // how frequently our timer event fires. + +integer MAXIMUM_SLACKNESS = 28; + // how many timer hits we'll allow before reverting to the default state. + +float VELOCITY_MULTIPLIER = 1.2; + // the total velocity comes from the base plus an equation that multiplies + // this value by some function of the distance. + +string PET_MENU_NAME = "#woof"; // name for our menu. +string PET_REPLY_MENU = "#aroo"; // replies with data. + +// symbolic labels for the different states of pet 'being'. +integer STATE_STAY = 0; +integer STATE_FREE = 1; // go home. +integer STATE_FOLLOW = 2; +integer STATE_COME = 3; +integer STATE_WANDER = 4; +integer STATE_ATTACK = 9; + +list SUPPORTED_COMMANDS = [ "go home", "come", "stay", + "wander", "follow", "attack", + "set home", "set name", "status" ]; + // attack = follow an avatar in a menacing way. + // come = follow owner. + // follow = follow an avatar. + // go home = return home, then move about freely. + // set home = set the home position based on owner location. + // set name = change the object's name. + // stay = sit right there. + // wander = roam a greater distance while following owner. + +// requires: jaunting library v3.4 or higher. +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +string REVERSE_VELOCITY_COMMAND = "#reverse#"; + // makes the object reverse its velocity and travel back from whence it came. +string SET_VELOCITY_COMMAND = "#setvelocity#"; + // makes the velocity equal to the vector passed as the first parameter. +string JAUNT_UP_COMMAND = "#jauntup#"; +string JAUNT_DOWN_COMMAND = "#jauntdown#"; + // commands for height adjustment. pass a float for number of meters to move. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a list of vectors as the first parameter; this list + // should be in the jaunter notecard format (separated by pipe characters). + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// + +//requires menutini library v4.2 or better. +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +// commands available via the menu system: +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. + // the reply will include: the menu name, the choice made and the key for + // the avatar. +// +////////////// + + +request_full_stop() +{ + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); +} + +request_jaunt_up(integer distance) +{ + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_UP_COMMAND, (string)distance); +} + +// global variables... + +key _OWNER; +integer current_state; +vector home_position; // the location where the pet lives. + +integer pending_target = FALSE; // is a target still being sought. + +integer _COMMAND_CHANNEL; +string _COMMAND_MESSAGE = "How may I assist you?"; + +integer _TARGET_ID; +vector TARGET_POSITION; + +float _FREE_RANGE = 10.0; + +string SIT_TEXT = "Meditate"; + +string SIT_ANIMATION = "yoga_float"; + +vector SIT_POSITION = <0.2, 0.2, 0.4>; + +vector SIT_ROTATION = <0.0, 0.0, 0.0>; + +key SITTING_AVATAR_KEY = NULL_KEY; + +// options for follow menu that pops up when pet is told to follow someone. +list _FOLLOW_KEY; +list _FOLLOW_NAME; // filled in with nearby avatars. +integer _FOLLOW_CHANNEL; +string _FOLLOW_MESSAGE = "Who should I follow?"; + +integer seeking_avatars = FALSE; +key KEY_OF_TARGET; + +////////////// + +// from hufflets... + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +/////////////// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay((string)debug_num + "- " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +/////////////// + +// info... + +// returns a string version of the state 's'. +string name_for_state(integer s) { + if (s == STATE_STAY) return "stay"; + if (s == STATE_FREE) return "go home"; + if (s == STATE_FOLLOW) return "follow"; + if (s == STATE_COME) return "come"; + if (s == STATE_WANDER) return "wander"; + if (s == STATE_ATTACK) return "attack"; + return "unknown"; +} + +// menu methods... + +list current_buttons; // holds onto the set of menu options. + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +string stringize_list(list to_flatten) { + return llDumpList2String(to_flatten, HUFFWARE_ITEM_SEPARATOR); +} + +// pops up a menu to interact with the pet's owner. +show_menu(string menu_name, string title, list buttons, integer channel) +{ + current_buttons = buttons; + key listen_to = _OWNER; + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + stringize_list(current_buttons) + + HUFFWARE_PARM_SEPARATOR + (string)channel + + HUFFWARE_PARM_SEPARATOR + (string)listen_to); +} + +// causes a state change to make the pet stay. +enter_stay_state() +{ + current_state = STATE_STAY; + llSensorRemove(); + stop_pet(); +} + +// handle the response message when the user chooses a button. +react_to_menu(integer sender, integer num, string msg, key id) +{ +log_it("react menu: " + msg + " parm=" + (string)id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string choice = llList2String(parms, 1); + + if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) || (msg != SHOW_MENU_COMMAND) ) { +log_it("why here in react to menu, not for us?"); + return; + } + + if (menu_name == PET_MENU_NAME) { +log_it("react: snd=" + (string)sender + " num=" + (string)num + " msg=" + msg + " key=" + (string)id); + if (find_in_list(SUPPORTED_COMMANDS, choice) < 0) { + llOwnerSay("i don't know what you mean..."); + return; + } +llOwnerSay("i heard you tell me: menu=" + menu_name + " choice=" + choice); + + // handle commands that are major changes in state... + + if (choice == "come") { + llOwnerSay("coming to find you now..."); + current_state = STATE_COME; + llSetPrimitiveParams([PRIM_PHYSICS, TRUE, + //]); + PRIM_PHANTOM, TRUE]); + llSensorRemove(); + llSensorRepeat("", _OWNER, AGENT, TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); + } + + if (choice == "stay") { + llOwnerSay("i will stay right here..."); + enter_stay_state(); + } + + if (choice == "wander") { + current_state = STATE_WANDER; + llOwnerSay("i'm going to wander around and kind of vaguely follow you..."); + llSetPrimitiveParams([PRIM_PHYSICS, TRUE, + //]); + PRIM_PHANTOM, TRUE]); + llSensorRemove(); + llSensorRepeat("", _OWNER, AGENT, TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); + } + + if ( (choice == "follow") || (choice == "attack") ) { + seeking_avatars = TRUE; + stop_pet(); + llSensorRemove(); + if (choice == "attack") { + // we only attack avatars. + //or not. since that's boring. watching a pet attack a physical object is fun. + llSensor("", NULL_KEY, AGENT | ACTIVE, TARGETING_SENSOR_RANGE, PI); + current_state = STATE_ATTACK; + } else { + // look for both objects and avatars to follow. + llSensor("", NULL_KEY, AGENT | ACTIVE, TARGETING_SENSOR_RANGE, PI); + current_state = STATE_FOLLOW; + } + } + + if (choice == "go home") { + current_state = STATE_FREE; // free to roam about the cabin, or wherever home is. + llOwnerSay("i'm going home now."); + jaunt_to_location(home_position); + } + + // commands that don't lead to state changes... + + if (choice == "status") { + string seek_addition; + if (KEY_OF_TARGET != "") + seek_addition = "was last seeking " + llKey2Name(KEY_OF_TARGET); + llOwnerSay("my name is " + llGetObjectName() + " and state is '" + + name_for_state(current_state) + "'.\n" + + seek_addition); + } + + if (choice == "set home") { + list pos_list = llGetObjectDetails(llGetOwner(), [OBJECT_POS]); + home_position = llList2Vector(pos_list, 0); + llOwnerSay("i'm setting my home to " + (string)home_position); + //hmmm: use a rounding print to show the position. + } + if (choice == "set name") { + llOwnerSay("to change my name from " + llGetObjectName() + ",\ntell me my new name by typing:\n/" + (string)PET_CHAT_CHANNEL + " name My Cool New Name"); + } + + } else if (menu_name == PET_REPLY_MENU) { +log_it("menu-act follow: snd=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); + llSetPrimitiveParams([PRIM_PHYSICS, TRUE, + //]); + PRIM_PHANTOM, !(current_state == STATE_ATTACK)]); + integer choice_indy = find_in_list(_FOLLOW_NAME, choice); + if (choice_indy < 0) { +//log_it("choice was not found in list"); +//log_it("followname list is: " + (string)_FOLLOW_NAME); + } else { + string action = "follow"; + if (current_state == STATE_ATTACK) action = "attack"; + llOwnerSay("now " + action + "ing " + + llList2String(_FOLLOW_NAME, choice_indy) + "..."); + seeking_avatars = FALSE; + KEY_OF_TARGET = llList2Key(_FOLLOW_KEY, choice_indy); + llSensorRemove(); + llSensorRepeat("", KEY_OF_TARGET, AGENT | ACTIVE, + TARGETING_SENSOR_RANGE, PI, SENSOR_INTERVAL); + } + } +} + +// processes the hits that we get back from the sensor. the information we receive +// is needed for most of the pet states. +handle_sensor(integer num_detected) +{ + if (current_state == STATE_COME) { + go_to_target(_OWNER, llDetectedPos(0)); + motivate(); + } + + if ( (current_state == STATE_FOLLOW) || (current_state == STATE_ATTACK) ) { + if (seeking_avatars) { + // reset the list of keys and names that were found previously. + _FOLLOW_KEY = []; + _FOLLOW_NAME = []; + // show the full set found if it will fit, otherwise just 12. + integer num_to_show = num_detected; + if (num_to_show > 12) num_to_show = 12; + // examine each of the avatars found and put them on the list. + integer i; + for (i = 0 ; i < num_to_show; i++) { + key to_follow = llDetectedKey(i); + if (to_follow != NULL_KEY) { + _FOLLOW_KEY += [to_follow]; + string str = llDetectedName(i); + // trim the menu item if it has hit the maximum limit. + if (llStringLength(str) > 24) str = llGetSubString(str, 0, 23); + integer name_try = 0; + while (find_in_list(_FOLLOW_NAME, str) >= 0) { + // this guy is already listed under that name, so change it a bit. + str = llGetSubString(str, 0, 22) + (string)name_try++; + } + _FOLLOW_NAME += [str]; + } + } + // now ask who to follow. + if (llGetListLength(_FOLLOW_KEY)) { + show_menu(PET_REPLY_MENU, _FOLLOW_MESSAGE, _FOLLOW_NAME, _FOLLOW_CHANNEL); + } + } else { + // not seeking the avatar any more; follow who was chosen. + go_to_target(KEY_OF_TARGET, llDetectedPos(0)); + motivate(); + } + } + + if (current_state == STATE_WANDER) { + if (jaunt_responses_awaited) return; // skip doing anything while we're still waiting. + vector pos = llDetectedPos(0); + float omg = llFrand(1) * PI * 2; + float t_r = llFrand(1) * _FREE_RANGE; + float t_x = t_r * llCos(omg); + float t_y = t_r * llSin(omg); + go_to_target(NULL_KEY, pos + ); + motivate(); + } + +} + +handle_timer() { + if (current_state != STATE_STAY) { + // make sure a bad jaunt didn't break our physics. + llSetStatus(STATUS_PHYSICS, TRUE); + } + + if (jaunt_responses_awaited) { + // we are not quite there yet. + if (slackness_counter++ > MAXIMUM_SLACKNESS) { + // go back to the main state. we took too long. +log_it("waiting for jaunt timed out."); +///argh? jaunt_responses_awaited--; + slackness_counter = 0; + } else return; // not time yet for rest of timed actions. + } + + // handle the free state, since we need may to readjust the target. + if (current_state == STATE_FREE) { + if (pending_target) return; // haven't arrived at previous yet. + vector pos = home_position; + float omg = llFrand(1) * PI * 2; +//hmmm: make free range settable + float t_r = llFrand(1) * _FREE_RANGE; + float t_x = t_r * llCos(omg); + float t_y = t_r * llSin(omg); + go_to_target(NULL_KEY, pos + ); + motivate(); + } +} + +handle_hearing_voices(integer channel, string name, key id, string message) +{ + if (channel != PET_CHAT_CHANNEL) return; // not our channel. +//log_it("into handle voice, msg=" + message); + if (id != llGetOwner()) return; // not authorized. + // we found a command. which specific one? + if (is_prefix(message, "up")) { + // upwards bump. + enter_stay_state(); + string dist = llDeleteSubString(message, 0, 2); + if (dist == "") dist = (string)DEFAULT_BUMP_SIZE; + request_jaunt_up((integer)dist); +llOwnerSay("bumping up by " + dist); + } else if (is_prefix(message, "down")) { + // downwards bump. + enter_stay_state(); + string dist = llDeleteSubString(message, 0, 4); + if (dist == "") dist = (string)DEFAULT_BUMP_SIZE; + request_jaunt_up(-(integer)dist); +llOwnerSay("bumping down by " + dist); + } else if (is_prefix(message, "jaunt")) { + // zip to a specific place in the sim. + enter_stay_state(); + string where = llDeleteSubString(message, 0, 5); + if (where == "") { + llOwnerSay("i can't jaunt to like nowhere dude."); + return; + } + vector loc = (vector)where; + if (loc == <0.0, 0.0, 0.0>) { + llOwnerSay("jaunt locations should be in the vector format, and jaunting to <0, 0, 0> is unsupported."); + return; + } +llOwnerSay("jaunting to " + (string)loc); + jaunt_to_location(loc); + } else if (is_prefix(message, "name")) { + // toss the command portion to get our new name. + string new_name = llDeleteSubString(message, 0, 4); + if (llStringLength(new_name) > 0) { + llOwnerSay("wheeee! my new name is: " + new_name); + llSetObjectName(new_name); + show_title(); + } else { + // no data was given for the name. + llOwnerSay("my name is still " + llGetObjectName()); + } + } else { + // we support a simple translation for a few orders. + if (message == "free") message = "go home"; + + // see if we can just flip this into a menu command instead. we don't + // really care whether that works or not, since anything that doesn't work is + // a bogus command. + llMessageLinked(LINK_THIS, _COMMAND_CHANNEL, SHOW_MENU_COMMAND, + PET_MENU_NAME + HUFFWARE_PARM_SEPARATOR + message); + } +} + +////////////// + +stop_pet() +{ +//log_it("stopping pet from moving..."); + llSetPrimitiveParams([PRIM_PHYSICS, FALSE, + //]); + PRIM_PHANTOM, TRUE]); +} + +go_to_target(key av, vector pos) +{ +//log_it("told to go to target: key=" + (string)av + " pos=" + (string)pos); + TARGET_POSITION = pos; + if (av != NULL_KEY) { + vector av_size = llGetAgentSize(av); + + // if it's an object, use a different method to find its height. + if (av_size.z == 0.0) { + // use the object's height. + list box = llGetBoundingBox(KEY_OF_TARGET); + float object_height = llVecDist(llList2Vector(box, 0), llList2Vector(box, 1)); + av_size.z = object_height; + } + // adding to get pet above target. + TARGET_POSITION += < 0.0, 0.0, av_size.z / 2.0>; +//log_it("adjusted targposn: " + (string)TARGET_POSITION); + } + if (current_state == STATE_ATTACK) { + TARGET_POSITION += < 0.0, 0.0, ATTACK_HEIGHT_ABOVE_FOLLOWED_OBJECT>; + TARGET_POSITION += ; + } else { +//log_it("normal target calc"); + TARGET_POSITION += < 0.0, 0.0, DEFAULT_HEIGHT_ABOVE_FOLLOWED_OBJECT>; + TARGET_POSITION += ; + } + // trim the height a bit to keep the pet on-world. + if (TARGET_POSITION.z > 4095.0) + TARGET_POSITION.z = 4095.0; +} + +integer jaunt_responses_awaited = 0; + // the number of pending jumps that we are hoping will happen. + +integer slackness_counter; + // how many snoozes we've had waiting for our destination. + +jaunt_to_location(vector target) +{ + // send jaunt request to get us to the specified place. + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, (string)target); + // add one to our counter so we know a jaunt is in progress. + jaunt_responses_awaited++; + // reset the overflow counter to recognize a new jaunt. + slackness_counter = 0; +} + +vector previous_position; + // how far away target was last time. + +motivate() +{ + // first, let's get into the right state of existence. + llSetStatus(STATUS_PHYSICS, TRUE); // we need to be able to move around here. + if (current_state == STATE_ATTACK) { + llSetStatus(STATUS_PHANTOM, FALSE); // we can bonk into things now. + } else { + llSetStatus(STATUS_PHANTOM, TRUE); // there are no obstructive contacts. + } + + vector current_pos = llGetPos(); + float distance = llVecDist(TARGET_POSITION, current_pos); + // a simple linear velocity calculation based on the object's distance. + float velocity; + if (current_state == STATE_ATTACK) { + velocity = ATTACK_BASE_VELOCITY + VELOCITY_MULTIPLIER * (distance / 10.0); + // beef the velocity up for attack mode. + velocity *= 10.0; + } else { + velocity = DEFAULT_BASE_VELOCITY + VELOCITY_MULTIPLIER * (distance / 10.0); + } + +//hmmm: make that 20 a constant + integer jump_regardless = FALSE; + if (llVecDist(current_pos, previous_position) >= 20) { + // we will always re-target when the distances have changed that much; this could mean + // the avatar is falling away. + jump_regardless = TRUE; + } +float IN_RANGE_CHANCE_TO_BAIL = 0.9; +float ATTACK_IN_RANGE_CHANCE_TO_BAIL = 0.5; + +float NEAR_RANGE_CHANCE_TO_BAIL = 0.5; +float ATTACK_NEAR_RANGE_CHANCE_TO_BAIL = 0.1; + + if (distance <= MAXIMUM_TARGETING_DISTANCE) { + // damp out the equation if the target is close enough. + if (current_state == STATE_ATTACK) velocity = ATTACK_BASE_VELOCITY; + else velocity = DEFAULT_BASE_VELOCITY; + float within_range_chance = IN_RANGE_CHANCE_TO_BAIL; + if (current_state == STATE_ATTACK) within_range_chance = ATTACK_IN_RANGE_CHANCE_TO_BAIL; + if (llFrand(1.0) <= within_range_chance) return; // do nothing; close enough. + } else if (distance <= 2.0 * MAXIMUM_TARGETING_DISTANCE) { + // we have a bit larger chance of setting a new target if the + // distance is pretty close still. + float near_range_chance = NEAR_RANGE_CHANCE_TO_BAIL; + if (current_state == STATE_ATTACK) near_range_chance = ATTACK_NEAR_RANGE_CHANCE_TO_BAIL; + if (llFrand(1.0) <= near_range_chance) return; + } + previous_position = current_pos; +//log_it("dist=" + (string)distance + " vel=" + (string)velocity); + float time = distance / velocity; + _TARGET_ID = llTarget(TARGET_POSITION, MAXIMUM_TARGETING_DISTANCE); + pending_target = TRUE; + // make sure we're in a physics mode before attempting physics changes... + llSetStatus(STATUS_PHYSICS, TRUE); + if (SITTING_AVATAR_KEY == NULL_KEY) { + // when we have nobody riding, we can look wherever we want. + llLookAt(TARGET_POSITION, 0.7, 0.5); + } else { + // if we're holding onto an avatar, we keep them pointed in a reasonable way. + vector curr_pos = llGetPos(); + vector new_lookat = ; + llLookAt(new_lookat, 0.7, 0.5); + } +//log_it("setting move to target: " + (string)TARGET_POSITION); + llMoveToTarget(TARGET_POSITION, time); + + integer panic_dist = DEFAULT_PANIC_DISTANCE; + if (current_state == STATE_ATTACK) { + panic_dist = ATTACK_PANIC_DISTANCE; + } + + // don't try to jump if we're still awaiting a jump response. + if (!jaunt_responses_awaited && (distance > panic_dist) ) { + // we need to shorten the distance to our buddy now. + jaunt_to_location(TARGET_POSITION); + } else if (jump_regardless || (distance > TARGETING_SENSOR_RANGE - 10)) { + // we are double our panic point, so jump even if still waiting for a reply. + // however, we don't want to queue up too many jaunts at a time either. + if (jaunt_responses_awaited <= 2) { + jaunt_to_location(TARGET_POSITION); + } + } + + // push the attack target if we're close enough. + if ( (current_state == STATE_ATTACK) && (distance < ATTACK_PUSH_DIST_THRESHOLD) ) { + // only decide to push if they win the lottery here. + if (llFrand(1.0) < ATTACK_PUSH_CHANCE) { + llPushObject(KEY_OF_TARGET, ATTACK_PUSH_MAGNITUDE * llRot2Up(llGetRot()), ZERO_VECTOR, FALSE); + } + } + +} + +show_title() +{ + llSetText(llGetObjectName(), <0.6, 0.3, 0.8>, 1.0); +} + +// processes a link message from some other script. +handle_link_message(integer which, integer num, string msg, key id) +{ +//log_it("got msg=" + msg + " id=" + (string)id); + if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { +//log_it("link jaunt reply"); + if (msg == JAUNT_COMMAND) { + jaunt_responses_awaited--; // one less response being awaited. + if (jaunt_responses_awaited < 0) { + log_it("erroneously went below zero for jaunt responses!"); + jaunt_responses_awaited = 0; + } + // unpack the reply. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer last_jaunt_was_success = (integer)llList2String(parms, 0); + vector posn = (vector)llList2String(parms, 1); +//log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); + } + return; + } + if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. +//log_it("menu reply"); + react_to_menu(which, num, msg, id); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +initialize() +{ + show_title(); + llSetPrimitiveParams([PRIM_PHYSICS, FALSE, + //]); + PRIM_PHANTOM, TRUE]); + llSitTarget(SIT_POSITION, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD)); + llSetSitText(SIT_TEXT); + llSetBuoyancy(1.0); + _OWNER = llGetOwner(); + _FOLLOW_KEY = []; + _FOLLOW_NAME = []; + current_state = STATE_FREE; + TARGET_POSITION = llGetPos(); + llSetTimerEvent(PERIODIC_INTERVAL); + slackness_counter = 0; + _COMMAND_CHANNEL = random_channel(); + _FOLLOW_CHANNEL = random_channel(); + _COMMAND_CHANNEL = random_channel(); + llListen(PET_CHAT_CHANNEL, "", llGetOwner(), ""); + home_position = llGetPos(); // start in a known place. +} + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize(); + } + + on_rez(integer param) { llResetScript(); } + + touch_start(integer num_detected) { + show_title(); +//change title to show menuing state? + if (_OWNER == llDetectedKey(0)) { + // show our menu here. + show_menu(PET_MENU_NAME, _COMMAND_MESSAGE, SUPPORTED_COMMANDS, _COMMAND_CHANNEL); + } + } + + link_message(integer sender, integer num, string msg, key id) { + handle_link_message(sender, num, msg, id); + } + + sensor(integer num_detected) { +//log_it("sensor found " + llDetectedName(0)); + handle_sensor(num_detected); + } + + no_sensor() { +//use another means to find the avatar? + } + + at_target(integer number, vector targetpos, vector ourpos) { +//log_it("at target"); + llTargetRemove(_TARGET_ID); + pending_target = FALSE; + llStopMoveToTarget(); + } + + not_at_target() { +//log_it("not at target"); + + } + + changed(integer change) { + if (change & CHANGED_LINK) { + key av = llAvatarOnSitTarget(); + if (SITTING_AVATAR_KEY != NULL_KEY) { + if (av == NULL_KEY) { + llStopAnimation(SIT_ANIMATION); + SITTING_AVATAR_KEY = NULL_KEY; + } + } else { + if (av != NULL_KEY) { + SITTING_AVATAR_KEY = av; + llRequestPermissions(SITTING_AVATAR_KEY, PERMISSION_TRIGGER_ANIMATION); +// we wish we could make the avatar a phantom here, but that's not allowed. + } + } + } + } + + run_time_permissions(integer perm) { + key perm_key = llGetPermissionsKey(); + if (perm_key == SITTING_AVATAR_KEY) { + if (perm & PERMISSION_TRIGGER_ANIMATION) { + list anms = llGetAnimationList(SITTING_AVATAR_KEY); + integer i; + for (i = 0 ; i < llGetListLength(anms) ; i++) { + llStopAnimation(llList2Key(anms, i)); + } + llStartAnimation(SIT_ANIMATION); + } + } + } + + timer() { + handle_timer(); + } + + listen(integer channel, string name, key id, string message) { + handle_hearing_voices(channel, name, id, message); + } + +} + +// attributions: +// this script is based (a lot!) on the "pet" script that might +// have been written by kazumasa loon. there was no attribution +// of author in the script, but the creator was kazumasa. thanks dude! +// +// that being said, the script was redone a lot by fred huffhines, +// mainly in the following areas: +// +// march or april 2008: added teleport capability to script. pet will now attempt +// to keep up with the owner during follow mode by teleporting to her. +// +// may 2008: added ipc menu system. now menus are dealt with by the huffware +// menu system, removing a lot of code from this script. + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.lsl deleted file mode 100755 index a5c10dce..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.lsl +++ /dev/null @@ -1,1248 +0,0 @@ - -// huffware script: huff-search brainiac, by fred huffhines -// -// this script is one portion of a search system. it is the brain for an object -// that can find nearby objects by a partial name match. this script should be -// located in the root primitive. it also requires an up-to-date jaunting library -// in the same primitive. see the (hopefully) enclosed documentation for more details. -// more implementation notes are stored at the back of the file. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global settings that can be very useful to change... - -integer MAX_MATCHES = 17; - // by default we try to match one object per rod so we can point at them. - -float MAX_SPIRAL_RADIUS = 72.0; - // the farthest that the object will travel from its home while searching. - // this is an important factor in the searchbert's range of vision; the other is - // the sensor range, below. - // ensure that it has access to the lands within this range or it might get stuck. - // you can also set the TRAVERSE_LANDS flag to false to make for safer searches when - // surrounded by a lot of banned lands. - -float SENSOR_MAX_RANGE = 96.0; - // the maximum range that we try to sense objects at. this is distinct from the spiral - // radius because often the range of movement is constrained by land conditions, where - // one might still want a large sensor radius to see as many things as possible in range. - // note though that searches will keep matching the things nearest to them if neither - // the position nor the angle nor object positions have changed. - -float SPIRAL_LOOPS = 7; - // how many loops there are in the spiral. this is measured by how many times the - // spiral cuts across the positive x-axis (that is, the zero angle vector) from - // the center of the spiral to the radius (that is, from <0, 0, 0> to ). - -integer TOTAL_STEPS = 42; - // how many positions within the spiral will the object travel to? the first step - // is step 0, which is the center of the spiral. positions 1 through TOTAL_STEPS - // spiral outward from the zero position, where the distance from the center at - // TOTAL_STEPS should be MAX_SPIRAL_RADIUS or less. - -integer MAX_SPIRAL_TRAVERSALS = 1; - // how many different spirals are we allowed for the same search? this will let the - // search engine cover more ground than with just one spiral, to allow different - // objects to be exposed. - -integer HUFF_SEARCH_CHAT_CHANNEL = 0; - // the channel where the object listens for commands. the default is to use open - // chat for this, but some people may want it more specific. - -// this flag is important to keep as false for wright plaza and other areas with script traps -// (where the perms allow objects to enter, but then their scripts are stopped dead). -integer TRAVERSE_LANDS = FALSE; - // if this is false, then the searchbert will stick to the land owner's land where it started. - // but if it's true, then searchbert will cross into other people's lands too, but if there - // are some weird border or permission conditions about object re-entry or scripts being able - // to run, that can be quite problematic. - -integer TRAVELLING_UPWARDS = FALSE; - // if this is true, the searchbert will climb in the vertical direction also. - -float MAX_UPWARDS_DISTANCE = 30.0; - // the farthest away that the searchbert will fly during an upwards search. - -float SEARCH_ROD_ANGULAR_SWEEP = PI_BY_TWO; - // angular arc of the sensor cone, placeholder. - -////////////// - -// constants that are not configurable in a notecard... - -integer DEBUGGING = FALSE; // set to true to make the script noisier. - -////////////// - -// global constants that aren't as useful to change... - -float MINIMUM_HEIGHT_ABOVE_GROUND = 0.14; - // the closest we allow the searcher to get to the ground. any lower and our search - // rods might be dragging around under ground. - -float FAST_TIMER_INTERVAL = 0.12; - // the time between jumps when we're doing our search spiral. this is the fastest - // the object can spin around its spiral trajectory, but it's more limited than by - // just this number; llSetPrimitiveParams is used for jaunting and it has a delay of - // 0.2 seconds built into it. - -integer NORMAL_TIMER_INTERVAL = 14; - // how frequently we check for things to do, in seconds. - -float STARTUP_TIME_ALLOWED = 50.0; // number of seconds before declaring a timeout. - -integer MAX_STEP_SNOOZES = 81; - // number of timer hits to allow before giving up on jaunt. - -float SNOOZE_BEFORE_RESET = 300; - // number of seconds before a scan will automatically reset. hopefully this is - // enough time for the user to follow the trail to the detected object. - -// imported interfaces below... - -// huff-search pointer API: -////////////// -// do not redefine these constants. -integer HUFF_SEARCH_POINTER_HUFFWARE_ID = 10032; - // the unique id within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string HUFF_SEARCH_RESET = "#reset#"; - // returns the script to its starting state. -string HUFF_SEARCH_POINT_PARTY = "#point_particles#"; - // aim at an object and show a particle stream leading to it. -string HUFF_SEARCH_JUST_POINT = "#just_point#"; - // aim at an object, but don't do any particles. -string HUFF_SEARCH_SENSEI = "#sensor#"; - // set up a sensor request for a search pattern. pings will cause - // the pattern to be sought in names of nearby objects. the parameters are: - // (1) the maximum range for the sensor, (2) the arc angle to use in sensing, - // (3) the search pattern to look for in object names, (4) the maximum number - // of matches to look for. -string HUFF_SEARCH_STOP_SENSE = "#stop_sensor#"; - // turn off the sensor but don't totally reset. -string HUFF_SEARCH_PING = "#ping#"; - // cause the searcher to actively sensor ping the targets. -string HUFF_SEARCH_MATCH_EVENT = "#match#"; - // fired at the root prim when matches are found for the search term. - // the payload is a list of matched item pairs [item key, location]. -////////////// - -// the armature button pushing API. -// (we have subclassed the simple button pushing API for searchbert armature.) -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10029; - // a unique ID within the huffware system for this script. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was pushed. -////////////// -string CHECK_ARMS_BUTTON_NAME = "^checkarms"; - // this is the signal given to the armature script that it should check the - // number of arms present on searchbert. if the number is fine, it will - // push the arms are good button back at the brainiac (using the button - // push api plus reply distance). -string ARMS_ARE_GOOD_BUTTON_NAME = "^goodarmz"; - // the event sent back by the searchbert armature when all arms are ready - // to go. -string PROBLEM_WITH_MY_THUMBS_BUTTON_NAME = "^ouch"; - // a problem was noticed with the number of arms and we could not fix it. - // the brain needs to try reconfiguring again. -////////////// - -// searchbert menus API. -////////////// -// do not redefine these constants. -integer SEARCHBERT_MENUS_HUFFWARE_ID = 10034; - // the unique id within the huffware system for this script. -////////////// -string SM_CONFIGURE_INFO = "#sm-info#"; - // sets important information this script will use, such as (1) the channel for listening. -string SM_POP_MAIN_MENU_UP = "#sm-main#"; - // causes the main menu to be displayed. this requires an avatar name and avatar key for the - // target of the menu. -////////////// -string SM_EVENT_MENU_CLICK = "#sm-clik#"; - // the user has requested a particular menu item that this script cannot fulfill. the - // event is generated back to the client of this script for handling. it will include (1) the - // menu name in question, (2) the item clicked, (3) the avatar name, and (4) the avatar key. -////////////// - -// card configurator link message API: -////////////// -// do not redefine these constants. -integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; - // the unique id within the huffware system for the card configurator script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -string BAD_NOTECARD_TEXT = "*badcrd*"; - // the sign that we hated the notecards we found, or there were none. -string FINISHED_READING_NOTECARDS = "**finished**"; - // the sign that we are done plowing through the card we found. -string BEGIN_READING_NOTECARD_COMMAND = "#read-cfg#"; - // requests that the configurator find a good notecard and read its contents. - // it should send the contents via the alert below. first parm is the signature and - // second is the wrapped list of valid item prefixes. -string READ_PARTICULAR_NOTECARD_COMMAND = "#read-note#"; - // requests that the configurator find a good notecard and read its contents. - // it should send the contents via the alert below. first two parms are the same as - // begin reading notecard, and the third parameter is the name of the specific notecard. -string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; - // this message is sent when the configurator has found some data updates or has finished - // reading the configuration file. -////////////// - -// jaunting library API: -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -//string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -//string REVERSE_VELOCITY_COMMAND = "#reverse#"; - // makes the object reverse its velocity and travel back from whence it came. -//string SET_VELOCITY_COMMAND = "#setvelocity#"; - // makes the velocity equal to the vector passed as the first parameter. -//string JAUNT_UP_COMMAND = "#jauntup#"; -//string JAUNT_DOWN_COMMAND = "#jauntdown#"; - // commands for height adjustment. pass a float for number of meters to move. -//string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a string in jaunt notecard format with vectors. - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// - -// global variables used in the script. - -// configuration variables... -integer all_setup_finished = FALSE; // have we read our configuration yet? -integer configuration_pending = FALSE; // true if the setup process (config and arms) is still going on. -integer listening_handle = 0; // tracks our handle for listening to commands. - -// matching variables... -string global_target_name = ""; // the name of the object being sought. - -list global_matches_found; // a list of keys that match the specified search terms. -list global_positions_found; // matches list of positions for the detected objects. - -// jaunting variables... - -vector global_home_posn; // the location where the search bot is located. -vector last_safe_target; // the last place we jaunted to that was safe. - -integer next_step_snoozes_left; // pauses allowed before deciding jaunt will not respond. - -integer jaunt_responses_awaited = 0; // true when a jaunt is pending. -integer last_jaunt_was_success = FALSE; // result of jaunting received by message. - -vector current_rotation = <0.0, 0.0, 0.0>; - // the current rotation around each axis for object. - -// spiral variables... - -integer global_current_step = 0; // the current position in the search spiral. -float spiral_start_angle = 0.0; // how many radians to offset spiral by for this pass. -integer global_current_pass = 0; // which spiral number are we working on? - -integer tried_jump_homeward = FALSE; - // when retracing to home, this records if we already tried the jump home that should - // come in between the spiral jaunt. - -integer retracing_steps = FALSE; - // this is true when we are trying to get back home after finishing our spirals. - -// object maintenance variables... - -integer reset_for_next_timer = FALSE; // true when next timer hit should do a reset. - -integer running_a_search = FALSE; // true if the object is seeking matches. - -////////////// - -// constants that should not be messed with. - -float MAX_SLACK_DISTANCE = 0.01; // how close we need to be to a target. - -integer ALL_SEEKER_ALERT = -1; // communicates with all search rods. - -integer last_time_ordered_stop_sensing = 0; - // tracks when we last tried to order the search rods to stop sensing matches. - -// jaunting variables... - -vector last_jaunt_target; - // where we're currently headed. this variable is mostly for record keeping, so we want - // to update it whenever we jaunt someplace. - -////////////// - -// main functions for getting work done as the searchbert... - -// pointing that doesn't use particles, but just aims a search rod. -aim_at_position(integer which_seeker, vector targetPosition) { - list paramList = [targetPosition]; - request_from_seeker(which_seeker, llDumpList2String(paramList, - HUFFWARE_PARM_SEPARATOR), HUFF_SEARCH_JUST_POINT); -} - -// tells the rod at "which_seeker" link to do a sensor scan. -start_sensing(integer which_seeker, float max_range, float arc_angle, string search_pattern, - integer matches_sought) -{ - list paramList = [max_range, arc_angle, search_pattern, matches_sought]; - request_from_seeker(which_seeker, llDumpList2String(paramList, - HUFFWARE_PARM_SEPARATOR), HUFF_SEARCH_SENSEI); -} - -// tells all of the seeker search rods to stop sensing matches. -stop_sensing() -{ - // make sure that we are not just blasting this order over and over. - if (llGetUnixTime() != last_time_ordered_stop_sensing) { - last_time_ordered_stop_sensing = llGetUnixTime(); - request_from_seeker(ALL_SEEKER_ALERT, "", HUFF_SEARCH_STOP_SENSE); - } -} - -// tell the seeker arms to find what we asked them about. -request_ping() { request_from_seeker(ALL_SEEKER_ALERT, "", HUFF_SEARCH_PING); } - -////////////// - -// teleports to the vector specified. this invokes a method in the jaunting library -// which will return its result asynchronously. thus we can't just expect that we -// have arrived at the target by the end of this function; we need to get back the -// IPC message in linked_message. -jaunt_to_target(vector target) -{ - if (!TRAVERSE_LANDS) { - // this is an important restriction since we don't want to get trapped in weird - // land perm screwups, like not being able to re-enter the land where we started, - // if that parcel option is set. - if (llGetLandOwnerAt(llGetPos()) != llGetLandOwnerAt(target)) { - return; - } - } - - // reset our snoozer count, since we're doing a new jaunt now. - next_step_snoozes_left += MAX_STEP_SNOOZES; - jaunt_responses_awaited++; - // record the current target. - last_jaunt_target = target; - - float minimum_rod_angle_addition = 0.2; - float maximum_rod_angle_addition = 10.8; - // add small random amounts to the current rotation to expose more matches. - current_rotation += - <(minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD, - (minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD, - (minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD>; - rotation new_rot = llEuler2Rot(current_rotation); -// log_it("new rot to " + (string)new_rot + " based on " + (string)current_rotation); - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, - (string)target + HUFFWARE_PARM_SEPARATOR + (string)new_rot); -} - -// provides the position on a spiral that has "loops" total loops (counted by -// how many times a line from the center to the outer "radius" is crossed). -// this provides an x and y offset from 0,0 for where the spiral should be if -// one were to walk it in "total_steps" (where the center is step 0). this is -// given for the current "step" one is at. the "start_angle" is the number of -// radians to start at for the spiral, to allow different areas to be traversed. -vector trace_spiral(float loops, float radius, integer total_steps, integer step, - float start_angle) -{ - float total_radians = TWO_PI * loops; - float angle_per_step = total_radians / (float)total_steps; - float distance = radius / (float)total_steps * (float)step; - float current_angle = start_angle + angle_per_step * (float)step; - float current_z = 0; - if (TRAVELLING_UPWARDS) { - // add in the vertical distance for this step. - current_z = MAX_UPWARDS_DISTANCE / total_steps * step; - } - return ; -} - -// this describes the list of matches in local chat. -chat_about_matches() -{ - integer len = llGetListLength(global_matches_found); - if (!len) { - llSay(0, global_target_name + " not found within a distance of " - + (string) (SENSOR_MAX_RANGE + MAX_SPIRAL_RADIUS) + " meters from here."); - return; - } - string addition; - if (len != 1) addition = "es"; - string match_description = (string)len + " match" + addition + " for search " - + "pattern \'" + global_target_name + "\':\n"; - integer i; - // only show a maximum number of matches as we have seeker objects. - if (len > MAX_MATCHES) len = MAX_MATCHES; - for (i = 0; i < len; i++) { - if (llStringLength(match_description) > 350) { - llSay(0, "\n" + match_description); - match_description = ""; - } else if (i != 0) match_description += "\n"; - key targetKey = llList2Key(global_matches_found, i); - vector targetPos = llList2Vector(global_positions_found, i); - match_description += llKey2Name(targetKey) - + " @ " + vector_to_string(targetPos) - + " [" + (string) targetKey + "]"; - } - llSay(0, "\n" + match_description); -} - -// once we accumulate a set of matches, we want to show them off. -show_matches() -{ - llSetRot(llEuler2Rot(ZERO_VECTOR)); // set the object to point at the zero vector. - reset_rod(ALL_SEEKER_ALERT); // clean up any current pointing first. - chat_about_matches(); // say where the matches are. - - integer i; - integer which_locater = 0; // which pointer to use. - // only show a maximum number of matches as we have seeker objects. - integer len = llGetListLength(global_matches_found); - if (len > MAX_MATCHES) len = MAX_MATCHES; - for (i = 0; i < len; i++) { - key targetKey = llList2Key(global_matches_found, i); - vector targetPos = llList2Vector(global_positions_found, i); - point_at_with_particles(which_locater++, targetKey, targetPos); - } -} - -// makes sure that a target we are given is above ground. this used to do a -// lot more checking, but really being above ground is the most important thing -// for us to check at this level of the code. -vector clean_target(vector to_clean) -{ - vector to_return = to_clean; - float ground_height = llGround(to_return - llGetPos()); -//log_it("ground height here: " + (string)ground_height); - - // we'll adjust the basic ground height by adding in the object's height. - list bounds = llGetBoundingBox(llGetKey()); -//hmmm: we have found a bug in opensim in that the bounding box only covers the root prim. -// this needs to be reported. - vector min = llList2Vector(bounds, 0); - vector max = llList2Vector(bounds, 1); -//log_it("calcd: min=" + (string)min + " max=" + (string)max); - -//real math float distance_to_add = llVecDist(<0, 0, min.z>, <0, 0, max.z>) / 2.0; -//below is bogus math for opensim currently. - float distance_to_add = llVecDist(<0, 0, min.z>, <0, 0, max.z>) * 1.1; - -//log_it("distance_to_add: " + (string)distance_to_add); - if (to_return.z - MINIMUM_HEIGHT_ABOVE_GROUND <= ground_height + distance_to_add) { - // patch up the height to be above ground. - to_return.z = ground_height + distance_to_add + MINIMUM_HEIGHT_ABOVE_GROUND; - } - return to_return; -} - -// shows all the matches by pointing our seekers at them and emitting a targeted -// trail of particles. this method should only be called after the final jaunt -// back to home has occurred. -show_off_what_was_found() -{ - // show the positions of what was found. - show_matches(); - llSetTimerEvent(SNOOZE_BEFORE_RESET); - reset_for_next_timer = TRUE; -} - -// stops the device from travelling around and asking for help from the search rods. -integer finish_spiral_traversal() -{ -//log_it("got to finish spiral..."); - stop_sensing(); // turn off all sensors. - - // are we close enough to home to declare victory? - if (llVecDist(llGetPos(), global_home_posn) > MAX_SLACK_DISTANCE) { - if (!tried_jump_homeward) { - // there are enough here; we completed early. - tried_jump_homeward = TRUE; -//log_it("finish spiral sees us as too far from home, jaunting there."); - jaunt_to_target(global_home_posn); - return FALSE; - } else { - // we already tried a jump home. dang, let's try spiraling. -//log_it("finish spiral failed jaunt home, continuing spiral."); - tried_jump_homeward = FALSE; // reset that we tried this. - return TRUE; - } - } - -//log_it("finish spiral success, showing off matches"); - - // this object has done enough spiraling. - llSetTimerEvent(NORMAL_TIMER_INTERVAL); // turn off jump timer. - running_a_search = FALSE; // reset our state since the search is done. - show_off_what_was_found(); - return FALSE; -} - -// our timer handling function; this will move the search engine to the next place on -// the current spiral (or to the start of the next spiral) when it is called. -// if we're not currently running a search, then it will just periodically update the -// sub-prims to make sure they have the latest versions. -handle_timer() -{ - if (!all_setup_finished) { - complain_about_config(!configuration_pending); - return; // should not get here. - } - - if (reset_for_next_timer) { - // this timer intends a reset so we don't just keep pointing forever. - llSay(0, "Timed Out: resetting matches now."); - reset_search(); - return; - } - - if (!running_a_search) { -//log_it("exiting timer since not searching."); - return; - } - -//llSay(0, "next search move!"); - - // make sure we don't allow too many pauses while awaiting a jaunt completion. - if (next_step_snoozes_left-- <= 0) { - log_it("waiting to arrive failed! ran out of snoozes trying to get to " - + (string)last_jaunt_target); - } else if (jaunt_responses_awaited) { - // not ready to do next step yet. - return; - } - if (next_step_snoozes_left < 0) { -//log_it("got below zero in next step snoozes!"); - next_step_snoozes_left = 0; - } - - if (llGetListLength(global_matches_found) < MAX_MATCHES) { - // tell the sensor arms to look for stuff right here. - request_ping(); - } - - // make sure we're not already done finding enough objects. - if (llGetListLength(global_matches_found) >= MAX_MATCHES) retracing_steps = TRUE; - - // check whether we're trying to get home again, rather than moving forward. - if (retracing_steps) { -//log_it("retrace steps in timed move."); - integer keep_going = finish_spiral_traversal(); - if (!keep_going) return; - } - - // see if the object has reached the end of its tether and should report - // home with results. we do this by taking a spiral pass outwards from home - // and a return pass to get back to home. if we've used up all our spiral - // traversals, then it's time to stay home and show the matches. - integer done_with_this_spiral = FALSE; - if (global_current_pass % 2 == 0) { - // even passes are outward bound ones. we're done when we've gotten to TOTAL_STEPS. - if (global_current_step++ > TOTAL_STEPS) done_with_this_spiral = TRUE; - } else { - // odd passes are for returning to home. those are done when they hit zero. - if (global_current_step-- <= 0) done_with_this_spiral = TRUE; - } - - if (done_with_this_spiral) { - // now evaluate whether we're totally done or just need to move to next spiral, - // whether inward or outward. - if (++global_current_pass < 2 * MAX_SPIRAL_TRAVERSALS) { - // just step to the next spiral. -//log_it("moving to next spiral"); - if (global_current_pass % 2 == 0) { - // even passes are outward bound ones. - global_current_step = 0; - // add some different angular rotation to get more matches for this spiral. - spiral_start_angle += TWO_PI / (MAX_SPIRAL_TRAVERSALS + 1); - } else { - // odd passes are for returning to home. - global_current_step = TOTAL_STEPS; - } -//hmmm: not currently resetting that angle for next search. - } else { -//log_it("done with spiral mode, now retracing steps."); - // we finished the search pattern. - retracing_steps = TRUE; - global_current_pass--; // try spiraling back. - global_current_step = TOTAL_STEPS; - return; - } - } - - // normal activity here--pick the next place on the spiral to look for objects. - vector new_posn = trace_spiral(SPIRAL_LOOPS, MAX_SPIRAL_RADIUS, - TOTAL_STEPS, global_current_step, spiral_start_angle); -//log_it("next step " + (string)global_current_step + " to " + (string)new_posn); - // go to that location now, or rather, when the jaunting library gets the message. - vector new_target = clean_target(new_posn + global_home_posn); - jaunt_to_target(new_target); -} - -// makes sure we are ready to run. TRUE is returned if we're good. -integer test_health() -{ - if (!configuration_pending && !all_setup_finished) { - llSay(0, "Configuration is not good yet; retrying."); - return FALSE; - } - return TRUE; -} - -// deals with the jaunter telling us about a completed jump. -process_jaunt_response(string str) -{ - jaunt_responses_awaited--; // one less response being awaited. - if (jaunt_responses_awaited < 0) { - if (DEBUGGING) - log_it("erroneously went below zero for jaunt responses!"); - jaunt_responses_awaited = 0; - } - // unpack the reply. - list parms = llParseString2List(str, [HUFFWARE_PARM_SEPARATOR], []); - last_jaunt_was_success = (integer)llList2String(parms, 0); - vector posn = (vector)llList2String(parms, 1); -//log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); - if (last_jaunt_was_success) { - last_safe_target = posn; - } else { - // we had a problem getting to the expected destination, so go to the last place we were - // completely safely able to reach. we should have no problem returning there, since that's - // where we should have been coming from when we failed to reach the intended destination. -//log_it("bkwd retracing to " + (string)last_safe_target); - jaunt_to_target(last_safe_target); - } -} - -reset_search() -{ - reset_for_next_timer = FALSE; - - llSetTimerEvent(NORMAL_TIMER_INTERVAL); // back to slow timer hits. - reset_rod(ALL_SEEKER_ALERT); // reset the pointers to camber position. - llSetRot(llEuler2Rot(ZERO_VECTOR)); // set the object to point at the zero vector. - - // set the home position to wherever we happen to be right now. - global_home_posn = clean_target(llGetPos()); - llSetPos(global_home_posn); // get us off the ground. - last_safe_target = global_home_posn; - - global_current_step = 0; - global_current_pass = 0; - global_matches_found = []; - global_positions_found = []; - next_step_snoozes_left = 4; // reset to small num, since this is additive. - reset_for_next_timer = FALSE; - running_a_search = FALSE; - tried_jump_homeward = FALSE; - retracing_steps = FALSE; - jaunt_responses_awaited = 0; - current_rotation = <0.0, 0.0, 0.0>; - // fix a global 'constant' that can't be pre-initiatlized in LSL. - SEARCH_ROD_ANGULAR_SWEEP = (PI_BY_TWO / 4.0); - // PI_BY_TWO / 4 is 22.25 degrees, which when turned into a sensor cone - // will be a range of 45 degrees around the zero vector. - -} - -initialize() -{ - llSay(0, "Initializing... this may take a few seconds."); - auto_retire(); - llSleep(0.2); // we ensure part of the claim above by waiting for sub-scripts to start. - request_configuration(""); -} - -// complete the initialization once we know our configuration. -finish_initializing() -{ - all_setup_finished = TRUE; // cancel the time-out checker. - configuration_pending = FALSE; - - // in case we already have some arms, clean up their pointing states. - reset_search(); - // set the position of rotation back to zero. - llSetRot(<0.0, 0.0, 0.0, 1.0>); - // listen for commands from our chat channel. - listening_handle = llListen(HUFF_SEARCH_CHAT_CHANNEL, "", NULL_KEY, ""); - - llSay(0, "Running and ready to search. Touch for more instructions."); - - llSetTimerEvent(NORMAL_TIMER_INTERVAL); -} - -// this points the rods at all angles we possibly can to get the best coverage. -// if show_particles is true, then a demo mode is used that points at the positions -// that the rods are aiming at. -skew_rod_angles(integer show_particles) -{ - reset_rod(ALL_SEEKER_ALERT); - // point everyone straight up for the moment. - float radius = 4.0; // arbitrary distance of target we're aiming at. - integer which_child; - integer total_searchers = llGetNumberOfPrims() - 1; - float angle_per_step = TWO_PI / (float)total_searchers; - // use a circle for the x and y coordinates. - for (which_child = 0; which_child < total_searchers; which_child++) { - vector spinner = < - radius * llCos((float)which_child * angle_per_step), - radius * llSin((float)which_child * angle_per_step), - radius * llCos((float)which_child * angle_per_step / 2.0)>; - vector target_location = llGetPos() + spinner; - if (!show_particles) { - aim_at_position(which_child, target_location); - } else { - point_at_with_particles(which_child, NULL_KEY, target_location); - } - } -} - -// if "noisy" is true, this says out loud that the searchbert is busy. -integer check_if_search_pending(integer noisy) -{ - if (running_a_search) { - if (noisy) llSay(0, "A search is still pending. Please wait for that to finish."); - return TRUE; // still working on a search. - } - return FALSE; // not busy. -} - -// processes a message coming back from a search rod or from the jaunter library. -handle_link_message(integer which, integer num, string msg, key id) -{ - if ( (num == CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE) - && (msg == CARD_CONFIG_RECEIVED_ALERT) ) { - // the first element of the list will still be the notecard name. - consume_configuration(llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], [])); - return; - } - - if ( (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) - && (msg == BUTTON_PUSHED_ALERT) ) { - if (id == ARMS_ARE_GOOD_BUTTON_NAME) { - finish_initializing(); - } else if (id == PROBLEM_WITH_MY_THUMBS_BUTTON_NAME) { - complain_about_config(TRUE); - } - return; - } - - if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { - if (msg == JAUNT_COMMAND) { - process_jaunt_response(id); - } - return; - } - - list parms; - - if ( (num == SEARCHBERT_MENUS_HUFFWARE_ID + REPLY_DISTANCE) && (msg == SM_EVENT_MENU_CLICK) ) { - parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - process_menu_choice(llList2String(parms, 0), llList2String(parms, 2), llList2String(parms, 3), - llList2String(parms, 1)); - return; - } - - if (num != HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. - if (msg != HUFF_SEARCH_MATCH_EVENT) return; // also not for us. - - // make sure this is not already redundant, before doing a costly list search. - if (llGetListLength(global_matches_found) >= MAX_MATCHES) { - // we have enough already. - stop_sensing(); - return; - } -//hmmm: searchbert arms are still backwards. - -//log_it("unpacking " + (string)llStringLength(id) + " byte string."); - // fluff out the list back from the encoded string. - parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("received " + (string)llGetListLength(parms) + " element list from string."); - - while (llGetListLength(parms) > 1) { - // unpack the match that one of our seekers found for us. - key found = (string)llList2String(parms, 0); - if (find_in_list(global_matches_found, found) < 0) { - vector posn = (vector)llList2String(parms, 1); - // that key wasn't already listed, so we can drop it in the list. - global_matches_found += found; - global_positions_found += posn; - } - // truncate the list by removing those two pieces we already handled. - parms = llDeleteSubList(parms, 0, 1); - if (llGetListLength(global_matches_found) >= MAX_MATCHES) { - // we can bail out of the list processing now; we have enough already. - parms = []; - } - } -} - -// uses the configuration item as the value of one of our variables, if we can figure out -// the name involved. -apply_variable_definition(string var, string value) -{ -//log_it("[" + var + "=" + value + "]"); - if (var == "max_matches") { - MAX_MATCHES = (integer)value; - } else if (var == "max_spiral_radius") { - MAX_SPIRAL_RADIUS = (float)value; - } else if (var == "sensor_max_range") { - SENSOR_MAX_RANGE = (float)value; - } else if (var == "huff_search_chat_channel") { - // we have to hook up our ears to the new channel here. - if (listening_handle) llListenRemove(listening_handle); - HUFF_SEARCH_CHAT_CHANNEL = (integer)value; - listening_handle = llListen(HUFF_SEARCH_CHAT_CHANNEL, "", NULL_KEY, ""); - } else if (var == "traverse_lands") { - TRAVERSE_LANDS = (integer)value; - } else if (var == "spiral_loops") { - SPIRAL_LOOPS = (integer)value; - } else if (var == "total_steps") { - TOTAL_STEPS = (integer)value; - } else if (var == "max_spiral_traversals") { - MAX_SPIRAL_TRAVERSALS = (integer)value; - } else if (var == "search_rod_angular_sweep") { - SEARCH_ROD_ANGULAR_SWEEP = (float)value; - } else if (var == "travelling_upwards") { - TRAVELLING_UPWARDS = (integer)value; - } else if (var == "max_upwards_distance") { - MAX_UPWARDS_DISTANCE = (float)value; - } else { - if (DEBUGGING) - log_it("unknown variable '" + var + "' tried to define value = " + value); - } -} - -// we have to consume the configuration in digestible chunks, since the pieces may -// be too large for sending in link messages. -consume_configuration(list config_chunk) -{ - string notecard_name = llList2String(config_chunk, 0); - if (notecard_name == BAD_NOTECARD_TEXT) { - complain_about_config(FALSE); - return; - } else if (notecard_name == FINISHED_READING_NOTECARDS) { - // we're ready to make use of our new configuration now. - if (DEBUGGING) - log_it("Configuration has been read, need validation of limbs."); - configuration_pending = FALSE; // no longer waiting for notecard config. - // configure the menu system to know what channel to talk about. - llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_CONFIGURE_INFO, - wrap_parameters([HUFF_SEARCH_CHAT_CHANNEL])); - // now check our arms to make sure they're all ready. - llMessageLinked(LINK_THIS, BUTTON_PUSHER_HUFFWARE_ID, BUTTON_PUSHED_ALERT, CHECK_ARMS_BUTTON_NAME); - return; - } - - integer sandy; - // scan the configuration items two at a time, but skip the notecard name at slot zero. - for (sandy = 1; sandy < llGetListLength(config_chunk); sandy += 2) { - string var = llList2String(config_chunk, sandy); - string value = llList2String(config_chunk, sandy + 1); - apply_variable_definition(var, value); - } - // clear the list out now that we've eaten its contents. - config_chunk = []; -} - -////////////// - -// sends a message to the "which_seeker" search object. the "parameters" should be a -// string-ized list of parameters. the "command" is the specific action requested. -request_from_seeker(integer which_seeker, string parameters, string command) -{ - integer linkNumber = which_seeker + 2; - if (which_seeker == ALL_SEEKER_ALERT) linkNumber = LINK_ALL_OTHERS; - llMessageLinked(linkNumber, HUFF_SEARCH_POINTER_HUFFWARE_ID, command, parameters); -} - -// aim the specified seeker rod at the object with the key and position. -point_at_with_particles(integer which_seeker, key targetId, vector targetPosition) -{ - list paramList = [targetId, targetPosition]; - request_from_seeker(which_seeker, llDumpList2String(paramList, HUFFWARE_PARM_SEPARATOR), - HUFF_SEARCH_POINT_PARTY); -} - -// stop the particle stream running at the specified search rod. -reset_rod(integer which_seeker) { request_from_seeker(which_seeker, "", HUFF_SEARCH_RESET); } - -// support for reading configuration from notecards... - -string CARD_CONFIGURATOR_SIGNATURE = "#searchbert"; - // the notecard signature we use for our configuration. - -// tries to load a searchbert configuration notecard with the name specified. if it's blank, -// then any config notecard will do. -request_configuration(string notecard_name) -{ - if (DEBUGGING) log_it("have hit request_configuration."); - all_setup_finished = FALSE; - configuration_pending = TRUE; - // figure out whether we have a pre-chosen configuration or not. - if (llStringLength(notecard_name) == 0) { - // start reading the configuration from whatever card. - llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID, - BEGIN_READING_NOTECARD_COMMAND, CARD_CONFIGURATOR_SIGNATURE + HUFFWARE_PARM_SEPARATOR - + wrap_item_list([])); - } else { - // get the specific one they wanted. - if (DEBUGGING) log_it("Reading configuration from notecard: " + notecard_name); - llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID, - READ_PARTICULAR_NOTECARD_COMMAND, CARD_CONFIGURATOR_SIGNATURE + HUFFWARE_PARM_SEPARATOR - + wrap_item_list([]) + HUFFWARE_PARM_SEPARATOR - + notecard_name); - } - - // make sure we complete this in time. - llSetTimerEvent(STARTUP_TIME_ALLOWED); -} - -// this is used when we've totally failed to start up properly. -// if "arms_problem" is true, then the issue is considered to be that the seeker arms -// are missing. -complain_about_config(integer arms_problem) -{ - configuration_pending = FALSE; // it's failed, so we no longer pause for it. - string explanation = "something prevented me from putting my seeker arms back on"; - if (!arms_problem) explanation = "either no notecard had the prefix '" - + CARD_CONFIGURATOR_SIGNATURE + "'\n" - + "or this sim is very busy and timed out"; - // we hated the notecards we found, or there were none, or our arms are still ripped off. - llOwnerSay("Sorry... " + explanation + ".\nI will restart now to try again."); - llSleep(4); - llResetScript(); -} - -// handles when a menu has been clicked on. -process_menu_choice(string menu_name, string av_name, string av_key, string which_choice) -{ - if (menu_name == "main") { - if (which_choice == "Matches") { - // if there are any current matches, describe them again. - if (llGetListLength(global_matches_found)) show_off_what_was_found(); - else llSay(0, "There are no current matches."); - return; - } else if (which_choice == "Reset") { - carefully_reset_search_list(av_key); - return; - } - } -//other things will come... - - if (DEBUGGING) - log_it("non-implemented menu: " + menu_name + "/" + which_choice + " for " + av_name); -} - -// reset the search list and get ready for a new search. -carefully_reset_search_list(key id) -{ - if (check_if_search_pending(FALSE)) { - // only allow reset while running if it's the owner. - if (id != llGetOwner()) { - check_if_search_pending(TRUE); // be noisy now. - return; // we're busy. - } - llOwnerSay("Stopping active search."); - retracing_steps = TRUE; - return; - } - llSay(0, "Resetting matches."); - reset_search(); -} - -////////////// -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -integer debug_num = 0; -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llWhisper(0, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// encases a list of vectors in the expected character for the jaunting library. -string wrap_vector_list(list to_wrap) -{ - integer len = llGetListLength(to_wrap); - integer i; - string to_return; - for (i = 0; i < len; i++) { - if (i > 0) to_return += "|"; - to_return += llList2String(to_wrap, i); - } - return to_return; -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -integer float_precision = 2; // number of digits used when printing floats. - -//hmmm: in hufflets yet??? -string float_to_string(float to_print) -{ - string to_return = (string)to_print; - // find out where the decimal point is in the string. - integer decimal_point_posn = llSubStringIndex(to_return, "."); - if (decimal_point_posn < 0) return to_return; - return llGetSubString(to_return, 0, decimal_point_posn + float_precision); -} - -//hmmm: in hufflets yet??? -string vector_to_string(vector to_print) -{ - string to_return = "<"; - to_return += float_to_string(to_print.x); - to_return += ", "; - to_return += float_to_string(to_print.y); - to_return += ", "; - to_return += float_to_string(to_print.z); - to_return += ">"; - return to_return; -} - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() { initialize(); } - - state_exit() { llSetTimerEvent(0); } - - on_rez(integer parm) { state default; } - - timer() { handle_timer(); } - - link_message(integer which, integer num, string str, key id) - { handle_link_message(which, num, str, id); } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(1.4); // snooze to allow other things to react first. - request_configuration(""); // see if there's a card update. - } - } - - listen(integer chan, string name, key id, string msg) { - if (msg == "#reset") { - carefully_reset_search_list(id); - } else if (is_prefix(msg, "#find ")) { - // needs arms for this trick. - if (!test_health()) state default; - // try to locate the object the user has specified. - if (check_if_search_pending(TRUE)) return; // we're busy. - reset_search(); // clean out prior state. - global_target_name = llDeleteSubString(msg, 0, 5); // Delete "#find " from msg - running_a_search = TRUE; // record that we're searching. - // point all the rods in as many different directions as we can. - skew_rod_angles(FALSE); - // look for any objects near each seeker and in the direction it's pointing. - // we double the arc we might need to try to get more matches. - start_sensing(ALL_SEEKER_ALERT, SENSOR_MAX_RANGE, - SEARCH_ROD_ANGULAR_SWEEP, global_target_name, MAX_MATCHES); - // start stepping through our search spirals. - llSetTimerEvent(FAST_TIMER_INTERVAL); - llSay(0, "Searching for " + global_target_name); - } else if (is_prefix(msg, "#initialize")) { - llResetScript(); - } else if (is_prefix(msg, "#skew")) { - llSetTimerEvent(SNOOZE_BEFORE_RESET); - reset_for_next_timer = TRUE; - skew_rod_angles(TRUE); - } else if (is_prefix(msg, "#channel")) { - HUFF_SEARCH_CHAT_CHANNEL = (integer)llDeleteSubString(msg, 0, 7); - llSay(0, "Changed listening channel to " + (string)HUFF_SEARCH_CHAT_CHANNEL + "."); - llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_CONFIGURE_INFO, - wrap_parameters([HUFF_SEARCH_CHAT_CHANNEL])); - apply_variable_definition("huff_search_chat_channel", (string)HUFF_SEARCH_CHAT_CHANNEL); - } - } - - touch_start(integer num) { - // make sure we have already been set up. - if (!test_health()) state default; - - if (check_if_search_pending(TRUE)) return; - - // send a request to the menu script for the users' clicks... - integer indy; - for (indy = 0; indy < num; indy++) { - // request new menu popup for each av that clicked. - llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_POP_MAIN_MENU_UP, - wrap_parameters([llDetectedName(indy), llDetectedKey(indy)])); - } - } -} - -///////// -// original attributions: -// Special Particle Sensor "Brain" Script -// Written by Christopher Omega -// Tasks: Listen to the owner, Parse the owner's message, Signal individual locators -// to reset, Or point at a certain object within 96 meters of the apparatus. -///////// - -// note by fred huffhines: -// much of this script was originally written by the attributed authors above. however, -// i have spent a ton of time improving this pair of scripts... (the brain and the -// search pointer). i've added pattern matching (rather than needing to know exact -// names), added the spiral search traversal method to improve search behavior and -// get more results, improved the particle streams, and other bits. i just recently added -// configurability from notecards for searchbert options and a menuing system to provide -// help and runtime control over some of the options. wheeee, it's been a lot of fun. -// --fred. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.txt new file mode 100755 index 00000000..a5c10dce --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_brainiac_v46.7.txt @@ -0,0 +1,1248 @@ + +// huffware script: huff-search brainiac, by fred huffhines +// +// this script is one portion of a search system. it is the brain for an object +// that can find nearby objects by a partial name match. this script should be +// located in the root primitive. it also requires an up-to-date jaunting library +// in the same primitive. see the (hopefully) enclosed documentation for more details. +// more implementation notes are stored at the back of the file. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global settings that can be very useful to change... + +integer MAX_MATCHES = 17; + // by default we try to match one object per rod so we can point at them. + +float MAX_SPIRAL_RADIUS = 72.0; + // the farthest that the object will travel from its home while searching. + // this is an important factor in the searchbert's range of vision; the other is + // the sensor range, below. + // ensure that it has access to the lands within this range or it might get stuck. + // you can also set the TRAVERSE_LANDS flag to false to make for safer searches when + // surrounded by a lot of banned lands. + +float SENSOR_MAX_RANGE = 96.0; + // the maximum range that we try to sense objects at. this is distinct from the spiral + // radius because often the range of movement is constrained by land conditions, where + // one might still want a large sensor radius to see as many things as possible in range. + // note though that searches will keep matching the things nearest to them if neither + // the position nor the angle nor object positions have changed. + +float SPIRAL_LOOPS = 7; + // how many loops there are in the spiral. this is measured by how many times the + // spiral cuts across the positive x-axis (that is, the zero angle vector) from + // the center of the spiral to the radius (that is, from <0, 0, 0> to ). + +integer TOTAL_STEPS = 42; + // how many positions within the spiral will the object travel to? the first step + // is step 0, which is the center of the spiral. positions 1 through TOTAL_STEPS + // spiral outward from the zero position, where the distance from the center at + // TOTAL_STEPS should be MAX_SPIRAL_RADIUS or less. + +integer MAX_SPIRAL_TRAVERSALS = 1; + // how many different spirals are we allowed for the same search? this will let the + // search engine cover more ground than with just one spiral, to allow different + // objects to be exposed. + +integer HUFF_SEARCH_CHAT_CHANNEL = 0; + // the channel where the object listens for commands. the default is to use open + // chat for this, but some people may want it more specific. + +// this flag is important to keep as false for wright plaza and other areas with script traps +// (where the perms allow objects to enter, but then their scripts are stopped dead). +integer TRAVERSE_LANDS = FALSE; + // if this is false, then the searchbert will stick to the land owner's land where it started. + // but if it's true, then searchbert will cross into other people's lands too, but if there + // are some weird border or permission conditions about object re-entry or scripts being able + // to run, that can be quite problematic. + +integer TRAVELLING_UPWARDS = FALSE; + // if this is true, the searchbert will climb in the vertical direction also. + +float MAX_UPWARDS_DISTANCE = 30.0; + // the farthest away that the searchbert will fly during an upwards search. + +float SEARCH_ROD_ANGULAR_SWEEP = PI_BY_TWO; + // angular arc of the sensor cone, placeholder. + +////////////// + +// constants that are not configurable in a notecard... + +integer DEBUGGING = FALSE; // set to true to make the script noisier. + +////////////// + +// global constants that aren't as useful to change... + +float MINIMUM_HEIGHT_ABOVE_GROUND = 0.14; + // the closest we allow the searcher to get to the ground. any lower and our search + // rods might be dragging around under ground. + +float FAST_TIMER_INTERVAL = 0.12; + // the time between jumps when we're doing our search spiral. this is the fastest + // the object can spin around its spiral trajectory, but it's more limited than by + // just this number; llSetPrimitiveParams is used for jaunting and it has a delay of + // 0.2 seconds built into it. + +integer NORMAL_TIMER_INTERVAL = 14; + // how frequently we check for things to do, in seconds. + +float STARTUP_TIME_ALLOWED = 50.0; // number of seconds before declaring a timeout. + +integer MAX_STEP_SNOOZES = 81; + // number of timer hits to allow before giving up on jaunt. + +float SNOOZE_BEFORE_RESET = 300; + // number of seconds before a scan will automatically reset. hopefully this is + // enough time for the user to follow the trail to the detected object. + +// imported interfaces below... + +// huff-search pointer API: +////////////// +// do not redefine these constants. +integer HUFF_SEARCH_POINTER_HUFFWARE_ID = 10032; + // the unique id within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string HUFF_SEARCH_RESET = "#reset#"; + // returns the script to its starting state. +string HUFF_SEARCH_POINT_PARTY = "#point_particles#"; + // aim at an object and show a particle stream leading to it. +string HUFF_SEARCH_JUST_POINT = "#just_point#"; + // aim at an object, but don't do any particles. +string HUFF_SEARCH_SENSEI = "#sensor#"; + // set up a sensor request for a search pattern. pings will cause + // the pattern to be sought in names of nearby objects. the parameters are: + // (1) the maximum range for the sensor, (2) the arc angle to use in sensing, + // (3) the search pattern to look for in object names, (4) the maximum number + // of matches to look for. +string HUFF_SEARCH_STOP_SENSE = "#stop_sensor#"; + // turn off the sensor but don't totally reset. +string HUFF_SEARCH_PING = "#ping#"; + // cause the searcher to actively sensor ping the targets. +string HUFF_SEARCH_MATCH_EVENT = "#match#"; + // fired at the root prim when matches are found for the search term. + // the payload is a list of matched item pairs [item key, location]. +////////////// + +// the armature button pushing API. +// (we have subclassed the simple button pushing API for searchbert armature.) +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10029; + // a unique ID within the huffware system for this script. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was pushed. +////////////// +string CHECK_ARMS_BUTTON_NAME = "^checkarms"; + // this is the signal given to the armature script that it should check the + // number of arms present on searchbert. if the number is fine, it will + // push the arms are good button back at the brainiac (using the button + // push api plus reply distance). +string ARMS_ARE_GOOD_BUTTON_NAME = "^goodarmz"; + // the event sent back by the searchbert armature when all arms are ready + // to go. +string PROBLEM_WITH_MY_THUMBS_BUTTON_NAME = "^ouch"; + // a problem was noticed with the number of arms and we could not fix it. + // the brain needs to try reconfiguring again. +////////////// + +// searchbert menus API. +////////////// +// do not redefine these constants. +integer SEARCHBERT_MENUS_HUFFWARE_ID = 10034; + // the unique id within the huffware system for this script. +////////////// +string SM_CONFIGURE_INFO = "#sm-info#"; + // sets important information this script will use, such as (1) the channel for listening. +string SM_POP_MAIN_MENU_UP = "#sm-main#"; + // causes the main menu to be displayed. this requires an avatar name and avatar key for the + // target of the menu. +////////////// +string SM_EVENT_MENU_CLICK = "#sm-clik#"; + // the user has requested a particular menu item that this script cannot fulfill. the + // event is generated back to the client of this script for handling. it will include (1) the + // menu name in question, (2) the item clicked, (3) the avatar name, and (4) the avatar key. +////////////// + +// card configurator link message API: +////////////// +// do not redefine these constants. +integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; + // the unique id within the huffware system for the card configurator script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +string BAD_NOTECARD_TEXT = "*badcrd*"; + // the sign that we hated the notecards we found, or there were none. +string FINISHED_READING_NOTECARDS = "**finished**"; + // the sign that we are done plowing through the card we found. +string BEGIN_READING_NOTECARD_COMMAND = "#read-cfg#"; + // requests that the configurator find a good notecard and read its contents. + // it should send the contents via the alert below. first parm is the signature and + // second is the wrapped list of valid item prefixes. +string READ_PARTICULAR_NOTECARD_COMMAND = "#read-note#"; + // requests that the configurator find a good notecard and read its contents. + // it should send the contents via the alert below. first two parms are the same as + // begin reading notecard, and the third parameter is the name of the specific notecard. +string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; + // this message is sent when the configurator has found some data updates or has finished + // reading the configuration file. +////////////// + +// jaunting library API: +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +//string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +//string REVERSE_VELOCITY_COMMAND = "#reverse#"; + // makes the object reverse its velocity and travel back from whence it came. +//string SET_VELOCITY_COMMAND = "#setvelocity#"; + // makes the velocity equal to the vector passed as the first parameter. +//string JAUNT_UP_COMMAND = "#jauntup#"; +//string JAUNT_DOWN_COMMAND = "#jauntdown#"; + // commands for height adjustment. pass a float for number of meters to move. +//string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a string in jaunt notecard format with vectors. + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// + +// global variables used in the script. + +// configuration variables... +integer all_setup_finished = FALSE; // have we read our configuration yet? +integer configuration_pending = FALSE; // true if the setup process (config and arms) is still going on. +integer listening_handle = 0; // tracks our handle for listening to commands. + +// matching variables... +string global_target_name = ""; // the name of the object being sought. + +list global_matches_found; // a list of keys that match the specified search terms. +list global_positions_found; // matches list of positions for the detected objects. + +// jaunting variables... + +vector global_home_posn; // the location where the search bot is located. +vector last_safe_target; // the last place we jaunted to that was safe. + +integer next_step_snoozes_left; // pauses allowed before deciding jaunt will not respond. + +integer jaunt_responses_awaited = 0; // true when a jaunt is pending. +integer last_jaunt_was_success = FALSE; // result of jaunting received by message. + +vector current_rotation = <0.0, 0.0, 0.0>; + // the current rotation around each axis for object. + +// spiral variables... + +integer global_current_step = 0; // the current position in the search spiral. +float spiral_start_angle = 0.0; // how many radians to offset spiral by for this pass. +integer global_current_pass = 0; // which spiral number are we working on? + +integer tried_jump_homeward = FALSE; + // when retracing to home, this records if we already tried the jump home that should + // come in between the spiral jaunt. + +integer retracing_steps = FALSE; + // this is true when we are trying to get back home after finishing our spirals. + +// object maintenance variables... + +integer reset_for_next_timer = FALSE; // true when next timer hit should do a reset. + +integer running_a_search = FALSE; // true if the object is seeking matches. + +////////////// + +// constants that should not be messed with. + +float MAX_SLACK_DISTANCE = 0.01; // how close we need to be to a target. + +integer ALL_SEEKER_ALERT = -1; // communicates with all search rods. + +integer last_time_ordered_stop_sensing = 0; + // tracks when we last tried to order the search rods to stop sensing matches. + +// jaunting variables... + +vector last_jaunt_target; + // where we're currently headed. this variable is mostly for record keeping, so we want + // to update it whenever we jaunt someplace. + +////////////// + +// main functions for getting work done as the searchbert... + +// pointing that doesn't use particles, but just aims a search rod. +aim_at_position(integer which_seeker, vector targetPosition) { + list paramList = [targetPosition]; + request_from_seeker(which_seeker, llDumpList2String(paramList, + HUFFWARE_PARM_SEPARATOR), HUFF_SEARCH_JUST_POINT); +} + +// tells the rod at "which_seeker" link to do a sensor scan. +start_sensing(integer which_seeker, float max_range, float arc_angle, string search_pattern, + integer matches_sought) +{ + list paramList = [max_range, arc_angle, search_pattern, matches_sought]; + request_from_seeker(which_seeker, llDumpList2String(paramList, + HUFFWARE_PARM_SEPARATOR), HUFF_SEARCH_SENSEI); +} + +// tells all of the seeker search rods to stop sensing matches. +stop_sensing() +{ + // make sure that we are not just blasting this order over and over. + if (llGetUnixTime() != last_time_ordered_stop_sensing) { + last_time_ordered_stop_sensing = llGetUnixTime(); + request_from_seeker(ALL_SEEKER_ALERT, "", HUFF_SEARCH_STOP_SENSE); + } +} + +// tell the seeker arms to find what we asked them about. +request_ping() { request_from_seeker(ALL_SEEKER_ALERT, "", HUFF_SEARCH_PING); } + +////////////// + +// teleports to the vector specified. this invokes a method in the jaunting library +// which will return its result asynchronously. thus we can't just expect that we +// have arrived at the target by the end of this function; we need to get back the +// IPC message in linked_message. +jaunt_to_target(vector target) +{ + if (!TRAVERSE_LANDS) { + // this is an important restriction since we don't want to get trapped in weird + // land perm screwups, like not being able to re-enter the land where we started, + // if that parcel option is set. + if (llGetLandOwnerAt(llGetPos()) != llGetLandOwnerAt(target)) { + return; + } + } + + // reset our snoozer count, since we're doing a new jaunt now. + next_step_snoozes_left += MAX_STEP_SNOOZES; + jaunt_responses_awaited++; + // record the current target. + last_jaunt_target = target; + + float minimum_rod_angle_addition = 0.2; + float maximum_rod_angle_addition = 10.8; + // add small random amounts to the current rotation to expose more matches. + current_rotation += + <(minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD, + (minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD, + (minimum_rod_angle_addition + llFrand(maximum_rod_angle_addition)) * DEG_TO_RAD>; + rotation new_rot = llEuler2Rot(current_rotation); +// log_it("new rot to " + (string)new_rot + " based on " + (string)current_rotation); + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, + (string)target + HUFFWARE_PARM_SEPARATOR + (string)new_rot); +} + +// provides the position on a spiral that has "loops" total loops (counted by +// how many times a line from the center to the outer "radius" is crossed). +// this provides an x and y offset from 0,0 for where the spiral should be if +// one were to walk it in "total_steps" (where the center is step 0). this is +// given for the current "step" one is at. the "start_angle" is the number of +// radians to start at for the spiral, to allow different areas to be traversed. +vector trace_spiral(float loops, float radius, integer total_steps, integer step, + float start_angle) +{ + float total_radians = TWO_PI * loops; + float angle_per_step = total_radians / (float)total_steps; + float distance = radius / (float)total_steps * (float)step; + float current_angle = start_angle + angle_per_step * (float)step; + float current_z = 0; + if (TRAVELLING_UPWARDS) { + // add in the vertical distance for this step. + current_z = MAX_UPWARDS_DISTANCE / total_steps * step; + } + return ; +} + +// this describes the list of matches in local chat. +chat_about_matches() +{ + integer len = llGetListLength(global_matches_found); + if (!len) { + llSay(0, global_target_name + " not found within a distance of " + + (string) (SENSOR_MAX_RANGE + MAX_SPIRAL_RADIUS) + " meters from here."); + return; + } + string addition; + if (len != 1) addition = "es"; + string match_description = (string)len + " match" + addition + " for search " + + "pattern \'" + global_target_name + "\':\n"; + integer i; + // only show a maximum number of matches as we have seeker objects. + if (len > MAX_MATCHES) len = MAX_MATCHES; + for (i = 0; i < len; i++) { + if (llStringLength(match_description) > 350) { + llSay(0, "\n" + match_description); + match_description = ""; + } else if (i != 0) match_description += "\n"; + key targetKey = llList2Key(global_matches_found, i); + vector targetPos = llList2Vector(global_positions_found, i); + match_description += llKey2Name(targetKey) + + " @ " + vector_to_string(targetPos) + + " [" + (string) targetKey + "]"; + } + llSay(0, "\n" + match_description); +} + +// once we accumulate a set of matches, we want to show them off. +show_matches() +{ + llSetRot(llEuler2Rot(ZERO_VECTOR)); // set the object to point at the zero vector. + reset_rod(ALL_SEEKER_ALERT); // clean up any current pointing first. + chat_about_matches(); // say where the matches are. + + integer i; + integer which_locater = 0; // which pointer to use. + // only show a maximum number of matches as we have seeker objects. + integer len = llGetListLength(global_matches_found); + if (len > MAX_MATCHES) len = MAX_MATCHES; + for (i = 0; i < len; i++) { + key targetKey = llList2Key(global_matches_found, i); + vector targetPos = llList2Vector(global_positions_found, i); + point_at_with_particles(which_locater++, targetKey, targetPos); + } +} + +// makes sure that a target we are given is above ground. this used to do a +// lot more checking, but really being above ground is the most important thing +// for us to check at this level of the code. +vector clean_target(vector to_clean) +{ + vector to_return = to_clean; + float ground_height = llGround(to_return - llGetPos()); +//log_it("ground height here: " + (string)ground_height); + + // we'll adjust the basic ground height by adding in the object's height. + list bounds = llGetBoundingBox(llGetKey()); +//hmmm: we have found a bug in opensim in that the bounding box only covers the root prim. +// this needs to be reported. + vector min = llList2Vector(bounds, 0); + vector max = llList2Vector(bounds, 1); +//log_it("calcd: min=" + (string)min + " max=" + (string)max); + +//real math float distance_to_add = llVecDist(<0, 0, min.z>, <0, 0, max.z>) / 2.0; +//below is bogus math for opensim currently. + float distance_to_add = llVecDist(<0, 0, min.z>, <0, 0, max.z>) * 1.1; + +//log_it("distance_to_add: " + (string)distance_to_add); + if (to_return.z - MINIMUM_HEIGHT_ABOVE_GROUND <= ground_height + distance_to_add) { + // patch up the height to be above ground. + to_return.z = ground_height + distance_to_add + MINIMUM_HEIGHT_ABOVE_GROUND; + } + return to_return; +} + +// shows all the matches by pointing our seekers at them and emitting a targeted +// trail of particles. this method should only be called after the final jaunt +// back to home has occurred. +show_off_what_was_found() +{ + // show the positions of what was found. + show_matches(); + llSetTimerEvent(SNOOZE_BEFORE_RESET); + reset_for_next_timer = TRUE; +} + +// stops the device from travelling around and asking for help from the search rods. +integer finish_spiral_traversal() +{ +//log_it("got to finish spiral..."); + stop_sensing(); // turn off all sensors. + + // are we close enough to home to declare victory? + if (llVecDist(llGetPos(), global_home_posn) > MAX_SLACK_DISTANCE) { + if (!tried_jump_homeward) { + // there are enough here; we completed early. + tried_jump_homeward = TRUE; +//log_it("finish spiral sees us as too far from home, jaunting there."); + jaunt_to_target(global_home_posn); + return FALSE; + } else { + // we already tried a jump home. dang, let's try spiraling. +//log_it("finish spiral failed jaunt home, continuing spiral."); + tried_jump_homeward = FALSE; // reset that we tried this. + return TRUE; + } + } + +//log_it("finish spiral success, showing off matches"); + + // this object has done enough spiraling. + llSetTimerEvent(NORMAL_TIMER_INTERVAL); // turn off jump timer. + running_a_search = FALSE; // reset our state since the search is done. + show_off_what_was_found(); + return FALSE; +} + +// our timer handling function; this will move the search engine to the next place on +// the current spiral (or to the start of the next spiral) when it is called. +// if we're not currently running a search, then it will just periodically update the +// sub-prims to make sure they have the latest versions. +handle_timer() +{ + if (!all_setup_finished) { + complain_about_config(!configuration_pending); + return; // should not get here. + } + + if (reset_for_next_timer) { + // this timer intends a reset so we don't just keep pointing forever. + llSay(0, "Timed Out: resetting matches now."); + reset_search(); + return; + } + + if (!running_a_search) { +//log_it("exiting timer since not searching."); + return; + } + +//llSay(0, "next search move!"); + + // make sure we don't allow too many pauses while awaiting a jaunt completion. + if (next_step_snoozes_left-- <= 0) { + log_it("waiting to arrive failed! ran out of snoozes trying to get to " + + (string)last_jaunt_target); + } else if (jaunt_responses_awaited) { + // not ready to do next step yet. + return; + } + if (next_step_snoozes_left < 0) { +//log_it("got below zero in next step snoozes!"); + next_step_snoozes_left = 0; + } + + if (llGetListLength(global_matches_found) < MAX_MATCHES) { + // tell the sensor arms to look for stuff right here. + request_ping(); + } + + // make sure we're not already done finding enough objects. + if (llGetListLength(global_matches_found) >= MAX_MATCHES) retracing_steps = TRUE; + + // check whether we're trying to get home again, rather than moving forward. + if (retracing_steps) { +//log_it("retrace steps in timed move."); + integer keep_going = finish_spiral_traversal(); + if (!keep_going) return; + } + + // see if the object has reached the end of its tether and should report + // home with results. we do this by taking a spiral pass outwards from home + // and a return pass to get back to home. if we've used up all our spiral + // traversals, then it's time to stay home and show the matches. + integer done_with_this_spiral = FALSE; + if (global_current_pass % 2 == 0) { + // even passes are outward bound ones. we're done when we've gotten to TOTAL_STEPS. + if (global_current_step++ > TOTAL_STEPS) done_with_this_spiral = TRUE; + } else { + // odd passes are for returning to home. those are done when they hit zero. + if (global_current_step-- <= 0) done_with_this_spiral = TRUE; + } + + if (done_with_this_spiral) { + // now evaluate whether we're totally done or just need to move to next spiral, + // whether inward or outward. + if (++global_current_pass < 2 * MAX_SPIRAL_TRAVERSALS) { + // just step to the next spiral. +//log_it("moving to next spiral"); + if (global_current_pass % 2 == 0) { + // even passes are outward bound ones. + global_current_step = 0; + // add some different angular rotation to get more matches for this spiral. + spiral_start_angle += TWO_PI / (MAX_SPIRAL_TRAVERSALS + 1); + } else { + // odd passes are for returning to home. + global_current_step = TOTAL_STEPS; + } +//hmmm: not currently resetting that angle for next search. + } else { +//log_it("done with spiral mode, now retracing steps."); + // we finished the search pattern. + retracing_steps = TRUE; + global_current_pass--; // try spiraling back. + global_current_step = TOTAL_STEPS; + return; + } + } + + // normal activity here--pick the next place on the spiral to look for objects. + vector new_posn = trace_spiral(SPIRAL_LOOPS, MAX_SPIRAL_RADIUS, + TOTAL_STEPS, global_current_step, spiral_start_angle); +//log_it("next step " + (string)global_current_step + " to " + (string)new_posn); + // go to that location now, or rather, when the jaunting library gets the message. + vector new_target = clean_target(new_posn + global_home_posn); + jaunt_to_target(new_target); +} + +// makes sure we are ready to run. TRUE is returned if we're good. +integer test_health() +{ + if (!configuration_pending && !all_setup_finished) { + llSay(0, "Configuration is not good yet; retrying."); + return FALSE; + } + return TRUE; +} + +// deals with the jaunter telling us about a completed jump. +process_jaunt_response(string str) +{ + jaunt_responses_awaited--; // one less response being awaited. + if (jaunt_responses_awaited < 0) { + if (DEBUGGING) + log_it("erroneously went below zero for jaunt responses!"); + jaunt_responses_awaited = 0; + } + // unpack the reply. + list parms = llParseString2List(str, [HUFFWARE_PARM_SEPARATOR], []); + last_jaunt_was_success = (integer)llList2String(parms, 0); + vector posn = (vector)llList2String(parms, 1); +//log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); + if (last_jaunt_was_success) { + last_safe_target = posn; + } else { + // we had a problem getting to the expected destination, so go to the last place we were + // completely safely able to reach. we should have no problem returning there, since that's + // where we should have been coming from when we failed to reach the intended destination. +//log_it("bkwd retracing to " + (string)last_safe_target); + jaunt_to_target(last_safe_target); + } +} + +reset_search() +{ + reset_for_next_timer = FALSE; + + llSetTimerEvent(NORMAL_TIMER_INTERVAL); // back to slow timer hits. + reset_rod(ALL_SEEKER_ALERT); // reset the pointers to camber position. + llSetRot(llEuler2Rot(ZERO_VECTOR)); // set the object to point at the zero vector. + + // set the home position to wherever we happen to be right now. + global_home_posn = clean_target(llGetPos()); + llSetPos(global_home_posn); // get us off the ground. + last_safe_target = global_home_posn; + + global_current_step = 0; + global_current_pass = 0; + global_matches_found = []; + global_positions_found = []; + next_step_snoozes_left = 4; // reset to small num, since this is additive. + reset_for_next_timer = FALSE; + running_a_search = FALSE; + tried_jump_homeward = FALSE; + retracing_steps = FALSE; + jaunt_responses_awaited = 0; + current_rotation = <0.0, 0.0, 0.0>; + // fix a global 'constant' that can't be pre-initiatlized in LSL. + SEARCH_ROD_ANGULAR_SWEEP = (PI_BY_TWO / 4.0); + // PI_BY_TWO / 4 is 22.25 degrees, which when turned into a sensor cone + // will be a range of 45 degrees around the zero vector. + +} + +initialize() +{ + llSay(0, "Initializing... this may take a few seconds."); + auto_retire(); + llSleep(0.2); // we ensure part of the claim above by waiting for sub-scripts to start. + request_configuration(""); +} + +// complete the initialization once we know our configuration. +finish_initializing() +{ + all_setup_finished = TRUE; // cancel the time-out checker. + configuration_pending = FALSE; + + // in case we already have some arms, clean up their pointing states. + reset_search(); + // set the position of rotation back to zero. + llSetRot(<0.0, 0.0, 0.0, 1.0>); + // listen for commands from our chat channel. + listening_handle = llListen(HUFF_SEARCH_CHAT_CHANNEL, "", NULL_KEY, ""); + + llSay(0, "Running and ready to search. Touch for more instructions."); + + llSetTimerEvent(NORMAL_TIMER_INTERVAL); +} + +// this points the rods at all angles we possibly can to get the best coverage. +// if show_particles is true, then a demo mode is used that points at the positions +// that the rods are aiming at. +skew_rod_angles(integer show_particles) +{ + reset_rod(ALL_SEEKER_ALERT); + // point everyone straight up for the moment. + float radius = 4.0; // arbitrary distance of target we're aiming at. + integer which_child; + integer total_searchers = llGetNumberOfPrims() - 1; + float angle_per_step = TWO_PI / (float)total_searchers; + // use a circle for the x and y coordinates. + for (which_child = 0; which_child < total_searchers; which_child++) { + vector spinner = < + radius * llCos((float)which_child * angle_per_step), + radius * llSin((float)which_child * angle_per_step), + radius * llCos((float)which_child * angle_per_step / 2.0)>; + vector target_location = llGetPos() + spinner; + if (!show_particles) { + aim_at_position(which_child, target_location); + } else { + point_at_with_particles(which_child, NULL_KEY, target_location); + } + } +} + +// if "noisy" is true, this says out loud that the searchbert is busy. +integer check_if_search_pending(integer noisy) +{ + if (running_a_search) { + if (noisy) llSay(0, "A search is still pending. Please wait for that to finish."); + return TRUE; // still working on a search. + } + return FALSE; // not busy. +} + +// processes a message coming back from a search rod or from the jaunter library. +handle_link_message(integer which, integer num, string msg, key id) +{ + if ( (num == CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE) + && (msg == CARD_CONFIG_RECEIVED_ALERT) ) { + // the first element of the list will still be the notecard name. + consume_configuration(llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], [])); + return; + } + + if ( (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) + && (msg == BUTTON_PUSHED_ALERT) ) { + if (id == ARMS_ARE_GOOD_BUTTON_NAME) { + finish_initializing(); + } else if (id == PROBLEM_WITH_MY_THUMBS_BUTTON_NAME) { + complain_about_config(TRUE); + } + return; + } + + if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { + if (msg == JAUNT_COMMAND) { + process_jaunt_response(id); + } + return; + } + + list parms; + + if ( (num == SEARCHBERT_MENUS_HUFFWARE_ID + REPLY_DISTANCE) && (msg == SM_EVENT_MENU_CLICK) ) { + parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + process_menu_choice(llList2String(parms, 0), llList2String(parms, 2), llList2String(parms, 3), + llList2String(parms, 1)); + return; + } + + if (num != HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. + if (msg != HUFF_SEARCH_MATCH_EVENT) return; // also not for us. + + // make sure this is not already redundant, before doing a costly list search. + if (llGetListLength(global_matches_found) >= MAX_MATCHES) { + // we have enough already. + stop_sensing(); + return; + } +//hmmm: searchbert arms are still backwards. + +//log_it("unpacking " + (string)llStringLength(id) + " byte string."); + // fluff out the list back from the encoded string. + parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("received " + (string)llGetListLength(parms) + " element list from string."); + + while (llGetListLength(parms) > 1) { + // unpack the match that one of our seekers found for us. + key found = (string)llList2String(parms, 0); + if (find_in_list(global_matches_found, found) < 0) { + vector posn = (vector)llList2String(parms, 1); + // that key wasn't already listed, so we can drop it in the list. + global_matches_found += found; + global_positions_found += posn; + } + // truncate the list by removing those two pieces we already handled. + parms = llDeleteSubList(parms, 0, 1); + if (llGetListLength(global_matches_found) >= MAX_MATCHES) { + // we can bail out of the list processing now; we have enough already. + parms = []; + } + } +} + +// uses the configuration item as the value of one of our variables, if we can figure out +// the name involved. +apply_variable_definition(string var, string value) +{ +//log_it("[" + var + "=" + value + "]"); + if (var == "max_matches") { + MAX_MATCHES = (integer)value; + } else if (var == "max_spiral_radius") { + MAX_SPIRAL_RADIUS = (float)value; + } else if (var == "sensor_max_range") { + SENSOR_MAX_RANGE = (float)value; + } else if (var == "huff_search_chat_channel") { + // we have to hook up our ears to the new channel here. + if (listening_handle) llListenRemove(listening_handle); + HUFF_SEARCH_CHAT_CHANNEL = (integer)value; + listening_handle = llListen(HUFF_SEARCH_CHAT_CHANNEL, "", NULL_KEY, ""); + } else if (var == "traverse_lands") { + TRAVERSE_LANDS = (integer)value; + } else if (var == "spiral_loops") { + SPIRAL_LOOPS = (integer)value; + } else if (var == "total_steps") { + TOTAL_STEPS = (integer)value; + } else if (var == "max_spiral_traversals") { + MAX_SPIRAL_TRAVERSALS = (integer)value; + } else if (var == "search_rod_angular_sweep") { + SEARCH_ROD_ANGULAR_SWEEP = (float)value; + } else if (var == "travelling_upwards") { + TRAVELLING_UPWARDS = (integer)value; + } else if (var == "max_upwards_distance") { + MAX_UPWARDS_DISTANCE = (float)value; + } else { + if (DEBUGGING) + log_it("unknown variable '" + var + "' tried to define value = " + value); + } +} + +// we have to consume the configuration in digestible chunks, since the pieces may +// be too large for sending in link messages. +consume_configuration(list config_chunk) +{ + string notecard_name = llList2String(config_chunk, 0); + if (notecard_name == BAD_NOTECARD_TEXT) { + complain_about_config(FALSE); + return; + } else if (notecard_name == FINISHED_READING_NOTECARDS) { + // we're ready to make use of our new configuration now. + if (DEBUGGING) + log_it("Configuration has been read, need validation of limbs."); + configuration_pending = FALSE; // no longer waiting for notecard config. + // configure the menu system to know what channel to talk about. + llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_CONFIGURE_INFO, + wrap_parameters([HUFF_SEARCH_CHAT_CHANNEL])); + // now check our arms to make sure they're all ready. + llMessageLinked(LINK_THIS, BUTTON_PUSHER_HUFFWARE_ID, BUTTON_PUSHED_ALERT, CHECK_ARMS_BUTTON_NAME); + return; + } + + integer sandy; + // scan the configuration items two at a time, but skip the notecard name at slot zero. + for (sandy = 1; sandy < llGetListLength(config_chunk); sandy += 2) { + string var = llList2String(config_chunk, sandy); + string value = llList2String(config_chunk, sandy + 1); + apply_variable_definition(var, value); + } + // clear the list out now that we've eaten its contents. + config_chunk = []; +} + +////////////// + +// sends a message to the "which_seeker" search object. the "parameters" should be a +// string-ized list of parameters. the "command" is the specific action requested. +request_from_seeker(integer which_seeker, string parameters, string command) +{ + integer linkNumber = which_seeker + 2; + if (which_seeker == ALL_SEEKER_ALERT) linkNumber = LINK_ALL_OTHERS; + llMessageLinked(linkNumber, HUFF_SEARCH_POINTER_HUFFWARE_ID, command, parameters); +} + +// aim the specified seeker rod at the object with the key and position. +point_at_with_particles(integer which_seeker, key targetId, vector targetPosition) +{ + list paramList = [targetId, targetPosition]; + request_from_seeker(which_seeker, llDumpList2String(paramList, HUFFWARE_PARM_SEPARATOR), + HUFF_SEARCH_POINT_PARTY); +} + +// stop the particle stream running at the specified search rod. +reset_rod(integer which_seeker) { request_from_seeker(which_seeker, "", HUFF_SEARCH_RESET); } + +// support for reading configuration from notecards... + +string CARD_CONFIGURATOR_SIGNATURE = "#searchbert"; + // the notecard signature we use for our configuration. + +// tries to load a searchbert configuration notecard with the name specified. if it's blank, +// then any config notecard will do. +request_configuration(string notecard_name) +{ + if (DEBUGGING) log_it("have hit request_configuration."); + all_setup_finished = FALSE; + configuration_pending = TRUE; + // figure out whether we have a pre-chosen configuration or not. + if (llStringLength(notecard_name) == 0) { + // start reading the configuration from whatever card. + llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID, + BEGIN_READING_NOTECARD_COMMAND, CARD_CONFIGURATOR_SIGNATURE + HUFFWARE_PARM_SEPARATOR + + wrap_item_list([])); + } else { + // get the specific one they wanted. + if (DEBUGGING) log_it("Reading configuration from notecard: " + notecard_name); + llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID, + READ_PARTICULAR_NOTECARD_COMMAND, CARD_CONFIGURATOR_SIGNATURE + HUFFWARE_PARM_SEPARATOR + + wrap_item_list([]) + HUFFWARE_PARM_SEPARATOR + + notecard_name); + } + + // make sure we complete this in time. + llSetTimerEvent(STARTUP_TIME_ALLOWED); +} + +// this is used when we've totally failed to start up properly. +// if "arms_problem" is true, then the issue is considered to be that the seeker arms +// are missing. +complain_about_config(integer arms_problem) +{ + configuration_pending = FALSE; // it's failed, so we no longer pause for it. + string explanation = "something prevented me from putting my seeker arms back on"; + if (!arms_problem) explanation = "either no notecard had the prefix '" + + CARD_CONFIGURATOR_SIGNATURE + "'\n" + + "or this sim is very busy and timed out"; + // we hated the notecards we found, or there were none, or our arms are still ripped off. + llOwnerSay("Sorry... " + explanation + ".\nI will restart now to try again."); + llSleep(4); + llResetScript(); +} + +// handles when a menu has been clicked on. +process_menu_choice(string menu_name, string av_name, string av_key, string which_choice) +{ + if (menu_name == "main") { + if (which_choice == "Matches") { + // if there are any current matches, describe them again. + if (llGetListLength(global_matches_found)) show_off_what_was_found(); + else llSay(0, "There are no current matches."); + return; + } else if (which_choice == "Reset") { + carefully_reset_search_list(av_key); + return; + } + } +//other things will come... + + if (DEBUGGING) + log_it("non-implemented menu: " + menu_name + "/" + which_choice + " for " + av_name); +} + +// reset the search list and get ready for a new search. +carefully_reset_search_list(key id) +{ + if (check_if_search_pending(FALSE)) { + // only allow reset while running if it's the owner. + if (id != llGetOwner()) { + check_if_search_pending(TRUE); // be noisy now. + return; // we're busy. + } + llOwnerSay("Stopping active search."); + retracing_steps = TRUE; + return; + } + llSay(0, "Resetting matches."); + reset_search(); +} + +////////////// +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +integer debug_num = 0; +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llWhisper(0, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// encases a list of vectors in the expected character for the jaunting library. +string wrap_vector_list(list to_wrap) +{ + integer len = llGetListLength(to_wrap); + integer i; + string to_return; + for (i = 0; i < len; i++) { + if (i > 0) to_return += "|"; + to_return += llList2String(to_wrap, i); + } + return to_return; +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +integer float_precision = 2; // number of digits used when printing floats. + +//hmmm: in hufflets yet??? +string float_to_string(float to_print) +{ + string to_return = (string)to_print; + // find out where the decimal point is in the string. + integer decimal_point_posn = llSubStringIndex(to_return, "."); + if (decimal_point_posn < 0) return to_return; + return llGetSubString(to_return, 0, decimal_point_posn + float_precision); +} + +//hmmm: in hufflets yet??? +string vector_to_string(vector to_print) +{ + string to_return = "<"; + to_return += float_to_string(to_print.x); + to_return += ", "; + to_return += float_to_string(to_print.y); + to_return += ", "; + to_return += float_to_string(to_print.z); + to_return += ">"; + return to_return; +} + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() { initialize(); } + + state_exit() { llSetTimerEvent(0); } + + on_rez(integer parm) { state default; } + + timer() { handle_timer(); } + + link_message(integer which, integer num, string str, key id) + { handle_link_message(which, num, str, id); } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(1.4); // snooze to allow other things to react first. + request_configuration(""); // see if there's a card update. + } + } + + listen(integer chan, string name, key id, string msg) { + if (msg == "#reset") { + carefully_reset_search_list(id); + } else if (is_prefix(msg, "#find ")) { + // needs arms for this trick. + if (!test_health()) state default; + // try to locate the object the user has specified. + if (check_if_search_pending(TRUE)) return; // we're busy. + reset_search(); // clean out prior state. + global_target_name = llDeleteSubString(msg, 0, 5); // Delete "#find " from msg + running_a_search = TRUE; // record that we're searching. + // point all the rods in as many different directions as we can. + skew_rod_angles(FALSE); + // look for any objects near each seeker and in the direction it's pointing. + // we double the arc we might need to try to get more matches. + start_sensing(ALL_SEEKER_ALERT, SENSOR_MAX_RANGE, + SEARCH_ROD_ANGULAR_SWEEP, global_target_name, MAX_MATCHES); + // start stepping through our search spirals. + llSetTimerEvent(FAST_TIMER_INTERVAL); + llSay(0, "Searching for " + global_target_name); + } else if (is_prefix(msg, "#initialize")) { + llResetScript(); + } else if (is_prefix(msg, "#skew")) { + llSetTimerEvent(SNOOZE_BEFORE_RESET); + reset_for_next_timer = TRUE; + skew_rod_angles(TRUE); + } else if (is_prefix(msg, "#channel")) { + HUFF_SEARCH_CHAT_CHANNEL = (integer)llDeleteSubString(msg, 0, 7); + llSay(0, "Changed listening channel to " + (string)HUFF_SEARCH_CHAT_CHANNEL + "."); + llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_CONFIGURE_INFO, + wrap_parameters([HUFF_SEARCH_CHAT_CHANNEL])); + apply_variable_definition("huff_search_chat_channel", (string)HUFF_SEARCH_CHAT_CHANNEL); + } + } + + touch_start(integer num) { + // make sure we have already been set up. + if (!test_health()) state default; + + if (check_if_search_pending(TRUE)) return; + + // send a request to the menu script for the users' clicks... + integer indy; + for (indy = 0; indy < num; indy++) { + // request new menu popup for each av that clicked. + llMessageLinked(LINK_THIS, SEARCHBERT_MENUS_HUFFWARE_ID, SM_POP_MAIN_MENU_UP, + wrap_parameters([llDetectedName(indy), llDetectedKey(indy)])); + } + } +} + +///////// +// original attributions: +// Special Particle Sensor "Brain" Script +// Written by Christopher Omega +// Tasks: Listen to the owner, Parse the owner's message, Signal individual locators +// to reset, Or point at a certain object within 96 meters of the apparatus. +///////// + +// note by fred huffhines: +// much of this script was originally written by the attributed authors above. however, +// i have spent a ton of time improving this pair of scripts... (the brain and the +// search pointer). i've added pattern matching (rather than needing to know exact +// names), added the spiral search traversal method to improve search behavior and +// get more results, improved the particle streams, and other bits. i just recently added +// configurability from notecards for searchbert options and a menuing system to provide +// help and runtime control over some of the options. wheeee, it's been a lot of fun. +// --fred. diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.lsl deleted file mode 100755 index 8cdeb3f4..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.lsl +++ /dev/null @@ -1,574 +0,0 @@ - -// huffware script: huff-search pointer, by fred huffhines -// -// note: parts of this script were written by the attributed authors below. -// -// this script is one portion of a search system. the pointer is meant to be in a child prim. -// it is told what to point at by the root prim. -// -// the newer version of this supports a search command that locates objects in the -// direction specified. -// -// original attributions: started life as "Particle Script 0.4, Created by Ama Omega, 3-7-2004" -// some code in this script is also from: Christopher Omega. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// huff-search pointer API: -////////////// -// do not redefine these constants. -integer HUFF_SEARCH_POINTER_HUFFWARE_ID = 10032; - // the unique id within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string HUFF_SEARCH_RESET = "#reset#"; - // returns the script to its starting state. -string HUFF_SEARCH_POINT_PARTY = "#point_particles#"; - // aim at an object and show a particle stream leading to it. -string HUFF_SEARCH_JUST_POINT = "#just_point#"; - // aim at an object, but don't do any particles. -string HUFF_SEARCH_SENSEI = "#sensor#"; - // set up a sensor request for a search pattern. pings will cause - // the pattern to be sought in names of nearby objects. the parameters are: - // (1) the maximum range for the sensor, (2) the arc angle to use in sensing, - // (3) the search pattern to look for in object names, (4) the maximum number - // of matches to look for. -string HUFF_SEARCH_STOP_SENSE = "#stop_sensor#"; - // turn off the sensor but don't totally reset. -string HUFF_SEARCH_PING = "#ping#"; - // cause the searcher to actively sensor ping the targets. -string HUFF_SEARCH_MATCH_EVENT = "#match#"; - // fired at the root prim when matches are found for the search term. - // the payload is a list of matched item pairs [item key, location]. -////////////// - -// global variables... - -// SENSOR_TYPE_ALL: a constant that tells the sensor to look for (ACTIVE|PASSIVE|AGENT). -integer SENSOR_TYPE_ALL = 7; - -// AXIS_* constants, represent the unit vector 1 unit on the specified axis. -vector AXIS_UP = <0.0, 0.0, 1.0>; -vector AXIS_LEFT = <0.0, 1.0, 0.0>; -vector AXIS_FWD = <1.0, 0.0, 0.0>; - -integer MAX_LIST_LEN = 17; - // the maximum matches we hang onto, to avoid using too many resources. - // this should be no longer than the number of search arms created by - // the brain script, but it can be less if fewer matches are needed. - -/////////////// - -// global variables... - -string search_pattern; - // the pattern that we are hoping to find from our sensor hits. - -list global_matches_found; - // a list of keys that match the specified search terms. - -integer our_link_number = 0; - // set to the number for our link if we ever see ourselves as a link greater than 1. - // this only happens when we have been made a sub-prim and are definitely not the root prim, - // so it is our key for whether the prim should die if it becomes unlinked. - -// Mask Flags - set to TRUE to enable -integer glow = TRUE; // Make the particles glow -integer bounce = FALSE; // Make particles bounce on Z plane of object -integer interpColor = TRUE; // Go from start to end color -integer interpSize = TRUE; // Go from start to end size -integer wind = FALSE; // Particles effected by wind -integer followSource = TRUE; // Particles follow the source -integer followVel = TRUE; // Particles turn to velocity direction - -// Choose a pattern from the following: -// PSYS_SRC_PATTERN_EXPLODE -// PSYS_SRC_PATTERN_DROP -// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY -// PSYS_SRC_PATTERN_ANGLE_CONE -// PSYS_SRC_PATTERN_ANGLE -integer pattern = PSYS_SRC_PATTERN_DROP; - -// Select a target for particles to go towards -// "" for no target, "owner" will follow object owner -// and "self" will target this object -// or put the key of an object for particles to go to -key target = "owner"; - -// useful particle parameters. -float age = 14; // Life of each particle -float startAlpha = 1.0; // Start alpha (transparency) value -float endAlpha = 1.0; // End alpha (transparency) value -vector startSize = <0.2, 0.2, 0.2>; // Start size of particles -vector endSize = <0.8, 0.8, 0.8>; // End size of particles (if interpSize == TRUE) - -// colors are now assigned dynamically per search. -vector startColor; // Start color of particles -vector endColor; // End color of particles (if interpColor == TRUE) - -// unused particle parameters. -float maxSpeed = 2; // Max speed each particle is spit out at -float minSpeed = 2; // Min speed each particle is spit out at -string texture; // Texture used for particles, default used if blank -vector push = <0.0, 0.0, 0.0>; // Force pushed on particles - -// System parameters -float rate = 0.08; // burst rate to emit particles, zero is fastest. -float radius = 1; // Radius to emit particles for BURST pattern -integer count = 1; // How many particles to emit per BURST -float outerAngle = 1.54; // Outer angle for all ANGLE patterns -float innerAngle = 1.55; // Inner angle for all ANGLE patterns -vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source -float life = 0; // Life in seconds for the system to make particles - -// Script variables -integer precision = 2; //Adjust the precision of the generated list. - -integer running_particles = FALSE; // is the particle system running? - -///integer start_parm; // set from the on_rez parameter. - -string float2String(float in) -{ - return llGetSubString((string)in, 0, precision - 7); -} - -create_particles() -{ - list system_content; - integer flags = 0; - if (target == "owner") target = llGetOwner(); - if (target == "self") target = llGetKey(); - if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK; - if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK; - if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK; - if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK; - if (wind) flags = flags | PSYS_PART_WIND_MASK; - if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK; - if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK; - if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK; - - // original recipe searchbert pointer... -// startColor = <0.92, 0.79412, 0.66863>; // Start color of particles -// endColor = <0.0, 1.0, 0.7>; // End color of particles (if interpColor == TRUE) - // new randomized version for colors. the current aesthetic here is to start - // with a relatively dark color and end on a relatively light color. - startColor = ; - endColor = ; - - system_content = [ PSYS_PART_MAX_AGE, age, - PSYS_PART_FLAGS,flags, - PSYS_PART_START_COLOR, startColor, - PSYS_PART_END_COLOR, endColor, - PSYS_PART_START_SCALE, startSize, - PSYS_PART_END_SCALE, endSize, - PSYS_SRC_PATTERN, pattern, - PSYS_SRC_BURST_RATE, rate, - PSYS_SRC_ACCEL, push, - PSYS_SRC_BURST_PART_COUNT, count, - PSYS_SRC_BURST_RADIUS, radius, - PSYS_SRC_BURST_SPEED_MIN, minSpeed, - PSYS_SRC_BURST_SPEED_MAX, maxSpeed, -// PSYS_SRC_INNERANGLE,innerAngle, -// PSYS_SRC_OUTERANGLE,outerAngle, - PSYS_SRC_OMEGA, omega, - PSYS_SRC_MAX_AGE, life, -// PSYS_SRC_TEXTURE, texture, - PSYS_PART_START_ALPHA, startAlpha, - PSYS_PART_END_ALPHA, endAlpha - ]; - if (target != NULL_KEY) { - system_content += [ PSYS_SRC_TARGET_KEY, target ]; - } - - llParticleSystem(system_content); - running_particles = TRUE; -} - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -/////////////// - -// SetLocalRot -// In a linked set, points a child object to the rotation. -// @param rot The rotation to rotate to. -SetLocalRot(rotation rot) -{ - if(llGetLinkNumber() > 1) - { - rotation locRot = llGetLocalRot(); - locRot.s = -locRot.s; // Invert local rot. - - rotation parentRot = locRot * llGetRot(); - parentRot.s = -parentRot.s; // Invert parent's rot. - - llSetLocalRot(rot * parentRot); - } -} - -// Gets the rotation to point the specified axis at the specified position. -// @param axis The axis to point. Easiest to just use an AXIS_* constant. -// @param target The target, in region-local coordinates, to point the axis at. -// @return The rotation necessary to point axis at target. -rotation getRotToPointAxisAt(vector axis, vector target) -{ - return llGetRot() * llRotBetween(axis * llGetRot(), target - llGetPos()); -} - -// aims in the direction of the target. -aim_at(vector targetPos) -{ - SetLocalRot(getRotToPointAxisAt(AXIS_UP, targetPos)); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// point_at -// Points up axis at targetPos, and emits a particle system at targetKey. -// @param targetKey The UUID of the target to emit particles to. -// @param targetPos The poaition of the target in region-local coordinates. -point_at(key targetKey, vector targetPos) -{ - aim_at(targetPos); - target = targetKey; - create_particles(); -} - -// variables that are established by a search and used periodically in the timer. -float max_range = 0.0; -float arc_angle = 0.0; -float sensor_interval = 0.0; - -reset_sensors() -{ - radius = 1; - llSetTimerEvent(0.0); - llSensorRemove(); -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// returns a number at most maximum and at least minimum. -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// makes sure that we record the current link number if it's higher than 1; this -// is how we know that we're a sub-prim. -record_link_num_if_useful() -{ - if (llGetLinkNumber() > 1) our_link_number = llGetLinkNumber(); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - llParticleSystem([]); - running_particles = FALSE; - SetLocalRot(<0.0, 0.0, 0.0, 1.0>); - global_matches_found = []; - record_link_num_if_useful(); - } - on_rez(integer parm) { - record_link_num_if_useful(); - state default; - } - link_message(integer sender, integer num, string command, key parameters) { - if (num != HUFF_SEARCH_POINTER_HUFFWARE_ID) return; // not for us. - if (llGetLinkNumber() <= 1) return; // do nothing as root prim. - if (command == HUFF_SEARCH_RESET) { - // returns to the normal state of the object. - reset_sensors(); - SetLocalRot(<0, 0, 0, 1>); - llParticleSystem([]); - running_particles = FALSE; - global_matches_found = []; - } else if (command == HUFF_SEARCH_POINT_PARTY) { - // aim at an object and show a particle stream leading to it. - reset_sensors(); - list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); - key targetKey = (key)llList2String(parsedParameters, 0); - vector targetPos = (vector)llList2String(parsedParameters, 1); - point_at(targetKey, targetPos); - } else if (command == HUFF_SEARCH_JUST_POINT) { - // aim at an object, but don't do any particles. - reset_sensors(); - list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); - vector targetPos = (vector)llList2String(parsedParameters, 0); - aim_at(targetPos); - } else if (command == HUFF_SEARCH_SENSEI) { - // set up a sensor request for a search pattern. pings will cause - // the pattern to be sought in names of nearby objects. - reset_sensors(); - global_matches_found = []; // reset any previous matches. - list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); - max_range = (float)llList2String(parsedParameters, 0); - arc_angle = (float)llList2String(parsedParameters, 1); - search_pattern = llToLower((string)llList2String(parsedParameters, 2)); - MAX_LIST_LEN = (integer)llList2String(parsedParameters, 3); -if (!MAX_LIST_LEN) { -MAX_LIST_LEN = 17; -log_it("failed to get list length param"); -} - } else if (command == HUFF_SEARCH_STOP_SENSE) { - // turn off the sensor but don't totally reset yet. - reset_sensors(); - global_matches_found = []; - } else if (command == HUFF_SEARCH_PING) { - // do a little particle emission while searching, just to let them know - // where we've been. - target = "self"; - radius = 5; - if (!running_particles) create_particles(); - // they want to check for objects right here, right now... - llSensor("", NULL_KEY, SENSOR_TYPE_ALL, max_range, arc_angle); - } - } - changed(integer change) { - if (change & CHANGED_LINK) { - // we have been linked or unlinked or sat upon. - if ( (our_link_number > 1) && (llGetLinkNumber() == 0) ) { - // this is now a single prim linked to nothing. - llDie(); - } else if (our_link_number <= 1) { - // we had no link number recorded, so let's track this if needed. - record_link_num_if_useful(); - } - } - } - sensor(integer num_detected) { - if (llGetLinkNumber() <= 1) return; // do nothing as root prim. - if (llGetListLength(global_matches_found) > MAX_LIST_LEN) { - // we have enough matches already. stop adding more. - return; - } - - list parms = []; // the full set of matches we found. - integer i; // loop variable. - integer matches_found = 0; - key root_key = llGetLinkKey(1); - for (i = 0; i < num_detected; i++) { - key targetKey = llDetectedKey(i); - string target_name = llDetectedName(i); - if ( (targetKey != root_key) - // we don't want to report our own object. - && matches_substring(target_name, search_pattern) - // check whether the current target matches our search pattern. - && (find_in_list(global_matches_found, targetKey) < 0) ) { - // make sure we haven't already reported this one. - -//if (matches_substring(target_name, "searchbert v")) { -//log_it("somehow got past the is it myself check with a no-answer, my key=" + llGetKey() + " their key=" + targetKey); -//} - - // store the match now. even if we don't like where it's located - // (as in, outside our sim), we still don't want to keep matching it - // and looking at it. - global_matches_found += targetKey; - - // the name matched the search pattern... but make sure the - // location is worth reporting; if it's outside the sim, we will - // not be able to name it or point at it properly. - vector location = llDetectedPos(i); - if (!outside_of_sim(location)) { - // it's a match that's inside the sim. send it along. - parms += [ targetKey, location ]; - matches_found++; // we got one! -//log_it("match added: " + (string)targetKey); - // shorten lists of matches so we don't overload the brain. - if (llGetListLength(parms) >= 8) { - llMessageLinked(LINK_ROOT, - HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE, - HUFF_SEARCH_MATCH_EVENT, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - matches_found = 0; - parms = []; - } - } - } - } - if (matches_found) { -//log_it("sending " + (string)matches_found + " matches in message..."); - // send message about matches back to parent. - llMessageLinked(LINK_ROOT, HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE, - HUFF_SEARCH_MATCH_EVENT, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.txt new file mode 100755 index 00000000..8cdeb3f4 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-search_pointer_v10.0.txt @@ -0,0 +1,574 @@ + +// huffware script: huff-search pointer, by fred huffhines +// +// note: parts of this script were written by the attributed authors below. +// +// this script is one portion of a search system. the pointer is meant to be in a child prim. +// it is told what to point at by the root prim. +// +// the newer version of this supports a search command that locates objects in the +// direction specified. +// +// original attributions: started life as "Particle Script 0.4, Created by Ama Omega, 3-7-2004" +// some code in this script is also from: Christopher Omega. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// huff-search pointer API: +////////////// +// do not redefine these constants. +integer HUFF_SEARCH_POINTER_HUFFWARE_ID = 10032; + // the unique id within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string HUFF_SEARCH_RESET = "#reset#"; + // returns the script to its starting state. +string HUFF_SEARCH_POINT_PARTY = "#point_particles#"; + // aim at an object and show a particle stream leading to it. +string HUFF_SEARCH_JUST_POINT = "#just_point#"; + // aim at an object, but don't do any particles. +string HUFF_SEARCH_SENSEI = "#sensor#"; + // set up a sensor request for a search pattern. pings will cause + // the pattern to be sought in names of nearby objects. the parameters are: + // (1) the maximum range for the sensor, (2) the arc angle to use in sensing, + // (3) the search pattern to look for in object names, (4) the maximum number + // of matches to look for. +string HUFF_SEARCH_STOP_SENSE = "#stop_sensor#"; + // turn off the sensor but don't totally reset. +string HUFF_SEARCH_PING = "#ping#"; + // cause the searcher to actively sensor ping the targets. +string HUFF_SEARCH_MATCH_EVENT = "#match#"; + // fired at the root prim when matches are found for the search term. + // the payload is a list of matched item pairs [item key, location]. +////////////// + +// global variables... + +// SENSOR_TYPE_ALL: a constant that tells the sensor to look for (ACTIVE|PASSIVE|AGENT). +integer SENSOR_TYPE_ALL = 7; + +// AXIS_* constants, represent the unit vector 1 unit on the specified axis. +vector AXIS_UP = <0.0, 0.0, 1.0>; +vector AXIS_LEFT = <0.0, 1.0, 0.0>; +vector AXIS_FWD = <1.0, 0.0, 0.0>; + +integer MAX_LIST_LEN = 17; + // the maximum matches we hang onto, to avoid using too many resources. + // this should be no longer than the number of search arms created by + // the brain script, but it can be less if fewer matches are needed. + +/////////////// + +// global variables... + +string search_pattern; + // the pattern that we are hoping to find from our sensor hits. + +list global_matches_found; + // a list of keys that match the specified search terms. + +integer our_link_number = 0; + // set to the number for our link if we ever see ourselves as a link greater than 1. + // this only happens when we have been made a sub-prim and are definitely not the root prim, + // so it is our key for whether the prim should die if it becomes unlinked. + +// Mask Flags - set to TRUE to enable +integer glow = TRUE; // Make the particles glow +integer bounce = FALSE; // Make particles bounce on Z plane of object +integer interpColor = TRUE; // Go from start to end color +integer interpSize = TRUE; // Go from start to end size +integer wind = FALSE; // Particles effected by wind +integer followSource = TRUE; // Particles follow the source +integer followVel = TRUE; // Particles turn to velocity direction + +// Choose a pattern from the following: +// PSYS_SRC_PATTERN_EXPLODE +// PSYS_SRC_PATTERN_DROP +// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY +// PSYS_SRC_PATTERN_ANGLE_CONE +// PSYS_SRC_PATTERN_ANGLE +integer pattern = PSYS_SRC_PATTERN_DROP; + +// Select a target for particles to go towards +// "" for no target, "owner" will follow object owner +// and "self" will target this object +// or put the key of an object for particles to go to +key target = "owner"; + +// useful particle parameters. +float age = 14; // Life of each particle +float startAlpha = 1.0; // Start alpha (transparency) value +float endAlpha = 1.0; // End alpha (transparency) value +vector startSize = <0.2, 0.2, 0.2>; // Start size of particles +vector endSize = <0.8, 0.8, 0.8>; // End size of particles (if interpSize == TRUE) + +// colors are now assigned dynamically per search. +vector startColor; // Start color of particles +vector endColor; // End color of particles (if interpColor == TRUE) + +// unused particle parameters. +float maxSpeed = 2; // Max speed each particle is spit out at +float minSpeed = 2; // Min speed each particle is spit out at +string texture; // Texture used for particles, default used if blank +vector push = <0.0, 0.0, 0.0>; // Force pushed on particles + +// System parameters +float rate = 0.08; // burst rate to emit particles, zero is fastest. +float radius = 1; // Radius to emit particles for BURST pattern +integer count = 1; // How many particles to emit per BURST +float outerAngle = 1.54; // Outer angle for all ANGLE patterns +float innerAngle = 1.55; // Inner angle for all ANGLE patterns +vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source +float life = 0; // Life in seconds for the system to make particles + +// Script variables +integer precision = 2; //Adjust the precision of the generated list. + +integer running_particles = FALSE; // is the particle system running? + +///integer start_parm; // set from the on_rez parameter. + +string float2String(float in) +{ + return llGetSubString((string)in, 0, precision - 7); +} + +create_particles() +{ + list system_content; + integer flags = 0; + if (target == "owner") target = llGetOwner(); + if (target == "self") target = llGetKey(); + if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK; + if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK; + if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK; + if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK; + if (wind) flags = flags | PSYS_PART_WIND_MASK; + if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK; + if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK; + if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK; + + // original recipe searchbert pointer... +// startColor = <0.92, 0.79412, 0.66863>; // Start color of particles +// endColor = <0.0, 1.0, 0.7>; // End color of particles (if interpColor == TRUE) + // new randomized version for colors. the current aesthetic here is to start + // with a relatively dark color and end on a relatively light color. + startColor = ; + endColor = ; + + system_content = [ PSYS_PART_MAX_AGE, age, + PSYS_PART_FLAGS,flags, + PSYS_PART_START_COLOR, startColor, + PSYS_PART_END_COLOR, endColor, + PSYS_PART_START_SCALE, startSize, + PSYS_PART_END_SCALE, endSize, + PSYS_SRC_PATTERN, pattern, + PSYS_SRC_BURST_RATE, rate, + PSYS_SRC_ACCEL, push, + PSYS_SRC_BURST_PART_COUNT, count, + PSYS_SRC_BURST_RADIUS, radius, + PSYS_SRC_BURST_SPEED_MIN, minSpeed, + PSYS_SRC_BURST_SPEED_MAX, maxSpeed, +// PSYS_SRC_INNERANGLE,innerAngle, +// PSYS_SRC_OUTERANGLE,outerAngle, + PSYS_SRC_OMEGA, omega, + PSYS_SRC_MAX_AGE, life, +// PSYS_SRC_TEXTURE, texture, + PSYS_PART_START_ALPHA, startAlpha, + PSYS_PART_END_ALPHA, endAlpha + ]; + if (target != NULL_KEY) { + system_content += [ PSYS_SRC_TARGET_KEY, target ]; + } + + llParticleSystem(system_content); + running_particles = TRUE; +} + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +/////////////// + +// SetLocalRot +// In a linked set, points a child object to the rotation. +// @param rot The rotation to rotate to. +SetLocalRot(rotation rot) +{ + if(llGetLinkNumber() > 1) + { + rotation locRot = llGetLocalRot(); + locRot.s = -locRot.s; // Invert local rot. + + rotation parentRot = locRot * llGetRot(); + parentRot.s = -parentRot.s; // Invert parent's rot. + + llSetLocalRot(rot * parentRot); + } +} + +// Gets the rotation to point the specified axis at the specified position. +// @param axis The axis to point. Easiest to just use an AXIS_* constant. +// @param target The target, in region-local coordinates, to point the axis at. +// @return The rotation necessary to point axis at target. +rotation getRotToPointAxisAt(vector axis, vector target) +{ + return llGetRot() * llRotBetween(axis * llGetRot(), target - llGetPos()); +} + +// aims in the direction of the target. +aim_at(vector targetPos) +{ + SetLocalRot(getRotToPointAxisAt(AXIS_UP, targetPos)); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// point_at +// Points up axis at targetPos, and emits a particle system at targetKey. +// @param targetKey The UUID of the target to emit particles to. +// @param targetPos The poaition of the target in region-local coordinates. +point_at(key targetKey, vector targetPos) +{ + aim_at(targetPos); + target = targetKey; + create_particles(); +} + +// variables that are established by a search and used periodically in the timer. +float max_range = 0.0; +float arc_angle = 0.0; +float sensor_interval = 0.0; + +reset_sensors() +{ + radius = 1; + llSetTimerEvent(0.0); + llSensorRemove(); +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// returns a number at most maximum and at least minimum. +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// makes sure that we record the current link number if it's higher than 1; this +// is how we know that we're a sub-prim. +record_link_num_if_useful() +{ + if (llGetLinkNumber() > 1) our_link_number = llGetLinkNumber(); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + llParticleSystem([]); + running_particles = FALSE; + SetLocalRot(<0.0, 0.0, 0.0, 1.0>); + global_matches_found = []; + record_link_num_if_useful(); + } + on_rez(integer parm) { + record_link_num_if_useful(); + state default; + } + link_message(integer sender, integer num, string command, key parameters) { + if (num != HUFF_SEARCH_POINTER_HUFFWARE_ID) return; // not for us. + if (llGetLinkNumber() <= 1) return; // do nothing as root prim. + if (command == HUFF_SEARCH_RESET) { + // returns to the normal state of the object. + reset_sensors(); + SetLocalRot(<0, 0, 0, 1>); + llParticleSystem([]); + running_particles = FALSE; + global_matches_found = []; + } else if (command == HUFF_SEARCH_POINT_PARTY) { + // aim at an object and show a particle stream leading to it. + reset_sensors(); + list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); + key targetKey = (key)llList2String(parsedParameters, 0); + vector targetPos = (vector)llList2String(parsedParameters, 1); + point_at(targetKey, targetPos); + } else if (command == HUFF_SEARCH_JUST_POINT) { + // aim at an object, but don't do any particles. + reset_sensors(); + list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); + vector targetPos = (vector)llList2String(parsedParameters, 0); + aim_at(targetPos); + } else if (command == HUFF_SEARCH_SENSEI) { + // set up a sensor request for a search pattern. pings will cause + // the pattern to be sought in names of nearby objects. + reset_sensors(); + global_matches_found = []; // reset any previous matches. + list parsedParameters = llParseString2List(parameters, [HUFFWARE_PARM_SEPARATOR], []); + max_range = (float)llList2String(parsedParameters, 0); + arc_angle = (float)llList2String(parsedParameters, 1); + search_pattern = llToLower((string)llList2String(parsedParameters, 2)); + MAX_LIST_LEN = (integer)llList2String(parsedParameters, 3); +if (!MAX_LIST_LEN) { +MAX_LIST_LEN = 17; +log_it("failed to get list length param"); +} + } else if (command == HUFF_SEARCH_STOP_SENSE) { + // turn off the sensor but don't totally reset yet. + reset_sensors(); + global_matches_found = []; + } else if (command == HUFF_SEARCH_PING) { + // do a little particle emission while searching, just to let them know + // where we've been. + target = "self"; + radius = 5; + if (!running_particles) create_particles(); + // they want to check for objects right here, right now... + llSensor("", NULL_KEY, SENSOR_TYPE_ALL, max_range, arc_angle); + } + } + changed(integer change) { + if (change & CHANGED_LINK) { + // we have been linked or unlinked or sat upon. + if ( (our_link_number > 1) && (llGetLinkNumber() == 0) ) { + // this is now a single prim linked to nothing. + llDie(); + } else if (our_link_number <= 1) { + // we had no link number recorded, so let's track this if needed. + record_link_num_if_useful(); + } + } + } + sensor(integer num_detected) { + if (llGetLinkNumber() <= 1) return; // do nothing as root prim. + if (llGetListLength(global_matches_found) > MAX_LIST_LEN) { + // we have enough matches already. stop adding more. + return; + } + + list parms = []; // the full set of matches we found. + integer i; // loop variable. + integer matches_found = 0; + key root_key = llGetLinkKey(1); + for (i = 0; i < num_detected; i++) { + key targetKey = llDetectedKey(i); + string target_name = llDetectedName(i); + if ( (targetKey != root_key) + // we don't want to report our own object. + && matches_substring(target_name, search_pattern) + // check whether the current target matches our search pattern. + && (find_in_list(global_matches_found, targetKey) < 0) ) { + // make sure we haven't already reported this one. + +//if (matches_substring(target_name, "searchbert v")) { +//log_it("somehow got past the is it myself check with a no-answer, my key=" + llGetKey() + " their key=" + targetKey); +//} + + // store the match now. even if we don't like where it's located + // (as in, outside our sim), we still don't want to keep matching it + // and looking at it. + global_matches_found += targetKey; + + // the name matched the search pattern... but make sure the + // location is worth reporting; if it's outside the sim, we will + // not be able to name it or point at it properly. + vector location = llDetectedPos(i); + if (!outside_of_sim(location)) { + // it's a match that's inside the sim. send it along. + parms += [ targetKey, location ]; + matches_found++; // we got one! +//log_it("match added: " + (string)targetKey); + // shorten lists of matches so we don't overload the brain. + if (llGetListLength(parms) >= 8) { + llMessageLinked(LINK_ROOT, + HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE, + HUFF_SEARCH_MATCH_EVENT, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + matches_found = 0; + parms = []; + } + } + } + } + if (matches_found) { +//log_it("sending " + (string)matches_found + " matches in message..."); + // send message about matches back to parent. + llMessageLinked(LINK_ROOT, HUFF_SEARCH_POINTER_HUFFWARE_ID + REPLY_DISTANCE, + HUFF_SEARCH_MATCH_EVENT, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.lsl deleted file mode 100755 index 4a458bb5..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.lsl +++ /dev/null @@ -1,826 +0,0 @@ - -// huffware script: huff-update client, by fred huffhines. -// -// this script is the client side of the update process. it should reside in an object that -// has scripts which should be automatically updated. it will listen for announcements by -// an update server and communicate with the server to ensure that all of its scripts are -// the most up to date available with the server. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -integer DEBUGGING = FALSE; // if TRUE, the script will output status information. - -integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. - -integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -integer MAXIMUM_SERVERS_TRACKED = 32; - // we will listen to this many servers before we decide to remove one. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string SERVER_SCRIPT = "a huffotronic update server"; - // the prefix of our server script that hands out updates. - -// global variables... - -integer inventory_request_channel; // used for newer version servers to cut down cross chatter. -list updaters_heard; // the update servers we've heard from recently. -list last_interactions; // times of the last update process engaged with the updater. -integer update_channel; // current channel for interaction with specific server. -key current_server; // the updater that is active right now, if any. -integer update_start_time; // when the last update process began. -list updates_needed; // stores the set of scripts that are in need of an update. -list known_script_dependencies; // stores the list of dependency info. - -careful_crankup() -{ - knock_around_other_scripts(TRUE); - // clean out the older items and scripts. we do this after getting everyone running - // since we might be whacking ourselves. - destroy_older_versions(); -} - -// reset our variables. -initialize() -{ - updaters_heard = []; - last_interactions = []; - inventory_request_channel = 0; - update_channel = 0; - current_server = NULL_KEY; - llSetTimerEvent(0.0); - llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); - // a new enhancements; tells the server that this guy has finished an update cycle. this - // only comes into play when the updater script itself has just been updated, but it's - // nice for the server to avoid claiming erroneous timeouts occurred. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); - llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); -} - -whack_updater_record(key id) -{ - integer prev_indy = find_in_list(updaters_heard, id); - if (prev_indy < 0) return; // not there. - updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) - + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); - last_interactions = chop_list(last_interactions, 0, prev_indy - 1) - + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); -} - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - if (DEBUGGING) - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -// sets the object to be listening for update info. -// if "just_owner" is true, then we will not listen on the general announcement channel. -listen_for_orders(integer just_owner) -{ - if (!just_owner) { - // try to hear an update being announced. - llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); - } - - // super secret owner controls. - llListen(0, "", llGetOwner(), ""); -} - -// returns true if this object is a huffotronic updater of some sort. -integer inside_of_updater() -{ - return find_substring(llGetObjectName(), "huffotronic") >= 0; -} - -// returns true if a script is a version of our update server. -integer matches_server_script(string to_check) -{ - return is_prefix(to_check, SERVER_SCRIPT); -} - -// stops all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - integer insider = inside_of_updater(); - if (running_state == TRUE) { - // make sure we crank up the scripts that are new first. we want to reset them - // as well, which we don't want to do for any existing scripts. - integer crank_indy; - for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { - string crankee = llList2String(updates_needed, crank_indy); - if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { - if (!insider || matches_server_script(crankee)) { - // allow it to run again. - llSetScriptState(crankee, TRUE); - // reset it, to make sure it starts at the top. - llResetOtherScript(crankee); - } - } - } - } - - integer indy; - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if ( (curr_script != self_script) - && (!insider || matches_server_script(curr_script)) ) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -// a random channel for the interaction with the server. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// make sure that any dependencies for the script with "basename" are added to the list -// of requests we make during an update. -list add_dependencies(string basename) -{ - list to_return; - integer indy; - for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { - list deps = llParseString2List(llList2String(known_script_dependencies, indy), - [ITEM_LIST_SEPARATOR], []); -//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); - if (basename == llList2String(deps, 0)) { - // first off, is this item with new dependencies actually present? - integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); - if (where >= 0) { - // we do use the script with deps, but is the dependent item really missing? - where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); - if (where < 0) { - // we found a dependency match for this script, so we'll ask for the missing item. - if (DEBUGGING) - log_it("missing dep: " + llList2String(deps, 1)); - to_return += [ llList2String(deps, 1) ]; - } - } - } - } - return to_return; -} - -// complains if memory seems to be getting tight. -test_memory() -{ - if (llGetFreeMemory() < 4096) - log_it("mem_free = " + (string)llGetFreeMemory()); -} - -// starts an update given a list of scripts that the server has available, encoded as -// a string in the "encoded_list". -integer initiate_update(string encoded_list) -{ - list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); - integer continue_listening_for_scripts = FALSE; - // if true, we aren't done hearing about available scripts yet. - encoded_list = ""; - // figure out which scripts we need by comparing the list available from the server - // against our current inventory. we only want scripts with newer version numbers. - integer sindy; - for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { - string curr = llList2String(scripts_avail, sindy); - if (curr == CONTINUANCE_MARKER) { - // this is a special continuation signal. we need to hear the rest of the list. - continue_listening_for_scripts = TRUE; - } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { - // we've found a dependency item. - known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; -//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); - } else { - list split = compute_basename_and_version(curr); - if (llGetListLength(split) == 2) { - string basename = llList2String(split, 0); - string version = llList2String(split, 1); - split = []; - integer oy_indy; -//replace common code with func. - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { -// if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); -// } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - updates_needed += add_dependencies(basename); - } - } - } - // we skip the next step if we're still waiting to hear about more. - if (continue_listening_for_scripts) { -//log_it("still listening for more updates..."); - return FALSE; - } - if (llGetListLength(updates_needed)) { -//log_it("update chan=" + (string)update_channel); - llSay(update_channel, REQUEST_SCRIPT_UPDATE); - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i need updating."); - } - } else { - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i am done updating."); - } - llSay(update_channel, DONE_UPDATING); - } - return TRUE; -} - -// this alerts the server to our most desired scripts. -tell_server_our_wish_list() -{ - llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); -} - -// checks whether all of the updates needed are present yet. -integer check_on_update_presence() -{ - integer indy; - for (indy = 0; indy < llGetListLength(updates_needed); indy++) { - integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); - // any single missing guy means they aren't up to date yet. - if (found < 0) { - if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); - return FALSE; - } - } - // nothing was detected as missing anymore. - return TRUE; -} - -// respond to spoken commands from the server. -integer process_update_news(integer channel, string name, key id, string message) -{ - if (!channel) { - // this is a command. - if (message == "ureset") { - llResetScript(); // start over. - } - if (message == "ushow") { - integer sindy; - integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); - list script_list = [ "scripts--" ]; // first item is just a header. - for (sindy = 0; sindy < script_count; sindy++) { - script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; - } - dump_list_to_log(script_list); - } - return FALSE; // nothing to do here. - } - if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { -/* never seen. if (id == llGetKey()) { -if (DEBUGGING) log_it("ignoring update from self."); - return FALSE; // ack, that's our very object. - } -*/ - if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { - // this is a new style update message. we can set a different request channel. - string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); - inventory_request_channel = (integer)just_chan; - } - integer prev_indy = find_in_list(updaters_heard, id); - // find the talker in our list. - if (prev_indy >= 0) { - // that guy was already heard from. check when last interacted. - integer last_heard = llList2Integer(last_interactions, prev_indy); - if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { - return FALSE; // not time to update with this guy again yet. - } -// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } - // make sure we think of this as a new updater now. - whack_updater_record(id); - } - - if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } - // record our new server. - current_server = id; - // make a random pause so not all updaters try to crank up at same time. - llSleep(randomize_within_range(2.8, 18.2, FALSE)); - - if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { - // oops, this is not good. we have too many servers now. -//hmmm: room for improvement here by tossing out the server that is oldest. - updaters_heard = llDeleteSubList(updaters_heard, 0, 0); - last_interactions = llDeleteSubList(last_interactions, 0, 0); - } - - // add the talker to our list. - updaters_heard += id; - last_interactions += llGetUnixTime(); - - // begin the update interaction with this guy. - update_channel = random_channel(); - return TRUE; - } - if (update_channel && (channel == update_channel) ) { - if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { - // tasty, this is a list of scripts that can be had. - message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); - if (message == BUSY_BUSY) { - // server has signified that it's too busy (or its owner is a moron) because it is - // claiming it has no scripts at all. - if (DEBUGGING) { - log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); - } - // make it seem like we need to do this one again sooner than normal. - whack_updater_record(id); - // busy server means move no further forward. - return FALSE; - } - return initiate_update(message); - } else if (is_prefix(message, SHUT_THEM_DOWN)) { - if (DEBUGGING) { log_it("stopping other scripts."); } - knock_around_other_scripts(FALSE); - // now that we know for sure the server's ready to update us, - // we tell it what we need. - tell_server_our_wish_list(); - return FALSE; - } else if (is_prefix(message, START_THEM_UP)) { - // let the server know that we've finished, for all intents and purposes. - llSay(update_channel, DONE_UPDATING); - // we pause a random bit first; we want to ensure we aren't swamping - // SL with our inventory loading. - llSleep(randomize_within_range(2.5, 8.2, FALSE)); - if (DEBUGGING) { log_it("starting other scripts."); } - careful_crankup(); - return TRUE; // change state now. -// } else { -//log_it("unknown command on update channel: " + message); - } - } - return FALSE; -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) - return inv; - else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) - return inv; - } - return -2; // failed to find it. -} - -////////////// - -integer MAX_CHAT_LINE = 900; - // the most characters we'll try to say in one chat. - -dump_list_to_log(list to_show) -{ - string text = dump_list(to_show); // get some help from the other version. - integer len = llStringLength(text); - integer i; - for (i = 0; i < len; i += MAX_CHAT_LINE) { - integer last_bit = i + MAX_CHAT_LINE - 1; - if (last_bit >= len) last_bit = len - 1; - string next_line = llGetSubString(text, i, last_bit); - llWhisper(0, next_line); - } -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "\"" + next_line + "\""; - } - text = text + next_line; - if (i < len - 1) text = text + " "; - } - return text; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -// no huffotronic trap state for startup, because this script will actually -// run (and is expected) inside a huffotronic updater object. - -default -{ - state_entry() - { - auto_retire(); // only allow the most recent revision. - initialize(); - state awaiting_commands; - } -} - -state awaiting_commands -{ - state_entry() - { - if (DEBUGGING) log_it(""); - careful_crankup(); // we always start by getting everyone running. - current_server = NULL_KEY; // forget previous server. - listen_for_orders(FALSE); - inventory_request_channel = 0; // no inventory request channel either. - update_channel = 0; // no channel currently. - updates_needed = []; // we know of no needs right now. - known_script_dependencies = []; // no deps either. - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) - state establish_private_channel; - } -} - -state establish_private_channel -{ - state_entry() - { - if (DEBUGGING) log_it(""); - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (inventory_request_channel) - llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); - else - llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); - llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); - } - - state_exit() { llSetTimerEvent(0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // ready for a state change, but what kind? - if (llGetListLength(updates_needed)) { -//log_it("have a list of updates now."); - state performing_update; - } else { -//log_it("no updates needed in list, going back"); - state awaiting_commands; - } - } - } - - timer() { - if (DEBUGGING) { - log_it("timed out establishing channel with server " + (string)inventory_request_channel); - } - whack_updater_record(current_server); - state awaiting_commands; - } - - on_rez(integer parm) { state default; } -} - -state performing_update -{ - state_entry() - { - // must re-listen after a state change. - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (DEBUGGING) log_it(""); - llSetTimerEvent(UPDATE_TIMER_INTERVAL); - update_start_time = llGetUnixTime(); - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // normal finish of update process. - state awaiting_commands; - } - } - - timer() { - if (llGetListLength(updates_needed) == 0) { -//log_it("nothing to update, leaving perform state."); - state awaiting_commands; // we've got nothing to do. - } else { - // see if all our requested scripts are there yet; if not, we're not done updating. - integer ready = check_on_update_presence(); - if (ready) { - if (DEBUGGING) log_it("reporting scripts are current."); - llSay(update_channel, SCRIPTS_ARE_CURRENT); - } - } - if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { - if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } - whack_updater_record(current_server); - state awaiting_commands; - } - } - - on_rez(integer parm) { state default; } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.txt new file mode 100755 index 00000000..4a458bb5 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huff-update_client_v20.1.txt @@ -0,0 +1,826 @@ + +// huffware script: huff-update client, by fred huffhines. +// +// this script is the client side of the update process. it should reside in an object that +// has scripts which should be automatically updated. it will listen for announcements by +// an update server and communicate with the server to ensure that all of its scripts are +// the most up to date available with the server. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +integer DEBUGGING = FALSE; // if TRUE, the script will output status information. + +integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. + +integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +integer MAXIMUM_SERVERS_TRACKED = 32; + // we will listen to this many servers before we decide to remove one. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string SERVER_SCRIPT = "a huffotronic update server"; + // the prefix of our server script that hands out updates. + +// global variables... + +integer inventory_request_channel; // used for newer version servers to cut down cross chatter. +list updaters_heard; // the update servers we've heard from recently. +list last_interactions; // times of the last update process engaged with the updater. +integer update_channel; // current channel for interaction with specific server. +key current_server; // the updater that is active right now, if any. +integer update_start_time; // when the last update process began. +list updates_needed; // stores the set of scripts that are in need of an update. +list known_script_dependencies; // stores the list of dependency info. + +careful_crankup() +{ + knock_around_other_scripts(TRUE); + // clean out the older items and scripts. we do this after getting everyone running + // since we might be whacking ourselves. + destroy_older_versions(); +} + +// reset our variables. +initialize() +{ + updaters_heard = []; + last_interactions = []; + inventory_request_channel = 0; + update_channel = 0; + current_server = NULL_KEY; + llSetTimerEvent(0.0); + llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); + // a new enhancements; tells the server that this guy has finished an update cycle. this + // only comes into play when the updater script itself has just been updated, but it's + // nice for the server to avoid claiming erroneous timeouts occurred. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); + llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); +} + +whack_updater_record(key id) +{ + integer prev_indy = find_in_list(updaters_heard, id); + if (prev_indy < 0) return; // not there. + updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) + + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); + last_interactions = chop_list(last_interactions, 0, prev_indy - 1) + + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); +} + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + if (DEBUGGING) + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +// sets the object to be listening for update info. +// if "just_owner" is true, then we will not listen on the general announcement channel. +listen_for_orders(integer just_owner) +{ + if (!just_owner) { + // try to hear an update being announced. + llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); + } + + // super secret owner controls. + llListen(0, "", llGetOwner(), ""); +} + +// returns true if this object is a huffotronic updater of some sort. +integer inside_of_updater() +{ + return find_substring(llGetObjectName(), "huffotronic") >= 0; +} + +// returns true if a script is a version of our update server. +integer matches_server_script(string to_check) +{ + return is_prefix(to_check, SERVER_SCRIPT); +} + +// stops all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + integer insider = inside_of_updater(); + if (running_state == TRUE) { + // make sure we crank up the scripts that are new first. we want to reset them + // as well, which we don't want to do for any existing scripts. + integer crank_indy; + for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { + string crankee = llList2String(updates_needed, crank_indy); + if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { + if (!insider || matches_server_script(crankee)) { + // allow it to run again. + llSetScriptState(crankee, TRUE); + // reset it, to make sure it starts at the top. + llResetOtherScript(crankee); + } + } + } + } + + integer indy; + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if ( (curr_script != self_script) + && (!insider || matches_server_script(curr_script)) ) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +// a random channel for the interaction with the server. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// make sure that any dependencies for the script with "basename" are added to the list +// of requests we make during an update. +list add_dependencies(string basename) +{ + list to_return; + integer indy; + for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { + list deps = llParseString2List(llList2String(known_script_dependencies, indy), + [ITEM_LIST_SEPARATOR], []); +//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); + if (basename == llList2String(deps, 0)) { + // first off, is this item with new dependencies actually present? + integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); + if (where >= 0) { + // we do use the script with deps, but is the dependent item really missing? + where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); + if (where < 0) { + // we found a dependency match for this script, so we'll ask for the missing item. + if (DEBUGGING) + log_it("missing dep: " + llList2String(deps, 1)); + to_return += [ llList2String(deps, 1) ]; + } + } + } + } + return to_return; +} + +// complains if memory seems to be getting tight. +test_memory() +{ + if (llGetFreeMemory() < 4096) + log_it("mem_free = " + (string)llGetFreeMemory()); +} + +// starts an update given a list of scripts that the server has available, encoded as +// a string in the "encoded_list". +integer initiate_update(string encoded_list) +{ + list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); + integer continue_listening_for_scripts = FALSE; + // if true, we aren't done hearing about available scripts yet. + encoded_list = ""; + // figure out which scripts we need by comparing the list available from the server + // against our current inventory. we only want scripts with newer version numbers. + integer sindy; + for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { + string curr = llList2String(scripts_avail, sindy); + if (curr == CONTINUANCE_MARKER) { + // this is a special continuation signal. we need to hear the rest of the list. + continue_listening_for_scripts = TRUE; + } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { + // we've found a dependency item. + known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; +//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); + } else { + list split = compute_basename_and_version(curr); + if (llGetListLength(split) == 2) { + string basename = llList2String(split, 0); + string version = llList2String(split, 1); + split = []; + integer oy_indy; +//replace common code with func. + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { +// if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); +// } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + updates_needed += add_dependencies(basename); + } + } + } + // we skip the next step if we're still waiting to hear about more. + if (continue_listening_for_scripts) { +//log_it("still listening for more updates..."); + return FALSE; + } + if (llGetListLength(updates_needed)) { +//log_it("update chan=" + (string)update_channel); + llSay(update_channel, REQUEST_SCRIPT_UPDATE); + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i need updating."); + } + } else { + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i am done updating."); + } + llSay(update_channel, DONE_UPDATING); + } + return TRUE; +} + +// this alerts the server to our most desired scripts. +tell_server_our_wish_list() +{ + llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); +} + +// checks whether all of the updates needed are present yet. +integer check_on_update_presence() +{ + integer indy; + for (indy = 0; indy < llGetListLength(updates_needed); indy++) { + integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); + // any single missing guy means they aren't up to date yet. + if (found < 0) { + if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); + return FALSE; + } + } + // nothing was detected as missing anymore. + return TRUE; +} + +// respond to spoken commands from the server. +integer process_update_news(integer channel, string name, key id, string message) +{ + if (!channel) { + // this is a command. + if (message == "ureset") { + llResetScript(); // start over. + } + if (message == "ushow") { + integer sindy; + integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); + list script_list = [ "scripts--" ]; // first item is just a header. + for (sindy = 0; sindy < script_count; sindy++) { + script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; + } + dump_list_to_log(script_list); + } + return FALSE; // nothing to do here. + } + if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { +/* never seen. if (id == llGetKey()) { +if (DEBUGGING) log_it("ignoring update from self."); + return FALSE; // ack, that's our very object. + } +*/ + if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { + // this is a new style update message. we can set a different request channel. + string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); + inventory_request_channel = (integer)just_chan; + } + integer prev_indy = find_in_list(updaters_heard, id); + // find the talker in our list. + if (prev_indy >= 0) { + // that guy was already heard from. check when last interacted. + integer last_heard = llList2Integer(last_interactions, prev_indy); + if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { + return FALSE; // not time to update with this guy again yet. + } +// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } + // make sure we think of this as a new updater now. + whack_updater_record(id); + } + + if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } + // record our new server. + current_server = id; + // make a random pause so not all updaters try to crank up at same time. + llSleep(randomize_within_range(2.8, 18.2, FALSE)); + + if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { + // oops, this is not good. we have too many servers now. +//hmmm: room for improvement here by tossing out the server that is oldest. + updaters_heard = llDeleteSubList(updaters_heard, 0, 0); + last_interactions = llDeleteSubList(last_interactions, 0, 0); + } + + // add the talker to our list. + updaters_heard += id; + last_interactions += llGetUnixTime(); + + // begin the update interaction with this guy. + update_channel = random_channel(); + return TRUE; + } + if (update_channel && (channel == update_channel) ) { + if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { + // tasty, this is a list of scripts that can be had. + message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); + if (message == BUSY_BUSY) { + // server has signified that it's too busy (or its owner is a moron) because it is + // claiming it has no scripts at all. + if (DEBUGGING) { + log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); + } + // make it seem like we need to do this one again sooner than normal. + whack_updater_record(id); + // busy server means move no further forward. + return FALSE; + } + return initiate_update(message); + } else if (is_prefix(message, SHUT_THEM_DOWN)) { + if (DEBUGGING) { log_it("stopping other scripts."); } + knock_around_other_scripts(FALSE); + // now that we know for sure the server's ready to update us, + // we tell it what we need. + tell_server_our_wish_list(); + return FALSE; + } else if (is_prefix(message, START_THEM_UP)) { + // let the server know that we've finished, for all intents and purposes. + llSay(update_channel, DONE_UPDATING); + // we pause a random bit first; we want to ensure we aren't swamping + // SL with our inventory loading. + llSleep(randomize_within_range(2.5, 8.2, FALSE)); + if (DEBUGGING) { log_it("starting other scripts."); } + careful_crankup(); + return TRUE; // change state now. +// } else { +//log_it("unknown command on update channel: " + message); + } + } + return FALSE; +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) + return inv; + else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) + return inv; + } + return -2; // failed to find it. +} + +////////////// + +integer MAX_CHAT_LINE = 900; + // the most characters we'll try to say in one chat. + +dump_list_to_log(list to_show) +{ + string text = dump_list(to_show); // get some help from the other version. + integer len = llStringLength(text); + integer i; + for (i = 0; i < len; i += MAX_CHAT_LINE) { + integer last_bit = i + MAX_CHAT_LINE - 1; + if (last_bit >= len) last_bit = len - 1; + string next_line = llGetSubString(text, i, last_bit); + llWhisper(0, next_line); + } +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "\"" + next_line + "\""; + } + text = text + next_line; + if (i < len - 1) text = text + " "; + } + return text; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +// no huffotronic trap state for startup, because this script will actually +// run (and is expected) inside a huffotronic updater object. + +default +{ + state_entry() + { + auto_retire(); // only allow the most recent revision. + initialize(); + state awaiting_commands; + } +} + +state awaiting_commands +{ + state_entry() + { + if (DEBUGGING) log_it(""); + careful_crankup(); // we always start by getting everyone running. + current_server = NULL_KEY; // forget previous server. + listen_for_orders(FALSE); + inventory_request_channel = 0; // no inventory request channel either. + update_channel = 0; // no channel currently. + updates_needed = []; // we know of no needs right now. + known_script_dependencies = []; // no deps either. + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) + state establish_private_channel; + } +} + +state establish_private_channel +{ + state_entry() + { + if (DEBUGGING) log_it(""); + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (inventory_request_channel) + llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); + else + llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); + llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); + } + + state_exit() { llSetTimerEvent(0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // ready for a state change, but what kind? + if (llGetListLength(updates_needed)) { +//log_it("have a list of updates now."); + state performing_update; + } else { +//log_it("no updates needed in list, going back"); + state awaiting_commands; + } + } + } + + timer() { + if (DEBUGGING) { + log_it("timed out establishing channel with server " + (string)inventory_request_channel); + } + whack_updater_record(current_server); + state awaiting_commands; + } + + on_rez(integer parm) { state default; } +} + +state performing_update +{ + state_entry() + { + // must re-listen after a state change. + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (DEBUGGING) log_it(""); + llSetTimerEvent(UPDATE_TIMER_INTERVAL); + update_start_time = llGetUnixTime(); + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // normal finish of update process. + state awaiting_commands; + } + } + + timer() { + if (llGetListLength(updates_needed) == 0) { +//log_it("nothing to update, leaving perform state."); + state awaiting_commands; // we've got nothing to do. + } else { + // see if all our requested scripts are there yet; if not, we're not done updating. + integer ready = check_on_update_presence(); + if (ready) { + if (DEBUGGING) log_it("reporting scripts are current."); + llSay(update_channel, SCRIPTS_ARE_CURRENT); + } + } + if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { + if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } + whack_updater_record(current_server); + state awaiting_commands; + } + } + + on_rez(integer parm) { state default; } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.lsl deleted file mode 100755 index 8f06aa13..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.lsl +++ /dev/null @@ -1,252 +0,0 @@ - -// huffware script: "huffbee bulb", by fred huffhines -// -// inspired by the higbee bulb script available in open source, but provides a few -// different functions. this accepts a click to turn on and off, but it also listens -// to a special command to hear requests from linked objects. this also shuts off -// at dusk and turns on at dawn. -// this script uses the party culiar script to get the particle system created, -// and hence relies on a notecard to define the lamp's particles. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer DUSK_CHECKING_PERIOD = 240; - // check for dusk this frequently. in seconds, so 240 = 4 minutes. - -integer SECRET_LIGHT_BULB_ILLUMINATI_CODE = -14058; - // a semi-secret code that is used in a linked message when some other script - // wants the lamp to turn on or off. - -float BULB_GLOW_LEVEL = 0.5; // how much glow should the bulb have when it's lit? - -integer CHECK_FOR_DUSK = TRUE; // true if this lamp should be driven by daylight. - -integer PARTICLE_FIX_COG = 7; // every N timer hits, we'll fix our particles. - -// party culiar link message API. -////////////// -integer PARTYCULIAR_HUFFWARE_ID = 10018; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. -// -string PARTYCULIAR_POWER_COMMAND = "#powrpcl"; - // tells the particle system to either turn on or off. the single parameter is - // either "on", "1", "true", or "off", "0", "false". -////////////// - -// globals. - -integer particle_cog = 0; - -////////////// - -// asks the particle system script for a favor, given by the command and the -// parameters. -send_partyculiar_request(string cmd, string params) -{ llMessageLinked(LINK_THIS, PARTYCULIAR_HUFFWARE_ID, cmd, params); } - -// shuts down the lamp. there is no coming back from this method, -// since it resets the script. -turn_off_lamp() -{ - turn_off_particles(); - llResetScript(); -} - -turn_off_particles() { send_partyculiar_request(PARTYCULIAR_POWER_COMMAND, "off"); } - -turn_on_particles() { send_partyculiar_request(PARTYCULIAR_POWER_COMMAND, "on"); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - turn_off_particles(); - // reset the bulb to a fairly dark color with no glow and no light. - llSetPrimitiveParams([ - PRIM_COLOR, ALL_SIDES, <0.42, 0.42, 0.42>, 0.5, - PRIM_FULLBRIGHT, ALL_SIDES, FALSE, - PRIM_GLOW, ALL_SIDES, 0.0, - PRIM_POINT_LIGHT, FALSE, <0, 0, 0>, 1.0, 10.0, 0.25 - ]); - llSetTimerEvent(DUSK_CHECKING_PERIOD); - } - on_rez(integer parm) { - state default; - } - timer() { - vector sun = llGetSunDirection(); - if (CHECK_FOR_DUSK && (sun.z <= 0) ) - state PowerUp; // turn on at dusk. - } - touch_start(integer total_number) { - state PowerUp; - } - - // handle requests to ignite the lamp. - link_message(integer sender, integer num, string str, key id) { - // we only support one message really, which is to turn on/off. - if (num == SECRET_LIGHT_BULB_ILLUMINATI_CODE) { - state PowerUp; // we know we aren't lit yet, so get that way. - } - } -} - -state PowerUp -{ - state_entry() { - // light the bulb, with a full color / full bright assault on - // the sense, using real light and a glow effect. - llSetPrimitiveParams([ - PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 0.5, - PRIM_FULLBRIGHT, ALL_SIDES, TRUE, - PRIM_GLOW, ALL_SIDES, BULB_GLOW_LEVEL, - PRIM_POINT_LIGHT, TRUE, <.8, .8, .3>, 1.0, 20.0, .9 - ]); - turn_on_particles(); - llSetTimerEvent(DUSK_CHECKING_PERIOD); - } - on_rez(integer parm) { - // if we rezzed in this state, that's a mistake. the lamp is intended - // to start in a dark state. - turn_off_lamp(); - } - timer() { - particle_cog++; - if (particle_cog >= PARTICLE_FIX_COG) { - // periodically refresh the particle system. - turn_on_particles(); - particle_cog = 0; // reset cog count. - } - // also periodically check if we should shut off. - vector sun = llGetSunDirection(); - if (CHECK_FOR_DUSK && (sun.z > 0) ) { - // turn off at dawn. - turn_off_lamp(); - } - } - - touch_start(integer total_number) - { - turn_off_lamp(); - } - - link_message(integer sender, integer num, string str, key id) { - // we only support one message really, which is to turn on/off. - if (num == SECRET_LIGHT_BULB_ILLUMINATI_CODE) { - turn_off_lamp(); // in this state, we are already lit, so get real dark. - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.txt new file mode 100755 index 00000000..8f06aa13 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huffbee_bulb_v4.7.txt @@ -0,0 +1,252 @@ + +// huffware script: "huffbee bulb", by fred huffhines +// +// inspired by the higbee bulb script available in open source, but provides a few +// different functions. this accepts a click to turn on and off, but it also listens +// to a special command to hear requests from linked objects. this also shuts off +// at dusk and turns on at dawn. +// this script uses the party culiar script to get the particle system created, +// and hence relies on a notecard to define the lamp's particles. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer DUSK_CHECKING_PERIOD = 240; + // check for dusk this frequently. in seconds, so 240 = 4 minutes. + +integer SECRET_LIGHT_BULB_ILLUMINATI_CODE = -14058; + // a semi-secret code that is used in a linked message when some other script + // wants the lamp to turn on or off. + +float BULB_GLOW_LEVEL = 0.5; // how much glow should the bulb have when it's lit? + +integer CHECK_FOR_DUSK = TRUE; // true if this lamp should be driven by daylight. + +integer PARTICLE_FIX_COG = 7; // every N timer hits, we'll fix our particles. + +// party culiar link message API. +////////////// +integer PARTYCULIAR_HUFFWARE_ID = 10018; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. +// +string PARTYCULIAR_POWER_COMMAND = "#powrpcl"; + // tells the particle system to either turn on or off. the single parameter is + // either "on", "1", "true", or "off", "0", "false". +////////////// + +// globals. + +integer particle_cog = 0; + +////////////// + +// asks the particle system script for a favor, given by the command and the +// parameters. +send_partyculiar_request(string cmd, string params) +{ llMessageLinked(LINK_THIS, PARTYCULIAR_HUFFWARE_ID, cmd, params); } + +// shuts down the lamp. there is no coming back from this method, +// since it resets the script. +turn_off_lamp() +{ + turn_off_particles(); + llResetScript(); +} + +turn_off_particles() { send_partyculiar_request(PARTYCULIAR_POWER_COMMAND, "off"); } + +turn_on_particles() { send_partyculiar_request(PARTYCULIAR_POWER_COMMAND, "on"); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + turn_off_particles(); + // reset the bulb to a fairly dark color with no glow and no light. + llSetPrimitiveParams([ + PRIM_COLOR, ALL_SIDES, <0.42, 0.42, 0.42>, 0.5, + PRIM_FULLBRIGHT, ALL_SIDES, FALSE, + PRIM_GLOW, ALL_SIDES, 0.0, + PRIM_POINT_LIGHT, FALSE, <0, 0, 0>, 1.0, 10.0, 0.25 + ]); + llSetTimerEvent(DUSK_CHECKING_PERIOD); + } + on_rez(integer parm) { + state default; + } + timer() { + vector sun = llGetSunDirection(); + if (CHECK_FOR_DUSK && (sun.z <= 0) ) + state PowerUp; // turn on at dusk. + } + touch_start(integer total_number) { + state PowerUp; + } + + // handle requests to ignite the lamp. + link_message(integer sender, integer num, string str, key id) { + // we only support one message really, which is to turn on/off. + if (num == SECRET_LIGHT_BULB_ILLUMINATI_CODE) { + state PowerUp; // we know we aren't lit yet, so get that way. + } + } +} + +state PowerUp +{ + state_entry() { + // light the bulb, with a full color / full bright assault on + // the sense, using real light and a glow effect. + llSetPrimitiveParams([ + PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 0.5, + PRIM_FULLBRIGHT, ALL_SIDES, TRUE, + PRIM_GLOW, ALL_SIDES, BULB_GLOW_LEVEL, + PRIM_POINT_LIGHT, TRUE, <.8, .8, .3>, 1.0, 20.0, .9 + ]); + turn_on_particles(); + llSetTimerEvent(DUSK_CHECKING_PERIOD); + } + on_rez(integer parm) { + // if we rezzed in this state, that's a mistake. the lamp is intended + // to start in a dark state. + turn_off_lamp(); + } + timer() { + particle_cog++; + if (particle_cog >= PARTICLE_FIX_COG) { + // periodically refresh the particle system. + turn_on_particles(); + particle_cog = 0; // reset cog count. + } + // also periodically check if we should shut off. + vector sun = llGetSunDirection(); + if (CHECK_FOR_DUSK && (sun.z > 0) ) { + // turn off at dawn. + turn_off_lamp(); + } + } + + touch_start(integer total_number) + { + turn_off_lamp(); + } + + link_message(integer sender, integer num, string str, key id) { + // we only support one message really, which is to turn on/off. + if (num == SECRET_LIGHT_BULB_ILLUMINATI_CODE) { + turn_off_lamp(); // in this state, we are already lit, so get real dark. + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.lsl deleted file mode 100755 index aa9a0e18..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.lsl +++ /dev/null @@ -1,742 +0,0 @@ - -// huffware script: hufflets, by fred huffhines. -// -// functions that are commonly used but really are too simple to implement via IPC. -// these just get copied and pasted into other scripts. -// *note* that means you should not drop this script into an object. it will not -// do anything for you. instead, copy what you need out of here. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer DEBUGGING = FALSE; - // if this is set to true, then some functions produce noisier results. - -////////////// - -// diagnostic hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -////////////// - -// mathematical hufflets... - -// returns a floating point absolute value. -float fabs(float take_absolute_value) { - if (take_absolute_value >= 0.0) return take_absolute_value; - else return -1.0 * take_absolute_value; -} - -////////////// - -// time hufflets... - -// shows a somewhat pretty printed version of the number of seconds. -string time_text(integer seconds) -{ - float s_min = 60; float s_hour = 60 * s_min; float s_day = 24 * s_hour; - float s_year = 365.25 * s_day; - - if (seconds < s_min) return (string)seconds + " seconds"; - else if (seconds < s_hour) return float_chop(seconds / s_min) + " minutes"; - else if (seconds < s_day) return float_chop(seconds / s_hour) + " hours"; - else if (seconds < s_year) return float_chop(seconds / s_day) + " days"; - else return float_chop(seconds / s_year) + " years"; -} - -////////////// - -// string processing hufflets... - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// takes any redundant space characters out of the string. -string compress_spaces(string s) -{ - string to_return; - integer in_space = FALSE; - integer i; - for (i = 0; i < llStringLength(s); i++) { - string chunk = llGetSubString(s, i, i); - if (chunk == " ") { - if (in_space) { - // we're have already seen a space. don't keep this too. - //continue; no such keyword in lsl. - } else { - in_space = TRUE; - to_return += chunk; - } - } else { - // the current character was not a space, so just add it. - in_space = FALSE; - to_return += chunk; - } - } - return to_return; -} - -////////////// - -// sim-related hufflets... - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -////////////// - -// list processing hufflets... - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// removes the entry at "index" and instead inserts the list "to_insert" -// at that position. -list replace_entry(list to_modify, integer index, list to_insert) -{ - if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. - return llListReplaceList(to_modify, to_insert, index, index); -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -////////////// - -integer MAX_CHAT_LINE = 1008; - // the most characters we'll try to say in one chat. - -dump_list_to_log(list to_show) -{ - string text = dump_list(to_show); // get some help from the other version. - integer len = llStringLength(text); - integer i; - for (i = 0; i < len; i += MAX_CHAT_LINE) { - integer last_bit = i + MAX_CHAT_LINE - 1; - if (last_bit >= len) last_bit = len - 1; - string next_line = llGetSubString(text, i, last_bit); - log_it(next_line); - } -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "'" + next_line + "'"; - } - text = text + next_line; - if (i < len - 1) text = text + " "; - } - return text; -} - -// extracts space separated elements from a string, and honors quoting of either -// variety as long as the quotes come in pairs. this enables the inclusion of -// spaces in the elements of the set. note that this function requires a well-formed -// string where there are no multiple space characters in a row. -list parse_quoted_strings(string to_parse) -{ - list to_return; // will pile up what we find in the string. - integer quoting = FALSE; // are we inside quotes? - string curr_quote = ""; // what is current quote char, if any? - string accum; // accumulates parts of the current element. - // loop over the string and apply our rules. - integer i; - for (i = 0; i < llStringLength(to_parse); i++) { - string c = llGetSubString(to_parse, i, i); - if (!quoting && (c == " ")) { - // this space marks the end of a word. - if (llStringLength(accum) > 0) { -//log_it("space adding to set: " + accum); - to_return += [ accum ]; - accum = ""; - } - } else if (quoting && (c == curr_quote)) { - // done with quotes, so add the quoted item, even if nil. - to_return += [ accum ]; -//log_it("quote adding to set: " + accum); - accum = ""; - quoting = FALSE; - } else if (!quoting && ( (c == "'") || (c == "\"") ) ) { - // we've started into quoting mode. - quoting = TRUE; - curr_quote = c; - } else { - // if no condition applies, just add this to the accumulator. - accum += c; - } - } - // add the last thing we accumulated. - if (llStringLength(accum) > 0) { -//log_it("last add to set: " + accum); - to_return += [ accum ]; - } - return to_return; -} - -////////////// - -// action queue for postponed activities. the first field held in a list item here -// is an integer action code. the format of the remaining parameters is up to the -// caller, and they can be used as the final parameters for when the queued action -// gets handled. -list action_queue; - -// looks at the action code at the head of the queue without removing the action. -integer peek_action_code() -{ - list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - return extract_action_code(fields); -} - -// extracts the action code from a retrieved list. -integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } - -// removes the current head of the action queue and returns it. -list pop_action_record() -{ - if (llGetListLength(action_queue) == 0) { -//log_it("failure in action q: no entries."); - return []; - } - list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - action_queue = llDeleteSubList(action_queue, 0, 0); - return top_action; -} - -// adds a new action to the end of the action queue. -push_action_record(integer action, list added_parms) -{ - action_queue += [ wrap_parameters([action] + added_parms) ]; -} - -////////////// - -// randomizing hufflets... - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -////////////// - -// vector hufflets... - -// returns TRUE if a is less than b in any component. -integer vector_less_than(vector a, vector b) -{ return (a.x < b.x) || (a.y < b.y) || (a.z < b.z); } - -// returns TRUE if a is greater than b in any component. -integer vector_greater_than(vector a, vector b) -{ return (a.x > b.x) || (a.y > b.y) || (a.z > b.z); } - -// returns text for a floating point number, but includes only -// three digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 1000.0) / 1000); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// prints the list of vectors with trimmed floats. -string vector_list_chop(list to_show) -{ - integer list_len = llGetListLength(to_show); - string to_return; - integer indy; - for (indy = 0; indy < list_len; indy++) { - if (indy != 0) to_return += HUFFWARE_ITEM_SEPARATOR; - to_return += vector_chop((vector)llList2String(to_show, indy)); - } - return to_return; -} - -// returns a list with two components; a new vector and a boolean. -// the new vector starts from "starting_point". it will have a vector -// between "minimum_addition" and "maximum_addition" added to it. -// if it is over the "minimum_allowed" or the "maximum_allowed", then -// it is reset to whichever it would have crossed over. two booleans -// are also returned to indicate when the lower and upper limits were -// exceeded (in that order). -list limit_and_add(vector starting_point, - vector minimum_allowed, vector maximum_allowed, - vector minimum_addition, vector maximum_addition) -{ - integer too_low = FALSE; - integer too_high = FALSE; - vector new_location = starting_point; - vector addition = random_bound_vector(minimum_addition, maximum_addition, FALSE); -//log_it("start=" + (string)starting_point + " addin=" + (string)addition); - new_location += addition; - if (vector_less_than(new_location, minimum_allowed)) { - too_low = TRUE; - new_location = minimum_allowed; - } else if (vector_greater_than(new_location, maximum_allowed)) { - too_high = TRUE; - new_location = maximum_allowed; - } - return [ new_location, too_low, too_high ]; -} - -////////////// - -// SL name hufflets... - -// returns the position of the last space in "look_within" or a negative number. -integer find_last_space(string look_within) -{ - integer indy = llStringLength(look_within) - 1; - while ( (indy >= 0) && (llGetSubString(look_within, indy, indy) != " ") ) indy--; - return indy; -} - -// returns the first name for an avatar with the "full_name". -string first_name(string full_name) -{ - integer finding = find_last_space(full_name); - if (finding >= 0) return llGetSubString(full_name, 0, finding - 1); - return full_name; // failed to find space. -} - -// returns the last name for an avatar with the "full_name". -string last_name(string full_name) -{ - integer finding = find_last_space(full_name); - if (finding >= 0) return llGetSubString(full_name, finding + 1, -1); - return full_name; // failed to find space. -} - -////////////// - -// variable handling hufflets... - -// substitutes a variable's name for its value. note that variables are assumed to start -// with a dollar sign character, which should not be provided in the "variable_name" parameter. -string substitute_variable(string substitute_within, string variable_name, string variable_value) -{ - string to_return = substitute_within; -//log_it("before var sub: " + substitute_within); - integer posn; - while ( (posn = find_substring(to_return, "$" + variable_name)) >= 0) { - // we found an occurrence of the variable. - to_return = llDeleteSubString(to_return, posn, -1) // keep part before. - + variable_value // add the value in place of the variable name. - + llDeleteSubString(to_return, 0, posn + llStringLength(variable_name)); - // keep part after. - } -//log_it("after var sub: " + to_return); - return to_return; -} - -// in "substitute_within", this finds any occurrences of items in the "variables_names" -// and replaces those with the corresponding item from "variable_values". -// note: this can be very stack intensive, so it might be better just to use multiple -// calls to the substitute_variable function. -string substitute_variable_list(string substitute_within, list variable_names, list variable_values) -{ - string to_return = substitute_within; - integer vars = llGetListLength(variable_names); - if (vars != llGetListLength(variable_values)) { - log_it("error in substitute_variable_list: inequal number of variable names vs. values."); - return to_return; - } - integer indy; - for (indy = 0; indy < vars; indy++) { - to_return = substitute_variable(to_return, - llList2String(variable_names, indy), - llList2String(variable_values, indy)); - } - return to_return; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ llStringTrim(x, STRING_TRIM), llStringTrim(y, STRING_TRIM) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -////////////// - -// inventory hufflets... - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} - -// looks for an inventory item with the same prefix as the "basename_to_seek". -integer find_basename_in_inventory(string basename_to_seek, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer indy; - for (indy = 0; indy < num_inv; indy++) { - if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) - return indy; - } - return -2; // failed to find it. -} - -////////////// -// -// imported from auto-retire, which is the official source!... -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); -} - -////////////// - -// interprocess communication hufflets... i.e., IPC parts. - -// a repository for commonly used inter-process communication (IPC) source -// code. hopefully in the future this will be worthwhile coming to first, -// when a new link message API is being built. - -// an example link message API... -////////////// -integer SERVICE_X_HUFFWARE_ID = -14000; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// - -// then the main body of IPC support functions. - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// handles when blank strings need to come through the pipe. -string wrap_blank_string(string to_wrap) -{ - if (llStringLength(to_wrap)) return to_wrap; // that one is okay. - return "\"\""; // return a quoted nothing as a signal for a blank. -} - -// undoes a previously wrapped blank string. -string interpret_blank_string(string to_unwrap) -{ - if (to_unwrap == "\"\"") return ""; // that was an encoded blank. - return to_unwrap; // no encoding. -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, SERVICE_X_HUFFWARE_ID + REPLY_DISTANCE, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// this should be invoked from the link_message event handler to process the requests -// for whatever service this library script provides. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ -log_it("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); - // this check is more for the server; the server should listen on the main huffware id. - if (huff_id != SERVICE_X_HUFFWARE_ID) { - // the check below would make more sense in the client; it should listen on huffware id + REPLY_DISTANCE. - if (huff_id != SERVICE_X_HUFFWARE_ID + REPLY_DISTANCE) return; // totally not for us. - // this is a reply to a previous request. - if (msg == "moobert") { - // handle the response. - } - // done with reply handling. - return; - } - // separate the list out - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - - //example usage of parsed pieces. - key k = (key)llList2String(parms, 0); - string s = interpret_blank_string(llList2String(parms, 1)); - integer i = (integer)llList2String(parms, 2); - vector v = (vector)llList2String(parms, 3); - - // we interpret the "msg" as a command. the "id" has extra parameters. - if (msg == "unflux") { - // do something - } -} - -////////////// - -// graphical hufflets... - -// a replacement for the deprecated llMakeExplosion function; this bangs the -// "texture" out as a particle with the "size" in meters. the number of -// particles in a burst is passed in "particle_count". the function will -// generate a timer event after "timeout" seconds (pass zero for no timeout). -make_explosion(string texture, vector size, integer particle_count, - float timeout) -{ - llParticleSystem([PSYS_PART_FLAGS, PSYS_PART_WIND_MASK | PSYS_PART_EMISSIVE_MASK, - PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE, - PSYS_PART_START_SCALE, size, - PSYS_PART_END_SCALE, size, - PSYS_SRC_BURST_PART_COUNT, particle_count, - PSYS_PART_MAX_AGE, 2, - PSYS_SRC_TEXTURE, texture]); - llSetTimerEvent(timeout); -} -// the event handler for the particle system to be shut down again. -//timer() { llParticleSystem([]); } - -////////////// - -// the following state mumbo jumbo is so that our scripts do not go crazy when the huffotronic -// updater is rezzed. that device has most of our scripts in it, and cannot always crush their -// state fast enough to stop them all. -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - log_it("memory left " + (string)llGetFreeMemory()); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.txt new file mode 100755 index 00000000..aa9a0e18 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/hufflets_v6.3.txt @@ -0,0 +1,742 @@ + +// huffware script: hufflets, by fred huffhines. +// +// functions that are commonly used but really are too simple to implement via IPC. +// these just get copied and pasted into other scripts. +// *note* that means you should not drop this script into an object. it will not +// do anything for you. instead, copy what you need out of here. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer DEBUGGING = FALSE; + // if this is set to true, then some functions produce noisier results. + +////////////// + +// diagnostic hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +////////////// + +// mathematical hufflets... + +// returns a floating point absolute value. +float fabs(float take_absolute_value) { + if (take_absolute_value >= 0.0) return take_absolute_value; + else return -1.0 * take_absolute_value; +} + +////////////// + +// time hufflets... + +// shows a somewhat pretty printed version of the number of seconds. +string time_text(integer seconds) +{ + float s_min = 60; float s_hour = 60 * s_min; float s_day = 24 * s_hour; + float s_year = 365.25 * s_day; + + if (seconds < s_min) return (string)seconds + " seconds"; + else if (seconds < s_hour) return float_chop(seconds / s_min) + " minutes"; + else if (seconds < s_day) return float_chop(seconds / s_hour) + " hours"; + else if (seconds < s_year) return float_chop(seconds / s_day) + " days"; + else return float_chop(seconds / s_year) + " years"; +} + +////////////// + +// string processing hufflets... + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// takes any redundant space characters out of the string. +string compress_spaces(string s) +{ + string to_return; + integer in_space = FALSE; + integer i; + for (i = 0; i < llStringLength(s); i++) { + string chunk = llGetSubString(s, i, i); + if (chunk == " ") { + if (in_space) { + // we're have already seen a space. don't keep this too. + //continue; no such keyword in lsl. + } else { + in_space = TRUE; + to_return += chunk; + } + } else { + // the current character was not a space, so just add it. + in_space = FALSE; + to_return += chunk; + } + } + return to_return; +} + +////////////// + +// sim-related hufflets... + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +////////////// + +// list processing hufflets... + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// removes the entry at "index" and instead inserts the list "to_insert" +// at that position. +list replace_entry(list to_modify, integer index, list to_insert) +{ + if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. + return llListReplaceList(to_modify, to_insert, index, index); +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +////////////// + +integer MAX_CHAT_LINE = 1008; + // the most characters we'll try to say in one chat. + +dump_list_to_log(list to_show) +{ + string text = dump_list(to_show); // get some help from the other version. + integer len = llStringLength(text); + integer i; + for (i = 0; i < len; i += MAX_CHAT_LINE) { + integer last_bit = i + MAX_CHAT_LINE - 1; + if (last_bit >= len) last_bit = len - 1; + string next_line = llGetSubString(text, i, last_bit); + log_it(next_line); + } +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "'" + next_line + "'"; + } + text = text + next_line; + if (i < len - 1) text = text + " "; + } + return text; +} + +// extracts space separated elements from a string, and honors quoting of either +// variety as long as the quotes come in pairs. this enables the inclusion of +// spaces in the elements of the set. note that this function requires a well-formed +// string where there are no multiple space characters in a row. +list parse_quoted_strings(string to_parse) +{ + list to_return; // will pile up what we find in the string. + integer quoting = FALSE; // are we inside quotes? + string curr_quote = ""; // what is current quote char, if any? + string accum; // accumulates parts of the current element. + // loop over the string and apply our rules. + integer i; + for (i = 0; i < llStringLength(to_parse); i++) { + string c = llGetSubString(to_parse, i, i); + if (!quoting && (c == " ")) { + // this space marks the end of a word. + if (llStringLength(accum) > 0) { +//log_it("space adding to set: " + accum); + to_return += [ accum ]; + accum = ""; + } + } else if (quoting && (c == curr_quote)) { + // done with quotes, so add the quoted item, even if nil. + to_return += [ accum ]; +//log_it("quote adding to set: " + accum); + accum = ""; + quoting = FALSE; + } else if (!quoting && ( (c == "'") || (c == "\"") ) ) { + // we've started into quoting mode. + quoting = TRUE; + curr_quote = c; + } else { + // if no condition applies, just add this to the accumulator. + accum += c; + } + } + // add the last thing we accumulated. + if (llStringLength(accum) > 0) { +//log_it("last add to set: " + accum); + to_return += [ accum ]; + } + return to_return; +} + +////////////// + +// action queue for postponed activities. the first field held in a list item here +// is an integer action code. the format of the remaining parameters is up to the +// caller, and they can be used as the final parameters for when the queued action +// gets handled. +list action_queue; + +// looks at the action code at the head of the queue without removing the action. +integer peek_action_code() +{ + list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + return extract_action_code(fields); +} + +// extracts the action code from a retrieved list. +integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } + +// removes the current head of the action queue and returns it. +list pop_action_record() +{ + if (llGetListLength(action_queue) == 0) { +//log_it("failure in action q: no entries."); + return []; + } + list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + action_queue = llDeleteSubList(action_queue, 0, 0); + return top_action; +} + +// adds a new action to the end of the action queue. +push_action_record(integer action, list added_parms) +{ + action_queue += [ wrap_parameters([action] + added_parms) ]; +} + +////////////// + +// randomizing hufflets... + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +////////////// + +// vector hufflets... + +// returns TRUE if a is less than b in any component. +integer vector_less_than(vector a, vector b) +{ return (a.x < b.x) || (a.y < b.y) || (a.z < b.z); } + +// returns TRUE if a is greater than b in any component. +integer vector_greater_than(vector a, vector b) +{ return (a.x > b.x) || (a.y > b.y) || (a.z > b.z); } + +// returns text for a floating point number, but includes only +// three digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 1000.0) / 1000); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// prints the list of vectors with trimmed floats. +string vector_list_chop(list to_show) +{ + integer list_len = llGetListLength(to_show); + string to_return; + integer indy; + for (indy = 0; indy < list_len; indy++) { + if (indy != 0) to_return += HUFFWARE_ITEM_SEPARATOR; + to_return += vector_chop((vector)llList2String(to_show, indy)); + } + return to_return; +} + +// returns a list with two components; a new vector and a boolean. +// the new vector starts from "starting_point". it will have a vector +// between "minimum_addition" and "maximum_addition" added to it. +// if it is over the "minimum_allowed" or the "maximum_allowed", then +// it is reset to whichever it would have crossed over. two booleans +// are also returned to indicate when the lower and upper limits were +// exceeded (in that order). +list limit_and_add(vector starting_point, + vector minimum_allowed, vector maximum_allowed, + vector minimum_addition, vector maximum_addition) +{ + integer too_low = FALSE; + integer too_high = FALSE; + vector new_location = starting_point; + vector addition = random_bound_vector(minimum_addition, maximum_addition, FALSE); +//log_it("start=" + (string)starting_point + " addin=" + (string)addition); + new_location += addition; + if (vector_less_than(new_location, minimum_allowed)) { + too_low = TRUE; + new_location = minimum_allowed; + } else if (vector_greater_than(new_location, maximum_allowed)) { + too_high = TRUE; + new_location = maximum_allowed; + } + return [ new_location, too_low, too_high ]; +} + +////////////// + +// SL name hufflets... + +// returns the position of the last space in "look_within" or a negative number. +integer find_last_space(string look_within) +{ + integer indy = llStringLength(look_within) - 1; + while ( (indy >= 0) && (llGetSubString(look_within, indy, indy) != " ") ) indy--; + return indy; +} + +// returns the first name for an avatar with the "full_name". +string first_name(string full_name) +{ + integer finding = find_last_space(full_name); + if (finding >= 0) return llGetSubString(full_name, 0, finding - 1); + return full_name; // failed to find space. +} + +// returns the last name for an avatar with the "full_name". +string last_name(string full_name) +{ + integer finding = find_last_space(full_name); + if (finding >= 0) return llGetSubString(full_name, finding + 1, -1); + return full_name; // failed to find space. +} + +////////////// + +// variable handling hufflets... + +// substitutes a variable's name for its value. note that variables are assumed to start +// with a dollar sign character, which should not be provided in the "variable_name" parameter. +string substitute_variable(string substitute_within, string variable_name, string variable_value) +{ + string to_return = substitute_within; +//log_it("before var sub: " + substitute_within); + integer posn; + while ( (posn = find_substring(to_return, "$" + variable_name)) >= 0) { + // we found an occurrence of the variable. + to_return = llDeleteSubString(to_return, posn, -1) // keep part before. + + variable_value // add the value in place of the variable name. + + llDeleteSubString(to_return, 0, posn + llStringLength(variable_name)); + // keep part after. + } +//log_it("after var sub: " + to_return); + return to_return; +} + +// in "substitute_within", this finds any occurrences of items in the "variables_names" +// and replaces those with the corresponding item from "variable_values". +// note: this can be very stack intensive, so it might be better just to use multiple +// calls to the substitute_variable function. +string substitute_variable_list(string substitute_within, list variable_names, list variable_values) +{ + string to_return = substitute_within; + integer vars = llGetListLength(variable_names); + if (vars != llGetListLength(variable_values)) { + log_it("error in substitute_variable_list: inequal number of variable names vs. values."); + return to_return; + } + integer indy; + for (indy = 0; indy < vars; indy++) { + to_return = substitute_variable(to_return, + llList2String(variable_names, indy), + llList2String(variable_values, indy)); + } + return to_return; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ llStringTrim(x, STRING_TRIM), llStringTrim(y, STRING_TRIM) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +////////////// + +// inventory hufflets... + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} + +// looks for an inventory item with the same prefix as the "basename_to_seek". +integer find_basename_in_inventory(string basename_to_seek, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer indy; + for (indy = 0; indy < num_inv; indy++) { + if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) + return indy; + } + return -2; // failed to find it. +} + +////////////// +// +// imported from auto-retire, which is the official source!... +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); +} + +////////////// + +// interprocess communication hufflets... i.e., IPC parts. + +// a repository for commonly used inter-process communication (IPC) source +// code. hopefully in the future this will be worthwhile coming to first, +// when a new link message API is being built. + +// an example link message API... +////////////// +integer SERVICE_X_HUFFWARE_ID = -14000; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// + +// then the main body of IPC support functions. + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// handles when blank strings need to come through the pipe. +string wrap_blank_string(string to_wrap) +{ + if (llStringLength(to_wrap)) return to_wrap; // that one is okay. + return "\"\""; // return a quoted nothing as a signal for a blank. +} + +// undoes a previously wrapped blank string. +string interpret_blank_string(string to_unwrap) +{ + if (to_unwrap == "\"\"") return ""; // that was an encoded blank. + return to_unwrap; // no encoding. +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, SERVICE_X_HUFFWARE_ID + REPLY_DISTANCE, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// this should be invoked from the link_message event handler to process the requests +// for whatever service this library script provides. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ +log_it("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); + // this check is more for the server; the server should listen on the main huffware id. + if (huff_id != SERVICE_X_HUFFWARE_ID) { + // the check below would make more sense in the client; it should listen on huffware id + REPLY_DISTANCE. + if (huff_id != SERVICE_X_HUFFWARE_ID + REPLY_DISTANCE) return; // totally not for us. + // this is a reply to a previous request. + if (msg == "moobert") { + // handle the response. + } + // done with reply handling. + return; + } + // separate the list out + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + + //example usage of parsed pieces. + key k = (key)llList2String(parms, 0); + string s = interpret_blank_string(llList2String(parms, 1)); + integer i = (integer)llList2String(parms, 2); + vector v = (vector)llList2String(parms, 3); + + // we interpret the "msg" as a command. the "id" has extra parameters. + if (msg == "unflux") { + // do something + } +} + +////////////// + +// graphical hufflets... + +// a replacement for the deprecated llMakeExplosion function; this bangs the +// "texture" out as a particle with the "size" in meters. the number of +// particles in a burst is passed in "particle_count". the function will +// generate a timer event after "timeout" seconds (pass zero for no timeout). +make_explosion(string texture, vector size, integer particle_count, + float timeout) +{ + llParticleSystem([PSYS_PART_FLAGS, PSYS_PART_WIND_MASK | PSYS_PART_EMISSIVE_MASK, + PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE, + PSYS_PART_START_SCALE, size, + PSYS_PART_END_SCALE, size, + PSYS_SRC_BURST_PART_COUNT, particle_count, + PSYS_PART_MAX_AGE, 2, + PSYS_SRC_TEXTURE, texture]); + llSetTimerEvent(timeout); +} +// the event handler for the particle system to be shut down again. +//timer() { llParticleSystem([]); } + +////////////// + +// the following state mumbo jumbo is so that our scripts do not go crazy when the huffotronic +// updater is rezzed. that device has most of our scripts in it, and cannot always crush their +// state fast enough to stop them all. +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + log_it("memory left " + (string)llGetFreeMemory()); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.lsl deleted file mode 100755 index d2bd4e69..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.lsl +++ /dev/null @@ -1,44 +0,0 @@ - -linked message IDs used already: - - 10008 jaunter library - teleportation and physics helper methods. - 10009 menutini library - a menuing system for requesting input from the avatar. - 10010 noteworthy library - reads notecards with a specific signature. - 10011 sitting script - alerts when avatar sits down. - 10012 remotely personable - can be told what text label to show and when to hide itself, plus *dancing*. - 10013 hud manager - can control the hud links at behest of other scripts. - 10014 sensor plugin - runs a hud manager by putting names of avatars up on buttons. - 10015 hud configurator - loads a configuration file for the HUD it lives in. - 10016 hud menu manager - accepts a set of menus and customizes them to the avatar. - 10017 data cow - manages a list of text. - 10018 party culiar particle system. - 10019 hud substituter - replaces patterns inside strings for the hud. - 10020 set comparator - provides operations on sets. - 10021 inventory exchanger - allows a root prim to keep its child prims synched. - 10022 jaunt configuration - a split piece of jaunt wik rez that handles config. - 10023 avatar timer manager - tracks time available to an avatar and generates alerts. - 10024 change click action - makes the object behave differently when clicked. - 10025 jaunt rezolator - handling of children rezzed by root jaunter. - 10026 avatar choice memory - tracks which items an avatar has already chosen. - 10027 viewscreen blitter - handles requests to show URLs and textures in opensim. - 10028 slate reader - manages notecards filled with readable information. - 10029 jaunter button pusher - specialized button pusher for jaunter-style teleporters. - 10030 sound player - triggers the playing of sound files from inventory. - 10031 animote configula - ejected configuration and menu functions to reduce memory usage. - 10032 huff-search pointer - supports searchbert and other search engines. - 10033 menu list manager - generalized management of a collection of menus. - 10034 searchbert menus - controller actions for searchbert's menu system. - 10035 general button pusher - used by prim buttons to signal that they have been clicked. - ... - 10042 card configurator - uses noteworthy to process notecards into lists of configuration items. - -script pins in use, at the moment: - -100008 unused? - -reply distance: - REPLY_DISTANCE = 100008 - this amount is added to the huffware ID to get the reply ID of the service. - -on rez IDs for communicating information to created object: - 10008 auto-rez jaunter startup code - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.txt new file mode 100755 index 00000000..d2bd4e69 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/huffware_id_registry_v3.2.txt @@ -0,0 +1,44 @@ + +linked message IDs used already: + + 10008 jaunter library - teleportation and physics helper methods. + 10009 menutini library - a menuing system for requesting input from the avatar. + 10010 noteworthy library - reads notecards with a specific signature. + 10011 sitting script - alerts when avatar sits down. + 10012 remotely personable - can be told what text label to show and when to hide itself, plus *dancing*. + 10013 hud manager - can control the hud links at behest of other scripts. + 10014 sensor plugin - runs a hud manager by putting names of avatars up on buttons. + 10015 hud configurator - loads a configuration file for the HUD it lives in. + 10016 hud menu manager - accepts a set of menus and customizes them to the avatar. + 10017 data cow - manages a list of text. + 10018 party culiar particle system. + 10019 hud substituter - replaces patterns inside strings for the hud. + 10020 set comparator - provides operations on sets. + 10021 inventory exchanger - allows a root prim to keep its child prims synched. + 10022 jaunt configuration - a split piece of jaunt wik rez that handles config. + 10023 avatar timer manager - tracks time available to an avatar and generates alerts. + 10024 change click action - makes the object behave differently when clicked. + 10025 jaunt rezolator - handling of children rezzed by root jaunter. + 10026 avatar choice memory - tracks which items an avatar has already chosen. + 10027 viewscreen blitter - handles requests to show URLs and textures in opensim. + 10028 slate reader - manages notecards filled with readable information. + 10029 jaunter button pusher - specialized button pusher for jaunter-style teleporters. + 10030 sound player - triggers the playing of sound files from inventory. + 10031 animote configula - ejected configuration and menu functions to reduce memory usage. + 10032 huff-search pointer - supports searchbert and other search engines. + 10033 menu list manager - generalized management of a collection of menus. + 10034 searchbert menus - controller actions for searchbert's menu system. + 10035 general button pusher - used by prim buttons to signal that they have been clicked. + ... + 10042 card configurator - uses noteworthy to process notecards into lists of configuration items. + +script pins in use, at the moment: + -100008 unused? + +reply distance: + REPLY_DISTANCE = 100008 + this amount is added to the huffware ID to get the reply ID of the service. + +on rez IDs for communicating information to created object: + 10008 auto-rez jaunter startup code + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.lsl deleted file mode 100755 index 7a5b6cd2..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.lsl +++ /dev/null @@ -1,488 +0,0 @@ - -// huffware script: inventory exchanger, by fred huffhines. -// -// manages inventory between a root prim and its children. this script should be placed in -// all prims that need to exchange contents. the root prim drives the exchange process based -// on a registered set of assets that it is told to synchronize in each child. all the child -// prims that have this script will ensure they are up to date with respect to those assets. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// inventory exchanger link message API... -////////////// -// do not redefine these constants. -integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the library: -string REGISTER_ASSETS_COMMAND = "#regis#"; - // makes the root prim's inventory exchanger track a set of items which each participating - // child prim should have. this command is only available to the root prim; child prims - // cannot register any assets but instead can get updates on the assets. the parameter - // required is a list of asset definitions, wrapped by the huffware parm separator. each - // asset definition is in turn a two part list wrapped with the asset field separator. -string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. -string WILDCARD_INVENTORY_NAME = "ALL"; - // this keyword can be used to register all of the inventory items available of the - // specified type. this should be passed as the inventory item name in the second half of - // an asset definition list. -string WHACK_INVENTORY_SIGNAL = "DEL*"; - // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. -string AVAILABLE_ASSETS_EVENT = "#gotz#"; - // the root prim publishes this event to list out what items it has available. the child - // prims need to ask for anything that they're currently missing. the included parameters - // are in the same format as the register assets command, but no wildcards will be present; - // all asset names will be fully expanded. -string REQUEST_UPDATES = "#nupd#"; - // used by the child prim to request an updated version of an asset or assets. the parameters - // should follow the register assets command. -string FINISHED_UPDATING = "#donq#"; - // a signal sent from the root prim to the child prim when the root has finished updating - // the assets requested. this lets the child know that it can clean out any outdated versions - // of items which got an update. there are no parameters to this, because the child prim - // should have at most one update outstanding at a time. -////////////// - -// constants... - -integer TIMER_PERIOD = 600; // the rate at which the root sends out updates (in seconds). - -integer INVEXCH_SCRIPT_PIN = -343781294; // used to slam scripts into the target prim. - -// global variables... - -list assets_available; - // the set of items that we will provide on demand. this list has items wrapped with the - // asset separator, where the unwrapped entries each provide the type (integer) and the - // name of the item. - -// gives out items that are asked for in "requested_assets". these go from the -// root prim into the kids. -populate_child_prim(integer link_num, list requested_assets) -{ - key asking_child = llGetLinkKey(link_num); // the kid that needs the update. - // look at the assets one by one and pass them over. - integer undy; - for (undy = 0; undy < llGetListLength(requested_assets); undy++) { - // unwrap the next asset definition from the requests. - list asset_def = llParseString2List(llList2String(requested_assets, undy), - [ASSET_FIELD_SEPARATOR], []); - integer type = llList2Integer(asset_def, 0); - string name = llList2String(asset_def, 1); -//log_it("root is giving link " + (string)link_num + " item " + name); - // fork over the item itself. - if (type != INVENTORY_SCRIPT) { - llGiveInventory(asking_child, name); - } else { - llRemoteLoadScriptPin(asking_child, name, INVEXCH_SCRIPT_PIN, TRUE, 0); - } - } - - // we send this event when done updating the kid. - llMessageLinked(link_num, INVENTORY_EXCHANGER_HUFFWARE_ID, FINISHED_UPDATING, NULL_KEY); -} - -// changes the run state of all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - // we won't start anything if we're running inside the updater object. - if (find_substring(llGetObjectName(), "huffotronic") >= 0) return; - - integer indy; - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if (curr_script != self_script) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -// kicks forward the periodic activities of the exchange process. -handle_timer() -{ - if (llGetLinkNumber() != 1) { - // child prim activities only. -// knock_around_other_scripts(TRUE); - return; - } else { - // the rest are root prim timer activities. - if (llGetListLength(assets_available) == 0) return; // nothing to do here. - // the root needs to send out link messages telling kids what good stuff its got. - llMessageLinked(LINK_ALL_CHILDREN, INVENTORY_EXCHANGER_HUFFWARE_ID, - AVAILABLE_ASSETS_EVENT, wrap_parameters(assets_available)); - } - -} - -// given a packed up list of items, this breaks out each asset definition and -// begins using the set as our full list of available items. -consume_asset_registration(string packed_assets) -{ - assets_available = llParseString2List(packed_assets, [HUFFWARE_PARM_SEPARATOR], []); -//hmmm: future enhancement might be to allow multiple clients of the root exchanger. -// currently we only support one script inside the root prim listing assets for inv exch. -// that's shown just above where we're just replacing the entire registered assets list. - - integer indy; - for (indy = 0; indy < llGetListLength(assets_available); indy++) { - list asset_def = llParseString2List(llList2String(assets_available, indy), - [ASSET_FIELD_SEPARATOR], []); - integer type = llList2Integer(asset_def, 0); - string name = llList2String(asset_def, 1); - if (name == WILDCARD_INVENTORY_NAME) { - // argh, we need to patch up the list for a wildcard option. - // first, whack the item with the wildcard in it. - assets_available = llDeleteSubList(assets_available, indy, indy); - // now revert the list index for the missing item. - indy--; - // and finally add all the items of that type. if one of them is named - // after the wildcard character, well, we disallow that craziness. - integer inv_pos; - for (inv_pos = 0; inv_pos < llGetInventoryNumber(type); inv_pos++) { - string inv_name = llGetInventoryName(type, inv_pos); - if (inv_name != WILDCARD_INVENTORY_NAME) { -//log_it("added wild: " + inv_name); - assets_available += [ llDumpList2String([type, inv_name], ASSET_FIELD_SEPARATOR) ]; - } - } - - } - } - - // make sure we get this new set out to the interested parties. - handle_timer(); -} - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); -log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -// has been called destroy_older_versions in other scripts. -clean_outdated_items() -{ - scrub_items_by_type(llGetScriptName(), INVENTORY_ALL); - // after cleaning up, make sure everything's running. - knock_around_other_scripts(TRUE); -} - -// locates the index of a specified type of inventory item with a particular name, -// or returns a negative number. -integer find_inventory(integer type, string name) -{ - integer indy; - for (indy = 0; indy < llGetInventoryNumber(type); indy++) { - if (name == llGetInventoryName(type, indy)) return indy; - } - return -1; -} - -// called on child prims to make sure they have everything the root does. -examine_inventory_freshness(string packed_assets) -{ - list missing_goods; // fill this with the things we don't have in this prim. - list provisions = llParseString2List(packed_assets, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - // scan through all the items that are available and make sure we have each of them. - for (indy = 0; indy < llGetListLength(provisions); indy++) { - string prov = llList2String(provisions, indy); - list fields = llParseString2List(prov, [ASSET_FIELD_SEPARATOR], []); -//log_it("checking: " + llList2String(fields, 1) + " type=" + (string)llList2Integer(fields, 0)); - // look for the type and name specified. - integer type = llList2Integer(fields, 0); - string name = llList2String(fields, 1); - if (name == WHACK_INVENTORY_SIGNAL) { - // we see our special signifier, so remove all items of the type specified. - // yes, this is dangerous. - integer delo; - for (delo = llGetInventoryNumber(type) - 1; delo >= 0; delo--) { - llRemoveInventory(llGetInventoryName(type, delo)); - } - } else { - integer found = find_inventory(type, name); - if (found < 0) { -//log_it("found " + llList2String(fields, 1) + " was missing!"); - // well, we are out of this one. tell the root we want it. - missing_goods += [ prov ]; - } - } - } - if (llGetListLength(missing_goods) > 0) { - // well we found some things that we're supposed to have, but do not. we will - // get the root prim to fix us up. - llMessageLinked(LINK_ROOT, INVENTORY_EXCHANGER_HUFFWARE_ID, - REQUEST_UPDATES, wrap_parameters(missing_goods)); - } -} - -//hmmm: this is not such a good model? why do the root and -// the child both need to be running this check on a timer? - -// processes inventory exchange commands in the root prim. this is where assets must -// be present so they can be distributed to the child prims. -process_root_msg(integer link_num, integer service, string cmd, key parms) -{ - if (service != INVENTORY_EXCHANGER_HUFFWARE_ID) return; // not for us. -//string name="root"; -//if (llGetLinkNumber() != 1) name="child"; -//log_it(name + " got request " + cmd); - if (link_num == 1) { - // this request is also from the root prim, where this script lives currently. - if (cmd == REGISTER_ASSETS_COMMAND) { - // root prim accepts a list of assets to provide to the kids. - consume_asset_registration(parms); - } - } else { - // a request is coming from a child prim. - if (cmd == REQUEST_UPDATES) { - // the root prim responds to update requests by handing out presents. - populate_child_prim(link_num, llParseString2List(parms, [HUFFWARE_PARM_SEPARATOR], [])); - } - } -} - -// implements the child API, mainly to track missing assets and clean out outdated items. -process_child_msg(integer link_num, integer service, string cmd, key parms) -{ - if (service != INVENTORY_EXCHANGER_HUFFWARE_ID) return; // not for us. - if (link_num != 1) return; // we don't listen to any chatter from other children. - if (cmd == AVAILABLE_ASSETS_EVENT) { - examine_inventory_freshness(parms); - } else if (cmd == FINISHED_UPDATING) { - clean_outdated_items(); - } -} - -// main processing function for the link messge API. -handle_link_message(integer link_num, integer service, string cmd, key parms) -{ - if (llGetLinkNumber() == 1) process_root_msg(link_num, service, cmd, parms); - else process_child_msg(link_num, service, cmd, parms); -} - -////////////// -// beginning of hufflets... -////////////// - -// diagnostic hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// joins a list of sub-items using the item sentinel for the library. -//string wrap_item_list(list to_wrap) -//{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -// end hufflets -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); -///log_it("\n\n\n\n\n\n\n\n\n** starting now............................"); - // register child prims for script replacement. - if (llGetLinkNumber() != 1) llSetRemoteScriptAccessPin(INVEXCH_SCRIPT_PIN); - //new idea; only allow timers to run in root prim. - if (llGetLinkNumber() == 1) llSetTimerEvent(TIMER_PERIOD); - knock_around_other_scripts(TRUE); - // first run happens right at startup. - if (llGetLinkNumber() == 1) handle_timer(); - } - - timer() { - llSetTimerEvent(0); // stop timer. - handle_timer(); - llSetTimerEvent(TIMER_PERIOD); // start timer. - } - - link_message(integer link_num, integer service, string cmd, key parms) { - handle_link_message(link_num, service, cmd, parms); - } -} - - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.txt new file mode 100755 index 00000000..7a5b6cd2 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/inventory_exchanger_v3.7.txt @@ -0,0 +1,488 @@ + +// huffware script: inventory exchanger, by fred huffhines. +// +// manages inventory between a root prim and its children. this script should be placed in +// all prims that need to exchange contents. the root prim drives the exchange process based +// on a registered set of assets that it is told to synchronize in each child. all the child +// prims that have this script will ensure they are up to date with respect to those assets. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// inventory exchanger link message API... +////////////// +// do not redefine these constants. +integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the library: +string REGISTER_ASSETS_COMMAND = "#regis#"; + // makes the root prim's inventory exchanger track a set of items which each participating + // child prim should have. this command is only available to the root prim; child prims + // cannot register any assets but instead can get updates on the assets. the parameter + // required is a list of asset definitions, wrapped by the huffware parm separator. each + // asset definition is in turn a two part list wrapped with the asset field separator. +string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. +string WILDCARD_INVENTORY_NAME = "ALL"; + // this keyword can be used to register all of the inventory items available of the + // specified type. this should be passed as the inventory item name in the second half of + // an asset definition list. +string WHACK_INVENTORY_SIGNAL = "DEL*"; + // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. +string AVAILABLE_ASSETS_EVENT = "#gotz#"; + // the root prim publishes this event to list out what items it has available. the child + // prims need to ask for anything that they're currently missing. the included parameters + // are in the same format as the register assets command, but no wildcards will be present; + // all asset names will be fully expanded. +string REQUEST_UPDATES = "#nupd#"; + // used by the child prim to request an updated version of an asset or assets. the parameters + // should follow the register assets command. +string FINISHED_UPDATING = "#donq#"; + // a signal sent from the root prim to the child prim when the root has finished updating + // the assets requested. this lets the child know that it can clean out any outdated versions + // of items which got an update. there are no parameters to this, because the child prim + // should have at most one update outstanding at a time. +////////////// + +// constants... + +integer TIMER_PERIOD = 600; // the rate at which the root sends out updates (in seconds). + +integer INVEXCH_SCRIPT_PIN = -343781294; // used to slam scripts into the target prim. + +// global variables... + +list assets_available; + // the set of items that we will provide on demand. this list has items wrapped with the + // asset separator, where the unwrapped entries each provide the type (integer) and the + // name of the item. + +// gives out items that are asked for in "requested_assets". these go from the +// root prim into the kids. +populate_child_prim(integer link_num, list requested_assets) +{ + key asking_child = llGetLinkKey(link_num); // the kid that needs the update. + // look at the assets one by one and pass them over. + integer undy; + for (undy = 0; undy < llGetListLength(requested_assets); undy++) { + // unwrap the next asset definition from the requests. + list asset_def = llParseString2List(llList2String(requested_assets, undy), + [ASSET_FIELD_SEPARATOR], []); + integer type = llList2Integer(asset_def, 0); + string name = llList2String(asset_def, 1); +//log_it("root is giving link " + (string)link_num + " item " + name); + // fork over the item itself. + if (type != INVENTORY_SCRIPT) { + llGiveInventory(asking_child, name); + } else { + llRemoteLoadScriptPin(asking_child, name, INVEXCH_SCRIPT_PIN, TRUE, 0); + } + } + + // we send this event when done updating the kid. + llMessageLinked(link_num, INVENTORY_EXCHANGER_HUFFWARE_ID, FINISHED_UPDATING, NULL_KEY); +} + +// changes the run state of all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + // we won't start anything if we're running inside the updater object. + if (find_substring(llGetObjectName(), "huffotronic") >= 0) return; + + integer indy; + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if (curr_script != self_script) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +// kicks forward the periodic activities of the exchange process. +handle_timer() +{ + if (llGetLinkNumber() != 1) { + // child prim activities only. +// knock_around_other_scripts(TRUE); + return; + } else { + // the rest are root prim timer activities. + if (llGetListLength(assets_available) == 0) return; // nothing to do here. + // the root needs to send out link messages telling kids what good stuff its got. + llMessageLinked(LINK_ALL_CHILDREN, INVENTORY_EXCHANGER_HUFFWARE_ID, + AVAILABLE_ASSETS_EVENT, wrap_parameters(assets_available)); + } + +} + +// given a packed up list of items, this breaks out each asset definition and +// begins using the set as our full list of available items. +consume_asset_registration(string packed_assets) +{ + assets_available = llParseString2List(packed_assets, [HUFFWARE_PARM_SEPARATOR], []); +//hmmm: future enhancement might be to allow multiple clients of the root exchanger. +// currently we only support one script inside the root prim listing assets for inv exch. +// that's shown just above where we're just replacing the entire registered assets list. + + integer indy; + for (indy = 0; indy < llGetListLength(assets_available); indy++) { + list asset_def = llParseString2List(llList2String(assets_available, indy), + [ASSET_FIELD_SEPARATOR], []); + integer type = llList2Integer(asset_def, 0); + string name = llList2String(asset_def, 1); + if (name == WILDCARD_INVENTORY_NAME) { + // argh, we need to patch up the list for a wildcard option. + // first, whack the item with the wildcard in it. + assets_available = llDeleteSubList(assets_available, indy, indy); + // now revert the list index for the missing item. + indy--; + // and finally add all the items of that type. if one of them is named + // after the wildcard character, well, we disallow that craziness. + integer inv_pos; + for (inv_pos = 0; inv_pos < llGetInventoryNumber(type); inv_pos++) { + string inv_name = llGetInventoryName(type, inv_pos); + if (inv_name != WILDCARD_INVENTORY_NAME) { +//log_it("added wild: " + inv_name); + assets_available += [ llDumpList2String([type, inv_name], ASSET_FIELD_SEPARATOR) ]; + } + } + + } + } + + // make sure we get this new set out to the interested parties. + handle_timer(); +} + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); +log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +// has been called destroy_older_versions in other scripts. +clean_outdated_items() +{ + scrub_items_by_type(llGetScriptName(), INVENTORY_ALL); + // after cleaning up, make sure everything's running. + knock_around_other_scripts(TRUE); +} + +// locates the index of a specified type of inventory item with a particular name, +// or returns a negative number. +integer find_inventory(integer type, string name) +{ + integer indy; + for (indy = 0; indy < llGetInventoryNumber(type); indy++) { + if (name == llGetInventoryName(type, indy)) return indy; + } + return -1; +} + +// called on child prims to make sure they have everything the root does. +examine_inventory_freshness(string packed_assets) +{ + list missing_goods; // fill this with the things we don't have in this prim. + list provisions = llParseString2List(packed_assets, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + // scan through all the items that are available and make sure we have each of them. + for (indy = 0; indy < llGetListLength(provisions); indy++) { + string prov = llList2String(provisions, indy); + list fields = llParseString2List(prov, [ASSET_FIELD_SEPARATOR], []); +//log_it("checking: " + llList2String(fields, 1) + " type=" + (string)llList2Integer(fields, 0)); + // look for the type and name specified. + integer type = llList2Integer(fields, 0); + string name = llList2String(fields, 1); + if (name == WHACK_INVENTORY_SIGNAL) { + // we see our special signifier, so remove all items of the type specified. + // yes, this is dangerous. + integer delo; + for (delo = llGetInventoryNumber(type) - 1; delo >= 0; delo--) { + llRemoveInventory(llGetInventoryName(type, delo)); + } + } else { + integer found = find_inventory(type, name); + if (found < 0) { +//log_it("found " + llList2String(fields, 1) + " was missing!"); + // well, we are out of this one. tell the root we want it. + missing_goods += [ prov ]; + } + } + } + if (llGetListLength(missing_goods) > 0) { + // well we found some things that we're supposed to have, but do not. we will + // get the root prim to fix us up. + llMessageLinked(LINK_ROOT, INVENTORY_EXCHANGER_HUFFWARE_ID, + REQUEST_UPDATES, wrap_parameters(missing_goods)); + } +} + +//hmmm: this is not such a good model? why do the root and +// the child both need to be running this check on a timer? + +// processes inventory exchange commands in the root prim. this is where assets must +// be present so they can be distributed to the child prims. +process_root_msg(integer link_num, integer service, string cmd, key parms) +{ + if (service != INVENTORY_EXCHANGER_HUFFWARE_ID) return; // not for us. +//string name="root"; +//if (llGetLinkNumber() != 1) name="child"; +//log_it(name + " got request " + cmd); + if (link_num == 1) { + // this request is also from the root prim, where this script lives currently. + if (cmd == REGISTER_ASSETS_COMMAND) { + // root prim accepts a list of assets to provide to the kids. + consume_asset_registration(parms); + } + } else { + // a request is coming from a child prim. + if (cmd == REQUEST_UPDATES) { + // the root prim responds to update requests by handing out presents. + populate_child_prim(link_num, llParseString2List(parms, [HUFFWARE_PARM_SEPARATOR], [])); + } + } +} + +// implements the child API, mainly to track missing assets and clean out outdated items. +process_child_msg(integer link_num, integer service, string cmd, key parms) +{ + if (service != INVENTORY_EXCHANGER_HUFFWARE_ID) return; // not for us. + if (link_num != 1) return; // we don't listen to any chatter from other children. + if (cmd == AVAILABLE_ASSETS_EVENT) { + examine_inventory_freshness(parms); + } else if (cmd == FINISHED_UPDATING) { + clean_outdated_items(); + } +} + +// main processing function for the link messge API. +handle_link_message(integer link_num, integer service, string cmd, key parms) +{ + if (llGetLinkNumber() == 1) process_root_msg(link_num, service, cmd, parms); + else process_child_msg(link_num, service, cmd, parms); +} + +////////////// +// beginning of hufflets... +////////////// + +// diagnostic hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// joins a list of sub-items using the item sentinel for the library. +//string wrap_item_list(list to_wrap) +//{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +// end hufflets +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); +///log_it("\n\n\n\n\n\n\n\n\n** starting now............................"); + // register child prims for script replacement. + if (llGetLinkNumber() != 1) llSetRemoteScriptAccessPin(INVEXCH_SCRIPT_PIN); + //new idea; only allow timers to run in root prim. + if (llGetLinkNumber() == 1) llSetTimerEvent(TIMER_PERIOD); + knock_around_other_scripts(TRUE); + // first run happens right at startup. + if (llGetLinkNumber() == 1) handle_timer(); + } + + timer() { + llSetTimerEvent(0); // stop timer. + handle_timer(); + llSetTimerEvent(TIMER_PERIOD); // start timer. + } + + link_message(integer link_num, integer service, string cmd, key parms) { + handle_link_message(link_num, service, cmd, parms); + } +} + + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.lsl deleted file mode 100755 index 2ae168d9..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.lsl +++ /dev/null @@ -1,135 +0,0 @@ - -// huffware script: invoke nechung, by fred huffhines. -// -// an example of invoking a web site from SL and getting the response. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -key last_request_id; // the current request that's in progress, if any. - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - } - - touch_start(integer num_touched) { - last_request_id = llHTTPRequest("http://gruntose.com//cgi-bin/nechung.cgi", [HTTP_METHOD,"GET"], ""); - } - - http_response(key request_id, integer status, list metadata, string body) - { - llSay(0, "\n" + body); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.txt new file mode 100755 index 00000000..2ae168d9 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/invoke_nechung_v1.2.txt @@ -0,0 +1,135 @@ + +// huffware script: invoke nechung, by fred huffhines. +// +// an example of invoking a web site from SL and getting the response. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +key last_request_id; // the current request that's in progress, if any. + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + } + + touch_start(integer num_touched) { + last_request_id = llHTTPRequest("http://gruntose.com//cgi-bin/nechung.cgi", [HTTP_METHOD,"GET"], ""); + } + + http_response(key request_id, integer status, list metadata, string body) + { + llSay(0, "\n" + body); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.lsl deleted file mode 100755 index 4d65cee3..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.lsl +++ /dev/null @@ -1,551 +0,0 @@ - -// huffware script: jaunting library, by fred huffhines, released under GPL-v3 license. -// -// this script is a library of useful teleportation and movement calls. it should be added -// into an object along with other scripts that use the library. the jaunting library -// responds to linked messages as commands. -// parts of this script are based on warpPos from "Teleporter Script v 3.0 by Asira Sakai", -// which was found at the LSL wiki. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -float PROXIMITY_REQUIRED = 0.1; - // how close we must be to the target location to call the jaunt done. - // we make this fairly low accuracy since we don't want jumps in space to immediately - // be counted as failures. - -// the most jumps the script will try to take. the overall distance from the start -// to the end can be 10 * MAXIMUM_JUMPS_PER_CALL meters. -integer MAXIMUM_JUMPS_PER_CALL = 84; - -// global variables... - -vector last_posn; // used to calculate jump distances. - -// jaunting library link message API... -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -string REVERSE_VELOCITY_COMMAND = "#reverse#"; - // makes the object reverse its velocity and travel back from whence it came. -string SET_VELOCITY_COMMAND = "#setvelocity#"; - // makes the velocity equal to the vector passed as the first parameter. -string JAUNT_UP_COMMAND = "#jauntup#"; -string JAUNT_DOWN_COMMAND = "#jauntdown#"; - // commands for height adjustment. pass a float for number of meters to move. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a list of vectors as the first parameter; this list - // should be in the jaunter notecard format (separated by pipe characters). - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -////////////// - -// returns what we consider to be safe to do in one big jump. -float distance_safe_to_jaunt() { return (float)(MAXIMUM_JUMPS_PER_CALL - 4) * 10.0; } - -// tests whether the destination is safe for an object to enter. -integer safe_for_entry(vector where) -{ - if (outside_of_sim(where)) { - // that's an obvious wrong idea; it tends to break us. - return FALSE; - } - return TRUE; -} - -// helper function for warp_across_list. this adds one jump vector to the -// list of rules as long as the destination is interesting. -list process_warp_item(vector next_jump) -{ -//log_it("mem: " + (string)llGetFreeMemory()); - // calculate the number of jumps needed. - integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; - last_posn = next_jump; // record for next check. - // set up our list which we'll replicate. - list rules = [ PRIM_POSITION, next_jump ]; - // Try and avoid stack/heap collisions. - if (jumps > MAXIMUM_JUMPS_PER_CALL - 1) jumps = MAXIMUM_JUMPS_PER_CALL; - // add the rules repeatedly to get the effective overall jump done. - integer count = 1; - while ( (count = count << 1) < jumps) - rules += rules; - // magnify the rule list before really adding it. this gets us to the proper - // final number of jumps. - return rules + llList2List(rules, (count - jumps) << 1 - 2, count); -} - -// originally based on warpPos from lsl wiki but drastically modified. -// uses a set of transfer points instead of a single target. -list warp_across_list(list full_journey, integer forwards) -{ - // make sure the list didn't run out. - if (llGetListLength(full_journey) == 0) return []; - if (forwards) { - // forwards traversal of the list. - vector next_jump = (vector)llList2String(full_journey, 0); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 1, - llGetListLength(full_journey) - 1), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); - } else { - // reverse traversal of the list. - vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 0, - llGetListLength(full_journey) - 2), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); - } -} - -// the main function that performs the jaunting process. -// now also supports adding a rotation into the mix to avoid paying the extra delay -// cost of calling llSetRot. -jaunt(list full_journey, integer forwards, string command_used, - integer use_rotation, rotation rot, integer reply_to_request) -{ -//log_it("jaunt: fullj=" + (string)full_journey + " forew=" + (string)forwards); - // set up our global variables... - last_posn = llGetPos(); - // calculate the trip and run it. - list rot_add; - if (use_rotation) - rot_add = [ PRIM_ROTATION, rot ]; - llSetPrimitiveParams(warp_across_list(full_journey, forwards) + rot_add); - if (reply_to_request) { - // pick out the last target in the list based on the direction we're moving. - integer last_indy = 0; - if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; - vector last_jump = (vector)llList2String(full_journey, last_indy); - // final judge of success here is how close we got to the target. - integer landed_there = (llVecDist(llGetPos(), last_jump) <= PROXIMITY_REQUIRED); - send_reply(LINK_THIS, [landed_there, llGetPos()], command_used); - } -} - -////////////// - -// sets the object's speed to "new_velocity". -// if "local_axis" is TRUE, then it will be relative to the object's -// own local coordinates. -set_velocity(vector new_velocity, integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - new_velocity -= current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -// attempts to bring the object to a complete stop. -full_stop() -{ - llSetForce(<0,0,0>, FALSE); - set_velocity(<0,0,0>, FALSE); -} - -// sends an object back along its trajectory. -reverse_velocity(integer local_axis) -{ - vector current_velocity = llGetVel(); - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - vector new_velocity = -2 * current_velocity; - new_velocity *= llGetMass(); - llApplyImpulse(new_velocity, local_axis); -} - -// teleports to the new "location", if possible. does not change object's phantom / physical -// states. this will do the jaunt in multiple steps if the distance from here to "location" -// is too large. -apportioned_jaunt(vector location, string command_used, integer use_rotation, rotation rot, - integer should_send_reply) -{ - if (!safe_for_entry(location)) { - // that's not good. we should not allow the script to get broken. - if (should_send_reply) - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; - } - // go to position specified, by leapfrogs if too long. - integer chunk_of_jump; - integer MAX_CHUNKS = 200; // multiplies the distance a single jaunt can cover. - for (chunk_of_jump = 0; chunk_of_jump < MAX_CHUNKS; chunk_of_jump++) { - vector interim_vec = location - llGetPos(); - float jump_dist = llVecDist(llGetPos(), location); - integer reply_needed = TRUE; - if (jump_dist > distance_safe_to_jaunt()) { - // the entire distance cannot be jumped. do the part of it that fits. - float proportion_can_do = distance_safe_to_jaunt() / jump_dist; - interim_vec *= proportion_can_do; - reply_needed = FALSE; // don't reply when this is not full jump. - } - interim_vec += llGetPos(); // bias jump back to where we are. -//log_it("jumping from " + (string)llGetPos() + " to " + (string)interim_vec); - jaunt([llGetPos(), interim_vec], TRUE, command_used, use_rotation, rot, - reply_needed && should_send_reply); - float dist_now = llVecDist(llGetPos(), interim_vec); - if (dist_now > PROXIMITY_REQUIRED) { -//log_it("failed to make interim jump, dist left is " + (string)dist_now); - // bail out. we failed to get as far as we thought we should. - chunk_of_jump = MAX_CHUNKS + 10; - if (!reply_needed) { - // we need to send the reply we hadn't sent yet. - if (should_send_reply) - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - } - } else if (llVecDist(llGetPos(), location) <= PROXIMITY_REQUIRED) { - // leave loop for a different reason; we got there. - chunk_of_jump = MAX_CHUNKS + 10; - if (!reply_needed) { - // we need to send the reply we hadn't sent yet. - if (should_send_reply) - send_reply(LINK_THIS, [TRUE, llGetPos()], command_used); - } - } - } -} - -// the entire distance embodied in the list of targets. this is a little smart, -// in that if there's only one target, we assume we're going from "here" to that -// one target. -float total_jaunt_distance(list targets) -{ - if (!llGetListLength(targets)) return 0.0; - // add in "this" location if they omitted it. - if (llGetListLength(targets) < 2) - targets = [ llGetPos() ] + targets; - integer disindy; - float total_dist = 0.0; - vector prev = (vector)llList2String(targets, 0); - for (disindy = 1; disindy < llGetListLength(targets); disindy++) { - vector next = (vector)llList2String(targets, disindy); - total_dist += llVecDist(prev, next); - prev = next; - } - return total_dist; -} - -// jaunts to a target via a set of intermediate locations. can either go forwards -// through the list or backwards. -phantom_jaunt_to_list(list targets, integer forwards, string command_used, - integer use_rotation, rotation rot) -{ - vector final_loc; - if (forwards) final_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); - else final_loc = (vector)llList2String(targets, 0); - -//hmmm: check each destination in list?? - if (!safe_for_entry(final_loc)) { - // that's not good. we should not allow the script to get broken. - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; - } - - // this turns off the physics property for the object, so that jaunt and - // llSetPos will still work. this became necessary due to havok4. - integer original_phantomosity = llGetStatus(STATUS_PHANTOM); - integer original_physicality = llGetStatus(STATUS_PHYSICS); - if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, FALSE); - if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, TRUE); - - integer send_reply_still = TRUE; // true if we should send a reply when done. - - // iterate through our list of targets and either we will jaunt to the next - // place directly or we will have to wrap a few destinations due to sim crossing. - while (llGetListLength(targets) > 0) { - vector next_loc; - if (forwards) next_loc = (vector)llList2String(targets, 0); - else next_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); - if (outside_of_sim(next_loc)) { - log_it("bad jaunt path: first target is out of sim."); - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; // skip that badness. - } - - // check how much total distance we have in the path that's left. if it's under our - // limit, then we'll just take it in one jump. - float total_dist = total_jaunt_distance(targets); - - // if we're below the threshold, we'll just jump now. - integer already_jumped = FALSE; - if (total_dist < distance_safe_to_jaunt()) { - jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); - targets = []; // reset the list now. - send_reply_still = FALSE; // we have already sent the reply in jaunt(). - already_jumped = TRUE; // don't do anything else. - } - if (!already_jumped) { - vector next_plus_1 = ZERO_VECTOR; // default cannot fail our "is inside sim" check. - if (llGetListLength(targets) > 1) { - if (forwards) next_plus_1 = (vector)llList2String(targets, 1); - else next_plus_1 = (vector)llList2String(targets, llGetListLength(targets) - 2); - } - if (outside_of_sim(next_plus_1)) { -//hmmm: eventually find all the negative ones in a row and do them in combo, rather than -// just giving up here and doing a jaunt to the rest.. - jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); - targets = []; // reset the list now. - send_reply_still = FALSE; // we have already sent the reply in jaunt(). - } else { - // we've passed the negativity test, so we can at least jump to the next place. - - // zap the next location, since we're about to jump there. - integer zap_pos = 0; - if (!forwards) zap_pos = llGetListLength(targets) - 1; - targets = llDeleteSubList(targets, zap_pos, zap_pos); - - // only bother jumping if we're not already there. - if (llVecDist(next_loc, llGetPos()) > PROXIMITY_REQUIRED) { - apportioned_jaunt(next_loc, command_used, use_rotation, rot, FALSE); - } - } - } - } - - if (send_reply_still) { - integer yippee = TRUE; // assume we succeeded until we prove otherwise. - if (llVecDist(final_loc, llGetPos()) > PROXIMITY_REQUIRED) - yippee = FALSE; - send_reply(LINK_THIS, [yippee, llGetPos()], command_used); - } - - // return to prior characteristics. - if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, original_phantomosity); - if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, original_physicality); -} - -// implements our API for jumping around. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - // separate the list out - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == JAUNT_COMMAND) { - // use list to string to avoid non-conversions. - vector v = (vector)llList2String(parms, 0); - rotation rot = <0.0, 0.0, 0.0, 1.0>; - integer gave_rot = llGetListLength(parms) > 1; - if (gave_rot) rot = (rotation)llList2String(parms, 1); // ooh, they gave us a rotational value also. -// log_it("gave rot? " + (string)gave_rot + " rot=" + (string)rot); - phantom_jaunt_to_list([llGetPos(), v], TRUE, msg, gave_rot, rot); - } else if (msg == FULL_STOP_COMMAND) { - full_stop(); - } else if (msg == REVERSE_VELOCITY_COMMAND) { - reverse_velocity(FALSE); - } else if (msg == SET_VELOCITY_COMMAND) { - vector v = (vector)llList2String(parms, 0); -//log_it("jaunting lib received set velocity request for " + (string)v); - set_velocity(v, FALSE); - } else if (msg == JAUNT_UP_COMMAND) { - phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, llList2Float(parms, 0)> ], - TRUE, msg, FALSE, ZERO_ROTATION); - } else if (msg == JAUNT_DOWN_COMMAND) { - phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, -llList2Float(parms, 0)> ], - TRUE, msg, FALSE, ZERO_ROTATION); - } else if (msg == JAUNT_LIST_COMMAND) { - string destination_list = llList2String(parms, 0); - list targets = llParseString2List(destination_list, [HUFFWARE_ITEM_SEPARATOR], []); - destination_list = ""; - integer forwards = TRUE; - // snag the directionality for the list, if specified. - if (llGetListLength(parms) > 1) forwards = llList2Integer(parms, 1); - rotation rot = <0.0, 0.0, 0.0, 1.0>; - integer gave_rot = llGetListLength(parms) > 2; - if (gave_rot) rot = llList2Rot(parms, 2); // ooh, they gave us a rotational value also. - phantom_jaunt_to_list(targets, forwards, msg, gave_rot, rot); - targets = []; - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); -} -////////////// - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, JAUNT_HUFFWARE_ID + REPLY_DISTANCE, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -/////////////// - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - link_message(integer sender, integer huff_id, string msg, key id) { - if (huff_id != JAUNT_HUFFWARE_ID) return; // not our responsibility. - handle_link_message(sender, huff_id, msg, id); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.txt new file mode 100755 index 00000000..4d65cee3 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/jaunting_library_v15.9.txt @@ -0,0 +1,551 @@ + +// huffware script: jaunting library, by fred huffhines, released under GPL-v3 license. +// +// this script is a library of useful teleportation and movement calls. it should be added +// into an object along with other scripts that use the library. the jaunting library +// responds to linked messages as commands. +// parts of this script are based on warpPos from "Teleporter Script v 3.0 by Asira Sakai", +// which was found at the LSL wiki. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +float PROXIMITY_REQUIRED = 0.1; + // how close we must be to the target location to call the jaunt done. + // we make this fairly low accuracy since we don't want jumps in space to immediately + // be counted as failures. + +// the most jumps the script will try to take. the overall distance from the start +// to the end can be 10 * MAXIMUM_JUMPS_PER_CALL meters. +integer MAXIMUM_JUMPS_PER_CALL = 84; + +// global variables... + +vector last_posn; // used to calculate jump distances. + +// jaunting library link message API... +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +string REVERSE_VELOCITY_COMMAND = "#reverse#"; + // makes the object reverse its velocity and travel back from whence it came. +string SET_VELOCITY_COMMAND = "#setvelocity#"; + // makes the velocity equal to the vector passed as the first parameter. +string JAUNT_UP_COMMAND = "#jauntup#"; +string JAUNT_DOWN_COMMAND = "#jauntdown#"; + // commands for height adjustment. pass a float for number of meters to move. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a list of vectors as the first parameter; this list + // should be in the jaunter notecard format (separated by pipe characters). + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +////////////// + +// returns what we consider to be safe to do in one big jump. +float distance_safe_to_jaunt() { return (float)(MAXIMUM_JUMPS_PER_CALL - 4) * 10.0; } + +// tests whether the destination is safe for an object to enter. +integer safe_for_entry(vector where) +{ + if (outside_of_sim(where)) { + // that's an obvious wrong idea; it tends to break us. + return FALSE; + } + return TRUE; +} + +// helper function for warp_across_list. this adds one jump vector to the +// list of rules as long as the destination is interesting. +list process_warp_item(vector next_jump) +{ +//log_it("mem: " + (string)llGetFreeMemory()); + // calculate the number of jumps needed. + integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; + last_posn = next_jump; // record for next check. + // set up our list which we'll replicate. + list rules = [ PRIM_POSITION, next_jump ]; + // Try and avoid stack/heap collisions. + if (jumps > MAXIMUM_JUMPS_PER_CALL - 1) jumps = MAXIMUM_JUMPS_PER_CALL; + // add the rules repeatedly to get the effective overall jump done. + integer count = 1; + while ( (count = count << 1) < jumps) + rules += rules; + // magnify the rule list before really adding it. this gets us to the proper + // final number of jumps. + return rules + llList2List(rules, (count - jumps) << 1 - 2, count); +} + +// originally based on warpPos from lsl wiki but drastically modified. +// uses a set of transfer points instead of a single target. +list warp_across_list(list full_journey, integer forwards) +{ + // make sure the list didn't run out. + if (llGetListLength(full_journey) == 0) return []; + if (forwards) { + // forwards traversal of the list. + vector next_jump = (vector)llList2String(full_journey, 0); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 1, + llGetListLength(full_journey) - 1), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); + } else { + // reverse traversal of the list. + vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 0, + llGetListLength(full_journey) - 2), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); + } +} + +// the main function that performs the jaunting process. +// now also supports adding a rotation into the mix to avoid paying the extra delay +// cost of calling llSetRot. +jaunt(list full_journey, integer forwards, string command_used, + integer use_rotation, rotation rot, integer reply_to_request) +{ +//log_it("jaunt: fullj=" + (string)full_journey + " forew=" + (string)forwards); + // set up our global variables... + last_posn = llGetPos(); + // calculate the trip and run it. + list rot_add; + if (use_rotation) + rot_add = [ PRIM_ROTATION, rot ]; + llSetPrimitiveParams(warp_across_list(full_journey, forwards) + rot_add); + if (reply_to_request) { + // pick out the last target in the list based on the direction we're moving. + integer last_indy = 0; + if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; + vector last_jump = (vector)llList2String(full_journey, last_indy); + // final judge of success here is how close we got to the target. + integer landed_there = (llVecDist(llGetPos(), last_jump) <= PROXIMITY_REQUIRED); + send_reply(LINK_THIS, [landed_there, llGetPos()], command_used); + } +} + +////////////// + +// sets the object's speed to "new_velocity". +// if "local_axis" is TRUE, then it will be relative to the object's +// own local coordinates. +set_velocity(vector new_velocity, integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + new_velocity -= current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +// attempts to bring the object to a complete stop. +full_stop() +{ + llSetForce(<0,0,0>, FALSE); + set_velocity(<0,0,0>, FALSE); +} + +// sends an object back along its trajectory. +reverse_velocity(integer local_axis) +{ + vector current_velocity = llGetVel(); + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + vector new_velocity = -2 * current_velocity; + new_velocity *= llGetMass(); + llApplyImpulse(new_velocity, local_axis); +} + +// teleports to the new "location", if possible. does not change object's phantom / physical +// states. this will do the jaunt in multiple steps if the distance from here to "location" +// is too large. +apportioned_jaunt(vector location, string command_used, integer use_rotation, rotation rot, + integer should_send_reply) +{ + if (!safe_for_entry(location)) { + // that's not good. we should not allow the script to get broken. + if (should_send_reply) + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; + } + // go to position specified, by leapfrogs if too long. + integer chunk_of_jump; + integer MAX_CHUNKS = 200; // multiplies the distance a single jaunt can cover. + for (chunk_of_jump = 0; chunk_of_jump < MAX_CHUNKS; chunk_of_jump++) { + vector interim_vec = location - llGetPos(); + float jump_dist = llVecDist(llGetPos(), location); + integer reply_needed = TRUE; + if (jump_dist > distance_safe_to_jaunt()) { + // the entire distance cannot be jumped. do the part of it that fits. + float proportion_can_do = distance_safe_to_jaunt() / jump_dist; + interim_vec *= proportion_can_do; + reply_needed = FALSE; // don't reply when this is not full jump. + } + interim_vec += llGetPos(); // bias jump back to where we are. +//log_it("jumping from " + (string)llGetPos() + " to " + (string)interim_vec); + jaunt([llGetPos(), interim_vec], TRUE, command_used, use_rotation, rot, + reply_needed && should_send_reply); + float dist_now = llVecDist(llGetPos(), interim_vec); + if (dist_now > PROXIMITY_REQUIRED) { +//log_it("failed to make interim jump, dist left is " + (string)dist_now); + // bail out. we failed to get as far as we thought we should. + chunk_of_jump = MAX_CHUNKS + 10; + if (!reply_needed) { + // we need to send the reply we hadn't sent yet. + if (should_send_reply) + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + } + } else if (llVecDist(llGetPos(), location) <= PROXIMITY_REQUIRED) { + // leave loop for a different reason; we got there. + chunk_of_jump = MAX_CHUNKS + 10; + if (!reply_needed) { + // we need to send the reply we hadn't sent yet. + if (should_send_reply) + send_reply(LINK_THIS, [TRUE, llGetPos()], command_used); + } + } + } +} + +// the entire distance embodied in the list of targets. this is a little smart, +// in that if there's only one target, we assume we're going from "here" to that +// one target. +float total_jaunt_distance(list targets) +{ + if (!llGetListLength(targets)) return 0.0; + // add in "this" location if they omitted it. + if (llGetListLength(targets) < 2) + targets = [ llGetPos() ] + targets; + integer disindy; + float total_dist = 0.0; + vector prev = (vector)llList2String(targets, 0); + for (disindy = 1; disindy < llGetListLength(targets); disindy++) { + vector next = (vector)llList2String(targets, disindy); + total_dist += llVecDist(prev, next); + prev = next; + } + return total_dist; +} + +// jaunts to a target via a set of intermediate locations. can either go forwards +// through the list or backwards. +phantom_jaunt_to_list(list targets, integer forwards, string command_used, + integer use_rotation, rotation rot) +{ + vector final_loc; + if (forwards) final_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); + else final_loc = (vector)llList2String(targets, 0); + +//hmmm: check each destination in list?? + if (!safe_for_entry(final_loc)) { + // that's not good. we should not allow the script to get broken. + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; + } + + // this turns off the physics property for the object, so that jaunt and + // llSetPos will still work. this became necessary due to havok4. + integer original_phantomosity = llGetStatus(STATUS_PHANTOM); + integer original_physicality = llGetStatus(STATUS_PHYSICS); + if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, FALSE); + if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, TRUE); + + integer send_reply_still = TRUE; // true if we should send a reply when done. + + // iterate through our list of targets and either we will jaunt to the next + // place directly or we will have to wrap a few destinations due to sim crossing. + while (llGetListLength(targets) > 0) { + vector next_loc; + if (forwards) next_loc = (vector)llList2String(targets, 0); + else next_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); + if (outside_of_sim(next_loc)) { + log_it("bad jaunt path: first target is out of sim."); + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; // skip that badness. + } + + // check how much total distance we have in the path that's left. if it's under our + // limit, then we'll just take it in one jump. + float total_dist = total_jaunt_distance(targets); + + // if we're below the threshold, we'll just jump now. + integer already_jumped = FALSE; + if (total_dist < distance_safe_to_jaunt()) { + jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); + targets = []; // reset the list now. + send_reply_still = FALSE; // we have already sent the reply in jaunt(). + already_jumped = TRUE; // don't do anything else. + } + if (!already_jumped) { + vector next_plus_1 = ZERO_VECTOR; // default cannot fail our "is inside sim" check. + if (llGetListLength(targets) > 1) { + if (forwards) next_plus_1 = (vector)llList2String(targets, 1); + else next_plus_1 = (vector)llList2String(targets, llGetListLength(targets) - 2); + } + if (outside_of_sim(next_plus_1)) { +//hmmm: eventually find all the negative ones in a row and do them in combo, rather than +// just giving up here and doing a jaunt to the rest.. + jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); + targets = []; // reset the list now. + send_reply_still = FALSE; // we have already sent the reply in jaunt(). + } else { + // we've passed the negativity test, so we can at least jump to the next place. + + // zap the next location, since we're about to jump there. + integer zap_pos = 0; + if (!forwards) zap_pos = llGetListLength(targets) - 1; + targets = llDeleteSubList(targets, zap_pos, zap_pos); + + // only bother jumping if we're not already there. + if (llVecDist(next_loc, llGetPos()) > PROXIMITY_REQUIRED) { + apportioned_jaunt(next_loc, command_used, use_rotation, rot, FALSE); + } + } + } + } + + if (send_reply_still) { + integer yippee = TRUE; // assume we succeeded until we prove otherwise. + if (llVecDist(final_loc, llGetPos()) > PROXIMITY_REQUIRED) + yippee = FALSE; + send_reply(LINK_THIS, [yippee, llGetPos()], command_used); + } + + // return to prior characteristics. + if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, original_phantomosity); + if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, original_physicality); +} + +// implements our API for jumping around. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + // separate the list out + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == JAUNT_COMMAND) { + // use list to string to avoid non-conversions. + vector v = (vector)llList2String(parms, 0); + rotation rot = <0.0, 0.0, 0.0, 1.0>; + integer gave_rot = llGetListLength(parms) > 1; + if (gave_rot) rot = (rotation)llList2String(parms, 1); // ooh, they gave us a rotational value also. +// log_it("gave rot? " + (string)gave_rot + " rot=" + (string)rot); + phantom_jaunt_to_list([llGetPos(), v], TRUE, msg, gave_rot, rot); + } else if (msg == FULL_STOP_COMMAND) { + full_stop(); + } else if (msg == REVERSE_VELOCITY_COMMAND) { + reverse_velocity(FALSE); + } else if (msg == SET_VELOCITY_COMMAND) { + vector v = (vector)llList2String(parms, 0); +//log_it("jaunting lib received set velocity request for " + (string)v); + set_velocity(v, FALSE); + } else if (msg == JAUNT_UP_COMMAND) { + phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, llList2Float(parms, 0)> ], + TRUE, msg, FALSE, ZERO_ROTATION); + } else if (msg == JAUNT_DOWN_COMMAND) { + phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, -llList2Float(parms, 0)> ], + TRUE, msg, FALSE, ZERO_ROTATION); + } else if (msg == JAUNT_LIST_COMMAND) { + string destination_list = llList2String(parms, 0); + list targets = llParseString2List(destination_list, [HUFFWARE_ITEM_SEPARATOR], []); + destination_list = ""; + integer forwards = TRUE; + // snag the directionality for the list, if specified. + if (llGetListLength(parms) > 1) forwards = llList2Integer(parms, 1); + rotation rot = <0.0, 0.0, 0.0, 1.0>; + integer gave_rot = llGetListLength(parms) > 2; + if (gave_rot) rot = llList2Rot(parms, 2); // ooh, they gave us a rotational value also. + phantom_jaunt_to_list(targets, forwards, msg, gave_rot, rot); + targets = []; + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); +} +////////////// + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, JAUNT_HUFFWARE_ID + REPLY_DISTANCE, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +/////////////// + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + link_message(integer sender, integer huff_id, string msg, key id) { + if (huff_id != JAUNT_HUFFWARE_ID) return; // not our responsibility. + handle_link_message(sender, huff_id, msg, id); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.lsl deleted file mode 100755 index a0537fdc..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.lsl +++ /dev/null @@ -1,318 +0,0 @@ - -// huffware script: jump good, by fred huffhines -// "jump good" is an homage to samurai jack. -// -// if you wear an object containing this script (and using the -// jump_good_jump_strength() value), then this script will make -// your jumps much higher than normal. other values for the -// jump strength will vary the force on you accordingly. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -// this section provides some example forces one might want to exert. -// all floating point numbers below are measured in meters per second squared, -// which is a measurement of acceleration. - -float EARTH_ACCELERATION = 9.80665; - // the acceleration due to gravity on earth. - -float JUPITER_ACCELERATION = 25.93; - // the acceleration on jupiter due to gravity. - -float earth_jump_strength() { return EARTH_ACCELERATION - EARTH_ACCELERATION; } - // normal gravity for the earth; no additional force added. - -float jupiter_jump_strength() -{ return EARTH_ACCELERATION - (JUPITER_ACCELERATION - EARTH_ACCELERATION); } - // this is what the jump force should be when approximating jupiter's gravity. - -float jump_good_jump_strength() { return 8.4; } - // samurai jack was probably able to jump this high after the tree dwellers - // taught him how to jump good. - -integer DEBUGGING = FALSE; - // if this is true, then extra noise is made about state transitions. - -float TIMER_PERIOD = 4.0; - // how frequently to check our state. - -////////////// - -// this is the most important jump strength, since it's the one we'll use... - -float jump_strength() { return jump_good_jump_strength(); } - // the amount of force that you're "thrown" upwards with. this is - // relative to your mass. the force of gravity pulls on objects with - // a force of 9.80665, so if the jump strength exceeds that, the object - // will never return to earth. - -////////////// - -// global variables... - -key attached_key; // key of the avatar wearing the object, if any avatar is. - -integer _last_seen_flying; // tracks the attached avatar's flight state. - -integer enabled; // records device's state; if false, then it's off. - -////////////// - -// makes the force appropriate to the mass of the overall object. -use_configured_force() -{ - float mass = llGetMass(); -//log_it("mass is " + (string)mass); - if (mass == 0.0) mass = 20000; - // fake there being a good mass. - vector force = <0,0, mass * jump_strength()>; -//log_it("using force of " + (string)force + "."); - llSetForce(force, FALSE); -} - -// resets force to zero to have normal gravity return. -use_zero_force() { -//log_it("using zero force."); - - llSetForce(<0,0,0>, FALSE); } - -// changes the objects current velocity to match "new_velocity". -// if the "local_axis" is true, then it applies the velocity to the -// object's own axis. if false, then it uses the global axis of -// the simulator. -set_velocity(vector new_velocity, integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - new_velocity -= current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -// picks the right amount of force based on whether the object is -// attached to an avatar and whether the avatar is flying. -set_force_appropriately() -{ - if (attached_key != NULL_KEY) { - // make sure we're not flying now; jump force would be redundant. - if (llGetAgentInfo(llGetOwner()) & AGENT_FLYING) { - if (!_last_seen_flying) { -//log_it("avatar wasn't flying, is now. setting zero force."); - use_zero_force(); - } - _last_seen_flying = TRUE; - } else { -//if (_last_seen_flying) { -//log_it("avatar was just flying, but is not now. setting configured force."); -//} - // we're not flying so keep our force set. - _last_seen_flying = FALSE; - use_configured_force(); - - } - } else { - // there's no one attached, so just follow our plan with the force. - use_configured_force(); - } -} - -initialize_forces() -{ - enabled = FALSE; - _last_seen_flying = FALSE; - attached_key = NULL_KEY; - llSetTimerEvent(TIMER_PERIOD); // check avatar's state periodically. - if (llGetAttached() != 0) { - // there's an avatar attached right now! get the stats right. - attached_key = llGetOwner(); - if (llGetAgentInfo(llGetOwner()) & AGENT_FLYING) _last_seen_flying = TRUE; - else _last_seen_flying = FALSE; - } - set_force_appropriately(); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - string addition; - if (DEBUGGING) addition = llGetScriptName() + "[" + (string)debug_num + "] "; - llOwnerSay(addition + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); -//log_it("state_entry"); - initialize_forces(); - } - - timer() { - // we can't do anything without physics enabled. - if (!llGetStatus(STATUS_PHYSICS)) - llSetStatus(STATUS_PHYSICS, TRUE); - if (!llGetStatus(STATUS_PHANTOM)) - llSetStatus(STATUS_PHANTOM, FALSE); - if (enabled) set_force_appropriately(); - else use_zero_force(); - } - - attach(key avatar) - { -//log_it("into attach, key=" + (string)avatar); - initialize_forces(); - } - - on_rez(integer parm) { -//log_it("on_rez"); - initialize_forces(); - } - - touch_start(integer count) { - if (llDetectedKey(0) != llGetOwner()) return; // not listening to that guy. - if (llGetAttached() == 0) return; // cannot change state if not attached. - // flip the current state, since they clicked. - if (enabled) { - log_it("disabled gravity control."); - enabled = FALSE; - use_zero_force(); - } else { - log_it("enabled gravity control."); - enabled = TRUE; - use_configured_force(); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.txt new file mode 100755 index 00000000..a0537fdc --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/jump_good_v6.0.txt @@ -0,0 +1,318 @@ + +// huffware script: jump good, by fred huffhines +// "jump good" is an homage to samurai jack. +// +// if you wear an object containing this script (and using the +// jump_good_jump_strength() value), then this script will make +// your jumps much higher than normal. other values for the +// jump strength will vary the force on you accordingly. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +// this section provides some example forces one might want to exert. +// all floating point numbers below are measured in meters per second squared, +// which is a measurement of acceleration. + +float EARTH_ACCELERATION = 9.80665; + // the acceleration due to gravity on earth. + +float JUPITER_ACCELERATION = 25.93; + // the acceleration on jupiter due to gravity. + +float earth_jump_strength() { return EARTH_ACCELERATION - EARTH_ACCELERATION; } + // normal gravity for the earth; no additional force added. + +float jupiter_jump_strength() +{ return EARTH_ACCELERATION - (JUPITER_ACCELERATION - EARTH_ACCELERATION); } + // this is what the jump force should be when approximating jupiter's gravity. + +float jump_good_jump_strength() { return 8.4; } + // samurai jack was probably able to jump this high after the tree dwellers + // taught him how to jump good. + +integer DEBUGGING = FALSE; + // if this is true, then extra noise is made about state transitions. + +float TIMER_PERIOD = 4.0; + // how frequently to check our state. + +////////////// + +// this is the most important jump strength, since it's the one we'll use... + +float jump_strength() { return jump_good_jump_strength(); } + // the amount of force that you're "thrown" upwards with. this is + // relative to your mass. the force of gravity pulls on objects with + // a force of 9.80665, so if the jump strength exceeds that, the object + // will never return to earth. + +////////////// + +// global variables... + +key attached_key; // key of the avatar wearing the object, if any avatar is. + +integer _last_seen_flying; // tracks the attached avatar's flight state. + +integer enabled; // records device's state; if false, then it's off. + +////////////// + +// makes the force appropriate to the mass of the overall object. +use_configured_force() +{ + float mass = llGetMass(); +//log_it("mass is " + (string)mass); + if (mass == 0.0) mass = 20000; + // fake there being a good mass. + vector force = <0,0, mass * jump_strength()>; +//log_it("using force of " + (string)force + "."); + llSetForce(force, FALSE); +} + +// resets force to zero to have normal gravity return. +use_zero_force() { +//log_it("using zero force."); + + llSetForce(<0,0,0>, FALSE); } + +// changes the objects current velocity to match "new_velocity". +// if the "local_axis" is true, then it applies the velocity to the +// object's own axis. if false, then it uses the global axis of +// the simulator. +set_velocity(vector new_velocity, integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + new_velocity -= current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +// picks the right amount of force based on whether the object is +// attached to an avatar and whether the avatar is flying. +set_force_appropriately() +{ + if (attached_key != NULL_KEY) { + // make sure we're not flying now; jump force would be redundant. + if (llGetAgentInfo(llGetOwner()) & AGENT_FLYING) { + if (!_last_seen_flying) { +//log_it("avatar wasn't flying, is now. setting zero force."); + use_zero_force(); + } + _last_seen_flying = TRUE; + } else { +//if (_last_seen_flying) { +//log_it("avatar was just flying, but is not now. setting configured force."); +//} + // we're not flying so keep our force set. + _last_seen_flying = FALSE; + use_configured_force(); + + } + } else { + // there's no one attached, so just follow our plan with the force. + use_configured_force(); + } +} + +initialize_forces() +{ + enabled = FALSE; + _last_seen_flying = FALSE; + attached_key = NULL_KEY; + llSetTimerEvent(TIMER_PERIOD); // check avatar's state periodically. + if (llGetAttached() != 0) { + // there's an avatar attached right now! get the stats right. + attached_key = llGetOwner(); + if (llGetAgentInfo(llGetOwner()) & AGENT_FLYING) _last_seen_flying = TRUE; + else _last_seen_flying = FALSE; + } + set_force_appropriately(); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + string addition; + if (DEBUGGING) addition = llGetScriptName() + "[" + (string)debug_num + "] "; + llOwnerSay(addition + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); +//log_it("state_entry"); + initialize_forces(); + } + + timer() { + // we can't do anything without physics enabled. + if (!llGetStatus(STATUS_PHYSICS)) + llSetStatus(STATUS_PHYSICS, TRUE); + if (!llGetStatus(STATUS_PHANTOM)) + llSetStatus(STATUS_PHANTOM, FALSE); + if (enabled) set_force_appropriately(); + else use_zero_force(); + } + + attach(key avatar) + { +//log_it("into attach, key=" + (string)avatar); + initialize_forces(); + } + + on_rez(integer parm) { +//log_it("on_rez"); + initialize_forces(); + } + + touch_start(integer count) { + if (llDetectedKey(0) != llGetOwner()) return; // not listening to that guy. + if (llGetAttached() == 0) return; // cannot change state if not attached. + // flip the current state, since they clicked. + if (enabled) { + log_it("disabled gravity control."); + enabled = FALSE; + use_zero_force(); + } else { + log_it("enabled gravity control."); + enabled = TRUE; + use_configured_force(); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.lsl deleted file mode 100755 index 0855fa5b..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.lsl +++ /dev/null @@ -1,727 +0,0 @@ - -// huffware script: mediatron control, by fred huffhines. -// -// controls the mediatron device and manages menus for the user. -// when buttons are clicked, this is the script that arranges for things to -// happen. this script also processes the spoken commands from the user. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// configurable constants... - -integer MEDIATRON_CHANNEL = 1008; - // fairly arbitrary channel for listening. - -integer ONLY_OWNER = FALSE; - // only listen to the owner's chats? - -vector TEXT_COLOR = <0.5, 0.7, 0.92>; - // the color that the current chapter is displayed in. - -string LATEX_DRIVER_URL = "http://universalbuilds.com/tib/gif.php?l="; - // the URL for turning tex code into tibetan and english bitmaps. - -// global constants that really should stay constant... - -//////// -// link ids for flinging messages at them. -//----these are useless until the OAR link number bug is fixed. -//integer ROOT_PRIM_LINK = 1; // by SL conventions. -//integer MAIN_VIEWSCREEN_LINK = 2; // the next prim after the root is our viewer. -//integer NEXT_BUTTON_LINK = 3; -//integer PREVIOUS_BUTTON_LINK = 4; -//integer UHHH_BUTTON_LINK = 5; -//integer MENU_BUTTON_LINK = 6; -//integer BACKGROUND_PLATE_LINK = 7; // the blank whitish plank underneath the main viewscreen. -//////// - -integer DEFAULT_CHANNEL = 1008; // this must remain unchanged so we can dynamically modify help. - -// commands that can begin the line of text spoken on our special channel. -// these are also used for interchange with sub-prims, such as when a button is pushed. -string TIBETAN_CHUNK = "tib"; -string ENGLISH_CHUNK = "en"; -string NEW_LINE_CMD = "line"; -string SHOW_BUFFER_CMD = "go"; - -string NEXT_PAGE_CMD = "next"; -string PREVIOUS_PAGE_CMD = "prev"; - -string RESET_MEDIATRON_CMD = "Reset"; -string CLEAR_MEDIATRON_CMD = "Clear"; - -string OPEN_MENU_CMD = "menu"; -string CHAPTER_PICKER_CMD = "chapter"; - -string CHANNEL_CHANGE_CMD = "channel"; -string DRIVER_WEB_SITE_CMD = "urldriver"; -string LOAD_WEB_PAGE_CMD = "loadweb"; - -string TEXT_COLOR_CHANGE_CMD = "textcolor"; - -string HELP_CMD = "Help"; - -// config / control menus that we support. -string STATUS_ITEM = "Status"; -string AUTHORIZE_ITEM = "Authorize"; -string TEXT_COLOR_ITEM = "Text Color"; -string CHANNEL_ITEM = "Channel"; -string WEB_SITE_ITEM = "Driver URL"; - -// API for the viewscreen blitter library... -////////////// -integer VIEWSCREEN_BLITTER_HUFFWARE_ID = 10027; - // unique ID for the viewscreen services. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// -string SHOW_URL_COMMAND = "#shurl"; - // requests the viewscreen to show a particular URL as its texture. -string RESET_VIEWSCREEN_COMMAND = "#shrz"; - // resets the viewscreen script to the default state. -string SHOW_TEXTURE_COMMAND = "#shtex"; - // displays a texture on the prim. the first parameter is the texture key or name. -////////////// - -// API for moving between the active notecards. -////////////// -// do not redefine these constants. -integer SLATE_READER_HUFFWARE_ID = 10028; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -string RESET_SLATE_READER_COMMAND = "#rsslt"; - // causes the notecard information to be forgotten and the script restarted. -string SR_GET_INFORMATION_COMMAND = "#infy"; - // used by clients to ask for information about the current number of notecards - // available, and their names. this information is sent back on the huffware ID - // plus the reply distance. first parm is the number, and the rest are the names. -string SR_PLAY_CARD_COMMAND = "#playvo"; - // picks a particular notecard for reading and send the notecard's contents in a - // series of link messages, using this command and the reply distance. there are - // two parameters: an integer for the notecard number to read (from 0 through the - // number of notecards - 1) and the link number to send the messages to. -////////////// - -// the button pushing API. -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10029; - // a unique ID within the huffware system for this script. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was pushed. -////////////// - -// menutini link message API... -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. - // the reply will include: the menu name, the choice made and the key for - // the avatar. -////////////// - -// global variables... - -string buffer_text; // the buffer being accumulated for display. - -integer page_number; // current page shown: ranges from zero to number of notecards - 1. - -integer maximum_notecards; // the maximum notecards that can be shown. - -list notecard_choices; // the chapters that can be chosen. - -integer listening_handle; // tracks our listening so we can change channels. - -set_viewscreen_texture() -{ - // get the video texture they want to use for the parcel. - key texture_key = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]), 0); - if (texture_key == NULL_KEY) { - // there wasn't one set yet. we can't do much about that here. we'll use the - // last inventory texture instead, which usually will be our proper image. - texture_key = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, - llGetInventoryNumber(INVENTORY_TEXTURE) - 1)); - if (texture_key == NULL_KEY) return; // now we're hosed; there's no texture. - } - // set the main viewer prim to the chosen texture... - llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, - SHOW_TEXTURE_COMMAND, (string)texture_key); -} - -// checks the parcel's media texture to make sure it's set. if it's not, we reset it to -// our favorite version. -fix_parcel_media_texture() -{ - // get the video texture they want to use for the parcel. - key texture_key = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]), 0); - if (texture_key == NULL_KEY) { - // there wasn't one set yet, so we need to fix that. we'll use the last inventory - // texture, which usually will be our proper image. this is a distinct chore from - // setting the viewscreen's texture, since we don't know that we have the capability - // to change the parcel media texture yet. - texture_key = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, - llGetInventoryNumber(INVENTORY_TEXTURE) - 1)); - if (texture_key != NULL_KEY) { - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE, texture_key]); - if (llGetLandOwnerAt(llGetPos()) != llGetOwner()) { - log_it("There is a problem with the parcel media: " - + llGetObjectName() + " is not owned by the parcel owner."); - } else { - log_it("No media texture found for video on this parcel. Using default texture: " - + (string)texture_key); - } - } else { - log_it("The object does not seem to contain any textures; we need at " - + "least one for a default viewscreen image."); - } - } -} - -// asks the slate reader to find out what cards there are for us. -reload_notecards() -{ - // now we find out what's really present so we can offer a menu. - llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, - SR_GET_INFORMATION_COMMAND, ""); -} - -// fixes the viewscreen face and parcel media texture, if needed, and gets the mediatron -// ready for commands. -initialize_mediatron() -{ - fix_parcel_media_texture(); - set_viewscreen_texture(); - llSetText("", TEXT_COLOR, 0.0); - page_number = -1; - reload_notecards(); - - // listening for commands from the user. - listening_handle = llListen(MEDIATRON_CHANNEL, "", NULL_KEY, ""); - - llSay(0, "Now listening for commands on channel /" + (string)MEDIATRON_CHANNEL); -} - -// locates the space boundaries between words and returns just a list of the words, -// with no spaces remaining. -list break_on_spaces(string msg) -{ - if (!llStringLength(msg)) return []; // no length means no list. - integer indy; - list to_return; - for (indy = 0; indy < llStringLength(msg); indy++) { - integer space_posn = llSubStringIndex(msg, " "); - if (space_posn < 0) { - // no spaces left, so use the whole string. - to_return += [ msg ]; - indy = 2 * llStringLength(msg); - } else { - // we found a space. chop out the first part to add to the list and - // keep the second part for further scanning. - to_return += [ llGetSubString(msg, 0, space_posn - 1) ]; - // we also trash any additional spaces that were after the one we found. - msg = llStringTrim(llGetSubString(msg, space_posn + 1, -1), STRING_TRIM); - indy = -1; // start over at top of string. - } - } - return to_return; -} - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -simply_display_menu(string menu_name, string title, list buttons) -{ - integer menu_channel = random_channel(); - key listen_to = llGetOwner(); - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR - + (string)menu_channel + HUFFWARE_PARM_SEPARATOR - + (string)listen_to); -} - -// handles when a button on the device has been clicked. -process_button_clicks(string msg, key id) -{ - if (msg != BUTTON_PUSHED_ALERT) return; // uhhhh, not sure what that was. - if (id == NEXT_PAGE_CMD) { - hear_voices(FALSE, "self", llGetOwner(), id); - } else if (id == PREVIOUS_PAGE_CMD) { - hear_voices(FALSE, "self", llGetOwner(), id); - } else if (id == CHAPTER_PICKER_CMD) { - list pruned_choices; - string list_as_block; - integer indy; - for (indy = 0; indy < llGetListLength(notecard_choices); indy++) { - string curr_name = prune_notecard_name(llList2String(notecard_choices, indy)); - pruned_choices += [ curr_name ]; - list_as_block += (string)(indy + 1) + ". " + curr_name; - if (indy < llGetListLength(notecard_choices) - 1) list_as_block += "\n"; - } - simply_display_menu(CHAPTER_PICKER_CMD, "Pick the Chapter to display...\n" + list_as_block, - pruned_choices); - } else if (id == OPEN_MENU_CMD) { - simply_display_menu(OPEN_MENU_CMD, "TibSlate Mediatron Control Menu", - [ HELP_CMD, STATUS_ITEM, AUTHORIZE_ITEM, TEXT_COLOR_ITEM, CHANNEL_ITEM, - WEB_SITE_ITEM, CLEAR_MEDIATRON_CMD, RESET_MEDIATRON_CMD ]); - } -} - -string bool_string_for_int(integer truth) -{ - if (truth) return "true"; else return "false"; -} - -tell_not_authorized() -{ - llSay(0, "The operation you have chosen can only be performed by the owner."); -} - -// handles the response message when the user chooses a button. -react_to_menu(string msg, key id) -{ - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string which_choice = llList2String(parms, 1); - key av_key = llList2String(parms, 2); - if (ONLY_OWNER && (av_key != llGetOwner())) { - tell_not_authorized(); - return; - } -//log_it("you clicked " + which_choice + " item for av " + av_key); - - if (menu_name == CHAPTER_PICKER_CMD) { - // find the index of the choice if we can, and make the choice be the new page. - page_number = find_similar_in_list(notecard_choices, which_choice); - play_chapter(); - return; - } else if (menu_name == OPEN_MENU_CMD) { - // show the main control menu. - if (which_choice == STATUS_ITEM) { - llSay(0, "Status...\n\tMemory Free " + (string)llGetFreeMemory() - + "\n\tListening Channel " + (string)MEDIATRON_CHANNEL - + "\n\tOwner Only? " + bool_string_for_int(ONLY_OWNER)); - return; - } else if (which_choice == AUTHORIZE_ITEM) { - if (av_key != llGetOwner()) { - // this option isn't allowed for anyone but the owner, ever. - tell_not_authorized(); - return; - } - simply_display_menu(AUTHORIZE_ITEM, "Authorization required to use device...", - [ "Any User", "Only Owner" ]); - return; - } else if (which_choice == TEXT_COLOR_ITEM) { - llSay(0, "To change the text color, say\n\t/" - + (string)MEDIATRON_CHANNEL + " " + TEXT_COLOR_CHANGE_CMD - + " \nwhere r, g, and b are the red, green and blue components of the color.\n" - + "Note that r, g & b can range from 0 to 1 inclusive."); - return; - } else if (which_choice == CHANNEL_ITEM) { - llSay(0, "To change the channel of the viewer, say\n\t/" - + (string)MEDIATRON_CHANNEL + " " + CHANNEL_CHANGE_CMD - + " N\nwhere N is a number for the new channel."); - return; - } else if (which_choice == WEB_SITE_ITEM) { - llSay(0, "Current driver web URL: " + LATEX_DRIVER_URL - + "\nTo replace this site, say:\n\t/" - + (string)MEDIATRON_CHANNEL + " " + DRIVER_WEB_SITE_CMD - + " newURL\nNote that this site must be capable of accepting LaTex code and\n" - + "converting that into simulator compatible bitmaps."); - return; - } else { - // handle all the others by just passing this on to the hear voices function. - // if it's a known command, we handle it. otherwise we bounce it off the couch. - hear_voices(FALSE, "self", llGetOwner(), which_choice); - return; - } - // the remainder of these handle the menu button's menu options... - } else if (menu_name == AUTHORIZE_ITEM) { - // they chose an option for authorization, so see if it was for only the owner. - ONLY_OWNER = is_prefix(which_choice, "only"); - llSay(0, "now, Owner Only = " + bool_string_for_int(ONLY_OWNER)); - return; - } - -log_it("i do not understand item " + which_choice + " in "+ menu_name); -} - -// processes the responses from the slate reader. -handle_slate_items(string msg, key id) -{ - if (msg == SR_PLAY_CARD_COMMAND) { - // we have gotten some data from our reader. - hear_voices(FALSE, "self", llGetOwner(), id); - } else if (msg == SR_GET_INFORMATION_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - maximum_notecards = llList2Integer(parms, 0); -//log_it("got info response, num notes=" + (string)maximum_notecards); - notecard_choices = llList2List(parms, 1, -1); - } -} - -// strips off any numerical info to make a more useful notecard name. -string prune_notecard_name(string note_name) -{ - // we look at the name and remove any numbers in front, so we can avoid cluttering up the - // user facing text with the numbers that are used for ordering the notecards. - list rip_these = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", " ", "." ]; - while (llListFindList(rip_these, [ llGetSubString(note_name, 0, 0) ]) >= 0) { - // found a number or space or period. rip it off. - note_name = llDeleteSubString(note_name, 0, 0); - } - return note_name; -} - -show_chapter_name() -{ - string note_name = prune_notecard_name(llList2String(notecard_choices, page_number)); - llSetText("Page #" + (string)(page_number + 1) - + " -- " + note_name, TEXT_COLOR, 1.0); -} - -// shows the contents of the current page's notecard on the viewscreen. -play_chapter() -{ - show_chapter_name(); - llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, - SR_PLAY_CARD_COMMAND, wrap_parameters([page_number, LINK_THIS])); -} - -// tell the viewscreen to display this possible tibetan. -// spoken reports whether it's a user speaking or not. if spoken is false, then -// the voice is internal from getting notecard info or button clicks. -hear_voices(integer spoken, string name, key id, string msg) -{ - msg = llStringTrim(msg, STRING_TRIM); // toss extra spaces. - if (msg == CLEAR_MEDIATRON_CMD) { - // wipe out anything on the screen. - set_viewscreen_texture(); - buffer_text = ""; // toss out any partial buffer also. - if (spoken) llSay(0, "Clearing viewscreen."); - page_number = -1; // reset page to the spot before the first. - llSetText("", TEXT_COLOR, 0.0); - return; - } else if ( (msg == RESET_MEDIATRON_CMD) && (id == llGetOwner()) ) { - llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, - RESET_VIEWSCREEN_COMMAND, ""); - llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, - RESET_SLATE_READER_COMMAND, ""); - if (spoken) llSay(0, "Resetting scripts."); - llResetScript(); - } else if (is_prefix(msg, CHANNEL_CHANGE_CMD)) { - integer new_channel = (integer)llGetSubString(msg, llStringLength(CHANNEL_CHANGE_CMD), -1); - llSay(0, "New channel is " + (string)new_channel); - MEDIATRON_CHANNEL = new_channel; - llListenRemove(listening_handle); - listening_handle = llListen(MEDIATRON_CHANNEL, "", NULL_KEY, ""); - return; - } else if (is_prefix(msg, TEXT_COLOR_CHANGE_CMD)) { - vector new_col = (vector)llGetSubString(msg, llStringLength(TEXT_COLOR_CHANGE_CMD), -1); - llSay(0, "New text color is " + (string)new_col); - TEXT_COLOR = new_col; - show_chapter_name(); - return; - } else if (is_prefix(msg, DRIVER_WEB_SITE_CMD)) { - string new_url = llGetSubString(msg, llStringLength(DRIVER_WEB_SITE_CMD), -1); - llSay(0, "New driver URL for LaTex: " + (string)new_url); - LATEX_DRIVER_URL = new_url; - return; - } else if (is_prefix(msg, NEXT_PAGE_CMD)) { - page_number++; - if (page_number >= maximum_notecards) { - page_number = 0; - } - play_chapter(); - return; - } else if (is_prefix(msg, PREVIOUS_PAGE_CMD)) { - page_number--; - if (page_number < 0) { - page_number = maximum_notecards - 1; - } - show_chapter_name(); - llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, - SR_PLAY_CARD_COMMAND, wrap_parameters([page_number, LINK_THIS])); - return; - } else if (is_prefix(msg, HELP_CMD)) { - provide_help(); - return; - } else if (is_prefix(msg, LOAD_WEB_PAGE_CMD)) { - string new_url = llGetSubString(msg, llStringLength(LOAD_WEB_PAGE_CMD), -1); - llSay(0, "Loading web site: " + (string)new_url); - llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, SHOW_URL_COMMAND, new_url); - buffer_text = ""; // clear the buffer out. - } - - // now we try to process the screen buffer commands which we suspect - // are in the text that was spoken. - list sentence = break_on_spaces(msg); - string first_word = llList2String(sentence, 0); -//log_it("first word is: " + first_word); - string remainder; - integer indo; - for (indo = 1; indo < llGetListLength(sentence); indo++) { - if (indo != 1) remainder += " "; - remainder += llList2String(sentence, indo); - } -//log_it("remainder is: " + remainder); - - if (first_word == TIBETAN_CHUNK) { - if (spoken) llSay(0, "Added Tibetan: " + remainder); - buffer_text += "{\\tib " + remainder + "}{ }"; - } else if (first_word == ENGLISH_CHUNK) { - if (spoken) llSay(0, "Added English: " + remainder); - buffer_text += "{" + remainder + " }"; - } else if (first_word == NEW_LINE_CMD) { - if (spoken) llSay(0, "Inserted blank line."); - buffer_text += "{\\\\}"; - } else if (first_word == SHOW_BUFFER_CMD) { - if (spoken) llSay(0, "Displaying buffered screen."); - // reset text label since that's no longer our page. - if (spoken) llSetText("", TEXT_COLOR, 0.0); - string url = LATEX_DRIVER_URL + buffer_text; - llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, SHOW_URL_COMMAND, url); - buffer_text = ""; // clear the buffer out. - } else { - // treat this as english. -//mostly redundant! - if (spoken) llSay(0, "Added English: " + first_word + " " + remainder); - buffer_text += "{" + first_word + " " + remainder + "}"; - // if we're assuming this is english, we will plug in a blank line afterwards. - // otherwise a text document will look right awful. - buffer_text += "{\\\\}"; - } -} - -// hands out any notecards with help in their names. -provide_help() -{ - integer count = llGetInventoryNumber(INVENTORY_NOTECARD); - integer indy; - list help_cards = []; - for (indy = 0; indy < count; indy++) { - string note_name = llGetInventoryName(INVENTORY_NOTECARD, indy); - if (find_substring(note_name, "help") >= 0) - help_cards += [ note_name ]; - } - - if (llGetListLength(help_cards)) llOwnerSay("Here is the built-in help file..."); - else llOwnerSay("There are currently no help notecards; sorry."); - // iterate on helper cards and give them out. - count = llGetListLength(help_cards); - for (indy = 0; indy < count; indy++) { - string note_name = llList2String(help_cards, indy); - llGiveInventory(llGetOwner(), note_name); - } -} - - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -////////////// - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(llToLower(compare_with), llToLower(prefix)) == 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// locates the string "text" as a partial match in the list to "search_in". -integer find_similar_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (find_substring(llList2String(search_in, i), text) >= 0) - return i; - } - return -1; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - initialize_mediatron(); - } - - listen(integer chan, string name, key id, string msg) { - if (chan != MEDIATRON_CHANNEL) return; // how are we even hearing that? - if (ONLY_OWNER && (id != llGetOwner())) return; // unauthorized talker. - hear_voices(TRUE, name, id, msg); - } - - on_rez(integer start_parm) { - llResetScript(); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - reload_notecards(); - } - } - - link_message(integer sender, integer num, string msg, key id) { - if (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) { - process_button_clicks(msg, id); - return; - } - if (num == MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) { - react_to_menu(msg, id); - } - - if (num != SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. - handle_slate_items(msg, id); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.txt new file mode 100755 index 00000000..0855fa5b --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/mediatron_control_v7.2.txt @@ -0,0 +1,727 @@ + +// huffware script: mediatron control, by fred huffhines. +// +// controls the mediatron device and manages menus for the user. +// when buttons are clicked, this is the script that arranges for things to +// happen. this script also processes the spoken commands from the user. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// configurable constants... + +integer MEDIATRON_CHANNEL = 1008; + // fairly arbitrary channel for listening. + +integer ONLY_OWNER = FALSE; + // only listen to the owner's chats? + +vector TEXT_COLOR = <0.5, 0.7, 0.92>; + // the color that the current chapter is displayed in. + +string LATEX_DRIVER_URL = "http://universalbuilds.com/tib/gif.php?l="; + // the URL for turning tex code into tibetan and english bitmaps. + +// global constants that really should stay constant... + +//////// +// link ids for flinging messages at them. +//----these are useless until the OAR link number bug is fixed. +//integer ROOT_PRIM_LINK = 1; // by SL conventions. +//integer MAIN_VIEWSCREEN_LINK = 2; // the next prim after the root is our viewer. +//integer NEXT_BUTTON_LINK = 3; +//integer PREVIOUS_BUTTON_LINK = 4; +//integer UHHH_BUTTON_LINK = 5; +//integer MENU_BUTTON_LINK = 6; +//integer BACKGROUND_PLATE_LINK = 7; // the blank whitish plank underneath the main viewscreen. +//////// + +integer DEFAULT_CHANNEL = 1008; // this must remain unchanged so we can dynamically modify help. + +// commands that can begin the line of text spoken on our special channel. +// these are also used for interchange with sub-prims, such as when a button is pushed. +string TIBETAN_CHUNK = "tib"; +string ENGLISH_CHUNK = "en"; +string NEW_LINE_CMD = "line"; +string SHOW_BUFFER_CMD = "go"; + +string NEXT_PAGE_CMD = "next"; +string PREVIOUS_PAGE_CMD = "prev"; + +string RESET_MEDIATRON_CMD = "Reset"; +string CLEAR_MEDIATRON_CMD = "Clear"; + +string OPEN_MENU_CMD = "menu"; +string CHAPTER_PICKER_CMD = "chapter"; + +string CHANNEL_CHANGE_CMD = "channel"; +string DRIVER_WEB_SITE_CMD = "urldriver"; +string LOAD_WEB_PAGE_CMD = "loadweb"; + +string TEXT_COLOR_CHANGE_CMD = "textcolor"; + +string HELP_CMD = "Help"; + +// config / control menus that we support. +string STATUS_ITEM = "Status"; +string AUTHORIZE_ITEM = "Authorize"; +string TEXT_COLOR_ITEM = "Text Color"; +string CHANNEL_ITEM = "Channel"; +string WEB_SITE_ITEM = "Driver URL"; + +// API for the viewscreen blitter library... +////////////// +integer VIEWSCREEN_BLITTER_HUFFWARE_ID = 10027; + // unique ID for the viewscreen services. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// +string SHOW_URL_COMMAND = "#shurl"; + // requests the viewscreen to show a particular URL as its texture. +string RESET_VIEWSCREEN_COMMAND = "#shrz"; + // resets the viewscreen script to the default state. +string SHOW_TEXTURE_COMMAND = "#shtex"; + // displays a texture on the prim. the first parameter is the texture key or name. +////////////// + +// API for moving between the active notecards. +////////////// +// do not redefine these constants. +integer SLATE_READER_HUFFWARE_ID = 10028; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +string RESET_SLATE_READER_COMMAND = "#rsslt"; + // causes the notecard information to be forgotten and the script restarted. +string SR_GET_INFORMATION_COMMAND = "#infy"; + // used by clients to ask for information about the current number of notecards + // available, and their names. this information is sent back on the huffware ID + // plus the reply distance. first parm is the number, and the rest are the names. +string SR_PLAY_CARD_COMMAND = "#playvo"; + // picks a particular notecard for reading and send the notecard's contents in a + // series of link messages, using this command and the reply distance. there are + // two parameters: an integer for the notecard number to read (from 0 through the + // number of notecards - 1) and the link number to send the messages to. +////////////// + +// the button pushing API. +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10029; + // a unique ID within the huffware system for this script. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was pushed. +////////////// + +// menutini link message API... +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. + // the reply will include: the menu name, the choice made and the key for + // the avatar. +////////////// + +// global variables... + +string buffer_text; // the buffer being accumulated for display. + +integer page_number; // current page shown: ranges from zero to number of notecards - 1. + +integer maximum_notecards; // the maximum notecards that can be shown. + +list notecard_choices; // the chapters that can be chosen. + +integer listening_handle; // tracks our listening so we can change channels. + +set_viewscreen_texture() +{ + // get the video texture they want to use for the parcel. + key texture_key = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]), 0); + if (texture_key == NULL_KEY) { + // there wasn't one set yet. we can't do much about that here. we'll use the + // last inventory texture instead, which usually will be our proper image. + texture_key = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, + llGetInventoryNumber(INVENTORY_TEXTURE) - 1)); + if (texture_key == NULL_KEY) return; // now we're hosed; there's no texture. + } + // set the main viewer prim to the chosen texture... + llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, + SHOW_TEXTURE_COMMAND, (string)texture_key); +} + +// checks the parcel's media texture to make sure it's set. if it's not, we reset it to +// our favorite version. +fix_parcel_media_texture() +{ + // get the video texture they want to use for the parcel. + key texture_key = llList2Key(llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]), 0); + if (texture_key == NULL_KEY) { + // there wasn't one set yet, so we need to fix that. we'll use the last inventory + // texture, which usually will be our proper image. this is a distinct chore from + // setting the viewscreen's texture, since we don't know that we have the capability + // to change the parcel media texture yet. + texture_key = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, + llGetInventoryNumber(INVENTORY_TEXTURE) - 1)); + if (texture_key != NULL_KEY) { + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE, texture_key]); + if (llGetLandOwnerAt(llGetPos()) != llGetOwner()) { + log_it("There is a problem with the parcel media: " + + llGetObjectName() + " is not owned by the parcel owner."); + } else { + log_it("No media texture found for video on this parcel. Using default texture: " + + (string)texture_key); + } + } else { + log_it("The object does not seem to contain any textures; we need at " + + "least one for a default viewscreen image."); + } + } +} + +// asks the slate reader to find out what cards there are for us. +reload_notecards() +{ + // now we find out what's really present so we can offer a menu. + llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, + SR_GET_INFORMATION_COMMAND, ""); +} + +// fixes the viewscreen face and parcel media texture, if needed, and gets the mediatron +// ready for commands. +initialize_mediatron() +{ + fix_parcel_media_texture(); + set_viewscreen_texture(); + llSetText("", TEXT_COLOR, 0.0); + page_number = -1; + reload_notecards(); + + // listening for commands from the user. + listening_handle = llListen(MEDIATRON_CHANNEL, "", NULL_KEY, ""); + + llSay(0, "Now listening for commands on channel /" + (string)MEDIATRON_CHANNEL); +} + +// locates the space boundaries between words and returns just a list of the words, +// with no spaces remaining. +list break_on_spaces(string msg) +{ + if (!llStringLength(msg)) return []; // no length means no list. + integer indy; + list to_return; + for (indy = 0; indy < llStringLength(msg); indy++) { + integer space_posn = llSubStringIndex(msg, " "); + if (space_posn < 0) { + // no spaces left, so use the whole string. + to_return += [ msg ]; + indy = 2 * llStringLength(msg); + } else { + // we found a space. chop out the first part to add to the list and + // keep the second part for further scanning. + to_return += [ llGetSubString(msg, 0, space_posn - 1) ]; + // we also trash any additional spaces that were after the one we found. + msg = llStringTrim(llGetSubString(msg, space_posn + 1, -1), STRING_TRIM); + indy = -1; // start over at top of string. + } + } + return to_return; +} + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +simply_display_menu(string menu_name, string title, list buttons) +{ + integer menu_channel = random_channel(); + key listen_to = llGetOwner(); + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR + + (string)menu_channel + HUFFWARE_PARM_SEPARATOR + + (string)listen_to); +} + +// handles when a button on the device has been clicked. +process_button_clicks(string msg, key id) +{ + if (msg != BUTTON_PUSHED_ALERT) return; // uhhhh, not sure what that was. + if (id == NEXT_PAGE_CMD) { + hear_voices(FALSE, "self", llGetOwner(), id); + } else if (id == PREVIOUS_PAGE_CMD) { + hear_voices(FALSE, "self", llGetOwner(), id); + } else if (id == CHAPTER_PICKER_CMD) { + list pruned_choices; + string list_as_block; + integer indy; + for (indy = 0; indy < llGetListLength(notecard_choices); indy++) { + string curr_name = prune_notecard_name(llList2String(notecard_choices, indy)); + pruned_choices += [ curr_name ]; + list_as_block += (string)(indy + 1) + ". " + curr_name; + if (indy < llGetListLength(notecard_choices) - 1) list_as_block += "\n"; + } + simply_display_menu(CHAPTER_PICKER_CMD, "Pick the Chapter to display...\n" + list_as_block, + pruned_choices); + } else if (id == OPEN_MENU_CMD) { + simply_display_menu(OPEN_MENU_CMD, "TibSlate Mediatron Control Menu", + [ HELP_CMD, STATUS_ITEM, AUTHORIZE_ITEM, TEXT_COLOR_ITEM, CHANNEL_ITEM, + WEB_SITE_ITEM, CLEAR_MEDIATRON_CMD, RESET_MEDIATRON_CMD ]); + } +} + +string bool_string_for_int(integer truth) +{ + if (truth) return "true"; else return "false"; +} + +tell_not_authorized() +{ + llSay(0, "The operation you have chosen can only be performed by the owner."); +} + +// handles the response message when the user chooses a button. +react_to_menu(string msg, key id) +{ + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string which_choice = llList2String(parms, 1); + key av_key = llList2String(parms, 2); + if (ONLY_OWNER && (av_key != llGetOwner())) { + tell_not_authorized(); + return; + } +//log_it("you clicked " + which_choice + " item for av " + av_key); + + if (menu_name == CHAPTER_PICKER_CMD) { + // find the index of the choice if we can, and make the choice be the new page. + page_number = find_similar_in_list(notecard_choices, which_choice); + play_chapter(); + return; + } else if (menu_name == OPEN_MENU_CMD) { + // show the main control menu. + if (which_choice == STATUS_ITEM) { + llSay(0, "Status...\n\tMemory Free " + (string)llGetFreeMemory() + + "\n\tListening Channel " + (string)MEDIATRON_CHANNEL + + "\n\tOwner Only? " + bool_string_for_int(ONLY_OWNER)); + return; + } else if (which_choice == AUTHORIZE_ITEM) { + if (av_key != llGetOwner()) { + // this option isn't allowed for anyone but the owner, ever. + tell_not_authorized(); + return; + } + simply_display_menu(AUTHORIZE_ITEM, "Authorization required to use device...", + [ "Any User", "Only Owner" ]); + return; + } else if (which_choice == TEXT_COLOR_ITEM) { + llSay(0, "To change the text color, say\n\t/" + + (string)MEDIATRON_CHANNEL + " " + TEXT_COLOR_CHANGE_CMD + + " \nwhere r, g, and b are the red, green and blue components of the color.\n" + + "Note that r, g & b can range from 0 to 1 inclusive."); + return; + } else if (which_choice == CHANNEL_ITEM) { + llSay(0, "To change the channel of the viewer, say\n\t/" + + (string)MEDIATRON_CHANNEL + " " + CHANNEL_CHANGE_CMD + + " N\nwhere N is a number for the new channel."); + return; + } else if (which_choice == WEB_SITE_ITEM) { + llSay(0, "Current driver web URL: " + LATEX_DRIVER_URL + + "\nTo replace this site, say:\n\t/" + + (string)MEDIATRON_CHANNEL + " " + DRIVER_WEB_SITE_CMD + + " newURL\nNote that this site must be capable of accepting LaTex code and\n" + + "converting that into simulator compatible bitmaps."); + return; + } else { + // handle all the others by just passing this on to the hear voices function. + // if it's a known command, we handle it. otherwise we bounce it off the couch. + hear_voices(FALSE, "self", llGetOwner(), which_choice); + return; + } + // the remainder of these handle the menu button's menu options... + } else if (menu_name == AUTHORIZE_ITEM) { + // they chose an option for authorization, so see if it was for only the owner. + ONLY_OWNER = is_prefix(which_choice, "only"); + llSay(0, "now, Owner Only = " + bool_string_for_int(ONLY_OWNER)); + return; + } + +log_it("i do not understand item " + which_choice + " in "+ menu_name); +} + +// processes the responses from the slate reader. +handle_slate_items(string msg, key id) +{ + if (msg == SR_PLAY_CARD_COMMAND) { + // we have gotten some data from our reader. + hear_voices(FALSE, "self", llGetOwner(), id); + } else if (msg == SR_GET_INFORMATION_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + maximum_notecards = llList2Integer(parms, 0); +//log_it("got info response, num notes=" + (string)maximum_notecards); + notecard_choices = llList2List(parms, 1, -1); + } +} + +// strips off any numerical info to make a more useful notecard name. +string prune_notecard_name(string note_name) +{ + // we look at the name and remove any numbers in front, so we can avoid cluttering up the + // user facing text with the numbers that are used for ordering the notecards. + list rip_these = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", " ", "." ]; + while (llListFindList(rip_these, [ llGetSubString(note_name, 0, 0) ]) >= 0) { + // found a number or space or period. rip it off. + note_name = llDeleteSubString(note_name, 0, 0); + } + return note_name; +} + +show_chapter_name() +{ + string note_name = prune_notecard_name(llList2String(notecard_choices, page_number)); + llSetText("Page #" + (string)(page_number + 1) + + " -- " + note_name, TEXT_COLOR, 1.0); +} + +// shows the contents of the current page's notecard on the viewscreen. +play_chapter() +{ + show_chapter_name(); + llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, + SR_PLAY_CARD_COMMAND, wrap_parameters([page_number, LINK_THIS])); +} + +// tell the viewscreen to display this possible tibetan. +// spoken reports whether it's a user speaking or not. if spoken is false, then +// the voice is internal from getting notecard info or button clicks. +hear_voices(integer spoken, string name, key id, string msg) +{ + msg = llStringTrim(msg, STRING_TRIM); // toss extra spaces. + if (msg == CLEAR_MEDIATRON_CMD) { + // wipe out anything on the screen. + set_viewscreen_texture(); + buffer_text = ""; // toss out any partial buffer also. + if (spoken) llSay(0, "Clearing viewscreen."); + page_number = -1; // reset page to the spot before the first. + llSetText("", TEXT_COLOR, 0.0); + return; + } else if ( (msg == RESET_MEDIATRON_CMD) && (id == llGetOwner()) ) { + llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, + RESET_VIEWSCREEN_COMMAND, ""); + llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, + RESET_SLATE_READER_COMMAND, ""); + if (spoken) llSay(0, "Resetting scripts."); + llResetScript(); + } else if (is_prefix(msg, CHANNEL_CHANGE_CMD)) { + integer new_channel = (integer)llGetSubString(msg, llStringLength(CHANNEL_CHANGE_CMD), -1); + llSay(0, "New channel is " + (string)new_channel); + MEDIATRON_CHANNEL = new_channel; + llListenRemove(listening_handle); + listening_handle = llListen(MEDIATRON_CHANNEL, "", NULL_KEY, ""); + return; + } else if (is_prefix(msg, TEXT_COLOR_CHANGE_CMD)) { + vector new_col = (vector)llGetSubString(msg, llStringLength(TEXT_COLOR_CHANGE_CMD), -1); + llSay(0, "New text color is " + (string)new_col); + TEXT_COLOR = new_col; + show_chapter_name(); + return; + } else if (is_prefix(msg, DRIVER_WEB_SITE_CMD)) { + string new_url = llGetSubString(msg, llStringLength(DRIVER_WEB_SITE_CMD), -1); + llSay(0, "New driver URL for LaTex: " + (string)new_url); + LATEX_DRIVER_URL = new_url; + return; + } else if (is_prefix(msg, NEXT_PAGE_CMD)) { + page_number++; + if (page_number >= maximum_notecards) { + page_number = 0; + } + play_chapter(); + return; + } else if (is_prefix(msg, PREVIOUS_PAGE_CMD)) { + page_number--; + if (page_number < 0) { + page_number = maximum_notecards - 1; + } + show_chapter_name(); + llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID, + SR_PLAY_CARD_COMMAND, wrap_parameters([page_number, LINK_THIS])); + return; + } else if (is_prefix(msg, HELP_CMD)) { + provide_help(); + return; + } else if (is_prefix(msg, LOAD_WEB_PAGE_CMD)) { + string new_url = llGetSubString(msg, llStringLength(LOAD_WEB_PAGE_CMD), -1); + llSay(0, "Loading web site: " + (string)new_url); + llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, SHOW_URL_COMMAND, new_url); + buffer_text = ""; // clear the buffer out. + } + + // now we try to process the screen buffer commands which we suspect + // are in the text that was spoken. + list sentence = break_on_spaces(msg); + string first_word = llList2String(sentence, 0); +//log_it("first word is: " + first_word); + string remainder; + integer indo; + for (indo = 1; indo < llGetListLength(sentence); indo++) { + if (indo != 1) remainder += " "; + remainder += llList2String(sentence, indo); + } +//log_it("remainder is: " + remainder); + + if (first_word == TIBETAN_CHUNK) { + if (spoken) llSay(0, "Added Tibetan: " + remainder); + buffer_text += "{\\tib " + remainder + "}{ }"; + } else if (first_word == ENGLISH_CHUNK) { + if (spoken) llSay(0, "Added English: " + remainder); + buffer_text += "{" + remainder + " }"; + } else if (first_word == NEW_LINE_CMD) { + if (spoken) llSay(0, "Inserted blank line."); + buffer_text += "{\\\\}"; + } else if (first_word == SHOW_BUFFER_CMD) { + if (spoken) llSay(0, "Displaying buffered screen."); + // reset text label since that's no longer our page. + if (spoken) llSetText("", TEXT_COLOR, 0.0); + string url = LATEX_DRIVER_URL + buffer_text; + llMessageLinked(LINK_SET, VIEWSCREEN_BLITTER_HUFFWARE_ID, SHOW_URL_COMMAND, url); + buffer_text = ""; // clear the buffer out. + } else { + // treat this as english. +//mostly redundant! + if (spoken) llSay(0, "Added English: " + first_word + " " + remainder); + buffer_text += "{" + first_word + " " + remainder + "}"; + // if we're assuming this is english, we will plug in a blank line afterwards. + // otherwise a text document will look right awful. + buffer_text += "{\\\\}"; + } +} + +// hands out any notecards with help in their names. +provide_help() +{ + integer count = llGetInventoryNumber(INVENTORY_NOTECARD); + integer indy; + list help_cards = []; + for (indy = 0; indy < count; indy++) { + string note_name = llGetInventoryName(INVENTORY_NOTECARD, indy); + if (find_substring(note_name, "help") >= 0) + help_cards += [ note_name ]; + } + + if (llGetListLength(help_cards)) llOwnerSay("Here is the built-in help file..."); + else llOwnerSay("There are currently no help notecards; sorry."); + // iterate on helper cards and give them out. + count = llGetListLength(help_cards); + for (indy = 0; indy < count; indy++) { + string note_name = llList2String(help_cards, indy); + llGiveInventory(llGetOwner(), note_name); + } +} + + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +////////////// + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(llToLower(compare_with), llToLower(prefix)) == 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// locates the string "text" as a partial match in the list to "search_in". +integer find_similar_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (find_substring(llList2String(search_in, i), text) >= 0) + return i; + } + return -1; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + initialize_mediatron(); + } + + listen(integer chan, string name, key id, string msg) { + if (chan != MEDIATRON_CHANNEL) return; // how are we even hearing that? + if (ONLY_OWNER && (id != llGetOwner())) return; // unauthorized talker. + hear_voices(TRUE, name, id, msg); + } + + on_rez(integer start_parm) { + llResetScript(); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + reload_notecards(); + } + } + + link_message(integer sender, integer num, string msg, key id) { + if (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) { + process_button_clicks(msg, id); + return; + } + if (num == MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) { + react_to_menu(msg, id); + } + + if (num != SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. + handle_slate_items(msg, id); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.lsl deleted file mode 100755 index 22ddbe46..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.lsl +++ /dev/null @@ -1,533 +0,0 @@ - -// huffware script: menu list manager, by fred huffhines. -// -// deals with popping up menus when desired. does not do any configuration -// reading; that all must be fed to the script via link messages. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -string GIFTING_MENU_NAME = "#gifting#"; - // the menu name that we support internally for giving gifts. - -// global variables... - -// these are the definition of the menuing system, -// and are valid once we have heard our config. - -// unique identifiers of menu names. -list menu_names; -// a list of titles for the menus. -list menu_titles; -// the menu choices are strings containing encoded lists of button text labels. -list menu_button_lists; - -// store current activated menu info... -string _private_global_av_name; -string _private_global_av_key; - -// menu list manager link message API. -////////////// -// do not redefine these constants. -integer MENU_LIST_MANAGER_HUFFWARE_ID = 10033; - // the unique id within the huffware system for this sensor plugin script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string MENU_LIST_MGR_RESET = "#ml-reset#"; - // throws out any current menus and gets ready to load a new set. -string MENU_LIST_MGR_ADD_MENU = "#ml-addmenu#"; - // puts a new menu into our list. this requires 3 parameters: menu name, - // menu title, menu button list. -string MENU_LIST_MGR_SHOW_MENU = "#ml-shomenu#"; - // a request that a particular menu be shown. the first parameter is the menu index. - // the second parameter is the avatar name. the third parameter is the avatar key. -string MENU_LIST_MGR_GIVE_ITEM = "#ml-give#"; - // brings up a gift giving menu. parms are avatar name and avatar key. -string MENU_LIST_MGR_MODIFY_MENU = "#ml-modmenu#"; -string MENU_LIST_KEEP_WORD = "KEEP"; - // replaces a menu already in the list. this requires 4 parameters: menu index, menu name, - // menu title, menu button list. if a parameter is the MENU_LIST_KEEP_WORD, then that field - // is not changed. -string MENU_LIST_MGR_CHOICE_MADE_ALERT = "#ml-event-picked"; - // alerts the driver for this script that the owner has picked a choice. the - // parameters include: the text of the choice, the name of the menu, the avatar name, - // the avatar key. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// requires HUD sensor plugin v21.4 or better. -////////////// -// do not redefine these constants. -integer SENSOR_PLUGIN_HUFFWARE_ID = 10014; - // the unique id within the huffware system for this sensor plugin script. -string GIVE_ALL_AVATARS = "#santa#"; - // if this is received, the sensor plugin attempts to hand out an object passed as - // the first parameter to every avatar it knows about. -////////////// - -// requires menutini v3.9 or better... -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -// commands available via menutini: -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. -// -////////////// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -// -////////////// - -// replaces occurences of $owner and $avatar with the owner's name and the -// targeted avatars name. _first and _last added to the name cause the first -// or last name to be used instead. -string senso_substitute_vars(string to_substitute, string avatars_name) -{ - string owners_name = llKey2Name(llGetOwner()); - return substitute_variable_list(to_substitute, - [ "avatar_first", "avatar_last", "avatar", - "owner_first", "owner_last", "owner" ], - [ first_name(avatars_name), last_name(avatars_name), avatars_name, - first_name(owners_name), last_name(owners_name), owners_name ]); -} - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -simply_display_menu(string menu_name, string title, list buttons, - string av_name, string av_key) -{ - // we only manage one global now for this stuff... - _private_global_av_name = av_name; - _private_global_av_key = av_key; - - integer menu_channel = random_channel(); - key listen_to = llGetOwner(); -//log_it("passing in key to use: " + (string)listen_to); - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR - + (string)menu_channel + HUFFWARE_PARM_SEPARATOR - + (string)listen_to); -} - -replace_vars_and_display_menu(integer menu_index, string av_name, string av_key) -{ - // patch the avatar names and owner names before displaying. - string title = senso_substitute_vars(llList2String(menu_titles, menu_index), av_name); - string button_text = llList2String(menu_button_lists, menu_index); - - simply_display_menu(llList2String(menu_names, menu_index), title, - llParseString2List(button_text, [HUFFWARE_ITEM_SEPARATOR], []), - av_name, av_key); -} - -// shows a menu by index. -show_menu(integer index, string av_name, string av_key) -{ - replace_vars_and_display_menu(index, av_name, av_key); -//log_it("sent the menu request... memory left=" + (string)llGetFreeMemory()); -} - -// handles the response message when the user chooses a button. -react_to_menu(string menu_name, string av_name, string av_key, string which_choice) -{ -//log_it("you clicked " + which_choice + " item for av " + av_name); - handle_chosen_menu_item(menu_name, av_name, av_key, which_choice); -} - -// the gift giving menu. we show the menu after looking through the -// inventory. if the owner picks an item, we'll deal with that response. -show_gift_menu(string av_name, string av_key) -{ - string menu_name = "gift"; - string menu_title = "Pick a gift for " + av_name + "..."; - list menu_button_list = []; - integer indy; - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) { - menu_button_list += llGetInventoryName(INVENTORY_OBJECT, indy); - } - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) { - string item_name = llGetInventoryName(INVENTORY_TEXTURE, indy); - if (!is_prefix(item_name, "ean hud keys")) - menu_button_list += item_name; - } - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_LANDMARK); indy++) { - menu_button_list += llGetInventoryName(INVENTORY_LANDMARK, indy); - } - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) { - string item_name = llGetInventoryName(INVENTORY_NOTECARD, indy); - if ( (find_substring(item_name, "help") < 0) - && (find_substring(item_name, "Help") < 0) - && (find_substring(item_name, "config") < 0) ) - menu_button_list += item_name; - } - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_CLOTHING); indy++) { - menu_button_list += llGetInventoryName(INVENTORY_CLOTHING, indy); - } - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_GESTURE); indy++) { - menu_button_list += llGetInventoryName(INVENTORY_GESTURE, indy); - } - - if (llGetListLength(menu_button_list) == 0) { - llOwnerSay("There are no objects loaded in the hud currently. I can make no gifts."); - } - simply_display_menu(GIFTING_MENU_NAME, menu_title, menu_button_list, - av_name, av_key); -} - -// handles a request for this library itself. -process_hud_menu_mgr_request(integer sender, integer num, string msg, key id) -{ - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == MENU_LIST_MGR_RESET) { - llResetScript(); - } else if (msg == MENU_LIST_MGR_ADD_MENU) { - if (llGetListLength(parms) < 3) { - log_it("too few parms to add menu."); - return; - } -//hmmm: sloppy list processing! - menu_names += [ llList2String(parms, 0) ]; - menu_titles += [ llList2String(parms, 1) ]; - menu_button_lists += [ llList2String(parms, 2) ]; - } else if (msg == MENU_LIST_MGR_GIVE_ITEM) { - // give over a gift. - string av_name = llList2String(parms, 0); - string av_key = llList2String(parms, 1); - show_gift_menu(av_name, av_key); - } else if (msg == MENU_LIST_MGR_SHOW_MENU) { - if (llGetListLength(parms) < 3) { - log_it("too few parms to show menu."); - return; - } -//log_it("key comes as " + llList2String(parms, 2)); - show_menu((integer)llList2String(parms, 0), llList2String(parms, 1), - (key)llList2String(parms, 2)); -//log_it("show menu... memory left=" + (string)llGetFreeMemory()); - } else if (msg == MENU_LIST_MGR_MODIFY_MENU) { - if (llGetListLength(parms) < 4) { - log_it("too few parms to replace menu."); - return; - } - integer indo = (integer)llList2String(parms, 0); -//log_it("modif menu request, indo is " + (string)indo); - if (indo >= llGetListLength(menu_names)) { -//log_it("index too large in replace menu"); - return; - } -//log_it("replacing entry " + (string)indo + " with " + llList2String(parms, 1) + ", " + llList2String(parms, 2) + ", " + llList2String(parms, 3)); - if (llList2String(parms, 1) != MENU_LIST_KEEP_WORD) - menu_names = replace_entry(menu_names, indo, [ llList2String(parms, 1) ]); - if (llList2String(parms, 2) != MENU_LIST_KEEP_WORD) - menu_titles = replace_entry(menu_titles, indo, [ llList2String(parms, 2) ]); - if (llList2String(parms, 3) != MENU_LIST_KEEP_WORD) - menu_button_lists = replace_entry(menu_button_lists, indo, [ llList2String(parms, 3) ]); -//log_it("new menu button:" + llList2String(parms, 3)); - } -} - -// processes a message from a link. some of this must be handled -// by the driver script that handles our configuration. -handle_link_message(integer sender, integer num, string msg, key id) -{ - if (num == MENU_LIST_MANAGER_HUFFWARE_ID) { - process_hud_menu_mgr_request(sender, num, msg, id); - } - - if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != SHOW_MENU_COMMAND) ) return; // not for us. - -//log_it("menu reply: sndr=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string which_choice = llList2String(parms, 1); -///not used: key av_key = llList2String(parms, 2); -//hmmm: should the menutini also offer av name and key options??? - react_to_menu(menu_name, _private_global_av_name, - _private_global_av_key, which_choice); -} - -////////////// - -// gives a present to the avatar named here. -give_gift(string av_name, string av_key, string present) -{ -//log_it("trying to give a gift of " + present + " to " + av_name); - if (av_name != "ALL") { - llGiveInventory(av_key, present); - llOwnerSay("gave " + present + " to " + av_name); - } else { - // send the request back to the sensor plugin for processing. - llMessageLinked(LINK_ROOT, SENSOR_PLUGIN_HUFFWARE_ID, - GIVE_ALL_AVATARS, wrap_parameters([present])); - } -} - -handle_chosen_menu_item(string menu_name, string av_name, - string av_key, string which_choice) -{ - if (menu_name == GIFTING_MENU_NAME) { - give_gift(av_name, av_key, which_choice); - } - - // send the alert to the driver. - llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE, - MENU_LIST_MGR_CHOICE_MADE_ALERT, - wrap_parameters([which_choice, menu_name, av_name, av_key])); -} - -////////////// -// from hufflets... -// -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -////////////// - -// returns the position of the last space in "look_within" or a negative number. -integer find_last_space(string look_within) -{ - integer indy = llStringLength(look_within) - 1; - while ( (indy >= 0) && (llGetSubString(look_within, indy, indy) != " ") ) indy--; - return indy; -} - -// returns the first name for an avatar with the "full_name". -string first_name(string full_name) -{ - integer finding = find_last_space(full_name); - if (finding >= 0) return llGetSubString(full_name, 0, finding - 1); - return full_name; // failed to find space. -} - -// returns the last name for an avatar with the "full_name". -string last_name(string full_name) -{ - integer finding = find_last_space(full_name); - if (finding >= 0) return llGetSubString(full_name, finding + 1, -1); - return full_name; // failed to find space. -} - -// substitutes a variable's name for its value. note that variables are assumed to start -// with a dollar sign character, which should not be provided in the "variable_name" parameter. -string substitute_variable(string substitute_within, string variable_name, string variable_value) -{ - string to_return = substitute_within; - integer posn; - while ( (posn = find_substring(to_return, "$" + variable_name)) >= 0) { - // we found an occurrence of the variable. - to_return = llDeleteSubString(to_return, posn, -1) // keep part before. - + variable_value // add the value in place of the variable name. - + llDeleteSubString(to_return, 0, posn + llStringLength(variable_name)); - // keep part after. - } - return to_return; -} - -// in "substitute_within", this finds any occurrences of items in the "variables_names" -// and replaces those with the corresponding item from "variable_values". -string substitute_variable_list(string substitute_within, list variable_names, list variable_values) -{ - string to_return = substitute_within; - integer vars = llGetListLength(variable_names); - if (vars != llGetListLength(variable_values)) { -// log_it("error in substitute_variable_list: inequal number of variable names vs. values."); - return to_return; - } - integer indy; - for (indy = 0; indy < vars; indy++) { - to_return = substitute_variable(to_return, - llList2String(variable_names, indy), - llList2String(variable_values, indy)); - } - return to_return; -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// removes the entry at "index" and instead inserts the list "to_insert" -// at that position. -list replace_entry(list to_modify, integer index, list to_insert) -{ - if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. - return llListReplaceList(to_modify, to_insert, index, index); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } -// -// end hufflets -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - // reset all our variables. - menu_names = []; - menu_titles = []; - menu_button_lists = []; - _private_global_av_name = ""; - _private_global_av_key = NULL_KEY; - } - - link_message(integer sender, integer num, string msg, key id) - { handle_link_message(sender, num, msg, id); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.txt new file mode 100755 index 00000000..22ddbe46 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/menu_list_manager_v12.4.txt @@ -0,0 +1,533 @@ + +// huffware script: menu list manager, by fred huffhines. +// +// deals with popping up menus when desired. does not do any configuration +// reading; that all must be fed to the script via link messages. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +string GIFTING_MENU_NAME = "#gifting#"; + // the menu name that we support internally for giving gifts. + +// global variables... + +// these are the definition of the menuing system, +// and are valid once we have heard our config. + +// unique identifiers of menu names. +list menu_names; +// a list of titles for the menus. +list menu_titles; +// the menu choices are strings containing encoded lists of button text labels. +list menu_button_lists; + +// store current activated menu info... +string _private_global_av_name; +string _private_global_av_key; + +// menu list manager link message API. +////////////// +// do not redefine these constants. +integer MENU_LIST_MANAGER_HUFFWARE_ID = 10033; + // the unique id within the huffware system for this sensor plugin script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string MENU_LIST_MGR_RESET = "#ml-reset#"; + // throws out any current menus and gets ready to load a new set. +string MENU_LIST_MGR_ADD_MENU = "#ml-addmenu#"; + // puts a new menu into our list. this requires 3 parameters: menu name, + // menu title, menu button list. +string MENU_LIST_MGR_SHOW_MENU = "#ml-shomenu#"; + // a request that a particular menu be shown. the first parameter is the menu index. + // the second parameter is the avatar name. the third parameter is the avatar key. +string MENU_LIST_MGR_GIVE_ITEM = "#ml-give#"; + // brings up a gift giving menu. parms are avatar name and avatar key. +string MENU_LIST_MGR_MODIFY_MENU = "#ml-modmenu#"; +string MENU_LIST_KEEP_WORD = "KEEP"; + // replaces a menu already in the list. this requires 4 parameters: menu index, menu name, + // menu title, menu button list. if a parameter is the MENU_LIST_KEEP_WORD, then that field + // is not changed. +string MENU_LIST_MGR_CHOICE_MADE_ALERT = "#ml-event-picked"; + // alerts the driver for this script that the owner has picked a choice. the + // parameters include: the text of the choice, the name of the menu, the avatar name, + // the avatar key. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// requires HUD sensor plugin v21.4 or better. +////////////// +// do not redefine these constants. +integer SENSOR_PLUGIN_HUFFWARE_ID = 10014; + // the unique id within the huffware system for this sensor plugin script. +string GIVE_ALL_AVATARS = "#santa#"; + // if this is received, the sensor plugin attempts to hand out an object passed as + // the first parameter to every avatar it knows about. +////////////// + +// requires menutini v3.9 or better... +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +// commands available via menutini: +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. +// +////////////// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +// +////////////// + +// replaces occurences of $owner and $avatar with the owner's name and the +// targeted avatars name. _first and _last added to the name cause the first +// or last name to be used instead. +string senso_substitute_vars(string to_substitute, string avatars_name) +{ + string owners_name = llKey2Name(llGetOwner()); + return substitute_variable_list(to_substitute, + [ "avatar_first", "avatar_last", "avatar", + "owner_first", "owner_last", "owner" ], + [ first_name(avatars_name), last_name(avatars_name), avatars_name, + first_name(owners_name), last_name(owners_name), owners_name ]); +} + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +simply_display_menu(string menu_name, string title, list buttons, + string av_name, string av_key) +{ + // we only manage one global now for this stuff... + _private_global_av_name = av_name; + _private_global_av_key = av_key; + + integer menu_channel = random_channel(); + key listen_to = llGetOwner(); +//log_it("passing in key to use: " + (string)listen_to); + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR + + (string)menu_channel + HUFFWARE_PARM_SEPARATOR + + (string)listen_to); +} + +replace_vars_and_display_menu(integer menu_index, string av_name, string av_key) +{ + // patch the avatar names and owner names before displaying. + string title = senso_substitute_vars(llList2String(menu_titles, menu_index), av_name); + string button_text = llList2String(menu_button_lists, menu_index); + + simply_display_menu(llList2String(menu_names, menu_index), title, + llParseString2List(button_text, [HUFFWARE_ITEM_SEPARATOR], []), + av_name, av_key); +} + +// shows a menu by index. +show_menu(integer index, string av_name, string av_key) +{ + replace_vars_and_display_menu(index, av_name, av_key); +//log_it("sent the menu request... memory left=" + (string)llGetFreeMemory()); +} + +// handles the response message when the user chooses a button. +react_to_menu(string menu_name, string av_name, string av_key, string which_choice) +{ +//log_it("you clicked " + which_choice + " item for av " + av_name); + handle_chosen_menu_item(menu_name, av_name, av_key, which_choice); +} + +// the gift giving menu. we show the menu after looking through the +// inventory. if the owner picks an item, we'll deal with that response. +show_gift_menu(string av_name, string av_key) +{ + string menu_name = "gift"; + string menu_title = "Pick a gift for " + av_name + "..."; + list menu_button_list = []; + integer indy; + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) { + menu_button_list += llGetInventoryName(INVENTORY_OBJECT, indy); + } + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) { + string item_name = llGetInventoryName(INVENTORY_TEXTURE, indy); + if (!is_prefix(item_name, "ean hud keys")) + menu_button_list += item_name; + } + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_LANDMARK); indy++) { + menu_button_list += llGetInventoryName(INVENTORY_LANDMARK, indy); + } + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) { + string item_name = llGetInventoryName(INVENTORY_NOTECARD, indy); + if ( (find_substring(item_name, "help") < 0) + && (find_substring(item_name, "Help") < 0) + && (find_substring(item_name, "config") < 0) ) + menu_button_list += item_name; + } + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_CLOTHING); indy++) { + menu_button_list += llGetInventoryName(INVENTORY_CLOTHING, indy); + } + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_GESTURE); indy++) { + menu_button_list += llGetInventoryName(INVENTORY_GESTURE, indy); + } + + if (llGetListLength(menu_button_list) == 0) { + llOwnerSay("There are no objects loaded in the hud currently. I can make no gifts."); + } + simply_display_menu(GIFTING_MENU_NAME, menu_title, menu_button_list, + av_name, av_key); +} + +// handles a request for this library itself. +process_hud_menu_mgr_request(integer sender, integer num, string msg, key id) +{ + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == MENU_LIST_MGR_RESET) { + llResetScript(); + } else if (msg == MENU_LIST_MGR_ADD_MENU) { + if (llGetListLength(parms) < 3) { + log_it("too few parms to add menu."); + return; + } +//hmmm: sloppy list processing! + menu_names += [ llList2String(parms, 0) ]; + menu_titles += [ llList2String(parms, 1) ]; + menu_button_lists += [ llList2String(parms, 2) ]; + } else if (msg == MENU_LIST_MGR_GIVE_ITEM) { + // give over a gift. + string av_name = llList2String(parms, 0); + string av_key = llList2String(parms, 1); + show_gift_menu(av_name, av_key); + } else if (msg == MENU_LIST_MGR_SHOW_MENU) { + if (llGetListLength(parms) < 3) { + log_it("too few parms to show menu."); + return; + } +//log_it("key comes as " + llList2String(parms, 2)); + show_menu((integer)llList2String(parms, 0), llList2String(parms, 1), + (key)llList2String(parms, 2)); +//log_it("show menu... memory left=" + (string)llGetFreeMemory()); + } else if (msg == MENU_LIST_MGR_MODIFY_MENU) { + if (llGetListLength(parms) < 4) { + log_it("too few parms to replace menu."); + return; + } + integer indo = (integer)llList2String(parms, 0); +//log_it("modif menu request, indo is " + (string)indo); + if (indo >= llGetListLength(menu_names)) { +//log_it("index too large in replace menu"); + return; + } +//log_it("replacing entry " + (string)indo + " with " + llList2String(parms, 1) + ", " + llList2String(parms, 2) + ", " + llList2String(parms, 3)); + if (llList2String(parms, 1) != MENU_LIST_KEEP_WORD) + menu_names = replace_entry(menu_names, indo, [ llList2String(parms, 1) ]); + if (llList2String(parms, 2) != MENU_LIST_KEEP_WORD) + menu_titles = replace_entry(menu_titles, indo, [ llList2String(parms, 2) ]); + if (llList2String(parms, 3) != MENU_LIST_KEEP_WORD) + menu_button_lists = replace_entry(menu_button_lists, indo, [ llList2String(parms, 3) ]); +//log_it("new menu button:" + llList2String(parms, 3)); + } +} + +// processes a message from a link. some of this must be handled +// by the driver script that handles our configuration. +handle_link_message(integer sender, integer num, string msg, key id) +{ + if (num == MENU_LIST_MANAGER_HUFFWARE_ID) { + process_hud_menu_mgr_request(sender, num, msg, id); + } + + if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != SHOW_MENU_COMMAND) ) return; // not for us. + +//log_it("menu reply: sndr=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string which_choice = llList2String(parms, 1); +///not used: key av_key = llList2String(parms, 2); +//hmmm: should the menutini also offer av name and key options??? + react_to_menu(menu_name, _private_global_av_name, + _private_global_av_key, which_choice); +} + +////////////// + +// gives a present to the avatar named here. +give_gift(string av_name, string av_key, string present) +{ +//log_it("trying to give a gift of " + present + " to " + av_name); + if (av_name != "ALL") { + llGiveInventory(av_key, present); + llOwnerSay("gave " + present + " to " + av_name); + } else { + // send the request back to the sensor plugin for processing. + llMessageLinked(LINK_ROOT, SENSOR_PLUGIN_HUFFWARE_ID, + GIVE_ALL_AVATARS, wrap_parameters([present])); + } +} + +handle_chosen_menu_item(string menu_name, string av_name, + string av_key, string which_choice) +{ + if (menu_name == GIFTING_MENU_NAME) { + give_gift(av_name, av_key, which_choice); + } + + // send the alert to the driver. + llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE, + MENU_LIST_MGR_CHOICE_MADE_ALERT, + wrap_parameters([which_choice, menu_name, av_name, av_key])); +} + +////////////// +// from hufflets... +// +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +////////////// + +// returns the position of the last space in "look_within" or a negative number. +integer find_last_space(string look_within) +{ + integer indy = llStringLength(look_within) - 1; + while ( (indy >= 0) && (llGetSubString(look_within, indy, indy) != " ") ) indy--; + return indy; +} + +// returns the first name for an avatar with the "full_name". +string first_name(string full_name) +{ + integer finding = find_last_space(full_name); + if (finding >= 0) return llGetSubString(full_name, 0, finding - 1); + return full_name; // failed to find space. +} + +// returns the last name for an avatar with the "full_name". +string last_name(string full_name) +{ + integer finding = find_last_space(full_name); + if (finding >= 0) return llGetSubString(full_name, finding + 1, -1); + return full_name; // failed to find space. +} + +// substitutes a variable's name for its value. note that variables are assumed to start +// with a dollar sign character, which should not be provided in the "variable_name" parameter. +string substitute_variable(string substitute_within, string variable_name, string variable_value) +{ + string to_return = substitute_within; + integer posn; + while ( (posn = find_substring(to_return, "$" + variable_name)) >= 0) { + // we found an occurrence of the variable. + to_return = llDeleteSubString(to_return, posn, -1) // keep part before. + + variable_value // add the value in place of the variable name. + + llDeleteSubString(to_return, 0, posn + llStringLength(variable_name)); + // keep part after. + } + return to_return; +} + +// in "substitute_within", this finds any occurrences of items in the "variables_names" +// and replaces those with the corresponding item from "variable_values". +string substitute_variable_list(string substitute_within, list variable_names, list variable_values) +{ + string to_return = substitute_within; + integer vars = llGetListLength(variable_names); + if (vars != llGetListLength(variable_values)) { +// log_it("error in substitute_variable_list: inequal number of variable names vs. values."); + return to_return; + } + integer indy; + for (indy = 0; indy < vars; indy++) { + to_return = substitute_variable(to_return, + llList2String(variable_names, indy), + llList2String(variable_values, indy)); + } + return to_return; +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// removes the entry at "index" and instead inserts the list "to_insert" +// at that position. +list replace_entry(list to_modify, integer index, list to_insert) +{ + if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. + return llListReplaceList(to_modify, to_insert, index, index); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } +// +// end hufflets +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + // reset all our variables. + menu_names = []; + menu_titles = []; + menu_button_lists = []; + _private_global_av_name = ""; + _private_global_av_key = NULL_KEY; + } + + link_message(integer sender, integer num, string msg, key id) + { handle_link_message(sender, num, msg, id); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.lsl deleted file mode 100755 index abd27116..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.lsl +++ /dev/null @@ -1,436 +0,0 @@ - -// huffware script: menutini library, by fred huffhines. -// -// this is a library script for menuing that provides a way to remote control the -// menu, somewhat. another script can zing link messages at this script and a menu -// will be shown based on the specified description and buttons. when the user -// selects an answer, that result is sent back in a link message reply. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// useful constants you might want to change: - -integer TIMEOUT_FOR_MENU = 42; - // timeout for the menu in seconds. -//hmmm: may want this to be selectable from menu request. -// or may even want to never time out! -// if we managed a list of ongoing menus, that would work. -// currently it cannot. - -integer DEBUGGING = FALSE; - // if this is true, then extra info will be printed when handling a menu. - -string NEXT_MENU_TEXT = "Next >>"; - // what the next item will say for showing next menu page. - -// menutini link message API... -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. - // the reply will include: the menu name, the choice made and the key for - // the avatar. -// -////////////// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -// -////////////// - -// global variables... - -list _private_global_buttons; // holds onto the active set of menu options. -string _private_global_av_key; // the key for the avatar who clicks the menu. -string _private_global_title; // holds onto current title text. - -integer _menu_base_start = 0; // position in the items of the current menu. - -integer listening_id = 0; - // the current id of our listening for the menu. it's an id returned by LSL - // that we need to track so we can cancel the listen. - -integer menu_system_channel = 0; - // messages come back to us from this channel when user clicks the dialog. - // this is set later and the default is meaningless. - -string global_menu_name = ""; - // hangs onto the current menu's name. - -//hmmm: note; to manage multiple concurrent menus on different channels, -// we must make these into lists. then the timeouts should apply -// individually to these instead of overall (if we even do timeouts; -// it's nicer if menus never stop being active). - - -// displays the menu requested. it's "menu_name" is an internal name that is -// not displayed to the user. the "title" is the content shown in the main area -// of the menu. "commands_in" is the list of menu items to show as buttons. -// the "menu_channel" is where the user's clicked response will be sent. the -// "listen_to" key is the avatar expected to click the menu, which is needed to -// listen to his response. -show_menu(string menu_name, string title, list buttons, - integer menu_channel, key listen_to) -{ - // save our new parms. - global_menu_name = menu_name; - _private_global_title = title; - _private_global_buttons = buttons; - menu_system_channel = menu_channel; - _private_global_av_key = listen_to; - if (DEBUGGING) { - log_it("menu name: " + global_menu_name); - log_it("title: " + _private_global_title); - log_it("buttons: " + (string)buttons); - log_it("channel: " + (string)menu_system_channel); - log_it("listen key: " + (string)listen_to); - } - - integer add_next = FALSE; // true if we should add a next menu item. - - // the math here incorporates current button position. - integer current = _menu_base_start; - integer max_buttons = llGetListLength(buttons) - current; - - if (max_buttons > 12) { - // limitation of SL: menus have a max of 12 buttons. - max_buttons = 12; - add_next = TRUE; - } else if (llGetListLength(buttons) > 12) { - // we already have been adding next. let's make sure this gets - // a wrap-around next button. - add_next = TRUE; - } - // chop out what we can use in a menu. - list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); - if (add_next) { - // we were asked to add a menu item for the next screen. - trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; - } - - listening_id = llListen(menu_channel, "", listen_to, ""); - list commands; - integer i; - // take only the prefix of the string, to avoid getting a length complaint. - for (i = 0; i < llGetListLength(trunc_buttons); i++) { - string curr = llList2String(trunc_buttons, i); - integer last_pos = 23; // default maximum, highest possible is 24. - if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; - curr = llGetSubString(curr, 0, last_pos); - commands += curr; - } - llDialog(listen_to, title, commands, menu_channel); - llSetTimerEvent(TIMEOUT_FOR_MENU); -} - -// shuts down any connection we might have had with any active menu. we will not -// send any responses after this point (although we might already have responded when -// the user clicked the menu). -clear_menu() -{ - llListenRemove(listening_id); - llSetTimerEvent(0.0); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -// ours do differ from normal in that we send back the channel as the number parameter -// instead of enforcing that being MENU_HUFFWARE_ID. -send_reply(integer destination, integer channel, list parms, string command) -{ - llMessageLinked(destination, channel, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// processes the menu requests. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - if (huff_id != MENUTINI_HUFFWARE_ID) return; // not for us. - - if (msg == SHOW_MENU_COMMAND) { - _menu_base_start = 0; // reset the position in the menus. - // separate the list out. -//log_it("id showing: " + id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - // toss any existing menu info. - clear_menu(); -//log_it("key here early: " + llList2String(parms, 4)); - show_menu(llList2String(parms, 0), llList2String(parms, 1), - llParseString2List(llList2String(parms, 2), - [HUFFWARE_ITEM_SEPARATOR], []), - (integer)llList2String(parms, 3), - (key)llList2String(parms, 4)); - } -} - -// process the response when the user chooses a menu item. this causes our -// caller to be told what was selected. -process_menu_response(integer channel, string name, key id, string message) -{ - if (channel != menu_system_channel) return; // not for us. - - if (message == NEXT_MENU_TEXT) { - // this is the special choice, so we need to go to the next page. - _menu_base_start += 11; - if (_menu_base_start > llGetListLength(_private_global_buttons)) { - // we have wrapped around the list. go to the start again. - _menu_base_start = 0; - } - show_menu(global_menu_name, _private_global_title, - _private_global_buttons, menu_system_channel, - _private_global_av_key); - return; // handled by opening a new menu. - } - - string calculated_name; - integer indy; - // first try for an exact match. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (curr == message) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - if (calculated_name == "") { - // try an imprecise match if the exact matching didn't work. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (is_prefix(curr, message)) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - } - if (calculated_name != "") { - // only send a response if that menu choice made sense to us. - send_reply(LINK_THIS, MENUTINI_HUFFWARE_ID + REPLY_DISTANCE, - [ global_menu_name, calculated_name, _private_global_av_key ], - SHOW_MENU_COMMAND); - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -////////////// - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//hmmm: extract this code to a menutini example! - -////////////// -// how to invoke a menu (assuming menutini is in same prim as calling script): -// -list buttons; // holds onto the set of menu options. -// -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } -// -example_invocation() -{ - string menu_name = "grumfazoid"; - string title = "These united colors of ben's futon have unfortunately run."; - buttons = [ "garp out", "sklonar", "fuzzlenog" ]; - integer menu_channel = random_channel(); - key listen_to = llGetOwner(); - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR - + (string)menu_channel + HUFFWARE_PARM_SEPARATOR - + (string)listen_to); -} -// -// how to handle the response message when the user chooses a button. -// -react_to_menu(string menu_name, string which_choice) -{ - // one might use the menu_name when dealing with multiple different menus. - - integer indy = 0; - // find the specified item and process it. - while (indy < llGetListLength(buttons)) { - // see if the current destination matches. - if (llSubStringIndex(llList2String(buttons, indy), which_choice) == 0) { - // this is the chosen item. -// process_menu_item(indy); // using numerical numbering. -// this function must be implemented in your own code; it is what handles the -// user picking a particular button on the menu. - return; - } - indy++; - } - llSay(0, "did not find menu option"); -} - -// an example for menu handling. this gets the response from menutini library -// and calls the menu processing method "react_to_menu". -example_handle_link_message(integer sender, integer num, string msg, key id) -{ - if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. - if (msg != SHOW_MENU_COMMAND) return; // also not for us. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string which_choice = llList2String(parms, 1); - react_to_menu(menu_name, which_choice); -} - -// then inside a state, you need an event handler like so: -// -// link_message(integer sender, integer num, string msg, key id) -// { example_handle_link_message(sender, num, msg, id); } - -// -// end invocation sample code... -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - link_message(integer sender, integer huff_id, string msg, key id) - { handle_link_message(sender, huff_id, msg, id); } - - listen(integer channel, string name, key id, string message) - { process_menu_response(channel, name, id, message); } - - // if the timer goes off, then the user has ignored the menu for longer than the - // timeout. we need to turn off our listen and ignore that menu. - timer() { clear_menu(); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.txt new file mode 100755 index 00000000..abd27116 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/menutini_library_v5.9.txt @@ -0,0 +1,436 @@ + +// huffware script: menutini library, by fred huffhines. +// +// this is a library script for menuing that provides a way to remote control the +// menu, somewhat. another script can zing link messages at this script and a menu +// will be shown based on the specified description and buttons. when the user +// selects an answer, that result is sent back in a link message reply. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// useful constants you might want to change: + +integer TIMEOUT_FOR_MENU = 42; + // timeout for the menu in seconds. +//hmmm: may want this to be selectable from menu request. +// or may even want to never time out! +// if we managed a list of ongoing menus, that would work. +// currently it cannot. + +integer DEBUGGING = FALSE; + // if this is true, then extra info will be printed when handling a menu. + +string NEXT_MENU_TEXT = "Next >>"; + // what the next item will say for showing next menu page. + +// menutini link message API... +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. + // the reply will include: the menu name, the choice made and the key for + // the avatar. +// +////////////// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +// +////////////// + +// global variables... + +list _private_global_buttons; // holds onto the active set of menu options. +string _private_global_av_key; // the key for the avatar who clicks the menu. +string _private_global_title; // holds onto current title text. + +integer _menu_base_start = 0; // position in the items of the current menu. + +integer listening_id = 0; + // the current id of our listening for the menu. it's an id returned by LSL + // that we need to track so we can cancel the listen. + +integer menu_system_channel = 0; + // messages come back to us from this channel when user clicks the dialog. + // this is set later and the default is meaningless. + +string global_menu_name = ""; + // hangs onto the current menu's name. + +//hmmm: note; to manage multiple concurrent menus on different channels, +// we must make these into lists. then the timeouts should apply +// individually to these instead of overall (if we even do timeouts; +// it's nicer if menus never stop being active). + + +// displays the menu requested. it's "menu_name" is an internal name that is +// not displayed to the user. the "title" is the content shown in the main area +// of the menu. "commands_in" is the list of menu items to show as buttons. +// the "menu_channel" is where the user's clicked response will be sent. the +// "listen_to" key is the avatar expected to click the menu, which is needed to +// listen to his response. +show_menu(string menu_name, string title, list buttons, + integer menu_channel, key listen_to) +{ + // save our new parms. + global_menu_name = menu_name; + _private_global_title = title; + _private_global_buttons = buttons; + menu_system_channel = menu_channel; + _private_global_av_key = listen_to; + if (DEBUGGING) { + log_it("menu name: " + global_menu_name); + log_it("title: " + _private_global_title); + log_it("buttons: " + (string)buttons); + log_it("channel: " + (string)menu_system_channel); + log_it("listen key: " + (string)listen_to); + } + + integer add_next = FALSE; // true if we should add a next menu item. + + // the math here incorporates current button position. + integer current = _menu_base_start; + integer max_buttons = llGetListLength(buttons) - current; + + if (max_buttons > 12) { + // limitation of SL: menus have a max of 12 buttons. + max_buttons = 12; + add_next = TRUE; + } else if (llGetListLength(buttons) > 12) { + // we already have been adding next. let's make sure this gets + // a wrap-around next button. + add_next = TRUE; + } + // chop out what we can use in a menu. + list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); + if (add_next) { + // we were asked to add a menu item for the next screen. + trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; + } + + listening_id = llListen(menu_channel, "", listen_to, ""); + list commands; + integer i; + // take only the prefix of the string, to avoid getting a length complaint. + for (i = 0; i < llGetListLength(trunc_buttons); i++) { + string curr = llList2String(trunc_buttons, i); + integer last_pos = 23; // default maximum, highest possible is 24. + if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; + curr = llGetSubString(curr, 0, last_pos); + commands += curr; + } + llDialog(listen_to, title, commands, menu_channel); + llSetTimerEvent(TIMEOUT_FOR_MENU); +} + +// shuts down any connection we might have had with any active menu. we will not +// send any responses after this point (although we might already have responded when +// the user clicked the menu). +clear_menu() +{ + llListenRemove(listening_id); + llSetTimerEvent(0.0); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +// ours do differ from normal in that we send back the channel as the number parameter +// instead of enforcing that being MENU_HUFFWARE_ID. +send_reply(integer destination, integer channel, list parms, string command) +{ + llMessageLinked(destination, channel, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// processes the menu requests. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + if (huff_id != MENUTINI_HUFFWARE_ID) return; // not for us. + + if (msg == SHOW_MENU_COMMAND) { + _menu_base_start = 0; // reset the position in the menus. + // separate the list out. +//log_it("id showing: " + id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + // toss any existing menu info. + clear_menu(); +//log_it("key here early: " + llList2String(parms, 4)); + show_menu(llList2String(parms, 0), llList2String(parms, 1), + llParseString2List(llList2String(parms, 2), + [HUFFWARE_ITEM_SEPARATOR], []), + (integer)llList2String(parms, 3), + (key)llList2String(parms, 4)); + } +} + +// process the response when the user chooses a menu item. this causes our +// caller to be told what was selected. +process_menu_response(integer channel, string name, key id, string message) +{ + if (channel != menu_system_channel) return; // not for us. + + if (message == NEXT_MENU_TEXT) { + // this is the special choice, so we need to go to the next page. + _menu_base_start += 11; + if (_menu_base_start > llGetListLength(_private_global_buttons)) { + // we have wrapped around the list. go to the start again. + _menu_base_start = 0; + } + show_menu(global_menu_name, _private_global_title, + _private_global_buttons, menu_system_channel, + _private_global_av_key); + return; // handled by opening a new menu. + } + + string calculated_name; + integer indy; + // first try for an exact match. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (curr == message) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + if (calculated_name == "") { + // try an imprecise match if the exact matching didn't work. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (is_prefix(curr, message)) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + } + if (calculated_name != "") { + // only send a response if that menu choice made sense to us. + send_reply(LINK_THIS, MENUTINI_HUFFWARE_ID + REPLY_DISTANCE, + [ global_menu_name, calculated_name, _private_global_av_key ], + SHOW_MENU_COMMAND); + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +////////////// + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//hmmm: extract this code to a menutini example! + +////////////// +// how to invoke a menu (assuming menutini is in same prim as calling script): +// +list buttons; // holds onto the set of menu options. +// +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } +// +example_invocation() +{ + string menu_name = "grumfazoid"; + string title = "These united colors of ben's futon have unfortunately run."; + buttons = [ "garp out", "sklonar", "fuzzlenog" ]; + integer menu_channel = random_channel(); + key listen_to = llGetOwner(); + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR + + (string)menu_channel + HUFFWARE_PARM_SEPARATOR + + (string)listen_to); +} +// +// how to handle the response message when the user chooses a button. +// +react_to_menu(string menu_name, string which_choice) +{ + // one might use the menu_name when dealing with multiple different menus. + + integer indy = 0; + // find the specified item and process it. + while (indy < llGetListLength(buttons)) { + // see if the current destination matches. + if (llSubStringIndex(llList2String(buttons, indy), which_choice) == 0) { + // this is the chosen item. +// process_menu_item(indy); // using numerical numbering. +// this function must be implemented in your own code; it is what handles the +// user picking a particular button on the menu. + return; + } + indy++; + } + llSay(0, "did not find menu option"); +} + +// an example for menu handling. this gets the response from menutini library +// and calls the menu processing method "react_to_menu". +example_handle_link_message(integer sender, integer num, string msg, key id) +{ + if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. + if (msg != SHOW_MENU_COMMAND) return; // also not for us. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string which_choice = llList2String(parms, 1); + react_to_menu(menu_name, which_choice); +} + +// then inside a state, you need an event handler like so: +// +// link_message(integer sender, integer num, string msg, key id) +// { example_handle_link_message(sender, num, msg, id); } + +// +// end invocation sample code... +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + link_message(integer sender, integer huff_id, string msg, key id) + { handle_link_message(sender, huff_id, msg, id); } + + listen(integer channel, string name, key id, string message) + { process_menu_response(channel, name, id, message); } + + // if the timer goes off, then the user has ignored the menu for longer than the + // timeout. we need to turn off our listen and ignore that menu. + timer() { clear_menu(); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.lsl deleted file mode 100755 index dd18ac3c..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.lsl +++ /dev/null @@ -1,395 +0,0 @@ - -// huffware script: minnow, modifications by fred huffhines. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// -// original attributions: -// Fixit Galatea generic boat script -// This script uses the basic direction keys for boat operation and requires -// the final prim to be oriented at rotation <0, 0, 0>. - -//**************************************************************************** -//**************************************************************************** -//**************************************************************************** -//* The following items can be edited in this script. See the comment for each -//* item to see how it work when it is changed. -//**************************************************************************** - -//* When the forward key is pressed and the mouse button is pressed at the -//* same time, this speed is used. This number should be between 0.0 and 30.0, -//* with higher numbers giving faster performance. -float fastspeed = 16.0; - -//* When the forward key is pressed and the mouse button is NOT pressed, this -//* speed is used. This number should be between 0.0 and whatever the -//* fastspeed value was set at, with higher numbers giving faster performance. -float slowspeed = 8.0; - -//* This is the reverse speed. It shouldn't be too fast, but can be between -//* 0.0 and 30.0. -float backspeed = 2.0; - -//* This is the vehicle 'hover' height, or how far it sits out of the water. -//* Adjust this as necessary for your boat. -float floatheight = 0.44; - -//* If the boat is to ramp up speed slowly, set the following value to '1'. -//* Otherwise, the board will instantly reach full speed when the forward -//* key is pressed. -integer fastforward = 0; // NOT IMPLEMENTED YET - -//* Turning speed, a small turning speed is best -float turnspeed = 1.5; - -//* If the boat 'angles' into turns, set the following value to '1'. -//* Otherwise, the boat will do flat turns. -integer angledturn = 1; // NOT IMPLEMENTED YET - -//* Height offset of seat -//vector seatheight = <.2, 0, 0.35>; - -vector camera_lives_at = <-7, 0, 3>; - // where the camera is poised when the avatar is seated. - -vector camera_looks_at = <4, 0, 1>; - -//**************************************************************************** -//**************************************************************************** -//**************************************************************************** - -// Initialize the vehicle as a boat -vehicle_init() -{ - llSetVehicleType(VEHICLE_TYPE_BOAT); - - // least for forward-back, most friction for up-down - llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10, 1, 3>); - - // uniform angular friction (setting it as a scalar rather than a vector) - llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 0.1); - - // linear motor wins after about five seconds, decays after about a minute - llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0>); - llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.1); - llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.05); - - // agular motor wins after four seconds, decays in same amount of time - llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0>); - llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1); - llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.2); - - // hover - llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, floatheight); - llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.2); - llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 0.4); - llSetVehicleFloatParam(VEHICLE_BUOYANCY, 1.0); - - // Slight linear deflection with timescale of 1 seconds - llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.1); - llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 1); - - // Slight angular deflection - llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.1); - llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 6); - - // somewhat bounscy vertical attractor - llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.5); - llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1); - - // weak negative damped banking - llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 1.0); - llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 1.0); - llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); - - // default rotation of local frame - llSetVehicleRotationParam(VEHICLE_REFERENCE_FRAME, - llEuler2Rot(<0, 0, 0>)); - - // remove these flags. -//disabled due to opensim problems running this call. -// llRemoveVehicleFlags(VEHICLE_FLAG_HOVER_TERRAIN_ONLY -// | VEHICLE_FLAG_LIMIT_ROLL_ONLY -// | VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT); - - // set these flags -// llSetVehicleFlags(VEHICLE_FLAG_NO_DEFLECTION_UP -// | VEHICLE_FLAG_HOVER_WATER_ONLY -// | VEHICLE_FLAG_HOVER_UP_ONLY -// | VEHICLE_FLAG_LIMIT_MOTOR_UP); -} - -// Setup everything -all_setup() -{ - // Display version number - llWhisper(0, "running script " + llGetScriptName()); - llSetStatus(STATUS_PHYSICS, FALSE); - - // Set sit direction (forward) and sight location slightly up and behind -// llSitTarget(seatheight, llEuler2Rot(<0, 0, 0>)); - llSetCameraAtOffset(camera_looks_at); - llSetCameraEyeOffset(camera_lives_at); - llSetSitText("Pilot"); - - // Initialize vehicle states - vehicle_init(); - - // Set up listener callback function - llListen(0, "", llGetOwner(), ""); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// State (default) event handlers -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - all_setup(); - } - - on_rez(integer start_param) - { - llSetStatus(STATUS_PHYSICS, FALSE); - } - - run_time_permissions(integer permissions) - { - // Get user permissions - if ((permissions & PERMISSION_TAKE_CONTROLS) == - PERMISSION_TAKE_CONTROLS) - { - llTakeControls(CONTROL_ML_LBUTTON | CONTROL_FWD | - CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | - CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT, TRUE, FALSE); - } - } - - changed(integer change) - { - if (change & CHANGED_LINK) - { - key agent = llAvatarOnSitTarget(); - if (agent) - { - if (agent != llGetOwner()) - { - llSay(0, "This boat isn't yours, but you can buy a copy!"); - llUnSit(agent); - } - else - { - llRequestPermissions(agent, PERMISSION_TAKE_CONTROLS); - llSetStatus(STATUS_PHYSICS, TRUE); - } - } - else - { - llReleaseControls(); - llSetStatus(STATUS_PHYSICS, FALSE); - } - } - } - - control(key name, integer levels, integer edges) - { - float side = 0.0; - float forw = 0.0; - float move = 0.0; - float turn; - - if (levels & CONTROL_ML_LBUTTON) - { - move = fastspeed; - turn = 1.5 * turnspeed; -// forw = 2 * PI / 3; - } - else if (levels & CONTROL_FWD) - { - move = slowspeed; - turn = 1.0 * turnspeed; -// forw = PI / 2; - } - else if (levels & CONTROL_BACK) - { - move = -backspeed; -// forw = -PI / 3; -// turn = -1.0 * turnspeed; - } - - if (levels & (CONTROL_LEFT | CONTROL_ROT_LEFT)) - { - if (move == fastspeed) - { - side = turnspeed; -// forw = PI; - } - else if (move != 0) - { - side = turnspeed; -// forw = PI / 3; - } - else - { - side = .67 * turnspeed; -// forw = PI / 4; - move = 0.1; - } - } - else if (levels & (CONTROL_RIGHT | CONTROL_ROT_RIGHT)) - { - if (move == fastspeed) - { - side = -turnspeed; -// forw = PI; - } - else if (move != 0) - { - side = -turnspeed; -// forw = PI / 3; - } - else - { - side = -.67 * turnspeed; -// forw = PI / 4; - move = 0.1; - } - } - - if (move == 0) - { - llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0>); - } - else - { - llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, - ); - llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, - <-side / 5, 0, side>); - } - } - - listen(integer channel, string name, key id, string message) - { - list params = llParseString2List(message, [" "], [":"]); - string cmd = llList2String(params, 0); - integer enable = llList2Integer(params, 1); - - // Commands - ; - } - - touch_start(integer total_number) - { - key id = llDetectedOwner(total_number - 1); - // llGiveInventory(id, "Info card"); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.txt new file mode 100755 index 00000000..dd18ac3c --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/minnow_v10.6.txt @@ -0,0 +1,395 @@ + +// huffware script: minnow, modifications by fred huffhines. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// +// original attributions: +// Fixit Galatea generic boat script +// This script uses the basic direction keys for boat operation and requires +// the final prim to be oriented at rotation <0, 0, 0>. + +//**************************************************************************** +//**************************************************************************** +//**************************************************************************** +//* The following items can be edited in this script. See the comment for each +//* item to see how it work when it is changed. +//**************************************************************************** + +//* When the forward key is pressed and the mouse button is pressed at the +//* same time, this speed is used. This number should be between 0.0 and 30.0, +//* with higher numbers giving faster performance. +float fastspeed = 16.0; + +//* When the forward key is pressed and the mouse button is NOT pressed, this +//* speed is used. This number should be between 0.0 and whatever the +//* fastspeed value was set at, with higher numbers giving faster performance. +float slowspeed = 8.0; + +//* This is the reverse speed. It shouldn't be too fast, but can be between +//* 0.0 and 30.0. +float backspeed = 2.0; + +//* This is the vehicle 'hover' height, or how far it sits out of the water. +//* Adjust this as necessary for your boat. +float floatheight = 0.44; + +//* If the boat is to ramp up speed slowly, set the following value to '1'. +//* Otherwise, the board will instantly reach full speed when the forward +//* key is pressed. +integer fastforward = 0; // NOT IMPLEMENTED YET + +//* Turning speed, a small turning speed is best +float turnspeed = 1.5; + +//* If the boat 'angles' into turns, set the following value to '1'. +//* Otherwise, the boat will do flat turns. +integer angledturn = 1; // NOT IMPLEMENTED YET + +//* Height offset of seat +//vector seatheight = <.2, 0, 0.35>; + +vector camera_lives_at = <-7, 0, 3>; + // where the camera is poised when the avatar is seated. + +vector camera_looks_at = <4, 0, 1>; + +//**************************************************************************** +//**************************************************************************** +//**************************************************************************** + +// Initialize the vehicle as a boat +vehicle_init() +{ + llSetVehicleType(VEHICLE_TYPE_BOAT); + + // least for forward-back, most friction for up-down + llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <10, 1, 3>); + + // uniform angular friction (setting it as a scalar rather than a vector) + llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 0.1); + + // linear motor wins after about five seconds, decays after about a minute + llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0>); + llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.1); + llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.05); + + // agular motor wins after four seconds, decays in same amount of time + llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0>); + llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1); + llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.2); + + // hover + llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, floatheight); + llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.2); + llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 0.4); + llSetVehicleFloatParam(VEHICLE_BUOYANCY, 1.0); + + // Slight linear deflection with timescale of 1 seconds + llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.1); + llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 1); + + // Slight angular deflection + llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.1); + llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 6); + + // somewhat bounscy vertical attractor + llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.5); + llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1); + + // weak negative damped banking + llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 1.0); + llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 1.0); + llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); + + // default rotation of local frame + llSetVehicleRotationParam(VEHICLE_REFERENCE_FRAME, + llEuler2Rot(<0, 0, 0>)); + + // remove these flags. +//disabled due to opensim problems running this call. +// llRemoveVehicleFlags(VEHICLE_FLAG_HOVER_TERRAIN_ONLY +// | VEHICLE_FLAG_LIMIT_ROLL_ONLY +// | VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT); + + // set these flags +// llSetVehicleFlags(VEHICLE_FLAG_NO_DEFLECTION_UP +// | VEHICLE_FLAG_HOVER_WATER_ONLY +// | VEHICLE_FLAG_HOVER_UP_ONLY +// | VEHICLE_FLAG_LIMIT_MOTOR_UP); +} + +// Setup everything +all_setup() +{ + // Display version number + llWhisper(0, "running script " + llGetScriptName()); + llSetStatus(STATUS_PHYSICS, FALSE); + + // Set sit direction (forward) and sight location slightly up and behind +// llSitTarget(seatheight, llEuler2Rot(<0, 0, 0>)); + llSetCameraAtOffset(camera_looks_at); + llSetCameraEyeOffset(camera_lives_at); + llSetSitText("Pilot"); + + // Initialize vehicle states + vehicle_init(); + + // Set up listener callback function + llListen(0, "", llGetOwner(), ""); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// State (default) event handlers +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + all_setup(); + } + + on_rez(integer start_param) + { + llSetStatus(STATUS_PHYSICS, FALSE); + } + + run_time_permissions(integer permissions) + { + // Get user permissions + if ((permissions & PERMISSION_TAKE_CONTROLS) == + PERMISSION_TAKE_CONTROLS) + { + llTakeControls(CONTROL_ML_LBUTTON | CONTROL_FWD | + CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | + CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT, TRUE, FALSE); + } + } + + changed(integer change) + { + if (change & CHANGED_LINK) + { + key agent = llAvatarOnSitTarget(); + if (agent) + { + if (agent != llGetOwner()) + { + llSay(0, "This boat isn't yours, but you can buy a copy!"); + llUnSit(agent); + } + else + { + llRequestPermissions(agent, PERMISSION_TAKE_CONTROLS); + llSetStatus(STATUS_PHYSICS, TRUE); + } + } + else + { + llReleaseControls(); + llSetStatus(STATUS_PHYSICS, FALSE); + } + } + } + + control(key name, integer levels, integer edges) + { + float side = 0.0; + float forw = 0.0; + float move = 0.0; + float turn; + + if (levels & CONTROL_ML_LBUTTON) + { + move = fastspeed; + turn = 1.5 * turnspeed; +// forw = 2 * PI / 3; + } + else if (levels & CONTROL_FWD) + { + move = slowspeed; + turn = 1.0 * turnspeed; +// forw = PI / 2; + } + else if (levels & CONTROL_BACK) + { + move = -backspeed; +// forw = -PI / 3; +// turn = -1.0 * turnspeed; + } + + if (levels & (CONTROL_LEFT | CONTROL_ROT_LEFT)) + { + if (move == fastspeed) + { + side = turnspeed; +// forw = PI; + } + else if (move != 0) + { + side = turnspeed; +// forw = PI / 3; + } + else + { + side = .67 * turnspeed; +// forw = PI / 4; + move = 0.1; + } + } + else if (levels & (CONTROL_RIGHT | CONTROL_ROT_RIGHT)) + { + if (move == fastspeed) + { + side = -turnspeed; +// forw = PI; + } + else if (move != 0) + { + side = -turnspeed; +// forw = PI / 3; + } + else + { + side = -.67 * turnspeed; +// forw = PI / 4; + move = 0.1; + } + } + + if (move == 0) + { + llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0>); + } + else + { + llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, + ); + llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, + <-side / 5, 0, side>); + } + } + + listen(integer channel, string name, key id, string message) + { + list params = llParseString2List(message, [" "], [":"]); + string cmd = llList2String(params, 0); + integer enable = llList2Integer(params, 1); + + // Commands + ; + } + + touch_start(integer total_number) + { + key id = llDetectedOwner(total_number - 1); + // llGiveInventory(id, "Info card"); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.lsl deleted file mode 100755 index 07e7c93e..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.lsl +++ /dev/null @@ -1,412 +0,0 @@ - -// huffware script: non-script giver, by fred huffhines. -// -// gives all objects, notecards, etc contained in an object when that object is touched. -// does not give out scripts, since these are generally not something that should be handed -// to the customer. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer ONLY_GIVE_TO_OWNER = TRUE; - // if this is true, then only the owner will receive a copy of the items. - -integer GIVE_UNCOPYABLES = FALSE; - // this flag is dangerous when true, because it means that uncopyable objects will still - // be handed to the target. if that target refuses the non-copyable items, then the items - // will be lost forever. that is not so good if you've sold the person a non-copy item. - -string EXCLUDED_NOTECARD = "product description"; - // a special case; if there is a giftorse configuration card, we won't hand that out. - -integer DEBUGGING = FALSE; // set to true for noisier runs. - -key first_toucher; // tracks who clicked on the object to get contents. - -// give out pictures, notecards, objects, etc. that are hiding in the object. -really_give_out_contents(key give_to) -{ - list all_to_give = []; // the set we will hand over in a batch. - list uncopyables = []; // the list we have to do individually. - // find out how many items there are. - integer count = llGetInventoryNumber(INVENTORY_ALL); - // iterate across all the items and add them to the gift list if appropriate. - integer indy; - for (indy = 0; indy < count; indy++) { - string item_name = llGetInventoryName(INVENTORY_ALL, indy); - integer type = llGetInventoryType(item_name); - if ( (type != INVENTORY_SCRIPT) - && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { - // it's okay to add this item; it's not a script and we are not skipping the special notecard. - integer mask = MASK_OWNER; - if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; - integer perms = llGetInventoryPermMask(item_name, mask); - if (perms & PERM_COPY) { - // a normal object that we can hand out. - all_to_give += item_name; - } else { - uncopyables += item_name; - } - } - } - // hand the customer the whole set as one big chunk, named after the object. - llGiveInventoryList(give_to, llGetObjectName(), all_to_give); - - // handle any problematic items. we cannot copy these objects into a category folder, - // so we can either not try to copy them (a lot safer) or we can try to deliver them - // normally as individual items. the latter choice is more dangerous, because if the - // owner discards these items rather than keeping them, the items will be lost forever! - if (llGetListLength(uncopyables) > 0) { - string plural = " "; - string is_verb = "is "; - string third_noun_subj = "it "; - string third_noun_obj = "it "; - if (llGetListLength(uncopyables) > 1) { - plural = "s "; - is_verb = "are "; - third_noun_subj = "they "; - third_noun_obj = "them "; - } - - string uncopyable_message = "will be left inside the object. To get " + third_noun_obj - + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; - if (GIVE_UNCOPYABLES) { - uncopyable_message = "will be moved over to your inventory." - + "\nPlease look in your main folders for " - + third_noun_obj + "(e.g., in Objects or Textures)."; - } - - string failure_message = "The item" + plural - + "[" + llDumpList2String(uncopyables, "; ") + "]\n" - + is_verb + "not copyable; " + third_noun_subj - + uncopyable_message; - - if (llGetOwner() == give_to) { - // the object can be moved to inventory, but not with the category method. - llOwnerSay(failure_message); - } else { - // this seems like a weird case; it will probably just fail anyhow? - // if the item's not copyable and you're not the owner of this object, - // how can we give it to you? - llInstantMessage(give_to, failure_message); - } - - // now that we've announced this weird situation, handle it appropriately. - if (GIVE_UNCOPYABLES) { - for (indy = 0; indy < llGetListLength(uncopyables); indy++) { - string item_name = llList2String(uncopyables, indy); - llGiveInventory(give_to, item_name); - } - } // otherwise leave them be. - } -} - - -////////////// -// code borrowed from menutini to raise a menu asking if they actually meant to get all -// the contents. an opensim inventory bug makes all the folders look foolish if we -// do any inventory giving accidentally. -////////////// - -// global variables... - -list _private_global_buttons; // holds onto the active set of menu options. -string _private_global_av_key; // the key for the avatar who clicks the menu. -string _private_global_title; // holds onto current title text. - -integer _menu_base_start = 0; // position in the items of the current menu. - -integer listening_id = 0; - // the current id of our listening for the menu. it's an id returned by LSL - // that we need to track so we can cancel the listen. - -integer menu_system_channel = -123; - // messages come back to us from this channel when user clicks the dialog. - // this is set later and the default is meaningless. - -string global_menu_name = ""; - // hangs onto the current menu's name. - -//hmmm: note; to manage multiple concurrent menus on different channels, -// we must make these into lists. then the timeouts should apply -// individually to these instead of overall (if we even do timeouts; -// it's nicer if menus never stop being active). - -string NEXT_MENU_TEXT = "Next >>"; - // what the next item will say for showing next menu page. - -//integer TIMEOUT_FOR_MENU = 42; - // timeout for the menu in seconds. - -// displays the menu requested. it's "menu_name" is an internal name that is -// not displayed to the user. the "title" is the content shown in the main area -// of the menu. "commands_in" is the list of menu items to show as buttons. -// the "menu_channel" is where the user's clicked response will be sent. the -// "listen_to" key is the avatar expected to click the menu, which is needed to -// listen to his response. -show_menu(string menu_name, string title, list buttons, - integer menu_channel, key listen_to) -{ - // save our new parms. - global_menu_name = menu_name; - _private_global_title = title; - _private_global_buttons = buttons; - menu_system_channel = menu_channel; - _private_global_av_key = listen_to; - if (DEBUGGING) { - log_it("menu name: " + global_menu_name); - log_it("title: " + _private_global_title); - log_it("buttons: " + (string)buttons); - log_it("channel: " + (string)menu_system_channel); - log_it("listen key: " + (string)listen_to); - } - - integer add_next = FALSE; // true if we should add a next menu item. - - // the math here incorporates current button position. - integer current = _menu_base_start; - integer max_buttons = llGetListLength(buttons) - current; - - if (max_buttons > 12) { - // limitation of SL: menus have a max of 12 buttons. - max_buttons = 12; - add_next = TRUE; - } else if (llGetListLength(buttons) > 12) { - // we already have been adding next. let's make sure this gets - // a wrap-around next button. - add_next = TRUE; - } - // chop out what we can use in a menu. - list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); - if (add_next) { - // we were asked to add a menu item for the next screen. - trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; - } - - listening_id = llListen(menu_channel, "", listen_to, ""); - list commands; - integer i; - // take only the prefix of the string, to avoid getting a length complaint. - for (i = 0; i < llGetListLength(trunc_buttons); i++) { - string curr = llList2String(trunc_buttons, i); - integer last_pos = 23; // default maximum, highest possible is 24. - if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; - curr = llGetSubString(curr, 0, last_pos); - commands += curr; - } - llDialog(listen_to, title, commands, menu_channel); -} - -// shuts down any connection we might have had with any active menu. we will not -// send any responses after this point (although we might already have responded when -// the user clicked the menu). -clear_menu() -{ - llListenRemove(listening_id); -} - -// process the response when the user chooses a menu item. -process_menu_response(integer channel, string name, key id, string message) -{ - if (channel != menu_system_channel) return; // not for us. - - if (message == NEXT_MENU_TEXT) { - // this is the special choice, so we need to go to the next page. - _menu_base_start += 11; - if (_menu_base_start > llGetListLength(_private_global_buttons)) { - // we have wrapped around the list. go to the start again. - _menu_base_start = 0; - } - show_menu(global_menu_name, _private_global_title, - _private_global_buttons, menu_system_channel, - _private_global_av_key); - return; // handled by opening a new menu. - } - - string calculated_name; - integer indy; - // first try for an exact match. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (curr == message) { - // correct the answer based on the full button string. - calculated_name = curr; - }//////////////[copy starting here...]////////////// - - } - if (calculated_name == "") { - // try an imprecise match if the exact matching didn't work. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (is_prefix(curr, message)) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - } - if (calculated_name == "yes") { - // only send a response if that menu choice made sense to us. - really_give_out_contents(first_toucher); - clear_menu(); - } -} - -// end from menutini. -////////////// - - -////////////// -// -// borrowed from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - } - - on_rez(integer param) { llResetScript(); } - - touch_start(integer num) { - first_toucher = llDetectedKey(0); - // are we only supposed to give stuff to the owner? - if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { - first_toucher = NULL_KEY; - return; // bail out. - } - show_menu("askreally", "Would you like a copy of this object's contents?", - ["yes", "no"], -18264, first_toucher); - } - - listen(integer channel, string name, key id, string message) - { process_menu_response(channel, name, id, message); } - -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.txt new file mode 100755 index 00000000..07e7c93e --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/non-script_giver_v2.8.txt @@ -0,0 +1,412 @@ + +// huffware script: non-script giver, by fred huffhines. +// +// gives all objects, notecards, etc contained in an object when that object is touched. +// does not give out scripts, since these are generally not something that should be handed +// to the customer. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer ONLY_GIVE_TO_OWNER = TRUE; + // if this is true, then only the owner will receive a copy of the items. + +integer GIVE_UNCOPYABLES = FALSE; + // this flag is dangerous when true, because it means that uncopyable objects will still + // be handed to the target. if that target refuses the non-copyable items, then the items + // will be lost forever. that is not so good if you've sold the person a non-copy item. + +string EXCLUDED_NOTECARD = "product description"; + // a special case; if there is a giftorse configuration card, we won't hand that out. + +integer DEBUGGING = FALSE; // set to true for noisier runs. + +key first_toucher; // tracks who clicked on the object to get contents. + +// give out pictures, notecards, objects, etc. that are hiding in the object. +really_give_out_contents(key give_to) +{ + list all_to_give = []; // the set we will hand over in a batch. + list uncopyables = []; // the list we have to do individually. + // find out how many items there are. + integer count = llGetInventoryNumber(INVENTORY_ALL); + // iterate across all the items and add them to the gift list if appropriate. + integer indy; + for (indy = 0; indy < count; indy++) { + string item_name = llGetInventoryName(INVENTORY_ALL, indy); + integer type = llGetInventoryType(item_name); + if ( (type != INVENTORY_SCRIPT) + && ( (type != INVENTORY_NOTECARD) || (item_name != EXCLUDED_NOTECARD) ) ) { + // it's okay to add this item; it's not a script and we are not skipping the special notecard. + integer mask = MASK_OWNER; + if (!ONLY_GIVE_TO_OWNER) mask = MASK_EVERYONE; + integer perms = llGetInventoryPermMask(item_name, mask); + if (perms & PERM_COPY) { + // a normal object that we can hand out. + all_to_give += item_name; + } else { + uncopyables += item_name; + } + } + } + // hand the customer the whole set as one big chunk, named after the object. + llGiveInventoryList(give_to, llGetObjectName(), all_to_give); + + // handle any problematic items. we cannot copy these objects into a category folder, + // so we can either not try to copy them (a lot safer) or we can try to deliver them + // normally as individual items. the latter choice is more dangerous, because if the + // owner discards these items rather than keeping them, the items will be lost forever! + if (llGetListLength(uncopyables) > 0) { + string plural = " "; + string is_verb = "is "; + string third_noun_subj = "it "; + string third_noun_obj = "it "; + if (llGetListLength(uncopyables) > 1) { + plural = "s "; + is_verb = "are "; + third_noun_subj = "they "; + third_noun_obj = "them "; + } + + string uncopyable_message = "will be left inside the object. To get " + third_noun_obj + + ", please copy " + third_noun_obj + "\nmanually from this object into your inventory."; + if (GIVE_UNCOPYABLES) { + uncopyable_message = "will be moved over to your inventory." + + "\nPlease look in your main folders for " + + third_noun_obj + "(e.g., in Objects or Textures)."; + } + + string failure_message = "The item" + plural + + "[" + llDumpList2String(uncopyables, "; ") + "]\n" + + is_verb + "not copyable; " + third_noun_subj + + uncopyable_message; + + if (llGetOwner() == give_to) { + // the object can be moved to inventory, but not with the category method. + llOwnerSay(failure_message); + } else { + // this seems like a weird case; it will probably just fail anyhow? + // if the item's not copyable and you're not the owner of this object, + // how can we give it to you? + llInstantMessage(give_to, failure_message); + } + + // now that we've announced this weird situation, handle it appropriately. + if (GIVE_UNCOPYABLES) { + for (indy = 0; indy < llGetListLength(uncopyables); indy++) { + string item_name = llList2String(uncopyables, indy); + llGiveInventory(give_to, item_name); + } + } // otherwise leave them be. + } +} + + +////////////// +// code borrowed from menutini to raise a menu asking if they actually meant to get all +// the contents. an opensim inventory bug makes all the folders look foolish if we +// do any inventory giving accidentally. +////////////// + +// global variables... + +list _private_global_buttons; // holds onto the active set of menu options. +string _private_global_av_key; // the key for the avatar who clicks the menu. +string _private_global_title; // holds onto current title text. + +integer _menu_base_start = 0; // position in the items of the current menu. + +integer listening_id = 0; + // the current id of our listening for the menu. it's an id returned by LSL + // that we need to track so we can cancel the listen. + +integer menu_system_channel = -123; + // messages come back to us from this channel when user clicks the dialog. + // this is set later and the default is meaningless. + +string global_menu_name = ""; + // hangs onto the current menu's name. + +//hmmm: note; to manage multiple concurrent menus on different channels, +// we must make these into lists. then the timeouts should apply +// individually to these instead of overall (if we even do timeouts; +// it's nicer if menus never stop being active). + +string NEXT_MENU_TEXT = "Next >>"; + // what the next item will say for showing next menu page. + +//integer TIMEOUT_FOR_MENU = 42; + // timeout for the menu in seconds. + +// displays the menu requested. it's "menu_name" is an internal name that is +// not displayed to the user. the "title" is the content shown in the main area +// of the menu. "commands_in" is the list of menu items to show as buttons. +// the "menu_channel" is where the user's clicked response will be sent. the +// "listen_to" key is the avatar expected to click the menu, which is needed to +// listen to his response. +show_menu(string menu_name, string title, list buttons, + integer menu_channel, key listen_to) +{ + // save our new parms. + global_menu_name = menu_name; + _private_global_title = title; + _private_global_buttons = buttons; + menu_system_channel = menu_channel; + _private_global_av_key = listen_to; + if (DEBUGGING) { + log_it("menu name: " + global_menu_name); + log_it("title: " + _private_global_title); + log_it("buttons: " + (string)buttons); + log_it("channel: " + (string)menu_system_channel); + log_it("listen key: " + (string)listen_to); + } + + integer add_next = FALSE; // true if we should add a next menu item. + + // the math here incorporates current button position. + integer current = _menu_base_start; + integer max_buttons = llGetListLength(buttons) - current; + + if (max_buttons > 12) { + // limitation of SL: menus have a max of 12 buttons. + max_buttons = 12; + add_next = TRUE; + } else if (llGetListLength(buttons) > 12) { + // we already have been adding next. let's make sure this gets + // a wrap-around next button. + add_next = TRUE; + } + // chop out what we can use in a menu. + list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); + if (add_next) { + // we were asked to add a menu item for the next screen. + trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; + } + + listening_id = llListen(menu_channel, "", listen_to, ""); + list commands; + integer i; + // take only the prefix of the string, to avoid getting a length complaint. + for (i = 0; i < llGetListLength(trunc_buttons); i++) { + string curr = llList2String(trunc_buttons, i); + integer last_pos = 23; // default maximum, highest possible is 24. + if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; + curr = llGetSubString(curr, 0, last_pos); + commands += curr; + } + llDialog(listen_to, title, commands, menu_channel); +} + +// shuts down any connection we might have had with any active menu. we will not +// send any responses after this point (although we might already have responded when +// the user clicked the menu). +clear_menu() +{ + llListenRemove(listening_id); +} + +// process the response when the user chooses a menu item. +process_menu_response(integer channel, string name, key id, string message) +{ + if (channel != menu_system_channel) return; // not for us. + + if (message == NEXT_MENU_TEXT) { + // this is the special choice, so we need to go to the next page. + _menu_base_start += 11; + if (_menu_base_start > llGetListLength(_private_global_buttons)) { + // we have wrapped around the list. go to the start again. + _menu_base_start = 0; + } + show_menu(global_menu_name, _private_global_title, + _private_global_buttons, menu_system_channel, + _private_global_av_key); + return; // handled by opening a new menu. + } + + string calculated_name; + integer indy; + // first try for an exact match. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (curr == message) { + // correct the answer based on the full button string. + calculated_name = curr; + }//////////////[copy starting here...]////////////// + + } + if (calculated_name == "") { + // try an imprecise match if the exact matching didn't work. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (is_prefix(curr, message)) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + } + if (calculated_name == "yes") { + // only send a response if that menu choice made sense to us. + really_give_out_contents(first_toucher); + clear_menu(); + } +} + +// end from menutini. +////////////// + + +////////////// +// +// borrowed from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + } + + on_rez(integer param) { llResetScript(); } + + touch_start(integer num) { + first_toucher = llDetectedKey(0); + // are we only supposed to give stuff to the owner? + if (ONLY_GIVE_TO_OWNER && (first_toucher != llGetOwner()) ) { + first_toucher = NULL_KEY; + return; // bail out. + } + show_menu("askreally", "Would you like a copy of this object's contents?", + ["yes", "no"], -18264, first_toucher); + } + + listen(integer channel, string name, key id, string message) + { process_menu_response(channel, name, id, message); } + +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.lsl deleted file mode 100755 index 4d56bac0..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.lsl +++ /dev/null @@ -1,541 +0,0 @@ - -// huffware script: noteworthy library, by fred huffhines. -// -// a handy approach to reading a notecard. this version supports requiring -// a 'signature' in the notecard's first line, so that multiple notecards can -// exist in an object without being misinterpreted. the script is accessed via -// its link message API, so it can be used in an object without all this code -// needing to be embedded in another script. it also supports queuing up requests -// to read notecards, so multiple scripts can use it to read their specific -// notecards without any special handling (besides waiting a bit longer). -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants that can be adapted to your needs... - -integer DEBUGGING = FALSE; - // if this is true, then a lot of extra noise is generated when notecards are read. - -float TIME_OUT_ON_ONE_NOTECARD = 42.0; - // we allow one line of a notecard this long to be read before we decide it's hosed. - // some sims are very very slow, and a time-out of one minute has been found lacking; - // we saw at least one case where the first notecard line to be read took longer than - // 60 seconds. that's why we kept cranking this time-out up... - -// constants that should not be changed... - -// outcomes from handling a line in a notecard. -integer STILL_READING = -8; // the notecard seems good, but isn't finished. -integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. -integer DONE_READING = -10; // the notecard is finished being read. - -integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. - -integer MAXIMUM_LINES_USED = 4; - // we will read this many lines at a time from the appropriate notecard. - -// this is the noteworthy library's API that is available via link messages. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. - -//STRIKE THIS from everywhere. -//string BUSY_READING_INDICATOR = "busy_already"; -// // this return value indicates that the script is already in use by some other script. -// // the calling script should try again later. - -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// global variables... - -string requested_signature = ""; - // if this is non-empty, then it must be found in the first line of the script. - -integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. - -string global_notecard_name; // the name of the card we're reading now. -key global_query_id = NULL_KEY; // the identifier of our data query. -integer current_response_code = 0; // the code that our client uses for its reading. -list global_query_contents; // the lines we have read from the notecard. - -integer line_number = 0; // which line are we at in notecard? - -integer found_signature_line = FALSE; // did we find our first line in a notecard yet? - -integer trying_notecard_at = -1; // where we are currently looking for a good notecard. - -list pending_signatures; // signatures from queued requests for reading. -list pending_response_codes; // response codes for the queued requests. -list pending_notecard_names; // card names if it's a specific request. - -////////////// - -startup_initialize() -{ - pending_signatures = []; - pending_response_codes = []; - pending_notecard_names = []; - current_response_code = 0; - llSetTimerEvent(0.0); -} - -reset_for_reading(string signature, integer response_code) -{ - requested_signature = signature; - current_response_code = response_code; - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. - global_query_contents = []; - global_notecard_name = ""; - line_number = 0; - found_signature_line = FALSE; - trying_notecard_at = -1; - global_query_id = NULL_KEY; -} - -// use the existing global notecard setting to start reading. -select_specific_notecard() -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - line_number = 0; // reset line number again. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// picks the notecard at the "index" (from 0 to num_notecards - 1) and -// starts reading it. -select_notecard(integer index) -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); - if (card_specified == "") return; // not good. bad index. - global_notecard_name = card_specified; - line_number = 0; // reset line number again. - // we have a new file name, so load up the destinations, hopefully. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// increments our index in the count of notecards that the object has, and start -// reading the next notecard (at the index). -integer try_next_notecard() -{ - if (only_read_one_notecard) { - return FALSE; // we were only going to try one. - } - // reset some values that might have applied before. - global_notecard_name = ""; - // skip to the next card. - trying_notecard_at++; - // make sure we're not over the count of cards. - if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { - // this is a problem. we didn't find anything suitable. - return FALSE; - } - // so, now we'll try the next notecard to look for our signature. - select_notecard(trying_notecard_at); - return TRUE; -} - -// process a line of text that we received from the current notecard. -integer handle_notecard_line(key query_id, string data) -{ - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - // there's more to read in the notecard still. - if (data != "") { - // make sure we even have a signature to look for. - if (!found_signature_line && (requested_signature == "")) { - // no signature means that we always find it. - found_signature_line = TRUE; - } - // did we already get our signature? if not, see if this is it. - if (!found_signature_line && (data != requested_signature) ) { - // this is a bad notecard. skip it. - if (!try_next_notecard()) { - // we have no more to work with. - return BAD_NOTECARD; - } - return STILL_READING; // we'll keep going. - } else if (!found_signature_line && (data == requested_signature) ) { - // this is a good signature line, so record that and then skip it. - found_signature_line = TRUE; - } else { - if (DEBUGGING - && ( ( (requested_signature == "") && (line_number == 0) ) - || ( (requested_signature != "") && (line_number == 1) ) ) ) { - log_it("started reading " + global_notecard_name + "..."); - } - // don't record any lines that are comments. - if ( (llGetSubString(data, 0, 0) != "#") - && (llGetSubString(data, 0, 0) != ";") ) { - // add the non-blank line to our list. - global_query_contents += data; - // make sure we still have enough space to keep going. - if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { - // ooh, make sure we pause before blowing our heap&stack. - send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, - current_response_code ], READ_NOTECARD_COMMAND, TRUE); - } - } - } - } - line_number++; // increase the line count. - // reset the timer rather than timing out, if we actually got some data. - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); - // request the next line from the notecard. - global_query_id = llGetNotecardLine(global_notecard_name, line_number); - if (global_query_id == NULL_KEY) { -//log_it("failed to restart notecard reading."); - return DONE_READING; -//is that the best outcome? - } - return STILL_READING; - } else { - // that's the end of the notecard. we need some minimal verification that it - // wasn't full of garbage. - if (!found_signature_line) { - if (DEBUGGING) log_it("never found signature in " + global_notecard_name); - if (!try_next_notecard()) { - return BAD_NOTECARD; // we failed to find a good line? - } else { - // the next notecard's coming through now. - return STILL_READING; - } - } else { -// if (DEBUGGING) log_it("found signature."); - // saw the signature line, so this is a good one. - return DONE_READING; - } - } -} - -// only sends reply; does not reset notecard process. -send_reply(integer destination, list parms, string command, - integer include_query) -{ -//integer items = llGetListLength(parms); -//if (include_query) items += llGetListLength(global_query_contents); -//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); - - if (!include_query) { - llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - } else { - llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, - llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); - } - global_query_contents = []; -//log_it("post-sending, mem=" + (string)llGetFreeMemory()); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply_and_reset(integer destination, list parms, string command, - integer include_query) -{ - llSetTimerEvent(0.0); // stop the timer, since we're about to reply. - send_reply(destination, parms, command, include_query); - current_response_code = 0; // reset back to default so we can start another read. - global_query_id = NULL_KEY; // reset so we accept no more data. -} - -// if there are other pending notecard reads, this goes to the next one listed. -dequeue_next_request() -{ - if (llGetListLength(pending_signatures)) { - // get the info from the next pending item. - string sig = llList2String(pending_signatures, 0); - integer response_code = llList2Integer(pending_response_codes, 0); - string notecard = llList2String(pending_notecard_names, 0); - // whack the head of the queue since we grabbed the info. - pending_signatures = llDeleteSubList(pending_signatures, 0, 0); - pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); - pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); - if (llStringLength(notecard)) { - global_notecard_name = notecard; - select_specific_notecard(); - } else { - reset_for_reading(sig, response_code); - } - } -} - -// deals with one data server answer from the notecard. -process_notecard_line(key query_id, string data) -{ - // try to consume a line from the notecard. - integer outcome = handle_notecard_line(query_id, data); - if (outcome == DONE_READING) { - // that was a valid notecard and we read all of it. - if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); - // send back the results. - send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], - READ_NOTECARD_COMMAND, TRUE); - } else if (outcome == BAD_NOTECARD) { - // bail; this problem must be addressed by other means. - if (DEBUGGING) log_it("failed to find an appropriate notecard"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } else if (outcome == STILL_READING) { - // we have a good card and are still processing it. - return; - } else { - if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); - // again, bail out. we have no idea what happened with this. - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } - // if we have reached here, we should crank up the next queued notecard reading. - dequeue_next_request(); -} - -// processes requests from our users. -handle_link_message(integer which, integer num, string msg, key id) -{ - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - - if (msg == READ_NOTECARD_COMMAND) { - only_read_one_notecard = FALSE; // general inquiry for any card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read notecard--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code = llList2Integer(parms, 1); -//log_it("got signature " + signature + " and respcode " + (string)response_code); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code); - if (!try_next_notecard()) { - if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code ], - READ_NOTECARD_COMMAND, FALSE); - return; - } -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code; -//holding: pending_notecard_names += ""; -//holding: } - } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { - only_read_one_notecard = TRUE; // they want one particular card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read specific--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code = llList2Integer(parms, 1); - string notecard_name = llList2String(parms, 2); -//log_it("got signature " + signature + " and respcode " + (string)response_code); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code); - global_notecard_name = notecard_name; // set our global. - select_specific_notecard(); -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code; -//holding: pending_notecard_names += notecard_name; -//holding: } - } -} - - -/////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - startup_initialize(); - } - - state_exit() { - llSetTimerEvent(0); - } - - // we don't do anything until we're given a command to read a notecard. - link_message(integer which, integer num, string msg, key id) - { - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - handle_link_message(which, num, msg, id); - } - - on_rez(integer parm) { state rerun; } - - timer() { - llSetTimerEvent(0.0); // stop any timer now. - // let the caller know this has failed out. -// if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - current_response_code = 0; // we gave up on that one. - dequeue_next_request(); // get next reading started if we have anything to read. - } - - dataserver(key query_id, string data) { - // make sure this data is for us. - if (global_query_id != query_id) return; - // yep, seems to be. - process_notecard_line(query_id, data); - } -} - - - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.txt new file mode 100755 index 00000000..4d56bac0 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/noteworthy_library_v12.4.txt @@ -0,0 +1,541 @@ + +// huffware script: noteworthy library, by fred huffhines. +// +// a handy approach to reading a notecard. this version supports requiring +// a 'signature' in the notecard's first line, so that multiple notecards can +// exist in an object without being misinterpreted. the script is accessed via +// its link message API, so it can be used in an object without all this code +// needing to be embedded in another script. it also supports queuing up requests +// to read notecards, so multiple scripts can use it to read their specific +// notecards without any special handling (besides waiting a bit longer). +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants that can be adapted to your needs... + +integer DEBUGGING = FALSE; + // if this is true, then a lot of extra noise is generated when notecards are read. + +float TIME_OUT_ON_ONE_NOTECARD = 42.0; + // we allow one line of a notecard this long to be read before we decide it's hosed. + // some sims are very very slow, and a time-out of one minute has been found lacking; + // we saw at least one case where the first notecard line to be read took longer than + // 60 seconds. that's why we kept cranking this time-out up... + +// constants that should not be changed... + +// outcomes from handling a line in a notecard. +integer STILL_READING = -8; // the notecard seems good, but isn't finished. +integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. +integer DONE_READING = -10; // the notecard is finished being read. + +integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. + +integer MAXIMUM_LINES_USED = 4; + // we will read this many lines at a time from the appropriate notecard. + +// this is the noteworthy library's API that is available via link messages. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. + +//STRIKE THIS from everywhere. +//string BUSY_READING_INDICATOR = "busy_already"; +// // this return value indicates that the script is already in use by some other script. +// // the calling script should try again later. + +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// global variables... + +string requested_signature = ""; + // if this is non-empty, then it must be found in the first line of the script. + +integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. + +string global_notecard_name; // the name of the card we're reading now. +key global_query_id = NULL_KEY; // the identifier of our data query. +integer current_response_code = 0; // the code that our client uses for its reading. +list global_query_contents; // the lines we have read from the notecard. + +integer line_number = 0; // which line are we at in notecard? + +integer found_signature_line = FALSE; // did we find our first line in a notecard yet? + +integer trying_notecard_at = -1; // where we are currently looking for a good notecard. + +list pending_signatures; // signatures from queued requests for reading. +list pending_response_codes; // response codes for the queued requests. +list pending_notecard_names; // card names if it's a specific request. + +////////////// + +startup_initialize() +{ + pending_signatures = []; + pending_response_codes = []; + pending_notecard_names = []; + current_response_code = 0; + llSetTimerEvent(0.0); +} + +reset_for_reading(string signature, integer response_code) +{ + requested_signature = signature; + current_response_code = response_code; + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. + global_query_contents = []; + global_notecard_name = ""; + line_number = 0; + found_signature_line = FALSE; + trying_notecard_at = -1; + global_query_id = NULL_KEY; +} + +// use the existing global notecard setting to start reading. +select_specific_notecard() +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + line_number = 0; // reset line number again. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// picks the notecard at the "index" (from 0 to num_notecards - 1) and +// starts reading it. +select_notecard(integer index) +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); + if (card_specified == "") return; // not good. bad index. + global_notecard_name = card_specified; + line_number = 0; // reset line number again. + // we have a new file name, so load up the destinations, hopefully. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// increments our index in the count of notecards that the object has, and start +// reading the next notecard (at the index). +integer try_next_notecard() +{ + if (only_read_one_notecard) { + return FALSE; // we were only going to try one. + } + // reset some values that might have applied before. + global_notecard_name = ""; + // skip to the next card. + trying_notecard_at++; + // make sure we're not over the count of cards. + if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { + // this is a problem. we didn't find anything suitable. + return FALSE; + } + // so, now we'll try the next notecard to look for our signature. + select_notecard(trying_notecard_at); + return TRUE; +} + +// process a line of text that we received from the current notecard. +integer handle_notecard_line(key query_id, string data) +{ + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + // there's more to read in the notecard still. + if (data != "") { + // make sure we even have a signature to look for. + if (!found_signature_line && (requested_signature == "")) { + // no signature means that we always find it. + found_signature_line = TRUE; + } + // did we already get our signature? if not, see if this is it. + if (!found_signature_line && (data != requested_signature) ) { + // this is a bad notecard. skip it. + if (!try_next_notecard()) { + // we have no more to work with. + return BAD_NOTECARD; + } + return STILL_READING; // we'll keep going. + } else if (!found_signature_line && (data == requested_signature) ) { + // this is a good signature line, so record that and then skip it. + found_signature_line = TRUE; + } else { + if (DEBUGGING + && ( ( (requested_signature == "") && (line_number == 0) ) + || ( (requested_signature != "") && (line_number == 1) ) ) ) { + log_it("started reading " + global_notecard_name + "..."); + } + // don't record any lines that are comments. + if ( (llGetSubString(data, 0, 0) != "#") + && (llGetSubString(data, 0, 0) != ";") ) { + // add the non-blank line to our list. + global_query_contents += data; + // make sure we still have enough space to keep going. + if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { + // ooh, make sure we pause before blowing our heap&stack. + send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, + current_response_code ], READ_NOTECARD_COMMAND, TRUE); + } + } + } + } + line_number++; // increase the line count. + // reset the timer rather than timing out, if we actually got some data. + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); + // request the next line from the notecard. + global_query_id = llGetNotecardLine(global_notecard_name, line_number); + if (global_query_id == NULL_KEY) { +//log_it("failed to restart notecard reading."); + return DONE_READING; +//is that the best outcome? + } + return STILL_READING; + } else { + // that's the end of the notecard. we need some minimal verification that it + // wasn't full of garbage. + if (!found_signature_line) { + if (DEBUGGING) log_it("never found signature in " + global_notecard_name); + if (!try_next_notecard()) { + return BAD_NOTECARD; // we failed to find a good line? + } else { + // the next notecard's coming through now. + return STILL_READING; + } + } else { +// if (DEBUGGING) log_it("found signature."); + // saw the signature line, so this is a good one. + return DONE_READING; + } + } +} + +// only sends reply; does not reset notecard process. +send_reply(integer destination, list parms, string command, + integer include_query) +{ +//integer items = llGetListLength(parms); +//if (include_query) items += llGetListLength(global_query_contents); +//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); + + if (!include_query) { + llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + } else { + llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, + llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); + } + global_query_contents = []; +//log_it("post-sending, mem=" + (string)llGetFreeMemory()); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply_and_reset(integer destination, list parms, string command, + integer include_query) +{ + llSetTimerEvent(0.0); // stop the timer, since we're about to reply. + send_reply(destination, parms, command, include_query); + current_response_code = 0; // reset back to default so we can start another read. + global_query_id = NULL_KEY; // reset so we accept no more data. +} + +// if there are other pending notecard reads, this goes to the next one listed. +dequeue_next_request() +{ + if (llGetListLength(pending_signatures)) { + // get the info from the next pending item. + string sig = llList2String(pending_signatures, 0); + integer response_code = llList2Integer(pending_response_codes, 0); + string notecard = llList2String(pending_notecard_names, 0); + // whack the head of the queue since we grabbed the info. + pending_signatures = llDeleteSubList(pending_signatures, 0, 0); + pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); + pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); + if (llStringLength(notecard)) { + global_notecard_name = notecard; + select_specific_notecard(); + } else { + reset_for_reading(sig, response_code); + } + } +} + +// deals with one data server answer from the notecard. +process_notecard_line(key query_id, string data) +{ + // try to consume a line from the notecard. + integer outcome = handle_notecard_line(query_id, data); + if (outcome == DONE_READING) { + // that was a valid notecard and we read all of it. + if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); + // send back the results. + send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], + READ_NOTECARD_COMMAND, TRUE); + } else if (outcome == BAD_NOTECARD) { + // bail; this problem must be addressed by other means. + if (DEBUGGING) log_it("failed to find an appropriate notecard"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } else if (outcome == STILL_READING) { + // we have a good card and are still processing it. + return; + } else { + if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); + // again, bail out. we have no idea what happened with this. + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } + // if we have reached here, we should crank up the next queued notecard reading. + dequeue_next_request(); +} + +// processes requests from our users. +handle_link_message(integer which, integer num, string msg, key id) +{ + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + + if (msg == READ_NOTECARD_COMMAND) { + only_read_one_notecard = FALSE; // general inquiry for any card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read notecard--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code = llList2Integer(parms, 1); +//log_it("got signature " + signature + " and respcode " + (string)response_code); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code); + if (!try_next_notecard()) { + if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code ], + READ_NOTECARD_COMMAND, FALSE); + return; + } +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code; +//holding: pending_notecard_names += ""; +//holding: } + } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { + only_read_one_notecard = TRUE; // they want one particular card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read specific--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code = llList2Integer(parms, 1); + string notecard_name = llList2String(parms, 2); +//log_it("got signature " + signature + " and respcode " + (string)response_code); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code); + global_notecard_name = notecard_name; // set our global. + select_specific_notecard(); +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code; +//holding: pending_notecard_names += notecard_name; +//holding: } + } +} + + +/////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + startup_initialize(); + } + + state_exit() { + llSetTimerEvent(0); + } + + // we don't do anything until we're given a command to read a notecard. + link_message(integer which, integer num, string msg, key id) + { + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + handle_link_message(which, num, msg, id); + } + + on_rez(integer parm) { state rerun; } + + timer() { + llSetTimerEvent(0.0); // stop any timer now. + // let the caller know this has failed out. +// if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + current_response_code = 0; // we gave up on that one. + dequeue_next_request(); // get next reading started if we have anything to read. + } + + dataserver(key query_id, string data) { + // make sure this data is for us. + if (global_query_id != query_id) return; + // yep, seems to be. + process_notecard_line(query_id, data); + } +} + + + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.lsl deleted file mode 100755 index f3201ee1..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.lsl +++ /dev/null @@ -1,210 +0,0 @@ - -// huffware script: particle projector, by fred huffhines. -// -// takes a texture from one side of the object and projects it in a forward X and upward Z direction. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants that can be modified for different behavior. - -float TEXTURE_DISPLAY_LIFE_SPAN = 14.0; // how long the texture should be shown. - -integer SIDE_TO_ACQUIRE_TEXTURE_FROM = 1; // which side of the object should give us our display texture? - -float MAGNIFIER = 4.0; // how much to expand the texture as it runs. - -vector TEXTURE_ACCELERATION = <0.02, 0.0, 0.01>; // change in speed of the texture over time. - -// global variables used in the script. - -string texture_to_display = "95c7bb7c-d777-26b1-4052-acd778bfcb40"; // a simple default texture. - -// displays a particle system with a texture that gradually enlarges over the object. -texture_hallucination() -{ - // get a bounding box around the object. - list bounds = llGetBoundingBox(llGetKey()); - // calculate the size of the object, which will be our starting particle size. - vector size = (vector)llList2String(bounds, 1) - (vector)llList2String(bounds, 0); - float chosen_dimension = size.x; - if (size.y > chosen_dimension) chosen_dimension = size.y; - if (size.z > chosen_dimension) chosen_dimension = size.z; - llParticleSystem([ - // properties regarding the generated particles. - PSYS_PART_FLAGS, PSYS_PART_BOUNCE_MASK | PSYS_PART_INTERP_SCALE_MASK, - PSYS_PART_START_SCALE, , - PSYS_PART_END_SCALE, , - PSYS_PART_MAX_AGE, TEXTURE_DISPLAY_LIFE_SPAN, - PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>, - PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>, - PSYS_PART_START_ALPHA, 1.0, - PSYS_PART_END_ALPHA, 1.0, - // properties for the particle system's source. - PSYS_SRC_MAX_AGE, TEXTURE_DISPLAY_LIFE_SPAN, - PSYS_SRC_TEXTURE, texture_to_display, - PSYS_SRC_ACCEL, TEXTURE_ACCELERATION, - PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP, - PSYS_SRC_BURST_PART_COUNT, 1, - PSYS_SRC_BURST_RADIUS, chosen_dimension, - PSYS_SRC_BURST_RATE, TEXTURE_DISPLAY_LIFE_SPAN, - PSYS_SRC_BURST_SPEED_MIN, 0.01, - PSYS_SRC_BURST_SPEED_MAX, 0.01, - PSYS_SRC_ANGLE_BEGIN, 0.0, - PSYS_SRC_ANGLE_END, 0.0, - PSYS_SRC_OMEGA, <0.0, 0.0, 0.0> - ]); -} - -// from hufflets... - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() { - auto_retire(); - } - - touch_start(integer touch_count) { - integer count = llGetInventoryNumber(INVENTORY_TEXTURE); - if (count > 0) { - // try getting a texture out of inventory. - integer which_texture = llRound(randomize_within_range(0, count - 1, FALSE)); - texture_to_display = llGetInventoryName(INVENTORY_TEXTURE, which_texture); -//if (texture_to_display == "") llOwnerSay("fail! got bad index from random."); - } else { - // if none in inventory, load the texture to show from our side. - texture_to_display = llGetTexture(SIDE_TO_ACQUIRE_TEXTURE_FROM); - } -//llOwnerSay("texture is now: " + texture_to_display); - texture_hallucination(); - llSetTimerEvent(TEXTURE_DISPLAY_LIFE_SPAN + 0.1); - } - - timer() { - llParticleSystem([]); // zap it back out again. - llSetTimerEvent(0); // turn off timer. - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.txt new file mode 100755 index 00000000..f3201ee1 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/particle_projector_v3.1.txt @@ -0,0 +1,210 @@ + +// huffware script: particle projector, by fred huffhines. +// +// takes a texture from one side of the object and projects it in a forward X and upward Z direction. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants that can be modified for different behavior. + +float TEXTURE_DISPLAY_LIFE_SPAN = 14.0; // how long the texture should be shown. + +integer SIDE_TO_ACQUIRE_TEXTURE_FROM = 1; // which side of the object should give us our display texture? + +float MAGNIFIER = 4.0; // how much to expand the texture as it runs. + +vector TEXTURE_ACCELERATION = <0.02, 0.0, 0.01>; // change in speed of the texture over time. + +// global variables used in the script. + +string texture_to_display = "95c7bb7c-d777-26b1-4052-acd778bfcb40"; // a simple default texture. + +// displays a particle system with a texture that gradually enlarges over the object. +texture_hallucination() +{ + // get a bounding box around the object. + list bounds = llGetBoundingBox(llGetKey()); + // calculate the size of the object, which will be our starting particle size. + vector size = (vector)llList2String(bounds, 1) - (vector)llList2String(bounds, 0); + float chosen_dimension = size.x; + if (size.y > chosen_dimension) chosen_dimension = size.y; + if (size.z > chosen_dimension) chosen_dimension = size.z; + llParticleSystem([ + // properties regarding the generated particles. + PSYS_PART_FLAGS, PSYS_PART_BOUNCE_MASK | PSYS_PART_INTERP_SCALE_MASK, + PSYS_PART_START_SCALE, , + PSYS_PART_END_SCALE, , + PSYS_PART_MAX_AGE, TEXTURE_DISPLAY_LIFE_SPAN, + PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>, + PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>, + PSYS_PART_START_ALPHA, 1.0, + PSYS_PART_END_ALPHA, 1.0, + // properties for the particle system's source. + PSYS_SRC_MAX_AGE, TEXTURE_DISPLAY_LIFE_SPAN, + PSYS_SRC_TEXTURE, texture_to_display, + PSYS_SRC_ACCEL, TEXTURE_ACCELERATION, + PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP, + PSYS_SRC_BURST_PART_COUNT, 1, + PSYS_SRC_BURST_RADIUS, chosen_dimension, + PSYS_SRC_BURST_RATE, TEXTURE_DISPLAY_LIFE_SPAN, + PSYS_SRC_BURST_SPEED_MIN, 0.01, + PSYS_SRC_BURST_SPEED_MAX, 0.01, + PSYS_SRC_ANGLE_BEGIN, 0.0, + PSYS_SRC_ANGLE_END, 0.0, + PSYS_SRC_OMEGA, <0.0, 0.0, 0.0> + ]); +} + +// from hufflets... + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() { + auto_retire(); + } + + touch_start(integer touch_count) { + integer count = llGetInventoryNumber(INVENTORY_TEXTURE); + if (count > 0) { + // try getting a texture out of inventory. + integer which_texture = llRound(randomize_within_range(0, count - 1, FALSE)); + texture_to_display = llGetInventoryName(INVENTORY_TEXTURE, which_texture); +//if (texture_to_display == "") llOwnerSay("fail! got bad index from random."); + } else { + // if none in inventory, load the texture to show from our side. + texture_to_display = llGetTexture(SIDE_TO_ACQUIRE_TEXTURE_FROM); + } +//llOwnerSay("texture is now: " + texture_to_display); + texture_hallucination(); + llSetTimerEvent(TEXTURE_DISPLAY_LIFE_SPAN + 0.1); + } + + timer() { + llParticleSystem([]); // zap it back out again. + llSetTimerEvent(0); // turn off timer. + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.lsl deleted file mode 100755 index ed0382a9..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.lsl +++ /dev/null @@ -1,646 +0,0 @@ - -// huffware script: "party culiar", by fred huffhines -// -// this is yet another particle system script, based on ideas seen -// in several scripts by various authors and assisted by the lsl wiki. -// it has the useful characteristic of being able to load its parameters -// from a notecard, thus making script modifications for the particle -// system unnecessary. -// on initial rez, if a notecard exists, then it is read for particle -// system parameters named similarly to the variables below (see the -// particle archetype notecard for more details). if the object is -// rezzed with an existing particle system already read from a notecard -// that's still present, it will keep playing that particle system. -// if a notecard is added or changed, then the particle variables are -// read again. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// party culiar link message API. -////////////// -integer PARTYCULIAR_HUFFWARE_ID = 10018; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. -// -string PARTYCULIAR_POWER_COMMAND = "#powrpcl"; - // tells the particle system to either turn on or off. the single parameter is - // either "on", "1", "true", or "off", "0", "false". -////////////// - -// constants... -float MIN_ROTATION = 0.1; // rotations used for omega value to rotate particles. -float MAX_ROTATION = 4.0; - -// items controlled by the notecard... - -// noisiness... -integer debug = FALSE; // controls whether logging occurs. - -integer start_enabled = FALSE; // if true, particle system starts up right away. - -// color... -integer interpolate_colors = TRUE; -integer randomize_colors = FALSE; -vector starting_color = <0.5, 0.7, 0.9>; -vector ending_color = <0.0, 1.0, 0.3>; - -// particle size... -integer interpolate_size = TRUE; -vector final_dimensions = <1.8, 1.8, 1.8>; -vector initial_dimensions = <0.72, 0.72, 0.72>; - -// transparency... -// 1.0 means completely opaque and 0.0 means completely transparent. -float initial_opacity = 1.0; -float final_opacity = 0.3; - -// target following (or not)... -integer follow_target_key = FALSE; -key target_key = NULL_KEY; - -// speed and acceleration of particles... -float minimum_velocity = 0.4; -float maximum_velocity = 1.4; -vector acceleration = <0.0, 0.4, 0.7>; -integer wind_blown = TRUE; // are particles affected by wind? - -// freaky effects for particles... -integer bounce_off_z_height = FALSE; // start at height of containing object. -integer glowing = FALSE; // particles will glow. -integer source_centered = TRUE; // particles start at object's center. -integer point_toward_velocity = TRUE; // rotate vertical axis toward velocity. - -string particle_texture = ""; // image used for the particle, if any. - -// when randomizing colors, these control how long a choice lasts. -float minimum_hold_time = 5.0; -float maximum_hold_time = 20.0; - -// timing (in seconds)... -float lifespan_for_particle = 3.0; -float lifespan_for_system = 0.0; // 0 means unlimited. -float creation_rate = 0.2; // delay between particle creations. -integer siblings = 7; // how many to create at once. - -// how to exude particles. -integer emission_pattern - = PSYS_SRC_PATTERN_ANGLE; // 2D emission between given angles. - // = PSYS_SRC_PATTERN_DROP; // just plop them at center of object. - // = PSYS_SRC_PATTERN_EXPLODE; // spew them out as if exploded. - // = PSYS_SRC_PATTERN_ANGLE_CONE; // 3D emission between given angles. - // = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY; // inverse of angle cone. - -// pattern details... -float starting_angle = 1.0; // initial angle where particles are emitted. -float ending_angle = 0.0; // bounding angle for emission. -vector rotation_between_bursts = <0.2, 0.2, 0.2>; // used in angle patterns. -float burst_radius = 2.0; // emission distance from source, unused for source centered. - -// add-in... huffware script: notecard library, by fred huffhines - -string current_notecard_name; // the name of the card we're reading now. -key current_query_id; // the query ID for the current notecard. -list query_contents; // the lines we have read from the notecard. -integer line_number; // which line are we at in notecard? - -initialize() -{ - current_notecard_name = ""; - current_query_id = NULL_KEY; - query_contents = []; - line_number = 0; -} - -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = len - 1; i >= 0; i--) { - text += llList2String(to_show, i) + "\n"; - } - return text; -} - -////////////// - -create_particle_system() -{ - if (randomize_colors) { - starting_color = ; - ending_color = ; - } - - list system_parameters; - integer flags_for_particle_effects = 0; - - if (interpolate_colors) - flags_for_particle_effects = PSYS_PART_INTERP_COLOR_MASK | flags_for_particle_effects; - system_parameters += [ PSYS_PART_START_COLOR, starting_color, - PSYS_PART_END_COLOR, ending_color ]; - - if (interpolate_size) - flags_for_particle_effects = PSYS_PART_INTERP_SCALE_MASK | flags_for_particle_effects; - system_parameters += [ PSYS_PART_START_SCALE, initial_dimensions, - PSYS_PART_END_SCALE, final_dimensions ]; - - system_parameters += [ PSYS_PART_START_ALPHA, initial_opacity, - PSYS_PART_END_ALPHA, final_opacity ]; - - if (follow_target_key && (target_key != NULL_KEY) ) { - flags_for_particle_effects = PSYS_PART_TARGET_POS_MASK | flags_for_particle_effects; - system_parameters += [ PSYS_SRC_TARGET_KEY, target_key ]; - } - - system_parameters += [ PSYS_SRC_BURST_SPEED_MIN, minimum_velocity, - PSYS_SRC_BURST_SPEED_MAX, maximum_velocity, - PSYS_SRC_ACCEL, acceleration ]; - if (wind_blown) - flags_for_particle_effects = PSYS_PART_WIND_MASK | flags_for_particle_effects; - - if (particle_texture != "") - system_parameters += [ PSYS_SRC_TEXTURE, particle_texture ]; - - if (emission_pattern != 0) - system_parameters += [ PSYS_SRC_PATTERN, emission_pattern ]; - - system_parameters += [ PSYS_PART_MAX_AGE, lifespan_for_particle, - PSYS_SRC_MAX_AGE, lifespan_for_system, - PSYS_SRC_BURST_PART_COUNT, siblings, - PSYS_SRC_BURST_RATE, creation_rate ]; - -//hmmm: only add if used? - system_parameters += [ PSYS_SRC_ANGLE_BEGIN, starting_angle, - PSYS_SRC_ANGLE_END, ending_angle, - PSYS_SRC_OMEGA, rotation_between_bursts ]; - - // assorted effects... - if (bounce_off_z_height) - flags_for_particle_effects = PSYS_PART_BOUNCE_MASK | flags_for_particle_effects; - if (glowing) - flags_for_particle_effects = PSYS_PART_EMISSIVE_MASK | flags_for_particle_effects; - if (point_toward_velocity) - flags_for_particle_effects = PSYS_PART_FOLLOW_VELOCITY_MASK | flags_for_particle_effects; - if (source_centered) - flags_for_particle_effects = PSYS_PART_FOLLOW_SRC_MASK | flags_for_particle_effects; - else - system_parameters += [ PSYS_SRC_BURST_RADIUS, burst_radius ]; // okay to use. - - // now that we're done accumulating the flags, we can add them to our list. - system_parameters += [ PSYS_PART_FLAGS, flags_for_particle_effects ]; // must be last. - - // and finally, we are ready to create the particle system of our dreams... - llParticleSystem(system_parameters); -} - -// returns a non-empty string if "to_check" defines contents for "variable_name". -string defines_variable(string to_check, string variable_name) -{ - // clean initial spaces. - while (llGetSubString(to_check, 0, 0) == " ") - to_check = llDeleteSubString(to_check, 0, 0); - if (!is_prefix(to_check, variable_name)) return ""; - to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); - // clean any spaces or valid assignment characters. - while ( (llGetSubString(to_check, 0, 0) == " ") - || (llGetSubString(to_check, 0, 0) == "=") - || (llGetSubString(to_check, 0, 0) == ",") ) - to_check = llDeleteSubString(to_check, 0, 0); - if (debug) - log_it("set " + variable_name + " = " + to_check); - // return what's left of the string. - return to_check; -} - -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - string texture_name; // temporary used in reading texture name. - - if ( (content = defines_variable(to_parse, "debug")) != "") - debug = (integer)content; - else if ( (content = defines_variable(to_parse, "interpolate_colors")) != "") - interpolate_colors = (integer)content; - else if ( (content = defines_variable(to_parse, "randomize_colors")) != "") - randomize_colors = (integer)content; - else if ( (content = defines_variable(to_parse, "starting_color")) != "") - starting_color = (vector)content; - else if ( (content = defines_variable(to_parse, "ending_color")) != "") - ending_color = (vector)content; - else if ( (content = defines_variable(to_parse, "interpolate_size")) != "") - interpolate_size = (integer)content; - else if ( (content = defines_variable(to_parse, "initial_dimensions")) != "") - initial_dimensions = (vector)content; - else if ( (content = defines_variable(to_parse, "final_dimensions")) != "") - final_dimensions = (vector)content; - else if ( (content = defines_variable(to_parse, "initial_opacity")) != "") - initial_opacity = (float)content; - else if ( (content = defines_variable(to_parse, "final_opacity")) != "") - final_opacity = (float)content; - else if ( (content = defines_variable(to_parse, "follow_target_key")) != "") - follow_target_key = (integer)content; - else if ( (content = defines_variable(to_parse, "target_key")) != "") - target_key = (string)content; - else if ( (content = defines_variable(to_parse, "minimum_velocity")) != "") - minimum_velocity = (float)content; - else if ( (content = defines_variable(to_parse, "maximum_velocity")) != "") - maximum_velocity = (float)content; - else if ( (content = defines_variable(to_parse, "wind_blown")) != "") - wind_blown = (integer)content; - else if ( (content = defines_variable(to_parse, "acceleration")) != "") - acceleration = (vector)content; - else if ( (content = defines_variable(to_parse, "bounce_off_z_height")) != "") - bounce_off_z_height = (integer)content; - else if ( (content = defines_variable(to_parse, "glowing")) != "") - glowing = (integer)content; - else if ( (content = defines_variable(to_parse, "source_centered")) != "") - source_centered = (integer)content; - else if ( (content = defines_variable(to_parse, "point_toward_velocity")) != "") - point_toward_velocity = (integer)content; - else if ( (content = defines_variable(to_parse, "particle_texture")) != "") - particle_texture = (string)content; - else if ( (content = defines_variable(to_parse, "lifespan_for_particle")) != "") - lifespan_for_particle = (float)content; - else if ( (content = defines_variable(to_parse, "lifespan_for_system")) != "") - lifespan_for_system = (float)content; - else if ( (content = defines_variable(to_parse, "creation_rate")) != "") - creation_rate = (float)content; - else if ( (content = defines_variable(to_parse, "siblings")) != "") - siblings = (integer)content; - else if ( (content = defines_variable(to_parse, "minimum_hold_time")) != "") - minimum_hold_time = (float)content; - else if ( (content = defines_variable(to_parse, "maximum_hold_time")) != "") - maximum_hold_time = (float)content; - else if ( (content = defines_variable(to_parse, "emission_pattern")) != "") { - texture_name = (string)content; - // translate the short hand name into an emission_pattern value. - if (texture_name == "ANGLE") emission_pattern = PSYS_SRC_PATTERN_ANGLE; - else if (texture_name == "DROP") emission_pattern = PSYS_SRC_PATTERN_DROP; - else if (texture_name == "EXPLODE") emission_pattern = PSYS_SRC_PATTERN_EXPLODE; - else if (texture_name == "ANGLE_CONE") emission_pattern = PSYS_SRC_PATTERN_ANGLE_CONE; - else if (texture_name == "ANGLE_CONE_EMPTY") - emission_pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY; -//log_it("emission pattern is now " + (string)emission_pattern); - } - else if ( (content = defines_variable(to_parse, "starting_angle")) != "") - starting_angle = (float)content; - else if ( (content = defines_variable(to_parse, "ending_angle")) != "") - ending_angle = (float)content; - else if ( (content = defines_variable(to_parse, "rotation_between_bursts")) != "") { - if (content == "random") - rotation_between_bursts = ; - else - rotation_between_bursts = (vector)content; - } else if ( (content = defines_variable(to_parse, "burst_radius")) != "") - burst_radius = (float)content; - else if ( (content = defines_variable(to_parse, "running")) != "") - start_enabled = (integer)content; - - // special cases for key to follow... - if (target_key == "owner") target_key = llGetOwner(); - else if (target_key == "self") target_key = llGetKey(); - // special cases for texture. - if (particle_texture == "inventory") - particle_texture = llGetInventoryName(INVENTORY_TEXTURE, 0); - -} - -process_particle_settings(list particle_definitions) -{ - integer current_item = 0; - integer max_items = llGetListLength(particle_definitions); - while (current_item < max_items) { - string curr_line = llList2String(particle_definitions, current_item); - parse_variable_definition(curr_line); - current_item++; - } -} - -randomize_timer() -{ - if (randomize_colors) { - llSetTimerEvent(randomize_within_range(maximum_hold_time, - minimum_hold_time, FALSE)); - } -} - -stop_timer() { llSetTimerEvent(0.0); } - -check_for_notecard() -{ - if (current_notecard_name != "") return; - // if there's a notecard, then we will start reading it. - if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0) { - current_notecard_name = llGetInventoryName(INVENTORY_NOTECARD, 0); - line_number = 0; - query_contents = []; - current_query_id = llGetNotecardLine(current_notecard_name, 0); - llSetTimerEvent(80); - } -} - -// this should be invoked from the link_message event handler to process the requests -// for whatever service this library script provides. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - if (huff_id != PARTYCULIAR_HUFFWARE_ID) { - return; - } -//llOwnerSay("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); - if (msg == PARTYCULIAR_POWER_COMMAND) { - string cmd = id; - if ( (find_substring(id, "on") == 0) - || (find_substring(id, "1") == 0) - || (find_substring(id, "true") == 0) ) { - // they want to crank the particle system up. - create_particle_system(); - randomize_timer(); - } else if ( (find_substring(id, "off") == 0) - || (find_substring(id, "0") == 0) - || (find_substring(id, "false") == 0) ) { - // the request is to shut the party down now. - llParticleSystem([]); - stop_timer(); - } - } -} - -////////////// -// from hufflets... - -////////////// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -////////////// - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// handles when blank strings need to come through the pipe. -string wrap_blank_string(string to_wrap) -{ - if (llStringLength(to_wrap)) return to_wrap; // that one is okay. - return "\"\""; // return a quoted nothing as a signal for a blank. -} - -// undoes a previously wrapped blank string. -string interpret_blank_string(string to_unwrap) -{ - if (to_unwrap == "\"\"") return ""; // that was an encoded blank. - return to_unwrap; // no encoding. -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, PARTYCULIAR_HUFFWARE_ID, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -////////////// - -// returns a number at most maximum and at least minimum. -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - initialize(); - if (start_enabled) { - create_particle_system(); - randomize_timer(); - } else { - llParticleSystem([]); - stop_timer(); - } - check_for_notecard(); - } - - timer() { - if (current_query_id != NULL_KEY) { - // there's been a failure of some sort; we were supposed to get a notecard to read. - llWhisper(0, "Failed to read the notecard, now restarting."); - llResetScript(); - } - create_particle_system(); - randomize_timer(); - } - - on_rez(integer parm) { - target_key = llGetKey(); // reset to get rid of weird wrong keys. - llResetScript(); - } - - link_message(integer sender, integer num, string msg, key id) { - handle_link_message(sender, num, msg, id); - } - - changed(integer change_type) { - if (change_type != CHANGED_INVENTORY) { - // we only care about inventory changes here. - return; - } - llResetScript(); - } - - dataserver(key query_id, string data) { - if (query_id != current_query_id) { -log_it("not our query id somehow? weird query had: id=" + (string)query_id + " data=" + (string)data); - // to heck with all this weirdness; if there's a failure, start over. - llResetScript(); - } - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - if (!line_number) { - if (data != "#party culiar") { - // this card has the wrong signature at the top. quit bothering - // with it now. - return; - } - log_it("starting to read notecard " + current_notecard_name + "..."); - } - if (data != "") { - // add the non-blank line to our destination list. - query_contents += data; -//log_it("line " + (string)line_number + ": data=" + data); - } - line_number++; // increase the line count. - // request the next line from the notecard. - current_query_id = llGetNotecardLine(current_notecard_name, line_number); - } else { - // no more data, so we're done with this card. - current_query_id = NULL_KEY; - if (!llGetListLength(query_contents)) { - // nothing was read? the heck with this card. - current_notecard_name = ""; // toss bad card. - return; - } -//log_it("notecard said:\n" + dump_list(query_contents)); - process_particle_settings(query_contents); - if (start_enabled) { - create_particle_system(); - randomize_timer(); - } else { - llParticleSystem([]); - stop_timer(); - } - log_it("done reading notecard " + current_notecard_name + "."); - } - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.txt new file mode 100755 index 00000000..ed0382a9 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/party_culiar_v5.7.txt @@ -0,0 +1,646 @@ + +// huffware script: "party culiar", by fred huffhines +// +// this is yet another particle system script, based on ideas seen +// in several scripts by various authors and assisted by the lsl wiki. +// it has the useful characteristic of being able to load its parameters +// from a notecard, thus making script modifications for the particle +// system unnecessary. +// on initial rez, if a notecard exists, then it is read for particle +// system parameters named similarly to the variables below (see the +// particle archetype notecard for more details). if the object is +// rezzed with an existing particle system already read from a notecard +// that's still present, it will keep playing that particle system. +// if a notecard is added or changed, then the particle variables are +// read again. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// party culiar link message API. +////////////// +integer PARTYCULIAR_HUFFWARE_ID = 10018; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. +// +string PARTYCULIAR_POWER_COMMAND = "#powrpcl"; + // tells the particle system to either turn on or off. the single parameter is + // either "on", "1", "true", or "off", "0", "false". +////////////// + +// constants... +float MIN_ROTATION = 0.1; // rotations used for omega value to rotate particles. +float MAX_ROTATION = 4.0; + +// items controlled by the notecard... + +// noisiness... +integer debug = FALSE; // controls whether logging occurs. + +integer start_enabled = FALSE; // if true, particle system starts up right away. + +// color... +integer interpolate_colors = TRUE; +integer randomize_colors = FALSE; +vector starting_color = <0.5, 0.7, 0.9>; +vector ending_color = <0.0, 1.0, 0.3>; + +// particle size... +integer interpolate_size = TRUE; +vector final_dimensions = <1.8, 1.8, 1.8>; +vector initial_dimensions = <0.72, 0.72, 0.72>; + +// transparency... +// 1.0 means completely opaque and 0.0 means completely transparent. +float initial_opacity = 1.0; +float final_opacity = 0.3; + +// target following (or not)... +integer follow_target_key = FALSE; +key target_key = NULL_KEY; + +// speed and acceleration of particles... +float minimum_velocity = 0.4; +float maximum_velocity = 1.4; +vector acceleration = <0.0, 0.4, 0.7>; +integer wind_blown = TRUE; // are particles affected by wind? + +// freaky effects for particles... +integer bounce_off_z_height = FALSE; // start at height of containing object. +integer glowing = FALSE; // particles will glow. +integer source_centered = TRUE; // particles start at object's center. +integer point_toward_velocity = TRUE; // rotate vertical axis toward velocity. + +string particle_texture = ""; // image used for the particle, if any. + +// when randomizing colors, these control how long a choice lasts. +float minimum_hold_time = 5.0; +float maximum_hold_time = 20.0; + +// timing (in seconds)... +float lifespan_for_particle = 3.0; +float lifespan_for_system = 0.0; // 0 means unlimited. +float creation_rate = 0.2; // delay between particle creations. +integer siblings = 7; // how many to create at once. + +// how to exude particles. +integer emission_pattern + = PSYS_SRC_PATTERN_ANGLE; // 2D emission between given angles. + // = PSYS_SRC_PATTERN_DROP; // just plop them at center of object. + // = PSYS_SRC_PATTERN_EXPLODE; // spew them out as if exploded. + // = PSYS_SRC_PATTERN_ANGLE_CONE; // 3D emission between given angles. + // = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY; // inverse of angle cone. + +// pattern details... +float starting_angle = 1.0; // initial angle where particles are emitted. +float ending_angle = 0.0; // bounding angle for emission. +vector rotation_between_bursts = <0.2, 0.2, 0.2>; // used in angle patterns. +float burst_radius = 2.0; // emission distance from source, unused for source centered. + +// add-in... huffware script: notecard library, by fred huffhines + +string current_notecard_name; // the name of the card we're reading now. +key current_query_id; // the query ID for the current notecard. +list query_contents; // the lines we have read from the notecard. +integer line_number; // which line are we at in notecard? + +initialize() +{ + current_notecard_name = ""; + current_query_id = NULL_KEY; + query_contents = []; + line_number = 0; +} + +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = len - 1; i >= 0; i--) { + text += llList2String(to_show, i) + "\n"; + } + return text; +} + +////////////// + +create_particle_system() +{ + if (randomize_colors) { + starting_color = ; + ending_color = ; + } + + list system_parameters; + integer flags_for_particle_effects = 0; + + if (interpolate_colors) + flags_for_particle_effects = PSYS_PART_INTERP_COLOR_MASK | flags_for_particle_effects; + system_parameters += [ PSYS_PART_START_COLOR, starting_color, + PSYS_PART_END_COLOR, ending_color ]; + + if (interpolate_size) + flags_for_particle_effects = PSYS_PART_INTERP_SCALE_MASK | flags_for_particle_effects; + system_parameters += [ PSYS_PART_START_SCALE, initial_dimensions, + PSYS_PART_END_SCALE, final_dimensions ]; + + system_parameters += [ PSYS_PART_START_ALPHA, initial_opacity, + PSYS_PART_END_ALPHA, final_opacity ]; + + if (follow_target_key && (target_key != NULL_KEY) ) { + flags_for_particle_effects = PSYS_PART_TARGET_POS_MASK | flags_for_particle_effects; + system_parameters += [ PSYS_SRC_TARGET_KEY, target_key ]; + } + + system_parameters += [ PSYS_SRC_BURST_SPEED_MIN, minimum_velocity, + PSYS_SRC_BURST_SPEED_MAX, maximum_velocity, + PSYS_SRC_ACCEL, acceleration ]; + if (wind_blown) + flags_for_particle_effects = PSYS_PART_WIND_MASK | flags_for_particle_effects; + + if (particle_texture != "") + system_parameters += [ PSYS_SRC_TEXTURE, particle_texture ]; + + if (emission_pattern != 0) + system_parameters += [ PSYS_SRC_PATTERN, emission_pattern ]; + + system_parameters += [ PSYS_PART_MAX_AGE, lifespan_for_particle, + PSYS_SRC_MAX_AGE, lifespan_for_system, + PSYS_SRC_BURST_PART_COUNT, siblings, + PSYS_SRC_BURST_RATE, creation_rate ]; + +//hmmm: only add if used? + system_parameters += [ PSYS_SRC_ANGLE_BEGIN, starting_angle, + PSYS_SRC_ANGLE_END, ending_angle, + PSYS_SRC_OMEGA, rotation_between_bursts ]; + + // assorted effects... + if (bounce_off_z_height) + flags_for_particle_effects = PSYS_PART_BOUNCE_MASK | flags_for_particle_effects; + if (glowing) + flags_for_particle_effects = PSYS_PART_EMISSIVE_MASK | flags_for_particle_effects; + if (point_toward_velocity) + flags_for_particle_effects = PSYS_PART_FOLLOW_VELOCITY_MASK | flags_for_particle_effects; + if (source_centered) + flags_for_particle_effects = PSYS_PART_FOLLOW_SRC_MASK | flags_for_particle_effects; + else + system_parameters += [ PSYS_SRC_BURST_RADIUS, burst_radius ]; // okay to use. + + // now that we're done accumulating the flags, we can add them to our list. + system_parameters += [ PSYS_PART_FLAGS, flags_for_particle_effects ]; // must be last. + + // and finally, we are ready to create the particle system of our dreams... + llParticleSystem(system_parameters); +} + +// returns a non-empty string if "to_check" defines contents for "variable_name". +string defines_variable(string to_check, string variable_name) +{ + // clean initial spaces. + while (llGetSubString(to_check, 0, 0) == " ") + to_check = llDeleteSubString(to_check, 0, 0); + if (!is_prefix(to_check, variable_name)) return ""; + to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); + // clean any spaces or valid assignment characters. + while ( (llGetSubString(to_check, 0, 0) == " ") + || (llGetSubString(to_check, 0, 0) == "=") + || (llGetSubString(to_check, 0, 0) == ",") ) + to_check = llDeleteSubString(to_check, 0, 0); + if (debug) + log_it("set " + variable_name + " = " + to_check); + // return what's left of the string. + return to_check; +} + +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + string texture_name; // temporary used in reading texture name. + + if ( (content = defines_variable(to_parse, "debug")) != "") + debug = (integer)content; + else if ( (content = defines_variable(to_parse, "interpolate_colors")) != "") + interpolate_colors = (integer)content; + else if ( (content = defines_variable(to_parse, "randomize_colors")) != "") + randomize_colors = (integer)content; + else if ( (content = defines_variable(to_parse, "starting_color")) != "") + starting_color = (vector)content; + else if ( (content = defines_variable(to_parse, "ending_color")) != "") + ending_color = (vector)content; + else if ( (content = defines_variable(to_parse, "interpolate_size")) != "") + interpolate_size = (integer)content; + else if ( (content = defines_variable(to_parse, "initial_dimensions")) != "") + initial_dimensions = (vector)content; + else if ( (content = defines_variable(to_parse, "final_dimensions")) != "") + final_dimensions = (vector)content; + else if ( (content = defines_variable(to_parse, "initial_opacity")) != "") + initial_opacity = (float)content; + else if ( (content = defines_variable(to_parse, "final_opacity")) != "") + final_opacity = (float)content; + else if ( (content = defines_variable(to_parse, "follow_target_key")) != "") + follow_target_key = (integer)content; + else if ( (content = defines_variable(to_parse, "target_key")) != "") + target_key = (string)content; + else if ( (content = defines_variable(to_parse, "minimum_velocity")) != "") + minimum_velocity = (float)content; + else if ( (content = defines_variable(to_parse, "maximum_velocity")) != "") + maximum_velocity = (float)content; + else if ( (content = defines_variable(to_parse, "wind_blown")) != "") + wind_blown = (integer)content; + else if ( (content = defines_variable(to_parse, "acceleration")) != "") + acceleration = (vector)content; + else if ( (content = defines_variable(to_parse, "bounce_off_z_height")) != "") + bounce_off_z_height = (integer)content; + else if ( (content = defines_variable(to_parse, "glowing")) != "") + glowing = (integer)content; + else if ( (content = defines_variable(to_parse, "source_centered")) != "") + source_centered = (integer)content; + else if ( (content = defines_variable(to_parse, "point_toward_velocity")) != "") + point_toward_velocity = (integer)content; + else if ( (content = defines_variable(to_parse, "particle_texture")) != "") + particle_texture = (string)content; + else if ( (content = defines_variable(to_parse, "lifespan_for_particle")) != "") + lifespan_for_particle = (float)content; + else if ( (content = defines_variable(to_parse, "lifespan_for_system")) != "") + lifespan_for_system = (float)content; + else if ( (content = defines_variable(to_parse, "creation_rate")) != "") + creation_rate = (float)content; + else if ( (content = defines_variable(to_parse, "siblings")) != "") + siblings = (integer)content; + else if ( (content = defines_variable(to_parse, "minimum_hold_time")) != "") + minimum_hold_time = (float)content; + else if ( (content = defines_variable(to_parse, "maximum_hold_time")) != "") + maximum_hold_time = (float)content; + else if ( (content = defines_variable(to_parse, "emission_pattern")) != "") { + texture_name = (string)content; + // translate the short hand name into an emission_pattern value. + if (texture_name == "ANGLE") emission_pattern = PSYS_SRC_PATTERN_ANGLE; + else if (texture_name == "DROP") emission_pattern = PSYS_SRC_PATTERN_DROP; + else if (texture_name == "EXPLODE") emission_pattern = PSYS_SRC_PATTERN_EXPLODE; + else if (texture_name == "ANGLE_CONE") emission_pattern = PSYS_SRC_PATTERN_ANGLE_CONE; + else if (texture_name == "ANGLE_CONE_EMPTY") + emission_pattern = PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY; +//log_it("emission pattern is now " + (string)emission_pattern); + } + else if ( (content = defines_variable(to_parse, "starting_angle")) != "") + starting_angle = (float)content; + else if ( (content = defines_variable(to_parse, "ending_angle")) != "") + ending_angle = (float)content; + else if ( (content = defines_variable(to_parse, "rotation_between_bursts")) != "") { + if (content == "random") + rotation_between_bursts = ; + else + rotation_between_bursts = (vector)content; + } else if ( (content = defines_variable(to_parse, "burst_radius")) != "") + burst_radius = (float)content; + else if ( (content = defines_variable(to_parse, "running")) != "") + start_enabled = (integer)content; + + // special cases for key to follow... + if (target_key == "owner") target_key = llGetOwner(); + else if (target_key == "self") target_key = llGetKey(); + // special cases for texture. + if (particle_texture == "inventory") + particle_texture = llGetInventoryName(INVENTORY_TEXTURE, 0); + +} + +process_particle_settings(list particle_definitions) +{ + integer current_item = 0; + integer max_items = llGetListLength(particle_definitions); + while (current_item < max_items) { + string curr_line = llList2String(particle_definitions, current_item); + parse_variable_definition(curr_line); + current_item++; + } +} + +randomize_timer() +{ + if (randomize_colors) { + llSetTimerEvent(randomize_within_range(maximum_hold_time, + minimum_hold_time, FALSE)); + } +} + +stop_timer() { llSetTimerEvent(0.0); } + +check_for_notecard() +{ + if (current_notecard_name != "") return; + // if there's a notecard, then we will start reading it. + if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0) { + current_notecard_name = llGetInventoryName(INVENTORY_NOTECARD, 0); + line_number = 0; + query_contents = []; + current_query_id = llGetNotecardLine(current_notecard_name, 0); + llSetTimerEvent(80); + } +} + +// this should be invoked from the link_message event handler to process the requests +// for whatever service this library script provides. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + if (huff_id != PARTYCULIAR_HUFFWARE_ID) { + return; + } +//llOwnerSay("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); + if (msg == PARTYCULIAR_POWER_COMMAND) { + string cmd = id; + if ( (find_substring(id, "on") == 0) + || (find_substring(id, "1") == 0) + || (find_substring(id, "true") == 0) ) { + // they want to crank the particle system up. + create_particle_system(); + randomize_timer(); + } else if ( (find_substring(id, "off") == 0) + || (find_substring(id, "0") == 0) + || (find_substring(id, "false") == 0) ) { + // the request is to shut the party down now. + llParticleSystem([]); + stop_timer(); + } + } +} + +////////////// +// from hufflets... + +////////////// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +////////////// + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// handles when blank strings need to come through the pipe. +string wrap_blank_string(string to_wrap) +{ + if (llStringLength(to_wrap)) return to_wrap; // that one is okay. + return "\"\""; // return a quoted nothing as a signal for a blank. +} + +// undoes a previously wrapped blank string. +string interpret_blank_string(string to_unwrap) +{ + if (to_unwrap == "\"\"") return ""; // that was an encoded blank. + return to_unwrap; // no encoding. +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, PARTYCULIAR_HUFFWARE_ID, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +////////////// + +// returns a number at most maximum and at least minimum. +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + initialize(); + if (start_enabled) { + create_particle_system(); + randomize_timer(); + } else { + llParticleSystem([]); + stop_timer(); + } + check_for_notecard(); + } + + timer() { + if (current_query_id != NULL_KEY) { + // there's been a failure of some sort; we were supposed to get a notecard to read. + llWhisper(0, "Failed to read the notecard, now restarting."); + llResetScript(); + } + create_particle_system(); + randomize_timer(); + } + + on_rez(integer parm) { + target_key = llGetKey(); // reset to get rid of weird wrong keys. + llResetScript(); + } + + link_message(integer sender, integer num, string msg, key id) { + handle_link_message(sender, num, msg, id); + } + + changed(integer change_type) { + if (change_type != CHANGED_INVENTORY) { + // we only care about inventory changes here. + return; + } + llResetScript(); + } + + dataserver(key query_id, string data) { + if (query_id != current_query_id) { +log_it("not our query id somehow? weird query had: id=" + (string)query_id + " data=" + (string)data); + // to heck with all this weirdness; if there's a failure, start over. + llResetScript(); + } + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + if (!line_number) { + if (data != "#party culiar") { + // this card has the wrong signature at the top. quit bothering + // with it now. + return; + } + log_it("starting to read notecard " + current_notecard_name + "..."); + } + if (data != "") { + // add the non-blank line to our destination list. + query_contents += data; +//log_it("line " + (string)line_number + ": data=" + data); + } + line_number++; // increase the line count. + // request the next line from the notecard. + current_query_id = llGetNotecardLine(current_notecard_name, line_number); + } else { + // no more data, so we're done with this card. + current_query_id = NULL_KEY; + if (!llGetListLength(query_contents)) { + // nothing was read? the heck with this card. + current_notecard_name = ""; // toss bad card. + return; + } +//log_it("notecard said:\n" + dump_list(query_contents)); + process_particle_settings(query_contents); + if (start_enabled) { + create_particle_system(); + randomize_timer(); + } else { + llParticleSystem([]); + stop_timer(); + } + log_it("done reading notecard " + current_notecard_name + "."); + } + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.lsl deleted file mode 100755 index 3efd92bf..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.lsl +++ /dev/null @@ -1,165 +0,0 @@ - -// huffware script: phantomizer, by fred huffhines -// -// turns the object that contains this into a phantom on the schedule specified below. -// note that this should not be done to physical objects or they will sink into whatever -// they were sitting on. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -float SECONDS_per_minute = 60.0; - -// variables... - -integer solid; // a boolean that represents our current solidity (TRUE=solid). - -// constant-ish functions. - -float solid_duration() // how long to be solid, in seconds. -{ return 4.20 * SECONDS_per_minute; } -float phantom_duration() // how long to be ghosty, in seconds. -{ return 14.0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - solid = FALSE; - llSetStatus(STATUS_PHANTOM, TRUE); -//llWhisper(0, "resetting and taking on phantom state."); - llSetTimerEvent(0); - llSetTimerEvent(phantom_duration()); - } - - timer() - { - if (solid) { - // we turn ethereal now. - solid = FALSE; -llWhisper(0, "becoming a phantom"); - llSetStatus(STATUS_PHANTOM, TRUE); - llSetTimerEvent(0); - llSetTimerEvent(phantom_duration()); - } else { - // time to solidify. - solid = TRUE; -llWhisper(0, "becoming solid"); - llSetStatus(STATUS_PHANTOM, FALSE); - llSetTimerEvent(0); - llSetTimerEvent(solid_duration()); - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.txt new file mode 100755 index 00000000..3efd92bf --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/phantomizer_v1.6.txt @@ -0,0 +1,165 @@ + +// huffware script: phantomizer, by fred huffhines +// +// turns the object that contains this into a phantom on the schedule specified below. +// note that this should not be done to physical objects or they will sink into whatever +// they were sitting on. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +float SECONDS_per_minute = 60.0; + +// variables... + +integer solid; // a boolean that represents our current solidity (TRUE=solid). + +// constant-ish functions. + +float solid_duration() // how long to be solid, in seconds. +{ return 4.20 * SECONDS_per_minute; } +float phantom_duration() // how long to be ghosty, in seconds. +{ return 14.0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + solid = FALSE; + llSetStatus(STATUS_PHANTOM, TRUE); +//llWhisper(0, "resetting and taking on phantom state."); + llSetTimerEvent(0); + llSetTimerEvent(phantom_duration()); + } + + timer() + { + if (solid) { + // we turn ethereal now. + solid = FALSE; +llWhisper(0, "becoming a phantom"); + llSetStatus(STATUS_PHANTOM, TRUE); + llSetTimerEvent(0); + llSetTimerEvent(phantom_duration()); + } else { + // time to solidify. + solid = TRUE; +llWhisper(0, "becoming solid"); + llSetStatus(STATUS_PHANTOM, FALSE); + llSetTimerEvent(0); + llSetTimerEvent(solid_duration()); + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.lsl deleted file mode 100755 index 99d575d0..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.lsl +++ /dev/null @@ -1,186 +0,0 @@ - -// huffware script: puffer, by fred huffhines -// -// causes the prim that this script is located in to enlarge periodically. this is -// mostly concerned with physical objects that are autonomous and can get stuck in -// prims as they move around. thus the script also tracks the current position and -// ensures that it keeps changing. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -vector NORMAL_SIZE = <1.0, 1.0, 0.04>; // normal size when we're not puffing. -vector PUFFED_SIZE = <1.0, 1.0, 1.0>; // size that we blow out to when puffing up. - -float PUFFING_PERIOD = 8.4; // number of seconds between puff-ups. -float STAY_PUFFED_TIME = 1.4; // number of seconds to remain puffed up. - -float PANIC_HOP_DISTANCE = 1.0; // meters to jump upwards if feeling stuck. -float MINIMAL_DISTANCE_OF_MOTION = 0.1; // must move at least this much to be considered unstuck. - -// variables... - -vector last_position; // tracks where the object is hanging out. - -// sets the object size to a new value. to do this, we need to turn off physics -// temporarily. -change_size(vector new_size) -{ - llSetStatus(STATUS_PHYSICS, FALSE); - llSetPrimitiveParams([PRIM_SIZE, new_size]); - llSetStatus(STATUS_PHYSICS, TRUE); -} - -// jumps upwards by a bit to try to escape fat prims we might get stuck inside of. -hop_up() -{ - llSetStatus(STATUS_PHYSICS, FALSE); - llSetPos(); - llSetStatus(STATUS_PHYSICS, TRUE); -} - -// this is our whole process for puffing out here. we will make sure to -// change size briefly for the puffing. we also track the last place we -// were at when puffing and if it's too close to our current position, -// then we'll jump up a bit. -emulate_puffer_fish() -{ - change_size(PUFFED_SIZE); - list siz = llGetPrimitiveParams([PRIM_SIZE]); -//llOwnerSay("size puffed=" + llList2String(siz, 0)); - llSleep(STAY_PUFFED_TIME); // snooze a bit. - change_size(NORMAL_SIZE); - siz = llGetPrimitiveParams([PRIM_SIZE]); -//llOwnerSay("size normal=" + llList2String(siz, 0)); - if (llVecDist(last_position, llGetPos()) < MINIMAL_DISTANCE_OF_MOTION) { - // we seem to be stuck, so hop up a bit and see if that helps. - hop_up(); - } - // reset our last position to where we are now. - last_position = llGetPos(); -} - -////////////// -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - last_position = llGetPos(); - change_size(NORMAL_SIZE); - llSetTimerEvent(PUFFING_PERIOD); // puff out this frequently. - } - - on_rez(integer parm) { llResetScript(); } - - timer() { emulate_puffer_fish(); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.txt new file mode 100755 index 00000000..99d575d0 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/puffer_v1.3.txt @@ -0,0 +1,186 @@ + +// huffware script: puffer, by fred huffhines +// +// causes the prim that this script is located in to enlarge periodically. this is +// mostly concerned with physical objects that are autonomous and can get stuck in +// prims as they move around. thus the script also tracks the current position and +// ensures that it keeps changing. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +vector NORMAL_SIZE = <1.0, 1.0, 0.04>; // normal size when we're not puffing. +vector PUFFED_SIZE = <1.0, 1.0, 1.0>; // size that we blow out to when puffing up. + +float PUFFING_PERIOD = 8.4; // number of seconds between puff-ups. +float STAY_PUFFED_TIME = 1.4; // number of seconds to remain puffed up. + +float PANIC_HOP_DISTANCE = 1.0; // meters to jump upwards if feeling stuck. +float MINIMAL_DISTANCE_OF_MOTION = 0.1; // must move at least this much to be considered unstuck. + +// variables... + +vector last_position; // tracks where the object is hanging out. + +// sets the object size to a new value. to do this, we need to turn off physics +// temporarily. +change_size(vector new_size) +{ + llSetStatus(STATUS_PHYSICS, FALSE); + llSetPrimitiveParams([PRIM_SIZE, new_size]); + llSetStatus(STATUS_PHYSICS, TRUE); +} + +// jumps upwards by a bit to try to escape fat prims we might get stuck inside of. +hop_up() +{ + llSetStatus(STATUS_PHYSICS, FALSE); + llSetPos(); + llSetStatus(STATUS_PHYSICS, TRUE); +} + +// this is our whole process for puffing out here. we will make sure to +// change size briefly for the puffing. we also track the last place we +// were at when puffing and if it's too close to our current position, +// then we'll jump up a bit. +emulate_puffer_fish() +{ + change_size(PUFFED_SIZE); + list siz = llGetPrimitiveParams([PRIM_SIZE]); +//llOwnerSay("size puffed=" + llList2String(siz, 0)); + llSleep(STAY_PUFFED_TIME); // snooze a bit. + change_size(NORMAL_SIZE); + siz = llGetPrimitiveParams([PRIM_SIZE]); +//llOwnerSay("size normal=" + llList2String(siz, 0)); + if (llVecDist(last_position, llGetPos()) < MINIMAL_DISTANCE_OF_MOTION) { + // we seem to be stuck, so hop up a bit and see if that helps. + hop_up(); + } + // reset our last position to where we are now. + last_position = llGetPos(); +} + +////////////// +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + last_position = llGetPos(); + change_size(NORMAL_SIZE); + llSetTimerEvent(PUFFING_PERIOD); // puff out this frequently. + } + + on_rez(integer parm) { llResetScript(); } + + timer() { emulate_puffer_fish(); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.lsl deleted file mode 100755 index 406a998c..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.lsl +++ /dev/null @@ -1,174 +0,0 @@ - -// huffware script: radio tuner, by fred huffhines -// -// a radio tuner with capability for overriding the channel. -// this is useful if you want it to stay tuned on a particular channel. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer force_channel = 0; // set to non-zero to force the channel to stay set. -integer channel_stays_on = 69; // the channel that the radio will stay stuck on when forced. - -integer listen_handle = 0; -integer channel = 0; - -//hmmm: really broken implementation. -// need to support multiple channels. -set_radio_channel(integer chan) -{ - channel = chan; - - if (listen_handle) - llListenRemove(listen_handle); - - if (!chan) - { - listen_handle = 0; - llOwnerSay("Radio turned off."); - return; - } - - listen_handle = llListen(chan, "", NULL_KEY, ""); - llOwnerSay("Listening to channel " + (string)chan); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); -//hmmm: logic broken here. subscribe to a default set. let them add and remove from set. - if (!force_channel) { -//hmmm: terrible defaults treatment. - llListen(96, "", llGetOwner(), ""); - llOwnerSay("Type \"/96 tune N\" to tune in to channel N, or \"/96 tune 0\" to turn radio off."); - } else { - llOwnerSay("Channel locked on " + (string)channel_stays_on + "."); - set_radio_channel(channel_stays_on); - } - } - - attach(key attached) - { - if (attached != NULL_KEY) - llResetScript(); - } - - listen(integer ch, string name, key id, string msg) - { - if (!force_channel && ((ch == 96) && llGetSubString(msg, 0, 4) == "tune ") ) - set_radio_channel((integer)llGetSubString(msg, 5, -1)); - else if (ch == channel) - llOwnerSay("[" + (string)ch + " " + name + "]: " + msg); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.txt new file mode 100755 index 00000000..406a998c --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/radio_tuner_v1.2.txt @@ -0,0 +1,174 @@ + +// huffware script: radio tuner, by fred huffhines +// +// a radio tuner with capability for overriding the channel. +// this is useful if you want it to stay tuned on a particular channel. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer force_channel = 0; // set to non-zero to force the channel to stay set. +integer channel_stays_on = 69; // the channel that the radio will stay stuck on when forced. + +integer listen_handle = 0; +integer channel = 0; + +//hmmm: really broken implementation. +// need to support multiple channels. +set_radio_channel(integer chan) +{ + channel = chan; + + if (listen_handle) + llListenRemove(listen_handle); + + if (!chan) + { + listen_handle = 0; + llOwnerSay("Radio turned off."); + return; + } + + listen_handle = llListen(chan, "", NULL_KEY, ""); + llOwnerSay("Listening to channel " + (string)chan); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); +//hmmm: logic broken here. subscribe to a default set. let them add and remove from set. + if (!force_channel) { +//hmmm: terrible defaults treatment. + llListen(96, "", llGetOwner(), ""); + llOwnerSay("Type \"/96 tune N\" to tune in to channel N, or \"/96 tune 0\" to turn radio off."); + } else { + llOwnerSay("Channel locked on " + (string)channel_stays_on + "."); + set_radio_channel(channel_stays_on); + } + } + + attach(key attached) + { + if (attached != NULL_KEY) + llResetScript(); + } + + listen(integer ch, string name, key id, string msg) + { + if (!force_channel && ((ch == 96) && llGetSubString(msg, 0, 4) == "tune ") ) + set_radio_channel((integer)llGetSubString(msg, 5, -1)); + else if (ch == channel) + llOwnerSay("[" + (string)ch + " " + name + "]: " + msg); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.lsl deleted file mode 100755 index 0e162579..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.lsl +++ /dev/null @@ -1,1061 +0,0 @@ - -// huffware script: rezzeroni, by fred huffhines -// -// a script that rezzes objects for you according to some game plan, which is defined -// in a notecard. this script can also run periodically to create temporary objects -// on a schedule. the real power of this script comes from its ability to rez up a -// collection of objects using relative positioning. the newly rezzed objects can be -// given a startup notecard also, which is held inside the rezzer. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// * note regarding the periodic rezzing capability: the objects that are created -// really need to be marked as temporary objects. otherwise the newly rezzed -// objects will clutter up the sim, flooding it with objects, and will eventually -// go over the owner's prim limit. that's not cool. so if you use a periodic -// rezzer, make sure your contained objects are temporaries. - -// global constants... - -integer DEBUGGING = FALSE; // produces noisy diagnostics if enabled. - -integer SUPER_NOISY_DEBUG = FALSE; // extraordinarily noisy items are logged. - -float HOME_PROXIMITY = 0.1; // object must be this close to home before we quit. - -integer PERFORM_JAUNTS = TRUE; // set to true if rezzer should teleport to rez locations. - -integer OBJECT_STARTUP_PARM = 14042; -//hmmm: may want this to come from notecard someday. - -// notecard configurable variables: -integer owner_only; // is the owner the only one allowed to run this rezzer? -vector obj_position; // absolute position for object to rez at. -integer obj_is_singleton; // should the object not be rezzed if similar named one exists? -//hmmm: support configurable singleton sensor range? -integer rezzed_at_once; // the number of each object that are rezzed at the same time. -float obj_rezzing_period; // how often the objects are rezzed up, in seconds. -integer max_run_time; // how long to run once enabled, in seconds. 1200=20 minutes. -string gift_card_name; // a gift object placed inside newly rezzed object. -vector obj_max_offset_add = <2.0, 2.0, 2.0>; // random offsets can be this large. -vector obj_max_rotation_add = ; // max random rotation. -// these object variables can be randomized. "random" means pick a random item. -string obj_name; // what is the object called? "ALL" means all items. -string obj_offset; // how far away from current position object rezzes. -string obj_rotation; // euler rotation for object to point at upon rez. -string obj_multi_offset; // the amount to add to the offset each time for count > 1. -string obj_multi_angle; // the angle added to each rez. -//hmmm: also allow position to be random? -integer DIE_ON_DEMAND_CHANNEL = 4826; // default, can be loaded from notecard. - -// assorted global variables... -integer is_enabled_now; // records whether the rezzer is running a plan right now. -integer when_last_enabled; // tracks time when device was turned on. -// notecard globals. -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -// globals tracking the current rezzing run. -list already_done_items; // the items that are finished being rezzed, since they have no rate. -integer rezzed_overall; // a count of the number of rezzes during this run. -list gift_stack; // a stack of items to hand to newly rezzed objects. -// somewhat ugly rez plan globals. -integer global_config_index; // where are we in the config list? -string global_singleton_checker; // is a singleton object being sensor checked? -integer global_found_the_singleton; // did we see the singleton object requested? -integer sensor_checks_pending; // how many sensor scans are awaited (zero or one). -integer recent_items_rezzed; // how many got rezzed in last run? -// object creation loop vars: -integer current_object_index = 0; // which object are we at, in the current section? -integer current_count; // the number already created of the current object. - -vector main_home; - // the home location for the rezzer object. it will return to this after - // performing the requested rezzes. -rotation main_rotate; - // original rotation of the rezzer object. - -integer jaunt_responses_awaited; - // the number of jumps still pending. should never be more than one in this script. - -// constants that should generally not be modified unless you are an expert... - -string REZZERONI_SIGNATURE = "#rezzeroni"; // the expected first line of our notecards. - -float MAXIMUM_REZ_DISTANCE = 9.9; - // the farthest distance that we can rez an object at reliably. if the distance is - // larger than this, then the rezzer will teleport to the work zone. - -float BASE_TIMER_PERIOD = 0.04; // the rate at which the timer runs to rez objects. - -// requires noteworthy library v9.3 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the noteworthy library: -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// looks for a notecard with our signature in it and reads the configuration. -// an empty string is returned if we couldn't find anything. -request_configuration() -{ - global_notecard_name = ""; - response_code = 0; - - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([REZZERONI_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from support libraries. -integer handle_link_message(integer which, integer num, string msg, key id) -{ - list parms; - if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { - // did we get a response to a teleport request? - if (msg == JAUNT_LIST_COMMAND) { -//log_it("msg: " + (string)num + " str=" + str); - jaunt_responses_awaited--; // one less response being awaited. - if (jaunt_responses_awaited < 0) { - log_it("error, jaunts awaited < 0!"); - jaunt_responses_awaited = 0; - } - // unpack the reply. - parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer last_jaunt_was_success = llList2Integer(parms, 0); - vector posn = (vector)llList2String(parms, 1); - //log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); - //do anything with the parms? - } - return FALSE; - } - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) return FALSE; // not for us. - - // process the result of reading the notecard. - parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return FALSE; // oops, this isn't for us. - // make sure if we are being told to keep going. - if (notecard_name == NOTECARD_READ_CONTINUATION) { -//log_it("continuation of notecard seen."); - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - // we're not done reading yet, so fall out to the false return. - } else if (notecard_name != "bad_notecard") { - // a valid notecard has been found and we're done with it now. - global_notecard_name = notecard_name; - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - global_config_index = 0; - // signal that we're done getting the config. - return TRUE; - } else { - // we hated the notecards we found, or there were none. - log_it("sorry, no notecards starting with '" - + REZZERONI_SIGNATURE - + "'; cannot rez yet."); - } - return FALSE; -} - -/////////////// - -// requires jaunting library v10.5 or greater. -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a list of vectors as the first parameter; this list - // should be in the jaunter notecard format (separated by pipe characters). - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// -// encases a list of vectors in the expected character for the jaunting library. -string wrap_vector_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -////////////// - -// asks the jaunting library to take us to the target using a list of waypoints. -request_jaunt(list full_journey, integer forwards) -{ - if (PERFORM_JAUNTS) { - jaunt_responses_awaited++; - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, - wrap_vector_list(full_journey) - + HUFFWARE_PARM_SEPARATOR + (string)forwards); - } -} - -// jaunts back to our home location. -attempt_to_go_home() -{ - // jump back to home. - request_jaunt([llGetPos(), main_home], TRUE); -} - -/////////////// - -// creates the real list of items to rez based on the obj_name variable. -// this might turn out to be an empty list. -list build_rezzing_list() -{ - list objects_to_rez; // what items are we expected to create in this round? - - integer num_inv = llGetInventoryNumber(INVENTORY_OBJECT); - if (num_inv == 0) { - log_it("Inventory is empty; please add objects to rez."); - llSetTimerEvent(0.0); // stop the timer; nothing further to do. - return []; - } -//hmmm: all has never been tested. - if (obj_name == "ALL") { - integer inv; - for (inv = 0; inv < num_inv; inv++) { - objects_to_rez += [ llGetInventoryName(INVENTORY_OBJECT, inv) ]; - } - obj_is_singleton = FALSE; // flag makes no sense for multiple objects. - } else { - // we know we are not being told to do a multiple set of objects. - if (obj_name == "random") { - // special keyword for a random object. - integer inv = (integer)randomize_within_range(0.0, num_inv, FALSE); - obj_name = llGetInventoryName(INVENTORY_OBJECT, inv); - if (SUPER_NOISY_DEBUG) - log_it("chose item #" + (string)inv + " randomly (called '" + obj_name + "')."); - } else { - // a normal singular object to create. - if (find_in_inventory(obj_name, INVENTORY_OBJECT) < 0) { - // this item is bogus! - log_it("item '" + obj_name + "' is bogus! not in inventory."); - obj_name = ""; // reset it. - } - } - // now make sure we didn't already do this one. - if (find_in_list(already_done_items, obj_name) >= 0) { -// if (SUPER_NOISY_DEBUG) -// log_it("item '" + obj_name + "' has already been rezzed. skipping it."); - obj_name = ""; - } else { - if (obj_name != "") objects_to_rez += [ obj_name ]; - } - } - - return objects_to_rez; -} - -// checks whether the object is even supposed to be a singleton or not. -// if it should be a singleton, then we run a sensor ping to see if it exists in the -// vicinity or not. if it's not there, we'll eventually hear about it and create it. -integer validate_singleton_object() -{ - // see if there's only supposed to be one of these objects. - if (!obj_is_singleton) return TRUE; // just keep going; it's not one. - if (obj_name == "") return TRUE; // this should never happen. pretend it's okay. - - // okay, we know we should have a singleton. now did we already check for its presence? - if (global_singleton_checker == "") { - // have not scanned yet; postpone the rezzing action and start a sensor for the object. - sensor_checks_pending++; - global_singleton_checker = obj_name; - // maximally distant ping in full arc on all types of objects we can see. - llSensor(obj_name, NULL_KEY, AGENT|ACTIVE|PASSIVE, 96, PI); - if (DEBUGGING) log_it("scanning for singleton item '" + obj_name + "' now."); - return FALSE; - } else { - // we should have finished a sensor probe now, since there were no checks pending - // and since this is a singleton. - if (global_found_the_singleton) { - if (DEBUGGING) - log_it("singleton item '" + obj_name + "' already present; not re-rezzing."); - already_done_items += [ obj_name ]; -//if (TERMINATE_IF_PRESENT) -string DIE_ON_DEMAND_MESSAGE = "die-on-demand"; -llShout(DIE_ON_DEMAND_CHANNEL, DIE_ON_DEMAND_MESSAGE); - } else { - if (DEBUGGING) - log_it("singleton item '" + obj_name + "' is absent; will rez one now if possible."); - } - return TRUE; - } -} - -// operates on the current parameters to rez an object or objects. -integer perform_rezzing_action() -{ - vector current_home = llGetPos(); - list objects_to_rez = build_rezzing_list(); -//log_it("rezzing " + (string)llGetListLength(objects_to_rez) + " objects"); - // create the specified number of the items we were told to use. - integer num_objects = llGetListLength(objects_to_rez); - if (num_objects == 0) { - // nothing to do at this point. -// if (SUPER_NOISY_DEBUG) log_it("no items in rez list; bailing out."); - return TRUE; - } - // iterate across each object in inventory. - integer inv; - for (inv= current_object_index; inv < num_objects; inv++) { -//log_it("object index " + (string)inv); - // rez as many of the object as we were requested to. - string new_rezzee = llList2String(objects_to_rez, inv); - integer counter; - for (counter = current_count; counter < rezzed_at_once; counter++) { - // make sure we've never rezzed a non-periodic with this name before. - if (find_in_list(already_done_items, new_rezzee) < 0) { -///log_it("haven't rezzed '" + new_rezzee + "' yet."); - vector rez_place = obj_position; -//log_it("configd rezplace=" + (string)rez_place); - if (rez_place == <0.0, 0.0, 0.0>) { - // they did not give us an absolute position, so use the home position. - rez_place = main_home; -//log_it("rehomed rezplace=" + (string)rez_place); - } - vector calc_offset = maybe_randomize_offset(obj_offset, obj_max_offset_add); - if (calc_offset != <0.0, 0.0, 0.0>) { - // the offset is non-zero, so apply it to the rez place. - rez_place += calc_offset * main_rotate; -//log_it("offsetd rezplace=" + (string)rez_place); - } - // add in the multiplier offset if this is not the first rezzing of this item. - rez_place += ((float)counter) - * maybe_randomize_offset(obj_multi_offset, obj_max_offset_add) - * main_rotate; -//log_it("home=" + (string)main_home + " rezplace=" + (string)rez_place); - - // check that we are not too far away. - float rez_distance = llVecDist(rez_place, llGetPos()); - if (rez_distance > MAXIMUM_REZ_DISTANCE) { - // try to jump there if we're too far away to rez from here. - if (DEBUGGING) - log_it("distance is " + (string)rez_distance - + "; jaunting closer."); - request_jaunt([llGetPos(), rez_place], TRUE); - current_count = counter; - current_object_index = inv; - return FALSE; - } - - // make sure we aren't already done with this object, if it's a singleton. - integer keep_going = validate_singleton_object(); - if (!keep_going) { - if (SUPER_NOISY_DEBUG) log_it("must sense for singleton, bailing."); - current_count = counter; - current_object_index = inv; - return FALSE; // we can't proceed yet. must check for singleton. - } - -//hmmm: we need to offer an angular offset also! -// this would mean that the multiple guys could be set at nice different angles. - - // now check again whether to rez this or not; the validation method adds it to the - // done list if the object is already present and is a singleton. - if (find_in_list(already_done_items, new_rezzee) < 0) { - if (DEBUGGING) - log_it("now rezzing '" + new_rezzee + "', rot " + obj_rotation); - vector rota = maybe_randomize_rotation(obj_rotation, obj_max_rotation_add); - rotation real_rot = llEuler2Rot(rota * DEG_TO_RAD); - -//hmmm: might be nice to offer an absolute version! -// that accounts for the specific position and offset, rather -// than relative to rezzer. angle should be kept absolutist also. - - // add in our rotation component as the rezzer. - real_rot *= main_rotate; -//this is bunkum. - // add in the angular addition for multiple object creation. - real_rot *= llEuler2Rot( - maybe_randomize_rotation(obj_multi_angle, obj_max_rotation_add) - * (float)counter * DEG_TO_RAD); - recent_items_rezzed++; // we got to do something. - // rez it up since we know what is wanted and where, plus we're in range. - llRezObject(new_rezzee, rez_place, ZERO_VECTOR, real_rot, OBJECT_STARTUP_PARM); - rezzed_overall++; // one more item. - if (gift_card_name != "") { - // this guy needs its startup gift. - string inv_name = gift_card_name + (string)rezzed_overall; - if (find_in_inventory(inv_name, INVENTORY_NOTECARD) >= 0) { - // this inventory item exists, so use it. - gift_stack += [ inv_name]; - } - } - global_singleton_checker = ""; // reset singleton checker for next object. - } else { - if (SUPER_NOISY_DEBUG) log_it("not rezzing, already saw it in list"); - } - } - } - current_count = 0; // got to the full count for the object. - // if this is a non-periodic object, we don't need any more runs. - if (obj_rezzing_period == 0.0) { - if (find_in_list(already_done_items, new_rezzee) < 0) { - if (SUPER_NOISY_DEBUG) log_it("adding newly done: " + (string)new_rezzee); - already_done_items += [ new_rezzee ]; - } - } - } - current_object_index = 0; // reset the current object index. - - return TRUE; -} - -/////////////// - -// returns true if the state should change. -integer handle_timer() -{ - // make sure we run at the fast rate; we'll reset the rate elsewhere if needed. - llSetTimerEvent(BASE_TIMER_PERIOD); - - if (!is_enabled_now) { - if (jaunt_responses_awaited > 0) { - if (SUPER_NOISY_DEBUG) log_it("done rez, but jaunts awaited."); - return FALSE; - } - if (llVecDist(llGetPos(), main_home) > HOME_PROXIMITY) { - if (SUPER_NOISY_DEBUG) log_it("done rez, but not at home."); - attempt_to_go_home(); - return FALSE; - } - if (llGetListLength(gift_stack)) { - if (SUPER_NOISY_DEBUG) log_it("done rez, but still pending gifts."); - return FALSE; - } - if (SUPER_NOISY_DEBUG) log_it("done rez, totally done."); - llSetTimerEvent(0.0); - return TRUE; - } - - // check whether the max run time has elapsed. - integer run_time = llAbs(llGetUnixTime() - when_last_enabled); - if (run_time > max_run_time) { - log_it("Maximum run time elapsed; shutting down."); - is_enabled_now = FALSE; - llSetTimerEvent(0.0); - return TRUE; - } - - // we have not gotten a configuration yet. - if (global_notecard_name == "") { -/// if (SUPER_NOISY_DEBUG) log_it("in timer with no notecard???"); - return FALSE; - } - - // crank to next step in config. - if (!run_through_rez_plan()) { -//log_it("told done with rez plan"); - // we were told not to keep going. if this is a periodic run, - // then we'll snooze until the next time. - if (obj_rezzing_period != 0.0) { - llSetTimerEvent(obj_rezzing_period); - finished_file = FALSE; - } - } - // even if the run were done, we still have to handle termination conditions. - return FALSE; -} - -// processes requests made by avatars via chat. -integer handle_hearing_voices(integer channel, string name, key id, string message) -{ - string rez_command = "#rez"; - // is this our command prefix? - if (is_prefix(message, rez_command)) { - // we found a command. which specific one? - string parm = llDeleteSubString(message, 0, llStringLength(rez_command)); - // eat the command portion, plus a space. - if ( (parm == "on") && !is_enabled_now) { - is_enabled_now = TRUE; - return TRUE; - } else if ( (parm == "off") && is_enabled_now) { - is_enabled_now = FALSE; - return TRUE; - } - } - return FALSE; -} - -// a helper function that turns the word "random" into a random value. -// we will never allow a negative z value for the random amount, since that will often be -// wrong (rezzing underneath where the object lives, e.g.). this implies always -// putting the rezzer below where one wants to see the random rezzing action. -vector maybe_randomize_offset(string vector_or_not, vector largest_add) -{ - if (vector_or_not == "random") { - vector just_xy = ; - vector just_z = <0.0, 0.0, largest_add.z>; - vector to_return = random_bound_vector(<0.0, 0.0, 0.0>, just_xy, TRUE) - + random_bound_vector(<0.0, 0.0, 0.0>, just_z, FALSE); -//log_it("calc rand off: " + (string)to_return); - return to_return; - } else { - return (vector)vector_or_not; - } -} - -vector maybe_randomize_rotation(string vector_or_not, vector largest_add) -{ - if (vector_or_not == "random") { - vector to_return = random_bound_vector(<0.0, 0.0, 0.0>, largest_add, TRUE); -//log_it("calc rand rot: " + (string)to_return); - return to_return; - } else { - return (vector)vector_or_not; - } -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// consumes the notecard in a very application specific way -// to retrieve the configurations for the items to rez. -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - - if ( (content = get_variable_value(to_parse, "name")) != "") - obj_name = content; - else if ( (content = get_variable_value(to_parse, "position")) != "") - obj_position = (vector)content; - else if ( (content = get_variable_value(to_parse, "offset")) != "") - obj_offset = content; - else if ( (content = get_variable_value(to_parse, "rotation")) != "") - obj_rotation = content; - else if ( (content = get_variable_value(to_parse, "multi_offset")) != "") - obj_multi_offset = content; - else if ( (content = get_variable_value(to_parse, "multi_angle")) != "") - obj_multi_angle = content; - else if ( (content = get_variable_value(to_parse, "singleton")) != "") - obj_is_singleton = (integer)content; - else if ( (content = get_variable_value(to_parse, "count")) != "") - rezzed_at_once = (integer)content; - else if ( (content = get_variable_value(to_parse, "rate")) != "") - obj_rezzing_period = (float)content; - else if ( (content = get_variable_value(to_parse, "max_run")) != "") - max_run_time = (integer)content; - else if ( (content = get_variable_value(to_parse, "gift")) != "") - gift_card_name = content; - else if ( (content = get_variable_value(to_parse, "maxrandoff")) != "") - obj_max_offset_add = (vector)content; - else if ( (content = get_variable_value(to_parse, "maxrandrot")) != "") - obj_max_rotation_add = (vector)content; - else if ( (content = get_variable_value(to_parse, "owner_only")) != "") - owner_only = (integer)content; - else if ( (content = get_variable_value(to_parse, "die_channel")) != "") - DIE_ON_DEMAND_CHANNEL = (integer)content; - else if ( (content = get_variable_value(to_parse, "perform_jaunts")) != "") - PERFORM_JAUNTS = (integer)content; -} - -// examines the configuration to find one section of rezzable plan. -// returns TRUE when the entire config has been consumed. -integer read_one_section() -{ - integer count = llGetListLength(global_config_list); - if (global_config_index >= count) return TRUE; // all done. - integer sec_indy = global_config_index; - string line = llList2String(global_config_list, sec_indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - reset_variables_to_defaults(); // clean out former thoughts. - if (SUPER_NOISY_DEBUG) - log_it("reading section: " + llGetSubString(line, 1, -2)); - // iterate across the items in current config section. - // initializer skips line we just read. - for (sec_indy++; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. - parse_variable_definition(line); - } else { - // done chowing on defs, so break out. - global_config_index = sec_indy; - // if the index is past the end, we're all done. - return global_config_index >= count; - } - } - global_config_index = sec_indy; - if (SUPER_NOISY_DEBUG) log_it("read_one_section finished file, post loop."); - return TRUE; // at end of list. - } else { - if ( (line != "") && !is_prefix(line, "#") ) { - if (SUPER_NOISY_DEBUG) log_it("skipping gibberish: " + line); - global_config_index++; - return FALSE; // not done yet. - } - } - - if (SUPER_NOISY_DEBUG) log_it("read_one_section finished file, bottom bailout."); - return TRUE; -} - -// resets our variables to the default parameters. -reset_variables_to_defaults() -{ - obj_name = ""; - obj_offset = "<0.0, 0.0, 0.0>"; - obj_position = <0.0, 0.0, 0.0>; - obj_rotation = "<0.0, 0.0, 0.0>"; - obj_is_singleton = FALSE; - obj_multi_offset = "<0.0, 0.0, 0.0>"; - obj_multi_angle = "<0.0, 0.0, 0.0>"; - rezzed_at_once = 1; - obj_rezzing_period = 0.0; - max_run_time = 1200; - gift_card_name = ""; - owner_only = FALSE; -} - -integer completed_previous_section; // had the last section finished processing? - -integer finished_file = FALSE; // has the config file been consumed? - -// returns TRUE while it should continue to be called at the normal rate. -integer run_through_rez_plan() -{ - if (jaunt_responses_awaited > 0) return TRUE; // not ready yet. - if (sensor_checks_pending > 0) return TRUE; // not ready yet. - - if (completed_previous_section) { -// if (SUPER_NOISY_DEBUG) log_it("decided to read config, prev sec complete now..."); - // read in the next section of config. - finished_file = read_one_section(); - // reset the current counters of rezzed items for the section. - current_count = 0; - current_object_index = 0; - recent_items_rezzed = 0; - already_done_items = []; - } - // now fire off the rez before we start the next section. - integer worked = perform_rezzing_action(); - if (!worked) { - // we can't keep going; there needs to be a pause. -// if (SUPER_NOISY_DEBUG) log_it("still working on previous section."); - completed_previous_section = FALSE; - return TRUE; - } else { -// if (SUPER_NOISY_DEBUG) log_it("completed running previous section."); - completed_previous_section = TRUE; - } - - // check whether we rezzed anything at all, and if we're done. - if (finished_file) { -//log_it("seeing file as finished"); - if (obj_rezzing_period == 0.0) { - // this one is not periodic, so we finish out its cycle. - if (DEBUGGING) log_it("shutting down rezzer; no objects left to create."); - is_enabled_now = FALSE; - } - global_config_index = 0; // reset reading position for config. - attempt_to_go_home(); // try to go home after the run. - // periodic plans will just cause a snooze now. - return FALSE; - } - return TRUE; -} - -// resets all our variables and starts reading the rez plan. -crank_rezzer_up() -{ - is_enabled_now = TRUE; // turn the device on. - - main_home = llGetPos(); // set our home location now. - main_rotate = llGetRot(); // set our home rotation also. - when_last_enabled = llGetUnixTime(); // restart the run counter. - global_config_list = []; // no config yet. - global_singleton_checker = ""; // we are not working on a sensor check for anything. - sensor_checks_pending = 0; // no sensors are awaited. - recent_items_rezzed = 0; // nothing rezzed recently. - jaunt_responses_awaited = 0; // no jumps in progress. - rezzed_overall = 0; // nothing has been rezzed yet. - gift_stack = []; // no gifts waiting yet. - - request_configuration(); // try to find a notecard and read our config. - - // announce that we're open for business. - if (DEBUGGING) log_it("rezzer started... [free mem=" + (string)llGetFreeMemory() + "]"); -} - -////////////// -// from hufflets... -// -integer debug_num = 0; - -// in the case of rezzeroni, we want to say things out loud for anyone -// to hear, since often the script is open to access by anyone. -// when debugging, we want to say to the owner also, so that problems can be removed. - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - if (!SUPER_NOISY_DEBUG) { - // say this on open chat. - llSay(0, "[" + (string)debug_num + "] " + to_say); - } else { - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - } -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - // clean initial spaces. - while (llGetSubString(to_check, 0, 0) == " ") - to_check = llDeleteSubString(to_check, 0, 0); - if (!is_prefix(to_check, variable_name)) return ""; - to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); - // clean any spaces or valid assignment characters. - while ( (llGetSubString(to_check, 0, 0) == " ") - || (llGetSubString(to_check, 0, 0) == "=") - || (llGetSubString(to_check, 0, 0) == ",") ) - to_check = llDeleteSubString(to_check, 0, 0); -//still too noisy... -// if (SUPER_NOISY_DEBUG) -// log_it("set '" + variable_name + "' = '" + to_check + "'"); - string chewed_content = to_check; -//this is patching in CR. shouldn't that be separate? - integer indy; - for (indy = 0; indy < llStringLength(chewed_content); indy++) { - if (llGetSubString(chewed_content, indy, indy) == "\\") { - if (llGetSubString(chewed_content, indy+1, indy+1) == "n") { - chewed_content = llGetSubString(chewed_content, 0, indy - 1) - + "\n" - + llGetSubString(chewed_content, indy + 2, - llStringLength(chewed_content) - 1); - } - } - } - // return what's left of the string. - return chewed_content; -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets -////////////// - -integer trigger_stop_message = FALSE; - // a simple logging switch; first time in to awaiting commands, - // we do not want to say a run ended. but every time after that, - // we do want to. - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - if (DEBUGGING) log_it(""); - // we immediately jump into the command handling state. - // this state is really only for cleaning up older scripts with the auto-upgrade. - state awaiting_commands; - } -} - -state awaiting_commands -{ - state_entry() { - if (DEBUGGING) log_it(""); - llSetTimerEvent(0.0); - if (trigger_stop_message) - if (DEBUGGING) log_it("rezzer finished. [free mem=" + (string)llGetFreeMemory() + "]"); - trigger_stop_message = TRUE; // always say it next time. - reset_variables_to_defaults(); // clean out any old notes. - llListen(0, "", NULL_KEY, ""); - } - - touch_start(integer count) { - // see if we're blocking others right now. - if (owner_only && (llDetectedKey(0) != llGetOwner())) return; - state reading_rez_plan; - } - - // is someone speaking to the object? - listen(integer channel, string name, key id, string message) { - if (owner_only && (llDetectedKey(0) != llGetOwner())) return; - if (handle_hearing_voices(channel, name, id, message)) state reading_rez_plan; - } -} - -state reading_rez_plan -{ - state_entry() { - if (DEBUGGING) log_it(""); - is_enabled_now = FALSE; - -// // we reset this list only here, since during periodic we'll keep resetting all -// // our other variables. this status must persist between runs though. -// already_done_items = []; // nothing's been done yet. - - // reset our state so the rez plan will start being read. - completed_previous_section = TRUE; - finished_file = FALSE; - - // get the timer cranking so we can process the configuration. - crank_rezzer_up(); - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { - if (handle_link_message(which, num, msg, id)) - state running_rez_plan; - } - - touch_start(integer count) {} // do nothing in this state, but keep touch event alive. - -} - -state running_rez_plan -{ - state_entry() { - if (DEBUGGING) log_it(""); - llListen(0, "", NULL_KEY, ""); - llSetTimerEvent(BASE_TIMER_PERIOD); - } - - state_exit() { llSetTimerEvent(0); } - - // we got clicked. - touch_start(integer count) { - if (owner_only && (llDetectedKey(0) != llGetOwner())) return; - // disable the rezzing process. - is_enabled_now = FALSE; - llSetTimerEvent(BASE_TIMER_PERIOD); - // now we must allow the timer to handle the return process. - } - - // is someone speaking to the object? - listen(integer channel, string name, key id, string message) { - if (owner_only && (llDetectedKey(0) != llGetOwner())) return; - if (handle_hearing_voices(channel, name, id, message)) is_enabled_now = FALSE; - llSetTimerEvent(BASE_TIMER_PERIOD); - } - - timer() { - if (handle_timer()) state awaiting_commands; - } - - object_rez(key id) { - if (SUPER_NOISY_DEBUG) log_it("heard object rez: id=" + (string)id); - if (!llGetListLength(gift_stack)) return; // no gifts to hand out. - string new_gift = llList2String(gift_stack, 0); - gift_stack = llDeleteSubList(gift_stack, 0, 0); - if (find_in_inventory(new_gift, INVENTORY_NOTECARD) < 0) { - // missing the present. this seems remarkable. - log_it("could not find gift specified: " + new_gift); - return; - } - llGiveInventory(id, new_gift); - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - // a sensor result came in--process either no match or the match. - no_sensor() { global_found_the_singleton = FALSE; sensor_checks_pending--; } - sensor(integer num_detected) { global_found_the_singleton = TRUE; sensor_checks_pending--; } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.txt new file mode 100755 index 00000000..0e162579 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/rezzeroni_v20.2.txt @@ -0,0 +1,1061 @@ + +// huffware script: rezzeroni, by fred huffhines +// +// a script that rezzes objects for you according to some game plan, which is defined +// in a notecard. this script can also run periodically to create temporary objects +// on a schedule. the real power of this script comes from its ability to rez up a +// collection of objects using relative positioning. the newly rezzed objects can be +// given a startup notecard also, which is held inside the rezzer. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// * note regarding the periodic rezzing capability: the objects that are created +// really need to be marked as temporary objects. otherwise the newly rezzed +// objects will clutter up the sim, flooding it with objects, and will eventually +// go over the owner's prim limit. that's not cool. so if you use a periodic +// rezzer, make sure your contained objects are temporaries. + +// global constants... + +integer DEBUGGING = FALSE; // produces noisy diagnostics if enabled. + +integer SUPER_NOISY_DEBUG = FALSE; // extraordinarily noisy items are logged. + +float HOME_PROXIMITY = 0.1; // object must be this close to home before we quit. + +integer PERFORM_JAUNTS = TRUE; // set to true if rezzer should teleport to rez locations. + +integer OBJECT_STARTUP_PARM = 14042; +//hmmm: may want this to come from notecard someday. + +// notecard configurable variables: +integer owner_only; // is the owner the only one allowed to run this rezzer? +vector obj_position; // absolute position for object to rez at. +integer obj_is_singleton; // should the object not be rezzed if similar named one exists? +//hmmm: support configurable singleton sensor range? +integer rezzed_at_once; // the number of each object that are rezzed at the same time. +float obj_rezzing_period; // how often the objects are rezzed up, in seconds. +integer max_run_time; // how long to run once enabled, in seconds. 1200=20 minutes. +string gift_card_name; // a gift object placed inside newly rezzed object. +vector obj_max_offset_add = <2.0, 2.0, 2.0>; // random offsets can be this large. +vector obj_max_rotation_add = ; // max random rotation. +// these object variables can be randomized. "random" means pick a random item. +string obj_name; // what is the object called? "ALL" means all items. +string obj_offset; // how far away from current position object rezzes. +string obj_rotation; // euler rotation for object to point at upon rez. +string obj_multi_offset; // the amount to add to the offset each time for count > 1. +string obj_multi_angle; // the angle added to each rez. +//hmmm: also allow position to be random? +integer DIE_ON_DEMAND_CHANNEL = 4826; // default, can be loaded from notecard. + +// assorted global variables... +integer is_enabled_now; // records whether the rezzer is running a plan right now. +integer when_last_enabled; // tracks time when device was turned on. +// notecard globals. +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +// globals tracking the current rezzing run. +list already_done_items; // the items that are finished being rezzed, since they have no rate. +integer rezzed_overall; // a count of the number of rezzes during this run. +list gift_stack; // a stack of items to hand to newly rezzed objects. +// somewhat ugly rez plan globals. +integer global_config_index; // where are we in the config list? +string global_singleton_checker; // is a singleton object being sensor checked? +integer global_found_the_singleton; // did we see the singleton object requested? +integer sensor_checks_pending; // how many sensor scans are awaited (zero or one). +integer recent_items_rezzed; // how many got rezzed in last run? +// object creation loop vars: +integer current_object_index = 0; // which object are we at, in the current section? +integer current_count; // the number already created of the current object. + +vector main_home; + // the home location for the rezzer object. it will return to this after + // performing the requested rezzes. +rotation main_rotate; + // original rotation of the rezzer object. + +integer jaunt_responses_awaited; + // the number of jumps still pending. should never be more than one in this script. + +// constants that should generally not be modified unless you are an expert... + +string REZZERONI_SIGNATURE = "#rezzeroni"; // the expected first line of our notecards. + +float MAXIMUM_REZ_DISTANCE = 9.9; + // the farthest distance that we can rez an object at reliably. if the distance is + // larger than this, then the rezzer will teleport to the work zone. + +float BASE_TIMER_PERIOD = 0.04; // the rate at which the timer runs to rez objects. + +// requires noteworthy library v9.3 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the noteworthy library: +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// looks for a notecard with our signature in it and reads the configuration. +// an empty string is returned if we couldn't find anything. +request_configuration() +{ + global_notecard_name = ""; + response_code = 0; + + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([REZZERONI_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from support libraries. +integer handle_link_message(integer which, integer num, string msg, key id) +{ + list parms; + if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { + // did we get a response to a teleport request? + if (msg == JAUNT_LIST_COMMAND) { +//log_it("msg: " + (string)num + " str=" + str); + jaunt_responses_awaited--; // one less response being awaited. + if (jaunt_responses_awaited < 0) { + log_it("error, jaunts awaited < 0!"); + jaunt_responses_awaited = 0; + } + // unpack the reply. + parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer last_jaunt_was_success = llList2Integer(parms, 0); + vector posn = (vector)llList2String(parms, 1); + //log_it("got a reply for a jaunt request, success=" + (string)last_jaunt_was_success + " posn=" + (string)posn); + //do anything with the parms? + } + return FALSE; + } + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) return FALSE; // not for us. + + // process the result of reading the notecard. + parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return FALSE; // oops, this isn't for us. + // make sure if we are being told to keep going. + if (notecard_name == NOTECARD_READ_CONTINUATION) { +//log_it("continuation of notecard seen."); + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + // we're not done reading yet, so fall out to the false return. + } else if (notecard_name != "bad_notecard") { + // a valid notecard has been found and we're done with it now. + global_notecard_name = notecard_name; + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + global_config_index = 0; + // signal that we're done getting the config. + return TRUE; + } else { + // we hated the notecards we found, or there were none. + log_it("sorry, no notecards starting with '" + + REZZERONI_SIGNATURE + + "'; cannot rez yet."); + } + return FALSE; +} + +/////////////// + +// requires jaunting library v10.5 or greater. +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a list of vectors as the first parameter; this list + // should be in the jaunter notecard format (separated by pipe characters). + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// +// encases a list of vectors in the expected character for the jaunting library. +string wrap_vector_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +////////////// + +// asks the jaunting library to take us to the target using a list of waypoints. +request_jaunt(list full_journey, integer forwards) +{ + if (PERFORM_JAUNTS) { + jaunt_responses_awaited++; + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, + wrap_vector_list(full_journey) + + HUFFWARE_PARM_SEPARATOR + (string)forwards); + } +} + +// jaunts back to our home location. +attempt_to_go_home() +{ + // jump back to home. + request_jaunt([llGetPos(), main_home], TRUE); +} + +/////////////// + +// creates the real list of items to rez based on the obj_name variable. +// this might turn out to be an empty list. +list build_rezzing_list() +{ + list objects_to_rez; // what items are we expected to create in this round? + + integer num_inv = llGetInventoryNumber(INVENTORY_OBJECT); + if (num_inv == 0) { + log_it("Inventory is empty; please add objects to rez."); + llSetTimerEvent(0.0); // stop the timer; nothing further to do. + return []; + } +//hmmm: all has never been tested. + if (obj_name == "ALL") { + integer inv; + for (inv = 0; inv < num_inv; inv++) { + objects_to_rez += [ llGetInventoryName(INVENTORY_OBJECT, inv) ]; + } + obj_is_singleton = FALSE; // flag makes no sense for multiple objects. + } else { + // we know we are not being told to do a multiple set of objects. + if (obj_name == "random") { + // special keyword for a random object. + integer inv = (integer)randomize_within_range(0.0, num_inv, FALSE); + obj_name = llGetInventoryName(INVENTORY_OBJECT, inv); + if (SUPER_NOISY_DEBUG) + log_it("chose item #" + (string)inv + " randomly (called '" + obj_name + "')."); + } else { + // a normal singular object to create. + if (find_in_inventory(obj_name, INVENTORY_OBJECT) < 0) { + // this item is bogus! + log_it("item '" + obj_name + "' is bogus! not in inventory."); + obj_name = ""; // reset it. + } + } + // now make sure we didn't already do this one. + if (find_in_list(already_done_items, obj_name) >= 0) { +// if (SUPER_NOISY_DEBUG) +// log_it("item '" + obj_name + "' has already been rezzed. skipping it."); + obj_name = ""; + } else { + if (obj_name != "") objects_to_rez += [ obj_name ]; + } + } + + return objects_to_rez; +} + +// checks whether the object is even supposed to be a singleton or not. +// if it should be a singleton, then we run a sensor ping to see if it exists in the +// vicinity or not. if it's not there, we'll eventually hear about it and create it. +integer validate_singleton_object() +{ + // see if there's only supposed to be one of these objects. + if (!obj_is_singleton) return TRUE; // just keep going; it's not one. + if (obj_name == "") return TRUE; // this should never happen. pretend it's okay. + + // okay, we know we should have a singleton. now did we already check for its presence? + if (global_singleton_checker == "") { + // have not scanned yet; postpone the rezzing action and start a sensor for the object. + sensor_checks_pending++; + global_singleton_checker = obj_name; + // maximally distant ping in full arc on all types of objects we can see. + llSensor(obj_name, NULL_KEY, AGENT|ACTIVE|PASSIVE, 96, PI); + if (DEBUGGING) log_it("scanning for singleton item '" + obj_name + "' now."); + return FALSE; + } else { + // we should have finished a sensor probe now, since there were no checks pending + // and since this is a singleton. + if (global_found_the_singleton) { + if (DEBUGGING) + log_it("singleton item '" + obj_name + "' already present; not re-rezzing."); + already_done_items += [ obj_name ]; +//if (TERMINATE_IF_PRESENT) +string DIE_ON_DEMAND_MESSAGE = "die-on-demand"; +llShout(DIE_ON_DEMAND_CHANNEL, DIE_ON_DEMAND_MESSAGE); + } else { + if (DEBUGGING) + log_it("singleton item '" + obj_name + "' is absent; will rez one now if possible."); + } + return TRUE; + } +} + +// operates on the current parameters to rez an object or objects. +integer perform_rezzing_action() +{ + vector current_home = llGetPos(); + list objects_to_rez = build_rezzing_list(); +//log_it("rezzing " + (string)llGetListLength(objects_to_rez) + " objects"); + // create the specified number of the items we were told to use. + integer num_objects = llGetListLength(objects_to_rez); + if (num_objects == 0) { + // nothing to do at this point. +// if (SUPER_NOISY_DEBUG) log_it("no items in rez list; bailing out."); + return TRUE; + } + // iterate across each object in inventory. + integer inv; + for (inv= current_object_index; inv < num_objects; inv++) { +//log_it("object index " + (string)inv); + // rez as many of the object as we were requested to. + string new_rezzee = llList2String(objects_to_rez, inv); + integer counter; + for (counter = current_count; counter < rezzed_at_once; counter++) { + // make sure we've never rezzed a non-periodic with this name before. + if (find_in_list(already_done_items, new_rezzee) < 0) { +///log_it("haven't rezzed '" + new_rezzee + "' yet."); + vector rez_place = obj_position; +//log_it("configd rezplace=" + (string)rez_place); + if (rez_place == <0.0, 0.0, 0.0>) { + // they did not give us an absolute position, so use the home position. + rez_place = main_home; +//log_it("rehomed rezplace=" + (string)rez_place); + } + vector calc_offset = maybe_randomize_offset(obj_offset, obj_max_offset_add); + if (calc_offset != <0.0, 0.0, 0.0>) { + // the offset is non-zero, so apply it to the rez place. + rez_place += calc_offset * main_rotate; +//log_it("offsetd rezplace=" + (string)rez_place); + } + // add in the multiplier offset if this is not the first rezzing of this item. + rez_place += ((float)counter) + * maybe_randomize_offset(obj_multi_offset, obj_max_offset_add) + * main_rotate; +//log_it("home=" + (string)main_home + " rezplace=" + (string)rez_place); + + // check that we are not too far away. + float rez_distance = llVecDist(rez_place, llGetPos()); + if (rez_distance > MAXIMUM_REZ_DISTANCE) { + // try to jump there if we're too far away to rez from here. + if (DEBUGGING) + log_it("distance is " + (string)rez_distance + + "; jaunting closer."); + request_jaunt([llGetPos(), rez_place], TRUE); + current_count = counter; + current_object_index = inv; + return FALSE; + } + + // make sure we aren't already done with this object, if it's a singleton. + integer keep_going = validate_singleton_object(); + if (!keep_going) { + if (SUPER_NOISY_DEBUG) log_it("must sense for singleton, bailing."); + current_count = counter; + current_object_index = inv; + return FALSE; // we can't proceed yet. must check for singleton. + } + +//hmmm: we need to offer an angular offset also! +// this would mean that the multiple guys could be set at nice different angles. + + // now check again whether to rez this or not; the validation method adds it to the + // done list if the object is already present and is a singleton. + if (find_in_list(already_done_items, new_rezzee) < 0) { + if (DEBUGGING) + log_it("now rezzing '" + new_rezzee + "', rot " + obj_rotation); + vector rota = maybe_randomize_rotation(obj_rotation, obj_max_rotation_add); + rotation real_rot = llEuler2Rot(rota * DEG_TO_RAD); + +//hmmm: might be nice to offer an absolute version! +// that accounts for the specific position and offset, rather +// than relative to rezzer. angle should be kept absolutist also. + + // add in our rotation component as the rezzer. + real_rot *= main_rotate; +//this is bunkum. + // add in the angular addition for multiple object creation. + real_rot *= llEuler2Rot( + maybe_randomize_rotation(obj_multi_angle, obj_max_rotation_add) + * (float)counter * DEG_TO_RAD); + recent_items_rezzed++; // we got to do something. + // rez it up since we know what is wanted and where, plus we're in range. + llRezObject(new_rezzee, rez_place, ZERO_VECTOR, real_rot, OBJECT_STARTUP_PARM); + rezzed_overall++; // one more item. + if (gift_card_name != "") { + // this guy needs its startup gift. + string inv_name = gift_card_name + (string)rezzed_overall; + if (find_in_inventory(inv_name, INVENTORY_NOTECARD) >= 0) { + // this inventory item exists, so use it. + gift_stack += [ inv_name]; + } + } + global_singleton_checker = ""; // reset singleton checker for next object. + } else { + if (SUPER_NOISY_DEBUG) log_it("not rezzing, already saw it in list"); + } + } + } + current_count = 0; // got to the full count for the object. + // if this is a non-periodic object, we don't need any more runs. + if (obj_rezzing_period == 0.0) { + if (find_in_list(already_done_items, new_rezzee) < 0) { + if (SUPER_NOISY_DEBUG) log_it("adding newly done: " + (string)new_rezzee); + already_done_items += [ new_rezzee ]; + } + } + } + current_object_index = 0; // reset the current object index. + + return TRUE; +} + +/////////////// + +// returns true if the state should change. +integer handle_timer() +{ + // make sure we run at the fast rate; we'll reset the rate elsewhere if needed. + llSetTimerEvent(BASE_TIMER_PERIOD); + + if (!is_enabled_now) { + if (jaunt_responses_awaited > 0) { + if (SUPER_NOISY_DEBUG) log_it("done rez, but jaunts awaited."); + return FALSE; + } + if (llVecDist(llGetPos(), main_home) > HOME_PROXIMITY) { + if (SUPER_NOISY_DEBUG) log_it("done rez, but not at home."); + attempt_to_go_home(); + return FALSE; + } + if (llGetListLength(gift_stack)) { + if (SUPER_NOISY_DEBUG) log_it("done rez, but still pending gifts."); + return FALSE; + } + if (SUPER_NOISY_DEBUG) log_it("done rez, totally done."); + llSetTimerEvent(0.0); + return TRUE; + } + + // check whether the max run time has elapsed. + integer run_time = llAbs(llGetUnixTime() - when_last_enabled); + if (run_time > max_run_time) { + log_it("Maximum run time elapsed; shutting down."); + is_enabled_now = FALSE; + llSetTimerEvent(0.0); + return TRUE; + } + + // we have not gotten a configuration yet. + if (global_notecard_name == "") { +/// if (SUPER_NOISY_DEBUG) log_it("in timer with no notecard???"); + return FALSE; + } + + // crank to next step in config. + if (!run_through_rez_plan()) { +//log_it("told done with rez plan"); + // we were told not to keep going. if this is a periodic run, + // then we'll snooze until the next time. + if (obj_rezzing_period != 0.0) { + llSetTimerEvent(obj_rezzing_period); + finished_file = FALSE; + } + } + // even if the run were done, we still have to handle termination conditions. + return FALSE; +} + +// processes requests made by avatars via chat. +integer handle_hearing_voices(integer channel, string name, key id, string message) +{ + string rez_command = "#rez"; + // is this our command prefix? + if (is_prefix(message, rez_command)) { + // we found a command. which specific one? + string parm = llDeleteSubString(message, 0, llStringLength(rez_command)); + // eat the command portion, plus a space. + if ( (parm == "on") && !is_enabled_now) { + is_enabled_now = TRUE; + return TRUE; + } else if ( (parm == "off") && is_enabled_now) { + is_enabled_now = FALSE; + return TRUE; + } + } + return FALSE; +} + +// a helper function that turns the word "random" into a random value. +// we will never allow a negative z value for the random amount, since that will often be +// wrong (rezzing underneath where the object lives, e.g.). this implies always +// putting the rezzer below where one wants to see the random rezzing action. +vector maybe_randomize_offset(string vector_or_not, vector largest_add) +{ + if (vector_or_not == "random") { + vector just_xy = ; + vector just_z = <0.0, 0.0, largest_add.z>; + vector to_return = random_bound_vector(<0.0, 0.0, 0.0>, just_xy, TRUE) + + random_bound_vector(<0.0, 0.0, 0.0>, just_z, FALSE); +//log_it("calc rand off: " + (string)to_return); + return to_return; + } else { + return (vector)vector_or_not; + } +} + +vector maybe_randomize_rotation(string vector_or_not, vector largest_add) +{ + if (vector_or_not == "random") { + vector to_return = random_bound_vector(<0.0, 0.0, 0.0>, largest_add, TRUE); +//log_it("calc rand rot: " + (string)to_return); + return to_return; + } else { + return (vector)vector_or_not; + } +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// consumes the notecard in a very application specific way +// to retrieve the configurations for the items to rez. +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + + if ( (content = get_variable_value(to_parse, "name")) != "") + obj_name = content; + else if ( (content = get_variable_value(to_parse, "position")) != "") + obj_position = (vector)content; + else if ( (content = get_variable_value(to_parse, "offset")) != "") + obj_offset = content; + else if ( (content = get_variable_value(to_parse, "rotation")) != "") + obj_rotation = content; + else if ( (content = get_variable_value(to_parse, "multi_offset")) != "") + obj_multi_offset = content; + else if ( (content = get_variable_value(to_parse, "multi_angle")) != "") + obj_multi_angle = content; + else if ( (content = get_variable_value(to_parse, "singleton")) != "") + obj_is_singleton = (integer)content; + else if ( (content = get_variable_value(to_parse, "count")) != "") + rezzed_at_once = (integer)content; + else if ( (content = get_variable_value(to_parse, "rate")) != "") + obj_rezzing_period = (float)content; + else if ( (content = get_variable_value(to_parse, "max_run")) != "") + max_run_time = (integer)content; + else if ( (content = get_variable_value(to_parse, "gift")) != "") + gift_card_name = content; + else if ( (content = get_variable_value(to_parse, "maxrandoff")) != "") + obj_max_offset_add = (vector)content; + else if ( (content = get_variable_value(to_parse, "maxrandrot")) != "") + obj_max_rotation_add = (vector)content; + else if ( (content = get_variable_value(to_parse, "owner_only")) != "") + owner_only = (integer)content; + else if ( (content = get_variable_value(to_parse, "die_channel")) != "") + DIE_ON_DEMAND_CHANNEL = (integer)content; + else if ( (content = get_variable_value(to_parse, "perform_jaunts")) != "") + PERFORM_JAUNTS = (integer)content; +} + +// examines the configuration to find one section of rezzable plan. +// returns TRUE when the entire config has been consumed. +integer read_one_section() +{ + integer count = llGetListLength(global_config_list); + if (global_config_index >= count) return TRUE; // all done. + integer sec_indy = global_config_index; + string line = llList2String(global_config_list, sec_indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + reset_variables_to_defaults(); // clean out former thoughts. + if (SUPER_NOISY_DEBUG) + log_it("reading section: " + llGetSubString(line, 1, -2)); + // iterate across the items in current config section. + // initializer skips line we just read. + for (sec_indy++; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. + parse_variable_definition(line); + } else { + // done chowing on defs, so break out. + global_config_index = sec_indy; + // if the index is past the end, we're all done. + return global_config_index >= count; + } + } + global_config_index = sec_indy; + if (SUPER_NOISY_DEBUG) log_it("read_one_section finished file, post loop."); + return TRUE; // at end of list. + } else { + if ( (line != "") && !is_prefix(line, "#") ) { + if (SUPER_NOISY_DEBUG) log_it("skipping gibberish: " + line); + global_config_index++; + return FALSE; // not done yet. + } + } + + if (SUPER_NOISY_DEBUG) log_it("read_one_section finished file, bottom bailout."); + return TRUE; +} + +// resets our variables to the default parameters. +reset_variables_to_defaults() +{ + obj_name = ""; + obj_offset = "<0.0, 0.0, 0.0>"; + obj_position = <0.0, 0.0, 0.0>; + obj_rotation = "<0.0, 0.0, 0.0>"; + obj_is_singleton = FALSE; + obj_multi_offset = "<0.0, 0.0, 0.0>"; + obj_multi_angle = "<0.0, 0.0, 0.0>"; + rezzed_at_once = 1; + obj_rezzing_period = 0.0; + max_run_time = 1200; + gift_card_name = ""; + owner_only = FALSE; +} + +integer completed_previous_section; // had the last section finished processing? + +integer finished_file = FALSE; // has the config file been consumed? + +// returns TRUE while it should continue to be called at the normal rate. +integer run_through_rez_plan() +{ + if (jaunt_responses_awaited > 0) return TRUE; // not ready yet. + if (sensor_checks_pending > 0) return TRUE; // not ready yet. + + if (completed_previous_section) { +// if (SUPER_NOISY_DEBUG) log_it("decided to read config, prev sec complete now..."); + // read in the next section of config. + finished_file = read_one_section(); + // reset the current counters of rezzed items for the section. + current_count = 0; + current_object_index = 0; + recent_items_rezzed = 0; + already_done_items = []; + } + // now fire off the rez before we start the next section. + integer worked = perform_rezzing_action(); + if (!worked) { + // we can't keep going; there needs to be a pause. +// if (SUPER_NOISY_DEBUG) log_it("still working on previous section."); + completed_previous_section = FALSE; + return TRUE; + } else { +// if (SUPER_NOISY_DEBUG) log_it("completed running previous section."); + completed_previous_section = TRUE; + } + + // check whether we rezzed anything at all, and if we're done. + if (finished_file) { +//log_it("seeing file as finished"); + if (obj_rezzing_period == 0.0) { + // this one is not periodic, so we finish out its cycle. + if (DEBUGGING) log_it("shutting down rezzer; no objects left to create."); + is_enabled_now = FALSE; + } + global_config_index = 0; // reset reading position for config. + attempt_to_go_home(); // try to go home after the run. + // periodic plans will just cause a snooze now. + return FALSE; + } + return TRUE; +} + +// resets all our variables and starts reading the rez plan. +crank_rezzer_up() +{ + is_enabled_now = TRUE; // turn the device on. + + main_home = llGetPos(); // set our home location now. + main_rotate = llGetRot(); // set our home rotation also. + when_last_enabled = llGetUnixTime(); // restart the run counter. + global_config_list = []; // no config yet. + global_singleton_checker = ""; // we are not working on a sensor check for anything. + sensor_checks_pending = 0; // no sensors are awaited. + recent_items_rezzed = 0; // nothing rezzed recently. + jaunt_responses_awaited = 0; // no jumps in progress. + rezzed_overall = 0; // nothing has been rezzed yet. + gift_stack = []; // no gifts waiting yet. + + request_configuration(); // try to find a notecard and read our config. + + // announce that we're open for business. + if (DEBUGGING) log_it("rezzer started... [free mem=" + (string)llGetFreeMemory() + "]"); +} + +////////////// +// from hufflets... +// +integer debug_num = 0; + +// in the case of rezzeroni, we want to say things out loud for anyone +// to hear, since often the script is open to access by anyone. +// when debugging, we want to say to the owner also, so that problems can be removed. + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + if (!SUPER_NOISY_DEBUG) { + // say this on open chat. + llSay(0, "[" + (string)debug_num + "] " + to_say); + } else { + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + } +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + // clean initial spaces. + while (llGetSubString(to_check, 0, 0) == " ") + to_check = llDeleteSubString(to_check, 0, 0); + if (!is_prefix(to_check, variable_name)) return ""; + to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); + // clean any spaces or valid assignment characters. + while ( (llGetSubString(to_check, 0, 0) == " ") + || (llGetSubString(to_check, 0, 0) == "=") + || (llGetSubString(to_check, 0, 0) == ",") ) + to_check = llDeleteSubString(to_check, 0, 0); +//still too noisy... +// if (SUPER_NOISY_DEBUG) +// log_it("set '" + variable_name + "' = '" + to_check + "'"); + string chewed_content = to_check; +//this is patching in CR. shouldn't that be separate? + integer indy; + for (indy = 0; indy < llStringLength(chewed_content); indy++) { + if (llGetSubString(chewed_content, indy, indy) == "\\") { + if (llGetSubString(chewed_content, indy+1, indy+1) == "n") { + chewed_content = llGetSubString(chewed_content, 0, indy - 1) + + "\n" + + llGetSubString(chewed_content, indy + 2, + llStringLength(chewed_content) - 1); + } + } + } + // return what's left of the string. + return chewed_content; +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets +////////////// + +integer trigger_stop_message = FALSE; + // a simple logging switch; first time in to awaiting commands, + // we do not want to say a run ended. but every time after that, + // we do want to. + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + if (DEBUGGING) log_it(""); + // we immediately jump into the command handling state. + // this state is really only for cleaning up older scripts with the auto-upgrade. + state awaiting_commands; + } +} + +state awaiting_commands +{ + state_entry() { + if (DEBUGGING) log_it(""); + llSetTimerEvent(0.0); + if (trigger_stop_message) + if (DEBUGGING) log_it("rezzer finished. [free mem=" + (string)llGetFreeMemory() + "]"); + trigger_stop_message = TRUE; // always say it next time. + reset_variables_to_defaults(); // clean out any old notes. + llListen(0, "", NULL_KEY, ""); + } + + touch_start(integer count) { + // see if we're blocking others right now. + if (owner_only && (llDetectedKey(0) != llGetOwner())) return; + state reading_rez_plan; + } + + // is someone speaking to the object? + listen(integer channel, string name, key id, string message) { + if (owner_only && (llDetectedKey(0) != llGetOwner())) return; + if (handle_hearing_voices(channel, name, id, message)) state reading_rez_plan; + } +} + +state reading_rez_plan +{ + state_entry() { + if (DEBUGGING) log_it(""); + is_enabled_now = FALSE; + +// // we reset this list only here, since during periodic we'll keep resetting all +// // our other variables. this status must persist between runs though. +// already_done_items = []; // nothing's been done yet. + + // reset our state so the rez plan will start being read. + completed_previous_section = TRUE; + finished_file = FALSE; + + // get the timer cranking so we can process the configuration. + crank_rezzer_up(); + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { + if (handle_link_message(which, num, msg, id)) + state running_rez_plan; + } + + touch_start(integer count) {} // do nothing in this state, but keep touch event alive. + +} + +state running_rez_plan +{ + state_entry() { + if (DEBUGGING) log_it(""); + llListen(0, "", NULL_KEY, ""); + llSetTimerEvent(BASE_TIMER_PERIOD); + } + + state_exit() { llSetTimerEvent(0); } + + // we got clicked. + touch_start(integer count) { + if (owner_only && (llDetectedKey(0) != llGetOwner())) return; + // disable the rezzing process. + is_enabled_now = FALSE; + llSetTimerEvent(BASE_TIMER_PERIOD); + // now we must allow the timer to handle the return process. + } + + // is someone speaking to the object? + listen(integer channel, string name, key id, string message) { + if (owner_only && (llDetectedKey(0) != llGetOwner())) return; + if (handle_hearing_voices(channel, name, id, message)) is_enabled_now = FALSE; + llSetTimerEvent(BASE_TIMER_PERIOD); + } + + timer() { + if (handle_timer()) state awaiting_commands; + } + + object_rez(key id) { + if (SUPER_NOISY_DEBUG) log_it("heard object rez: id=" + (string)id); + if (!llGetListLength(gift_stack)) return; // no gifts to hand out. + string new_gift = llList2String(gift_stack, 0); + gift_stack = llDeleteSubList(gift_stack, 0, 0); + if (find_in_inventory(new_gift, INVENTORY_NOTECARD) < 0) { + // missing the present. this seems remarkable. + log_it("could not find gift specified: " + new_gift); + return; + } + llGiveInventory(id, new_gift); + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + // a sensor result came in--process either no match or the match. + no_sensor() { global_found_the_singleton = FALSE; sensor_checks_pending--; } + sensor(integer num_detected) { global_found_the_singleton = TRUE; sensor_checks_pending--; } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.lsl deleted file mode 100755 index 99ff84ca..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.lsl +++ /dev/null @@ -1,258 +0,0 @@ - -// huffware script: rotanium rotato, by fred huffhines. -// -// causes the object to rotate according to the parameters set below. -// this can use herky-jerky timed rotation with llSetRot or it can use -// smooth rotation with llTargetOmega. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer RANDOMIZE_ROTATION = TRUE; - -integer SMOOTH_ROTATION = TRUE; - // if this is true, then the object will rotate smoothly rather than - // being rotated by the timer. - -float SMOOTH_TIMER_FREQUENCY = 14.0; - // the smooth rotater doesn't need to hit the timer all that often. - -float SMOOTH_CHANCE_FOR_ADJUSTING = 0.8; - // we won't always change the smooth rotation, even though our timer - // is pretty slow. - -float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; - // the gain is how fast we will rotate in radians per second. - // PI / 2 is about 90 degrees per second, which seems way too fast. - // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, - // and 0.0490873852122 is about PI / 64. - -float JERKY_TIMER_FREQUENCY = 0.50; - // this is the fastest that llSetRot rotation can happen anyhow, - // so we fire the timer at this rate. - -float JERKY_CHANCE_FOR_ADJUSTING = 0.1; - // this is the probability of changing the current direction. - -vector current_add_in = <0.0, 0.0, 0.4>; - // randomly assigned to if RANDOMIZE_ROTATION is true. - -float current_gain = -0.05; - // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. - -float MIN_ADDITION = 0.01; - // smallest amount of change we will ever have. -float MAX_ADDITION = 7.0; - // largest amount of change we will ever have. - -// sets the gain and add in to random choices. -randomize_values() -{ - current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); - current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); -} - -// performs the timed rotation that has been configured for us. -rotate_as_requested() -{ - if (SMOOTH_ROTATION) { - // our slack timer went off, so randomize the rotation if requested. - if (RANDOMIZE_ROTATION && (llFrand(1.0) >= SMOOTH_CHANCE_FOR_ADJUSTING) ) - randomize_values(); - // make sure we are using the rotational values we were asked to. - llTargetOmega(current_add_in, current_gain, 1.0); - } else { - // herky jerky rotation. - -//hmmm: seeing that GetRot or GetLocalRot might be useful at different times. - rotation curr_rot = llGetLocalRot(); // get our current state. - vector euler_curr = llRot2Euler(curr_rot); // turn into euler coords. - euler_curr *= RAD_TO_DEG; // convert to degrees. - vector new_rot = euler_curr + current_add_in; // add our adjustment in. - new_rot *= DEG_TO_RAD; // convert to radians. - rotation quat = llEuler2Rot(new_rot); // convert to quaternion - llSetLocalRot(quat); // rotate the object -//will the local work for a single prim? -//in the current case, we do want just the local rot to change. - - // change the rotation add-in if the mood strikes us. - float starter = 0.420; // where we start looking for change. - float change_cap = starter + JERKY_CHANCE_FOR_ADJUSTING; - float randomness = llFrand(1.000); - if ( (randomness <= change_cap) && (randomness >= starter) ) { - // time for a change in the rotation. - if (RANDOMIZE_ROTATION) - randomize_values(); - } - } -} - -////////////// -// start of hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -// end hufflets -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - // if needed, we will set our initial random rotation. - if (RANDOMIZE_ROTATION) randomize_values(); - // do a first rotate, so we move right at startup. otherwise we won't move - // until after our first timer hits. - rotate_as_requested(); - // now set the timer for our mode. - if (SMOOTH_ROTATION) { - llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); - } else { - llSetTimerEvent(JERKY_TIMER_FREQUENCY); - } - } - - timer() { rotate_as_requested(); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.txt new file mode 100755 index 00000000..99ff84ca --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/rotanium_rotato_v2.7.txt @@ -0,0 +1,258 @@ + +// huffware script: rotanium rotato, by fred huffhines. +// +// causes the object to rotate according to the parameters set below. +// this can use herky-jerky timed rotation with llSetRot or it can use +// smooth rotation with llTargetOmega. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer RANDOMIZE_ROTATION = TRUE; + +integer SMOOTH_ROTATION = TRUE; + // if this is true, then the object will rotate smoothly rather than + // being rotated by the timer. + +float SMOOTH_TIMER_FREQUENCY = 14.0; + // the smooth rotater doesn't need to hit the timer all that often. + +float SMOOTH_CHANCE_FOR_ADJUSTING = 0.8; + // we won't always change the smooth rotation, even though our timer + // is pretty slow. + +float SMOOTH_ROTATION_GAIN_MAX = 0.0490873852122; + // the gain is how fast we will rotate in radians per second. + // PI / 2 is about 90 degrees per second, which seems way too fast. + // 0.196349540849 is about PI / 16, 0.0981747704244 is about PI / 32, + // and 0.0490873852122 is about PI / 64. + +float JERKY_TIMER_FREQUENCY = 0.50; + // this is the fastest that llSetRot rotation can happen anyhow, + // so we fire the timer at this rate. + +float JERKY_CHANCE_FOR_ADJUSTING = 0.1; + // this is the probability of changing the current direction. + +vector current_add_in = <0.0, 0.0, 0.4>; + // randomly assigned to if RANDOMIZE_ROTATION is true. + +float current_gain = -0.05; + // speed of smooth rotation; will randomly change if RANDOMIZE_ROTATION is true. + +float MIN_ADDITION = 0.01; + // smallest amount of change we will ever have. +float MAX_ADDITION = 7.0; + // largest amount of change we will ever have. + +// sets the gain and add in to random choices. +randomize_values() +{ + current_gain = randomize_within_range(0.001, SMOOTH_ROTATION_GAIN_MAX, TRUE); + current_add_in = random_vector(MIN_ADDITION, MAX_ADDITION, TRUE); +} + +// performs the timed rotation that has been configured for us. +rotate_as_requested() +{ + if (SMOOTH_ROTATION) { + // our slack timer went off, so randomize the rotation if requested. + if (RANDOMIZE_ROTATION && (llFrand(1.0) >= SMOOTH_CHANCE_FOR_ADJUSTING) ) + randomize_values(); + // make sure we are using the rotational values we were asked to. + llTargetOmega(current_add_in, current_gain, 1.0); + } else { + // herky jerky rotation. + +//hmmm: seeing that GetRot or GetLocalRot might be useful at different times. + rotation curr_rot = llGetLocalRot(); // get our current state. + vector euler_curr = llRot2Euler(curr_rot); // turn into euler coords. + euler_curr *= RAD_TO_DEG; // convert to degrees. + vector new_rot = euler_curr + current_add_in; // add our adjustment in. + new_rot *= DEG_TO_RAD; // convert to radians. + rotation quat = llEuler2Rot(new_rot); // convert to quaternion + llSetLocalRot(quat); // rotate the object +//will the local work for a single prim? +//in the current case, we do want just the local rot to change. + + // change the rotation add-in if the mood strikes us. + float starter = 0.420; // where we start looking for change. + float change_cap = starter + JERKY_CHANCE_FOR_ADJUSTING; + float randomness = llFrand(1.000); + if ( (randomness <= change_cap) && (randomness >= starter) ) { + // time for a change in the rotation. + if (RANDOMIZE_ROTATION) + randomize_values(); + } + } +} + +////////////// +// start of hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +// end hufflets +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + // if needed, we will set our initial random rotation. + if (RANDOMIZE_ROTATION) randomize_values(); + // do a first rotate, so we move right at startup. otherwise we won't move + // until after our first timer hits. + rotate_as_requested(); + // now set the timer for our mode. + if (SMOOTH_ROTATION) { + llSetTimerEvent(SMOOTH_TIMER_FREQUENCY); + } else { + llSetTimerEvent(JERKY_TIMER_FREQUENCY); + } + } + + timer() { rotate_as_requested(); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.lsl deleted file mode 100755 index e6d81c39..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.lsl +++ /dev/null @@ -1,492 +0,0 @@ - -// huffware script: searchbert armature, by fred huffhines -// -// this script serves two useful functions for searchbert: -// 1) this is searchbert's ease-of-use auto-repair feature. the script puts searchbert's arms back -// on if they should ever get ripped off. this happens more frequently than one might expect, but this -// script makes searchbert feel all better again. -// 2) this script also manages the exchange of resources between the root prim and the arms. if there -// are updates to the search pointer script or others, they'll get synched on a periodic basis. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -// global constants. - -integer DEBUGGING = FALSE; // set to true to make the script noisier. - -integer SPECIAL_STARTUP_SAUCE = -10408; - // used to signal that this is a real searchbert arm, so it should evaporate on detach. - -integer INVENTORY_UPDATE_INTERVAL = 6000; - // how often to rescan the inventory so sub-prims get the right contents, in seconds. - -integer TOTAL_SEARCH_RODS = 17; // given our current pattern, this is how many we rez. - -// object maintenance variables... - -integer objects_rezzed = 0; // how many kids did we see created? - -integer alerted_brainiac = FALSE; // did we tell the brain that our arms are good? - -////////////// - -// exported interfaces... - -// the armature button pushing API. -// (we have subclassed the simple button pushing API for searchbert armature.) -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10029; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was pushed. -////////////// -string CHECK_ARMS_BUTTON_NAME = "^checkarms"; - // this is the signal given to the armature script that it should check the - // number of arms present on searchbert. if the number is fine, it will - // push the arms are good button back at the brainiac (using the button - // push api plus reply distance). -string ARMS_ARE_GOOD_BUTTON_NAME = "^goodarmz"; - // the event sent back by the searchbert armature when all arms are ready - // to go. -string PROBLEM_WITH_MY_THUMBS_BUTTON_NAME = "^ouch"; - // a problem was noticed with the number of arms and we could not fix it. - // the brain needs to try reconfiguring again. -////////////// - -// imported interfaces... - -// inventory exchanger API. -////////////// -// do not redefine these constants. -integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -//string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -//integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available via the library: -string REGISTER_ASSETS_COMMAND = "#regis#"; - // makes the root prim's inventory exchanger track a set of items which each participating - // child prim should have. this command is only available to the root prim; child prims - // cannot register any assets but instead can get updates on the assets. the parameter - // required is a list of asset definitions, wrapped by the huffware item separator. each - // asset definition is in turn a two part list wrapped with the asset field separator. -string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. -string WILDCARD_INVENTORY_NAME = "ALL"; - // this keyword can be used to register all of the inventory items available of the - // specified type. this should be passed as the inventory item name in the second half of - // an asset definition list. -string WHACK_INVENTORY_SIGNAL = "DEL*"; - // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. -string AVAILABLE_ASSETS_EVENT = "#gotz#"; - // the root prim publishes this event to list out what items it has available. the child - // prims need to ask for anything that they're currently missing. the included parameters - // are in the same format as the register assets command, but no wildcards will be present; - // all asset names will be fully expanded. -string REQUEST_UPDATES = "#nupd#"; - // used by the child prim to request an updated version of an asset or assets. the parameters - // should follow the register assets command. -string FINISHED_UPDATING = "#donq#"; - // a signal sent from the root prim to the child prim when the root has finished updating - // the assets requested. this lets the child know that it can clean out any outdated versions - // of items which got an update. there are no parameters to this, because the child prim - // should have at most one update outstanding at a time. -////////////// - -// startup function that gets things going. this is not called at startup time, it -// has to be activated by the brain script. -initialize_armatures() -{ - objects_rezzed = 0; - alerted_brainiac = FALSE; - check_integrity(); -} - -// starts the process of exchanging the inventory items with our arms. -initialize_exchanger() -{ - llSetTimerEvent(5); // check on inventory soon. -} - -// looks for an inventory item with the same prefix as the "basename_to_seek". -integer find_basename_in_inventory(string basename_to_seek, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer indy; - for (indy = 0; indy < num_inv; indy++) { - if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) - return indy; - } - return -2; // failed to find it. -} - -// lets the searchbert brain know the arms are all ready. -report_arms_are_good() -{ - if (!alerted_brainiac) { - // let the brain know we're doing okay on our arm count. - alerted_brainiac = TRUE; - llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, - BUTTON_PUSHED_ALERT, ARMS_ARE_GOOD_BUTTON_NAME); - } -} - -// we ran into a snag, like the user didn't give us permission. we need the -// controlling script to try this all again. -report_arms_are_bad() -{ - alerted_brainiac = FALSE; - llSay(0, "I did not get permission to attach my seeker arms."); - llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, - BUTTON_PUSHED_ALERT, PROBLEM_WITH_MY_THUMBS_BUTTON_NAME); -} - -// returns the name of the inventory exchange script, if one is present. we don't worry -// about there being more than one present; that's a different script's problem. -list get_exchanger_and_pointer_names() -{ - list to_return; - integer found = find_basename_in_inventory("inventory exchanger", INVENTORY_SCRIPT); - if (found >= 0) { - to_return += [ (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR - + llGetInventoryName(INVENTORY_SCRIPT, found) ]; - } - found = find_basename_in_inventory("huff-search pointer", INVENTORY_SCRIPT); - if (found >= 0) { - to_return += [ (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR - + llGetInventoryName(INVENTORY_SCRIPT, found) ]; - } - return to_return; -} - -// tell the root prim's inventory exchanger what to monitor. -post_exchangeable_assets() -{ - // it's time to post. we allow a couple seconds leeways since timers are inexact. - llMessageLinked(LINK_THIS, INVENTORY_EXCHANGER_HUFFWARE_ID, REGISTER_ASSETS_COMMAND, - // what we really want here is to make sure our pointer script is kept up to date. - wrap_parameters(get_exchanger_and_pointer_names() )); -} - -// our timer handling function; this will move the search engine to the next place on -// the current spiral (or to the start of the next spiral) when it is called. -// if we're not currently running a search, then it will just periodically update the -// sub-prims to make sure they have the latest versions. -handle_timer() -{ - // stop the clock. - llSetTimerEvent(0); - // if we haven't updated the inventory assets in a while, then we want - // to make sure the sub-prims have all the right versions of things. - post_exchangeable_assets(); - // restart ticking. - llSetTimerEvent(INVENTORY_UPDATE_INTERVAL); -} - -// this function is called when we have acquired permissions to manipulate this object, -// so we can crank up all the search rods to be our seekers. -got_link_permissions() -{ - if ( (llGetNumberOfPrims() - 1) >= TOTAL_SEARCH_RODS) { - // seems like the arms are already present. - objects_rezzed = TOTAL_SEARCH_RODS; - if (DEBUGGING) log_it("I'm done setting up my arms."); - // make sure we alert brain. - check_integrity(); - return; - } - - // reset our count now that we're going to reattach everything. - objects_rezzed = 0; - - // postpone the next inventory exchange until we have all our arms on. - // each link addition takes at least a second of built in delay (currently). - llSetTimerEvent(TOTAL_SEARCH_RODS + 7); - - llBreakAllLinks(); // drop all current attachments and let them evaporate. - - string search_object = llGetInventoryName(INVENTORY_OBJECT, 0); - - integer which_locator = 2; - float curr_rotation; - // calculate the size of the root prim so we can put the search arms in the - // right locations. - list sizes = llGetBoundingBox(llGetKey()); - vector min = llList2Vector(sizes, 0); - vector max = llList2Vector(sizes, 1); - // not exactly sure if this formula will always be right. have seen some anomalous - // results from get bounding box. - float radius = (max.x - min.x) / 2.0; - - for (curr_rotation = 0.0; curr_rotation < PI / 4.0 + .001; - curr_rotation += PI / 4.0) { - float x = 0.0; - // handle dots on x axis. - for (x = -0.4 / 0.54 * radius; x < 0.41 / 0.54 * radius; x += 0.2 / 0.54 * radius) { - if ( (curr_rotation != 0.0) || (llRound(x * 100.0) != 0) ) { - vector rez_place = ; - rotation z_45 = llEuler2Rot(<0.0, 0.0, curr_rotation>); - rez_place *= z_45; - rez_place += llGetPos(); -//log_it("x rez place " + (string)rez_place + " rot=" + (string)curr_rotation); - which_locator++; - llRezObject(search_object, rez_place, ZERO_VECTOR, ZERO_ROTATION, - SPECIAL_STARTUP_SAUCE); - } - } - float y = 0.0; - // handle dots on y axis. - for (y = -0.4 / 0.54 * radius; y < 0.41 / 0.54 * radius; y += 0.2 / 0.54 * radius) { - if (llRound(y * 100.0) != 0) { - vector rez_place = <0.0, y, 0.0>; - rotation z_45 = llEuler2Rot(<0.0, 0.0, curr_rotation>); - rez_place *= z_45; - rez_place += llGetPos(); -//log_it("y rez place " + (string)rez_place + " rot=" + (string)curr_rotation); - which_locator++; - llRezObject(search_object, rez_place, ZERO_VECTOR, ZERO_ROTATION, - SPECIAL_STARTUP_SAUCE); - } - } - } -} - -handle_new_child(key new_child) -{ - // report (via text label) how many others there are still to hook in. - integer count; - integer remaining_to_rez = TOTAL_SEARCH_RODS - objects_rezzed; - string tag; - for (count = 0; count < remaining_to_rez; count++) tag += "+"; - llSetText(tag + " " + (string)remaining_to_rez + " " + tag, - <0.4 + llFrand(0.6), 0.4 + llFrand(0.6), 0.4 + llFrand(0.6)>, 1.0); - // link the new kid to us. - // this also delays the script a whole second?! argh. - llCreateLink(new_child, TRUE); - // check if we're done yet. - if (++objects_rezzed >= TOTAL_SEARCH_RODS) { - // that was the last one. - llSetText("", <0.0, 0.0, 0.0>, 0.0); - if (DEBUGGING) log_it("All of my arms have been rezzed and connected now."); - // one last check and alert the brain about us being ready. - check_integrity(); - } -} - -// processes a request for our armature services, probably from the search brain. -handle_link_message(integer which, integer num, string msg, key id) -{ - if ( (num == BUTTON_PUSHER_HUFFWARE_ID) - && (msg == BUTTON_PUSHED_ALERT) - && (id == CHECK_ARMS_BUTTON_NAME) ) { - // see if we can put our arms on, if they're not already. - initialize_armatures(); - } -} - -// makes sure that searchbert is all assembled properly. -check_integrity() -{ - if (llGetNumberOfPrims() - 1 < TOTAL_SEARCH_RODS) { - alerted_brainiac = FALSE; - if (DEBUGGING) log_it("I do not have enough arms on my body. Please grant me permission to link and delink."); - // get permissions to take off our arms and add possibly updated ones. - llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS); - } else { - if (!alerted_brainiac) { - // let the brain know we're doing okay on our arm count. - report_arms_are_good(); - alerted_brainiac = TRUE; - } - } -} - -////////////// -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -integer debug_num = 0; -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llWhisper(0, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() { - auto_retire(); - initialize_exchanger(); - } - - on_rez(integer parm) { llResetScript(); } - - object_rez(key new_child) { handle_new_child(new_child); } - - timer() { handle_timer(); } - - link_message(integer which, integer num, string str, key id) - { handle_link_message(which, num, str, id); } - - run_time_permissions(integer perm) { - if (perm & PERMISSION_CHANGE_LINKS) - got_link_permissions(); - else - report_arms_are_bad(); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSetTimerEvent(2); // fire exchange sooner in case scripts changed. - } else if (change & CHANGED_LINK) { - check_integrity(); - } - } - -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.txt new file mode 100755 index 00000000..e6d81c39 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_armature_v15.3.txt @@ -0,0 +1,492 @@ + +// huffware script: searchbert armature, by fred huffhines +// +// this script serves two useful functions for searchbert: +// 1) this is searchbert's ease-of-use auto-repair feature. the script puts searchbert's arms back +// on if they should ever get ripped off. this happens more frequently than one might expect, but this +// script makes searchbert feel all better again. +// 2) this script also manages the exchange of resources between the root prim and the arms. if there +// are updates to the search pointer script or others, they'll get synched on a periodic basis. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +// global constants. + +integer DEBUGGING = FALSE; // set to true to make the script noisier. + +integer SPECIAL_STARTUP_SAUCE = -10408; + // used to signal that this is a real searchbert arm, so it should evaporate on detach. + +integer INVENTORY_UPDATE_INTERVAL = 6000; + // how often to rescan the inventory so sub-prims get the right contents, in seconds. + +integer TOTAL_SEARCH_RODS = 17; // given our current pattern, this is how many we rez. + +// object maintenance variables... + +integer objects_rezzed = 0; // how many kids did we see created? + +integer alerted_brainiac = FALSE; // did we tell the brain that our arms are good? + +////////////// + +// exported interfaces... + +// the armature button pushing API. +// (we have subclassed the simple button pushing API for searchbert armature.) +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10029; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was pushed. +////////////// +string CHECK_ARMS_BUTTON_NAME = "^checkarms"; + // this is the signal given to the armature script that it should check the + // number of arms present on searchbert. if the number is fine, it will + // push the arms are good button back at the brainiac (using the button + // push api plus reply distance). +string ARMS_ARE_GOOD_BUTTON_NAME = "^goodarmz"; + // the event sent back by the searchbert armature when all arms are ready + // to go. +string PROBLEM_WITH_MY_THUMBS_BUTTON_NAME = "^ouch"; + // a problem was noticed with the number of arms and we could not fix it. + // the brain needs to try reconfiguring again. +////////////// + +// imported interfaces... + +// inventory exchanger API. +////////////// +// do not redefine these constants. +integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +//string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +//integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available via the library: +string REGISTER_ASSETS_COMMAND = "#regis#"; + // makes the root prim's inventory exchanger track a set of items which each participating + // child prim should have. this command is only available to the root prim; child prims + // cannot register any assets but instead can get updates on the assets. the parameter + // required is a list of asset definitions, wrapped by the huffware item separator. each + // asset definition is in turn a two part list wrapped with the asset field separator. +string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. +string WILDCARD_INVENTORY_NAME = "ALL"; + // this keyword can be used to register all of the inventory items available of the + // specified type. this should be passed as the inventory item name in the second half of + // an asset definition list. +string WHACK_INVENTORY_SIGNAL = "DEL*"; + // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. +string AVAILABLE_ASSETS_EVENT = "#gotz#"; + // the root prim publishes this event to list out what items it has available. the child + // prims need to ask for anything that they're currently missing. the included parameters + // are in the same format as the register assets command, but no wildcards will be present; + // all asset names will be fully expanded. +string REQUEST_UPDATES = "#nupd#"; + // used by the child prim to request an updated version of an asset or assets. the parameters + // should follow the register assets command. +string FINISHED_UPDATING = "#donq#"; + // a signal sent from the root prim to the child prim when the root has finished updating + // the assets requested. this lets the child know that it can clean out any outdated versions + // of items which got an update. there are no parameters to this, because the child prim + // should have at most one update outstanding at a time. +////////////// + +// startup function that gets things going. this is not called at startup time, it +// has to be activated by the brain script. +initialize_armatures() +{ + objects_rezzed = 0; + alerted_brainiac = FALSE; + check_integrity(); +} + +// starts the process of exchanging the inventory items with our arms. +initialize_exchanger() +{ + llSetTimerEvent(5); // check on inventory soon. +} + +// looks for an inventory item with the same prefix as the "basename_to_seek". +integer find_basename_in_inventory(string basename_to_seek, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer indy; + for (indy = 0; indy < num_inv; indy++) { + if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) + return indy; + } + return -2; // failed to find it. +} + +// lets the searchbert brain know the arms are all ready. +report_arms_are_good() +{ + if (!alerted_brainiac) { + // let the brain know we're doing okay on our arm count. + alerted_brainiac = TRUE; + llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, + BUTTON_PUSHED_ALERT, ARMS_ARE_GOOD_BUTTON_NAME); + } +} + +// we ran into a snag, like the user didn't give us permission. we need the +// controlling script to try this all again. +report_arms_are_bad() +{ + alerted_brainiac = FALSE; + llSay(0, "I did not get permission to attach my seeker arms."); + llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, + BUTTON_PUSHED_ALERT, PROBLEM_WITH_MY_THUMBS_BUTTON_NAME); +} + +// returns the name of the inventory exchange script, if one is present. we don't worry +// about there being more than one present; that's a different script's problem. +list get_exchanger_and_pointer_names() +{ + list to_return; + integer found = find_basename_in_inventory("inventory exchanger", INVENTORY_SCRIPT); + if (found >= 0) { + to_return += [ (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR + + llGetInventoryName(INVENTORY_SCRIPT, found) ]; + } + found = find_basename_in_inventory("huff-search pointer", INVENTORY_SCRIPT); + if (found >= 0) { + to_return += [ (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR + + llGetInventoryName(INVENTORY_SCRIPT, found) ]; + } + return to_return; +} + +// tell the root prim's inventory exchanger what to monitor. +post_exchangeable_assets() +{ + // it's time to post. we allow a couple seconds leeways since timers are inexact. + llMessageLinked(LINK_THIS, INVENTORY_EXCHANGER_HUFFWARE_ID, REGISTER_ASSETS_COMMAND, + // what we really want here is to make sure our pointer script is kept up to date. + wrap_parameters(get_exchanger_and_pointer_names() )); +} + +// our timer handling function; this will move the search engine to the next place on +// the current spiral (or to the start of the next spiral) when it is called. +// if we're not currently running a search, then it will just periodically update the +// sub-prims to make sure they have the latest versions. +handle_timer() +{ + // stop the clock. + llSetTimerEvent(0); + // if we haven't updated the inventory assets in a while, then we want + // to make sure the sub-prims have all the right versions of things. + post_exchangeable_assets(); + // restart ticking. + llSetTimerEvent(INVENTORY_UPDATE_INTERVAL); +} + +// this function is called when we have acquired permissions to manipulate this object, +// so we can crank up all the search rods to be our seekers. +got_link_permissions() +{ + if ( (llGetNumberOfPrims() - 1) >= TOTAL_SEARCH_RODS) { + // seems like the arms are already present. + objects_rezzed = TOTAL_SEARCH_RODS; + if (DEBUGGING) log_it("I'm done setting up my arms."); + // make sure we alert brain. + check_integrity(); + return; + } + + // reset our count now that we're going to reattach everything. + objects_rezzed = 0; + + // postpone the next inventory exchange until we have all our arms on. + // each link addition takes at least a second of built in delay (currently). + llSetTimerEvent(TOTAL_SEARCH_RODS + 7); + + llBreakAllLinks(); // drop all current attachments and let them evaporate. + + string search_object = llGetInventoryName(INVENTORY_OBJECT, 0); + + integer which_locator = 2; + float curr_rotation; + // calculate the size of the root prim so we can put the search arms in the + // right locations. + list sizes = llGetBoundingBox(llGetKey()); + vector min = llList2Vector(sizes, 0); + vector max = llList2Vector(sizes, 1); + // not exactly sure if this formula will always be right. have seen some anomalous + // results from get bounding box. + float radius = (max.x - min.x) / 2.0; + + for (curr_rotation = 0.0; curr_rotation < PI / 4.0 + .001; + curr_rotation += PI / 4.0) { + float x = 0.0; + // handle dots on x axis. + for (x = -0.4 / 0.54 * radius; x < 0.41 / 0.54 * radius; x += 0.2 / 0.54 * radius) { + if ( (curr_rotation != 0.0) || (llRound(x * 100.0) != 0) ) { + vector rez_place = ; + rotation z_45 = llEuler2Rot(<0.0, 0.0, curr_rotation>); + rez_place *= z_45; + rez_place += llGetPos(); +//log_it("x rez place " + (string)rez_place + " rot=" + (string)curr_rotation); + which_locator++; + llRezObject(search_object, rez_place, ZERO_VECTOR, ZERO_ROTATION, + SPECIAL_STARTUP_SAUCE); + } + } + float y = 0.0; + // handle dots on y axis. + for (y = -0.4 / 0.54 * radius; y < 0.41 / 0.54 * radius; y += 0.2 / 0.54 * radius) { + if (llRound(y * 100.0) != 0) { + vector rez_place = <0.0, y, 0.0>; + rotation z_45 = llEuler2Rot(<0.0, 0.0, curr_rotation>); + rez_place *= z_45; + rez_place += llGetPos(); +//log_it("y rez place " + (string)rez_place + " rot=" + (string)curr_rotation); + which_locator++; + llRezObject(search_object, rez_place, ZERO_VECTOR, ZERO_ROTATION, + SPECIAL_STARTUP_SAUCE); + } + } + } +} + +handle_new_child(key new_child) +{ + // report (via text label) how many others there are still to hook in. + integer count; + integer remaining_to_rez = TOTAL_SEARCH_RODS - objects_rezzed; + string tag; + for (count = 0; count < remaining_to_rez; count++) tag += "+"; + llSetText(tag + " " + (string)remaining_to_rez + " " + tag, + <0.4 + llFrand(0.6), 0.4 + llFrand(0.6), 0.4 + llFrand(0.6)>, 1.0); + // link the new kid to us. + // this also delays the script a whole second?! argh. + llCreateLink(new_child, TRUE); + // check if we're done yet. + if (++objects_rezzed >= TOTAL_SEARCH_RODS) { + // that was the last one. + llSetText("", <0.0, 0.0, 0.0>, 0.0); + if (DEBUGGING) log_it("All of my arms have been rezzed and connected now."); + // one last check and alert the brain about us being ready. + check_integrity(); + } +} + +// processes a request for our armature services, probably from the search brain. +handle_link_message(integer which, integer num, string msg, key id) +{ + if ( (num == BUTTON_PUSHER_HUFFWARE_ID) + && (msg == BUTTON_PUSHED_ALERT) + && (id == CHECK_ARMS_BUTTON_NAME) ) { + // see if we can put our arms on, if they're not already. + initialize_armatures(); + } +} + +// makes sure that searchbert is all assembled properly. +check_integrity() +{ + if (llGetNumberOfPrims() - 1 < TOTAL_SEARCH_RODS) { + alerted_brainiac = FALSE; + if (DEBUGGING) log_it("I do not have enough arms on my body. Please grant me permission to link and delink."); + // get permissions to take off our arms and add possibly updated ones. + llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS); + } else { + if (!alerted_brainiac) { + // let the brain know we're doing okay on our arm count. + report_arms_are_good(); + alerted_brainiac = TRUE; + } + } +} + +////////////// +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +integer debug_num = 0; +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llWhisper(0, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() { + auto_retire(); + initialize_exchanger(); + } + + on_rez(integer parm) { llResetScript(); } + + object_rez(key new_child) { handle_new_child(new_child); } + + timer() { handle_timer(); } + + link_message(integer which, integer num, string str, key id) + { handle_link_message(which, num, str, id); } + + run_time_permissions(integer perm) { + if (perm & PERMISSION_CHANGE_LINKS) + got_link_permissions(); + else + report_arms_are_bad(); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSetTimerEvent(2); // fire exchange sooner in case scripts changed. + } else if (change & CHANGED_LINK) { + check_integrity(); + } + } + +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.lsl deleted file mode 100755 index e86e2d86..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.lsl +++ /dev/null @@ -1,22 +0,0 @@ -#searchbert - -# see the huff-search brainiac script for more information about what these mean. they correspond to the -# global variables that are "useful to change" near the top of the script. - -# can only point to maximum of 17 things. -max_matches = 17 -huff_search_chat_channel = 0 -traverse_lands = 0 - -sensor_max_range = 96.0 -# angular default is pi / 2 (90 degrees). -search_rod_angular_sweep = 1.57079632679 - -max_spiral_radius = 72.0 -spiral_loops = 7 -total_steps = 42 -max_spiral_traversals = 1 - -travelling_upwards = 0 -max_upwards_distance = 30.0 - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.txt new file mode 100755 index 00000000..e86e2d86 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_config_v0.4.txt @@ -0,0 +1,22 @@ +#searchbert + +# see the huff-search brainiac script for more information about what these mean. they correspond to the +# global variables that are "useful to change" near the top of the script. + +# can only point to maximum of 17 things. +max_matches = 17 +huff_search_chat_channel = 0 +traverse_lands = 0 + +sensor_max_range = 96.0 +# angular default is pi / 2 (90 degrees). +search_rod_angular_sweep = 1.57079632679 + +max_spiral_radius = 72.0 +spiral_loops = 7 +total_steps = 42 +max_spiral_traversals = 1 + +travelling_upwards = 0 +max_upwards_distance = 30.0 + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.lsl deleted file mode 100755 index 719813c2..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.lsl +++ /dev/null @@ -1,505 +0,0 @@ - -// huffware script: searchbert menus, by fred huffhines. -// -// manages the menu system for searchbert so the main script is free to do its thing. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -//notes -// + need to have the searchbert initiate anything here. this cannot be free range and -// running even if the searchbert isn't in a menuable mode. -// + is the above true? - -// global constants... - -string MAIN_MENU_NAME = "main"; // name we use in menu list manager for the main menu. -// boilerplate text that's shown at top of main menu. we'll add the channel info later. -string MAIN_MENU_PREFIX = "Quick help: Say '"; -string MAIN_MENU_MIDDLE = "#find XYZ' in chat to locate nearby objects with 'XYZ' in their names.\nSay '"; -string MAIN_MENU_SUFFIX = "#reset' to stop showing a previous search.\n\n[Matches] shows recent search results.\n[Configure] changes options.\n[Reset] clears recent results.\n[Help] dispenses an instruction notecard."; - -// main menu items... -string HELP_CHOICE = "Help"; -string CONFIG_CHOICE = "Configure"; -string MATCHES_CHOICE = "Matches"; -string RESET_CHOICE = "Reset"; - -// configuration menu items... -string MAX_MATCHES_CHOICE = "Max Match"; -string CHAT_CHANNEL_CHOICE = "Channel"; - -// menu indices... -integer MAIN_MENU_INDEX = 0; // we always do main menu as zero. -integer CONFIG_MENU_INDEX = 1; // choices for configurable items. -integer MAX_MATCHES_MENU_INDEX = 2; // changing the number of matches. - -// searchbert menus API. -////////////// -// do not redefine these constants. -integer SEARCHBERT_MENUS_HUFFWARE_ID = 10034; - // the unique id within the huffware system for this script. -////////////// -string SM_CONFIGURE_INFO = "#sm-info#"; - // sets important information this script will use, such as (1) the channel for listening. -string SM_POP_MAIN_MENU_UP = "#sm-main#"; - // causes the main menu to be displayed. this requires an avatar name and avatar key for the - // target of the menu. -////////////// -string SM_EVENT_MENU_CLICK = "#sm-clik#"; - // the user has requested a particular menu item that this script cannot fulfill. the - // event is generated back to the client of this script for handling. it will include (1) the - // menu name in question, (2) the item clicked, (3) the avatar name, and (4) the avatar key. -////////////// - -// imported interfaces... - -// menu list manager link message API. -////////////// -// do not redefine these constants. -integer MENU_LIST_MANAGER_HUFFWARE_ID = 10033; - // the unique id within the huffware system for this sensor plugin script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string MENU_LIST_MGR_RESET = "#ml-reset#"; - // throws out any current menus and gets ready to load a new set. -string MENU_LIST_MGR_ADD_MENU = "#ml-addmenu#"; - // puts a new menu into our list. this requires 3 parameters: menu name, - // menu title, menu button list. -string MENU_LIST_MGR_SHOW_MENU = "#ml-shomenu#"; - // a request that a particular menu be shown. the first parameter is the menu index. - // the second parameter is the avatar name. the third parameter is the avatar key. -string MENU_LIST_MGR_GIVE_ITEM = "#ml-give#"; - // brings up a gift giving menu. parms are avatar name and avatar key. -string MENU_LIST_MGR_MODIFY_MENU = "#ml-modmenu#"; -string MENU_LIST_KEEP_WORD = "KEEP"; - // replaces a menu already in the list. this requires 4 parameters: menu index, menu name, - // menu title, menu button list. if a parameter is the MENU_LIST_KEEP_WORD, then that field - // is not changed. -string MENU_LIST_MGR_CHOICE_MADE_ALERT = "#ml-event-picked"; - // alerts the driver for this script that the owner has picked a choice. the - // parameters include: the text of the choice, the name of the menu, the avatar name, - // the avatar key. -// -////////////// - -// we snag just enough of this interface to masquerade as it... -// card configurator link message API: -////////////// -// do not redefine these constants. -integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; - // the unique id within the huffware system for the card configurator script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; - // this message is sent when the configurator has found some data updates or has finished - // reading the configuration file. -////////////// - -// global variables... - -integer initialized_menus_yet = FALSE; - // records if the menus have been set up. - -// additional information that's provided by the client script. -integer TALKY_CHANNEL = 0; - -////////////// - -// sends a new menu to be placed in the menu manager. -add_menu(string menu_name, string menu_title, list button_list) -{ - if (llGetListLength(button_list) == 0) { - // patch this degenerate list into a bogus one. - button_list = [ "none" ]; - } - llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_ADD_MENU, - menu_name + HUFFWARE_PARM_SEPARATOR - + menu_title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(button_list)); -} - -// stuffs in a new version of an old menu. -replace_menu(integer index, string menu_name, string menu_title, list button_list) -{ - llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_MODIFY_MENU, - (string)index + HUFFWARE_PARM_SEPARATOR - + menu_name + HUFFWARE_PARM_SEPARATOR - + menu_title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(button_list)); -} - -// sets up the main menu options. if "new_now" is false, then this replaces -// the main menu rather than expecting to add a new one. -establish_main_menu(integer new_now) -{ - // menu zero: this is the main menu. - string menu_name = "main"; - string menu_title = MAIN_MENU_PREFIX + channel_string() + MAIN_MENU_MIDDLE - + channel_string() + MAIN_MENU_SUFFIX; - list menu_button_list = [ MATCHES_CHOICE, CONFIG_CHOICE, RESET_CHOICE, HELP_CHOICE ]; - if (new_now) { - add_menu(menu_name, menu_title, menu_button_list); - } else { - replace_menu(MAIN_MENU_INDEX, menu_name, menu_title, menu_button_list); - } -} - -// sets up all of the static menus for searchbert. -prepare_all_menus() -{ - establish_main_menu(TRUE); // set up the main menu as a new menu. - - // configuration menu provides tasty options for changing the way searchbert behaves. - string menu_name = CONFIG_CHOICE; // reusing menu button from main menu for the menu name. - string menu_title = "Configurable Options...\n[" + MAX_MATCHES_CHOICE + "] selects number of items to find.\n[" + CHAT_CHANNEL_CHOICE + "] changes listening channel for commands.\n"; - list menu_button_list = [ MAX_MATCHES_CHOICE, CHAT_CHANNEL_CHOICE ]; - add_menu(menu_name, menu_title, menu_button_list); - - menu_name = MAX_MATCHES_CHOICE; // reusing menu button from config menu. - menu_title = "Choose a new maximum number of items to find:"; - menu_button_list = produce_nums(17); // ultimate number of arms available (magic constant!). - add_menu(menu_name, menu_title, menu_button_list); - -} - -// if we haven't initialized yet, we'll do it now. -maybe_really_setup_menus() -{ - if (!initialized_menus_yet) { -//log_it("needed initialization still!"); - prepare_all_menus(); - initialized_menus_yet = TRUE; - llSetTimerEvent(0); // stop timer. - return; - } -} - -// deals with the timer elapsing. -handle_timer_hit() -{ - // see if this timer is for initialization purposes. - maybe_really_setup_menus(); -} - -// processes a message requesting our services or updating our info. or ignore it. -handle_link_message(integer sender, integer num, string msg, key id) -{ - if ( (num != MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE) - && (num != SEARCHBERT_MENUS_HUFFWARE_ID) ) - return; - - // make sure we're already initialized. - maybe_really_setup_menus(); - - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - - if (num == MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE) { - if (msg == MENU_LIST_MGR_CHOICE_MADE_ALERT) { - // now deal with the implications of the menu they chose. - process_menu_choice(llList2String(parms, 1), llList2String(parms, 2), - llList2String(parms, 3), llList2String(parms, 0)); - } - return; - } - - // if we got to here, it must be for our main interface methods. -//log_it("got searchbert menu request: " + msg + ". memory left=" + (string)llGetFreeMemory()); - if (msg == SM_CONFIGURE_INFO) { - TALKY_CHANNEL = (integer)llList2String(parms, 0); - establish_main_menu(FALSE); - } else if (msg == SM_POP_MAIN_MENU_UP) { - // show the main menu for the specified avatar. - request_menu_popup(MAIN_MENU_INDEX, llList2String(parms, 0), llList2String(parms, 1)); - } - -} - -request_menu_popup(integer menu_index, string av_name, string av_key) -{ - llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_SHOW_MENU, - wrap_parameters([menu_index, av_name, av_key])); -//log_it("sent menu popup... memory left=" + (string)llGetFreeMemory()); -} - -// generates a list of numbers up to and including the "max". -list produce_nums(integer max) -{ - list to_return; - integer indy; - for (indy = 1; indy <= max; indy++) { - to_return += (string)indy; - } - return to_return; -} - -// returns the appropriate extra text if the channel is not zero for open chat. -string channel_string() -{ - string add_in_channel = ""; - if (TALKY_CHANNEL != 0) - add_in_channel = "/" + (string)TALKY_CHANNEL + " "; - return add_in_channel; -} - -// handles when a menu has been clicked on. -process_menu_choice(string menu_name, string av_name, string av_key, string which_choice) -{ -//log_it("into process menu " + menu_name + " for " + av_name + " who chose " + which_choice); - if (menu_name == MAIN_MENU_NAME) { - if (which_choice == HELP_CHOICE) { - // see if we can find a helper notecard. - integer indy = find_basename_in_inventory("docs", INVENTORY_NOTECARD); - if (indy < 0) { - llSay(0, "We're very sorry, but there do not seem to be any documentation notecards available. There may be a better version at eepaw shop (osgrid or SL)."); - } else { - string invname = llGetInventoryName(INVENTORY_NOTECARD, indy); - llGiveInventory(av_key, invname); - llWhisper(0, "Here's a copy of the help file: " + invname); - } - return; - } else if (which_choice == CONFIG_CHOICE) { - request_menu_popup(CONFIG_MENU_INDEX, av_name, av_key); - return; - } - // MATCHES_CHOICE falls through for forwarding. - // so does RESET_CHOICE. - } else if (menu_name == CONFIG_CHOICE) { - if (which_choice == MAX_MATCHES_CHOICE) { - // let them pick a new maximum number of matches to find. - request_menu_popup(MAX_MATCHES_MENU_INDEX, av_name, av_key); - return; - } else if (which_choice == CHAT_CHANNEL_CHOICE) { - llSay(0, "To change the chat channel, say '" + channel_string() - + "#channel N' where N is your new channel number."); - return; - } -//more config options... - - } else if (menu_name == MAX_MATCHES_CHOICE) { - integer max = (integer)which_choice; - if (max >= 1) { - // a new number of search matches has been decided upon. - send_data_burst(["max_matches", which_choice]); - llSay(0, "Maximum number of matches is now set to " + (string)max + "."); - return; - } - } - - // cases that aren't handled get forwarded to the client script. - llMessageLinked(LINK_ROOT, SEARCHBERT_MENUS_HUFFWARE_ID + REPLY_DISTANCE, SM_EVENT_MENU_CLICK , - wrap_parameters([menu_name, which_choice, av_name, av_key])); -} - -// borrowed from card configurator. -// sends the currently held data out to whoever requested it. -send_data_burst(list to_send) -{ -//log_it("sending " + (string)llGetListLength(to_send) + " items"); - llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, CARD_CONFIG_RECEIVED_ALERT, - wrap_parameters(["yo-updated"] + to_send)); - to_send = []; // reset any items held. -} - -// set up all the parts of the externally configured bits. -initialize() -{ -//log_it("initializing. memory left=" + (string)llGetFreeMemory()); - llSleep(0.1); // initial pause before chatting with menu manager. - - // reset the menu manager to get it ready for our new menus. - llMessageLinked(LINK_THIS, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_RESET, ""); - - // snooze a bit to allow our helper to wake up. - llSetTimerEvent(0.34); // snooze until helper is ready. - initialized_menus_yet = FALSE; -} - -////////////// -// from hufflets... -// -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -////////////// - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -////////////// - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// looks for an inventory item with the same prefix as the "basename_to_seek". -integer find_basename_in_inventory(string basename_to_seek, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer indy; - for (indy = 0; indy < num_inv; indy++) { - if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) - return indy; - } - return -2; // failed to find it. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize(); - } - - on_rez(integer parm) { llResetScript(); } - - timer() { handle_timer_hit(); } - - link_message(integer sender, integer num, string msg, key id) { - handle_link_message(sender, num, msg, id); - } - -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.txt new file mode 100755 index 00000000..719813c2 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/searchbert_menus_v4.6.txt @@ -0,0 +1,505 @@ + +// huffware script: searchbert menus, by fred huffhines. +// +// manages the menu system for searchbert so the main script is free to do its thing. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +//notes +// + need to have the searchbert initiate anything here. this cannot be free range and +// running even if the searchbert isn't in a menuable mode. +// + is the above true? + +// global constants... + +string MAIN_MENU_NAME = "main"; // name we use in menu list manager for the main menu. +// boilerplate text that's shown at top of main menu. we'll add the channel info later. +string MAIN_MENU_PREFIX = "Quick help: Say '"; +string MAIN_MENU_MIDDLE = "#find XYZ' in chat to locate nearby objects with 'XYZ' in their names.\nSay '"; +string MAIN_MENU_SUFFIX = "#reset' to stop showing a previous search.\n\n[Matches] shows recent search results.\n[Configure] changes options.\n[Reset] clears recent results.\n[Help] dispenses an instruction notecard."; + +// main menu items... +string HELP_CHOICE = "Help"; +string CONFIG_CHOICE = "Configure"; +string MATCHES_CHOICE = "Matches"; +string RESET_CHOICE = "Reset"; + +// configuration menu items... +string MAX_MATCHES_CHOICE = "Max Match"; +string CHAT_CHANNEL_CHOICE = "Channel"; + +// menu indices... +integer MAIN_MENU_INDEX = 0; // we always do main menu as zero. +integer CONFIG_MENU_INDEX = 1; // choices for configurable items. +integer MAX_MATCHES_MENU_INDEX = 2; // changing the number of matches. + +// searchbert menus API. +////////////// +// do not redefine these constants. +integer SEARCHBERT_MENUS_HUFFWARE_ID = 10034; + // the unique id within the huffware system for this script. +////////////// +string SM_CONFIGURE_INFO = "#sm-info#"; + // sets important information this script will use, such as (1) the channel for listening. +string SM_POP_MAIN_MENU_UP = "#sm-main#"; + // causes the main menu to be displayed. this requires an avatar name and avatar key for the + // target of the menu. +////////////// +string SM_EVENT_MENU_CLICK = "#sm-clik#"; + // the user has requested a particular menu item that this script cannot fulfill. the + // event is generated back to the client of this script for handling. it will include (1) the + // menu name in question, (2) the item clicked, (3) the avatar name, and (4) the avatar key. +////////////// + +// imported interfaces... + +// menu list manager link message API. +////////////// +// do not redefine these constants. +integer MENU_LIST_MANAGER_HUFFWARE_ID = 10033; + // the unique id within the huffware system for this sensor plugin script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string MENU_LIST_MGR_RESET = "#ml-reset#"; + // throws out any current menus and gets ready to load a new set. +string MENU_LIST_MGR_ADD_MENU = "#ml-addmenu#"; + // puts a new menu into our list. this requires 3 parameters: menu name, + // menu title, menu button list. +string MENU_LIST_MGR_SHOW_MENU = "#ml-shomenu#"; + // a request that a particular menu be shown. the first parameter is the menu index. + // the second parameter is the avatar name. the third parameter is the avatar key. +string MENU_LIST_MGR_GIVE_ITEM = "#ml-give#"; + // brings up a gift giving menu. parms are avatar name and avatar key. +string MENU_LIST_MGR_MODIFY_MENU = "#ml-modmenu#"; +string MENU_LIST_KEEP_WORD = "KEEP"; + // replaces a menu already in the list. this requires 4 parameters: menu index, menu name, + // menu title, menu button list. if a parameter is the MENU_LIST_KEEP_WORD, then that field + // is not changed. +string MENU_LIST_MGR_CHOICE_MADE_ALERT = "#ml-event-picked"; + // alerts the driver for this script that the owner has picked a choice. the + // parameters include: the text of the choice, the name of the menu, the avatar name, + // the avatar key. +// +////////////// + +// we snag just enough of this interface to masquerade as it... +// card configurator link message API: +////////////// +// do not redefine these constants. +integer CARD_CONFIGURATOR_HUFFWARE_ID = 10042; + // the unique id within the huffware system for the card configurator script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +string CARD_CONFIG_RECEIVED_ALERT = "#cfg-event-upd#"; + // this message is sent when the configurator has found some data updates or has finished + // reading the configuration file. +////////////// + +// global variables... + +integer initialized_menus_yet = FALSE; + // records if the menus have been set up. + +// additional information that's provided by the client script. +integer TALKY_CHANNEL = 0; + +////////////// + +// sends a new menu to be placed in the menu manager. +add_menu(string menu_name, string menu_title, list button_list) +{ + if (llGetListLength(button_list) == 0) { + // patch this degenerate list into a bogus one. + button_list = [ "none" ]; + } + llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_ADD_MENU, + menu_name + HUFFWARE_PARM_SEPARATOR + + menu_title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(button_list)); +} + +// stuffs in a new version of an old menu. +replace_menu(integer index, string menu_name, string menu_title, list button_list) +{ + llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_MODIFY_MENU, + (string)index + HUFFWARE_PARM_SEPARATOR + + menu_name + HUFFWARE_PARM_SEPARATOR + + menu_title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(button_list)); +} + +// sets up the main menu options. if "new_now" is false, then this replaces +// the main menu rather than expecting to add a new one. +establish_main_menu(integer new_now) +{ + // menu zero: this is the main menu. + string menu_name = "main"; + string menu_title = MAIN_MENU_PREFIX + channel_string() + MAIN_MENU_MIDDLE + + channel_string() + MAIN_MENU_SUFFIX; + list menu_button_list = [ MATCHES_CHOICE, CONFIG_CHOICE, RESET_CHOICE, HELP_CHOICE ]; + if (new_now) { + add_menu(menu_name, menu_title, menu_button_list); + } else { + replace_menu(MAIN_MENU_INDEX, menu_name, menu_title, menu_button_list); + } +} + +// sets up all of the static menus for searchbert. +prepare_all_menus() +{ + establish_main_menu(TRUE); // set up the main menu as a new menu. + + // configuration menu provides tasty options for changing the way searchbert behaves. + string menu_name = CONFIG_CHOICE; // reusing menu button from main menu for the menu name. + string menu_title = "Configurable Options...\n[" + MAX_MATCHES_CHOICE + "] selects number of items to find.\n[" + CHAT_CHANNEL_CHOICE + "] changes listening channel for commands.\n"; + list menu_button_list = [ MAX_MATCHES_CHOICE, CHAT_CHANNEL_CHOICE ]; + add_menu(menu_name, menu_title, menu_button_list); + + menu_name = MAX_MATCHES_CHOICE; // reusing menu button from config menu. + menu_title = "Choose a new maximum number of items to find:"; + menu_button_list = produce_nums(17); // ultimate number of arms available (magic constant!). + add_menu(menu_name, menu_title, menu_button_list); + +} + +// if we haven't initialized yet, we'll do it now. +maybe_really_setup_menus() +{ + if (!initialized_menus_yet) { +//log_it("needed initialization still!"); + prepare_all_menus(); + initialized_menus_yet = TRUE; + llSetTimerEvent(0); // stop timer. + return; + } +} + +// deals with the timer elapsing. +handle_timer_hit() +{ + // see if this timer is for initialization purposes. + maybe_really_setup_menus(); +} + +// processes a message requesting our services or updating our info. or ignore it. +handle_link_message(integer sender, integer num, string msg, key id) +{ + if ( (num != MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE) + && (num != SEARCHBERT_MENUS_HUFFWARE_ID) ) + return; + + // make sure we're already initialized. + maybe_really_setup_menus(); + + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + + if (num == MENU_LIST_MANAGER_HUFFWARE_ID + REPLY_DISTANCE) { + if (msg == MENU_LIST_MGR_CHOICE_MADE_ALERT) { + // now deal with the implications of the menu they chose. + process_menu_choice(llList2String(parms, 1), llList2String(parms, 2), + llList2String(parms, 3), llList2String(parms, 0)); + } + return; + } + + // if we got to here, it must be for our main interface methods. +//log_it("got searchbert menu request: " + msg + ". memory left=" + (string)llGetFreeMemory()); + if (msg == SM_CONFIGURE_INFO) { + TALKY_CHANNEL = (integer)llList2String(parms, 0); + establish_main_menu(FALSE); + } else if (msg == SM_POP_MAIN_MENU_UP) { + // show the main menu for the specified avatar. + request_menu_popup(MAIN_MENU_INDEX, llList2String(parms, 0), llList2String(parms, 1)); + } + +} + +request_menu_popup(integer menu_index, string av_name, string av_key) +{ + llMessageLinked(LINK_ROOT, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_SHOW_MENU, + wrap_parameters([menu_index, av_name, av_key])); +//log_it("sent menu popup... memory left=" + (string)llGetFreeMemory()); +} + +// generates a list of numbers up to and including the "max". +list produce_nums(integer max) +{ + list to_return; + integer indy; + for (indy = 1; indy <= max; indy++) { + to_return += (string)indy; + } + return to_return; +} + +// returns the appropriate extra text if the channel is not zero for open chat. +string channel_string() +{ + string add_in_channel = ""; + if (TALKY_CHANNEL != 0) + add_in_channel = "/" + (string)TALKY_CHANNEL + " "; + return add_in_channel; +} + +// handles when a menu has been clicked on. +process_menu_choice(string menu_name, string av_name, string av_key, string which_choice) +{ +//log_it("into process menu " + menu_name + " for " + av_name + " who chose " + which_choice); + if (menu_name == MAIN_MENU_NAME) { + if (which_choice == HELP_CHOICE) { + // see if we can find a helper notecard. + integer indy = find_basename_in_inventory("docs", INVENTORY_NOTECARD); + if (indy < 0) { + llSay(0, "We're very sorry, but there do not seem to be any documentation notecards available. There may be a better version at eepaw shop (osgrid or SL)."); + } else { + string invname = llGetInventoryName(INVENTORY_NOTECARD, indy); + llGiveInventory(av_key, invname); + llWhisper(0, "Here's a copy of the help file: " + invname); + } + return; + } else if (which_choice == CONFIG_CHOICE) { + request_menu_popup(CONFIG_MENU_INDEX, av_name, av_key); + return; + } + // MATCHES_CHOICE falls through for forwarding. + // so does RESET_CHOICE. + } else if (menu_name == CONFIG_CHOICE) { + if (which_choice == MAX_MATCHES_CHOICE) { + // let them pick a new maximum number of matches to find. + request_menu_popup(MAX_MATCHES_MENU_INDEX, av_name, av_key); + return; + } else if (which_choice == CHAT_CHANNEL_CHOICE) { + llSay(0, "To change the chat channel, say '" + channel_string() + + "#channel N' where N is your new channel number."); + return; + } +//more config options... + + } else if (menu_name == MAX_MATCHES_CHOICE) { + integer max = (integer)which_choice; + if (max >= 1) { + // a new number of search matches has been decided upon. + send_data_burst(["max_matches", which_choice]); + llSay(0, "Maximum number of matches is now set to " + (string)max + "."); + return; + } + } + + // cases that aren't handled get forwarded to the client script. + llMessageLinked(LINK_ROOT, SEARCHBERT_MENUS_HUFFWARE_ID + REPLY_DISTANCE, SM_EVENT_MENU_CLICK , + wrap_parameters([menu_name, which_choice, av_name, av_key])); +} + +// borrowed from card configurator. +// sends the currently held data out to whoever requested it. +send_data_burst(list to_send) +{ +//log_it("sending " + (string)llGetListLength(to_send) + " items"); + llMessageLinked(LINK_THIS, CARD_CONFIGURATOR_HUFFWARE_ID + REPLY_DISTANCE, CARD_CONFIG_RECEIVED_ALERT, + wrap_parameters(["yo-updated"] + to_send)); + to_send = []; // reset any items held. +} + +// set up all the parts of the externally configured bits. +initialize() +{ +//log_it("initializing. memory left=" + (string)llGetFreeMemory()); + llSleep(0.1); // initial pause before chatting with menu manager. + + // reset the menu manager to get it ready for our new menus. + llMessageLinked(LINK_THIS, MENU_LIST_MANAGER_HUFFWARE_ID, MENU_LIST_MGR_RESET, ""); + + // snooze a bit to allow our helper to wake up. + llSetTimerEvent(0.34); // snooze until helper is ready. + initialized_menus_yet = FALSE; +} + +////////////// +// from hufflets... +// +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +////////////// + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +////////////// + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// looks for an inventory item with the same prefix as the "basename_to_seek". +integer find_basename_in_inventory(string basename_to_seek, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer indy; + for (indy = 0; indy < num_inv; indy++) { + if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) + return indy; + } + return -2; // failed to find it. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize(); + } + + on_rez(integer parm) { llResetScript(); } + + timer() { handle_timer_hit(); } + + link_message(integer sender, integer num, string msg, key id) { + handle_link_message(sender, num, msg, id); + } + +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.lsl deleted file mode 100755 index b6d06e24..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.lsl +++ /dev/null @@ -1,554 +0,0 @@ - -// huffware script: set comparator, by fred huffhines. -// -// provides a library of functions for managing sets. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// API for set operations. -////////////// -integer SET_COMPARATOR_HUFFWARE_ID = 10020; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string DEFINE_SET_CMD = "#def-set"; - // adds a new set or replaces existing one with same name. first parm is name of set, - // second and further parms are a list of elements that should be in the set. return - // value is a boolean for success. -string REMOVE_SET_CMD = "#rm-set"; - // trashes a named set. first parm is the name. returns a bool for success. -string ADD_ELEMENTS_CMD = "#add-elem"; - // adds more elements to an existing set. first parm is the name, second and more are - // the list of new elements. set must already exist. returns a bool for success. -string CUT_ELEMENTS_CMD = "#cut-elem"; - // removes a set of elements from an existing set. first parm is set name, second etc - // is list of elements to remove. set must already exist. returns bool. -string INTERSECT_CMD = "#inter-set"; - // reports the set of elements in the intersection of two sets. first and second parm - // are the set names. returns a wrapped list of elements that are common members of both sets. -string UNION_CMD = "#union-set"; - // returns the union of two named sets. results sent similar to intersection. -string DIFFERENCE_CMD = "#diff-set"; - // returns the difference of set A (parm 1) minus set B (parm 2). results are similar - // to intersection. -string WHAT_MU_CMD = "#mu-set"; - // returns one of the possibility values below to describe the relationship between - // two sets. -string GET_SET_CMD = "#get-set"; - // retrieves the contents of the set named in first parameter. -string LIST_SET_NAMES_CMD = "#whichunz"; - // retrieves the list of set names that exist. -string CLEAR_ALL_CMD = "#clearall"; - // throws out all set definitions. -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// these are the possible types of set relationships. -string POSSIBILITY_ONE_MEANING = "one meaning (don gcig)"; // same set. -string POSSIBILITY_THREE_POSSES = "proper subset (mu gsum)"; // set A contains set B or vice-versa. -string POSSIBILITY_FOUR_POSSES = "four zones (mu bzhi)"; // non-null intersection, mutual non-null differences. -string POSSIBILITY_MUTUAL_EXCLUDE = "mutually exclusive ('gal ba)"; // no members are shared between the sets. -string POSSIBILITY_ERRONEOUS = "erroneous"; // not a valid request. - -// global variables... - -list all_sets; // a list of condensed lists. -list set_names; // the names of each list in our list. - -integer DEBUGGING = TRUE; // produces noisy logging if true. - -// finds index of named list. -integer find_set(string name_to_find) -{ - return find_in_list(set_names, name_to_find); -} - -// ensures that the list does not contain duplicate members. -list uniquify(list to_strain) { - integer i; - integer j; - for (i = 1; i < llGetListLength(to_strain); i++) { - string curr_i = llList2String(to_strain, i); - for (j = 0; j < i; j++) { - if (llList2String(to_strain, j) == curr_i) { - // this one is a duplicate! argh, remove it at index i. - to_strain = chop_list(to_strain, 0, i - 1) - + chop_list(to_strain, i + 1, llGetListLength(to_strain) - 1); - i--; // skip back since that element no longer exists. - j = i*3; // scoot j out to stop inner loop. - } - } - } - return to_strain; -} - -// this version retrieves bare sets, not ones that are fluffed out from inclusions. -list simple_get_set_by_index(integer index) -{ - if ( (index >= llGetListLength(set_names)) || (index < 0) ) return []; // out of range. - return llParseString2List(llList2String(all_sets, index), [HUFFWARE_ITEM_SEPARATOR], []); -} - - -// adds or replaces the set that is called "name". -integer define_set(string name, list contents) -{ - contents = uniquify(contents); - integer curr = find_set(name); - if (curr >= 0) { - // an existing entry should be updated. - remove_set_by_index(curr); - } - all_sets += [ wrap_item_list(contents) ]; - set_names += [ name ]; -//hmmm: may want to bomb out with false if too much space in use. - return TRUE; -} - -// turns a combination of set linkages into the full set requested. -// assumes that the index is pre-validated! -list evaluate_set_components(integer index) -{ - string wrap = llList2String(all_sets, index); - list to_return = llParseString2List(wrap, [HUFFWARE_ITEM_SEPARATOR], []); - // check for our "equal to set X" case. - if (llGetListLength(to_return) == 1) { - string memb = llList2String(to_return, 0); - if (llGetSubString(memb, 0, 0) == "=") { -//log_it("got a set assignment to other set called: " + llGetSubString(memb, 1, -1)); - // we found a set that's equal to another. look up its equivalent. - index = find_set(llGetSubString(memb, 1, -1)); - if (index < 0) return []; // unknown. - // got another set to check. - wrap = ""; to_return = []; - return evaluate_set_components(index); - } - } - if (llGetListLength(to_return) > 0) { - // scan for set includers. - integer i; - // must iterate forwards, since included sets can also include other sets. - for (i = 0; i < llGetListLength(to_return); i++) { - string curr = llList2String(to_return, i); - if (llGetSubString(curr, 0, 0) == "+") { - // found that this set includes another one. add in the second set, - // but chop out the element we just looked at. - to_return = chop_list(to_return, 0, i - 1) - + chop_list(to_return, i + 1, llGetListLength(to_return) - 1) - + simple_get_set_by_index(find_set(llGetSubString(curr, 1, -1))); - i--; // skip back so we don't omit the new element at i. - } - } - } - return to_return; -} - -// retrieves the specified set from the list using its index. -list get_set_by_index(integer index) -{ - if ( (index >= llGetListLength(set_names)) || (index < 0) ) return []; // out of range. - return evaluate_set_components(index); -} - -// retrieves the specified set from the list using its name. -list get_set_by_name(string set_name) { return get_set_by_index(find_set(set_name)); } - -// drops the set listed at the "index". -integer remove_set_by_index(integer index) -{ - if ( (index >= llGetListLength(set_names)) || (index < 0) ) return FALSE; // out of range. - set_names = llDeleteSubList(set_names, index, index); - all_sets = llDeleteSubList(all_sets, index, index); - return TRUE; -} - -// tosses the set called "set_name". -integer remove_set_by_name(string set_name) { return remove_set_by_index(find_set(set_name)); } - -integer add_items(string name, list new_items) -{ - new_items = uniquify(new_items); - integer curr = find_set(name); - if (curr < 0) return FALSE; // unknown set. - list content = get_set_by_index(curr); - integer i; - for (i = 0; i < llGetListLength(new_items); i++) { - string new_item = llList2String(new_items, i); - integer found = find_in_list(content, new_item); - if (found < 0) { - // was not present yet so add it. - content += [ new_item ]; - } - } - define_set(name, content); - return TRUE; -} - -integer remove_items(string name, list dead_items) -{ - integer curr = find_set(name); - if (curr < 0) return FALSE; // unknown set. - list content = get_set_by_index(curr); - integer i; - for (i = 0; i < llGetListLength(dead_items); i++) { - string dead_item = llList2String(dead_items, i); - integer found = find_in_list(content, dead_item); - if (found >= 0) { - // was not present yet so add it. - content = llDeleteSubList(content, found, found); - } - } - - define_set(name, content); - return TRUE; -} - -// returns the union of two named sets. -list set_union(string set_a, string set_b) -{ - integer where_a = find_set(set_a); - if (where_a < 0) return []; // not known. - integer where_b = find_set(set_b); - if (where_b < 0) return []; - list to_return = get_set_by_index(where_a); - list adding = get_set_by_index(where_b); - integer i; - for (i = 0; i < llGetListLength(adding); i++) { - string curr = llList2String(adding, i); - integer where = find_in_list(to_return, curr); - if (where < 0) { - // wasn't found in to_return, so add it. - to_return += [ curr ]; - } - } - return to_return; -} - -// returns the difference of two named sets. -list set_difference(string set_a, string set_b) -{ - integer where_a = find_set(set_a); - if (where_a < 0) return []; // not known. - integer where_b = find_set(set_b); - if (where_b < 0) return []; - list to_return = get_set_by_index(where_a); - list adding = get_set_by_index(where_b); - integer i; - for (i = 0; i < llGetListLength(adding); i++) { - string curr = llList2String(adding, i); - integer where = find_in_list(to_return, curr); - if (where >= 0) { - // this item does exist in both, so remove it. - to_return = llDeleteSubList(to_return, where, where); - } - } - return to_return; -} - -// returns the intersection of two named sets. -list set_intersection(string set_a, string set_b) -{ - integer where_a = find_set(set_a); - if (where_a < 0) return []; // not known. - integer where_b = find_set(set_b); - if (where_b < 0) return []; - list to_return = []; - list a_con = get_set_by_index(where_a); - list b_con = get_set_by_index(where_b); - integer i; - for (i = 0; i < llGetListLength(b_con); i++) { - string curr = llList2String(b_con, i); - integer where = find_in_list(a_con, curr); - if (where >= 0) { - // this item does exist in both, so include in the result. - to_return += [ curr ]; - } - } - return to_return; -} - -// returns TRUE if minor is a proper subset of major. -integer proper_subset(string minor_set, string major_set) -{ - integer where_a = find_set(minor_set); - if (where_a < 0) return FALSE; // not known. - integer where_b = find_set(major_set); - if (where_b < 0) return FALSE; - list min_con = get_set_by_index(where_a); - list maj_con = get_set_by_index(where_b); - // the list must be smaller to be a proper subset. - if (llGetListLength(min_con) >= llGetListLength(maj_con)) return FALSE; - // now make sure anything in the min is also in maj. if not, it's not - // a subset at all. - integer i; - for (i = 0; i < llGetListLength(min_con); i++) { - string curr = llList2String(min_con, i); - integer where = find_in_list(maj_con, curr); - if (where < 0) return FALSE; - } - // every item was present. yippee. - return TRUE; -} - -// returns an assessment of the two sets in terms of the -// possible relationships between them. -string consider_mu(string set_a, string set_b) -{ - // firstly, validate these set names. - integer where_a = find_set(set_a); - if (where_a < 0) return POSSIBILITY_ERRONEOUS; // not known. - integer where_b = find_set(set_b); - if (where_b < 0) return POSSIBILITY_ERRONEOUS; - if (set_a == set_b) return POSSIBILITY_ONE_MEANING; // easy check. - // check whether they have any common members at all. - list inter = set_intersection(set_a, set_b); - if (inter == []) return POSSIBILITY_MUTUAL_EXCLUDE; - // see if one set is contained in the other. - if (proper_subset(set_a, set_b) - || proper_subset(set_b, set_a) ) { - return POSSIBILITY_THREE_POSSES; - } - // resign ourselves to loading up the sets to check equality. - integer len_a = llGetListLength(get_set_by_index(where_a)); - integer len_b = llGetListLength(get_set_by_index(where_b)); - if (len_a == len_b) { - // this is the only way they can be equivalent. - // simple interpretation of this currently... - list diff = set_difference(set_a, set_b); - if (diff == []) return POSSIBILITY_ONE_MEANING; - // so now, although they are of equal length, we know they are not - // equal sets. - } - // if our logic is correct, there is only one option left. - return POSSIBILITY_FOUR_POSSES; -} - -// this should be invoked from the link_message event handler to process the requests -// for whatever service this library script provides. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ -//log_it("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); - // separate the list out - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - - // we interpret the "msg" as a command. - if (msg == DEFINE_SET_CMD) { - string name = llList2String(parms, 0); - parms = llDeleteSubList(parms, 0, 0); - integer to_return = define_set(name, parms); - send_reply(sender, [ to_return ], msg); - } else if (msg == REMOVE_SET_CMD) { - string name = llList2String(parms, 0); - integer to_return = remove_set_by_name(name); - send_reply(sender, [ to_return ], msg); - } else if (msg == ADD_ELEMENTS_CMD) { - string name = llList2String(parms, 0); - parms = llDeleteSubList(parms, 0, 0); - integer to_return = add_items(name, parms); - send_reply(sender, [ to_return ], msg); - } else if (msg == CUT_ELEMENTS_CMD) { - string name = llList2String(parms, 0); - parms = llDeleteSubList(parms, 0, 0); - integer to_return = remove_items(name, parms); - send_reply(sender, [ to_return ], msg); - } else if (msg == INTERSECT_CMD) { - string name1 = llList2String(parms, 0); - string name2 = llList2String(parms, 1); - list to_return = set_intersection(name1, name2); - send_reply(sender, to_return, msg); - } else if (msg == UNION_CMD) { - string name1 = llList2String(parms, 0); - string name2 = llList2String(parms, 1); - list to_return = set_union(name1, name2); - send_reply(sender, to_return, msg); - } else if (msg == DIFFERENCE_CMD) { - string name1 = llList2String(parms, 0); - string name2 = llList2String(parms, 1); - list to_return = set_difference(name1, name2); - send_reply(sender, to_return, msg); - } else if (msg == WHAT_MU_CMD) { - string name1 = llList2String(parms, 0); - string name2 = llList2String(parms, 1); - string to_return = consider_mu(name1, name2); - send_reply(sender, [ to_return ], msg); - } else if (msg == GET_SET_CMD) { - string name = llList2String(parms, 0); - send_reply(sender, get_set_by_name(name), msg); - } else if (msg == LIST_SET_NAMES_CMD) { - send_reply(sender, set_names, msg); - } else if (msg == CLEAR_ALL_CMD) { - set_names = []; - all_sets = []; - send_reply(sender, [ 1 ], msg); - } else { - log_it("unknown set command: msg=" + msg + " id=" + (string)id); - } -} - - -////////////// -// -// from hufflets... - -// diagnostic hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -////////////// - -// string processing hufflets... - -// the string processing methods are not case sensitive. - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// - -// sim-related hufflets... - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -////////////// - -// list processing hufflets... - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// removes the entry at "index" and instead inserts the list "to_insert" -// at that position. -list replace_entry(list to_modify, integer index, list to_insert) -{ - if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. - return llListReplaceList(to_modify, to_insert, index, index); -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -////////////// - -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// handles when blank strings need to come through the pipe. -string wrap_blank_string(string to_wrap) -{ - if (llStringLength(to_wrap)) return to_wrap; // that one is okay. - return "\"\""; // return a quoted nothing as a signal for a blank. -} - -// undoes a previously wrapped blank string. -string interpret_blank_string(string to_unwrap) -{ - if (to_unwrap == "\"\"") return ""; // that was an encoded blank. - return to_unwrap; // no encoding. -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ -//log_it("reply set: " + dump_list(parms)); - llMessageLinked(destination, SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "'" + next_line + "'"; - } - text += next_line; - if (i < len - 1) text += " "; - } - return text; -} - -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { -// log_it("memory left " + (string)llGetFreeMemory()); -//hmmm: turn this into a report function. - } - - link_message(integer sender, integer num, string str, key id) { - if (num != SET_COMPARATOR_HUFFWARE_ID) return; - handle_link_message(sender, num, str, id); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.txt new file mode 100755 index 00000000..b6d06e24 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/set_comparator_library_v4.1.txt @@ -0,0 +1,554 @@ + +// huffware script: set comparator, by fred huffhines. +// +// provides a library of functions for managing sets. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// API for set operations. +////////////// +integer SET_COMPARATOR_HUFFWARE_ID = 10020; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string DEFINE_SET_CMD = "#def-set"; + // adds a new set or replaces existing one with same name. first parm is name of set, + // second and further parms are a list of elements that should be in the set. return + // value is a boolean for success. +string REMOVE_SET_CMD = "#rm-set"; + // trashes a named set. first parm is the name. returns a bool for success. +string ADD_ELEMENTS_CMD = "#add-elem"; + // adds more elements to an existing set. first parm is the name, second and more are + // the list of new elements. set must already exist. returns a bool for success. +string CUT_ELEMENTS_CMD = "#cut-elem"; + // removes a set of elements from an existing set. first parm is set name, second etc + // is list of elements to remove. set must already exist. returns bool. +string INTERSECT_CMD = "#inter-set"; + // reports the set of elements in the intersection of two sets. first and second parm + // are the set names. returns a wrapped list of elements that are common members of both sets. +string UNION_CMD = "#union-set"; + // returns the union of two named sets. results sent similar to intersection. +string DIFFERENCE_CMD = "#diff-set"; + // returns the difference of set A (parm 1) minus set B (parm 2). results are similar + // to intersection. +string WHAT_MU_CMD = "#mu-set"; + // returns one of the possibility values below to describe the relationship between + // two sets. +string GET_SET_CMD = "#get-set"; + // retrieves the contents of the set named in first parameter. +string LIST_SET_NAMES_CMD = "#whichunz"; + // retrieves the list of set names that exist. +string CLEAR_ALL_CMD = "#clearall"; + // throws out all set definitions. +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// these are the possible types of set relationships. +string POSSIBILITY_ONE_MEANING = "one meaning (don gcig)"; // same set. +string POSSIBILITY_THREE_POSSES = "proper subset (mu gsum)"; // set A contains set B or vice-versa. +string POSSIBILITY_FOUR_POSSES = "four zones (mu bzhi)"; // non-null intersection, mutual non-null differences. +string POSSIBILITY_MUTUAL_EXCLUDE = "mutually exclusive ('gal ba)"; // no members are shared between the sets. +string POSSIBILITY_ERRONEOUS = "erroneous"; // not a valid request. + +// global variables... + +list all_sets; // a list of condensed lists. +list set_names; // the names of each list in our list. + +integer DEBUGGING = TRUE; // produces noisy logging if true. + +// finds index of named list. +integer find_set(string name_to_find) +{ + return find_in_list(set_names, name_to_find); +} + +// ensures that the list does not contain duplicate members. +list uniquify(list to_strain) { + integer i; + integer j; + for (i = 1; i < llGetListLength(to_strain); i++) { + string curr_i = llList2String(to_strain, i); + for (j = 0; j < i; j++) { + if (llList2String(to_strain, j) == curr_i) { + // this one is a duplicate! argh, remove it at index i. + to_strain = chop_list(to_strain, 0, i - 1) + + chop_list(to_strain, i + 1, llGetListLength(to_strain) - 1); + i--; // skip back since that element no longer exists. + j = i*3; // scoot j out to stop inner loop. + } + } + } + return to_strain; +} + +// this version retrieves bare sets, not ones that are fluffed out from inclusions. +list simple_get_set_by_index(integer index) +{ + if ( (index >= llGetListLength(set_names)) || (index < 0) ) return []; // out of range. + return llParseString2List(llList2String(all_sets, index), [HUFFWARE_ITEM_SEPARATOR], []); +} + + +// adds or replaces the set that is called "name". +integer define_set(string name, list contents) +{ + contents = uniquify(contents); + integer curr = find_set(name); + if (curr >= 0) { + // an existing entry should be updated. + remove_set_by_index(curr); + } + all_sets += [ wrap_item_list(contents) ]; + set_names += [ name ]; +//hmmm: may want to bomb out with false if too much space in use. + return TRUE; +} + +// turns a combination of set linkages into the full set requested. +// assumes that the index is pre-validated! +list evaluate_set_components(integer index) +{ + string wrap = llList2String(all_sets, index); + list to_return = llParseString2List(wrap, [HUFFWARE_ITEM_SEPARATOR], []); + // check for our "equal to set X" case. + if (llGetListLength(to_return) == 1) { + string memb = llList2String(to_return, 0); + if (llGetSubString(memb, 0, 0) == "=") { +//log_it("got a set assignment to other set called: " + llGetSubString(memb, 1, -1)); + // we found a set that's equal to another. look up its equivalent. + index = find_set(llGetSubString(memb, 1, -1)); + if (index < 0) return []; // unknown. + // got another set to check. + wrap = ""; to_return = []; + return evaluate_set_components(index); + } + } + if (llGetListLength(to_return) > 0) { + // scan for set includers. + integer i; + // must iterate forwards, since included sets can also include other sets. + for (i = 0; i < llGetListLength(to_return); i++) { + string curr = llList2String(to_return, i); + if (llGetSubString(curr, 0, 0) == "+") { + // found that this set includes another one. add in the second set, + // but chop out the element we just looked at. + to_return = chop_list(to_return, 0, i - 1) + + chop_list(to_return, i + 1, llGetListLength(to_return) - 1) + + simple_get_set_by_index(find_set(llGetSubString(curr, 1, -1))); + i--; // skip back so we don't omit the new element at i. + } + } + } + return to_return; +} + +// retrieves the specified set from the list using its index. +list get_set_by_index(integer index) +{ + if ( (index >= llGetListLength(set_names)) || (index < 0) ) return []; // out of range. + return evaluate_set_components(index); +} + +// retrieves the specified set from the list using its name. +list get_set_by_name(string set_name) { return get_set_by_index(find_set(set_name)); } + +// drops the set listed at the "index". +integer remove_set_by_index(integer index) +{ + if ( (index >= llGetListLength(set_names)) || (index < 0) ) return FALSE; // out of range. + set_names = llDeleteSubList(set_names, index, index); + all_sets = llDeleteSubList(all_sets, index, index); + return TRUE; +} + +// tosses the set called "set_name". +integer remove_set_by_name(string set_name) { return remove_set_by_index(find_set(set_name)); } + +integer add_items(string name, list new_items) +{ + new_items = uniquify(new_items); + integer curr = find_set(name); + if (curr < 0) return FALSE; // unknown set. + list content = get_set_by_index(curr); + integer i; + for (i = 0; i < llGetListLength(new_items); i++) { + string new_item = llList2String(new_items, i); + integer found = find_in_list(content, new_item); + if (found < 0) { + // was not present yet so add it. + content += [ new_item ]; + } + } + define_set(name, content); + return TRUE; +} + +integer remove_items(string name, list dead_items) +{ + integer curr = find_set(name); + if (curr < 0) return FALSE; // unknown set. + list content = get_set_by_index(curr); + integer i; + for (i = 0; i < llGetListLength(dead_items); i++) { + string dead_item = llList2String(dead_items, i); + integer found = find_in_list(content, dead_item); + if (found >= 0) { + // was not present yet so add it. + content = llDeleteSubList(content, found, found); + } + } + + define_set(name, content); + return TRUE; +} + +// returns the union of two named sets. +list set_union(string set_a, string set_b) +{ + integer where_a = find_set(set_a); + if (where_a < 0) return []; // not known. + integer where_b = find_set(set_b); + if (where_b < 0) return []; + list to_return = get_set_by_index(where_a); + list adding = get_set_by_index(where_b); + integer i; + for (i = 0; i < llGetListLength(adding); i++) { + string curr = llList2String(adding, i); + integer where = find_in_list(to_return, curr); + if (where < 0) { + // wasn't found in to_return, so add it. + to_return += [ curr ]; + } + } + return to_return; +} + +// returns the difference of two named sets. +list set_difference(string set_a, string set_b) +{ + integer where_a = find_set(set_a); + if (where_a < 0) return []; // not known. + integer where_b = find_set(set_b); + if (where_b < 0) return []; + list to_return = get_set_by_index(where_a); + list adding = get_set_by_index(where_b); + integer i; + for (i = 0; i < llGetListLength(adding); i++) { + string curr = llList2String(adding, i); + integer where = find_in_list(to_return, curr); + if (where >= 0) { + // this item does exist in both, so remove it. + to_return = llDeleteSubList(to_return, where, where); + } + } + return to_return; +} + +// returns the intersection of two named sets. +list set_intersection(string set_a, string set_b) +{ + integer where_a = find_set(set_a); + if (where_a < 0) return []; // not known. + integer where_b = find_set(set_b); + if (where_b < 0) return []; + list to_return = []; + list a_con = get_set_by_index(where_a); + list b_con = get_set_by_index(where_b); + integer i; + for (i = 0; i < llGetListLength(b_con); i++) { + string curr = llList2String(b_con, i); + integer where = find_in_list(a_con, curr); + if (where >= 0) { + // this item does exist in both, so include in the result. + to_return += [ curr ]; + } + } + return to_return; +} + +// returns TRUE if minor is a proper subset of major. +integer proper_subset(string minor_set, string major_set) +{ + integer where_a = find_set(minor_set); + if (where_a < 0) return FALSE; // not known. + integer where_b = find_set(major_set); + if (where_b < 0) return FALSE; + list min_con = get_set_by_index(where_a); + list maj_con = get_set_by_index(where_b); + // the list must be smaller to be a proper subset. + if (llGetListLength(min_con) >= llGetListLength(maj_con)) return FALSE; + // now make sure anything in the min is also in maj. if not, it's not + // a subset at all. + integer i; + for (i = 0; i < llGetListLength(min_con); i++) { + string curr = llList2String(min_con, i); + integer where = find_in_list(maj_con, curr); + if (where < 0) return FALSE; + } + // every item was present. yippee. + return TRUE; +} + +// returns an assessment of the two sets in terms of the +// possible relationships between them. +string consider_mu(string set_a, string set_b) +{ + // firstly, validate these set names. + integer where_a = find_set(set_a); + if (where_a < 0) return POSSIBILITY_ERRONEOUS; // not known. + integer where_b = find_set(set_b); + if (where_b < 0) return POSSIBILITY_ERRONEOUS; + if (set_a == set_b) return POSSIBILITY_ONE_MEANING; // easy check. + // check whether they have any common members at all. + list inter = set_intersection(set_a, set_b); + if (inter == []) return POSSIBILITY_MUTUAL_EXCLUDE; + // see if one set is contained in the other. + if (proper_subset(set_a, set_b) + || proper_subset(set_b, set_a) ) { + return POSSIBILITY_THREE_POSSES; + } + // resign ourselves to loading up the sets to check equality. + integer len_a = llGetListLength(get_set_by_index(where_a)); + integer len_b = llGetListLength(get_set_by_index(where_b)); + if (len_a == len_b) { + // this is the only way they can be equivalent. + // simple interpretation of this currently... + list diff = set_difference(set_a, set_b); + if (diff == []) return POSSIBILITY_ONE_MEANING; + // so now, although they are of equal length, we know they are not + // equal sets. + } + // if our logic is correct, there is only one option left. + return POSSIBILITY_FOUR_POSSES; +} + +// this should be invoked from the link_message event handler to process the requests +// for whatever service this library script provides. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ +//log_it("link msg: " + (string)sender + " " + (string)huff_id + " msg=" + msg + " id=" + (string)id); + // separate the list out + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + + // we interpret the "msg" as a command. + if (msg == DEFINE_SET_CMD) { + string name = llList2String(parms, 0); + parms = llDeleteSubList(parms, 0, 0); + integer to_return = define_set(name, parms); + send_reply(sender, [ to_return ], msg); + } else if (msg == REMOVE_SET_CMD) { + string name = llList2String(parms, 0); + integer to_return = remove_set_by_name(name); + send_reply(sender, [ to_return ], msg); + } else if (msg == ADD_ELEMENTS_CMD) { + string name = llList2String(parms, 0); + parms = llDeleteSubList(parms, 0, 0); + integer to_return = add_items(name, parms); + send_reply(sender, [ to_return ], msg); + } else if (msg == CUT_ELEMENTS_CMD) { + string name = llList2String(parms, 0); + parms = llDeleteSubList(parms, 0, 0); + integer to_return = remove_items(name, parms); + send_reply(sender, [ to_return ], msg); + } else if (msg == INTERSECT_CMD) { + string name1 = llList2String(parms, 0); + string name2 = llList2String(parms, 1); + list to_return = set_intersection(name1, name2); + send_reply(sender, to_return, msg); + } else if (msg == UNION_CMD) { + string name1 = llList2String(parms, 0); + string name2 = llList2String(parms, 1); + list to_return = set_union(name1, name2); + send_reply(sender, to_return, msg); + } else if (msg == DIFFERENCE_CMD) { + string name1 = llList2String(parms, 0); + string name2 = llList2String(parms, 1); + list to_return = set_difference(name1, name2); + send_reply(sender, to_return, msg); + } else if (msg == WHAT_MU_CMD) { + string name1 = llList2String(parms, 0); + string name2 = llList2String(parms, 1); + string to_return = consider_mu(name1, name2); + send_reply(sender, [ to_return ], msg); + } else if (msg == GET_SET_CMD) { + string name = llList2String(parms, 0); + send_reply(sender, get_set_by_name(name), msg); + } else if (msg == LIST_SET_NAMES_CMD) { + send_reply(sender, set_names, msg); + } else if (msg == CLEAR_ALL_CMD) { + set_names = []; + all_sets = []; + send_reply(sender, [ 1 ], msg); + } else { + log_it("unknown set command: msg=" + msg + " id=" + (string)id); + } +} + + +////////////// +// +// from hufflets... + +// diagnostic hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +////////////// + +// string processing hufflets... + +// the string processing methods are not case sensitive. + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// + +// sim-related hufflets... + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +////////////// + +// list processing hufflets... + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// removes the entry at "index" and instead inserts the list "to_insert" +// at that position. +list replace_entry(list to_modify, integer index, list to_insert) +{ + if (llGetListLength(to_modify) == 0) return to_insert; // special case for empty. + return llListReplaceList(to_modify, to_insert, index, index); +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +////////////// + +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// handles when blank strings need to come through the pipe. +string wrap_blank_string(string to_wrap) +{ + if (llStringLength(to_wrap)) return to_wrap; // that one is okay. + return "\"\""; // return a quoted nothing as a signal for a blank. +} + +// undoes a previously wrapped blank string. +string interpret_blank_string(string to_unwrap) +{ + if (to_unwrap == "\"\"") return ""; // that was an encoded blank. + return to_unwrap; // no encoding. +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ +//log_it("reply set: " + dump_list(parms)); + llMessageLinked(destination, SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "'" + next_line + "'"; + } + text += next_line; + if (i < len - 1) text += " "; + } + return text; +} + +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { +// log_it("memory left " + (string)llGetFreeMemory()); +//hmmm: turn this into a report function. + } + + link_message(integer sender, integer num, string str, key id) { + if (num != SET_COMPARATOR_HUFFWARE_ID) return; + handle_link_message(sender, num, str, id); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.lsl deleted file mode 100755 index 66059a4b..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.lsl +++ /dev/null @@ -1,363 +0,0 @@ - -// huffware script: slate reader, by fred huffhines -// -// uses the noteworthy library to read a set of notecards. the list of notecards -// can be queried, and the current notecard's contents can be read aloud or sent -// to a link as link messages. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -string SLATE_SIGNATURE = "#slate"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -// global variables... - -integer response_code; // set to uniquely identify the notecard read in progress. -integer global_link_num; // which prim number to deliver the notecard contents to. - -// implements an API for moving between the active notecards. -////////////// -// do not redefine these constants. -integer SLATE_READER_HUFFWARE_ID = 10028; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string RESET_SLATE_READER_COMMAND = "#rsslt"; - // causes the notecard information to be forgotten and the script restarted. -string SR_GET_INFORMATION_COMMAND = "#infy"; - // used by clients to ask for information about the current number of notecards - // available, and their names. this information is sent back on the huffware ID - // plus the reply distance. first parm is the number, and the rest are the names. -string SR_PLAY_CARD_COMMAND = "#playvo"; - // picks a particular notecard for reading and send the notecard's contents in a - // series of link messages, using this command and the reply distance. there are - // two parameters: an integer for the notecard number to read (from 0 through the - // number of notecards - 1) and the link number to send the messages to. -////////////// - -// requires noteworthy library v10.4 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration(string note_name) -{ - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([SLATE_SIGNATURE, response_code, note_name]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_SPECIFIC_NOTECARD_COMMAND, - parms_sent); -} - -// provides the functions of the slate reader API. -process_slate_requests(string msg, key id) -{ - if (msg == RESET_SLATE_READER_COMMAND) { - llResetScript(); - } else if (msg == SR_GET_INFORMATION_COMMAND) { - list parms = [ llGetInventoryNumber(INVENTORY_NOTECARD) ]; - integer indy; - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) { - parms += llGetInventoryName(INVENTORY_NOTECARD, indy); - } - llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE, msg, - wrap_parameters(parms)); - } else if (msg == SR_PLAY_CARD_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer note_number = llList2Integer(parms, 0); - integer link_number = llList2Integer(parms, 1); - initialize_reader(note_number, link_number); - } -} - -// processes link messages received from the noteworthy library. -handle_link_message(integer which, integer num, string msg, key id) -{ - if (num == SLATE_READER_HUFFWARE_ID) { - process_slate_requests(msg, id); - return; - } - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) - return; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return; // oops, this isn't for us. - if (notecard_name == BAD_NOTECARD_INDICATOR) { - // we hated the notecards we found, or there were none. - log_it("We apologize; there seem to be no notecards with a first line of '" - + SLATE_SIGNATURE - + "'. We can't read any configuration until that situation improves."); - } else { - // snag all but the first two elements for our config now. - list config_list = llList2List(parms, 2, -1); - // a valid notecard has been found. - integer lines_to_say = llGetListLength(config_list); - integer indy; - for (indy = 0; indy < lines_to_say; indy++) { - string line = llList2String(config_list, indy); - if (!is_prefix(line, "#")) { - llMessageLinked(global_link_num, SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE, - SR_PLAY_CARD_COMMAND, line); - } - } - } -} - -/////////////// - -initialize_reader(integer note_number, integer link_number) -{ - // reset our relevant variables. - global_link_num = link_number; - - if (note_number >= llGetInventoryNumber(INVENTORY_NOTECARD)) { - llSay(0, "Cannot initialize reader to notecard number " + (string)note_number + " because that is out of range."); - return; - } - string notecard_name = llGetInventoryName(INVENTORY_NOTECARD, note_number); - - // request that the noteworthy library start looking for our notecard. - request_configuration(notecard_name); -} - -////////////// -// from hufflets... -// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - } - -// on_rez(integer parm) { llResetScript(); } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.txt new file mode 100755 index 00000000..66059a4b --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/slate_reader_v1.2.txt @@ -0,0 +1,363 @@ + +// huffware script: slate reader, by fred huffhines +// +// uses the noteworthy library to read a set of notecards. the list of notecards +// can be queried, and the current notecard's contents can be read aloud or sent +// to a link as link messages. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +string SLATE_SIGNATURE = "#slate"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +// global variables... + +integer response_code; // set to uniquely identify the notecard read in progress. +integer global_link_num; // which prim number to deliver the notecard contents to. + +// implements an API for moving between the active notecards. +////////////// +// do not redefine these constants. +integer SLATE_READER_HUFFWARE_ID = 10028; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string RESET_SLATE_READER_COMMAND = "#rsslt"; + // causes the notecard information to be forgotten and the script restarted. +string SR_GET_INFORMATION_COMMAND = "#infy"; + // used by clients to ask for information about the current number of notecards + // available, and their names. this information is sent back on the huffware ID + // plus the reply distance. first parm is the number, and the rest are the names. +string SR_PLAY_CARD_COMMAND = "#playvo"; + // picks a particular notecard for reading and send the notecard's contents in a + // series of link messages, using this command and the reply distance. there are + // two parameters: an integer for the notecard number to read (from 0 through the + // number of notecards - 1) and the link number to send the messages to. +////////////// + +// requires noteworthy library v10.4 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration(string note_name) +{ + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([SLATE_SIGNATURE, response_code, note_name]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_SPECIFIC_NOTECARD_COMMAND, + parms_sent); +} + +// provides the functions of the slate reader API. +process_slate_requests(string msg, key id) +{ + if (msg == RESET_SLATE_READER_COMMAND) { + llResetScript(); + } else if (msg == SR_GET_INFORMATION_COMMAND) { + list parms = [ llGetInventoryNumber(INVENTORY_NOTECARD) ]; + integer indy; + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) { + parms += llGetInventoryName(INVENTORY_NOTECARD, indy); + } + llMessageLinked(LINK_THIS, SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE, msg, + wrap_parameters(parms)); + } else if (msg == SR_PLAY_CARD_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer note_number = llList2Integer(parms, 0); + integer link_number = llList2Integer(parms, 1); + initialize_reader(note_number, link_number); + } +} + +// processes link messages received from the noteworthy library. +handle_link_message(integer which, integer num, string msg, key id) +{ + if (num == SLATE_READER_HUFFWARE_ID) { + process_slate_requests(msg, id); + return; + } + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) + return; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return; // oops, this isn't for us. + if (notecard_name == BAD_NOTECARD_INDICATOR) { + // we hated the notecards we found, or there were none. + log_it("We apologize; there seem to be no notecards with a first line of '" + + SLATE_SIGNATURE + + "'. We can't read any configuration until that situation improves."); + } else { + // snag all but the first two elements for our config now. + list config_list = llList2List(parms, 2, -1); + // a valid notecard has been found. + integer lines_to_say = llGetListLength(config_list); + integer indy; + for (indy = 0; indy < lines_to_say; indy++) { + string line = llList2String(config_list, indy); + if (!is_prefix(line, "#")) { + llMessageLinked(global_link_num, SLATE_READER_HUFFWARE_ID + REPLY_DISTANCE, + SR_PLAY_CARD_COMMAND, line); + } + } + } +} + +/////////////// + +initialize_reader(integer note_number, integer link_number) +{ + // reset our relevant variables. + global_link_num = link_number; + + if (note_number >= llGetInventoryNumber(INVENTORY_NOTECARD)) { + llSay(0, "Cannot initialize reader to notecard number " + (string)note_number + " because that is out of range."); + return; + } + string notecard_name = llGetInventoryName(INVENTORY_NOTECARD, note_number); + + // request that the noteworthy library start looking for our notecard. + request_configuration(notecard_name); +} + +////////////// +// from hufflets... +// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + } + +// on_rez(integer parm) { llResetScript(); } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.lsl deleted file mode 100755 index 8016e42f..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.lsl +++ /dev/null @@ -1,11 +0,0 @@ -#sitting -# for star chair. -avatar_rotation = <0, 0, -90> -avatar_position = <-0.1, -0.28, -0.1> -which_floor_is_this=1 -base_floor_height = 0 -floor_size_in_meters=0 -unseat_afterwards = 0 -pause_before_eviction = 0.28 -camera_eye_offset = <3, 2, 1.5> -camera_target = <-3, 0, 1> diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.txt new file mode 100755 index 00000000..8016e42f --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/star_chair_sitting_config_v0.4.txt @@ -0,0 +1,11 @@ +#sitting +# for star chair. +avatar_rotation = <0, 0, -90> +avatar_position = <-0.1, -0.28, -0.1> +which_floor_is_this=1 +base_floor_height = 0 +floor_size_in_meters=0 +unseat_afterwards = 0 +pause_before_eviction = 0.28 +camera_eye_offset = <3, 2, 1.5> +camera_target = <-3, 0, 1> diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.lsl deleted file mode 100755 index 62af88d2..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.lsl +++ /dev/null @@ -1,19 +0,0 @@ - -// huffware script: take touches, by fred huffhines. -// -// eats any touches from an avatar so that other prims do not know they happened. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -default -{ - state_entry() { } - - touch_start(integer total_number) - { - // do nothing. - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.txt new file mode 100755 index 00000000..62af88d2 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/take_touches_v0.2.txt @@ -0,0 +1,19 @@ + +// huffware script: take touches, by fred huffhines. +// +// eats any touches from an avatar so that other prims do not know they happened. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +default +{ + state_entry() { } + + touch_start(integer total_number) + { + // do nothing. + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.lsl deleted file mode 100755 index 0fddf076..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.lsl +++ /dev/null @@ -1,170 +0,0 @@ - -// huffware script: text label, by fred huffhines -// -// a super simple script for giving an object readable text. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -string OBJECT_LABEL = "default"; // change this if you want a specific name. - -vector LABEL_COLOR = <0.3, 0.9, 0.4>; // color of the text above object. - -set_text() -{ - string object_label = OBJECT_LABEL; - // reset the label to a decorated version of object name if it was default. - if (object_label == "default") object_label = llGetObjectName(); - integer indy; - integer keep_going = TRUE; - while (keep_going) { - indy = find_substring(object_label, "\\n"); - if (indy < 0) { - keep_going = FALSE; - } else { - object_label = llGetSubString(object_label, 0, indy - 1) - + "\n" + llGetSubString(object_label, indy + 2, -1); - } - } -//log_it("setting text: " + object_label); - llSetText(object_label, LABEL_COLOR, 1.0); -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//end hufflets... -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); set_text(); } - on_rez(integer start_parm) { state default; } - touch_start(integer count) { set_text(); } - changed(integer change) { if (change & CHANGED_INVENTORY) set_text(); } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.txt new file mode 100755 index 00000000..0fddf076 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/text_label_v3.9.txt @@ -0,0 +1,170 @@ + +// huffware script: text label, by fred huffhines +// +// a super simple script for giving an object readable text. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +string OBJECT_LABEL = "default"; // change this if you want a specific name. + +vector LABEL_COLOR = <0.3, 0.9, 0.4>; // color of the text above object. + +set_text() +{ + string object_label = OBJECT_LABEL; + // reset the label to a decorated version of object name if it was default. + if (object_label == "default") object_label = llGetObjectName(); + integer indy; + integer keep_going = TRUE; + while (keep_going) { + indy = find_substring(object_label, "\\n"); + if (indy < 0) { + keep_going = FALSE; + } else { + object_label = llGetSubString(object_label, 0, indy - 1) + + "\n" + llGetSubString(object_label, indy + 2, -1); + } + } +//log_it("setting text: " + object_label); + llSetText(object_label, LABEL_COLOR, 1.0); +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//end hufflets... +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); set_text(); } + on_rez(integer start_parm) { state default; } + touch_start(integer count) { set_text(); } + changed(integer change) { if (change & CHANGED_INVENTORY) set_text(); } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.lsl deleted file mode 100755 index 57a1e641..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.lsl +++ /dev/null @@ -1,237 +0,0 @@ - -// huffware script: texture mover, by fred huffhines -// -// moves a texture across the object, either by smooth animation or brute force offsetting. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -integer USE_TEXTURE_ANIMATION = TRUE; - // by default, we use texture animation which is a lower-lag way to - // make the texture move. if this is false, then we use a timed update - // to move the texture instead. - // note: these modes are actually really different. the texture animation - // is included here because i wanted to smooth out some objects that used - // texture movement. - -// used in both types... - -float TIMER_INTERVAL = 0.2; // how fast do we move texture? - -// for timed movement... - -vector OFFSET_MOVEMENT = ZERO_VECTOR; // no movement. -//vector OFFSET_MOVEMENT = <0.0, -0.02, 0.0>; - // how much to move the texture by in x,y,z directions. - -//float OFFSET_ROTATION = 0.0; // in degrees. -float OFFSET_ROTATION = -1.0; // in degrees. - -// for texture animations... - -float MOVER_TIMER_DIVISOR = 30.0; - // makes the movement comparable to timed method. - -float ROTATER_TIMER_DIVISOR = 7.0; - // makes the rotation comparable to timed method. - -// iterative movement of texture. -move_texture(vector offset) -{ - vector current = llGetTextureOffset(ALL_SIDES); - current += offset; - if (current.x > 1.0) current.x = -1.0; - if (current.x < -1.0) current.x = 1.0; - if (current.y > 1.0) current.y = -1.0; - if (current.y < -1.0) current.y = 1.0; - llOffsetTexture(current.x, current.y, ALL_SIDES); -} - -// iterative rotation of texture. "spin" is measured in degrees. -spin_texture(float spin) -{ - float rot = llGetTextureRot(ALL_SIDES); // get our current state. - rot += spin * DEG_TO_RAD; // add some rotation. - llRotateTexture(rot, ALL_SIDES); //rotate the object -} - -initialize_texture_mover() -{ - if (!USE_TEXTURE_ANIMATION) { - // we're stuck with the timed update style for movement. - llSetTimerEvent(TIMER_INTERVAL); - // turn off previous animation. - llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); - } else { - // we can just set the texture movement here and be done with it. - integer x_frames = 1; - integer y_frames = 1; - llSetTimerEvent(0); // we don't use a timer. - -//hmmm: how do we combine rotation and offsets? currently mutually exclusive. - - if (OFFSET_MOVEMENT != ZERO_VECTOR) { - float timer_interval = TIMER_INTERVAL / MOVER_TIMER_DIVISOR; -log_it("getting x_frames=" + (string)x_frames -+ " y_frames=" + (string)y_frames -+ " timer_intvl=" + (string)timer_interval); - - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, - x_frames, y_frames, - 0, 100, timer_interval); - } else if (OFFSET_ROTATION != 0.0) { - float timer_interval = TIMER_INTERVAL / ROTATER_TIMER_DIVISOR; - // we're actually not using the rotation at all here, except for - // the sign. that seems pretty busted. - if (OFFSET_ROTATION < 0) timer_interval *= -1.0; - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, ALL_SIDES, - 0, 0, - 0, TWO_PI, timer_interval); - } - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} -// -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize_texture_mover(); - } - - timer() { - // the timed approach is the only one so far that allows both a - // movement of the texture and a rotation. - if (OFFSET_MOVEMENT != ZERO_VECTOR) move_texture(OFFSET_MOVEMENT); - if (OFFSET_ROTATION != 0.0) spin_texture(OFFSET_ROTATION); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.txt new file mode 100755 index 00000000..57a1e641 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_mover_v3.0.txt @@ -0,0 +1,237 @@ + +// huffware script: texture mover, by fred huffhines +// +// moves a texture across the object, either by smooth animation or brute force offsetting. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +integer USE_TEXTURE_ANIMATION = TRUE; + // by default, we use texture animation which is a lower-lag way to + // make the texture move. if this is false, then we use a timed update + // to move the texture instead. + // note: these modes are actually really different. the texture animation + // is included here because i wanted to smooth out some objects that used + // texture movement. + +// used in both types... + +float TIMER_INTERVAL = 0.2; // how fast do we move texture? + +// for timed movement... + +vector OFFSET_MOVEMENT = ZERO_VECTOR; // no movement. +//vector OFFSET_MOVEMENT = <0.0, -0.02, 0.0>; + // how much to move the texture by in x,y,z directions. + +//float OFFSET_ROTATION = 0.0; // in degrees. +float OFFSET_ROTATION = -1.0; // in degrees. + +// for texture animations... + +float MOVER_TIMER_DIVISOR = 30.0; + // makes the movement comparable to timed method. + +float ROTATER_TIMER_DIVISOR = 7.0; + // makes the rotation comparable to timed method. + +// iterative movement of texture. +move_texture(vector offset) +{ + vector current = llGetTextureOffset(ALL_SIDES); + current += offset; + if (current.x > 1.0) current.x = -1.0; + if (current.x < -1.0) current.x = 1.0; + if (current.y > 1.0) current.y = -1.0; + if (current.y < -1.0) current.y = 1.0; + llOffsetTexture(current.x, current.y, ALL_SIDES); +} + +// iterative rotation of texture. "spin" is measured in degrees. +spin_texture(float spin) +{ + float rot = llGetTextureRot(ALL_SIDES); // get our current state. + rot += spin * DEG_TO_RAD; // add some rotation. + llRotateTexture(rot, ALL_SIDES); //rotate the object +} + +initialize_texture_mover() +{ + if (!USE_TEXTURE_ANIMATION) { + // we're stuck with the timed update style for movement. + llSetTimerEvent(TIMER_INTERVAL); + // turn off previous animation. + llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); + } else { + // we can just set the texture movement here and be done with it. + integer x_frames = 1; + integer y_frames = 1; + llSetTimerEvent(0); // we don't use a timer. + +//hmmm: how do we combine rotation and offsets? currently mutually exclusive. + + if (OFFSET_MOVEMENT != ZERO_VECTOR) { + float timer_interval = TIMER_INTERVAL / MOVER_TIMER_DIVISOR; +log_it("getting x_frames=" + (string)x_frames ++ " y_frames=" + (string)y_frames ++ " timer_intvl=" + (string)timer_interval); + + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, + x_frames, y_frames, + 0, 100, timer_interval); + } else if (OFFSET_ROTATION != 0.0) { + float timer_interval = TIMER_INTERVAL / ROTATER_TIMER_DIVISOR; + // we're actually not using the rotation at all here, except for + // the sign. that seems pretty busted. + if (OFFSET_ROTATION < 0) timer_interval *= -1.0; + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, ALL_SIDES, + 0, 0, + 0, TWO_PI, timer_interval); + } + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} +// +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize_texture_mover(); + } + + timer() { + // the timed approach is the only one so far that allows both a + // movement of the texture and a rotation. + if (OFFSET_MOVEMENT != ZERO_VECTOR) move_texture(OFFSET_MOVEMENT); + if (OFFSET_ROTATION != 0.0) spin_texture(OFFSET_ROTATION); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.lsl deleted file mode 100755 index 629dd587..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.lsl +++ /dev/null @@ -1,480 +0,0 @@ - -// huffware script: texture shower, by fred huffhines. -// -// displays a texture from its inventory when the name is spoken in chat. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - - -// global constants... - -string SHOWER_SIGNATURE = "#texture_shower"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -// global variables... - -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -list texture_names; // the set of textures we've got in inventory. - -integer LISTENING_CHANNEL = 1008; - // the default listening channel is hardly ever used; the channel should - // come from the notecard. - -////////////// - -// processes the variables that come from the notecard. -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - if ( (content = get_variable_value(to_parse, "channel")) != "") { -// log_it("channel=" + content); - LISTENING_CHANNEL = (integer)content; - } -} - -////////////// - -// sets the viewing sides' textures to a particular inventory item. -set_texture_to_item(string inv_tex) -{ - llSetTexture(inv_tex, 1); - llSetTexture(inv_tex, 3); -} - -// sets our viewing sides back to the default texture. -reset_textures() -{ - string tex_cur = llGetTexture(0); - set_texture_to_item(tex_cur); -} - -// startup for the very early part of the object's lifetime. -initialize_phase_1() -{ - // reset our relevant variables. - global_notecard_name = ""; - global_config_list = []; - global_config_index = 0; - texture_names = []; - - // request that the noteworthy library start looking for our notecard. - request_configuration(); - -// log_it("started, free mem=" + (string)llGetFreeMemory()); -} - -// this gets us ready to enter our active state. -initialize_phase_2() -{ - // listen for commands on the channel we're configured for. - llListen(LISTENING_CHANNEL, "", NULL_KEY, ""); - // load all the texture names we know about. - integer texture_count = llGetInventoryNumber(INVENTORY_TEXTURE); - integer indy; - for (indy = 0; indy < texture_count; indy++) - texture_names += llGetInventoryName(INVENTORY_TEXTURE, indy); -} - -manage_those_voices(integer channel, string message) -{ - if (channel != LISTENING_CHANNEL) return; // not for us. - if (message == "reset-texture") { - reset_textures(); - return; - } - // wasn't a command to reset, so let's see if we know it. - integer texture_count = llGetListLength(texture_names); - integer indy; - for (indy = 0; indy < texture_count; indy++) { - integer posn = llListFindList(texture_names, (message)); - if (posn >= 0) { - // found one... - set_texture_to_item(message); - return; - } - } -} - -////////////// - -// this chunk largely comes from the example noteworthy usage... - -// requires noteworthy library v8.4 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or "bad_notecard" if none was found) and - // as subsequent elements an embedded list that was read from the notecard. this - // necessarily limits the size of the notecards that we can read and return. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - global_notecard_name = ""; // reset any previous card. - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([SHOWER_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from the noteworthy library and others. -// if the message indicates we should change states, then TRUE is returned. -integer handle_link_message(integer which, integer num, string msg, key id) -{ - if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - return FALSE; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return FALSE; // oops, this isn't for us. - if (notecard_name != "bad_notecard") { - // a valid notecard has been found. - global_notecard_name = notecard_name; // record its name for later use. - global_config_index = 0; // we are starting over in the config list. - // snag all but the first two elements for our config now. - global_config_list = llList2List(parms, 2, -1); - // and process the file as a set of definitions. - process_ini_config(); - return TRUE; - } else { - // we hated the notecards we found, or there were none. - log_it("We apologize; there seem to be no notecards with a first line of '" - + SHOWER_SIGNATURE - + "'. We can't read any configuration until that situation improves."); - } - return FALSE; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -////////////// -// from hufflets... -// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ strip_spaces(x), strip_spaces(y) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ -// log_it("scanning notecard for variable definitions..."); - integer indy; - integer count = llGetListLength(global_config_list); - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - log_it("reading section: " + llGetSubString(line, 1, -2)); - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} -// end hufflets -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. - initialize_phase_1(); - } - - on_rez(integer param) { state rerun; } - - // reset when we see changes to our notecard configuration. - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(3.14159265358); // delay to avoid interfering with upgrade. - state rerun; - } - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) { - integer retval = handle_link_message(which, num, msg, id); - if (retval) state configured; // skip states if we were asked to. - } -} - -state configured -{ - state_entry() { - initialize_phase_2(); - } - - listen(integer channel, string name, key id, string message) { - manage_those_voices(channel, message); - } - - link_message(integer which, integer num, string msg, key id) { - manage_those_voices(num, msg); - } - - // reset when we see changes to our notecard configuration. - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(3.14159265358); // delay to avoid interfering with upgrade. - state default; - } - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.txt new file mode 100755 index 00000000..629dd587 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/texture_shower_v2.7.txt @@ -0,0 +1,480 @@ + +// huffware script: texture shower, by fred huffhines. +// +// displays a texture from its inventory when the name is spoken in chat. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + + +// global constants... + +string SHOWER_SIGNATURE = "#texture_shower"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +// global variables... + +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +list texture_names; // the set of textures we've got in inventory. + +integer LISTENING_CHANNEL = 1008; + // the default listening channel is hardly ever used; the channel should + // come from the notecard. + +////////////// + +// processes the variables that come from the notecard. +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + if ( (content = get_variable_value(to_parse, "channel")) != "") { +// log_it("channel=" + content); + LISTENING_CHANNEL = (integer)content; + } +} + +////////////// + +// sets the viewing sides' textures to a particular inventory item. +set_texture_to_item(string inv_tex) +{ + llSetTexture(inv_tex, 1); + llSetTexture(inv_tex, 3); +} + +// sets our viewing sides back to the default texture. +reset_textures() +{ + string tex_cur = llGetTexture(0); + set_texture_to_item(tex_cur); +} + +// startup for the very early part of the object's lifetime. +initialize_phase_1() +{ + // reset our relevant variables. + global_notecard_name = ""; + global_config_list = []; + global_config_index = 0; + texture_names = []; + + // request that the noteworthy library start looking for our notecard. + request_configuration(); + +// log_it("started, free mem=" + (string)llGetFreeMemory()); +} + +// this gets us ready to enter our active state. +initialize_phase_2() +{ + // listen for commands on the channel we're configured for. + llListen(LISTENING_CHANNEL, "", NULL_KEY, ""); + // load all the texture names we know about. + integer texture_count = llGetInventoryNumber(INVENTORY_TEXTURE); + integer indy; + for (indy = 0; indy < texture_count; indy++) + texture_names += llGetInventoryName(INVENTORY_TEXTURE, indy); +} + +manage_those_voices(integer channel, string message) +{ + if (channel != LISTENING_CHANNEL) return; // not for us. + if (message == "reset-texture") { + reset_textures(); + return; + } + // wasn't a command to reset, so let's see if we know it. + integer texture_count = llGetListLength(texture_names); + integer indy; + for (indy = 0; indy < texture_count; indy++) { + integer posn = llListFindList(texture_names, (message)); + if (posn >= 0) { + // found one... + set_texture_to_item(message); + return; + } + } +} + +////////////// + +// this chunk largely comes from the example noteworthy usage... + +// requires noteworthy library v8.4 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or "bad_notecard" if none was found) and + // as subsequent elements an embedded list that was read from the notecard. this + // necessarily limits the size of the notecards that we can read and return. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + global_notecard_name = ""; // reset any previous card. + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([SHOWER_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from the noteworthy library and others. +// if the message indicates we should change states, then TRUE is returned. +integer handle_link_message(integer which, integer num, string msg, key id) +{ + if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + return FALSE; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return FALSE; // oops, this isn't for us. + if (notecard_name != "bad_notecard") { + // a valid notecard has been found. + global_notecard_name = notecard_name; // record its name for later use. + global_config_index = 0; // we are starting over in the config list. + // snag all but the first two elements for our config now. + global_config_list = llList2List(parms, 2, -1); + // and process the file as a set of definitions. + process_ini_config(); + return TRUE; + } else { + // we hated the notecards we found, or there were none. + log_it("We apologize; there seem to be no notecards with a first line of '" + + SHOWER_SIGNATURE + + "'. We can't read any configuration until that situation improves."); + } + return FALSE; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +////////////// +// from hufflets... +// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ strip_spaces(x), strip_spaces(y) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ +// log_it("scanning notecard for variable definitions..."); + integer indy; + integer count = llGetListLength(global_config_list); + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + log_it("reading section: " + llGetSubString(line, 1, -2)); + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} +// end hufflets +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. + initialize_phase_1(); + } + + on_rez(integer param) { state rerun; } + + // reset when we see changes to our notecard configuration. + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(3.14159265358); // delay to avoid interfering with upgrade. + state rerun; + } + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) { + integer retval = handle_link_message(which, num, msg, id); + if (retval) state configured; // skip states if we were asked to. + } +} + +state configured +{ + state_entry() { + initialize_phase_2(); + } + + listen(integer channel, string name, key id, string message) { + manage_those_voices(channel, message); + } + + link_message(integer which, integer num, string msg, key id) { + manage_those_voices(num, msg); + } + + // reset when we see changes to our notecard configuration. + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(3.14159265358); // delay to avoid interfering with upgrade. + state default; + } + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.lsl deleted file mode 100755 index beed1fc7..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.lsl +++ /dev/null @@ -1,205 +0,0 @@ - -// huffware script: viewscreen blitter, by fred huffhines. -// -// listens for web addresses to show and puts them on the screen of this prim. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// important switches... - -integer IS_OPENSIM = TRUE; - // selects the major mode of operation for the viewscreen. - -integer DEBUGGING = TRUE; - // if this is set to true, more diagnostic info is printed than normal. - -// global constants... - -// API for the viewscreen blitter library... -////////////// -integer VIEWSCREEN_BLITTER_HUFFWARE_ID = 10027; - // unique ID for the viewscreen services. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// -string SHOW_URL_COMMAND = "#shurl"; - // requests the viewscreen to show a particular URL as its texture. -string RESET_VIEWSCREEN_COMMAND = "#shrz"; - // resets the viewscreen script to the default state. -string SHOW_TEXTURE_COMMAND = "#shtex"; - // displays a texture on the prim. the first parameter is the texture key or name. -////////////// - -// configurable constants... - -handle_view_request(string command, string parms) -{ - if (command == SHOW_URL_COMMAND) { - // the parms is just the URL to display. - if (DEBUGGING) { - string to_show = "url is: "; - integer i; - for (i = 0; i < llStringLength(parms); i += 512) { - // show the string a chunk at a time or we will be censored by chat limits. - integer end = i + 511; - if (i >= llStringLength(parms) - 1) i = llStringLength(parms) - 1; - to_show += llGetSubString(parms, i, end); - llSay(0, to_show); - to_show = ""; - } - } - if (!IS_OPENSIM) { - // second life implementation... - llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_STOP, - PARCEL_MEDIA_COMMAND_TYPE, "text/html", - PARCEL_MEDIA_COMMAND_URL, parms ] ); - // we separate out the looping player call since we can't rely on the new media - // setting being ready within the same media call. - llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_PLAY, PARCEL_MEDIA_COMMAND_LOOP ] ); - } else { - // opensim implementation... - string extra_parms = ""; - //bgcolor:white,alpha:false,width:1024,height:768, - string url_texture_key = osSetDynamicTextureURL("", "image", parms, extra_parms, 5000); -//string url_texture_key =""; - -//llSay(0, "dyn texture is " + url_texture_key); - if (url_texture_key != "") { - llSetTexture(url_texture_key, ALL_SIDES); - } - } - } else if (command == RESET_VIEWSCREEN_COMMAND) { - llResetScript(); - } else if (command == SHOW_TEXTURE_COMMAND) { - llSetLinkTexture(LINK_THIS, parms, ALL_SIDES); - } -} - -////////////// -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_STOP ] ); - } - - link_message(integer linknum, integer num, string cmd, key parms) { - if (num != VIEWSCREEN_BLITTER_HUFFWARE_ID) return; // not for us. - handle_view_request(cmd, parms); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.txt new file mode 100755 index 00000000..beed1fc7 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/viewscreen_blitter_v3.9.txt @@ -0,0 +1,205 @@ + +// huffware script: viewscreen blitter, by fred huffhines. +// +// listens for web addresses to show and puts them on the screen of this prim. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// important switches... + +integer IS_OPENSIM = TRUE; + // selects the major mode of operation for the viewscreen. + +integer DEBUGGING = TRUE; + // if this is set to true, more diagnostic info is printed than normal. + +// global constants... + +// API for the viewscreen blitter library... +////////////// +integer VIEWSCREEN_BLITTER_HUFFWARE_ID = 10027; + // unique ID for the viewscreen services. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// +string SHOW_URL_COMMAND = "#shurl"; + // requests the viewscreen to show a particular URL as its texture. +string RESET_VIEWSCREEN_COMMAND = "#shrz"; + // resets the viewscreen script to the default state. +string SHOW_TEXTURE_COMMAND = "#shtex"; + // displays a texture on the prim. the first parameter is the texture key or name. +////////////// + +// configurable constants... + +handle_view_request(string command, string parms) +{ + if (command == SHOW_URL_COMMAND) { + // the parms is just the URL to display. + if (DEBUGGING) { + string to_show = "url is: "; + integer i; + for (i = 0; i < llStringLength(parms); i += 512) { + // show the string a chunk at a time or we will be censored by chat limits. + integer end = i + 511; + if (i >= llStringLength(parms) - 1) i = llStringLength(parms) - 1; + to_show += llGetSubString(parms, i, end); + llSay(0, to_show); + to_show = ""; + } + } + if (!IS_OPENSIM) { + // second life implementation... + llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_STOP, + PARCEL_MEDIA_COMMAND_TYPE, "text/html", + PARCEL_MEDIA_COMMAND_URL, parms ] ); + // we separate out the looping player call since we can't rely on the new media + // setting being ready within the same media call. + llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_PLAY, PARCEL_MEDIA_COMMAND_LOOP ] ); + } else { + // opensim implementation... + string extra_parms = ""; + //bgcolor:white,alpha:false,width:1024,height:768, + string url_texture_key = osSetDynamicTextureURL("", "image", parms, extra_parms, 5000); +//string url_texture_key =""; + +//llSay(0, "dyn texture is " + url_texture_key); + if (url_texture_key != "") { + llSetTexture(url_texture_key, ALL_SIDES); + } + } + } else if (command == RESET_VIEWSCREEN_COMMAND) { + llResetScript(); + } else if (command == SHOW_TEXTURE_COMMAND) { + llSetLinkTexture(LINK_THIS, parms, ALL_SIDES); + } +} + +////////////// +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + llParcelMediaCommandList( [ PARCEL_MEDIA_COMMAND_STOP ] ); + } + + link_message(integer linknum, integer num, string cmd, key parms) { + if (num != VIEWSCREEN_BLITTER_HUFFWARE_ID) return; // not for us. + handle_view_request(cmd, parms); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.lsl deleted file mode 100755 index 5e3908ea..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.lsl +++ /dev/null @@ -1,219 +0,0 @@ - -// huffware script: weapon fire, by fred huffhines. -// -// finds the first item in inventory and uses it as a bullet. it also finds the first -// sound in inventory and uses that as the report noise for firing the bullet. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// modifiable constants... - -integer LEFT_HANDED = TRUE; - -//float SPEED = 100.0; -float SPEED = 20.0; - -float DELAY = 0.0; // an enforced delay before the weapon can fire again. - -float VOLUME = 0.2; - -integer USE_ANIMATION = FALSE; // if this is true, then the bearer is posed. - -// global variables... - -vector velocity; -vector position; -rotation rotation_vec; - -integer have_permissions = FALSE; -integer armed = TRUE; - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// performs the act of firing the bullet. -fire() -{ - if (armed) { - rotation_vec = llGetRot(); - velocity = llRot2Fwd(rotation_vec); - position = llGetPos(); - position = position + velocity; - position.z += 0.75; - velocity = velocity * SPEED; - if (llGetInventoryNumber(INVENTORY_SOUND) > 0) - llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), VOLUME); - integer i; - for (i = 0; i < llGetInventoryNumber(INVENTORY_OBJECT); i++) - llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), position, velocity, rotation_vec, 2814); - if (DELAY != 0.0) { - armed = FALSE; - llSetTimerEvent(DELAY); - } - } -} - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - if (llGetInventoryNumber(INVENTORY_SOUND) > 0) - llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); - if (!have_permissions) { - llRequestPermissions(llGetOwner(), - PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); - } - } - - on_rez(integer param) { llResetScript(); } - - run_time_permissions(integer permissions) { - if (permissions == PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS) { - llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); - if (USE_ANIMATION) { - if (LEFT_HANDED) { - llStartAnimation("hold_L_bow"); - llStopAnimation("aim_L_bow"); - } else { - llStartAnimation("hold_R_handgun"); - llStopAnimation("aim_R_handgun"); - } - } - have_permissions = TRUE; - } - } - - attach(key attachedAgent) { - if (attachedAgent != NULL_KEY) { - llRequestPermissions(llGetOwner(), - PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); - } else { - if (have_permissions) { - llStopAnimation("hold_R_handgun"); - llStopAnimation("aim_R_handgun"); - llReleaseControls(); - llSetRot(<0,0,0,1>); - have_permissions = FALSE; - } - } - } - - control(key name, integer levels, integer edges) { - if ( ((edges & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) - && ((levels & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) ) { - fire(); - } - } - - timer() { - llSetTimerEvent(0.0); - armed = TRUE; - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.txt new file mode 100755 index 00000000..5e3908ea --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/weapon_fire_v2.2.txt @@ -0,0 +1,219 @@ + +// huffware script: weapon fire, by fred huffhines. +// +// finds the first item in inventory and uses it as a bullet. it also finds the first +// sound in inventory and uses that as the report noise for firing the bullet. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// modifiable constants... + +integer LEFT_HANDED = TRUE; + +//float SPEED = 100.0; +float SPEED = 20.0; + +float DELAY = 0.0; // an enforced delay before the weapon can fire again. + +float VOLUME = 0.2; + +integer USE_ANIMATION = FALSE; // if this is true, then the bearer is posed. + +// global variables... + +vector velocity; +vector position; +rotation rotation_vec; + +integer have_permissions = FALSE; +integer armed = TRUE; + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// performs the act of firing the bullet. +fire() +{ + if (armed) { + rotation_vec = llGetRot(); + velocity = llRot2Fwd(rotation_vec); + position = llGetPos(); + position = position + velocity; + position.z += 0.75; + velocity = velocity * SPEED; + if (llGetInventoryNumber(INVENTORY_SOUND) > 0) + llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), VOLUME); + integer i; + for (i = 0; i < llGetInventoryNumber(INVENTORY_OBJECT); i++) + llRezObject(llGetInventoryName(INVENTORY_OBJECT, i), position, velocity, rotation_vec, 2814); + if (DELAY != 0.0) { + armed = FALSE; + llSetTimerEvent(DELAY); + } + } +} + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + if (llGetInventoryNumber(INVENTORY_SOUND) > 0) + llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); + if (!have_permissions) { + llRequestPermissions(llGetOwner(), + PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); + } + } + + on_rez(integer param) { llResetScript(); } + + run_time_permissions(integer permissions) { + if (permissions == PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS) { + llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); + if (USE_ANIMATION) { + if (LEFT_HANDED) { + llStartAnimation("hold_L_bow"); + llStopAnimation("aim_L_bow"); + } else { + llStartAnimation("hold_R_handgun"); + llStopAnimation("aim_R_handgun"); + } + } + have_permissions = TRUE; + } + } + + attach(key attachedAgent) { + if (attachedAgent != NULL_KEY) { + llRequestPermissions(llGetOwner(), + PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); + } else { + if (have_permissions) { + llStopAnimation("hold_R_handgun"); + llStopAnimation("aim_R_handgun"); + llReleaseControls(); + llSetRot(<0,0,0,1>); + have_permissions = FALSE; + } + } + } + + control(key name, integer levels, integer edges) { + if ( ((edges & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) + && ((levels & CONTROL_ML_LBUTTON) == CONTROL_ML_LBUTTON) ) { + fire(); + } + } + + timer() { + llSetTimerEvent(0.0); + armed = TRUE; + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.lsl deleted file mode 100755 index e12750c2..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.lsl +++ /dev/null @@ -1,529 +0,0 @@ - -// huffware script: welcomebot visitor list, by fred huffhines -// -// originally based on LSL wiki examples. -// how to use this script: -// 1) create an object that you want to track visitors to your area. -// 2) change the parameters below to reflect your own information. -// 3) add the script to your tracker object. -// 4) reply to the script's rez email with the following commands: -// list: send the current visitor list. -// scan: scan the area near the greeter object. -// clear: throw out the visitor list. sends a copy before deleting. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -//todo: -// how do we reconcile having a config notecard with the giveaway ones? -// just name it special? -// we want the script not to reset when the parameters change! -// it should just reset the notecard stuff and other variables. -// no new setup on email and all that stuff! -// maintain list of last visit times. -// just as a string? - - -// put your e-mail address here. -string owner_email = "fred@gruntose.com"; - -// put the GUIDs of your business partners here. the owner is automatically -// notified. -list notification_list = []; - -// place name used to identify this visitor list. -string greeter_name = "eepaw shop welcomebot"; - -// the description of where this is. -string welcome_message = "Welcome to the eepaw shop (Eclectic Electric Patterns and Widgets). Please touch the welcomebot for more information."; - -// you can make the bot listen on a different channel if you like... -integer OWNER_CHANNEL = 14; - -integer MAX_ITEMS_PER_LINE = 4; // how many visitors to show on one line of output. - -integer EMAIL_RECEPTION_ENABLED = FALSE; // currently not enabled in opensim. - -integer EMAIL_SENDING_ENABLED = FALSE; // apparently many sims don't allow email sending. - -integer MAX_VISITORS_TRACKED = 120; - // the number of items we keep around in the list of visitors. - -float pause_when_mail_pending = 2.0; // check for mail this frequently when there's a stack. -float pause_no_pending_mail = 42.0; // if no mail had been waiting, we check more slackly. - -// number of seconds between sending the owner a visitor list. -integer auto_list_interval = 43200; // 43200 is every 12 hours. - -// any variables that need to be modified are above this... -/////////////////////////////////////////////////////////// - -float SENSOR_RANGE = 10.0; // in meters. - -float SENSOR_RATE = 30.0; // in seconds. - -// Global variables -string regionName; -key myKey; -list visitor_list; -list current_list; -string scan_list; -float maxZ = 0.0; -float minZ = 0; -integer MAXZ = 20; -integer MINZ = 20; -integer last_automatic_list_sent; // when we last updated the owner automatically. - -// sends an email. somewhat a thin wrapper. -send_email(string recipient, string subject, string text) -{ - if (EMAIL_SENDING_ENABLED) { - // some sims do not support email. - llEmail(recipient, subject, text); - } -} - -cloaked_owner_alert(string text) -{ - // temporarily change the name so emails will come from the expected greeter. - string hold_name = llGetObjectName(); - llSetObjectName(greeter_name); - // send the message. - llOwnerSay(text); - // restore our name back to the original. - llSetObjectName(hold_name); -} - -cloaked_IM(key who_to_tell, string text) -{ - // temporarily change the name so emails will come from the expected greeter. - string hold_name = llGetObjectName(); - llSetObjectName(greeter_name); - // send the message. - llInstantMessage(who_to_tell, text); - // restore our name back to the original. - llSetObjectName(hold_name); -} - -// notifies all the people in the list who want to hear about visitors. -notify_folks(string text) -{ - // temporarily change the name so emails will come from the expected greeter. - string hold_name = llGetObjectName(); - llSetObjectName(greeter_name); - - list temp_notify = notification_list; - temp_notify += [llGetOwner()]; - - integer i; - for (i = 0; i < llGetListLength(temp_notify); i++) { - string current_id = llList2String(temp_notify, i); - if ((key)current_id == llGetOwner()) cloaked_owner_alert(text); - else cloaked_IM((key)current_id, text); - } - - // restore our name back to the original. - llSetObjectName(hold_name); -} - -// looks for the name provided in a list. the index is returned if -// the name is found, otherwise a negative number is returned. -integer find_name_in_list(string name, list avlist) -{ - integer len = llGetListLength(avlist); - integer i; - for (i = 0; i < len; i++) - { - if (llList2String(avlist, i) == name) - return i; - } - return -1; -} - -// looks for changes in the current locale. -check_region(list detected) -{ - // we accumulate information about people who have changed state in the variables below. - string names_entering = ""; - string names_leaving = ""; - integer num_entering = 0; - integer num_leaving = 0; - - // see if we have somebody new. - integer len = llGetListLength(detected); - integer i; - for (i = 0; i < len; i++) { - string name = llList2String(detected, i); - if (find_name_in_list(name, current_list) < 0) { - current_list += name; - if (num_entering > 0) names_entering += ", "; - names_entering += name; - num_entering++; - } - } - - // see if somebody left. - len = llGetListLength(current_list); - for (i = 0; i < len; i++) { - string name = llList2String(current_list, i); - if (find_name_in_list(name, detected) < 0) { - if (num_leaving > 0) names_leaving += ", "; - names_leaving += name; - num_leaving++; - } - } - - // update current list to be current only - current_list = detected; - - // create a message describing the state. - string msg = ""; - if (num_entering > 0) msg = "Arrived: " + names_entering; - if (num_leaving > 0) { - if (llStringLength(msg) > 0) msg += "\n"; - msg += "Left: " + names_leaving; - } - if (msg != "") notify_folks(msg); -} - -string build_visitor_list() -{ - string text = greeter_name + ":\n"; - integer len = llGetListLength(visitor_list); - integer i; - integer items_per_line = 0; - for (i = len - 1; i >= 0; i--) { - if (items_per_line != 0) { - text += "\t"; - } - text += llList2String(visitor_list, i); - items_per_line++; - if (items_per_line >= MAX_ITEMS_PER_LINE) { - text += "\n"; - items_per_line = 0; - } - } - // handle case for last line. - if (items_per_line != 0) text += "\n"; - text += "Total=" + (string)len; - return text; -} - -send_list_in_text() -{ - llOwnerSay(build_visitor_list()); -} - -send_scan_in_text() -{ - llOwnerSay(greeter_name + " scan\n" + scan_list); -} - -send_list_in_email() -{ - string text = build_visitor_list(); - send_email(owner_email, greeter_name + " visitor list", text); -} - -send_scan_in_email() -{ - send_email(owner_email, greeter_name + " scan", scan_list); -} - -clear_list() -{ - visitor_list = []; -} - -initialize_greeter() -{ - last_automatic_list_sent = llGetUnixTime(); - - scan_list = ""; - - myKey = llGetKey(); - regionName = llGetRegionName(); - - vector rezPos = llGetPos(); - maxZ = rezPos.z + MAXZ; - minZ = rezPos.z - MINZ; - string rezInfo = "Key: "+(string)myKey + " @ "+regionName+" "+(string)rezPos+" ("+(string)maxZ+")"; - notify_folks(rezInfo); - send_email(owner_email, greeter_name + " Rez Information", rezInfo); - llSetTimerEvent(pause_no_pending_mail); - llSensorRepeat( "", "", AGENT, SENSOR_RANGE, TWO_PI, SENSOR_RANGE); - // hook up the bot to the radio so it will hear commands. - llListen(OWNER_CHANNEL, "", llGetOwner(), ""); - llOwnerSay("Listening to commands on channel " + (string)OWNER_CHANNEL - + " (list, scan, clear)"); -} - -// performs the requested command. -process_command_locally(string msg) -{ - if (msg == "list") send_list_in_text(); - else if (msg == "scan") send_scan_in_text(); - else if (msg == "clear") { - send_list_in_text(); - clear_list(); - } -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize_greeter(); - } - - on_rez(integer param) { llResetScript(); } - - timer() - { - if (EMAIL_RECEPTION_ENABLED) { - llGetNextEmail("", ""); // check for email with any subject/sender - - integer curTime = llGetUnixTime(); - if (curTime - last_automatic_list_sent < auto_list_interval) return; - last_automatic_list_sent = curTime; - send_list_in_email(); - } - } - - email(string time, string address, string subj, string message, integer num_left) - { - list args = llParseString2List(message, [" "], []); - if (llGetListLength(args) < 1) return; // nothing to do. - string cmd = llToLower(llList2String(args, 0)); -//room for a process_command_for_email here. - if (cmd == "list") send_list_in_email(); - else if (cmd == "scan") send_scan_in_email(); - else if (cmd == "clear") { - send_list_in_email(); - clear_list(); - } - - if (num_left == 0) llSetTimerEvent(pause_no_pending_mail); // sleep longer before checking. - else llSetTimerEvent(pause_when_mail_pending); // short sleep since others are waiting. - } - - listen(integer channel, string name, key id, string msg) - { - if ( (channel != OWNER_CHANNEL) || (id != llGetOwner()) ) return; // not for them. - process_command_locally(msg); - } - - // when a visitor touches the welcomebot, hand out the first landmark and - // first notecard we have stored. - touch_start(integer count) { - string item_name = llGetInventoryName(INVENTORY_NOTECARD, 0); // first notecard. - if (item_name != "") - llGiveInventory(llDetectedKey(0), item_name); - item_name = llGetInventoryName(INVENTORY_LANDMARK, 0); - if (item_name != "") - llGiveInventory(llDetectedKey(0), item_name); - } - - sensor(integer number_detected) - { - list detected = []; - vector pos = llGetPos(); - string textVerbose = ""; - string textNewVerbose = ""; - string textNew = ""; - integer other = 0; - integer group = 0; - integer new = 0; - integer outer; - - textVerbose = ""; - for (outer = 0; outer < number_detected; outer++) - { - vector dpos = llDetectedPos(outer); - if (llGetLandOwnerAt(dpos)==llGetLandOwnerAt(llGetPos())) - { - string detected_name = llDetectedName(outer); - string detected_key = llDetectedKey(outer); - integer info_res = llGetAgentInfo(detected_key); - float diff = llVecDist(pos,dpos); - integer dist = llRound(diff); - string result = detected_name+" ("+detected_key+") " + (string)dist; - if(dpos.y>pos.y) result+="N"; - else if(dpos.ypos.x) result+="E"; - else if(dpos.x= 0 && dpos.x <= 256) && - (dpos.y >= 0 && dpos.y <= 256) && - (dpos.z >= minZ) && (dpos.z <= maxZ)) - { - if (llDetectedGroup(outer)) group++; - else other++; - - // add to the detected list - detected += detected_name; - - // see if they are on the visitor list - if (find_name_in_list(detected_name, visitor_list) < 0) { - // make sure we haven't gone beyond our limit. - if (llGetListLength(visitor_list) >= MAX_VISITORS_TRACKED) { - visitor_list = llDeleteSubList(visitor_list, 0, 0); - } - // add to the visitor list - visitor_list += detected_name; - - // handle any separators to make more readable - if (new > 0) { - textNew += ", "; - textNewVerbose += "\n"; - } - - // add to the text - textNew += detected_name; - textNewVerbose += detected_name+" ("+detected_key+") @ "+regionName+" "+(string)dpos; - result += "N"; - - // increment the count of new visitors - new++; - cloaked_IM(detected_key, welcome_message); - } - } - else - { - result += "*"; - } - textVerbose += result + "\n"; - } - } - - if (new > 0) { - // extra verbose logging. -// notify_folks(textNew + "\n" + textNewVerbose); - } - scan_list = textVerbose; - - check_region(detected); - } - - no_sensor() - { - check_region([]); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.txt new file mode 100755 index 00000000..e12750c2 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/welcomebot_v4.0.txt @@ -0,0 +1,529 @@ + +// huffware script: welcomebot visitor list, by fred huffhines +// +// originally based on LSL wiki examples. +// how to use this script: +// 1) create an object that you want to track visitors to your area. +// 2) change the parameters below to reflect your own information. +// 3) add the script to your tracker object. +// 4) reply to the script's rez email with the following commands: +// list: send the current visitor list. +// scan: scan the area near the greeter object. +// clear: throw out the visitor list. sends a copy before deleting. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +//todo: +// how do we reconcile having a config notecard with the giveaway ones? +// just name it special? +// we want the script not to reset when the parameters change! +// it should just reset the notecard stuff and other variables. +// no new setup on email and all that stuff! +// maintain list of last visit times. +// just as a string? + + +// put your e-mail address here. +string owner_email = "fred@gruntose.com"; + +// put the GUIDs of your business partners here. the owner is automatically +// notified. +list notification_list = []; + +// place name used to identify this visitor list. +string greeter_name = "eepaw shop welcomebot"; + +// the description of where this is. +string welcome_message = "Welcome to the eepaw shop (Eclectic Electric Patterns and Widgets). Please touch the welcomebot for more information."; + +// you can make the bot listen on a different channel if you like... +integer OWNER_CHANNEL = 14; + +integer MAX_ITEMS_PER_LINE = 4; // how many visitors to show on one line of output. + +integer EMAIL_RECEPTION_ENABLED = FALSE; // currently not enabled in opensim. + +integer EMAIL_SENDING_ENABLED = FALSE; // apparently many sims don't allow email sending. + +integer MAX_VISITORS_TRACKED = 120; + // the number of items we keep around in the list of visitors. + +float pause_when_mail_pending = 2.0; // check for mail this frequently when there's a stack. +float pause_no_pending_mail = 42.0; // if no mail had been waiting, we check more slackly. + +// number of seconds between sending the owner a visitor list. +integer auto_list_interval = 43200; // 43200 is every 12 hours. + +// any variables that need to be modified are above this... +/////////////////////////////////////////////////////////// + +float SENSOR_RANGE = 10.0; // in meters. + +float SENSOR_RATE = 30.0; // in seconds. + +// Global variables +string regionName; +key myKey; +list visitor_list; +list current_list; +string scan_list; +float maxZ = 0.0; +float minZ = 0; +integer MAXZ = 20; +integer MINZ = 20; +integer last_automatic_list_sent; // when we last updated the owner automatically. + +// sends an email. somewhat a thin wrapper. +send_email(string recipient, string subject, string text) +{ + if (EMAIL_SENDING_ENABLED) { + // some sims do not support email. + llEmail(recipient, subject, text); + } +} + +cloaked_owner_alert(string text) +{ + // temporarily change the name so emails will come from the expected greeter. + string hold_name = llGetObjectName(); + llSetObjectName(greeter_name); + // send the message. + llOwnerSay(text); + // restore our name back to the original. + llSetObjectName(hold_name); +} + +cloaked_IM(key who_to_tell, string text) +{ + // temporarily change the name so emails will come from the expected greeter. + string hold_name = llGetObjectName(); + llSetObjectName(greeter_name); + // send the message. + llInstantMessage(who_to_tell, text); + // restore our name back to the original. + llSetObjectName(hold_name); +} + +// notifies all the people in the list who want to hear about visitors. +notify_folks(string text) +{ + // temporarily change the name so emails will come from the expected greeter. + string hold_name = llGetObjectName(); + llSetObjectName(greeter_name); + + list temp_notify = notification_list; + temp_notify += [llGetOwner()]; + + integer i; + for (i = 0; i < llGetListLength(temp_notify); i++) { + string current_id = llList2String(temp_notify, i); + if ((key)current_id == llGetOwner()) cloaked_owner_alert(text); + else cloaked_IM((key)current_id, text); + } + + // restore our name back to the original. + llSetObjectName(hold_name); +} + +// looks for the name provided in a list. the index is returned if +// the name is found, otherwise a negative number is returned. +integer find_name_in_list(string name, list avlist) +{ + integer len = llGetListLength(avlist); + integer i; + for (i = 0; i < len; i++) + { + if (llList2String(avlist, i) == name) + return i; + } + return -1; +} + +// looks for changes in the current locale. +check_region(list detected) +{ + // we accumulate information about people who have changed state in the variables below. + string names_entering = ""; + string names_leaving = ""; + integer num_entering = 0; + integer num_leaving = 0; + + // see if we have somebody new. + integer len = llGetListLength(detected); + integer i; + for (i = 0; i < len; i++) { + string name = llList2String(detected, i); + if (find_name_in_list(name, current_list) < 0) { + current_list += name; + if (num_entering > 0) names_entering += ", "; + names_entering += name; + num_entering++; + } + } + + // see if somebody left. + len = llGetListLength(current_list); + for (i = 0; i < len; i++) { + string name = llList2String(current_list, i); + if (find_name_in_list(name, detected) < 0) { + if (num_leaving > 0) names_leaving += ", "; + names_leaving += name; + num_leaving++; + } + } + + // update current list to be current only + current_list = detected; + + // create a message describing the state. + string msg = ""; + if (num_entering > 0) msg = "Arrived: " + names_entering; + if (num_leaving > 0) { + if (llStringLength(msg) > 0) msg += "\n"; + msg += "Left: " + names_leaving; + } + if (msg != "") notify_folks(msg); +} + +string build_visitor_list() +{ + string text = greeter_name + ":\n"; + integer len = llGetListLength(visitor_list); + integer i; + integer items_per_line = 0; + for (i = len - 1; i >= 0; i--) { + if (items_per_line != 0) { + text += "\t"; + } + text += llList2String(visitor_list, i); + items_per_line++; + if (items_per_line >= MAX_ITEMS_PER_LINE) { + text += "\n"; + items_per_line = 0; + } + } + // handle case for last line. + if (items_per_line != 0) text += "\n"; + text += "Total=" + (string)len; + return text; +} + +send_list_in_text() +{ + llOwnerSay(build_visitor_list()); +} + +send_scan_in_text() +{ + llOwnerSay(greeter_name + " scan\n" + scan_list); +} + +send_list_in_email() +{ + string text = build_visitor_list(); + send_email(owner_email, greeter_name + " visitor list", text); +} + +send_scan_in_email() +{ + send_email(owner_email, greeter_name + " scan", scan_list); +} + +clear_list() +{ + visitor_list = []; +} + +initialize_greeter() +{ + last_automatic_list_sent = llGetUnixTime(); + + scan_list = ""; + + myKey = llGetKey(); + regionName = llGetRegionName(); + + vector rezPos = llGetPos(); + maxZ = rezPos.z + MAXZ; + minZ = rezPos.z - MINZ; + string rezInfo = "Key: "+(string)myKey + " @ "+regionName+" "+(string)rezPos+" ("+(string)maxZ+")"; + notify_folks(rezInfo); + send_email(owner_email, greeter_name + " Rez Information", rezInfo); + llSetTimerEvent(pause_no_pending_mail); + llSensorRepeat( "", "", AGENT, SENSOR_RANGE, TWO_PI, SENSOR_RANGE); + // hook up the bot to the radio so it will hear commands. + llListen(OWNER_CHANNEL, "", llGetOwner(), ""); + llOwnerSay("Listening to commands on channel " + (string)OWNER_CHANNEL + + " (list, scan, clear)"); +} + +// performs the requested command. +process_command_locally(string msg) +{ + if (msg == "list") send_list_in_text(); + else if (msg == "scan") send_scan_in_text(); + else if (msg == "clear") { + send_list_in_text(); + clear_list(); + } +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize_greeter(); + } + + on_rez(integer param) { llResetScript(); } + + timer() + { + if (EMAIL_RECEPTION_ENABLED) { + llGetNextEmail("", ""); // check for email with any subject/sender + + integer curTime = llGetUnixTime(); + if (curTime - last_automatic_list_sent < auto_list_interval) return; + last_automatic_list_sent = curTime; + send_list_in_email(); + } + } + + email(string time, string address, string subj, string message, integer num_left) + { + list args = llParseString2List(message, [" "], []); + if (llGetListLength(args) < 1) return; // nothing to do. + string cmd = llToLower(llList2String(args, 0)); +//room for a process_command_for_email here. + if (cmd == "list") send_list_in_email(); + else if (cmd == "scan") send_scan_in_email(); + else if (cmd == "clear") { + send_list_in_email(); + clear_list(); + } + + if (num_left == 0) llSetTimerEvent(pause_no_pending_mail); // sleep longer before checking. + else llSetTimerEvent(pause_when_mail_pending); // short sleep since others are waiting. + } + + listen(integer channel, string name, key id, string msg) + { + if ( (channel != OWNER_CHANNEL) || (id != llGetOwner()) ) return; // not for them. + process_command_locally(msg); + } + + // when a visitor touches the welcomebot, hand out the first landmark and + // first notecard we have stored. + touch_start(integer count) { + string item_name = llGetInventoryName(INVENTORY_NOTECARD, 0); // first notecard. + if (item_name != "") + llGiveInventory(llDetectedKey(0), item_name); + item_name = llGetInventoryName(INVENTORY_LANDMARK, 0); + if (item_name != "") + llGiveInventory(llDetectedKey(0), item_name); + } + + sensor(integer number_detected) + { + list detected = []; + vector pos = llGetPos(); + string textVerbose = ""; + string textNewVerbose = ""; + string textNew = ""; + integer other = 0; + integer group = 0; + integer new = 0; + integer outer; + + textVerbose = ""; + for (outer = 0; outer < number_detected; outer++) + { + vector dpos = llDetectedPos(outer); + if (llGetLandOwnerAt(dpos)==llGetLandOwnerAt(llGetPos())) + { + string detected_name = llDetectedName(outer); + string detected_key = llDetectedKey(outer); + integer info_res = llGetAgentInfo(detected_key); + float diff = llVecDist(pos,dpos); + integer dist = llRound(diff); + string result = detected_name+" ("+detected_key+") " + (string)dist; + if(dpos.y>pos.y) result+="N"; + else if(dpos.ypos.x) result+="E"; + else if(dpos.x= 0 && dpos.x <= 256) && + (dpos.y >= 0 && dpos.y <= 256) && + (dpos.z >= minZ) && (dpos.z <= maxZ)) + { + if (llDetectedGroup(outer)) group++; + else other++; + + // add to the detected list + detected += detected_name; + + // see if they are on the visitor list + if (find_name_in_list(detected_name, visitor_list) < 0) { + // make sure we haven't gone beyond our limit. + if (llGetListLength(visitor_list) >= MAX_VISITORS_TRACKED) { + visitor_list = llDeleteSubList(visitor_list, 0, 0); + } + // add to the visitor list + visitor_list += detected_name; + + // handle any separators to make more readable + if (new > 0) { + textNew += ", "; + textNewVerbose += "\n"; + } + + // add to the text + textNew += detected_name; + textNewVerbose += detected_name+" ("+detected_key+") @ "+regionName+" "+(string)dpos; + result += "N"; + + // increment the count of new visitors + new++; + cloaked_IM(detected_key, welcome_message); + } + } + else + { + result += "*"; + } + textVerbose += result + "\n"; + } + } + + if (new > 0) { + // extra verbose logging. +// notify_folks(textNew + "\n" + textNewVerbose); + } + scan_list = textVerbose; + + check_region(detected); + } + + no_sensor() + { + check_region([]); + } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.lsl deleted file mode 100755 index 873bbf27..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.lsl +++ /dev/null @@ -1,624 +0,0 @@ - -// huffware script: wylie controller, by fred huffhines and wam7c macchi. -// -// accepts wylie input and distributes the command to the various parts of the letter. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// configurable values... the settings below are just defaults. - -integer LISTENING_CHANNEL = 0; // the channel where we'll listen for commands. -integer ONLY_LISTEN_TO_OWNER = FALSE; // if true, only the owner's voice counts. -integer SHOW_CHANNEL = TRUE; // puts a title over our heads if true. -vector TITLE_COLOR = <1.0, 1.0, 1.0>; // the color the title should be. - -integer DEBUGGING = FALSE; // if this is true, then the debugging will be noisy. - -// constants... do not change these. - -integer STARTUP_CODE_NOTECARD_RETRIES = 14042; - // secret code used to launch the wylie writers with many notecard retries. - -// channels for speech / link messages. -integer LOWER_VOWEL_CHANNEL = 11008; -integer CONSONTANT_CHANNEL = 21008; -integer UPPER_VOWEL_CHANNEL = 31008; - -string RESET_TEXTURE_WORD = "reset-texture"; - // tells the letter blocks to go back to default texture. -string BROADCAST_WORD = "bcast"; - // used to tell many wylie writers to do something at the same time. - -string WYLIE_NOTEWORTHY_SIGNATURE = "#wylie"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -integer SNOOZE_BEFORE_CONFIG_RESET = 14; - // number of seconds to wait before trying to read notecard again. - -// requires noteworthy library v10.2 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string BUSY_READING_INDICATOR = "busy_already"; - // this return value indicates that the script is already in use by some other script. - // the calling script should try again later. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or "bad_notecard" if none was found) and - // as subsequent elements an embedded list that was read from the notecard. this - // necessarily limits the size of the notecards that we can read and return. -// -////////////// - -// global variables that track notecard reading and any configuration found. -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -integer startup_parm = 0; // the startup parameter for the script. -integer retries_allowed = 1; // number of attempts to read notecards. - -// sets the object up. -initialize_wylie() -{ - // listen for commands from the appropriate person(s) on the right channel. - key id = NULL_KEY; - if (ONLY_LISTEN_TO_OWNER) id = llGetOwner(); - llListen(LISTENING_CHANNEL, "", id, ""); - // display a text title if we were configured to. - float title_alpha = 1.0; - if (!SHOW_CHANNEL || !LISTENING_CHANNEL) title_alpha = 0.0; - llSetText("/" + (string)LISTENING_CHANNEL, TITLE_COLOR, title_alpha); - if (LISTENING_CHANNEL) { - // if we're not on open chat listen, then we still peek out on the - // open chat channel for certain instructions. - llListen(0, "", id, ""); - } - llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); // snooze a bit, and try reading again. - - if (startup_parm == STARTUP_CODE_NOTECARD_RETRIES) { -///hmmm: parameterize - retries_allowed = 11; - startup_parm = -3; // no longer allowed to hit unless we get restarted. - } - retries_allowed--; -} - -// tells all the character blocks to go back to their default texture. -reset_textures() -{ - set_texture(LOWER_VOWEL_CHANNEL, RESET_TEXTURE_WORD); - set_texture(CONSONTANT_CHANNEL, RESET_TEXTURE_WORD); - set_texture(UPPER_VOWEL_CHANNEL, RESET_TEXTURE_WORD); -} - -// makes one of the blocks show the tibetan character, if it knows it. -set_texture(integer block_number, string tib_char_wylie) -{ - llMessageLinked(LINK_SET, block_number, tib_char_wylie, NULL_KEY); -} - -// find the vowel in the string provided and separate the word into its -// components for each of the blocks (in the order: upper, middle, lower). -list consume_wylie(string maybe_wylie_in) -{ - string maybe_wylie = llToLower(maybe_wylie_in); // drop to lower case. - // if it has a space in it, then it's not for us. - integer posn = llSubStringIndex(maybe_wylie, " "); - if (posn >= 0) return []; // wrong answer. - list vowels = [ "a", "e", "i", "o", "u" ]; - integer vow_indy; - for (vow_indy = 0; vow_indy < llGetListLength(vowels); vow_indy++) { - string curr_vow = llList2String(vowels, vow_indy); - posn = find_substring(maybe_wylie, curr_vow); - if (posn >= 0) { - // found one! -// log_it("found the vowel " + curr_vow); - -//hmmm: here is where better logic would be needed to support multi-vowel words. - -//hmmm: here is also where better logic needed for processing words, with multiple chars. -// that would just require splitting the remainder off instead of having the rule about -// vowel must be at end. - - // compute the consonant portion. - string consonant = llGetSubString(maybe_wylie, 0, posn - 1) + "a"; - // we guess that the consonant is about right already. - // dratted special cases for specific characters. - if (maybe_wylie == curr_vow + "h") consonant = "ah"; - else if (maybe_wylie == curr_vow) consonant = "a"; -// log_it("consonant now is " + consonant); - - // now calculate the right vowel(s) and where they live. - string lower_vowel; - string upper_vowel; - if (curr_vow == "a") { - // no extra vowel markers, since there's an 'a'. - lower_vowel = RESET_TEXTURE_WORD; - upper_vowel = RESET_TEXTURE_WORD; - } else if (curr_vow == "u") { - // our one vowel that goes below. - lower_vowel = curr_vow; - upper_vowel = RESET_TEXTURE_WORD; - } else { - // mainstream vowels fly high. - lower_vowel = RESET_TEXTURE_WORD; - upper_vowel = curr_vow; - } -// log_it("success, answering: " + upper_vowel + " / " + consonant + " / " + lower_vowel); - return [ upper_vowel, consonant, lower_vowel ]; - } - - } - // no vowel was found!? - return []; -} - -////////////// - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -////////////// - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - global_notecard_name = ""; // reset any previous card. - global_config_list = []; // toss previous contents. - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([WYLIE_NOTEWORTHY_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from the noteworthy library. -integer handle_link_message(integer which, integer num, string msg, key id) -{ -//log_it("got linkmsg: " + (string)which + " - " + (string)num + " - " + msg); - if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) return FALSE; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return FALSE; // oops, this isn't for us. - if (notecard_name == BAD_NOTECARD_INDICATOR) { -// should we try again? - return FALSE; // drop that one. - } - - // a valid notecard has been found. -//log_it("notecard name: " + notecard_name); - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - if (notecard_name == BUSY_READING_INDICATOR) { - llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); - return FALSE; - } else if (notecard_name != NOTECARD_READ_CONTINUATION) { - global_notecard_name = notecard_name; // record its name for later use. - // now we're done reading, process the file as a set of definitions. - global_config_index = 0; // we are starting over in the config list. - process_ini_config(); - return TRUE; - } else { - // we're going to keep reading; notecard has more. - llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); - return FALSE; - } -} - -/////////////// - -// consumes the notecard in a very application specific way to retrieve our configuration items. -// the example script only looks for two variables: name and description. if those are found in -// the sample card, then they are proudly shown. -parse_variable_definition(string to_parse) -{ -//log_it("parse_var: " + to_parse); - string content; // filled after finding a variable name. - if ( (content = get_variable_value(to_parse, "channel")) != "") { - LISTENING_CHANNEL = (integer)content; - } else if ( (content = get_variable_value(to_parse, "owner_only")) != "") { - ONLY_LISTEN_TO_OWNER = (integer)content; - } else if ( (content = get_variable_value(to_parse, "show_channel")) != "") { - SHOW_CHANNEL = (integer)content; - } else if ( (content = get_variable_value(to_parse, "title_color")) != "") { - TITLE_COLOR = (vector)content; - } -} - -initialize_notecard_reader() -{ - // reset our relevant variables. - global_notecard_name = ""; - global_config_list = []; - global_config_index = 0; - // reset our configurable constants to the defaults. - LISTENING_CHANNEL = 0; - ONLY_LISTEN_TO_OWNER = FALSE; - SHOW_CHANNEL = TRUE; - TITLE_COLOR = <1.0, 1.0, 1.0>; - - // request that the noteworthy library start looking for our notecard. - request_configuration(); - - llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); // snooze a bit, and try reading again. -} - -hear_the_voices(integer channel, string name, key id, string message) -{ - if (ONLY_LISTEN_TO_OWNER && (id != llGetOwner())) return; // not valid from this guy. - if (!channel && (id == llGetOwner())) { -///&& LISTENING_CHANNEL && - // this is general chat, which is not our listening channel. we only - // allow special owner commands here. - if (is_prefix(message, BROADCAST_WORD)) { - // whoa, they know the secret broadcasting code. - channel = LISTENING_CHANNEL; - // chop the bcast word, plus a space, from the command. - message = llDeleteSubString(message, 0, llStringLength(BROADCAST_WORD)); - } - } - if (channel != LISTENING_CHANNEL) return; // this is not for us. - if (message == "reset") { - reset_textures(); - return; - } else if ( (message == "self-destruct") && (id == llGetOwner())) { - // this is going to send us to object heaven, we hope. - llDie(); - } - // wasn't a command to reset, so let's see if we know it. - list chopped = consume_wylie(message); - if (llGetListLength(chopped) != 3) return; // not understood as even close to wylie. - set_texture(UPPER_VOWEL_CHANNEL, llList2String(chopped, 0)); - set_texture(CONSONTANT_CHANNEL, llList2String(chopped, 1)); - set_texture(LOWER_VOWEL_CHANNEL, llList2String(chopped, 2)); -} - -////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ strip_spaces(x), strip_spaces(y) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ - integer indy; - integer count = llGetListLength(global_config_list); - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - indy = sec_indy; // track that we've passed this line. - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//defect in default state: -// if no response from noteworthy library, infinite hang. - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { startup_parm = parm; state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - if (DEBUGGING) log_it("started, free mem=" + (string)llGetFreeMemory()); - auto_retire(); // make sure newest addition is only version of script. - if (DEBUGGING) log_it("entered default state."); - initialize_wylie(); - initialize_notecard_reader(); - } - - state_exit() { llSetTimerEvent(0); } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { - if (handle_link_message(which, num, msg, id)) - state ready_for_instructions; - } - - // restart when we see changes to our notecard configuration. - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(4); // delay to avoid rez-time premature startup. - if (DEBUGGING) log_it("restarting due to inv change."); - state rerun; - } - } - - // invoked when the notecard reading has failed. - timer() { - if (global_notecard_name == "") { - if (retries_allowed < 0) { - if (DEBUGGING) log_it("ran out of retries, skipping reset."); - state ready_for_instructions; - } - if (DEBUGGING) log_it("timed out, going back to default."); - state default; // start over again. - } - } - - listen(integer channel, string name, key id, string message) { - hear_the_voices(channel, name, id, message); - } - - on_rez(integer parm) { startup_parm = parm; state rerun; } -} - -state ready_for_instructions -{ - state_entry() { - if (DEBUGGING) log_it("entered ready_for_instructions state."); - initialize_wylie(); - } - - state_exit() { llSetTimerEvent(0); } - - listen(integer channel, string name, key id, string message) { - hear_the_voices(channel, name, id, message); - } - - // reset when we see changes to our notecard configuration. - changed(integer change) { - if (change & CHANGED_INVENTORY) { - if (DEBUGGING) log_it("inventory change seen; restarting"); - state rerun; - } - } - - on_rez(integer parm) { startup_parm = parm; state default; } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.txt new file mode 100755 index 00000000..873bbf27 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/wylie_controller_v8.4.txt @@ -0,0 +1,624 @@ + +// huffware script: wylie controller, by fred huffhines and wam7c macchi. +// +// accepts wylie input and distributes the command to the various parts of the letter. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// configurable values... the settings below are just defaults. + +integer LISTENING_CHANNEL = 0; // the channel where we'll listen for commands. +integer ONLY_LISTEN_TO_OWNER = FALSE; // if true, only the owner's voice counts. +integer SHOW_CHANNEL = TRUE; // puts a title over our heads if true. +vector TITLE_COLOR = <1.0, 1.0, 1.0>; // the color the title should be. + +integer DEBUGGING = FALSE; // if this is true, then the debugging will be noisy. + +// constants... do not change these. + +integer STARTUP_CODE_NOTECARD_RETRIES = 14042; + // secret code used to launch the wylie writers with many notecard retries. + +// channels for speech / link messages. +integer LOWER_VOWEL_CHANNEL = 11008; +integer CONSONTANT_CHANNEL = 21008; +integer UPPER_VOWEL_CHANNEL = 31008; + +string RESET_TEXTURE_WORD = "reset-texture"; + // tells the letter blocks to go back to default texture. +string BROADCAST_WORD = "bcast"; + // used to tell many wylie writers to do something at the same time. + +string WYLIE_NOTEWORTHY_SIGNATURE = "#wylie"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +integer SNOOZE_BEFORE_CONFIG_RESET = 14; + // number of seconds to wait before trying to read notecard again. + +// requires noteworthy library v10.2 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string BUSY_READING_INDICATOR = "busy_already"; + // this return value indicates that the script is already in use by some other script. + // the calling script should try again later. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or "bad_notecard" if none was found) and + // as subsequent elements an embedded list that was read from the notecard. this + // necessarily limits the size of the notecards that we can read and return. +// +////////////// + +// global variables that track notecard reading and any configuration found. +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +integer startup_parm = 0; // the startup parameter for the script. +integer retries_allowed = 1; // number of attempts to read notecards. + +// sets the object up. +initialize_wylie() +{ + // listen for commands from the appropriate person(s) on the right channel. + key id = NULL_KEY; + if (ONLY_LISTEN_TO_OWNER) id = llGetOwner(); + llListen(LISTENING_CHANNEL, "", id, ""); + // display a text title if we were configured to. + float title_alpha = 1.0; + if (!SHOW_CHANNEL || !LISTENING_CHANNEL) title_alpha = 0.0; + llSetText("/" + (string)LISTENING_CHANNEL, TITLE_COLOR, title_alpha); + if (LISTENING_CHANNEL) { + // if we're not on open chat listen, then we still peek out on the + // open chat channel for certain instructions. + llListen(0, "", id, ""); + } + llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); // snooze a bit, and try reading again. + + if (startup_parm == STARTUP_CODE_NOTECARD_RETRIES) { +///hmmm: parameterize + retries_allowed = 11; + startup_parm = -3; // no longer allowed to hit unless we get restarted. + } + retries_allowed--; +} + +// tells all the character blocks to go back to their default texture. +reset_textures() +{ + set_texture(LOWER_VOWEL_CHANNEL, RESET_TEXTURE_WORD); + set_texture(CONSONTANT_CHANNEL, RESET_TEXTURE_WORD); + set_texture(UPPER_VOWEL_CHANNEL, RESET_TEXTURE_WORD); +} + +// makes one of the blocks show the tibetan character, if it knows it. +set_texture(integer block_number, string tib_char_wylie) +{ + llMessageLinked(LINK_SET, block_number, tib_char_wylie, NULL_KEY); +} + +// find the vowel in the string provided and separate the word into its +// components for each of the blocks (in the order: upper, middle, lower). +list consume_wylie(string maybe_wylie_in) +{ + string maybe_wylie = llToLower(maybe_wylie_in); // drop to lower case. + // if it has a space in it, then it's not for us. + integer posn = llSubStringIndex(maybe_wylie, " "); + if (posn >= 0) return []; // wrong answer. + list vowels = [ "a", "e", "i", "o", "u" ]; + integer vow_indy; + for (vow_indy = 0; vow_indy < llGetListLength(vowels); vow_indy++) { + string curr_vow = llList2String(vowels, vow_indy); + posn = find_substring(maybe_wylie, curr_vow); + if (posn >= 0) { + // found one! +// log_it("found the vowel " + curr_vow); + +//hmmm: here is where better logic would be needed to support multi-vowel words. + +//hmmm: here is also where better logic needed for processing words, with multiple chars. +// that would just require splitting the remainder off instead of having the rule about +// vowel must be at end. + + // compute the consonant portion. + string consonant = llGetSubString(maybe_wylie, 0, posn - 1) + "a"; + // we guess that the consonant is about right already. + // dratted special cases for specific characters. + if (maybe_wylie == curr_vow + "h") consonant = "ah"; + else if (maybe_wylie == curr_vow) consonant = "a"; +// log_it("consonant now is " + consonant); + + // now calculate the right vowel(s) and where they live. + string lower_vowel; + string upper_vowel; + if (curr_vow == "a") { + // no extra vowel markers, since there's an 'a'. + lower_vowel = RESET_TEXTURE_WORD; + upper_vowel = RESET_TEXTURE_WORD; + } else if (curr_vow == "u") { + // our one vowel that goes below. + lower_vowel = curr_vow; + upper_vowel = RESET_TEXTURE_WORD; + } else { + // mainstream vowels fly high. + lower_vowel = RESET_TEXTURE_WORD; + upper_vowel = curr_vow; + } +// log_it("success, answering: " + upper_vowel + " / " + consonant + " / " + lower_vowel); + return [ upper_vowel, consonant, lower_vowel ]; + } + + } + // no vowel was found!? + return []; +} + +////////////// + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +////////////// + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + global_notecard_name = ""; // reset any previous card. + global_config_list = []; // toss previous contents. + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([WYLIE_NOTEWORTHY_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from the noteworthy library. +integer handle_link_message(integer which, integer num, string msg, key id) +{ +//log_it("got linkmsg: " + (string)which + " - " + (string)num + " - " + msg); + if (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) return FALSE; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return FALSE; // oops, this isn't for us. + if (notecard_name == BAD_NOTECARD_INDICATOR) { +// should we try again? + return FALSE; // drop that one. + } + + // a valid notecard has been found. +//log_it("notecard name: " + notecard_name); + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + if (notecard_name == BUSY_READING_INDICATOR) { + llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); + return FALSE; + } else if (notecard_name != NOTECARD_READ_CONTINUATION) { + global_notecard_name = notecard_name; // record its name for later use. + // now we're done reading, process the file as a set of definitions. + global_config_index = 0; // we are starting over in the config list. + process_ini_config(); + return TRUE; + } else { + // we're going to keep reading; notecard has more. + llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); + return FALSE; + } +} + +/////////////// + +// consumes the notecard in a very application specific way to retrieve our configuration items. +// the example script only looks for two variables: name and description. if those are found in +// the sample card, then they are proudly shown. +parse_variable_definition(string to_parse) +{ +//log_it("parse_var: " + to_parse); + string content; // filled after finding a variable name. + if ( (content = get_variable_value(to_parse, "channel")) != "") { + LISTENING_CHANNEL = (integer)content; + } else if ( (content = get_variable_value(to_parse, "owner_only")) != "") { + ONLY_LISTEN_TO_OWNER = (integer)content; + } else if ( (content = get_variable_value(to_parse, "show_channel")) != "") { + SHOW_CHANNEL = (integer)content; + } else if ( (content = get_variable_value(to_parse, "title_color")) != "") { + TITLE_COLOR = (vector)content; + } +} + +initialize_notecard_reader() +{ + // reset our relevant variables. + global_notecard_name = ""; + global_config_list = []; + global_config_index = 0; + // reset our configurable constants to the defaults. + LISTENING_CHANNEL = 0; + ONLY_LISTEN_TO_OWNER = FALSE; + SHOW_CHANNEL = TRUE; + TITLE_COLOR = <1.0, 1.0, 1.0>; + + // request that the noteworthy library start looking for our notecard. + request_configuration(); + + llSetTimerEvent(SNOOZE_BEFORE_CONFIG_RESET); // snooze a bit, and try reading again. +} + +hear_the_voices(integer channel, string name, key id, string message) +{ + if (ONLY_LISTEN_TO_OWNER && (id != llGetOwner())) return; // not valid from this guy. + if (!channel && (id == llGetOwner())) { +///&& LISTENING_CHANNEL && + // this is general chat, which is not our listening channel. we only + // allow special owner commands here. + if (is_prefix(message, BROADCAST_WORD)) { + // whoa, they know the secret broadcasting code. + channel = LISTENING_CHANNEL; + // chop the bcast word, plus a space, from the command. + message = llDeleteSubString(message, 0, llStringLength(BROADCAST_WORD)); + } + } + if (channel != LISTENING_CHANNEL) return; // this is not for us. + if (message == "reset") { + reset_textures(); + return; + } else if ( (message == "self-destruct") && (id == llGetOwner())) { + // this is going to send us to object heaven, we hope. + llDie(); + } + // wasn't a command to reset, so let's see if we know it. + list chopped = consume_wylie(message); + if (llGetListLength(chopped) != 3) return; // not understood as even close to wylie. + set_texture(UPPER_VOWEL_CHANNEL, llList2String(chopped, 0)); + set_texture(CONSONTANT_CHANNEL, llList2String(chopped, 1)); + set_texture(LOWER_VOWEL_CHANNEL, llList2String(chopped, 2)); +} + +////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ strip_spaces(x), strip_spaces(y) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ + integer indy; + integer count = llGetListLength(global_config_list); + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + indy = sec_indy; // track that we've passed this line. + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//defect in default state: +// if no response from noteworthy library, infinite hang. + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { startup_parm = parm; state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + if (DEBUGGING) log_it("started, free mem=" + (string)llGetFreeMemory()); + auto_retire(); // make sure newest addition is only version of script. + if (DEBUGGING) log_it("entered default state."); + initialize_wylie(); + initialize_notecard_reader(); + } + + state_exit() { llSetTimerEvent(0); } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { + if (handle_link_message(which, num, msg, id)) + state ready_for_instructions; + } + + // restart when we see changes to our notecard configuration. + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(4); // delay to avoid rez-time premature startup. + if (DEBUGGING) log_it("restarting due to inv change."); + state rerun; + } + } + + // invoked when the notecard reading has failed. + timer() { + if (global_notecard_name == "") { + if (retries_allowed < 0) { + if (DEBUGGING) log_it("ran out of retries, skipping reset."); + state ready_for_instructions; + } + if (DEBUGGING) log_it("timed out, going back to default."); + state default; // start over again. + } + } + + listen(integer channel, string name, key id, string message) { + hear_the_voices(channel, name, id, message); + } + + on_rez(integer parm) { startup_parm = parm; state rerun; } +} + +state ready_for_instructions +{ + state_entry() { + if (DEBUGGING) log_it("entered ready_for_instructions state."); + initialize_wylie(); + } + + state_exit() { llSetTimerEvent(0); } + + listen(integer channel, string name, key id, string message) { + hear_the_voices(channel, name, id, message); + } + + // reset when we see changes to our notecard configuration. + changed(integer change) { + if (change & CHANGED_INVENTORY) { + if (DEBUGGING) log_it("inventory change seen; restarting"); + state rerun; + } + } + + on_rez(integer parm) { startup_parm = parm; state default; } +} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.lsl deleted file mode 100755 index 6dee724d..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.lsl +++ /dev/null @@ -1,187 +0,0 @@ - -// huffware script: zap updater from elevators, by fred huffhines -// -// this script is an evil little assassin that is supposed to remove the updater -// script from the objects it's added to. it should not remove that script from -// any huffotronic devices though. -// this is an attempt to quell some SL stability problems due to some seeming -// combination of numbers of objects and numbers of scripts. -// we hope to be able to add the updater back in automatically later because the -// script pin should still be set. let's see if osgrid has that behavior the same -// as second life did. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - - -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// returns true if this object is a huffotronic updater of some sort. -integer inside_of_updater() -{ - return find_substring(llGetObjectName(), "huffotronic") >= 0; -} - -// stops all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - integer indy; - integer insider = inside_of_updater(); - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if ( (curr_script != self_script) - && (!insider || matches_server_script(curr_script)) ) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -string SERVER_SCRIPT = "huffotronic update server"; - // the prefix of our server script that hands out updates. - -// returns true if a script is a version of our update server. -integer matches_server_script(string to_check) -{ - return is_prefix(to_check, SERVER_SCRIPT); -} - -// end hufflets. -////////////// - -default -{ - state_entry() - { - auto_retire(); - if (inside_of_updater()) return; // do nothing else. - - llWhisper(0, "hello, i'm jeeves. pleased to meet you."); - llSleep(32); - - string gotta_zap = "huff-update client v"; - integer i; - for (i = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; i >= 0; i--) { - string cur = llGetInventoryName(INVENTORY_SCRIPT, i); - if (is_prefix(cur, gotta_zap)) { - llWhisper(0, "i, jeeves, will now clean out this script: " + cur); - llRemoveInventory(cur); - } - } - llSleep(14); - knock_around_other_scripts(TRUE); - llSleep(4); - llWhisper(0, "i'm sorry to say sir that i now must bid you adieu, as i am removing myself from the world."); - llSleep(1); - llRemoveInventory(llGetScriptName()); - } -} - diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.txt new file mode 100755 index 00000000..6dee724d --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/zap_updater_from_elevators_v1.3.txt @@ -0,0 +1,187 @@ + +// huffware script: zap updater from elevators, by fred huffhines +// +// this script is an evil little assassin that is supposed to remove the updater +// script from the objects it's added to. it should not remove that script from +// any huffotronic devices though. +// this is an attempt to quell some SL stability problems due to some seeming +// combination of numbers of objects and numbers of scripts. +// we hope to be able to add the updater back in automatically later because the +// script pin should still be set. let's see if osgrid has that behavior the same +// as second life did. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + + +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// returns true if this object is a huffotronic updater of some sort. +integer inside_of_updater() +{ + return find_substring(llGetObjectName(), "huffotronic") >= 0; +} + +// stops all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + integer indy; + integer insider = inside_of_updater(); + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if ( (curr_script != self_script) + && (!insider || matches_server_script(curr_script)) ) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +string SERVER_SCRIPT = "huffotronic update server"; + // the prefix of our server script that hands out updates. + +// returns true if a script is a version of our update server. +integer matches_server_script(string to_check) +{ + return is_prefix(to_check, SERVER_SCRIPT); +} + +// end hufflets. +////////////// + +default +{ + state_entry() + { + auto_retire(); + if (inside_of_updater()) return; // do nothing else. + + llWhisper(0, "hello, i'm jeeves. pleased to meet you."); + llSleep(32); + + string gotta_zap = "huff-update client v"; + integer i; + for (i = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; i >= 0; i--) { + string cur = llGetInventoryName(INVENTORY_SCRIPT, i); + if (is_prefix(cur, gotta_zap)) { + llWhisper(0, "i, jeeves, will now clean out this script: " + cur); + llRemoveInventory(cur); + } + } + llSleep(14); + knock_around_other_scripts(TRUE); + llSleep(4); + llWhisper(0, "i'm sorry to say sir that i now must bid you adieu, as i am removing myself from the world."); + llSleep(1); + llRemoveInventory(llGetScriptName()); + } +} + diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.lsl b/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.lsl deleted file mode 100755 index 4e6eb831..00000000 --- a/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.lsl +++ /dev/null @@ -1,276 +0,0 @@ - -// huffware script: zen mondo's mailbox, modified by fred huffhines. -// -// original attributions are below. -// -// my changes are licensed via: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////////////////////////////// -// ZenMondo's Mailbox by ZenMondo Wormser -// -// Displays Online Status, as well as accepting -// notecard "mail" to be be delivered to owner. -// -// Cleans Up after itself, deletes non-notecards. -// -// -// LICENSE: -// -// This script is given for free, and may NOT be -// resold or used in a commercial product. -// You may copy and distribute this script for free. -// When you redistribute or copy this script, you must -// do so with FULL PERMS (modify, copy, and transfer), -// and leave this notice intact. -// -// You are free to modify this code, but any derivitive -// scripts must not be used in a commercial product or -// or sold, and must contain this license. -// -// This script is provided free for learning -// purposes, take it apart, break it, fix it, -// learn something. If you come up with something -// clever, share it. -// -// Questions about codepoetry (scripting) can always be addressed -// to me, ZenMondo Wormser. -// -///////////////////////////////////////// - -key online_query; - -key name_query; - -string user_name; - - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - llAllowInventoryDrop(TRUE); - name_query = llRequestAgentData(llGetOwner(), DATA_NAME); - llSetText("Setting Up, Ready in one minute.", <0,1,1>, 1.0); - llSetTimerEvent(60); - - - } - - timer() - { - online_query = llRequestAgentData(llGetOwner(),DATA_ONLINE); - } - - dataserver(key queryid, string data) - { - - if(queryid == name_query) - { - user_name = data; - //llSay(0, data + " " + user_name); - } - - if(queryid == online_query) - { - integer online = (integer) data; - - if(online) - { - llSetText(user_name + " is ONLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <0,1,0>, 1.0); - return; - } - - else - { - llSetText(user_name + " is OFFLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <1,0,0>, 1.0); - return; - } - - } - } - - changed(integer mask) - { - if(mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY)) - { - integer num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); - - if(num_notes > 0) - { - string note_name = llGetInventoryName(INVENTORY_NOTECARD, 0); - - llSay(0, "Sending Notecard, '" + note_name +"' please stand by."); - - llGiveInventory(llGetOwner(), note_name); - - llInstantMessage(llGetOwner(), "A NoteCard has been sent to you: " + note_name); - llSay(0, "The Notecard, " + note_name + " has been sent. Thank you."); - - - llRemoveInventory(note_name); - - num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); - - while(num_notes > 0) // They dropped more than one notecard. Clean it up - { - note_name = llGetInventoryName(INVENTORY_NOTECARD, 0); - - llSay(0, "Deleting " + note_name + ". It was not submitted. Try Dropping one note at a time."); - - llRemoveInventory(note_name); - - num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); - - } - - } - - else //Not a Notecard - { - //find out what was dropped and remove it. - - - list inventory; - integer num_inv = llGetInventoryNumber(INVENTORY_ALL); // Should be 2 - integer counter = 0; - while(counter < num_inv) - { - inventory += [llGetInventoryName(INVENTORY_ALL, counter)]; - counter ++; - } - - // WHat we expect to find - list this_script = [llGetScriptName()]; - - //Delete this script (which belong in the inventory) from the list - integer index = llListFindList(inventory, this_script); - inventory = llDeleteSubList(inventory, index, index); - - - index = llGetListLength(inventory); - - - //Just in case they snuck in more than one inventory item - while (index >= 1) - { - llSay(0, "That was not a notecard. Removing " + llList2String(inventory, 0)); - llRemoveInventory(llList2String(inventory, 0)); - inventory = llDeleteSubList(inventory, 0, 0); - index = llGetListLength(inventory); - } - } - } - } - - on_rez(integer start_param) - { - llResetScript(); - } -} diff --git a/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.txt b/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.txt new file mode 100755 index 00000000..4e6eb831 --- /dev/null +++ b/huffware/huffotronic_eepaw_knowledge_v60.9/zenmondos_mailbox_v0.4.txt @@ -0,0 +1,276 @@ + +// huffware script: zen mondo's mailbox, modified by fred huffhines. +// +// original attributions are below. +// +// my changes are licensed via: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////////////////////////////// +// ZenMondo's Mailbox by ZenMondo Wormser +// +// Displays Online Status, as well as accepting +// notecard "mail" to be be delivered to owner. +// +// Cleans Up after itself, deletes non-notecards. +// +// +// LICENSE: +// +// This script is given for free, and may NOT be +// resold or used in a commercial product. +// You may copy and distribute this script for free. +// When you redistribute or copy this script, you must +// do so with FULL PERMS (modify, copy, and transfer), +// and leave this notice intact. +// +// You are free to modify this code, but any derivitive +// scripts must not be used in a commercial product or +// or sold, and must contain this license. +// +// This script is provided free for learning +// purposes, take it apart, break it, fix it, +// learn something. If you come up with something +// clever, share it. +// +// Questions about codepoetry (scripting) can always be addressed +// to me, ZenMondo Wormser. +// +///////////////////////////////////////// + +key online_query; + +key name_query; + +string user_name; + + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + llAllowInventoryDrop(TRUE); + name_query = llRequestAgentData(llGetOwner(), DATA_NAME); + llSetText("Setting Up, Ready in one minute.", <0,1,1>, 1.0); + llSetTimerEvent(60); + + + } + + timer() + { + online_query = llRequestAgentData(llGetOwner(),DATA_ONLINE); + } + + dataserver(key queryid, string data) + { + + if(queryid == name_query) + { + user_name = data; + //llSay(0, data + " " + user_name); + } + + if(queryid == online_query) + { + integer online = (integer) data; + + if(online) + { + llSetText(user_name + " is ONLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <0,1,0>, 1.0); + return; + } + + else + { + llSetText(user_name + " is OFFLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <1,0,0>, 1.0); + return; + } + + } + } + + changed(integer mask) + { + if(mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY)) + { + integer num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); + + if(num_notes > 0) + { + string note_name = llGetInventoryName(INVENTORY_NOTECARD, 0); + + llSay(0, "Sending Notecard, '" + note_name +"' please stand by."); + + llGiveInventory(llGetOwner(), note_name); + + llInstantMessage(llGetOwner(), "A NoteCard has been sent to you: " + note_name); + llSay(0, "The Notecard, " + note_name + " has been sent. Thank you."); + + + llRemoveInventory(note_name); + + num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); + + while(num_notes > 0) // They dropped more than one notecard. Clean it up + { + note_name = llGetInventoryName(INVENTORY_NOTECARD, 0); + + llSay(0, "Deleting " + note_name + ". It was not submitted. Try Dropping one note at a time."); + + llRemoveInventory(note_name); + + num_notes = llGetInventoryNumber(INVENTORY_NOTECARD); + + } + + } + + else //Not a Notecard + { + //find out what was dropped and remove it. + + + list inventory; + integer num_inv = llGetInventoryNumber(INVENTORY_ALL); // Should be 2 + integer counter = 0; + while(counter < num_inv) + { + inventory += [llGetInventoryName(INVENTORY_ALL, counter)]; + counter ++; + } + + // WHat we expect to find + list this_script = [llGetScriptName()]; + + //Delete this script (which belong in the inventory) from the list + integer index = llListFindList(inventory, this_script); + inventory = llDeleteSubList(inventory, index, index); + + + index = llGetListLength(inventory); + + + //Just in case they snuck in more than one inventory item + while (index >= 1) + { + llSay(0, "That was not a notecard. Removing " + llList2String(inventory, 0)); + llRemoveInventory(llList2String(inventory, 0)); + inventory = llDeleteSubList(inventory, 0, 0); + index = llGetListLength(inventory); + } + } + } + } + + on_rez(integer start_param) + { + llResetScript(); + } +} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.lsl b/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.lsl deleted file mode 100755 index 0c231927..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.lsl +++ /dev/null @@ -1,28 +0,0 @@ -string hower = "Hyper Jump\n* Wilder Westen *"; // Hover text -vector color = <0,0,0>; // color of the hover text -string sim = "grid-ww.talentraspel.de:9000:Wilder Westen"; // ip/name + port of the target - -vector pos = <147,158,25>; // position - - -key user; - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - llSetText(hower,color,1); - } - - touch_start(integer total_number) { - user = llDetectedKey(0); - llMapDestination (sim, pos, <1,1,1>); - } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.txt b/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.txt new file mode 100755 index 00000000..0c231927 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/Hyper_Jump_Wilder_Westen_v0.2.txt @@ -0,0 +1,28 @@ +string hower = "Hyper Jump\n* Wilder Westen *"; // Hover text +vector color = <0,0,0>; // color of the hover text +string sim = "grid-ww.talentraspel.de:9000:Wilder Westen"; // ip/name + port of the target + +vector pos = <147,158,25>; // position + + +key user; + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + llSetText(hower,color,1); + } + + touch_start(integer total_number) { + user = llDetectedKey(0); + llMapDestination (sim, pos, <1,1,1>); + } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.lsl b/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.lsl deleted file mode 100755 index ef201cf7..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.lsl +++ /dev/null @@ -1,940 +0,0 @@ - -// huffware script: huff-update server, by fred huffhines. -// -// this script is the server side of the update process. it should reside in an object that -// has all the newest versions of scripts and objects that will be updated. when rezzed, and -// at periodic intervals, it announces on a private chat channel that updates are available. -// when objects respond that they might like an update, it tells them the scripts that it has -// stored inside of it. if any of those scripts are an older version inside the client -// (update requesting) object, then the client will request the newer versions. the server -// object will stuff them into it and tell them to start running. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. - -integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. - - - -// updater dependency section: -// should be moved to a notecard!!! -// -// format is a list of strings, where each string has a pair wrapped by the -// huffware item separators. the pair contains (1) the basename of a script -// that has a new dependency and (2) the basename of that new dependency. -list known_script_dependencies; - - - - -load_script_deps() -{ - known_script_dependencies = [ - llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), - llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), - llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), - llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), - - -//special purpose -- removes the updater from the elevator buttons... -//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), -// => do not uncomment unless you want your elevators to shed their ability to update. - - - // this allows us to add or remove items above at will without complaints about comma. - llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) - ]; -} - - - - -// global constants... - -integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. - -float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. -string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. -string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. - -integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. - -integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. - -float LONGEST_SLACK_PER_CLIENT = 84.0; - // we allow a client to be out of touch with us for this many seconds. after that, - // we decide it's deceased and remove it from our list. - -integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). - -float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. - -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -float CHANGED_INVENTORY_SNOOZER = 7.0; - // the number of seconds we sleep once we see an inventory change. we don't want to - // react to this immediately. this overrides the normal announcement cycle until it's - // dealt with by the timer. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string UPDATER_BASE_NAME = "huff-update client"; - // the name of the updater script that keeps everything in sync. - -////////////// - -// global variables... - -list scripts_available; // the list of scripts we have in our inventory for distribution. -list objects_available; // list of objects for handing out. - -list active_clients; // list of keys for clients that are updating currently. -list active_update_channels; // active conversations on client chosen channels. -list active_listen_ids; // the ids for the listener on those channels. -list active_timestamps; // tracks when the client was last active. - -integer inventory_request_channel; // our personal channel that the update client should talk with. - -integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. - -// displays the status of the update server. -show_status(key who_says) -{ - string title = "[mem free=" + (string)llGetFreeMemory() + "]"; - title = "Listening for requests on channel " + (string)inventory_request_channel; - if (llGetListLength(active_update_channels)) - title += "\nactive channels=" - + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); - else - title += "\nNo channels active."; - - if (llGetListLength(active_clients)) - title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); - else - title += "\nNo clients active."; - - if (llGetOwner() == who_says) { - string addition = " "; - if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; - title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " - + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " - + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; - } - - llWhisper(0, title); -} - -// plink a quietous string of resonance... -squonk(integer indy) -{ - string snd = llGetInventoryName(INVENTORY_SOUND, indy); - if (snd != "") llTriggerSound(snd, 1.0); -} - -// list out the scripts that the server's object contains. -show_scripts() -{ - string title = (string)llGetListLength(scripts_available) + " scripts available:"; - show_list(title, scripts_available); - title = (string)llGetListLength(objects_available) + " objects available:"; - show_list(title, objects_available); -} - -// lets the client know that we're here and have some scripts available. -announce_presence() -{ - if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { - // only announce if we're not already booked up. - llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); - } -} - -// lifted from "clear text and effects" script; should be nearly identical -// to that, except that we set the texture animation. -reset_all_effects() -{ - llSetText("", <0,0,0>, 0); // clear any text above object. - llSetSitText("Sit Here"); // reset sit text to default state. - llSetTouchText("Touch"); // similarly for touch. - llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. - llParticleSystem([]); // turn off all particles. - llSensorRemove(); // stop any running sensors. - llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. - llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. - // keep it from being physical and from disapparating. - llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, - PRIM_PHANTOM, TRUE]); - llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. - - // - // the following are specific to the huffotronic update server. - // - - // we re-assert our special texture set here, in case some wayward scripts have - // messed with us. - integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); - integer indy; - for (indy = 0; indy < textures_held; indy++) { - string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); - // we have a simple scheme for putting textures on the updater. - // we have an inside, an outside and the ends. - if (is_prefix(curr_tex, "~~s0")) { - llSetTexture(curr_tex, ALL_SIDES); - } else if (is_prefix(curr_tex, "~~s1")) { - llSetTexture(curr_tex, 1); - } else if (is_prefix(curr_tex, "~~s2")) { - llSetTexture(curr_tex, 0); - llSetTexture(curr_tex, 3); - } - } - - // re-assert our texture animation also. - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, - ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); -} - -// set up the update server object. -initialize_root() -{ - // set up our particular "look". - reset_all_effects(); - - // shut down any competing scripts in this object. - // we try to swat any other script that's been added before we let them do weird - // stuff. for example, a pet script might start acting like one. this - // function is not guaranteed to run before that bad stuff can happen, - // and that's maybe the one major issue with this approach. as long as - // the contained scripts aren't evil (like if they jump someplace else - // as soon as they start), then there shouldn't be any serious problems. - knock_down_other_scripts(); - - // reset our variables. - active_update_channels = []; - active_listen_ids = []; - active_clients = []; - active_timestamps = []; - scripts_available = []; - objects_available = []; - dealing_with_change = FALSE; // not handling any inventory changes. - - // make sure we know about any scripts that have new dependencies. - load_script_deps(); - - // clean out any older versions of the scripts before we make our - // inventory. - destroy_older_versions(); - - // now accumulate the list of scripts in our inventory. - integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); - integer indy; - for (indy = 0; indy < items_held; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - // we don't provide our own script for updating; it must be kept from - // floating around, like into other objects that are not updaters. -//// if (curr_script != llGetScriptName()) - scripts_available += curr_script; - } - items_held = llGetInventoryNumber(INVENTORY_OBJECT); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); -//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); - } - items_held = llGetInventoryNumber(INVENTORY_NOTECARD); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); -//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); - } - - // listen to the owner. - llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); - // listen for any requests from our loyal clients. - inventory_request_channel = random_channel(); - llListen(inventory_request_channel, "", NULL_KEY, ""); - // listen for older clients too. - llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); - - // set up the periodic announcements. - llSetTimerEvent(ANNOUNCEMENT_PERIOD); -} - -handle_timer() -{ - if (dealing_with_change) { - dealing_with_change = FALSE; - state rerun; // zoom back to the starting point. - } - integer indy; - integer timecheck = llGetUnixTime(); // use for whole loop. - for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { - integer last_time = llList2Integer(active_timestamps, indy); - if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { - // we need to clear out this item. we know we can whack the client - // at the same index and that will take care of this slacker. - key curr_key = llList2Key(active_clients, indy); - log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); - remove_client(curr_key); - } - } - - // let the objects nearby know that we are open for business by - // announcing the script inventory. - announce_presence(); -} - -// turns a list into a nicely formatted string. -string dump_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string cursc = llList2String(to_show, indy); - msg += cursc; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// similar to dump_keyed_list, but only shows the names, each on their own line. -string dump_names_for_keys(list to_show) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we only line break after the first entry. - if (indy > 0) msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr); - } - return msg; -} - -// similar to dump_list -string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr) + " (" + keystr + ")"; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// shows the list specified in a compact manner. -show_list(string title, list to_show) -{ - string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); - // flush some memory. - title = ""; - to_show = []; - integer indy; - // say the output in pieces to avoid over-clogging chat. - for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { - integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; - string addition; - if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; - llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); - } -} - -// stops all the scripts besides this one. -knock_down_other_scripts() -{ - // set all scripts but this to not be running. - integer indy; - string self_script = llGetScriptName(); - list split = compute_basename_and_version(self_script); - string self_base = llList2String(split, 0); - self_script = ""; split = []; // free memory. - integer count = llGetInventoryNumber(INVENTORY_SCRIPT); - // we set all other scripts that are not versions of this script to not be running. - for (indy = 0; indy < count; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if (!is_prefix(curr_script, self_base) - && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { - llSetScriptState(curr_script, FALSE); - } - } -} - -// set a text label on the updater with the list of clients. -set_our_label() -{ - string label = ""; - if (llGetListLength(active_clients) > 0) label = "[updating]\n"; - llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); -} - -// clean out a client that we should be done with. -remove_client(key id) -{ - // locate said client of deceased nature... - integer indy = find_in_list(active_clients, id); - if (indy < 0) { -// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); - return; - } - active_clients = llDeleteSubList(active_clients, indy, indy); - // also clean out the channel and stop listening to it. -integer act_chan = llList2Integer(active_update_channels, indy); - active_update_channels = llDeleteSubList(active_update_channels, indy, indy); - integer listen_to_remove = llList2Integer(active_listen_ids, indy); -//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); - llListenRemove(listen_to_remove); - active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); - active_timestamps = llDeleteSubList(active_timestamps, indy, indy); - set_our_label(); -} - -// fix a partial match to a script name if we can't find the exact item. -string backpatch_script_name(string partial) -{ - if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. - integer dep_indy; - for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { - string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); - if (is_prefix(curr_name, partial)) { -// log_it("found real name " + curr_name + " for part: " + partial); - return curr_name; - } - } -// log_it("no matches for partial script name!"); - return ""; // no matches! -} - -// moves the upgrade process with "id" along to the next step given the request in -// the message. -propel_upgrade_process(integer channel, key id, string message) -{ - if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); - if (message == REQUEST_SCRIPT_UPDATE) { - // begins the update process with the client. - llSay(channel, SHUT_THEM_DOWN); - } else if (is_prefix(message, READY_TO_UPDATE)) { - // whack the prefix so we can get the list they want. - message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); - list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); - message = ""; - // send over the scripts the client asked for, since it seems to be ready for them. - if (llGetListLength(requests)) { - show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); - integer indy; - for (indy = 0; indy < llGetListLength(requests); indy++) { - string curr = llList2String(requests, indy); - if (find_in_list(objects_available, curr) >= 0) { -//log_it("handing object over: " + curr); - // it's an object, so treat it that way. - llGiveInventory(id, curr); - } else { -//log_it("handing script over: " + curr); - // assume it's a script, and use script pin to stuff it. - curr = backpatch_script_name(curr); - if (curr != "") { -// integer starting_state = FALSE; -// second life was okay with scripts being plugged in unstarted. opensim is not. -// and second life appears to be unhappy with scripts plugged in as started. so we -// have an impasse. -// this should be: true for opensim, and false for second life. - integer starting_state = IS_OPENSIM; -// if (DEBUGGING) log_it("installing script using updater pin."); - llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); - } - } - } - } - } else if (message == SCRIPTS_ARE_CURRENT) { - // the client thinks it's ready to get back up and running. -//log_it("heard client is ready!"); - llSay(channel, START_THEM_UP); - // kludge for older clients (pre 10.4 version) to try to help them start up. -//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); - remove_client(id); - } else if (message == DONE_UPDATING) { - // this client has nothing to do for now. -//log_it("heard client is done: " + (string)id); - remove_client(id); - } else { -//log_it("weird note from client: " + message); - return; // not used. - } - -} - -// blasts out the inventory list to a curious client. -spew_inventory_list(integer channel, string message, key id) -{ - if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { - - // this is an old style update alert that we still use at startup of the client - // to ensure that finishing replacement of the updater script is never unnoticed. - if (is_prefix(message, DONE_UPDATING)) { -// if (DEBUGGING) log_it("found very special message from startup of updater."); - propel_upgrade_process(channel, id, message); - } - - // argh, this is not the right kind of message on our channel. - return; - } - string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); - integer new_update_channel = (integer)chan_str; - if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { - // got to tell them "not right now". we'll pretend we have no - // scripts; they'll know what we mean if the update client is - // recent enough. really old clients will just go to sleep until later. - if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); - llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); - return; - } - - // looks like we're going to try to handle the request for them. - if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); - -//log_it("add client convo chan " + (string)new_update_channel); - integer existing_indy = find_in_list(active_clients, id); - if (existing_indy < 0) { - active_clients += id; - active_update_channels += new_update_channel; - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); - active_listen_ids += new_listen_id; - active_timestamps += llGetUnixTime(); - set_our_label(); - } else { -// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); - // delete old listener so we don't leave it dangling. - integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); -//log_it("remove old listen " + (string)old_listen_id); - llListenRemove(old_listen_id); - // update the channel and listener id for the new registration. - active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) - + [ new_update_channel ] - + chop_list(active_update_channels, existing_indy + 1, - llGetListLength(active_update_channels) - 1); - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add new listen " + (string)new_listen_id); - active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_listen_ids, existing_indy + 1, - llGetListLength(active_listen_ids) - 1); - active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_timestamps, existing_indy + 1, - llGetListLength(active_timestamps) - 1); - } - - // our report name is always called available scripts, but it can actually have - // script dependency definitions, script names and object names. - string msg = REPORT_AVAILABLE_SCRIPTS; - string curr; // temp. - - // add in the huff updater, since that's the most crucial that they know we have. - integer posn; - string UPDATE_CLIENT_SCRIPT = "huff-update client"; - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - == UPDATE_CLIENT_SCRIPT) { -//log_it("found " + curr); - msg += curr + UPDATER_PARM_SEPARATOR; - posn = 99999; // jump out. - } - if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { - log_it("epic fail, found no updater client script."); - } - } - - // speak about the dependencies that we know. - for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { - msg += SCRIPT_DEPENDENCY_MARK - + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // tell this new client what scripts we have. - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - != UPDATE_CLIENT_SCRIPT) { - // add in the next item, along with the parameter separator. - msg += curr + UPDATER_PARM_SEPARATOR; -//log_it("adding " + curr); - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { - // stop sending the list to them since they may not know how - // to interpret a multiple part update list. - return; - } - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - } - // mention any objects that are available. - for (posn = 0; posn < llGetListLength(objects_available); posn++) { - // add in the next item, along with the parameter separator. - msg += llList2String(objects_available, posn) - + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // say final bit, even if it's mostly blank. we need to let them know - // that we're done and not adding that continuation flag string. - llSay(new_update_channel, msg); -} - -// handles verbal commands from objects that want updates. -process_verbal_requests(integer channel, string name, key id, string message) -{ - if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { - spew_inventory_list(channel, message, id); - return; - } else if (channel == USER_COMMAND_CHANNEL) { -if (DEBUGGING) log_it("heard orders: " + message); - // simple verbal commands. - if (message == RESTART_UPDATER_COMMAND) { - log_it("Restarting now."); - llResetScript(); - } else if (message == SHOW_SCRIPTS_COMMAND) { - show_scripts(); - } else if (message == SHUTDOWN_COMMAND) { - // we will de-rez now (i.e., die) if we are not one of the special names that is undying. - if (!matches_substring(llGetObjectName(), "keeper")) { -// log_it("server " + (string)inventory_request_channel + " now disintegrating."); - squonk(1); - llDie(); - } - } - return; - } - - integer indy; - // see if the channel is for one of our valid updates that's in progress. - for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { - integer cur_chan = llList2Integer(active_update_channels, indy); - if (cur_chan == channel) { - // yes, this is really for that guy. - propel_upgrade_process(channel, id, message); - return; - } - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. -// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// a random channel for the first interaction with the client. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } - - if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { - log_it("now restarting to avoid opensim late updating change event."); - llResetScript(); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() - { - auto_retire(); - initialize_root(); // get set up to start answering requests. - llWhisper(0, llGetScriptName() + " started... touch for more info."); - squonk(0); - } - - state_exit() { llSetTimerEvent(0); } - - on_rez(integer parm) { - state rerun; - } - - timer() { handle_timer(); } - - touch_start(integer count) { - show_status(llDetectedKey(0)); - } - - listen(integer channel, string name, key id, string message) { - // make sure that the object is something we should even talk to. - if (llGetOwnerKey(id) != llGetOwner()) { - return; - } - // looks okay, let's see if this is useful communication. - process_verbal_requests(channel, name, id, message); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - log_it("inventory changed, scheduled a restart."); - // sleep a little bit; otherwise we get SL noise about scripts not being - // there when it told us they were there. this can lead to some scripts - // doing bizarre things if they are running when added. - dealing_with_change = TRUE; - llSetTimerEvent(0.0); // kludge to get around second life bug. - llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); - } - } -} - -state rerun { state_entry() { state default; } } - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.txt b/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.txt new file mode 100755 index 00000000..ef201cf7 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/a_huffotronic_update_server_v23.2.txt @@ -0,0 +1,940 @@ + +// huffware script: huff-update server, by fred huffhines. +// +// this script is the server side of the update process. it should reside in an object that +// has all the newest versions of scripts and objects that will be updated. when rezzed, and +// at periodic intervals, it announces on a private chat channel that updates are available. +// when objects respond that they might like an update, it tells them the scripts that it has +// stored inside of it. if any of those scripts are an older version inside the client +// (update requesting) object, then the client will request the newer versions. the server +// object will stuff them into it and tell them to start running. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. + +integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. + + + +// updater dependency section: +// should be moved to a notecard!!! +// +// format is a list of strings, where each string has a pair wrapped by the +// huffware item separators. the pair contains (1) the basename of a script +// that has a new dependency and (2) the basename of that new dependency. +list known_script_dependencies; + + + + +load_script_deps() +{ + known_script_dependencies = [ + llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), + llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), + llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), + llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), + + +//special purpose -- removes the updater from the elevator buttons... +//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), +// => do not uncomment unless you want your elevators to shed their ability to update. + + + // this allows us to add or remove items above at will without complaints about comma. + llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) + ]; +} + + + + +// global constants... + +integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. + +float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. +string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. +string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. + +integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. + +integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. + +float LONGEST_SLACK_PER_CLIENT = 84.0; + // we allow a client to be out of touch with us for this many seconds. after that, + // we decide it's deceased and remove it from our list. + +integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). + +float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. + +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +float CHANGED_INVENTORY_SNOOZER = 7.0; + // the number of seconds we sleep once we see an inventory change. we don't want to + // react to this immediately. this overrides the normal announcement cycle until it's + // dealt with by the timer. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string UPDATER_BASE_NAME = "huff-update client"; + // the name of the updater script that keeps everything in sync. + +////////////// + +// global variables... + +list scripts_available; // the list of scripts we have in our inventory for distribution. +list objects_available; // list of objects for handing out. + +list active_clients; // list of keys for clients that are updating currently. +list active_update_channels; // active conversations on client chosen channels. +list active_listen_ids; // the ids for the listener on those channels. +list active_timestamps; // tracks when the client was last active. + +integer inventory_request_channel; // our personal channel that the update client should talk with. + +integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. + +// displays the status of the update server. +show_status(key who_says) +{ + string title = "[mem free=" + (string)llGetFreeMemory() + "]"; + title = "Listening for requests on channel " + (string)inventory_request_channel; + if (llGetListLength(active_update_channels)) + title += "\nactive channels=" + + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); + else + title += "\nNo channels active."; + + if (llGetListLength(active_clients)) + title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); + else + title += "\nNo clients active."; + + if (llGetOwner() == who_says) { + string addition = " "; + if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; + title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " + + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " + + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; + } + + llWhisper(0, title); +} + +// plink a quietous string of resonance... +squonk(integer indy) +{ + string snd = llGetInventoryName(INVENTORY_SOUND, indy); + if (snd != "") llTriggerSound(snd, 1.0); +} + +// list out the scripts that the server's object contains. +show_scripts() +{ + string title = (string)llGetListLength(scripts_available) + " scripts available:"; + show_list(title, scripts_available); + title = (string)llGetListLength(objects_available) + " objects available:"; + show_list(title, objects_available); +} + +// lets the client know that we're here and have some scripts available. +announce_presence() +{ + if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { + // only announce if we're not already booked up. + llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); + } +} + +// lifted from "clear text and effects" script; should be nearly identical +// to that, except that we set the texture animation. +reset_all_effects() +{ + llSetText("", <0,0,0>, 0); // clear any text above object. + llSetSitText("Sit Here"); // reset sit text to default state. + llSetTouchText("Touch"); // similarly for touch. + llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. + llParticleSystem([]); // turn off all particles. + llSensorRemove(); // stop any running sensors. + llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. + llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. + // keep it from being physical and from disapparating. + llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, + PRIM_PHANTOM, TRUE]); + llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. + + // + // the following are specific to the huffotronic update server. + // + + // we re-assert our special texture set here, in case some wayward scripts have + // messed with us. + integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); + integer indy; + for (indy = 0; indy < textures_held; indy++) { + string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); + // we have a simple scheme for putting textures on the updater. + // we have an inside, an outside and the ends. + if (is_prefix(curr_tex, "~~s0")) { + llSetTexture(curr_tex, ALL_SIDES); + } else if (is_prefix(curr_tex, "~~s1")) { + llSetTexture(curr_tex, 1); + } else if (is_prefix(curr_tex, "~~s2")) { + llSetTexture(curr_tex, 0); + llSetTexture(curr_tex, 3); + } + } + + // re-assert our texture animation also. + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, + ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); +} + +// set up the update server object. +initialize_root() +{ + // set up our particular "look". + reset_all_effects(); + + // shut down any competing scripts in this object. + // we try to swat any other script that's been added before we let them do weird + // stuff. for example, a pet script might start acting like one. this + // function is not guaranteed to run before that bad stuff can happen, + // and that's maybe the one major issue with this approach. as long as + // the contained scripts aren't evil (like if they jump someplace else + // as soon as they start), then there shouldn't be any serious problems. + knock_down_other_scripts(); + + // reset our variables. + active_update_channels = []; + active_listen_ids = []; + active_clients = []; + active_timestamps = []; + scripts_available = []; + objects_available = []; + dealing_with_change = FALSE; // not handling any inventory changes. + + // make sure we know about any scripts that have new dependencies. + load_script_deps(); + + // clean out any older versions of the scripts before we make our + // inventory. + destroy_older_versions(); + + // now accumulate the list of scripts in our inventory. + integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); + integer indy; + for (indy = 0; indy < items_held; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + // we don't provide our own script for updating; it must be kept from + // floating around, like into other objects that are not updaters. +//// if (curr_script != llGetScriptName()) + scripts_available += curr_script; + } + items_held = llGetInventoryNumber(INVENTORY_OBJECT); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); +//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); + } + items_held = llGetInventoryNumber(INVENTORY_NOTECARD); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); +//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); + } + + // listen to the owner. + llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); + // listen for any requests from our loyal clients. + inventory_request_channel = random_channel(); + llListen(inventory_request_channel, "", NULL_KEY, ""); + // listen for older clients too. + llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); + + // set up the periodic announcements. + llSetTimerEvent(ANNOUNCEMENT_PERIOD); +} + +handle_timer() +{ + if (dealing_with_change) { + dealing_with_change = FALSE; + state rerun; // zoom back to the starting point. + } + integer indy; + integer timecheck = llGetUnixTime(); // use for whole loop. + for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { + integer last_time = llList2Integer(active_timestamps, indy); + if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { + // we need to clear out this item. we know we can whack the client + // at the same index and that will take care of this slacker. + key curr_key = llList2Key(active_clients, indy); + log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); + remove_client(curr_key); + } + } + + // let the objects nearby know that we are open for business by + // announcing the script inventory. + announce_presence(); +} + +// turns a list into a nicely formatted string. +string dump_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string cursc = llList2String(to_show, indy); + msg += cursc; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// similar to dump_keyed_list, but only shows the names, each on their own line. +string dump_names_for_keys(list to_show) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we only line break after the first entry. + if (indy > 0) msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr); + } + return msg; +} + +// similar to dump_list +string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr) + " (" + keystr + ")"; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// shows the list specified in a compact manner. +show_list(string title, list to_show) +{ + string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); + // flush some memory. + title = ""; + to_show = []; + integer indy; + // say the output in pieces to avoid over-clogging chat. + for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { + integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; + string addition; + if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; + llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); + } +} + +// stops all the scripts besides this one. +knock_down_other_scripts() +{ + // set all scripts but this to not be running. + integer indy; + string self_script = llGetScriptName(); + list split = compute_basename_and_version(self_script); + string self_base = llList2String(split, 0); + self_script = ""; split = []; // free memory. + integer count = llGetInventoryNumber(INVENTORY_SCRIPT); + // we set all other scripts that are not versions of this script to not be running. + for (indy = 0; indy < count; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if (!is_prefix(curr_script, self_base) + && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { + llSetScriptState(curr_script, FALSE); + } + } +} + +// set a text label on the updater with the list of clients. +set_our_label() +{ + string label = ""; + if (llGetListLength(active_clients) > 0) label = "[updating]\n"; + llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); +} + +// clean out a client that we should be done with. +remove_client(key id) +{ + // locate said client of deceased nature... + integer indy = find_in_list(active_clients, id); + if (indy < 0) { +// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); + return; + } + active_clients = llDeleteSubList(active_clients, indy, indy); + // also clean out the channel and stop listening to it. +integer act_chan = llList2Integer(active_update_channels, indy); + active_update_channels = llDeleteSubList(active_update_channels, indy, indy); + integer listen_to_remove = llList2Integer(active_listen_ids, indy); +//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); + llListenRemove(listen_to_remove); + active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); + active_timestamps = llDeleteSubList(active_timestamps, indy, indy); + set_our_label(); +} + +// fix a partial match to a script name if we can't find the exact item. +string backpatch_script_name(string partial) +{ + if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. + integer dep_indy; + for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { + string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); + if (is_prefix(curr_name, partial)) { +// log_it("found real name " + curr_name + " for part: " + partial); + return curr_name; + } + } +// log_it("no matches for partial script name!"); + return ""; // no matches! +} + +// moves the upgrade process with "id" along to the next step given the request in +// the message. +propel_upgrade_process(integer channel, key id, string message) +{ + if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); + if (message == REQUEST_SCRIPT_UPDATE) { + // begins the update process with the client. + llSay(channel, SHUT_THEM_DOWN); + } else if (is_prefix(message, READY_TO_UPDATE)) { + // whack the prefix so we can get the list they want. + message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); + list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); + message = ""; + // send over the scripts the client asked for, since it seems to be ready for them. + if (llGetListLength(requests)) { + show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); + integer indy; + for (indy = 0; indy < llGetListLength(requests); indy++) { + string curr = llList2String(requests, indy); + if (find_in_list(objects_available, curr) >= 0) { +//log_it("handing object over: " + curr); + // it's an object, so treat it that way. + llGiveInventory(id, curr); + } else { +//log_it("handing script over: " + curr); + // assume it's a script, and use script pin to stuff it. + curr = backpatch_script_name(curr); + if (curr != "") { +// integer starting_state = FALSE; +// second life was okay with scripts being plugged in unstarted. opensim is not. +// and second life appears to be unhappy with scripts plugged in as started. so we +// have an impasse. +// this should be: true for opensim, and false for second life. + integer starting_state = IS_OPENSIM; +// if (DEBUGGING) log_it("installing script using updater pin."); + llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); + } + } + } + } + } else if (message == SCRIPTS_ARE_CURRENT) { + // the client thinks it's ready to get back up and running. +//log_it("heard client is ready!"); + llSay(channel, START_THEM_UP); + // kludge for older clients (pre 10.4 version) to try to help them start up. +//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); + remove_client(id); + } else if (message == DONE_UPDATING) { + // this client has nothing to do for now. +//log_it("heard client is done: " + (string)id); + remove_client(id); + } else { +//log_it("weird note from client: " + message); + return; // not used. + } + +} + +// blasts out the inventory list to a curious client. +spew_inventory_list(integer channel, string message, key id) +{ + if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { + + // this is an old style update alert that we still use at startup of the client + // to ensure that finishing replacement of the updater script is never unnoticed. + if (is_prefix(message, DONE_UPDATING)) { +// if (DEBUGGING) log_it("found very special message from startup of updater."); + propel_upgrade_process(channel, id, message); + } + + // argh, this is not the right kind of message on our channel. + return; + } + string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); + integer new_update_channel = (integer)chan_str; + if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { + // got to tell them "not right now". we'll pretend we have no + // scripts; they'll know what we mean if the update client is + // recent enough. really old clients will just go to sleep until later. + if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); + llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); + return; + } + + // looks like we're going to try to handle the request for them. + if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); + +//log_it("add client convo chan " + (string)new_update_channel); + integer existing_indy = find_in_list(active_clients, id); + if (existing_indy < 0) { + active_clients += id; + active_update_channels += new_update_channel; + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); + active_listen_ids += new_listen_id; + active_timestamps += llGetUnixTime(); + set_our_label(); + } else { +// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); + // delete old listener so we don't leave it dangling. + integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); +//log_it("remove old listen " + (string)old_listen_id); + llListenRemove(old_listen_id); + // update the channel and listener id for the new registration. + active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) + + [ new_update_channel ] + + chop_list(active_update_channels, existing_indy + 1, + llGetListLength(active_update_channels) - 1); + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add new listen " + (string)new_listen_id); + active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_listen_ids, existing_indy + 1, + llGetListLength(active_listen_ids) - 1); + active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_timestamps, existing_indy + 1, + llGetListLength(active_timestamps) - 1); + } + + // our report name is always called available scripts, but it can actually have + // script dependency definitions, script names and object names. + string msg = REPORT_AVAILABLE_SCRIPTS; + string curr; // temp. + + // add in the huff updater, since that's the most crucial that they know we have. + integer posn; + string UPDATE_CLIENT_SCRIPT = "huff-update client"; + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + == UPDATE_CLIENT_SCRIPT) { +//log_it("found " + curr); + msg += curr + UPDATER_PARM_SEPARATOR; + posn = 99999; // jump out. + } + if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { + log_it("epic fail, found no updater client script."); + } + } + + // speak about the dependencies that we know. + for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { + msg += SCRIPT_DEPENDENCY_MARK + + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // tell this new client what scripts we have. + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + != UPDATE_CLIENT_SCRIPT) { + // add in the next item, along with the parameter separator. + msg += curr + UPDATER_PARM_SEPARATOR; +//log_it("adding " + curr); + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { + // stop sending the list to them since they may not know how + // to interpret a multiple part update list. + return; + } + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + } + // mention any objects that are available. + for (posn = 0; posn < llGetListLength(objects_available); posn++) { + // add in the next item, along with the parameter separator. + msg += llList2String(objects_available, posn) + + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // say final bit, even if it's mostly blank. we need to let them know + // that we're done and not adding that continuation flag string. + llSay(new_update_channel, msg); +} + +// handles verbal commands from objects that want updates. +process_verbal_requests(integer channel, string name, key id, string message) +{ + if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { + spew_inventory_list(channel, message, id); + return; + } else if (channel == USER_COMMAND_CHANNEL) { +if (DEBUGGING) log_it("heard orders: " + message); + // simple verbal commands. + if (message == RESTART_UPDATER_COMMAND) { + log_it("Restarting now."); + llResetScript(); + } else if (message == SHOW_SCRIPTS_COMMAND) { + show_scripts(); + } else if (message == SHUTDOWN_COMMAND) { + // we will de-rez now (i.e., die) if we are not one of the special names that is undying. + if (!matches_substring(llGetObjectName(), "keeper")) { +// log_it("server " + (string)inventory_request_channel + " now disintegrating."); + squonk(1); + llDie(); + } + } + return; + } + + integer indy; + // see if the channel is for one of our valid updates that's in progress. + for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { + integer cur_chan = llList2Integer(active_update_channels, indy); + if (cur_chan == channel) { + // yes, this is really for that guy. + propel_upgrade_process(channel, id, message); + return; + } + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. +// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// a random channel for the first interaction with the client. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } + + if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { + log_it("now restarting to avoid opensim late updating change event."); + llResetScript(); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() + { + auto_retire(); + initialize_root(); // get set up to start answering requests. + llWhisper(0, llGetScriptName() + " started... touch for more info."); + squonk(0); + } + + state_exit() { llSetTimerEvent(0); } + + on_rez(integer parm) { + state rerun; + } + + timer() { handle_timer(); } + + touch_start(integer count) { + show_status(llDetectedKey(0)); + } + + listen(integer channel, string name, key id, string message) { + // make sure that the object is something we should even talk to. + if (llGetOwnerKey(id) != llGetOwner()) { + return; + } + // looks okay, let's see if this is useful communication. + process_verbal_requests(channel, name, id, message); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + log_it("inventory changed, scheduled a restart."); + // sleep a little bit; otherwise we get SL noise about scripts not being + // there when it told us they were there. this can lead to some scripts + // doing bizarre things if they are running when added. + dealing_with_change = TRUE; + llSetTimerEvent(0.0); // kludge to get around second life bug. + llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); + } + } +} + +state rerun { state_entry() { state default; } } + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.lsl b/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.lsl deleted file mode 100755 index 76465b72..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.lsl +++ /dev/null @@ -1,679 +0,0 @@ - -// huffware script: child jaunter, by fred huffhines, released under GPL license. -// -// this is the sub-jaunter implementation, for children of a root jaunter. this script -// handles reconnaissance and one-way trips. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -// configurable constants... - -string TEXT_COLOR = "<0.5, 0.7, 0.95>"; - // set float text color to a nice color. - -integer DEBUGGING = FALSE; - // set to true to get debugging noises. - -// requires jaunting library API. -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available via the jaunting library: -string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a string in jaunt notecard format with vectors. - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// - -// the API for this library script to be used in other scripts. -////////////// -// do not redefine these constants. -integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; - // the unique id within the huffware system for this script's commands. - // it's used in llMessageLinked as the num parameter. -////////////// -// commands available from the library: -string RESET_REZOLATOR = "#reset"; - // tells the script to stop any previous efforts to rez children. -//string REZ_CHILD_NOW = "#rezkd#"; - // requests this script to create a new child object. this requires several - // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object - // to implement, 3) the chat channel to listen for and speak to new child on, - // 4) the destination name for where the child should go, 5) a count of the full - // set of known destinations, 6) the target where the jaunt should arrive at. -string REPORT_CHILD_REZZED = "#reziam"; - // requests that this class report to the root jaunter that a child has rezzed and - // is ready for service. there are no required parameters. -string REZOLATOR_CHILD_SUPPORT = "#rzsup"; - // used by child jaunters to request that the rezolator handle things for them. -string REZOLATOR_CHILD_RETURNED = "#rezdon"; - // used by the child jaunter to tell the rezolator that it has jumped to wherever it - // was supposed to and is ready to report to the parent, if needed. the first parameter - // required for the rezolator is whether the jump was successful (1) or not (0), and - // the second parameter should be the last safe position that the jaunter was at when - // it was possibly closest to the target. -////////////// -// events generated by the library: -//string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; - // an event generated for a previous rez child request. this lets the caller know that - // the child has been created and told what to do. the single parameter is where the - // jaunter has been rezzed. -string REZOLATOR_EVENT_GOT_INSTRUCTIONS = "#rzsta"; - // the root jaunter has given a child instructions on where to go. this info includes - // the name of the destination, the pathway to get there, and the conveyance mode. -//string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; - // an event generated when the recon process has concluded. this includes parms: - // number of good destinations. -// -////////////// - -// important constants used internally... these should not be changed willy nilly. - -////////////// jaunt base API - -// the following constants define how the script should behave (i.e., its conveyance mode). -// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere -// and then takes the same pathway back, but in reverse order. -// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to -// the root telehub. that object is loaded with the destination notecard and this script. -// the rezzed object can then be used for the next few minutes to jaunt to the selected -// destination. the temporary object will use the ONE_WAY_TRIP mode. -// ONE_WAY_TRIP: the object containing this script will take the user to a particular -// destination, but the object does not survive the trip. it self-destructs after -// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER -// mode and should generally never be used on its own. -// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a -// destination. -integer TWO_WAY_TRIP = 1; -integer AUTOREZ_JAUNTER = 2; -integer ONE_WAY_TRIP = 3; -integer RECONNAISSANCE_TRIP = 4; - -// values used to represent different stages of verification. -integer VERIFY_UNTESTED = -3; // don't know destinations tate yet. -integer VERIFY_SAFE = -4; // the destination last tested safe. -integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. -integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. - -integer MAXIMUM_PRIV_CHAN = 90000; - // the largest amount we will ever subtract from the tricky parms in order to - // tell the sub-jaunter which channel to listen on. - -string VECTOR_SEPARATOR = "|"; - // how we separate components of vectors from each other. -string DB_SEPARATOR = "``"; // separating items in lists. - -////////////// end jaunt base API - -integer MAX_DEST_NAME = 24; // the longest name that we store. - -float NORMAL_TIMER_PERIOD = 1.0; // our normal timer rate. - -float POSITION_CHECKING_INTERVAL = 0.11; - // how frequently the waiting for arrival state will check where we are. - -integer MAXIMUM_SLACKNESS = 108; - // how many timer hits we'll allow before reverting to the default state. - -integer FREE_MEM_REQUIRED = 3200; - // we need at least this much memory before adding new targets. - -////////////// - -// global variables. - -integer startup_parm; // recorded at rez time. used for deciding what to do. - -integer conveyance_mode; // when we are given our instructions, we will know what type of jump to use. - -// jaunter target configuration... -string global_name; // the name for our destination. -integer global_verification_state; // the verification state of the last destination we asked for. -string global_pathway; // similar, but the last pathway we heard. - -// jaunt trip variables... -vector eventual_destination; // where we're headed, if we're headed anywhere. -integer slackness_counter; // snoozes had while waiting for destination. -list full_journey; // the full pathway we expect to jaunt on. -integer jaunt_responses_awaited; // number of pending jumps in progress. -integer got_close_enough; // did we arrive at right place? -vector last_safe_position; // where did we actually reach? - -// asks the jaunting library to take us to the target using a list of waypoints. -request_jaunt(list journey, integer forwards) -{ - // ask for a jump. - jaunt_responses_awaited++; - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, - wrap_item_list(journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); - // stops the jaunter in its tracks. - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); -} - -// this function returns TRUE if we are close enough to the "destination". -integer close_enough(vector destination) -{ - float PROXIMITY_REQUIRED = 0.1; - // how close we must be to the target location to call it done. - // matches current jaunting library proximity. - return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); -} - -// sets up the initial state. -initialize_child() -{ - llSetTimerEvent(0.0); // cancel any existing timers. - // load up an arrival sound if any exist. - if (llGetInventoryNumber(INVENTORY_SOUND)) - llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); - if (DEBUGGING) log_it("child init startparm=" + (string)startup_parm); - -//voodoo. - llSleep(0.5); - - if (startup_parm != 0) { - // tell the rezolator to start listening for commands. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZOLATOR_CHILD_SUPPORT, - wrap_parameters([startup_parm])); - // let our parent know we're here. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REPORT_CHILD_REZZED, ""); - } - // set up some of the object properties... - llSetSitText("Jaunt"); // change to the proper text for our mode. -} - -// shows our next target for jaunting above the object. -text_label_for_destination() -{ - string msg = "↣ " + global_name; - llSetText(msg, (vector)TEXT_COLOR, 1.0); -} - -// signal that we are where we were going. -proclaim_arrival() -{ - if (conveyance_mode == ONE_WAY_TRIP) { - // sing a little song, if there's a sound to use. - if (llGetInventoryNumber(INVENTORY_SOUND)) - llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), 1.0); - } -} - -string verification_name(integer enumtype) -{ - if (enumtype == VERIFY_SAFE) return "ok"; - else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; - else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; - // catch-all, including untested. - return "?"; -} - -// returns true if the slackness counter awaiting things has elapsed. -integer check_for_timeout() -{ - if (slackness_counter++ > MAXIMUM_SLACKNESS) { - // go back to the main state. we took too long. - log_it("timed out!"); - llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. - llSetTimerEvent(0.0); - return TRUE; - } - return FALSE; -} - -////////////// - -// returns the value of a boolean variable definition. -integer parse_bool_def(string def) -{ return !(llGetSubString(def, find_substring(def, "=") + 1, -1) == "0"); } - -// processes link messages received from support libraries. -integer handle_link_message(integer which, integer num, string msg, string id) -{ - // is it a jaunting library response? - if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { - jaunt_responses_awaited--; // one less response being awaited. - if (jaunt_responses_awaited < 0) { - log_it("error: responses awaited < 0"); - jaunt_responses_awaited = 0; - } - return FALSE; - } - - // is it an event from the rezolator script? - if (num == JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == REZOLATOR_EVENT_GOT_INSTRUCTIONS) { - global_name = llList2String(parms, 0); - full_journey = [ llGetPos() ] + llParseString2List(llList2String(parms, 1), [VECTOR_SEPARATOR], []); - eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - conveyance_mode = llList2Integer(parms, 2); - if (DEBUGGING) - log_it("got instructions: name=" + global_name + " dest=" + (string)eventual_destination); - text_label_for_destination(); - if (conveyance_mode == RECONNAISSANCE_TRIP) { - return TRUE; - } - } - return FALSE; - } - - return FALSE; -} - -// processes a destination set to handle special cases, like for offset jaunting. -list prechewed_destinations(string dests) -{ - -//document this!!! -// as in, we support the offset format! - - // look for our special start character for offsets. - if (is_prefix(dests, "o")) - // if this is an offset version, then chop whatever word they used starting with 'o' - // and compute the destination based on current position. - return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; - else - // normal jaunt to absolute coordinates. - return llParseString2List(dests, [VECTOR_SEPARATOR], []); -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -/////////////// - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -// returns text for a floating point number, but includes only -// two digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 100.0) / 100); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -////////////// - -// default state scrounges for information in a notecard and looks for landmarks in -// inventory to add as destinations. -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { - startup_parm = parm; - if (DEBUGGING) log_it("default onrez " + (string)startup_parm); - state rerun; - } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - if (DEBUGGING) log_it("=> real_default state, mem=" + (string)llGetFreeMemory()); - initialize_child(); - state normal_runtime; - } - - on_rez(integer parm) { - startup_parm = parm; - if (DEBUGGING) log_it("default onrez " + (string)startup_parm); - state default; - } -} - -// the normal state is pretty calm; the jaunter just sits there waiting for -// an avatar who needs it to do something. -state normal_runtime -{ - state_entry() { - if (DEBUGGING) log_it("=> normal state, mem=" + (string)llGetFreeMemory()); - jaunt_responses_awaited = 0; // nothing pending right now. - got_close_enough = FALSE; // have not even tried going there yet. - } - - on_rez(integer parm) { - startup_parm = parm; - if (DEBUGGING) log_it("default onrez " + (string)startup_parm); - state default; - } - - touch_end(integer total_number) { - // if we got to here, we may need to check the safety of the target and show the - // map if the conditions are right. - if (outside_of_sim(eventual_destination)) { - // bring up the map; maybe we can't get there from here. definitely out of sim. - llMapDestination(llGetRegionName(), eventual_destination, ZERO_VECTOR); - proclaim_arrival(); - } - } - - changed(integer change) { - if (!(change & CHANGED_LINK)) return; // don't care then. -//no, bad, ack. if the jaunter has multiple parts and they sit on non-root prim, this breaks our ability to react to sit events properly. if (llAvatarOnSitTarget() == NULL_KEY) return; // there is no one sitting now. - if (outside_of_sim(eventual_destination)) { - llWhisper(0, "This type of jaunter needs to be clicked rather than sat upon. Please left-click it (or right-click it and select 'touch')."); - llUnSit(llAvatarOnSitTarget()); - return; - } - state jaunting_now; // sweet, we're off. - } - - // process the response from the APIs we use. - link_message(integer which, integer num, string msg, key id) { - if (handle_link_message(which, num, msg, id)) state jaunting_now; - } - -} - -// once someone is trying to jump to a target, this state processes the request. -state jaunting_now -{ - state_entry() { - if (DEBUGGING) log_it("=> jauntnow state, posn=" + vector_chop(llGetPos())); - slackness_counter = 0; - // most jaunters go to at least the first location... - request_jaunt(full_journey, TRUE); - eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - } - - on_rez(integer parm) - { - startup_parm = parm; - if (DEBUGGING) log_it("default onrez " + (string)startup_parm); - state default; - } - - timer() { - if (jaunt_responses_awaited) { - // we are not quite there yet. - if (check_for_timeout()) state normal_runtime; // oops. - return; // not time yet. - } - // we got to where we were going, maybe. unseat the avatar, leaving her - // at the destination. - llUnSit(llAvatarOnSitTarget()); - state arrived_at_target; - } - - // process the response from the jaunting library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } -} - -// this state is activated when the first jaunt is complete. -state arrived_at_target -{ - state_entry() { - if (DEBUGGING) log_it("=> arriv targ state, posn=" + vector_chop(llGetPos())); - // we are close enough; get back to work. - jaunt_responses_awaited = 0; // nothing pending right now. - if (conveyance_mode != RECONNAISSANCE_TRIP) { - llWhisper(0, "↣ " + global_name); - } else { - if (DEBUGGING) { - string close = "yep"; - if (!close_enough(eventual_destination)) close = "nope"; - log_it("close enough here? " + close + ", want to get to " - + (string)eventual_destination); - } - got_close_enough = close_enough(eventual_destination); - last_safe_position = llGetPos(); - } - - // we've gotten where we were going. - proclaim_arrival(); - -//hmmm: nice mod to make the one way trip actually flip its target list and allow a return. - - // reverse direction and head back without rider. - eventual_destination = (vector)llList2String(full_journey, 0); - request_jaunt(full_journey, FALSE); - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - slackness_counter = 0; - if (DEBUGGING) log_it("now trying to jaunt home, responses awaited=" + (string)jaunt_responses_awaited); - } - - on_rez(integer parm) { - startup_parm = parm; - if (DEBUGGING) log_it("default onrez " + (string)startup_parm); - state default; - } - - timer() { - if (jaunt_responses_awaited) { - // we are not quite there yet. - if (check_for_timeout()) state normal_runtime; // oops. - return; // not time yet. - } - if (DEBUGGING) log_it("==> telling parent we got back, now at posn: " + (string)llGetPos()); - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZOLATOR_CHILD_RETURNED, - wrap_parameters([got_close_enough, - llDumpList2String(llDeleteSubList(full_journey, 0, 0) + [ last_safe_position ], - VECTOR_SEPARATOR)])); - state normal_runtime; - } - - // process the response from the jaunting library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } -} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.txt b/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.txt new file mode 100755 index 00000000..76465b72 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/child_jaunter_v85.2.txt @@ -0,0 +1,679 @@ + +// huffware script: child jaunter, by fred huffhines, released under GPL license. +// +// this is the sub-jaunter implementation, for children of a root jaunter. this script +// handles reconnaissance and one-way trips. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +// configurable constants... + +string TEXT_COLOR = "<0.5, 0.7, 0.95>"; + // set float text color to a nice color. + +integer DEBUGGING = FALSE; + // set to true to get debugging noises. + +// requires jaunting library API. +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available via the jaunting library: +string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a string in jaunt notecard format with vectors. + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// + +// the API for this library script to be used in other scripts. +////////////// +// do not redefine these constants. +integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; + // the unique id within the huffware system for this script's commands. + // it's used in llMessageLinked as the num parameter. +////////////// +// commands available from the library: +string RESET_REZOLATOR = "#reset"; + // tells the script to stop any previous efforts to rez children. +//string REZ_CHILD_NOW = "#rezkd#"; + // requests this script to create a new child object. this requires several + // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object + // to implement, 3) the chat channel to listen for and speak to new child on, + // 4) the destination name for where the child should go, 5) a count of the full + // set of known destinations, 6) the target where the jaunt should arrive at. +string REPORT_CHILD_REZZED = "#reziam"; + // requests that this class report to the root jaunter that a child has rezzed and + // is ready for service. there are no required parameters. +string REZOLATOR_CHILD_SUPPORT = "#rzsup"; + // used by child jaunters to request that the rezolator handle things for them. +string REZOLATOR_CHILD_RETURNED = "#rezdon"; + // used by the child jaunter to tell the rezolator that it has jumped to wherever it + // was supposed to and is ready to report to the parent, if needed. the first parameter + // required for the rezolator is whether the jump was successful (1) or not (0), and + // the second parameter should be the last safe position that the jaunter was at when + // it was possibly closest to the target. +////////////// +// events generated by the library: +//string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; + // an event generated for a previous rez child request. this lets the caller know that + // the child has been created and told what to do. the single parameter is where the + // jaunter has been rezzed. +string REZOLATOR_EVENT_GOT_INSTRUCTIONS = "#rzsta"; + // the root jaunter has given a child instructions on where to go. this info includes + // the name of the destination, the pathway to get there, and the conveyance mode. +//string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; + // an event generated when the recon process has concluded. this includes parms: + // number of good destinations. +// +////////////// + +// important constants used internally... these should not be changed willy nilly. + +////////////// jaunt base API + +// the following constants define how the script should behave (i.e., its conveyance mode). +// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere +// and then takes the same pathway back, but in reverse order. +// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to +// the root telehub. that object is loaded with the destination notecard and this script. +// the rezzed object can then be used for the next few minutes to jaunt to the selected +// destination. the temporary object will use the ONE_WAY_TRIP mode. +// ONE_WAY_TRIP: the object containing this script will take the user to a particular +// destination, but the object does not survive the trip. it self-destructs after +// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER +// mode and should generally never be used on its own. +// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a +// destination. +integer TWO_WAY_TRIP = 1; +integer AUTOREZ_JAUNTER = 2; +integer ONE_WAY_TRIP = 3; +integer RECONNAISSANCE_TRIP = 4; + +// values used to represent different stages of verification. +integer VERIFY_UNTESTED = -3; // don't know destinations tate yet. +integer VERIFY_SAFE = -4; // the destination last tested safe. +integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. +integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. + +integer MAXIMUM_PRIV_CHAN = 90000; + // the largest amount we will ever subtract from the tricky parms in order to + // tell the sub-jaunter which channel to listen on. + +string VECTOR_SEPARATOR = "|"; + // how we separate components of vectors from each other. +string DB_SEPARATOR = "``"; // separating items in lists. + +////////////// end jaunt base API + +integer MAX_DEST_NAME = 24; // the longest name that we store. + +float NORMAL_TIMER_PERIOD = 1.0; // our normal timer rate. + +float POSITION_CHECKING_INTERVAL = 0.11; + // how frequently the waiting for arrival state will check where we are. + +integer MAXIMUM_SLACKNESS = 108; + // how many timer hits we'll allow before reverting to the default state. + +integer FREE_MEM_REQUIRED = 3200; + // we need at least this much memory before adding new targets. + +////////////// + +// global variables. + +integer startup_parm; // recorded at rez time. used for deciding what to do. + +integer conveyance_mode; // when we are given our instructions, we will know what type of jump to use. + +// jaunter target configuration... +string global_name; // the name for our destination. +integer global_verification_state; // the verification state of the last destination we asked for. +string global_pathway; // similar, but the last pathway we heard. + +// jaunt trip variables... +vector eventual_destination; // where we're headed, if we're headed anywhere. +integer slackness_counter; // snoozes had while waiting for destination. +list full_journey; // the full pathway we expect to jaunt on. +integer jaunt_responses_awaited; // number of pending jumps in progress. +integer got_close_enough; // did we arrive at right place? +vector last_safe_position; // where did we actually reach? + +// asks the jaunting library to take us to the target using a list of waypoints. +request_jaunt(list journey, integer forwards) +{ + // ask for a jump. + jaunt_responses_awaited++; + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, + wrap_item_list(journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); + // stops the jaunter in its tracks. + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); +} + +// this function returns TRUE if we are close enough to the "destination". +integer close_enough(vector destination) +{ + float PROXIMITY_REQUIRED = 0.1; + // how close we must be to the target location to call it done. + // matches current jaunting library proximity. + return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); +} + +// sets up the initial state. +initialize_child() +{ + llSetTimerEvent(0.0); // cancel any existing timers. + // load up an arrival sound if any exist. + if (llGetInventoryNumber(INVENTORY_SOUND)) + llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); + if (DEBUGGING) log_it("child init startparm=" + (string)startup_parm); + +//voodoo. + llSleep(0.5); + + if (startup_parm != 0) { + // tell the rezolator to start listening for commands. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZOLATOR_CHILD_SUPPORT, + wrap_parameters([startup_parm])); + // let our parent know we're here. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REPORT_CHILD_REZZED, ""); + } + // set up some of the object properties... + llSetSitText("Jaunt"); // change to the proper text for our mode. +} + +// shows our next target for jaunting above the object. +text_label_for_destination() +{ + string msg = "↣ " + global_name; + llSetText(msg, (vector)TEXT_COLOR, 1.0); +} + +// signal that we are where we were going. +proclaim_arrival() +{ + if (conveyance_mode == ONE_WAY_TRIP) { + // sing a little song, if there's a sound to use. + if (llGetInventoryNumber(INVENTORY_SOUND)) + llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), 1.0); + } +} + +string verification_name(integer enumtype) +{ + if (enumtype == VERIFY_SAFE) return "ok"; + else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; + else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; + // catch-all, including untested. + return "?"; +} + +// returns true if the slackness counter awaiting things has elapsed. +integer check_for_timeout() +{ + if (slackness_counter++ > MAXIMUM_SLACKNESS) { + // go back to the main state. we took too long. + log_it("timed out!"); + llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. + llSetTimerEvent(0.0); + return TRUE; + } + return FALSE; +} + +////////////// + +// returns the value of a boolean variable definition. +integer parse_bool_def(string def) +{ return !(llGetSubString(def, find_substring(def, "=") + 1, -1) == "0"); } + +// processes link messages received from support libraries. +integer handle_link_message(integer which, integer num, string msg, string id) +{ + // is it a jaunting library response? + if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { + jaunt_responses_awaited--; // one less response being awaited. + if (jaunt_responses_awaited < 0) { + log_it("error: responses awaited < 0"); + jaunt_responses_awaited = 0; + } + return FALSE; + } + + // is it an event from the rezolator script? + if (num == JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == REZOLATOR_EVENT_GOT_INSTRUCTIONS) { + global_name = llList2String(parms, 0); + full_journey = [ llGetPos() ] + llParseString2List(llList2String(parms, 1), [VECTOR_SEPARATOR], []); + eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + conveyance_mode = llList2Integer(parms, 2); + if (DEBUGGING) + log_it("got instructions: name=" + global_name + " dest=" + (string)eventual_destination); + text_label_for_destination(); + if (conveyance_mode == RECONNAISSANCE_TRIP) { + return TRUE; + } + } + return FALSE; + } + + return FALSE; +} + +// processes a destination set to handle special cases, like for offset jaunting. +list prechewed_destinations(string dests) +{ + +//document this!!! +// as in, we support the offset format! + + // look for our special start character for offsets. + if (is_prefix(dests, "o")) + // if this is an offset version, then chop whatever word they used starting with 'o' + // and compute the destination based on current position. + return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; + else + // normal jaunt to absolute coordinates. + return llParseString2List(dests, [VECTOR_SEPARATOR], []); +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +/////////////// + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +// returns text for a floating point number, but includes only +// two digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 100.0) / 100); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +////////////// + +// default state scrounges for information in a notecard and looks for landmarks in +// inventory to add as destinations. +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { + startup_parm = parm; + if (DEBUGGING) log_it("default onrez " + (string)startup_parm); + state rerun; + } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + if (DEBUGGING) log_it("=> real_default state, mem=" + (string)llGetFreeMemory()); + initialize_child(); + state normal_runtime; + } + + on_rez(integer parm) { + startup_parm = parm; + if (DEBUGGING) log_it("default onrez " + (string)startup_parm); + state default; + } +} + +// the normal state is pretty calm; the jaunter just sits there waiting for +// an avatar who needs it to do something. +state normal_runtime +{ + state_entry() { + if (DEBUGGING) log_it("=> normal state, mem=" + (string)llGetFreeMemory()); + jaunt_responses_awaited = 0; // nothing pending right now. + got_close_enough = FALSE; // have not even tried going there yet. + } + + on_rez(integer parm) { + startup_parm = parm; + if (DEBUGGING) log_it("default onrez " + (string)startup_parm); + state default; + } + + touch_end(integer total_number) { + // if we got to here, we may need to check the safety of the target and show the + // map if the conditions are right. + if (outside_of_sim(eventual_destination)) { + // bring up the map; maybe we can't get there from here. definitely out of sim. + llMapDestination(llGetRegionName(), eventual_destination, ZERO_VECTOR); + proclaim_arrival(); + } + } + + changed(integer change) { + if (!(change & CHANGED_LINK)) return; // don't care then. +//no, bad, ack. if the jaunter has multiple parts and they sit on non-root prim, this breaks our ability to react to sit events properly. if (llAvatarOnSitTarget() == NULL_KEY) return; // there is no one sitting now. + if (outside_of_sim(eventual_destination)) { + llWhisper(0, "This type of jaunter needs to be clicked rather than sat upon. Please left-click it (or right-click it and select 'touch')."); + llUnSit(llAvatarOnSitTarget()); + return; + } + state jaunting_now; // sweet, we're off. + } + + // process the response from the APIs we use. + link_message(integer which, integer num, string msg, key id) { + if (handle_link_message(which, num, msg, id)) state jaunting_now; + } + +} + +// once someone is trying to jump to a target, this state processes the request. +state jaunting_now +{ + state_entry() { + if (DEBUGGING) log_it("=> jauntnow state, posn=" + vector_chop(llGetPos())); + slackness_counter = 0; + // most jaunters go to at least the first location... + request_jaunt(full_journey, TRUE); + eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + } + + on_rez(integer parm) + { + startup_parm = parm; + if (DEBUGGING) log_it("default onrez " + (string)startup_parm); + state default; + } + + timer() { + if (jaunt_responses_awaited) { + // we are not quite there yet. + if (check_for_timeout()) state normal_runtime; // oops. + return; // not time yet. + } + // we got to where we were going, maybe. unseat the avatar, leaving her + // at the destination. + llUnSit(llAvatarOnSitTarget()); + state arrived_at_target; + } + + // process the response from the jaunting library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } +} + +// this state is activated when the first jaunt is complete. +state arrived_at_target +{ + state_entry() { + if (DEBUGGING) log_it("=> arriv targ state, posn=" + vector_chop(llGetPos())); + // we are close enough; get back to work. + jaunt_responses_awaited = 0; // nothing pending right now. + if (conveyance_mode != RECONNAISSANCE_TRIP) { + llWhisper(0, "↣ " + global_name); + } else { + if (DEBUGGING) { + string close = "yep"; + if (!close_enough(eventual_destination)) close = "nope"; + log_it("close enough here? " + close + ", want to get to " + + (string)eventual_destination); + } + got_close_enough = close_enough(eventual_destination); + last_safe_position = llGetPos(); + } + + // we've gotten where we were going. + proclaim_arrival(); + +//hmmm: nice mod to make the one way trip actually flip its target list and allow a return. + + // reverse direction and head back without rider. + eventual_destination = (vector)llList2String(full_journey, 0); + request_jaunt(full_journey, FALSE); + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + slackness_counter = 0; + if (DEBUGGING) log_it("now trying to jaunt home, responses awaited=" + (string)jaunt_responses_awaited); + } + + on_rez(integer parm) { + startup_parm = parm; + if (DEBUGGING) log_it("default onrez " + (string)startup_parm); + state default; + } + + timer() { + if (jaunt_responses_awaited) { + // we are not quite there yet. + if (check_for_timeout()) state normal_runtime; // oops. + return; // not time yet. + } + if (DEBUGGING) log_it("==> telling parent we got back, now at posn: " + (string)llGetPos()); + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZOLATOR_CHILD_RETURNED, + wrap_parameters([got_close_enough, + llDumpList2String(llDeleteSubList(full_journey, 0, 0) + [ last_safe_position ], + VECTOR_SEPARATOR)])); + state normal_runtime; + } + + // process the response from the jaunting library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } +} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.lsl b/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.lsl deleted file mode 100755 index 2382a845..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.lsl +++ /dev/null @@ -1,12 +0,0 @@ -#jaunt -:add_name=1 -<30, 105, 1825> -huffhines landing -<14, 74, 41> -ground floor -<48, 105, 95> -perilous walkways v4 -<46, 97, 38> -coastal connector -<14, 84, 405> -eepaw shop diff --git a/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.txt b/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.txt new file mode 100755 index 00000000..2382a845 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/coastal_connector_hubs_v2.4.txt @@ -0,0 +1,12 @@ +#jaunt +:add_name=1 +<30, 105, 1825> +huffhines landing +<14, 74, 41> +ground floor +<48, 105, 95> +perilous walkways v4 +<46, 97, 38> +coastal connector +<14, 84, 405> +eepaw shop diff --git a/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.lsl b/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.lsl deleted file mode 100755 index c03cb4c5..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.lsl +++ /dev/null @@ -1,227 +0,0 @@ - -// huffware script: data cow, by fred huffhines. -// -// a data cow is a script that manages a list of text items. it allows an object -// to offload the memory burden of managing a list of items, since LSL is very tight -// on memory, even when compiled to mono. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global variables. - -list the_list; - // the main list that we manage here. we support adding to it, retrieving it - // and modifying it via our API. -list the_names; - // the short names for each item in our list. we are basically supporting a - // symbol table data structure here. - -// link message API for the data cow library. -////////////// -// do not redefine these constants. -integer DATA_COW_HUFFWARE_ID = 10017; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -///string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// -string RESET_LIST_COMMAND = "reset_L"; - // flushes out the currently held list. does not send a reply. -string ADD_ITEM_COMMAND = "add_I"; - // adds items to the list. this is a list of pairs of name/value, where the name is - // how the item will be looked up from the list, and the value is the contents to be stored. - // this command has no reply. -string REMOVE_ITEM_COMMAND = "rm_I"; - // accepts a list of names for items. all the mentioned ones will be removed from the list. - // this command also has no reply. -string GET_COW_LENGTH = "get_Lc"; - // returns a single integer which is the length of the cow's list currently. -string GET_ITEM_COMMAND = "get_I"; - // retrieves the item's contents for a given name. first parm is the name. if there - // are other parameters, then they are taken as other items to return also. - // the return data will be pairs of for each of the names in the request - // that is not empty. note that you can use an integer index by prefacing it with a - // '#' sign. for example, asking for item "#32" will return index 32 in the list of items. -string TAGGED_GET_ITEM_COMMAND = "get_T"; - // like get item, except the first parameter is an identifier that the caller wants to - // use to tag this request. the other parameters are still taken as names. the response - // will contain the tag as the first item, then the pairs that were found. -////////////// - -// sets up the data cow for business. -initialize() -{ - // flush all contents. - the_list = []; - the_names = []; -} - -// find a named item in our list, if it exists. -integer lookup_item(string name) -{ - integer indy; - if (llGetSubString(name, 0, 0) == "#") { - // our special sign for just using an index. - indy = (integer)llGetSubString(name, 1, -1); - if ( (indy >= 0) && (indy < llGetListLength(the_names)) ) return indy; - } else { - for (indy = 0; indy < llGetListLength(the_names); indy++) { - if (name == llList2String(the_names, indy)) return indy; // we know where it is now. - } - } - return -1; // never found it. -} - -// places a named item in our list. if there's an existing item with -// that name, then it's replaced. -integer global_mem_complained = FALSE; -add_item(string name, string content) -{ - if (llGetFreeMemory() < 2000) { - if (!global_mem_complained) { - global_mem_complained = TRUE; - llOwnerSay("out of memory at " + name); - } - return; - } - integer current = lookup_item(name); - if (current < 0) { -//llOwnerSay("new item: " + name); - // this is a new item. - the_names += name; - the_list += content; - } else { -//llOwnerSay("reusing slot " + (string)current + " for " + name); - // this is an old item to be replaced. - the_list = chop_list(the_list, 0, current - 1) - + [ content ] - + chop_list(the_list, current + 1, llGetListLength(the_list) - 1); - } -//log_it("mem=" + (string)llGetFreeMemory()); -} - -// deletes an existing item if possible. TRUE is returned on success. -integer remove_item(string name) -{ - integer indy = lookup_item(name); - if (indy < 0) return FALSE; // not present. - // found our sad whackee. we know the name and content should be - // stored at the exact same index in the two lists. - the_names = chop_list(the_names, 0, indy - 1) - + chop_list(the_names, indy + 1, llGetListLength(the_names) - 1); - the_list = chop_list(the_list, 0, indy - 1) - + chop_list(the_list, indy + 1, llGetListLength(the_list) - 1); - return TRUE; // all done here. -} - -// supports our link message API by answering requests from clients. -handle_link_message(integer sender, integer num, string msg, key id) -{ - if (num != DATA_COW_HUFFWARE_ID) return; // not for us. -//log_it("hlm--mem free=" + (string)llGetFreeMemory()); -//log_it("rcvd: " + msg + " " + (string)num + " " + (string)id); - if (msg == RESET_LIST_COMMAND) { - initialize(); - } else if (msg == ADD_ITEM_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy += 2) { - add_item(llList2String(parms, indy), llList2String(parms, indy + 1)); - } - } else if (msg == REMOVE_ITEM_COMMAND) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy++) { - remove_item(llList2String(parms, indy)); - } - } else if (msg == GET_COW_LENGTH) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string tag = llList2String(parms, 0); - list to_reply; - if (tag != "") to_reply = [ tag ]; - to_reply += [ llGetListLength(the_list) ]; - send_reply(LINK_THIS, to_reply, msg); - } else if ( (msg == GET_ITEM_COMMAND) || (msg == TAGGED_GET_ITEM_COMMAND) ) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer indy; - string tag; - if (msg == TAGGED_GET_ITEM_COMMAND) { - // extract the tag, if they want that type of command handling. - tag = llList2String(parms, 0); - parms = llDeleteSubList(parms, 0, 0); - } - list to_reply; - // make sure we return the tag if they gave us one. - if (tag != "") to_reply = [ tag ]; - for (indy = 0; indy < llGetListLength(parms); indy++) { - // iterate through the parameters and reply about any that we find. - integer found_posn = lookup_item(llList2String(parms, indy)); - if (found_posn >= 0) { - // this item did exist. - to_reply += [ llList2String(the_names, found_posn), llList2String(the_list, found_posn) ]; - } - } - send_reply(LINK_THIS, to_reply, msg); - } -} - -////////////// -// from hufflets... -// -//integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -//log_it(string to_say) -//{ -// debug_num++; -// // tell this to the owner. -// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -// // say this on open chat, but use an unusual channel. -//// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -//} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, DATA_COW_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// -// end hufflets -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { initialize(); } - - link_message(integer sender, integer num, string msg, key id) - { handle_link_message(sender, num, msg, id); } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.txt b/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.txt new file mode 100755 index 00000000..c03cb4c5 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/data_cow_v3.3.txt @@ -0,0 +1,227 @@ + +// huffware script: data cow, by fred huffhines. +// +// a data cow is a script that manages a list of text items. it allows an object +// to offload the memory burden of managing a list of items, since LSL is very tight +// on memory, even when compiled to mono. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global variables. + +list the_list; + // the main list that we manage here. we support adding to it, retrieving it + // and modifying it via our API. +list the_names; + // the short names for each item in our list. we are basically supporting a + // symbol table data structure here. + +// link message API for the data cow library. +////////////// +// do not redefine these constants. +integer DATA_COW_HUFFWARE_ID = 10017; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +///string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// +string RESET_LIST_COMMAND = "reset_L"; + // flushes out the currently held list. does not send a reply. +string ADD_ITEM_COMMAND = "add_I"; + // adds items to the list. this is a list of pairs of name/value, where the name is + // how the item will be looked up from the list, and the value is the contents to be stored. + // this command has no reply. +string REMOVE_ITEM_COMMAND = "rm_I"; + // accepts a list of names for items. all the mentioned ones will be removed from the list. + // this command also has no reply. +string GET_COW_LENGTH = "get_Lc"; + // returns a single integer which is the length of the cow's list currently. +string GET_ITEM_COMMAND = "get_I"; + // retrieves the item's contents for a given name. first parm is the name. if there + // are other parameters, then they are taken as other items to return also. + // the return data will be pairs of for each of the names in the request + // that is not empty. note that you can use an integer index by prefacing it with a + // '#' sign. for example, asking for item "#32" will return index 32 in the list of items. +string TAGGED_GET_ITEM_COMMAND = "get_T"; + // like get item, except the first parameter is an identifier that the caller wants to + // use to tag this request. the other parameters are still taken as names. the response + // will contain the tag as the first item, then the pairs that were found. +////////////// + +// sets up the data cow for business. +initialize() +{ + // flush all contents. + the_list = []; + the_names = []; +} + +// find a named item in our list, if it exists. +integer lookup_item(string name) +{ + integer indy; + if (llGetSubString(name, 0, 0) == "#") { + // our special sign for just using an index. + indy = (integer)llGetSubString(name, 1, -1); + if ( (indy >= 0) && (indy < llGetListLength(the_names)) ) return indy; + } else { + for (indy = 0; indy < llGetListLength(the_names); indy++) { + if (name == llList2String(the_names, indy)) return indy; // we know where it is now. + } + } + return -1; // never found it. +} + +// places a named item in our list. if there's an existing item with +// that name, then it's replaced. +integer global_mem_complained = FALSE; +add_item(string name, string content) +{ + if (llGetFreeMemory() < 2000) { + if (!global_mem_complained) { + global_mem_complained = TRUE; + llOwnerSay("out of memory at " + name); + } + return; + } + integer current = lookup_item(name); + if (current < 0) { +//llOwnerSay("new item: " + name); + // this is a new item. + the_names += name; + the_list += content; + } else { +//llOwnerSay("reusing slot " + (string)current + " for " + name); + // this is an old item to be replaced. + the_list = chop_list(the_list, 0, current - 1) + + [ content ] + + chop_list(the_list, current + 1, llGetListLength(the_list) - 1); + } +//log_it("mem=" + (string)llGetFreeMemory()); +} + +// deletes an existing item if possible. TRUE is returned on success. +integer remove_item(string name) +{ + integer indy = lookup_item(name); + if (indy < 0) return FALSE; // not present. + // found our sad whackee. we know the name and content should be + // stored at the exact same index in the two lists. + the_names = chop_list(the_names, 0, indy - 1) + + chop_list(the_names, indy + 1, llGetListLength(the_names) - 1); + the_list = chop_list(the_list, 0, indy - 1) + + chop_list(the_list, indy + 1, llGetListLength(the_list) - 1); + return TRUE; // all done here. +} + +// supports our link message API by answering requests from clients. +handle_link_message(integer sender, integer num, string msg, key id) +{ + if (num != DATA_COW_HUFFWARE_ID) return; // not for us. +//log_it("hlm--mem free=" + (string)llGetFreeMemory()); +//log_it("rcvd: " + msg + " " + (string)num + " " + (string)id); + if (msg == RESET_LIST_COMMAND) { + initialize(); + } else if (msg == ADD_ITEM_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy += 2) { + add_item(llList2String(parms, indy), llList2String(parms, indy + 1)); + } + } else if (msg == REMOVE_ITEM_COMMAND) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy++) { + remove_item(llList2String(parms, indy)); + } + } else if (msg == GET_COW_LENGTH) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string tag = llList2String(parms, 0); + list to_reply; + if (tag != "") to_reply = [ tag ]; + to_reply += [ llGetListLength(the_list) ]; + send_reply(LINK_THIS, to_reply, msg); + } else if ( (msg == GET_ITEM_COMMAND) || (msg == TAGGED_GET_ITEM_COMMAND) ) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer indy; + string tag; + if (msg == TAGGED_GET_ITEM_COMMAND) { + // extract the tag, if they want that type of command handling. + tag = llList2String(parms, 0); + parms = llDeleteSubList(parms, 0, 0); + } + list to_reply; + // make sure we return the tag if they gave us one. + if (tag != "") to_reply = [ tag ]; + for (indy = 0; indy < llGetListLength(parms); indy++) { + // iterate through the parameters and reply about any that we find. + integer found_posn = lookup_item(llList2String(parms, indy)); + if (found_posn >= 0) { + // this item did exist. + to_reply += [ llList2String(the_names, found_posn), llList2String(the_list, found_posn) ]; + } + } + send_reply(LINK_THIS, to_reply, msg); + } +} + +////////////// +// from hufflets... +// +//integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +//log_it(string to_say) +//{ +// debug_num++; +// // tell this to the owner. +// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +// // say this on open chat, but use an unusual channel. +//// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +//} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, DATA_COW_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// +// end hufflets +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { initialize(); } + + link_message(integer sender, integer num, string msg, key id) + { handle_link_message(sender, num, msg, id); } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.lsl b/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.lsl deleted file mode 100755 index 97458789..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.lsl +++ /dev/null @@ -1,25 +0,0 @@ -#jaunt -:show_text=1 -:add_name=1 -<14, 74, 41> -ground floor -<46, 97, 38> -coastal connector -<47, 105, 85> -worm tube walkway -<11, 75, 99> -penthouse de moo -<17, 76, 109> -flower deck -<48, 105, 95> -perilous walkways v4 -<42, 86, 750> -high sierra testing zone -<34, 90, 1008> -om 1008 disc -<24, 72, 1224> -get ready--long drop -<36, 93, 4095> -nearly off world -<14, 84, 405> -eepaw shop diff --git a/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.txt b/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.txt new file mode 100755 index 00000000..97458789 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/fred_main_hubs_v5.4.txt @@ -0,0 +1,25 @@ +#jaunt +:show_text=1 +:add_name=1 +<14, 74, 41> +ground floor +<46, 97, 38> +coastal connector +<47, 105, 85> +worm tube walkway +<11, 75, 99> +penthouse de moo +<17, 76, 109> +flower deck +<48, 105, 95> +perilous walkways v4 +<42, 86, 750> +high sierra testing zone +<34, 90, 1008> +om 1008 disc +<24, 72, 1224> +get ready--long drop +<36, 93, 4095> +nearly off world +<14, 84, 405> +eepaw shop diff --git a/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.lsl b/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.lsl deleted file mode 100755 index 4a458bb5..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.lsl +++ /dev/null @@ -1,826 +0,0 @@ - -// huffware script: huff-update client, by fred huffhines. -// -// this script is the client side of the update process. it should reside in an object that -// has scripts which should be automatically updated. it will listen for announcements by -// an update server and communicate with the server to ensure that all of its scripts are -// the most up to date available with the server. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -integer DEBUGGING = FALSE; // if TRUE, the script will output status information. - -integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. - -integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -integer MAXIMUM_SERVERS_TRACKED = 32; - // we will listen to this many servers before we decide to remove one. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string SERVER_SCRIPT = "a huffotronic update server"; - // the prefix of our server script that hands out updates. - -// global variables... - -integer inventory_request_channel; // used for newer version servers to cut down cross chatter. -list updaters_heard; // the update servers we've heard from recently. -list last_interactions; // times of the last update process engaged with the updater. -integer update_channel; // current channel for interaction with specific server. -key current_server; // the updater that is active right now, if any. -integer update_start_time; // when the last update process began. -list updates_needed; // stores the set of scripts that are in need of an update. -list known_script_dependencies; // stores the list of dependency info. - -careful_crankup() -{ - knock_around_other_scripts(TRUE); - // clean out the older items and scripts. we do this after getting everyone running - // since we might be whacking ourselves. - destroy_older_versions(); -} - -// reset our variables. -initialize() -{ - updaters_heard = []; - last_interactions = []; - inventory_request_channel = 0; - update_channel = 0; - current_server = NULL_KEY; - llSetTimerEvent(0.0); - llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); - // a new enhancements; tells the server that this guy has finished an update cycle. this - // only comes into play when the updater script itself has just been updated, but it's - // nice for the server to avoid claiming erroneous timeouts occurred. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); - llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); -} - -whack_updater_record(key id) -{ - integer prev_indy = find_in_list(updaters_heard, id); - if (prev_indy < 0) return; // not there. - updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) - + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); - last_interactions = chop_list(last_interactions, 0, prev_indy - 1) - + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); -} - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - if (DEBUGGING) - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -// sets the object to be listening for update info. -// if "just_owner" is true, then we will not listen on the general announcement channel. -listen_for_orders(integer just_owner) -{ - if (!just_owner) { - // try to hear an update being announced. - llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); - } - - // super secret owner controls. - llListen(0, "", llGetOwner(), ""); -} - -// returns true if this object is a huffotronic updater of some sort. -integer inside_of_updater() -{ - return find_substring(llGetObjectName(), "huffotronic") >= 0; -} - -// returns true if a script is a version of our update server. -integer matches_server_script(string to_check) -{ - return is_prefix(to_check, SERVER_SCRIPT); -} - -// stops all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - integer insider = inside_of_updater(); - if (running_state == TRUE) { - // make sure we crank up the scripts that are new first. we want to reset them - // as well, which we don't want to do for any existing scripts. - integer crank_indy; - for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { - string crankee = llList2String(updates_needed, crank_indy); - if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { - if (!insider || matches_server_script(crankee)) { - // allow it to run again. - llSetScriptState(crankee, TRUE); - // reset it, to make sure it starts at the top. - llResetOtherScript(crankee); - } - } - } - } - - integer indy; - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if ( (curr_script != self_script) - && (!insider || matches_server_script(curr_script)) ) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -// a random channel for the interaction with the server. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// make sure that any dependencies for the script with "basename" are added to the list -// of requests we make during an update. -list add_dependencies(string basename) -{ - list to_return; - integer indy; - for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { - list deps = llParseString2List(llList2String(known_script_dependencies, indy), - [ITEM_LIST_SEPARATOR], []); -//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); - if (basename == llList2String(deps, 0)) { - // first off, is this item with new dependencies actually present? - integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); - if (where >= 0) { - // we do use the script with deps, but is the dependent item really missing? - where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); - if (where < 0) { - // we found a dependency match for this script, so we'll ask for the missing item. - if (DEBUGGING) - log_it("missing dep: " + llList2String(deps, 1)); - to_return += [ llList2String(deps, 1) ]; - } - } - } - } - return to_return; -} - -// complains if memory seems to be getting tight. -test_memory() -{ - if (llGetFreeMemory() < 4096) - log_it("mem_free = " + (string)llGetFreeMemory()); -} - -// starts an update given a list of scripts that the server has available, encoded as -// a string in the "encoded_list". -integer initiate_update(string encoded_list) -{ - list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); - integer continue_listening_for_scripts = FALSE; - // if true, we aren't done hearing about available scripts yet. - encoded_list = ""; - // figure out which scripts we need by comparing the list available from the server - // against our current inventory. we only want scripts with newer version numbers. - integer sindy; - for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { - string curr = llList2String(scripts_avail, sindy); - if (curr == CONTINUANCE_MARKER) { - // this is a special continuation signal. we need to hear the rest of the list. - continue_listening_for_scripts = TRUE; - } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { - // we've found a dependency item. - known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; -//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); - } else { - list split = compute_basename_and_version(curr); - if (llGetListLength(split) == 2) { - string basename = llList2String(split, 0); - string version = llList2String(split, 1); - split = []; - integer oy_indy; -//replace common code with func. - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { -// if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); -// } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - updates_needed += add_dependencies(basename); - } - } - } - // we skip the next step if we're still waiting to hear about more. - if (continue_listening_for_scripts) { -//log_it("still listening for more updates..."); - return FALSE; - } - if (llGetListLength(updates_needed)) { -//log_it("update chan=" + (string)update_channel); - llSay(update_channel, REQUEST_SCRIPT_UPDATE); - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i need updating."); - } - } else { - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i am done updating."); - } - llSay(update_channel, DONE_UPDATING); - } - return TRUE; -} - -// this alerts the server to our most desired scripts. -tell_server_our_wish_list() -{ - llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); -} - -// checks whether all of the updates needed are present yet. -integer check_on_update_presence() -{ - integer indy; - for (indy = 0; indy < llGetListLength(updates_needed); indy++) { - integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); - // any single missing guy means they aren't up to date yet. - if (found < 0) { - if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); - return FALSE; - } - } - // nothing was detected as missing anymore. - return TRUE; -} - -// respond to spoken commands from the server. -integer process_update_news(integer channel, string name, key id, string message) -{ - if (!channel) { - // this is a command. - if (message == "ureset") { - llResetScript(); // start over. - } - if (message == "ushow") { - integer sindy; - integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); - list script_list = [ "scripts--" ]; // first item is just a header. - for (sindy = 0; sindy < script_count; sindy++) { - script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; - } - dump_list_to_log(script_list); - } - return FALSE; // nothing to do here. - } - if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { -/* never seen. if (id == llGetKey()) { -if (DEBUGGING) log_it("ignoring update from self."); - return FALSE; // ack, that's our very object. - } -*/ - if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { - // this is a new style update message. we can set a different request channel. - string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); - inventory_request_channel = (integer)just_chan; - } - integer prev_indy = find_in_list(updaters_heard, id); - // find the talker in our list. - if (prev_indy >= 0) { - // that guy was already heard from. check when last interacted. - integer last_heard = llList2Integer(last_interactions, prev_indy); - if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { - return FALSE; // not time to update with this guy again yet. - } -// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } - // make sure we think of this as a new updater now. - whack_updater_record(id); - } - - if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } - // record our new server. - current_server = id; - // make a random pause so not all updaters try to crank up at same time. - llSleep(randomize_within_range(2.8, 18.2, FALSE)); - - if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { - // oops, this is not good. we have too many servers now. -//hmmm: room for improvement here by tossing out the server that is oldest. - updaters_heard = llDeleteSubList(updaters_heard, 0, 0); - last_interactions = llDeleteSubList(last_interactions, 0, 0); - } - - // add the talker to our list. - updaters_heard += id; - last_interactions += llGetUnixTime(); - - // begin the update interaction with this guy. - update_channel = random_channel(); - return TRUE; - } - if (update_channel && (channel == update_channel) ) { - if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { - // tasty, this is a list of scripts that can be had. - message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); - if (message == BUSY_BUSY) { - // server has signified that it's too busy (or its owner is a moron) because it is - // claiming it has no scripts at all. - if (DEBUGGING) { - log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); - } - // make it seem like we need to do this one again sooner than normal. - whack_updater_record(id); - // busy server means move no further forward. - return FALSE; - } - return initiate_update(message); - } else if (is_prefix(message, SHUT_THEM_DOWN)) { - if (DEBUGGING) { log_it("stopping other scripts."); } - knock_around_other_scripts(FALSE); - // now that we know for sure the server's ready to update us, - // we tell it what we need. - tell_server_our_wish_list(); - return FALSE; - } else if (is_prefix(message, START_THEM_UP)) { - // let the server know that we've finished, for all intents and purposes. - llSay(update_channel, DONE_UPDATING); - // we pause a random bit first; we want to ensure we aren't swamping - // SL with our inventory loading. - llSleep(randomize_within_range(2.5, 8.2, FALSE)); - if (DEBUGGING) { log_it("starting other scripts."); } - careful_crankup(); - return TRUE; // change state now. -// } else { -//log_it("unknown command on update channel: " + message); - } - } - return FALSE; -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) - return inv; - else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) - return inv; - } - return -2; // failed to find it. -} - -////////////// - -integer MAX_CHAT_LINE = 900; - // the most characters we'll try to say in one chat. - -dump_list_to_log(list to_show) -{ - string text = dump_list(to_show); // get some help from the other version. - integer len = llStringLength(text); - integer i; - for (i = 0; i < len; i += MAX_CHAT_LINE) { - integer last_bit = i + MAX_CHAT_LINE - 1; - if (last_bit >= len) last_bit = len - 1; - string next_line = llGetSubString(text, i, last_bit); - llWhisper(0, next_line); - } -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "\"" + next_line + "\""; - } - text = text + next_line; - if (i < len - 1) text = text + " "; - } - return text; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -// no huffotronic trap state for startup, because this script will actually -// run (and is expected) inside a huffotronic updater object. - -default -{ - state_entry() - { - auto_retire(); // only allow the most recent revision. - initialize(); - state awaiting_commands; - } -} - -state awaiting_commands -{ - state_entry() - { - if (DEBUGGING) log_it(""); - careful_crankup(); // we always start by getting everyone running. - current_server = NULL_KEY; // forget previous server. - listen_for_orders(FALSE); - inventory_request_channel = 0; // no inventory request channel either. - update_channel = 0; // no channel currently. - updates_needed = []; // we know of no needs right now. - known_script_dependencies = []; // no deps either. - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) - state establish_private_channel; - } -} - -state establish_private_channel -{ - state_entry() - { - if (DEBUGGING) log_it(""); - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (inventory_request_channel) - llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); - else - llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); - llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); - } - - state_exit() { llSetTimerEvent(0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // ready for a state change, but what kind? - if (llGetListLength(updates_needed)) { -//log_it("have a list of updates now."); - state performing_update; - } else { -//log_it("no updates needed in list, going back"); - state awaiting_commands; - } - } - } - - timer() { - if (DEBUGGING) { - log_it("timed out establishing channel with server " + (string)inventory_request_channel); - } - whack_updater_record(current_server); - state awaiting_commands; - } - - on_rez(integer parm) { state default; } -} - -state performing_update -{ - state_entry() - { - // must re-listen after a state change. - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (DEBUGGING) log_it(""); - llSetTimerEvent(UPDATE_TIMER_INTERVAL); - update_start_time = llGetUnixTime(); - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // normal finish of update process. - state awaiting_commands; - } - } - - timer() { - if (llGetListLength(updates_needed) == 0) { -//log_it("nothing to update, leaving perform state."); - state awaiting_commands; // we've got nothing to do. - } else { - // see if all our requested scripts are there yet; if not, we're not done updating. - integer ready = check_on_update_presence(); - if (ready) { - if (DEBUGGING) log_it("reporting scripts are current."); - llSay(update_channel, SCRIPTS_ARE_CURRENT); - } - } - if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { - if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } - whack_updater_record(current_server); - state awaiting_commands; - } - } - - on_rez(integer parm) { state default; } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.txt b/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.txt new file mode 100755 index 00000000..4a458bb5 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/huff-update_client_v20.1.txt @@ -0,0 +1,826 @@ + +// huffware script: huff-update client, by fred huffhines. +// +// this script is the client side of the update process. it should reside in an object that +// has scripts which should be automatically updated. it will listen for announcements by +// an update server and communicate with the server to ensure that all of its scripts are +// the most up to date available with the server. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +integer DEBUGGING = FALSE; // if TRUE, the script will output status information. + +integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. + +integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +integer MAXIMUM_SERVERS_TRACKED = 32; + // we will listen to this many servers before we decide to remove one. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string SERVER_SCRIPT = "a huffotronic update server"; + // the prefix of our server script that hands out updates. + +// global variables... + +integer inventory_request_channel; // used for newer version servers to cut down cross chatter. +list updaters_heard; // the update servers we've heard from recently. +list last_interactions; // times of the last update process engaged with the updater. +integer update_channel; // current channel for interaction with specific server. +key current_server; // the updater that is active right now, if any. +integer update_start_time; // when the last update process began. +list updates_needed; // stores the set of scripts that are in need of an update. +list known_script_dependencies; // stores the list of dependency info. + +careful_crankup() +{ + knock_around_other_scripts(TRUE); + // clean out the older items and scripts. we do this after getting everyone running + // since we might be whacking ourselves. + destroy_older_versions(); +} + +// reset our variables. +initialize() +{ + updaters_heard = []; + last_interactions = []; + inventory_request_channel = 0; + update_channel = 0; + current_server = NULL_KEY; + llSetTimerEvent(0.0); + llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); + // a new enhancements; tells the server that this guy has finished an update cycle. this + // only comes into play when the updater script itself has just been updated, but it's + // nice for the server to avoid claiming erroneous timeouts occurred. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); + llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); +} + +whack_updater_record(key id) +{ + integer prev_indy = find_in_list(updaters_heard, id); + if (prev_indy < 0) return; // not there. + updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) + + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); + last_interactions = chop_list(last_interactions, 0, prev_indy - 1) + + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); +} + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + if (DEBUGGING) + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +// sets the object to be listening for update info. +// if "just_owner" is true, then we will not listen on the general announcement channel. +listen_for_orders(integer just_owner) +{ + if (!just_owner) { + // try to hear an update being announced. + llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); + } + + // super secret owner controls. + llListen(0, "", llGetOwner(), ""); +} + +// returns true if this object is a huffotronic updater of some sort. +integer inside_of_updater() +{ + return find_substring(llGetObjectName(), "huffotronic") >= 0; +} + +// returns true if a script is a version of our update server. +integer matches_server_script(string to_check) +{ + return is_prefix(to_check, SERVER_SCRIPT); +} + +// stops all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + integer insider = inside_of_updater(); + if (running_state == TRUE) { + // make sure we crank up the scripts that are new first. we want to reset them + // as well, which we don't want to do for any existing scripts. + integer crank_indy; + for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { + string crankee = llList2String(updates_needed, crank_indy); + if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { + if (!insider || matches_server_script(crankee)) { + // allow it to run again. + llSetScriptState(crankee, TRUE); + // reset it, to make sure it starts at the top. + llResetOtherScript(crankee); + } + } + } + } + + integer indy; + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if ( (curr_script != self_script) + && (!insider || matches_server_script(curr_script)) ) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +// a random channel for the interaction with the server. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// make sure that any dependencies for the script with "basename" are added to the list +// of requests we make during an update. +list add_dependencies(string basename) +{ + list to_return; + integer indy; + for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { + list deps = llParseString2List(llList2String(known_script_dependencies, indy), + [ITEM_LIST_SEPARATOR], []); +//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); + if (basename == llList2String(deps, 0)) { + // first off, is this item with new dependencies actually present? + integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); + if (where >= 0) { + // we do use the script with deps, but is the dependent item really missing? + where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); + if (where < 0) { + // we found a dependency match for this script, so we'll ask for the missing item. + if (DEBUGGING) + log_it("missing dep: " + llList2String(deps, 1)); + to_return += [ llList2String(deps, 1) ]; + } + } + } + } + return to_return; +} + +// complains if memory seems to be getting tight. +test_memory() +{ + if (llGetFreeMemory() < 4096) + log_it("mem_free = " + (string)llGetFreeMemory()); +} + +// starts an update given a list of scripts that the server has available, encoded as +// a string in the "encoded_list". +integer initiate_update(string encoded_list) +{ + list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); + integer continue_listening_for_scripts = FALSE; + // if true, we aren't done hearing about available scripts yet. + encoded_list = ""; + // figure out which scripts we need by comparing the list available from the server + // against our current inventory. we only want scripts with newer version numbers. + integer sindy; + for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { + string curr = llList2String(scripts_avail, sindy); + if (curr == CONTINUANCE_MARKER) { + // this is a special continuation signal. we need to hear the rest of the list. + continue_listening_for_scripts = TRUE; + } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { + // we've found a dependency item. + known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; +//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); + } else { + list split = compute_basename_and_version(curr); + if (llGetListLength(split) == 2) { + string basename = llList2String(split, 0); + string version = llList2String(split, 1); + split = []; + integer oy_indy; +//replace common code with func. + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { +// if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); +// } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + updates_needed += add_dependencies(basename); + } + } + } + // we skip the next step if we're still waiting to hear about more. + if (continue_listening_for_scripts) { +//log_it("still listening for more updates..."); + return FALSE; + } + if (llGetListLength(updates_needed)) { +//log_it("update chan=" + (string)update_channel); + llSay(update_channel, REQUEST_SCRIPT_UPDATE); + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i need updating."); + } + } else { + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i am done updating."); + } + llSay(update_channel, DONE_UPDATING); + } + return TRUE; +} + +// this alerts the server to our most desired scripts. +tell_server_our_wish_list() +{ + llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); +} + +// checks whether all of the updates needed are present yet. +integer check_on_update_presence() +{ + integer indy; + for (indy = 0; indy < llGetListLength(updates_needed); indy++) { + integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); + // any single missing guy means they aren't up to date yet. + if (found < 0) { + if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); + return FALSE; + } + } + // nothing was detected as missing anymore. + return TRUE; +} + +// respond to spoken commands from the server. +integer process_update_news(integer channel, string name, key id, string message) +{ + if (!channel) { + // this is a command. + if (message == "ureset") { + llResetScript(); // start over. + } + if (message == "ushow") { + integer sindy; + integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); + list script_list = [ "scripts--" ]; // first item is just a header. + for (sindy = 0; sindy < script_count; sindy++) { + script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; + } + dump_list_to_log(script_list); + } + return FALSE; // nothing to do here. + } + if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { +/* never seen. if (id == llGetKey()) { +if (DEBUGGING) log_it("ignoring update from self."); + return FALSE; // ack, that's our very object. + } +*/ + if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { + // this is a new style update message. we can set a different request channel. + string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); + inventory_request_channel = (integer)just_chan; + } + integer prev_indy = find_in_list(updaters_heard, id); + // find the talker in our list. + if (prev_indy >= 0) { + // that guy was already heard from. check when last interacted. + integer last_heard = llList2Integer(last_interactions, prev_indy); + if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { + return FALSE; // not time to update with this guy again yet. + } +// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } + // make sure we think of this as a new updater now. + whack_updater_record(id); + } + + if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } + // record our new server. + current_server = id; + // make a random pause so not all updaters try to crank up at same time. + llSleep(randomize_within_range(2.8, 18.2, FALSE)); + + if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { + // oops, this is not good. we have too many servers now. +//hmmm: room for improvement here by tossing out the server that is oldest. + updaters_heard = llDeleteSubList(updaters_heard, 0, 0); + last_interactions = llDeleteSubList(last_interactions, 0, 0); + } + + // add the talker to our list. + updaters_heard += id; + last_interactions += llGetUnixTime(); + + // begin the update interaction with this guy. + update_channel = random_channel(); + return TRUE; + } + if (update_channel && (channel == update_channel) ) { + if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { + // tasty, this is a list of scripts that can be had. + message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); + if (message == BUSY_BUSY) { + // server has signified that it's too busy (or its owner is a moron) because it is + // claiming it has no scripts at all. + if (DEBUGGING) { + log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); + } + // make it seem like we need to do this one again sooner than normal. + whack_updater_record(id); + // busy server means move no further forward. + return FALSE; + } + return initiate_update(message); + } else if (is_prefix(message, SHUT_THEM_DOWN)) { + if (DEBUGGING) { log_it("stopping other scripts."); } + knock_around_other_scripts(FALSE); + // now that we know for sure the server's ready to update us, + // we tell it what we need. + tell_server_our_wish_list(); + return FALSE; + } else if (is_prefix(message, START_THEM_UP)) { + // let the server know that we've finished, for all intents and purposes. + llSay(update_channel, DONE_UPDATING); + // we pause a random bit first; we want to ensure we aren't swamping + // SL with our inventory loading. + llSleep(randomize_within_range(2.5, 8.2, FALSE)); + if (DEBUGGING) { log_it("starting other scripts."); } + careful_crankup(); + return TRUE; // change state now. +// } else { +//log_it("unknown command on update channel: " + message); + } + } + return FALSE; +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) + return inv; + else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) + return inv; + } + return -2; // failed to find it. +} + +////////////// + +integer MAX_CHAT_LINE = 900; + // the most characters we'll try to say in one chat. + +dump_list_to_log(list to_show) +{ + string text = dump_list(to_show); // get some help from the other version. + integer len = llStringLength(text); + integer i; + for (i = 0; i < len; i += MAX_CHAT_LINE) { + integer last_bit = i + MAX_CHAT_LINE - 1; + if (last_bit >= len) last_bit = len - 1; + string next_line = llGetSubString(text, i, last_bit); + llWhisper(0, next_line); + } +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "\"" + next_line + "\""; + } + text = text + next_line; + if (i < len - 1) text = text + " "; + } + return text; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +// no huffotronic trap state for startup, because this script will actually +// run (and is expected) inside a huffotronic updater object. + +default +{ + state_entry() + { + auto_retire(); // only allow the most recent revision. + initialize(); + state awaiting_commands; + } +} + +state awaiting_commands +{ + state_entry() + { + if (DEBUGGING) log_it(""); + careful_crankup(); // we always start by getting everyone running. + current_server = NULL_KEY; // forget previous server. + listen_for_orders(FALSE); + inventory_request_channel = 0; // no inventory request channel either. + update_channel = 0; // no channel currently. + updates_needed = []; // we know of no needs right now. + known_script_dependencies = []; // no deps either. + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) + state establish_private_channel; + } +} + +state establish_private_channel +{ + state_entry() + { + if (DEBUGGING) log_it(""); + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (inventory_request_channel) + llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); + else + llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); + llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); + } + + state_exit() { llSetTimerEvent(0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // ready for a state change, but what kind? + if (llGetListLength(updates_needed)) { +//log_it("have a list of updates now."); + state performing_update; + } else { +//log_it("no updates needed in list, going back"); + state awaiting_commands; + } + } + } + + timer() { + if (DEBUGGING) { + log_it("timed out establishing channel with server " + (string)inventory_request_channel); + } + whack_updater_record(current_server); + state awaiting_commands; + } + + on_rez(integer parm) { state default; } +} + +state performing_update +{ + state_entry() + { + // must re-listen after a state change. + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (DEBUGGING) log_it(""); + llSetTimerEvent(UPDATE_TIMER_INTERVAL); + update_start_time = llGetUnixTime(); + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // normal finish of update process. + state awaiting_commands; + } + } + + timer() { + if (llGetListLength(updates_needed) == 0) { +//log_it("nothing to update, leaving perform state."); + state awaiting_commands; // we've got nothing to do. + } else { + // see if all our requested scripts are there yet; if not, we're not done updating. + integer ready = check_on_update_presence(); + if (ready) { + if (DEBUGGING) log_it("reporting scripts are current."); + llSay(update_channel, SCRIPTS_ARE_CURRENT); + } + } + if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { + if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } + whack_updater_record(current_server); + state awaiting_commands; + } + } + + on_rez(integer parm) { state default; } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.lsl b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.lsl deleted file mode 100755 index c09890c8..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.lsl +++ /dev/null @@ -1,494 +0,0 @@ - -// huffware script: jaunt config funcs, by fred huffhines, released under GPL license. -// -// this is the part of the jaunt wik rez ensemble that deals with configuration. -// it reads the configuration from notecards and passes it to the main script. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -integer DEBUGGING = FALSE; - // make this true for noisy runtime diagnostics. - -// defines the jaunt config funcs messaging API. -////////////// -// do not redefine these constants. -integer JAUNT_CONFIGURATION_HUFFWARE_ID = 10022; - // the unique id within the huffware system for this script's commands. - // it's used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available from the jaunt config library: -string LOAD_ALL_CONFIGURATIONS = "#rdcfg#"; - // this starts the process of loading jaunt destinations from the notecards and - // landmarks that we find in the object. the parms are: private channel - // and conveyance mode. -string JAUNT_CFG_DATA_EVENT = "#yodata#"; - // this event is generated from this script back to the caller. when we have some - // landmark data or configuration information, it's passed back in chunks. the - // deluge of pieces will continue until the JAUNT_CFG_EOF event is passed. the - // parameters include packed destination name and vector pairs (which form 2 elements - // in the list) and packed config variable definitions (where config items start - // with a colon, and the definition is only one element in the list). -string JAUNT_CFG_EOF = "#done#"; - // sent after all valid configuration items that we could find were processed. there - // are no parameters for this command. -// -////////////// - -// important constants used internally... these should generally not be changed. - -// indicates a reconnaissance command when found as a prefix on chat text -// on our official recon channel. -string RECON_TEXT = "#rcn"; -string READY_TEXT = "-y"; // lets us know that a jaunter is ready to be filled. -string RETURN_WORD = "-b"; // used to signal a returning recong jaunter. - -integer MAXIMUM_BLAST_SIZE = 6; // maximum number of config items per blurt. - -integer TIMEOUT_FOR_CONFIGURATION_PROCESS = 42; - // how long the notecard and lm reading processes are allowed to last. - -integer TWO_WAY_TRIP = 1; -integer AUTOREZ_JAUNTER = 2; -integer ONE_WAY_TRIP = 3; -integer RECONNAISSANCE_TRIP = 4; - -string DB_SEPARATOR = "``"; // separating items in lists. - -////////////// - -// global variables. - -integer unused_private_chat_channel; // where sub-jaunters communicate with root. - -integer conveyance_mode; //// = TWO_WAY_TRIP; - // default is a standard two way trip, there and back again. note that the object - // will fail to return if any lands in between are blocking object entry. those - // situations should use an auto-rez jaunter, which is specified by prefixing the - // target vectors with AR. - -////integer current_target_index; // the location in the list that we would currently jaunt to. - -list config_to_blast; // what we will send to our client. - -// notecard variables... -integer response_code; // set to uniquely identify the notecard read in progress. -string leftover_parms; // items leftover during config. - -// lm variables... -integer current_lm; -key lm_data_req; // this is the current landmark being served as data. - -////////////// - -// requires noteworthy library v5.4 or higher. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -//string BUSY_READING_INDICATOR = "busy_already"; - // this return value indicates that the script is already in use by some other script. - // the calling script should try again later. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the only parameter. the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // an embedded list that was read from the notecard. this necessarily limits the - // size of the notecards that we can read and return. -// -////////////// - -// begins getting configuration items from notecards and landmarks. -start_reading_configuration() -{ - llSetTimerEvent(0.0); // cancel any existing timers. - - string JAUNT_SIGNATURE = "#jaunt"; // the expected first line of our notecards. - - // a normal startup where we read notecards and stuff... - // see if we can load a notecard for destinations. - response_code = random_channel(); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - wrap_parameters([JAUNT_SIGNATURE, response_code])); - // we pick a private channel that fits in between our rez parm ranges. - // during a normal trip, we will make sure the notecard reading doesn't stall. - // the recon and one way jaunters don't need this; they're temporary. - // we allow this number of seconds before notecard reader is awol. - - llSetTimerEvent(TIMEOUT_FOR_CONFIGURATION_PROCESS); -} - -// main API implementor; answers requests to start reading config. -handle_config_request(string msg, string id) -{ - if (msg != LOAD_ALL_CONFIGURATIONS) return; // not for us. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - // set our variables from the parameters we were given. - unused_private_chat_channel = llList2Integer(parms, 0); - conveyance_mode = llList2Integer(parms, 1); - if ( (conveyance_mode != RECONNAISSANCE_TRIP) && (conveyance_mode != ONE_WAY_TRIP) ) { - // setting up a root jaunter. - start_reading_configuration(); - } -} - -// sends out our current configuration perhaps. if the check_length flag is true, -// then we'll only send if the list is already too fat. if the flag is false, then -// we always just send our config (if it's non-empty). -send_config_blast(integer check_length) -{ - if (!check_length || (llGetListLength(config_to_blast) > MAXIMUM_BLAST_SIZE) ) { - if (llGetListLength(config_to_blast) > 0) { - llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE, - JAUNT_CFG_DATA_EVENT, wrap_parameters(config_to_blast)); - config_to_blast = []; - } - } -} - -// deals with responses from the notecard library. -process_notecard_lines(string msg, string id) -{ - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (llList2Integer(parms, 1) != response_code) return; // this isn't for us. - - integer totally_done = TRUE; // if left set to true, then notecard is done being consumed. - - string note_name = llList2String(parms, 0); - if (DEBUGGING) log_it("note name: " + note_name); - parms = llDeleteSubList(parms, 0, 1); - - // add in the leftovers. - if (leftover_parms != "") { - if (DEBUGGING) log_it("added leftover: " + leftover_parms); - parms = [ leftover_parms ] + parms; - leftover_parms = ""; - } - - if (note_name == NOTECARD_READ_CONTINUATION) { - totally_done = FALSE; - if (DEBUGGING) log_it("not totally done reading yet."); - } - if (note_name != BAD_NOTECARD_INDICATOR) { - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy++) { - if (DEBUGGING) log_it("index: " + (string)indy); - string targ = llList2String(parms, indy); - if (DEBUGGING) log_it("targ: " + targ); - if (is_prefix(targ, ":")) { - if (DEBUGGING) log_it("targ is special command. just adding."); - config_to_blast += [ targ ]; - } else { - if (indy < llGetListLength(parms) - 1) { - if (DEBUGGING) log_it("decided we can steal two items."); - // this looks like a normal pair of destination vector and name. - string the_name = prune_name(llList2String(parms, indy + 1)); - config_to_blast += [ the_name, targ ]; - if (DEBUGGING) log_it("stole: " + the_name + " --> " + targ); - indy++; // skip an extra index since we stole two. - } else { - // save this tidbit for next config cycle. - if (DEBUGGING) log_it("saving tidbit for next round: " + targ); - leftover_parms = targ; - } - } - send_config_blast(TRUE); - } - } - - if (totally_done) { - // now that we've gotten our notecard read in, check the landmarks in - // the inventory to see if they're useful. - current_lm = 0; - if (current_lm < llGetInventoryNumber(INVENTORY_LANDMARK)) { - lm_data_req = llRequestInventoryData( - llGetInventoryName(INVENTORY_LANDMARK, current_lm)); - } else { - // kick out of this state and signal completion. - llSetTimerEvent(0.001); - } - } -} - -// report our getting configured properly. -completed_configuration() -{ - send_config_blast(FALSE); // get last of config bits out to the client. - llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE, - JAUNT_CFG_EOF, NULL_KEY); -} - -// fixes a location name so we don't get crushed on memory usage. -string prune_name(string to_prune) -{ - integer MAX_DEST_NAME = 28; // the longest name that we store. - - // see if we can strip off the locational info. comma is a common separator for stuff that's - // not part of the lm name. - integer indy = find_substring(to_prune, ","); - if (indy > 5) to_prune = llGetSubString(to_prune, 0, indy - 1); - // parentheses are another common way of adding extra stuff we don't need for the name. - indy = find_substring(to_prune, "("); - if (indy > 5) to_prune = llGetSubString(to_prune, 0, indy - 1); - // crop the name on general length issues too. - to_prune = llGetSubString(to_prune, 0, MAX_DEST_NAME); - return to_prune; -} - -// called when dataserver brings us landmark info. -process_landmark_data(key id, string data) -{ - if (id != lm_data_req) return; // not for us. - lm_data_req = NULL_KEY; // drop our prior key. - if (data != EOF) { - string dest = vector_chop((vector)data); - config_to_blast += [ prune_name(llGetInventoryName(INVENTORY_LANDMARK, current_lm)), dest ]; - send_config_blast(TRUE); - current_lm++; - if (current_lm < llGetInventoryNumber(INVENTORY_LANDMARK)) { - lm_data_req = llRequestInventoryData( - llGetInventoryName(INVENTORY_LANDMARK, current_lm)); - } - } - // check our sentinel data key about being done. - if (lm_data_req == NULL_KEY) { - // looks like we got our destinations and are totally done now. - llSetTimerEvent(0.001); // trigger state change very shortly. - } -} - -////////////// - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -/////////////// - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -// returns text for a floating point number, but includes only -// three digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 1000.0) / 1000); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -////////////// - -// default state scrounges for information in a notecard and looks for landmarks in -// inventory to add as destinations. -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - link_message(integer which, integer num, string msg, key id) - { - if (num == NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) { - process_notecard_lines(msg, id); - } else if (num == JAUNT_CONFIGURATION_HUFFWARE_ID) { - handle_config_request(msg, id); - } - } - - dataserver(key id, string data) { process_landmark_data(id, data); } - - timer() { - // this is the only place we publish a result. - completed_configuration(); - llSetTimerEvent(0.0); // stop the timer again, until next request. - } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.txt b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.txt new file mode 100755 index 00000000..c09890c8 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_config_funcs_v2.9.txt @@ -0,0 +1,494 @@ + +// huffware script: jaunt config funcs, by fred huffhines, released under GPL license. +// +// this is the part of the jaunt wik rez ensemble that deals with configuration. +// it reads the configuration from notecards and passes it to the main script. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +integer DEBUGGING = FALSE; + // make this true for noisy runtime diagnostics. + +// defines the jaunt config funcs messaging API. +////////////// +// do not redefine these constants. +integer JAUNT_CONFIGURATION_HUFFWARE_ID = 10022; + // the unique id within the huffware system for this script's commands. + // it's used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available from the jaunt config library: +string LOAD_ALL_CONFIGURATIONS = "#rdcfg#"; + // this starts the process of loading jaunt destinations from the notecards and + // landmarks that we find in the object. the parms are: private channel + // and conveyance mode. +string JAUNT_CFG_DATA_EVENT = "#yodata#"; + // this event is generated from this script back to the caller. when we have some + // landmark data or configuration information, it's passed back in chunks. the + // deluge of pieces will continue until the JAUNT_CFG_EOF event is passed. the + // parameters include packed destination name and vector pairs (which form 2 elements + // in the list) and packed config variable definitions (where config items start + // with a colon, and the definition is only one element in the list). +string JAUNT_CFG_EOF = "#done#"; + // sent after all valid configuration items that we could find were processed. there + // are no parameters for this command. +// +////////////// + +// important constants used internally... these should generally not be changed. + +// indicates a reconnaissance command when found as a prefix on chat text +// on our official recon channel. +string RECON_TEXT = "#rcn"; +string READY_TEXT = "-y"; // lets us know that a jaunter is ready to be filled. +string RETURN_WORD = "-b"; // used to signal a returning recong jaunter. + +integer MAXIMUM_BLAST_SIZE = 6; // maximum number of config items per blurt. + +integer TIMEOUT_FOR_CONFIGURATION_PROCESS = 42; + // how long the notecard and lm reading processes are allowed to last. + +integer TWO_WAY_TRIP = 1; +integer AUTOREZ_JAUNTER = 2; +integer ONE_WAY_TRIP = 3; +integer RECONNAISSANCE_TRIP = 4; + +string DB_SEPARATOR = "``"; // separating items in lists. + +////////////// + +// global variables. + +integer unused_private_chat_channel; // where sub-jaunters communicate with root. + +integer conveyance_mode; //// = TWO_WAY_TRIP; + // default is a standard two way trip, there and back again. note that the object + // will fail to return if any lands in between are blocking object entry. those + // situations should use an auto-rez jaunter, which is specified by prefixing the + // target vectors with AR. + +////integer current_target_index; // the location in the list that we would currently jaunt to. + +list config_to_blast; // what we will send to our client. + +// notecard variables... +integer response_code; // set to uniquely identify the notecard read in progress. +string leftover_parms; // items leftover during config. + +// lm variables... +integer current_lm; +key lm_data_req; // this is the current landmark being served as data. + +////////////// + +// requires noteworthy library v5.4 or higher. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +//string BUSY_READING_INDICATOR = "busy_already"; + // this return value indicates that the script is already in use by some other script. + // the calling script should try again later. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the only parameter. the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // an embedded list that was read from the notecard. this necessarily limits the + // size of the notecards that we can read and return. +// +////////////// + +// begins getting configuration items from notecards and landmarks. +start_reading_configuration() +{ + llSetTimerEvent(0.0); // cancel any existing timers. + + string JAUNT_SIGNATURE = "#jaunt"; // the expected first line of our notecards. + + // a normal startup where we read notecards and stuff... + // see if we can load a notecard for destinations. + response_code = random_channel(); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + wrap_parameters([JAUNT_SIGNATURE, response_code])); + // we pick a private channel that fits in between our rez parm ranges. + // during a normal trip, we will make sure the notecard reading doesn't stall. + // the recon and one way jaunters don't need this; they're temporary. + // we allow this number of seconds before notecard reader is awol. + + llSetTimerEvent(TIMEOUT_FOR_CONFIGURATION_PROCESS); +} + +// main API implementor; answers requests to start reading config. +handle_config_request(string msg, string id) +{ + if (msg != LOAD_ALL_CONFIGURATIONS) return; // not for us. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + // set our variables from the parameters we were given. + unused_private_chat_channel = llList2Integer(parms, 0); + conveyance_mode = llList2Integer(parms, 1); + if ( (conveyance_mode != RECONNAISSANCE_TRIP) && (conveyance_mode != ONE_WAY_TRIP) ) { + // setting up a root jaunter. + start_reading_configuration(); + } +} + +// sends out our current configuration perhaps. if the check_length flag is true, +// then we'll only send if the list is already too fat. if the flag is false, then +// we always just send our config (if it's non-empty). +send_config_blast(integer check_length) +{ + if (!check_length || (llGetListLength(config_to_blast) > MAXIMUM_BLAST_SIZE) ) { + if (llGetListLength(config_to_blast) > 0) { + llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE, + JAUNT_CFG_DATA_EVENT, wrap_parameters(config_to_blast)); + config_to_blast = []; + } + } +} + +// deals with responses from the notecard library. +process_notecard_lines(string msg, string id) +{ + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (llList2Integer(parms, 1) != response_code) return; // this isn't for us. + + integer totally_done = TRUE; // if left set to true, then notecard is done being consumed. + + string note_name = llList2String(parms, 0); + if (DEBUGGING) log_it("note name: " + note_name); + parms = llDeleteSubList(parms, 0, 1); + + // add in the leftovers. + if (leftover_parms != "") { + if (DEBUGGING) log_it("added leftover: " + leftover_parms); + parms = [ leftover_parms ] + parms; + leftover_parms = ""; + } + + if (note_name == NOTECARD_READ_CONTINUATION) { + totally_done = FALSE; + if (DEBUGGING) log_it("not totally done reading yet."); + } + if (note_name != BAD_NOTECARD_INDICATOR) { + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy++) { + if (DEBUGGING) log_it("index: " + (string)indy); + string targ = llList2String(parms, indy); + if (DEBUGGING) log_it("targ: " + targ); + if (is_prefix(targ, ":")) { + if (DEBUGGING) log_it("targ is special command. just adding."); + config_to_blast += [ targ ]; + } else { + if (indy < llGetListLength(parms) - 1) { + if (DEBUGGING) log_it("decided we can steal two items."); + // this looks like a normal pair of destination vector and name. + string the_name = prune_name(llList2String(parms, indy + 1)); + config_to_blast += [ the_name, targ ]; + if (DEBUGGING) log_it("stole: " + the_name + " --> " + targ); + indy++; // skip an extra index since we stole two. + } else { + // save this tidbit for next config cycle. + if (DEBUGGING) log_it("saving tidbit for next round: " + targ); + leftover_parms = targ; + } + } + send_config_blast(TRUE); + } + } + + if (totally_done) { + // now that we've gotten our notecard read in, check the landmarks in + // the inventory to see if they're useful. + current_lm = 0; + if (current_lm < llGetInventoryNumber(INVENTORY_LANDMARK)) { + lm_data_req = llRequestInventoryData( + llGetInventoryName(INVENTORY_LANDMARK, current_lm)); + } else { + // kick out of this state and signal completion. + llSetTimerEvent(0.001); + } + } +} + +// report our getting configured properly. +completed_configuration() +{ + send_config_blast(FALSE); // get last of config bits out to the client. + llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE, + JAUNT_CFG_EOF, NULL_KEY); +} + +// fixes a location name so we don't get crushed on memory usage. +string prune_name(string to_prune) +{ + integer MAX_DEST_NAME = 28; // the longest name that we store. + + // see if we can strip off the locational info. comma is a common separator for stuff that's + // not part of the lm name. + integer indy = find_substring(to_prune, ","); + if (indy > 5) to_prune = llGetSubString(to_prune, 0, indy - 1); + // parentheses are another common way of adding extra stuff we don't need for the name. + indy = find_substring(to_prune, "("); + if (indy > 5) to_prune = llGetSubString(to_prune, 0, indy - 1); + // crop the name on general length issues too. + to_prune = llGetSubString(to_prune, 0, MAX_DEST_NAME); + return to_prune; +} + +// called when dataserver brings us landmark info. +process_landmark_data(key id, string data) +{ + if (id != lm_data_req) return; // not for us. + lm_data_req = NULL_KEY; // drop our prior key. + if (data != EOF) { + string dest = vector_chop((vector)data); + config_to_blast += [ prune_name(llGetInventoryName(INVENTORY_LANDMARK, current_lm)), dest ]; + send_config_blast(TRUE); + current_lm++; + if (current_lm < llGetInventoryNumber(INVENTORY_LANDMARK)) { + lm_data_req = llRequestInventoryData( + llGetInventoryName(INVENTORY_LANDMARK, current_lm)); + } + } + // check our sentinel data key about being done. + if (lm_data_req == NULL_KEY) { + // looks like we got our destinations and are totally done now. + llSetTimerEvent(0.001); // trigger state change very shortly. + } +} + +////////////// + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +/////////////// + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +// returns text for a floating point number, but includes only +// three digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 1000.0) / 1000); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 1000.0) - mant * 1000) / 1000.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +////////////// + +// default state scrounges for information in a notecard and looks for landmarks in +// inventory to add as destinations. +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + link_message(integer which, integer num, string msg, key id) + { + if (num == NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) { + process_notecard_lines(msg, id); + } else if (num == JAUNT_CONFIGURATION_HUFFWARE_ID) { + handle_config_request(msg, id); + } + } + + dataserver(key id, string data) { process_landmark_data(id, data); } + + timer() { + // this is the only place we publish a result. + completed_configuration(); + llSetTimerEvent(0.0); // stop the timer again, until next request. + } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.lsl b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.lsl deleted file mode 100755 index f7f7481c..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.lsl +++ /dev/null @@ -1,1278 +0,0 @@ - -// huffware script: jaunt rezolator, by fred huffhines. -// -// this script supports the jaunt wik rez script by dealing with the rezzed objects. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants that can be changed to good effect. - -integer DEBUGGING = FALSE; // set this to true for noisier run times. - -// important constants used internally... these should not be changed willy nilly. - -// begin jaunt base API: - -// the following constants define how the script should behave (i.e., its conveyance mode). -// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere -// and then takes the same pathway back, but in reverse order. -// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to -// the root telehub. that object is loaded with the destination notecard and this script. -// the rezzed object can then be used for the next few minutes to jaunt to the selected -// destination. the temporary object will use the ONE_WAY_TRIP mode. -// ONE_WAY_TRIP: the object containing this script will take the user to a particular -// destination, but the object does not survive the trip. it self-destructs after -// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER -// mode and should generally never be used on its own. -// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a -// destination. -integer TWO_WAY_TRIP = 1; -integer AUTOREZ_JAUNTER = 2; -integer ONE_WAY_TRIP = 3; -integer RECONNAISSANCE_TRIP = 4; - -// indicates a reconnaissance command when found as a prefix on chat text -// on our official recon channel. -string CHILD_CHAT_TEXT = "#rcn"; -string READY_TEXT = "-y"; // lets us know that a jaunter is ready to be filled. -string RETURN_WORD = "-b"; // used to signal a returning recong jaunter. - -// values used to represent different stages of verification. -integer VERIFY_UNTESTED = -3; // don't know destinations tate yet. -integer VERIFY_SAFE = -4; // the destination last tested safe. -integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. -integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. - -integer ONE_WAY_TRICKY_PARM = -100000; - // used to signal to the one way jaunter that it's taking a single pathway. -integer RECONNAISSANCE_TRICKY_PARM = -200000; - // on_rez parm indicates that this will be a recon trip to check out a path. -integer MAXIMUM_PRIV_CHAN = 90000; - // the largest amount we will ever subtract from the tricky parms in order to - // tell the sub-jaunter which channel to listen on. - -string VECTOR_SEPARATOR = "|"; - // how we separate components of vectors from each other. -string DB_SEPARATOR = "``"; // separating items in lists. - -// end of jaunt base API. - -integer REZ_KID_FIELDS_NEEDED = 6; // the rez kid API method needs this many parms. - -integer MAXIMUM_RECON_ATTEMPTS = 7; - // maximum tries to find a path for the hard cases (after first simple jaunt fails). - -float TIMER_PERIOD = 1.0; // we run a pretty slow timer to check on destinations. - -integer MAXIMUM_SNOOZES = 20; // how long we let a pending action go before declaring it failed. - -string OUR_COW_TAG = "l_jrzltr_dc"; - // a hopefully unique id for this script to talk to the data cow with. - -// the actions that can be held in the action queue. -integer AQ_ONEWAY_JAUNTER_VOYAGE = 40; // information will be used for one-way jaunter. -integer AQ_PREP_RECON_JAUNTER = 41; // info for the reconnaissance jaunter to go check out. -integer AQ_CHECK_HARD_CASE = 42; // working on hard cases to get to destination somehow. -integer AQ_ACQUIRE_BASE_PATH = 43; // we are grabbing a random path that we think is healthy. - -string QUADRANT_TAG_NAME = "q:"; // a piece of text we put in front of generated destinations. - -integer MAXIMUM_SAFE_LOCATIONS = 28; // we'll track this many extra locations. -float MINIMUM_DISTANCE_FOR_EXTRAS = 10.0; // how far a new locale must be to add. - -integer MAX_CHAT_REPEAT = 3; // give instructions N times in case things are slow. -float SLEEPY_TIME = 0.02; // how long to snooze between chats. - -////////////// - -// global variables. - -list global_verifications; // we gradually acquire knowledge of the health of the destinations. -string global_object_name; // the object to rez from inventory. -string global_destination_name; // the name of the place where the jaunter should go. -vector global_rez_place; // starting location for the rezzed jaunter. -integer conveyance_mode; // how the rezzed jaunter should process its destination. - -integer private_id_from_listen; // set when we listen to our private channel. -integer private_chat_channel; // where sub-jaunters communicate with root. - -integer serving_root; // if this is true, it means we are serving a root jaunter. - -integer destinations_total; // how many destinations are known in total? we compute this. -integer destinations_real; // how many are user-configured destinations? - -integer snooze_counter; // how many times have we slept during a process? - -integer heard_from_root; // true if the root jaunter has told us (a child jaunter) where to go. - -// recon variables... -integer is_recon_pending; // are we awaiting a reconnaissance? -integer trying_hard_cases; // are we already working on the tough ones? -integer current_recon_index; // where is the recon jaunter testing. -integer recon_reattempts; // how many tries did we take? -integer done_reconnoiter; // is recon process finished? -integer succeeded_recon; // set to true if close enough. -integer good_destinations_counted; // a tally of how many destinations looked healthy. -integer ungenerated_good_destinations_counted; // counts only user selected good dests. -vector final_destination; // where the recon process is really headed. -integer partial_path_count; // the counter for partial path replies. -list safe_locales_seen; // locations that we have a safe route to, as reported by recons. - -// jaunt trip variables... -list full_journey; // the full pathway we expect to jaunt on. -integer last_verification; // the last state we heard. - -// root jaunter variables... -integer child_needs_setup; - // true when a child has been rezzed and still needs to be filled with the script. - -// the API for this library script to be used in other scripts. -////////////// -// do not redefine these constants. -integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; - // the unique id within the huffware system for this script's commands. - // it's used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available from the library: -string RESET_REZOLATOR = "#reset"; - // tells the script to stop any previous efforts to rez children. -string REZ_CHILD_NOW = "#rezkd#"; - // requests this script to create a new child object. this requires several - // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object - // to implement, 3) the chat channel to listen for and speak to new child on, - // 4) the destination name for where the child should go, 5) a count of the full - // set of known destinations, 6) the target where the jaunt should arrive at. -string REPORT_CHILD_REZZED = "#reziam"; - // requests that this class report to the root jaunter that a child has rezzed and - // is ready for service. there are no required parameters. -//hmmm: combine the above with the below! -string REZOLATOR_CHILD_SUPPORT = "#rzsup"; - // used by child jaunters to request that the rezolator handle things for them. - // the first parameter is the startup parameter handed to the control script. -string REZOLATOR_CHILD_RETURNED = "#rezdon"; - // used by the child jaunter to tell the rezolator that it has jumped to wherever it - // was supposed to and is ready to report to the parent, if needed. the first parameter - // required for the rezolator is whether the jump was successful (1) or not (0), and - // the second parameter should be the last safe position that the jaunter was at when - // it was possibly closest to the target. -////////////// -// events generated by the library: -string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; - // an event generated for a previous rez child request. this lets the caller know that - // the child has been created and told what to do. the single parameter is where the - // jaunter has been rezzed. -string REZOLATOR_EVENT_GOT_INSTRUCTIONS = "#rzsta"; - // the root jaunter has given a child instructions on where to go. this info includes - // the name of the destination, the pathway to get there, and the conveyance mode. -string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; - // an event generated when the recon process has concluded. this includes parms: - // number of good destinations. -// -////////////// - -// requires click action API... -////////////// -integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; - // a unique ID within the huffware system for this script. -// the API only supports the service number; there are no commands to pass in the "msg" -// parameter. the id does accept a parameter, which is the type of click action to begin -// using for this prim. -////////////// - -// requires data cow library... -////////////// -// do not redefine these constants. -integer DATA_COW_HUFFWARE_ID = 10017; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -//string RESET_LIST_COMMAND = "reset_L"; // flushes out the currently held list. -string ADD_ITEM_COMMAND = "add_I"; - // adds items to the list. this is a list of pairs of name/value, where the name is - // how the item will be looked up from the list, and the value is the contents to be stored. -//string REMOVE_ITEM_COMMAND = "rm_I"; - // accepts a list of names for items. all the mentioned ones will be removed from the list. -//string GET_ITEM_COMMAND = "get_I"; - // retrieves the item's contents for a given name. first parm is the name. if there - // are other parameters, then they are taken as other items to return also. - // the return data will be pairs of for each of the names in the request. -string TAGGED_GET_ITEM_COMMAND = "get_T"; - // like get item, except the first parameter is an identifier that the caller wants to - // use to tag this request. the other parameters are still taken as names. the response - // will contain the tag as the first item, then the pairs that were found. -////////////// - -// sets up the initial state, if this script has just started, or it -// cleans up the state, if the script was already running. -initialize_rezolator() -{ - if (DEBUGGING) log_it("start mem=" + (string)llGetFreeMemory()); - global_rez_place = llGetPos(); - heard_from_root = FALSE; // we don't know root from adam yet. -} - -// sets up the rezolator to be a child jaunter and report to a root jaunter. -provide_child_support(integer startup_parm) -{ - serving_root = FALSE; - // we are serving as a special purpose jaunter object. - // set our method of jaunting based on the secret signal. - if (-(startup_parm - ONE_WAY_TRICKY_PARM) < MAXIMUM_PRIV_CHAN) { - conveyance_mode = ONE_WAY_TRIP; - private_chat_channel = startup_parm - ONE_WAY_TRICKY_PARM; - if (DEBUGGING) log_it("one way child: private chat on " + private_chat_channel); - } else if (-(startup_parm - RECONNAISSANCE_TRICKY_PARM) < MAXIMUM_PRIV_CHAN) { - conveyance_mode = RECONNAISSANCE_TRIP; - private_chat_channel = startup_parm - RECONNAISSANCE_TRICKY_PARM; - if (DEBUGGING) log_it("recon child: private chat on " + private_chat_channel); - } - - if (private_id_from_listen) { - // toss old listening since we're working on a new deal now. - llListenRemove(private_id_from_listen); - } - // listen to chats on our special channel. - private_id_from_listen = llListen(private_chat_channel, "", NULL_KEY, ""); - if (DEBUGGING) log_it("listening for cmds on chan " + (string)private_chat_channel); -} - -// this handles the case where we need to send out another seeker drone. -// true is returned if this function thinks things are doing well. -integer advance_reconnaissance_position() -{ - if (!trying_hard_cases) { - list added_parms = []; - if (current_recon_index < 0) { - // this is a signalled condition. we have just started chowing through - // the destinations to look at them. - current_recon_index = 0; - } else { - // a normal move to the next slot now. - current_recon_index++; - } - if (DEBUGGING) - log_it("total dests are " + destinations_total - + " and we're at indy " + current_recon_index); - if (current_recon_index <= destinations_total - 1) { - // try jumping to the next place. - if (DEBUGGING) log_it("next normal test, index " + (string)current_recon_index); - push_action_record(AQ_PREP_RECON_JAUNTER, added_parms); - } else { - // we've gone off the edge of our list in normal mode. - // now check those that are marked as failures. - trying_hard_cases = TRUE; - if (DEBUGGING) log_it("started trying hard cases, back to index 0"); - // start over in processing the list. - current_recon_index = 0; - is_recon_pending = FALSE; - good_destinations_counted = 0; - ungenerated_good_destinations_counted = 0; - push_action_record(AQ_CHECK_HARD_CASE, added_parms); - } - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, "#" + (string)current_recon_index])); - return TRUE; - } - if ((current_recon_index < destinations_total) && trying_hard_cases) { - // if the conditions are very right or very wrong, move to next place. - if ( (last_verification == VERIFY_SAFE) || (last_verification == VERIFY_UNSAFE_DECIDED) - || (current_recon_index < 0) ) { - current_recon_index++; - } - if (DEBUGGING) log_it("next hard test at index " + (string)current_recon_index); - // make sure we're still in range. - if (current_recon_index < destinations_total) { - // we're running the hard cases now, so go to the next one of those. - list added_parms = []; - push_action_record(AQ_CHECK_HARD_CASE, added_parms); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, "#" + (string)current_recon_index])); - return TRUE; - } - } - - if (!done_reconnoiter) { - if (DEBUGGING) log_it("decided we're done with recon."); - // all have been checked. - done_reconnoiter = TRUE; - // let the root know how many were tasty healthy places. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, - REZOLATOR_EVENT_RECON_FINISHED, - (string)ungenerated_good_destinations_counted); - } - if (DEBUGGING) log_it("doing nothing else in advance."); - return FALSE; // not good. -} - -// considers the current state of affairs and schedules the next reasonable thing -// that needs to be done to move the rezzing process along. -take_the_next_appropriate_action() -{ - // see if the child setup process is still running. - if (child_needs_setup || is_recon_pending || (llGetListLength(action_queue) > 0) ) { - // we're still waiting on something. make sure it hasn't timed out. - if (!check_for_child_timeout()) return; // we still have time. - // saying this one failed, so we set it such that we are not waiting for kids - // or recons or the data cow right now. - snooze_counter = 0; - if (child_needs_setup) { - if (DEBUGGING) log_it("TNAP: child needs setup..."); - child_needs_setup = FALSE; - if (conveyance_mode == ONE_WAY_TRIP) { -//log_it("TNAP: telling root one way kid is hosed."); - // the startup of a child jaunter has failed. let the root think we're - // doing okay so it can get on with its life. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, - REZOLATOR_EVENT_REZZED_CHILD, (string)global_rez_place); - return; - } else { -//log_it("TNAP: recon fail for kid needs setup, fall through."); - } - } else if (is_recon_pending) { - // the current reconnaissance drone has crashed apparently. deal with it. - if (DEBUGGING) log_it("TNAP: setting recon pend to false"); - is_recon_pending = FALSE; - return; - } else if (llGetListLength(action_queue) > 0) { - // action_queue must be non-empty, or we wouldn't be here. - list action_rec = pop_action_record(); // what else can we do? - if (DEBUGGING) log_it("TNAP: time-out on action: " + (string)action_rec); - return; - } - // proceed to the next steps which are probably remedial. - } - - if (DEBUGGING) log_it("TNAP: nothing pending, move things along..."); - - // nothing is pending right now. - if (conveyance_mode == ONE_WAY_TRIP) { - // this means we are done, since the only thing we do is start the kid up. - llSetTimerEvent(0.0); - return; - } - - // if the recon advancement returns true, then we are all set for the next place. - if (advance_reconnaissance_position()) return; - - // if we got to here, then we need to do something about being past end of list... - - if (done_reconnoiter) { - // all done with that, so we don't need the timer anymore. - llSetTimerEvent(0.0); // stop coming here. - return; // don't need to do any more. - } - - if (trying_hard_cases) { - try_the_hard_cases(); - } - - if (DEBUGGING) log_it("fell completely through TNAP()"); -} - -// tries to crack the hard cases using added random jaunt destinations. -try_the_hard_cases() -{ - if (DEBUGGING) log_it("hardcase performing recon re-attempt, name=" + global_destination_name); - if (is_prefix(global_destination_name, QUADRANT_TAG_NAME)) { -//log_it("seeing that " + global_destination_name + " is a generated dest, ignoring."); - splice_destination_info(current_recon_index, "#" + (string)current_recon_index, - vector_chop(final_destination), VERIFY_UNSAFE_DECIDED); - advance_reconnaissance_position(); - return; - } - // count that as a failure, since we're not still on our first run through the list. - recon_reattempts++; - if (recon_reattempts > MAXIMUM_RECON_ATTEMPTS) { - // we have totally failed to find a workable pathway. we'll store the - // most simple form of the path back as the one to use. - log_it("total failure reaching " + (string)final_destination); - splice_destination_info(current_recon_index, "#" + (string)current_recon_index, - vector_chop(final_destination), VERIFY_UNSAFE_DECIDED); - recon_reattempts = 0; - advance_reconnaissance_position(); - return; - } - - // start the process of finding a good random path. - if (!load_random_safe_path()) { - // can't get there from anywhere else, so try from here. - log_it("could not find a good random path!"); - scramble_to_find_a_way([]); - } -} - -// called to start a jaunter in the appropriate mode. -rez_requested_child(string object_name, integer conv_mode, - integer chat_channel, string destination_name, integer all_dests_count, - string target_location) -{ - if (DEBUGGING) - log_it("rez req: " + object_name + " convey=" + (string)conveyance_mode + " chat=" + (string)chat_channel + " dest=" + destination_name + " fullcount=" + (string)all_dests_count + " targ=" + target_location); - - if (private_id_from_listen) { - // toss old listening since we're working on a new deal now. - llListenRemove(private_id_from_listen); - } - // listen to chats on our special channel. - private_id_from_listen = llListen(chat_channel, "", NULL_KEY, ""); - - // remember the info so we can tell our new child. - conveyance_mode = conv_mode; - global_destination_name = destination_name; - global_object_name = object_name; // the object to rez from inventory. - private_chat_channel = chat_channel; - full_journey = llParseString2List(target_location, [VECTOR_SEPARATOR], []); - destinations_total = all_dests_count; - global_verifications = []; // clear any old verifications. - integer indy; - for (indy = 0; indy < destinations_total; indy++) - global_verifications += [ VERIFY_UNTESTED ]; - - if (conveyance_mode == RECONNAISSANCE_TRIP) { - // we need to start reconnaissance mode. - current_recon_index = -1; // a signal that we haven't started. - snooze_counter = 0; - is_recon_pending = FALSE; - done_reconnoiter = FALSE; - -//turned off currently. doesn't seem to help much. -if (FALSE) { - // experimental: add the quadrants of the sim as destinations. if some of these - // are reachable, then they should help us out. - destinations_real = destinations_total; - integer x; - integer y; - for (x = 32; x <= 255; x += 64) { - for (y = 32; y <= 255; y += 64) { - vector calculated = ; - float height = llGround(calculated - llGetPos()); - calculated.z = height + 64; - add_destination(QUADRANT_TAG_NAME + (string)x + "," + (string)y, - (string)adjust_to_ground(, 64), VERIFY_UNTESTED); - } - } -} - - take_the_next_appropriate_action(); - } else { - // create the jaunter object for a one way trip. - rez_a_jaunter(object_name, ONE_WAY_TRICKY_PARM + chat_channel, conveyance_mode); - } - llSetTimerEvent(TIMER_PERIOD); -} - -// handles responses about our list coming back from the data cow. -answer_to_the_cow(string msg, string id, list parms) -{ - string tag = llList2String(parms, 0); - if (tag != OUR_COW_TAG) return; // was not for us. - parms = llDeleteSubList(parms, 0, 0); // trim out the tag. - list action_record = pop_action_record(); - integer actyo = extract_action_code(action_record); - // get the name out of the set first. - list split = llParseString2List(llList2String(parms, 1), [HUFFWARE_ITEM_SEPARATOR], []); - - if (actyo != AQ_ACQUIRE_BASE_PATH) { - // it's very important that when we're acquiring other targets' path components, - // we do not mistake that for our own state for the path we're trying to reach. - // thus we only record the answer for actions that are about our real target. - global_destination_name = llList2String(parms, 0); - last_verification = llList2Integer(split, 1); - full_journey = prechewed_destinations(llList2String(split, 0)); - if (DEBUGGING) - log_it("just heard verif=" + (string)last_verification + " for " + global_destination_name); - } - - if (actyo == AQ_ONEWAY_JAUNTER_VOYAGE) { -//log_it("one way, saying on chan " + (string)private_chat_channel + " -- " + global_destination_name + " fullj=" + (string)full_journey); - - child_needs_setup = FALSE; // count off the one we just set up. - - integer indy; // i told you N times. - for (indy = 0; indy < MAX_CHAT_REPEAT; indy++) { - llSay(private_chat_channel, CHILD_CHAT_TEXT - + global_destination_name - + DB_SEPARATOR - + llDumpList2String(full_journey, VECTOR_SEPARATOR)); - // pausing to let our words sink in. - llSleep(SLEEPY_TIME); - } - - // tell the root jaunter that this kid has been issued. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, - REZOLATOR_EVENT_REZZED_CHILD, (string)global_rez_place ); - } else if (actyo == AQ_PREP_RECON_JAUNTER) { - // we got info about a place to try. record the last verif state locally. - if (DEBUGGING) log_it("info re destination: verif = " + last_verification); - splice_just_verification(current_recon_index, last_verification); - if ( (last_verification == VERIFY_UNTESTED) - || (trying_hard_cases && (last_verification == VERIFY_UNSAFE_SO_FAR) ) ) { - // this one is not tested yet or had problems. try it now. -//log_it("testing unchecked locale."); - is_recon_pending = TRUE; - // if the destination is claiming it's untested, we fix that now untrue statement. - if (last_verification == VERIFY_UNTESTED) { - splice_destination_info(current_recon_index, "#" + (string)current_recon_index, - llDumpList2String(full_journey, VECTOR_SEPARATOR), VERIFY_UNSAFE_SO_FAR); - } - if (DEBUGGING) - log_it("rezzing jaunter for: name " + global_destination_name + " journ" + (string)full_journey); - rez_a_jaunter(global_object_name, - RECONNAISSANCE_TRICKY_PARM + private_chat_channel, RECONNAISSANCE_TRIP); - } else { - // this one doesn't need a recon. - is_recon_pending = FALSE; -//log_it("skipping recon for verif " + (string)last_verification); - advance_reconnaissance_position(); - } - } else if (actyo == AQ_CHECK_HARD_CASE) { - // we got an answer to our request for a new hard locale to try. - // remember the verification state locally. - splice_just_verification(current_recon_index, last_verification); - - if ( (last_verification == VERIFY_UNTESTED) || (last_verification == VERIFY_UNSAFE_SO_FAR) ) { - // this one is not tested yet or had problems. try it now. - if (DEBUGGING) - log_it("testing hard case locale at " + (string)current_recon_index - + " name=" + global_destination_name); - final_destination = (vector)llList2String(full_journey, -1); - try_the_hard_cases(); - } else { -//log_it("check hard case--already safe or decidedly unsafe, skipping."); - if (last_verification == VERIFY_SAFE) { - good_destinations_counted++; - if (!is_prefix(global_destination_name, QUADRANT_TAG_NAME)) { - ungenerated_good_destinations_counted++; - } - } - advance_reconnaissance_position(); - } - take_the_next_appropriate_action(); - } else if (actyo == AQ_ACQUIRE_BASE_PATH) { - // a response with a hopefully good destination arrived; base a path on that. - scramble_to_find_a_way(prechewed_destinations(llList2String(split, 0))); - } -} - -// looks at the location "look_here" and finds the ground height as the z component -// of the returned vector (where x and y are copied from "look_here"). if the -// "height_add_in" is non-zero, it is added to the z component to adjust the ground -// height by an offset. -vector adjust_to_ground(vector look_here, float height_add_in) -{ - float height = llGround(look_here - llGetPos()); - look_here.z = height + height_add_in; - return look_here; -} - -// tries to come up with a random path that can reach a difficult place. -scramble_to_find_a_way(list possible_helpful_path) -{ - // we were told this was a good pathway, so let's try it. - if (randomize_within_range(0.0, 1.0, FALSE) > 0.5) { - // if we feel like it, add some huge random vectors in. - integer indy; - integer how_many = (integer)randomize_within_range(1, 5, FALSE); -//magic constant above. - vector rando = llGetPos(); // start with current place. - for (indy = 0; indy < how_many; indy++) { - // try to add a random completely other place in the sim. - vector other_rando = adjust_to_ground(random_vector(0.0, 256.0, FALSE), 64); - rando.z = other_rando.z; - // by only changing one axis at a time for x and y, we kind of slide around. - // this is considered more beneficial than just jumping randomly. - if (randomize_within_range(0.0, 1.0, FALSE) > 0.5) { - // this 50% modulates the x. - rando.x = other_rando.x; - } else { - // this other 50% modulates the y. - rando.y = other_rando.y; - } -//log_it("scramble: wacky rando: " + vector_chop(rando)); - possible_helpful_path += [ vector_chop(rando) ]; - } - } - if (randomize_within_range(0.0, 1.0, FALSE) > 0.2) { - // maybe we also feel like adding a small amount to the final destination, - // trying for a hook shot, most of the time. -//log_it("scramble: addition relative to final destination."); - vector rando = adjust_to_ground(final_destination + random_vector(0.0, 8.0, TRUE), 64); -//magic constant above. - possible_helpful_path += [ vector_chop(rando) ]; - } - if ( (final_destination.z < 1000.0) && (randomize_within_range(0.0, 1.0, FALSE) > 0.05) ) { -//hmmm: is this redundant now? - // we very often add a vertical component so as to swoop down on the destination - // and hopefully avoid ground fault conditions. - possible_helpful_path += [ vector_chop() ]; -//magic constant above. - } - // now finally we add in the real place where we're going. - possible_helpful_path += [ vector_chop(final_destination) ]; - // prepare our state for the new attempt. - is_recon_pending = TRUE; - snooze_counter = 0; - full_journey = possible_helpful_path; -//log_it("scramble: final guess=" + (string)full_journey); - // rez for this nutty test path. - rez_a_jaunter(global_object_name, - RECONNAISSANCE_TRICKY_PARM + private_chat_channel, RECONNAISSANCE_TRIP); -} - -// this function returns TRUE if we are close enough to the "destination". -integer close_enough(vector destination) -{ - float PROXIMITY_REQUIRED = 0.1; - // how close we must be to the target location to call it done. - // matches current jaunting library proximity. - return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); -} - -// records a verification state locally so we can make decisions during testing. -splice_just_verification(integer index, integer verif_state) -{ - if ( (index < 0) || (index >= destinations_total) ) return; // can't do it. - global_verifications = chop_list(global_verifications, 0, index - 1) - + [ verif_state ] - + chop_list(global_verifications, index + 1, destinations_total - 1); -} - -// replaces an existing entry at the "index" if known (otherwise this should be negative) -// for the location named "dest_name" if known (otherwise should be a restatement of the -// numerical index with '#' in front). -splice_destination_info(integer index, string dest_name, string pathway, integer verif) -{ -//log_it("splicedest: " + (string)index + " name=" + dest_name + " verif=" + (string)verif + " path=" + pathway); - splice_just_verification(index, verif); - string new_entry = wrap_item_list([pathway, verif]); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, - wrap_parameters([dest_name, new_entry])); -} - -string verification_name(integer enumtype) -{ - if (enumtype == VERIFY_SAFE) return "ok"; - else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; - else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; - // catch-all, including untested. - return "?"; -} - -// returns true if the slackness counter awaiting things has elapsed. -integer check_for_child_timeout() -{ - if (snooze_counter++ > MAXIMUM_SNOOZES) { - // go back to the main state. we took too long. -// log_it("timed out!"); - llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. - return TRUE; - } - return FALSE; -} - -////////////// - -// action queue for postponed activities. the first field held in a list item here -// is an integer action code. the format of the remaining parameters is up to the -// caller, and they can be used as the final parameters for when the queued action -// gets handled. -list action_queue; - -// looks at the action code at the head of the queue without removing the action. -integer peek_action_code() -{ - list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - return extract_action_code(fields); -} - -// extracts the action code from a retrieved list. -integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } - -// removes the current head of the action queue and returns it. -list pop_action_record() -{ - list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - action_queue = llDeleteSubList(action_queue, 0, 0); - return top_action; -} - -// adds a new action to the end of the action queue. -push_action_record(integer action, list added_parms) -{ - snooze_counter = 0; // reset back for new action. - action_queue += [ wrap_parameters([action] + added_parms) ]; -} - -////////////// - -// processes link messages received from support libraries. -handle_link_message(integer which, integer num, string msg, string id) -{ - // maybe it's a piece of data from the data cow. - if (num == DATA_COW_HUFFWARE_ID + REPLY_DISTANCE) { - // unpack the parameters we were given. - list parms_x = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - answer_to_the_cow(msg, id, parms_x); - return; - } - - if (num != JAUNT_REZOLATOR_HUFFWARE_ID) return; // not interesting. - if (DEBUGGING) log_it("linkmsg: msg " + msg + " id " + id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == REZ_CHILD_NOW) { - serving_root = TRUE; - snooze_counter = 0; // reset counter. - if (llGetListLength(parms) < REZ_KID_FIELDS_NEEDED) { -// log_it("insufficient parameters for rezzing child."); - return; - } - rez_requested_child(llList2String(parms, 0), llList2Integer(parms, 1), - llList2Integer(parms, 2), llList2String(parms, 3), - llList2Integer(parms, 4), llList2String(parms, 5)); - } else if (msg == REPORT_CHILD_REZZED) { - report_to_root(); - } else if (msg == RESET_REZOLATOR) { - llResetScript(); - } else if (msg == REZOLATOR_CHILD_SUPPORT) { - provide_child_support(llList2Integer(parms, 0)); - } else if (msg == REZOLATOR_CHILD_RETURNED) { - if (conveyance_mode == RECONNAISSANCE_TRIP) { - // unpack the success value from jaunter's check. - integer succeeded_recon = llList2Integer(parms, 0); - // report on our success. - list report_loc = full_journey; - if (!succeeded_recon) { - // we did at least get to somewhere, even if not to target. - report_loc = llParseString2List(llList2String(parms, 1), - [VECTOR_SEPARATOR], []); - } - llWhisper(private_chat_channel, CHILD_CHAT_TEXT + RETURN_WORD - + (string)succeeded_recon + DB_SEPARATOR - + global_destination_name - + DB_SEPARATOR - + llDumpList2String(report_loc, VECTOR_SEPARATOR)); -//log_it("child reporting success=" + (string)succeeded_recon + " for " + global_destination_name + " via " + llDumpList2String(report_loc, VECTOR_SEPARATOR) ); - // shuffle off... -//log_it("now dying at posn " + (string)llGetPos()); - llDie(); // oh crud, we're toast. - } else { - // one way trip?? - if (!succeeded_recon) log_it("too far away; path okay?"); - } - } -} - -// makes our click action change to the type requested, and sends the request -// out to all our sub-prims also. -set_click_action(integer action) -{ - llSetClickAction(action); - // secret message to other prims to change click action. - llMessageLinked(LINK_SET, CHANGE_CLICK_ACTION_HUFFWARE_ID, "", (string)action); -} - -// tries to find a known safe locale that's close to the target. if there are any -// that are close, then we will not add this location. otherwise, we do add it, -// if the list is not already too large. -add_if_no_close_match(string pathway) -{ - // make sure there's enough room to bother checking. - if (llGetListLength(safe_locales_seen) >= MAXIMUM_SAFE_LOCATIONS) return; - list dests = llParseString2List(pathway, [VECTOR_SEPARATOR], []); - vector final_locn = (vector)llList2String(dests, -1); - // set the z component to zero for this comparison, which is only about x,y position. - // since we then add this trimmed vector, we don't need to worry about the z component - // for the items already in the list. - final_locn.z = 0; - integer i; - for (i = 0; i < llGetListLength(safe_locales_seen); i++) { - vector curr = (vector)llList2String(safe_locales_seen, i); - if (llVecDist(curr, final_locn) < MINIMUM_DISTANCE_FOR_EXTRAS) { -//log_it("dest too close: dist = " + (string)llVecDist(curr, final_locn)); - return; - } - } - if (DEBUGGING) log_it("dest far enough to add: " + pathway); - // no known locale is close, so we'll add this one. - safe_locales_seen += [ final_locn ]; - good_destinations_counted++; - add_destination(QUADRANT_TAG_NAME + "pt#" + (string)(partial_path_count++), - pathway, VERIFY_SAFE); -} - -// process what we hear in open chat and on our special channels. -// this function should always return FALSE unless it's been given enough info -// to enter a new state, in which case it should return true. -listen_to_voices(integer channel, string name, key id, string message) -{ - // check to see if the text is right. - if (DEBUGGING) - log_it("heard: " + message + " from " + name); - if (!is_prefix(message, CHILD_CHAT_TEXT)) return; // not right. - message = llDeleteSubString(message, 0, llStringLength(CHILD_CHAT_TEXT) - 1); - // maybe this is a startup request. - if (is_prefix(message, READY_TEXT) && serving_root) { - // yes, this is a request for a destination. we are going to fill the rezzed object - // now, so figure out what type of jaunter needs info. formerly fill_rezzed_object. - integer is_recon = (integer)llGetSubString(message, -1, -1); - if (done_reconnoiter && is_recon) return; // we already did all that. - if (is_recon) { - // a recon jaunter needs its instructions. - if (DEBUGGING) - log_it("telling recon kid: name " + global_destination_name + " journ=" + (string)full_journey); - is_recon_pending = TRUE; - integer indy; // i told you N times. - for (indy = 0; indy < MAX_CHAT_REPEAT; indy++) { - llSay(private_chat_channel, CHILD_CHAT_TEXT - + global_destination_name - + DB_SEPARATOR - + llDumpList2String(full_journey, VECTOR_SEPARATOR)); - // snooze to make sure we pause a little between mouthings. - llSleep(SLEEPY_TIME); - } - - snooze_counter = 0; // starting over. - child_needs_setup = FALSE; // count off the one we just set up. - } else { - if (DEBUGGING) - log_it("into code for one way jaunter"); - // simple one way jaunter needs fillin'. - list added_parms = []; - push_action_record(AQ_ONEWAY_JAUNTER_VOYAGE, added_parms); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, global_destination_name])); - } - return; - } - - if (DEBUGGING) log_it("into kid side of rezolator..."); - - if (!serving_root) { - if ( (conveyance_mode == RECONNAISSANCE_TRIP) || (conveyance_mode == ONE_WAY_TRIP) ) { - if (heard_from_root) return; // we already did this bit. - // this jaunter is destined for short-lived work, but now at least has a goal. - // we just pass along the parameters that were told to us from the root jaunter. - list parms = llParseString2List(message, [DB_SEPARATOR], []); - global_destination_name = llList2String(parms, 0); - full_journey = llParseString2List(llList2String(parms, 1), [VECTOR_SEPARATOR], []); - final_destination = (vector)llList2String(full_journey, -1); - parms += [ conveyance_mode ]; - - if (conveyance_mode == ONE_WAY_TRIP) { - // set the click action properly. - if (outside_of_sim(final_destination)) set_click_action(CLICK_ACTION_TOUCH); - else set_click_action(CLICK_ACTION_SIT); - } - - if (DEBUGGING) log_it("kid heard go to: " + global_destination_name + " via " + (string)full_journey); - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, - REZOLATOR_EVENT_GOT_INSTRUCTIONS, wrap_parameters(parms)); - // make sure we cancel the listening so we don't hear directions that aren't for us. - llListenRemove(private_id_from_listen); - heard_from_root = TRUE; - return; // only leave for recon. - } - } else { - // this jaunter's role should be a root jaunter, and we have a reply about a recon mission. - is_recon_pending = FALSE; // we got an acceptable answer. - list parms = llParseString2List(llDeleteSubString - (message, 0, llStringLength(RETURN_WORD) - 1), [DB_SEPARATOR], []); - integer success = llList2Integer(parms, 0); - string dest_name = llList2String(parms, 1); - string pathway = llList2String(parms, 2); -//log_it("|||| recon reply: " + dest_name + " good=" + (string)success + " path=" + pathway); - if (success) { - // record this as a safe pathway. - last_verification = VERIFY_SAFE; - good_destinations_counted++; - } else { - // a failure is being reported. record this as a bad pathway. - last_verification = VERIFY_UNSAFE_SO_FAR; - // however, the jaunter should have told us where it did get to. record that whole - // thing if it seems like a good distance from our other known good places. - if (DEBUGGING) log_it("failed path did get to: " + pathway); - add_if_no_close_match(pathway); - - } - // only save this info if we're not working on recons. - if (!trying_hard_cases || success) { - // fix name for tough destination's real one. - if (trying_hard_cases) { - dest_name = "#" + (string)current_recon_index; - } - splice_destination_info(current_recon_index, dest_name, - llDumpList2String(full_journey, - ///llList2List(full_journey, 1, -1), - VECTOR_SEPARATOR), - last_verification); - } - take_the_next_appropriate_action(); - } -} - -// processes a destination set to handle special cases, like for offset jaunting. -list prechewed_destinations(string dests) -{ - -//hmmm: document this! as in, we support the offset format. - - // look for our special start character for offsets. - if (is_prefix(dests, "o")) - // if this is an offset version, then chop whatever word they used starting with 'o' - // and compute the destination based on current position. - return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; - else - // normal jaunt to absolute coordinates. - return llParseString2List(dests, [VECTOR_SEPARATOR], []); -} - -// creates a jaunter object given which inventory item and the startup parm. -rez_a_jaunter(string object_name, integer rez_parm, integer conveyance_mode) -{ - // the minimum and maximum distances for placing the auto-rezzed jaunter object. - integer MIN_REZ_DISTANCE = 1; - integer MAX_REZ_DISTANCE = 3; - vector RECON_ROTATION = <270.0, 0.0, 0.0>; - // what angle we use when planting the recon jaunter. - // this is tightly coupled to our particular object. - vector point_at_jaunter; - if (conveyance_mode == RECONNAISSANCE_TRIP) { - // we just use our specified rotation. - point_at_jaunter = RECON_ROTATION * DEG_TO_RAD; - // start at where the jaunter will be when it tries the same path. - global_rez_place = llGetPos(); - } else { - // we randomize the location to avoid people having the objects - // in a big pile on top of each other. - global_rez_place = llGetPos() - + ; // pop it up a bit. - // aim the temporary ride at the root jaunter. - vector aim_back = llGetPos() - global_rez_place; - float z_rot = llAtan2(aim_back.y, aim_back.x); - // calculate the vector for rotation given the z rotation. - point_at_jaunter = <0.0, 0.0, z_rot>; - } - llRezObject(object_name, global_rez_place, - ZERO_VECTOR, llEuler2Rot(point_at_jaunter), rez_parm); - if (conveyance_mode != RECONNAISSANCE_TRIP) { - // this model only jaunts to where it gave out the object. that - // should hopefully always work. but at least if it can't get back, - // it's really close by. - full_journey = [ vector_chop(llGetPos()), vector_chop(global_rez_place) ]; - } - child_needs_setup = TRUE; // we aren't ready to go even if jaunt is done. - snooze_counter = 0; // amnesty on the timer. -} - -// finds a pathway that's already in our list and that we think is safe. -integer load_random_safe_path() -{ - integer indy; - integer goodunz = good_destinations_counted; - - // now that we know how many are safe, we can pick a good destination. - integer randola = llRound(randomize_within_range(0, goodunz - 1, FALSE)); - integer safe_indy = -1; // tracks which safe item we're at. - for (indy = 0; indy < llGetListLength(global_verifications); indy++) { - // scoot across the list to find the Nth safe one. - if (llList2Integer(global_verifications, indy) == VERIFY_SAFE) { - if (safe_indy == randola) { -//log_it("like path at " + (string)safe_indy); - // we're at the Nth safe item, so this is our random choice. - list added_parms = []; - push_action_record(AQ_ACQUIRE_BASE_PATH, added_parms); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, "#" + (string)safe_indy])); - return TRUE; - } - // increment to the next position, since we've seen this one. - safe_indy++; - } - } -//log_it("found no good path to use"); - return FALSE; -} - -// processes the timer events during an ongoing rezzing process. -handle_timer() -{ - // this is the root's timer process, which is implemented in great detail - // in the function below. - if (serving_root) take_the_next_appropriate_action(); -} - -// file a report with the root jaunter that the child has been created and is -// ready for service. -report_to_root() -{ - // tell the root jaunter know that we're ready to be packed for our trip. - llSay(private_chat_channel, CHILD_CHAT_TEXT + READY_TEXT - + (string)(conveyance_mode == RECONNAISSANCE_TRIP)); -} - -// plops a new destination on the end of the lists. -add_destination(string name, string path, integer verif) -{ -//log_it("adding " + name + " with path " + path + " and verif=" + (string)verif); - global_verifications += [ verif ]; - // send our new information to the data cow. we store the information encoded as - // two separated items, where the first element is the destination and the second - // is the verification state. - string new_entry = wrap_item_list([path, verif]); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, - wrap_parameters([name, new_entry])); - destinations_total++; // we just added another destination. -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -// returns text for a floating point number, but includes only -// two digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 100.0) / 100); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); initialize_rezolator(); } - - on_rez(integer startup) { llResetScript(); } - - state_exit() { llSetTimerEvent(0.0); } - - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - listen(integer channel, string name, key id, string message) - { listen_to_voices(channel, name, id, message); } - - timer() { handle_timer(); } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.txt b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.txt new file mode 100755 index 00000000..f7f7481c --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_rezolator_v22.3.txt @@ -0,0 +1,1278 @@ + +// huffware script: jaunt rezolator, by fred huffhines. +// +// this script supports the jaunt wik rez script by dealing with the rezzed objects. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants that can be changed to good effect. + +integer DEBUGGING = FALSE; // set this to true for noisier run times. + +// important constants used internally... these should not be changed willy nilly. + +// begin jaunt base API: + +// the following constants define how the script should behave (i.e., its conveyance mode). +// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere +// and then takes the same pathway back, but in reverse order. +// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to +// the root telehub. that object is loaded with the destination notecard and this script. +// the rezzed object can then be used for the next few minutes to jaunt to the selected +// destination. the temporary object will use the ONE_WAY_TRIP mode. +// ONE_WAY_TRIP: the object containing this script will take the user to a particular +// destination, but the object does not survive the trip. it self-destructs after +// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER +// mode and should generally never be used on its own. +// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a +// destination. +integer TWO_WAY_TRIP = 1; +integer AUTOREZ_JAUNTER = 2; +integer ONE_WAY_TRIP = 3; +integer RECONNAISSANCE_TRIP = 4; + +// indicates a reconnaissance command when found as a prefix on chat text +// on our official recon channel. +string CHILD_CHAT_TEXT = "#rcn"; +string READY_TEXT = "-y"; // lets us know that a jaunter is ready to be filled. +string RETURN_WORD = "-b"; // used to signal a returning recong jaunter. + +// values used to represent different stages of verification. +integer VERIFY_UNTESTED = -3; // don't know destinations tate yet. +integer VERIFY_SAFE = -4; // the destination last tested safe. +integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. +integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. + +integer ONE_WAY_TRICKY_PARM = -100000; + // used to signal to the one way jaunter that it's taking a single pathway. +integer RECONNAISSANCE_TRICKY_PARM = -200000; + // on_rez parm indicates that this will be a recon trip to check out a path. +integer MAXIMUM_PRIV_CHAN = 90000; + // the largest amount we will ever subtract from the tricky parms in order to + // tell the sub-jaunter which channel to listen on. + +string VECTOR_SEPARATOR = "|"; + // how we separate components of vectors from each other. +string DB_SEPARATOR = "``"; // separating items in lists. + +// end of jaunt base API. + +integer REZ_KID_FIELDS_NEEDED = 6; // the rez kid API method needs this many parms. + +integer MAXIMUM_RECON_ATTEMPTS = 7; + // maximum tries to find a path for the hard cases (after first simple jaunt fails). + +float TIMER_PERIOD = 1.0; // we run a pretty slow timer to check on destinations. + +integer MAXIMUM_SNOOZES = 20; // how long we let a pending action go before declaring it failed. + +string OUR_COW_TAG = "l_jrzltr_dc"; + // a hopefully unique id for this script to talk to the data cow with. + +// the actions that can be held in the action queue. +integer AQ_ONEWAY_JAUNTER_VOYAGE = 40; // information will be used for one-way jaunter. +integer AQ_PREP_RECON_JAUNTER = 41; // info for the reconnaissance jaunter to go check out. +integer AQ_CHECK_HARD_CASE = 42; // working on hard cases to get to destination somehow. +integer AQ_ACQUIRE_BASE_PATH = 43; // we are grabbing a random path that we think is healthy. + +string QUADRANT_TAG_NAME = "q:"; // a piece of text we put in front of generated destinations. + +integer MAXIMUM_SAFE_LOCATIONS = 28; // we'll track this many extra locations. +float MINIMUM_DISTANCE_FOR_EXTRAS = 10.0; // how far a new locale must be to add. + +integer MAX_CHAT_REPEAT = 3; // give instructions N times in case things are slow. +float SLEEPY_TIME = 0.02; // how long to snooze between chats. + +////////////// + +// global variables. + +list global_verifications; // we gradually acquire knowledge of the health of the destinations. +string global_object_name; // the object to rez from inventory. +string global_destination_name; // the name of the place where the jaunter should go. +vector global_rez_place; // starting location for the rezzed jaunter. +integer conveyance_mode; // how the rezzed jaunter should process its destination. + +integer private_id_from_listen; // set when we listen to our private channel. +integer private_chat_channel; // where sub-jaunters communicate with root. + +integer serving_root; // if this is true, it means we are serving a root jaunter. + +integer destinations_total; // how many destinations are known in total? we compute this. +integer destinations_real; // how many are user-configured destinations? + +integer snooze_counter; // how many times have we slept during a process? + +integer heard_from_root; // true if the root jaunter has told us (a child jaunter) where to go. + +// recon variables... +integer is_recon_pending; // are we awaiting a reconnaissance? +integer trying_hard_cases; // are we already working on the tough ones? +integer current_recon_index; // where is the recon jaunter testing. +integer recon_reattempts; // how many tries did we take? +integer done_reconnoiter; // is recon process finished? +integer succeeded_recon; // set to true if close enough. +integer good_destinations_counted; // a tally of how many destinations looked healthy. +integer ungenerated_good_destinations_counted; // counts only user selected good dests. +vector final_destination; // where the recon process is really headed. +integer partial_path_count; // the counter for partial path replies. +list safe_locales_seen; // locations that we have a safe route to, as reported by recons. + +// jaunt trip variables... +list full_journey; // the full pathway we expect to jaunt on. +integer last_verification; // the last state we heard. + +// root jaunter variables... +integer child_needs_setup; + // true when a child has been rezzed and still needs to be filled with the script. + +// the API for this library script to be used in other scripts. +////////////// +// do not redefine these constants. +integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; + // the unique id within the huffware system for this script's commands. + // it's used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available from the library: +string RESET_REZOLATOR = "#reset"; + // tells the script to stop any previous efforts to rez children. +string REZ_CHILD_NOW = "#rezkd#"; + // requests this script to create a new child object. this requires several + // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object + // to implement, 3) the chat channel to listen for and speak to new child on, + // 4) the destination name for where the child should go, 5) a count of the full + // set of known destinations, 6) the target where the jaunt should arrive at. +string REPORT_CHILD_REZZED = "#reziam"; + // requests that this class report to the root jaunter that a child has rezzed and + // is ready for service. there are no required parameters. +//hmmm: combine the above with the below! +string REZOLATOR_CHILD_SUPPORT = "#rzsup"; + // used by child jaunters to request that the rezolator handle things for them. + // the first parameter is the startup parameter handed to the control script. +string REZOLATOR_CHILD_RETURNED = "#rezdon"; + // used by the child jaunter to tell the rezolator that it has jumped to wherever it + // was supposed to and is ready to report to the parent, if needed. the first parameter + // required for the rezolator is whether the jump was successful (1) or not (0), and + // the second parameter should be the last safe position that the jaunter was at when + // it was possibly closest to the target. +////////////// +// events generated by the library: +string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; + // an event generated for a previous rez child request. this lets the caller know that + // the child has been created and told what to do. the single parameter is where the + // jaunter has been rezzed. +string REZOLATOR_EVENT_GOT_INSTRUCTIONS = "#rzsta"; + // the root jaunter has given a child instructions on where to go. this info includes + // the name of the destination, the pathway to get there, and the conveyance mode. +string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; + // an event generated when the recon process has concluded. this includes parms: + // number of good destinations. +// +////////////// + +// requires click action API... +////////////// +integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; + // a unique ID within the huffware system for this script. +// the API only supports the service number; there are no commands to pass in the "msg" +// parameter. the id does accept a parameter, which is the type of click action to begin +// using for this prim. +////////////// + +// requires data cow library... +////////////// +// do not redefine these constants. +integer DATA_COW_HUFFWARE_ID = 10017; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +//string RESET_LIST_COMMAND = "reset_L"; // flushes out the currently held list. +string ADD_ITEM_COMMAND = "add_I"; + // adds items to the list. this is a list of pairs of name/value, where the name is + // how the item will be looked up from the list, and the value is the contents to be stored. +//string REMOVE_ITEM_COMMAND = "rm_I"; + // accepts a list of names for items. all the mentioned ones will be removed from the list. +//string GET_ITEM_COMMAND = "get_I"; + // retrieves the item's contents for a given name. first parm is the name. if there + // are other parameters, then they are taken as other items to return also. + // the return data will be pairs of for each of the names in the request. +string TAGGED_GET_ITEM_COMMAND = "get_T"; + // like get item, except the first parameter is an identifier that the caller wants to + // use to tag this request. the other parameters are still taken as names. the response + // will contain the tag as the first item, then the pairs that were found. +////////////// + +// sets up the initial state, if this script has just started, or it +// cleans up the state, if the script was already running. +initialize_rezolator() +{ + if (DEBUGGING) log_it("start mem=" + (string)llGetFreeMemory()); + global_rez_place = llGetPos(); + heard_from_root = FALSE; // we don't know root from adam yet. +} + +// sets up the rezolator to be a child jaunter and report to a root jaunter. +provide_child_support(integer startup_parm) +{ + serving_root = FALSE; + // we are serving as a special purpose jaunter object. + // set our method of jaunting based on the secret signal. + if (-(startup_parm - ONE_WAY_TRICKY_PARM) < MAXIMUM_PRIV_CHAN) { + conveyance_mode = ONE_WAY_TRIP; + private_chat_channel = startup_parm - ONE_WAY_TRICKY_PARM; + if (DEBUGGING) log_it("one way child: private chat on " + private_chat_channel); + } else if (-(startup_parm - RECONNAISSANCE_TRICKY_PARM) < MAXIMUM_PRIV_CHAN) { + conveyance_mode = RECONNAISSANCE_TRIP; + private_chat_channel = startup_parm - RECONNAISSANCE_TRICKY_PARM; + if (DEBUGGING) log_it("recon child: private chat on " + private_chat_channel); + } + + if (private_id_from_listen) { + // toss old listening since we're working on a new deal now. + llListenRemove(private_id_from_listen); + } + // listen to chats on our special channel. + private_id_from_listen = llListen(private_chat_channel, "", NULL_KEY, ""); + if (DEBUGGING) log_it("listening for cmds on chan " + (string)private_chat_channel); +} + +// this handles the case where we need to send out another seeker drone. +// true is returned if this function thinks things are doing well. +integer advance_reconnaissance_position() +{ + if (!trying_hard_cases) { + list added_parms = []; + if (current_recon_index < 0) { + // this is a signalled condition. we have just started chowing through + // the destinations to look at them. + current_recon_index = 0; + } else { + // a normal move to the next slot now. + current_recon_index++; + } + if (DEBUGGING) + log_it("total dests are " + destinations_total + + " and we're at indy " + current_recon_index); + if (current_recon_index <= destinations_total - 1) { + // try jumping to the next place. + if (DEBUGGING) log_it("next normal test, index " + (string)current_recon_index); + push_action_record(AQ_PREP_RECON_JAUNTER, added_parms); + } else { + // we've gone off the edge of our list in normal mode. + // now check those that are marked as failures. + trying_hard_cases = TRUE; + if (DEBUGGING) log_it("started trying hard cases, back to index 0"); + // start over in processing the list. + current_recon_index = 0; + is_recon_pending = FALSE; + good_destinations_counted = 0; + ungenerated_good_destinations_counted = 0; + push_action_record(AQ_CHECK_HARD_CASE, added_parms); + } + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, "#" + (string)current_recon_index])); + return TRUE; + } + if ((current_recon_index < destinations_total) && trying_hard_cases) { + // if the conditions are very right or very wrong, move to next place. + if ( (last_verification == VERIFY_SAFE) || (last_verification == VERIFY_UNSAFE_DECIDED) + || (current_recon_index < 0) ) { + current_recon_index++; + } + if (DEBUGGING) log_it("next hard test at index " + (string)current_recon_index); + // make sure we're still in range. + if (current_recon_index < destinations_total) { + // we're running the hard cases now, so go to the next one of those. + list added_parms = []; + push_action_record(AQ_CHECK_HARD_CASE, added_parms); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, "#" + (string)current_recon_index])); + return TRUE; + } + } + + if (!done_reconnoiter) { + if (DEBUGGING) log_it("decided we're done with recon."); + // all have been checked. + done_reconnoiter = TRUE; + // let the root know how many were tasty healthy places. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, + REZOLATOR_EVENT_RECON_FINISHED, + (string)ungenerated_good_destinations_counted); + } + if (DEBUGGING) log_it("doing nothing else in advance."); + return FALSE; // not good. +} + +// considers the current state of affairs and schedules the next reasonable thing +// that needs to be done to move the rezzing process along. +take_the_next_appropriate_action() +{ + // see if the child setup process is still running. + if (child_needs_setup || is_recon_pending || (llGetListLength(action_queue) > 0) ) { + // we're still waiting on something. make sure it hasn't timed out. + if (!check_for_child_timeout()) return; // we still have time. + // saying this one failed, so we set it such that we are not waiting for kids + // or recons or the data cow right now. + snooze_counter = 0; + if (child_needs_setup) { + if (DEBUGGING) log_it("TNAP: child needs setup..."); + child_needs_setup = FALSE; + if (conveyance_mode == ONE_WAY_TRIP) { +//log_it("TNAP: telling root one way kid is hosed."); + // the startup of a child jaunter has failed. let the root think we're + // doing okay so it can get on with its life. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, + REZOLATOR_EVENT_REZZED_CHILD, (string)global_rez_place); + return; + } else { +//log_it("TNAP: recon fail for kid needs setup, fall through."); + } + } else if (is_recon_pending) { + // the current reconnaissance drone has crashed apparently. deal with it. + if (DEBUGGING) log_it("TNAP: setting recon pend to false"); + is_recon_pending = FALSE; + return; + } else if (llGetListLength(action_queue) > 0) { + // action_queue must be non-empty, or we wouldn't be here. + list action_rec = pop_action_record(); // what else can we do? + if (DEBUGGING) log_it("TNAP: time-out on action: " + (string)action_rec); + return; + } + // proceed to the next steps which are probably remedial. + } + + if (DEBUGGING) log_it("TNAP: nothing pending, move things along..."); + + // nothing is pending right now. + if (conveyance_mode == ONE_WAY_TRIP) { + // this means we are done, since the only thing we do is start the kid up. + llSetTimerEvent(0.0); + return; + } + + // if the recon advancement returns true, then we are all set for the next place. + if (advance_reconnaissance_position()) return; + + // if we got to here, then we need to do something about being past end of list... + + if (done_reconnoiter) { + // all done with that, so we don't need the timer anymore. + llSetTimerEvent(0.0); // stop coming here. + return; // don't need to do any more. + } + + if (trying_hard_cases) { + try_the_hard_cases(); + } + + if (DEBUGGING) log_it("fell completely through TNAP()"); +} + +// tries to crack the hard cases using added random jaunt destinations. +try_the_hard_cases() +{ + if (DEBUGGING) log_it("hardcase performing recon re-attempt, name=" + global_destination_name); + if (is_prefix(global_destination_name, QUADRANT_TAG_NAME)) { +//log_it("seeing that " + global_destination_name + " is a generated dest, ignoring."); + splice_destination_info(current_recon_index, "#" + (string)current_recon_index, + vector_chop(final_destination), VERIFY_UNSAFE_DECIDED); + advance_reconnaissance_position(); + return; + } + // count that as a failure, since we're not still on our first run through the list. + recon_reattempts++; + if (recon_reattempts > MAXIMUM_RECON_ATTEMPTS) { + // we have totally failed to find a workable pathway. we'll store the + // most simple form of the path back as the one to use. + log_it("total failure reaching " + (string)final_destination); + splice_destination_info(current_recon_index, "#" + (string)current_recon_index, + vector_chop(final_destination), VERIFY_UNSAFE_DECIDED); + recon_reattempts = 0; + advance_reconnaissance_position(); + return; + } + + // start the process of finding a good random path. + if (!load_random_safe_path()) { + // can't get there from anywhere else, so try from here. + log_it("could not find a good random path!"); + scramble_to_find_a_way([]); + } +} + +// called to start a jaunter in the appropriate mode. +rez_requested_child(string object_name, integer conv_mode, + integer chat_channel, string destination_name, integer all_dests_count, + string target_location) +{ + if (DEBUGGING) + log_it("rez req: " + object_name + " convey=" + (string)conveyance_mode + " chat=" + (string)chat_channel + " dest=" + destination_name + " fullcount=" + (string)all_dests_count + " targ=" + target_location); + + if (private_id_from_listen) { + // toss old listening since we're working on a new deal now. + llListenRemove(private_id_from_listen); + } + // listen to chats on our special channel. + private_id_from_listen = llListen(chat_channel, "", NULL_KEY, ""); + + // remember the info so we can tell our new child. + conveyance_mode = conv_mode; + global_destination_name = destination_name; + global_object_name = object_name; // the object to rez from inventory. + private_chat_channel = chat_channel; + full_journey = llParseString2List(target_location, [VECTOR_SEPARATOR], []); + destinations_total = all_dests_count; + global_verifications = []; // clear any old verifications. + integer indy; + for (indy = 0; indy < destinations_total; indy++) + global_verifications += [ VERIFY_UNTESTED ]; + + if (conveyance_mode == RECONNAISSANCE_TRIP) { + // we need to start reconnaissance mode. + current_recon_index = -1; // a signal that we haven't started. + snooze_counter = 0; + is_recon_pending = FALSE; + done_reconnoiter = FALSE; + +//turned off currently. doesn't seem to help much. +if (FALSE) { + // experimental: add the quadrants of the sim as destinations. if some of these + // are reachable, then they should help us out. + destinations_real = destinations_total; + integer x; + integer y; + for (x = 32; x <= 255; x += 64) { + for (y = 32; y <= 255; y += 64) { + vector calculated = ; + float height = llGround(calculated - llGetPos()); + calculated.z = height + 64; + add_destination(QUADRANT_TAG_NAME + (string)x + "," + (string)y, + (string)adjust_to_ground(, 64), VERIFY_UNTESTED); + } + } +} + + take_the_next_appropriate_action(); + } else { + // create the jaunter object for a one way trip. + rez_a_jaunter(object_name, ONE_WAY_TRICKY_PARM + chat_channel, conveyance_mode); + } + llSetTimerEvent(TIMER_PERIOD); +} + +// handles responses about our list coming back from the data cow. +answer_to_the_cow(string msg, string id, list parms) +{ + string tag = llList2String(parms, 0); + if (tag != OUR_COW_TAG) return; // was not for us. + parms = llDeleteSubList(parms, 0, 0); // trim out the tag. + list action_record = pop_action_record(); + integer actyo = extract_action_code(action_record); + // get the name out of the set first. + list split = llParseString2List(llList2String(parms, 1), [HUFFWARE_ITEM_SEPARATOR], []); + + if (actyo != AQ_ACQUIRE_BASE_PATH) { + // it's very important that when we're acquiring other targets' path components, + // we do not mistake that for our own state for the path we're trying to reach. + // thus we only record the answer for actions that are about our real target. + global_destination_name = llList2String(parms, 0); + last_verification = llList2Integer(split, 1); + full_journey = prechewed_destinations(llList2String(split, 0)); + if (DEBUGGING) + log_it("just heard verif=" + (string)last_verification + " for " + global_destination_name); + } + + if (actyo == AQ_ONEWAY_JAUNTER_VOYAGE) { +//log_it("one way, saying on chan " + (string)private_chat_channel + " -- " + global_destination_name + " fullj=" + (string)full_journey); + + child_needs_setup = FALSE; // count off the one we just set up. + + integer indy; // i told you N times. + for (indy = 0; indy < MAX_CHAT_REPEAT; indy++) { + llSay(private_chat_channel, CHILD_CHAT_TEXT + + global_destination_name + + DB_SEPARATOR + + llDumpList2String(full_journey, VECTOR_SEPARATOR)); + // pausing to let our words sink in. + llSleep(SLEEPY_TIME); + } + + // tell the root jaunter that this kid has been issued. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, + REZOLATOR_EVENT_REZZED_CHILD, (string)global_rez_place ); + } else if (actyo == AQ_PREP_RECON_JAUNTER) { + // we got info about a place to try. record the last verif state locally. + if (DEBUGGING) log_it("info re destination: verif = " + last_verification); + splice_just_verification(current_recon_index, last_verification); + if ( (last_verification == VERIFY_UNTESTED) + || (trying_hard_cases && (last_verification == VERIFY_UNSAFE_SO_FAR) ) ) { + // this one is not tested yet or had problems. try it now. +//log_it("testing unchecked locale."); + is_recon_pending = TRUE; + // if the destination is claiming it's untested, we fix that now untrue statement. + if (last_verification == VERIFY_UNTESTED) { + splice_destination_info(current_recon_index, "#" + (string)current_recon_index, + llDumpList2String(full_journey, VECTOR_SEPARATOR), VERIFY_UNSAFE_SO_FAR); + } + if (DEBUGGING) + log_it("rezzing jaunter for: name " + global_destination_name + " journ" + (string)full_journey); + rez_a_jaunter(global_object_name, + RECONNAISSANCE_TRICKY_PARM + private_chat_channel, RECONNAISSANCE_TRIP); + } else { + // this one doesn't need a recon. + is_recon_pending = FALSE; +//log_it("skipping recon for verif " + (string)last_verification); + advance_reconnaissance_position(); + } + } else if (actyo == AQ_CHECK_HARD_CASE) { + // we got an answer to our request for a new hard locale to try. + // remember the verification state locally. + splice_just_verification(current_recon_index, last_verification); + + if ( (last_verification == VERIFY_UNTESTED) || (last_verification == VERIFY_UNSAFE_SO_FAR) ) { + // this one is not tested yet or had problems. try it now. + if (DEBUGGING) + log_it("testing hard case locale at " + (string)current_recon_index + + " name=" + global_destination_name); + final_destination = (vector)llList2String(full_journey, -1); + try_the_hard_cases(); + } else { +//log_it("check hard case--already safe or decidedly unsafe, skipping."); + if (last_verification == VERIFY_SAFE) { + good_destinations_counted++; + if (!is_prefix(global_destination_name, QUADRANT_TAG_NAME)) { + ungenerated_good_destinations_counted++; + } + } + advance_reconnaissance_position(); + } + take_the_next_appropriate_action(); + } else if (actyo == AQ_ACQUIRE_BASE_PATH) { + // a response with a hopefully good destination arrived; base a path on that. + scramble_to_find_a_way(prechewed_destinations(llList2String(split, 0))); + } +} + +// looks at the location "look_here" and finds the ground height as the z component +// of the returned vector (where x and y are copied from "look_here"). if the +// "height_add_in" is non-zero, it is added to the z component to adjust the ground +// height by an offset. +vector adjust_to_ground(vector look_here, float height_add_in) +{ + float height = llGround(look_here - llGetPos()); + look_here.z = height + height_add_in; + return look_here; +} + +// tries to come up with a random path that can reach a difficult place. +scramble_to_find_a_way(list possible_helpful_path) +{ + // we were told this was a good pathway, so let's try it. + if (randomize_within_range(0.0, 1.0, FALSE) > 0.5) { + // if we feel like it, add some huge random vectors in. + integer indy; + integer how_many = (integer)randomize_within_range(1, 5, FALSE); +//magic constant above. + vector rando = llGetPos(); // start with current place. + for (indy = 0; indy < how_many; indy++) { + // try to add a random completely other place in the sim. + vector other_rando = adjust_to_ground(random_vector(0.0, 256.0, FALSE), 64); + rando.z = other_rando.z; + // by only changing one axis at a time for x and y, we kind of slide around. + // this is considered more beneficial than just jumping randomly. + if (randomize_within_range(0.0, 1.0, FALSE) > 0.5) { + // this 50% modulates the x. + rando.x = other_rando.x; + } else { + // this other 50% modulates the y. + rando.y = other_rando.y; + } +//log_it("scramble: wacky rando: " + vector_chop(rando)); + possible_helpful_path += [ vector_chop(rando) ]; + } + } + if (randomize_within_range(0.0, 1.0, FALSE) > 0.2) { + // maybe we also feel like adding a small amount to the final destination, + // trying for a hook shot, most of the time. +//log_it("scramble: addition relative to final destination."); + vector rando = adjust_to_ground(final_destination + random_vector(0.0, 8.0, TRUE), 64); +//magic constant above. + possible_helpful_path += [ vector_chop(rando) ]; + } + if ( (final_destination.z < 1000.0) && (randomize_within_range(0.0, 1.0, FALSE) > 0.05) ) { +//hmmm: is this redundant now? + // we very often add a vertical component so as to swoop down on the destination + // and hopefully avoid ground fault conditions. + possible_helpful_path += [ vector_chop() ]; +//magic constant above. + } + // now finally we add in the real place where we're going. + possible_helpful_path += [ vector_chop(final_destination) ]; + // prepare our state for the new attempt. + is_recon_pending = TRUE; + snooze_counter = 0; + full_journey = possible_helpful_path; +//log_it("scramble: final guess=" + (string)full_journey); + // rez for this nutty test path. + rez_a_jaunter(global_object_name, + RECONNAISSANCE_TRICKY_PARM + private_chat_channel, RECONNAISSANCE_TRIP); +} + +// this function returns TRUE if we are close enough to the "destination". +integer close_enough(vector destination) +{ + float PROXIMITY_REQUIRED = 0.1; + // how close we must be to the target location to call it done. + // matches current jaunting library proximity. + return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); +} + +// records a verification state locally so we can make decisions during testing. +splice_just_verification(integer index, integer verif_state) +{ + if ( (index < 0) || (index >= destinations_total) ) return; // can't do it. + global_verifications = chop_list(global_verifications, 0, index - 1) + + [ verif_state ] + + chop_list(global_verifications, index + 1, destinations_total - 1); +} + +// replaces an existing entry at the "index" if known (otherwise this should be negative) +// for the location named "dest_name" if known (otherwise should be a restatement of the +// numerical index with '#' in front). +splice_destination_info(integer index, string dest_name, string pathway, integer verif) +{ +//log_it("splicedest: " + (string)index + " name=" + dest_name + " verif=" + (string)verif + " path=" + pathway); + splice_just_verification(index, verif); + string new_entry = wrap_item_list([pathway, verif]); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, + wrap_parameters([dest_name, new_entry])); +} + +string verification_name(integer enumtype) +{ + if (enumtype == VERIFY_SAFE) return "ok"; + else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; + else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; + // catch-all, including untested. + return "?"; +} + +// returns true if the slackness counter awaiting things has elapsed. +integer check_for_child_timeout() +{ + if (snooze_counter++ > MAXIMUM_SNOOZES) { + // go back to the main state. we took too long. +// log_it("timed out!"); + llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. + return TRUE; + } + return FALSE; +} + +////////////// + +// action queue for postponed activities. the first field held in a list item here +// is an integer action code. the format of the remaining parameters is up to the +// caller, and they can be used as the final parameters for when the queued action +// gets handled. +list action_queue; + +// looks at the action code at the head of the queue without removing the action. +integer peek_action_code() +{ + list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + return extract_action_code(fields); +} + +// extracts the action code from a retrieved list. +integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } + +// removes the current head of the action queue and returns it. +list pop_action_record() +{ + list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + action_queue = llDeleteSubList(action_queue, 0, 0); + return top_action; +} + +// adds a new action to the end of the action queue. +push_action_record(integer action, list added_parms) +{ + snooze_counter = 0; // reset back for new action. + action_queue += [ wrap_parameters([action] + added_parms) ]; +} + +////////////// + +// processes link messages received from support libraries. +handle_link_message(integer which, integer num, string msg, string id) +{ + // maybe it's a piece of data from the data cow. + if (num == DATA_COW_HUFFWARE_ID + REPLY_DISTANCE) { + // unpack the parameters we were given. + list parms_x = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + answer_to_the_cow(msg, id, parms_x); + return; + } + + if (num != JAUNT_REZOLATOR_HUFFWARE_ID) return; // not interesting. + if (DEBUGGING) log_it("linkmsg: msg " + msg + " id " + id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == REZ_CHILD_NOW) { + serving_root = TRUE; + snooze_counter = 0; // reset counter. + if (llGetListLength(parms) < REZ_KID_FIELDS_NEEDED) { +// log_it("insufficient parameters for rezzing child."); + return; + } + rez_requested_child(llList2String(parms, 0), llList2Integer(parms, 1), + llList2Integer(parms, 2), llList2String(parms, 3), + llList2Integer(parms, 4), llList2String(parms, 5)); + } else if (msg == REPORT_CHILD_REZZED) { + report_to_root(); + } else if (msg == RESET_REZOLATOR) { + llResetScript(); + } else if (msg == REZOLATOR_CHILD_SUPPORT) { + provide_child_support(llList2Integer(parms, 0)); + } else if (msg == REZOLATOR_CHILD_RETURNED) { + if (conveyance_mode == RECONNAISSANCE_TRIP) { + // unpack the success value from jaunter's check. + integer succeeded_recon = llList2Integer(parms, 0); + // report on our success. + list report_loc = full_journey; + if (!succeeded_recon) { + // we did at least get to somewhere, even if not to target. + report_loc = llParseString2List(llList2String(parms, 1), + [VECTOR_SEPARATOR], []); + } + llWhisper(private_chat_channel, CHILD_CHAT_TEXT + RETURN_WORD + + (string)succeeded_recon + DB_SEPARATOR + + global_destination_name + + DB_SEPARATOR + + llDumpList2String(report_loc, VECTOR_SEPARATOR)); +//log_it("child reporting success=" + (string)succeeded_recon + " for " + global_destination_name + " via " + llDumpList2String(report_loc, VECTOR_SEPARATOR) ); + // shuffle off... +//log_it("now dying at posn " + (string)llGetPos()); + llDie(); // oh crud, we're toast. + } else { + // one way trip?? + if (!succeeded_recon) log_it("too far away; path okay?"); + } + } +} + +// makes our click action change to the type requested, and sends the request +// out to all our sub-prims also. +set_click_action(integer action) +{ + llSetClickAction(action); + // secret message to other prims to change click action. + llMessageLinked(LINK_SET, CHANGE_CLICK_ACTION_HUFFWARE_ID, "", (string)action); +} + +// tries to find a known safe locale that's close to the target. if there are any +// that are close, then we will not add this location. otherwise, we do add it, +// if the list is not already too large. +add_if_no_close_match(string pathway) +{ + // make sure there's enough room to bother checking. + if (llGetListLength(safe_locales_seen) >= MAXIMUM_SAFE_LOCATIONS) return; + list dests = llParseString2List(pathway, [VECTOR_SEPARATOR], []); + vector final_locn = (vector)llList2String(dests, -1); + // set the z component to zero for this comparison, which is only about x,y position. + // since we then add this trimmed vector, we don't need to worry about the z component + // for the items already in the list. + final_locn.z = 0; + integer i; + for (i = 0; i < llGetListLength(safe_locales_seen); i++) { + vector curr = (vector)llList2String(safe_locales_seen, i); + if (llVecDist(curr, final_locn) < MINIMUM_DISTANCE_FOR_EXTRAS) { +//log_it("dest too close: dist = " + (string)llVecDist(curr, final_locn)); + return; + } + } + if (DEBUGGING) log_it("dest far enough to add: " + pathway); + // no known locale is close, so we'll add this one. + safe_locales_seen += [ final_locn ]; + good_destinations_counted++; + add_destination(QUADRANT_TAG_NAME + "pt#" + (string)(partial_path_count++), + pathway, VERIFY_SAFE); +} + +// process what we hear in open chat and on our special channels. +// this function should always return FALSE unless it's been given enough info +// to enter a new state, in which case it should return true. +listen_to_voices(integer channel, string name, key id, string message) +{ + // check to see if the text is right. + if (DEBUGGING) + log_it("heard: " + message + " from " + name); + if (!is_prefix(message, CHILD_CHAT_TEXT)) return; // not right. + message = llDeleteSubString(message, 0, llStringLength(CHILD_CHAT_TEXT) - 1); + // maybe this is a startup request. + if (is_prefix(message, READY_TEXT) && serving_root) { + // yes, this is a request for a destination. we are going to fill the rezzed object + // now, so figure out what type of jaunter needs info. formerly fill_rezzed_object. + integer is_recon = (integer)llGetSubString(message, -1, -1); + if (done_reconnoiter && is_recon) return; // we already did all that. + if (is_recon) { + // a recon jaunter needs its instructions. + if (DEBUGGING) + log_it("telling recon kid: name " + global_destination_name + " journ=" + (string)full_journey); + is_recon_pending = TRUE; + integer indy; // i told you N times. + for (indy = 0; indy < MAX_CHAT_REPEAT; indy++) { + llSay(private_chat_channel, CHILD_CHAT_TEXT + + global_destination_name + + DB_SEPARATOR + + llDumpList2String(full_journey, VECTOR_SEPARATOR)); + // snooze to make sure we pause a little between mouthings. + llSleep(SLEEPY_TIME); + } + + snooze_counter = 0; // starting over. + child_needs_setup = FALSE; // count off the one we just set up. + } else { + if (DEBUGGING) + log_it("into code for one way jaunter"); + // simple one way jaunter needs fillin'. + list added_parms = []; + push_action_record(AQ_ONEWAY_JAUNTER_VOYAGE, added_parms); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, global_destination_name])); + } + return; + } + + if (DEBUGGING) log_it("into kid side of rezolator..."); + + if (!serving_root) { + if ( (conveyance_mode == RECONNAISSANCE_TRIP) || (conveyance_mode == ONE_WAY_TRIP) ) { + if (heard_from_root) return; // we already did this bit. + // this jaunter is destined for short-lived work, but now at least has a goal. + // we just pass along the parameters that were told to us from the root jaunter. + list parms = llParseString2List(message, [DB_SEPARATOR], []); + global_destination_name = llList2String(parms, 0); + full_journey = llParseString2List(llList2String(parms, 1), [VECTOR_SEPARATOR], []); + final_destination = (vector)llList2String(full_journey, -1); + parms += [ conveyance_mode ]; + + if (conveyance_mode == ONE_WAY_TRIP) { + // set the click action properly. + if (outside_of_sim(final_destination)) set_click_action(CLICK_ACTION_TOUCH); + else set_click_action(CLICK_ACTION_SIT); + } + + if (DEBUGGING) log_it("kid heard go to: " + global_destination_name + " via " + (string)full_journey); + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE, + REZOLATOR_EVENT_GOT_INSTRUCTIONS, wrap_parameters(parms)); + // make sure we cancel the listening so we don't hear directions that aren't for us. + llListenRemove(private_id_from_listen); + heard_from_root = TRUE; + return; // only leave for recon. + } + } else { + // this jaunter's role should be a root jaunter, and we have a reply about a recon mission. + is_recon_pending = FALSE; // we got an acceptable answer. + list parms = llParseString2List(llDeleteSubString + (message, 0, llStringLength(RETURN_WORD) - 1), [DB_SEPARATOR], []); + integer success = llList2Integer(parms, 0); + string dest_name = llList2String(parms, 1); + string pathway = llList2String(parms, 2); +//log_it("|||| recon reply: " + dest_name + " good=" + (string)success + " path=" + pathway); + if (success) { + // record this as a safe pathway. + last_verification = VERIFY_SAFE; + good_destinations_counted++; + } else { + // a failure is being reported. record this as a bad pathway. + last_verification = VERIFY_UNSAFE_SO_FAR; + // however, the jaunter should have told us where it did get to. record that whole + // thing if it seems like a good distance from our other known good places. + if (DEBUGGING) log_it("failed path did get to: " + pathway); + add_if_no_close_match(pathway); + + } + // only save this info if we're not working on recons. + if (!trying_hard_cases || success) { + // fix name for tough destination's real one. + if (trying_hard_cases) { + dest_name = "#" + (string)current_recon_index; + } + splice_destination_info(current_recon_index, dest_name, + llDumpList2String(full_journey, + ///llList2List(full_journey, 1, -1), + VECTOR_SEPARATOR), + last_verification); + } + take_the_next_appropriate_action(); + } +} + +// processes a destination set to handle special cases, like for offset jaunting. +list prechewed_destinations(string dests) +{ + +//hmmm: document this! as in, we support the offset format. + + // look for our special start character for offsets. + if (is_prefix(dests, "o")) + // if this is an offset version, then chop whatever word they used starting with 'o' + // and compute the destination based on current position. + return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; + else + // normal jaunt to absolute coordinates. + return llParseString2List(dests, [VECTOR_SEPARATOR], []); +} + +// creates a jaunter object given which inventory item and the startup parm. +rez_a_jaunter(string object_name, integer rez_parm, integer conveyance_mode) +{ + // the minimum and maximum distances for placing the auto-rezzed jaunter object. + integer MIN_REZ_DISTANCE = 1; + integer MAX_REZ_DISTANCE = 3; + vector RECON_ROTATION = <270.0, 0.0, 0.0>; + // what angle we use when planting the recon jaunter. + // this is tightly coupled to our particular object. + vector point_at_jaunter; + if (conveyance_mode == RECONNAISSANCE_TRIP) { + // we just use our specified rotation. + point_at_jaunter = RECON_ROTATION * DEG_TO_RAD; + // start at where the jaunter will be when it tries the same path. + global_rez_place = llGetPos(); + } else { + // we randomize the location to avoid people having the objects + // in a big pile on top of each other. + global_rez_place = llGetPos() + + ; // pop it up a bit. + // aim the temporary ride at the root jaunter. + vector aim_back = llGetPos() - global_rez_place; + float z_rot = llAtan2(aim_back.y, aim_back.x); + // calculate the vector for rotation given the z rotation. + point_at_jaunter = <0.0, 0.0, z_rot>; + } + llRezObject(object_name, global_rez_place, + ZERO_VECTOR, llEuler2Rot(point_at_jaunter), rez_parm); + if (conveyance_mode != RECONNAISSANCE_TRIP) { + // this model only jaunts to where it gave out the object. that + // should hopefully always work. but at least if it can't get back, + // it's really close by. + full_journey = [ vector_chop(llGetPos()), vector_chop(global_rez_place) ]; + } + child_needs_setup = TRUE; // we aren't ready to go even if jaunt is done. + snooze_counter = 0; // amnesty on the timer. +} + +// finds a pathway that's already in our list and that we think is safe. +integer load_random_safe_path() +{ + integer indy; + integer goodunz = good_destinations_counted; + + // now that we know how many are safe, we can pick a good destination. + integer randola = llRound(randomize_within_range(0, goodunz - 1, FALSE)); + integer safe_indy = -1; // tracks which safe item we're at. + for (indy = 0; indy < llGetListLength(global_verifications); indy++) { + // scoot across the list to find the Nth safe one. + if (llList2Integer(global_verifications, indy) == VERIFY_SAFE) { + if (safe_indy == randola) { +//log_it("like path at " + (string)safe_indy); + // we're at the Nth safe item, so this is our random choice. + list added_parms = []; + push_action_record(AQ_ACQUIRE_BASE_PATH, added_parms); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, "#" + (string)safe_indy])); + return TRUE; + } + // increment to the next position, since we've seen this one. + safe_indy++; + } + } +//log_it("found no good path to use"); + return FALSE; +} + +// processes the timer events during an ongoing rezzing process. +handle_timer() +{ + // this is the root's timer process, which is implemented in great detail + // in the function below. + if (serving_root) take_the_next_appropriate_action(); +} + +// file a report with the root jaunter that the child has been created and is +// ready for service. +report_to_root() +{ + // tell the root jaunter know that we're ready to be packed for our trip. + llSay(private_chat_channel, CHILD_CHAT_TEXT + READY_TEXT + + (string)(conveyance_mode == RECONNAISSANCE_TRIP)); +} + +// plops a new destination on the end of the lists. +add_destination(string name, string path, integer verif) +{ +//log_it("adding " + name + " with path " + path + " and verif=" + (string)verif); + global_verifications += [ verif ]; + // send our new information to the data cow. we store the information encoded as + // two separated items, where the first element is the destination and the second + // is the verification state. + string new_entry = wrap_item_list([path, verif]); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, + wrap_parameters([name, new_entry])); + destinations_total++; // we just added another destination. +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +// returns text for a floating point number, but includes only +// two digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 100.0) / 100); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); initialize_rezolator(); } + + on_rez(integer startup) { llResetScript(); } + + state_exit() { llSetTimerEvent(0.0); } + + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + listen(integer channel, string name, key id, string message) + { listen_to_voices(channel, name, id, message); } + + timer() { handle_timer(); } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.lsl b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.lsl deleted file mode 100755 index f8273c1d..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.lsl +++ /dev/null @@ -1,1205 +0,0 @@ - -// huffware script: jaunt wik rez, by fred huffhines, released under GPL license. -// -// this is a jaunter (teleporter) script with some useful and uncommon features. -// it can work around certain types of complicated land permissions on neighboring land -// that might otherwise lead to blocked jaunts. -// the usage of "jaunt" for teleportation is inspired by the alfred bester novel, "the stars -// my destination". if you like science fiction and have not read this book, it is highly -// recommended. -// parts of this script are based on "Teleporter Script v 3.0 by Asira Sakai", from -// the LSL wiki. -// -// use jaunt wik rez by placing a notecard in the inventory of your jaunter object. the notecard -// should start with "#jaunt" on the first line and then should have alternating lines of -// (1) jaunt target (as a vector) and (2) readable target name, for example: -// #jaunt -// <23, 18, 92> -// gracy square -// <182, 32, 56> -// tourmaline palace -// <23, 18, 92>|<118, 19, 108>|<120, 33, 57> -// unblocked pathway, hurrah -// note the last destination; the script also supports a list of intermediate destinations. -// this feature can enable one to route a teleport around blocked lands by using waypoints -// that are still accessible. but since the current version of the script automatically -// finds routes for most destinations, this is not needed very frequently. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -integer DEBUGGING = FALSE; - // make true to print diagnostic logging. - -// configurable options (set in notecard): - -integer SHOW_TEXT = TRUE; - // if true, then the jaunter will show a text label for the destination. - // this can be configured from the notecard with ":show_text=0" to turn off, - // or 1 to turn on. -integer ADD_NAME = FALSE; - // if this is true, then the text shown will include the object's name. - -string TEXT_COLOR = "<0.3, 0.9, 0.7>"; - // set float text color to a nice color. -///hmmm: doesn't seem to be in the notecard yet! - -////////////// - -// the jaunter button pushing API. -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10029; - // a unique ID within the huffware system for this script. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was -string JAUNT_NEXT_BUTTON_NAME = "next"; -string JAUNT_MENU_BUTTON_NAME = "menu"; - -////////////// - -// requires the jaunt config API. -////////////// -// do not redefine these constants. -integer JAUNT_CONFIGURATION_HUFFWARE_ID = 10022; - // the unique id within the huffware system for this script's commands. - // it's used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available from the jaunt config library: -string LOAD_ALL_CONFIGURATIONS = "#rdcfg#"; - // this starts the process of loading jaunt destinations from the notecards and - // landmarks that we find in the object. the parms are: private channel - // and conveyance mode. -string JAUNT_CFG_DATA_EVENT = "#yodata#"; - // this event is generated from this script back to the caller. when we have some - // landmark data or configuration information, it's passed back in chunks. the - // deluge of pieces will continue until the JAUNT_CFG_EOF event is passed. the - // parameters include packed destination name and vector pairs (which form 2 elements - // in the list) and packed config variable definitions (where config items start - // with a colon, and the definition is only one element in the list). -string JAUNT_CFG_EOF = "#done#"; - // sent after all valid configuration items that we could find were processed. -// -////////////// - -// requires jaunting library API. -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -// commands available via the jaunting library: -string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a string in jaunt notecard format with vectors. - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// - -// requires menutini API. -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. - -// requires data cow library API. -////////////// -// do not redefine these constants. -integer DATA_COW_HUFFWARE_ID = 10017; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -////////////// -string RESET_LIST_COMMAND = "reset_L"; - // flushes out the currently held list. does not send a reply. -string ADD_ITEM_COMMAND = "add_I"; - // adds items to the list. this is a list of pairs of name/value, where the name is - // how the item will be looked up from the list, and the value is the contents to be stored. - // this command has no reply. -string GET_COW_LENGTH = "get_Lc"; - // returns a single integer which is the length of the cow's list currently. -//string REMOVE_ITEM_COMMAND = "rm_I"; - // accepts a list of names for items. all the mentioned ones will be removed from the list. - // this command also has no reply. -//string GET_ITEM_COMMAND = "get_I"; - // retrieves the item's contents for a given name. first parm is the name. if there - // are other parameters, then they are taken as other items to return also. - // the return data will be pairs of for each of the names in the request. - // if the data was not located, then the entry will be empty. -string TAGGED_GET_ITEM_COMMAND = "get_T"; - // like get item, except the first parameter is an identifier that the caller wants to - // use to tag this request. the other parameters are still taken as names. the response - // will contain the tag as the first item, then the pairs that were found. - -////////////// - -// requires click action API... -////////////// -integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; - // a unique ID within the huffware system for this script. -// the API only supports the service number; there are no commands to pass in the "msg" -// parameter. the id does accept a parameter, which is the type of click action to begin -// using for this prim. -////////////// - -// the API for this library script to be used in other scripts. -////////////// -// do not redefine these constants. -integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; - // the unique id within the huffware system for this script's commands. - // it's used in llMessageLinked as the num parameter. -////////////// -// commands available from the library: -string RESET_REZOLATOR = "#reset"; - // tells the script to stop any previous efforts to rez children. -string REZ_CHILD_NOW = "#rezkd#"; - // requests this script to create a new child object. this requires several - // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object - // to implement, 3) the chat channel to listen for and speak to new child on, - // 4) the destination name for where the child should go, 5) a count of the full - // set of known destinations, 6) the target where the jaunt should arrive at. -////////////// -// events generated by the library: -string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; - // an event generated for a previous rez child request. this lets the caller know that - // the child has been created and told what to do. the single parameter is where the - // jaunter has been rezzed. -string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; - // an event generated when the recon process has concluded. this includes parms: - // number of good destinations. -// -////////////// - -// important constants used internally... these should not be changed willy nilly. - -////////////// jaunt base API - -// the following constants define how the script should behave (i.e., its conveyance mode). -// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere -// and then takes the same pathway back, but in reverse order. -// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to -// the root telehub. that object is loaded with the destination notecard and this script. -// the rezzed object can then be used for the next few minutes to jaunt to the selected -// destination. the temporary object will use the ONE_WAY_TRIP mode. -// ONE_WAY_TRIP: the object containing this script will take the user to a particular -// destination, but the object does not survive the trip. it self-destructs after -// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER -// mode and should generally never be used on its own. -// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a -// destination. -integer TWO_WAY_TRIP = 1; -integer AUTOREZ_JAUNTER = 2; -integer ONE_WAY_TRIP = 3; -integer RECONNAISSANCE_TRIP = 4; - -// values used to represent different stages of verification. -integer VERIFY_UNTESTED = -3; // don't know destinations state yet. -integer VERIFY_SAFE = -4; // the destination last tested safe. -integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. -integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. - -integer MAXIMUM_PRIV_CHAN = 90000; - // the largest amount we will ever subtract from the tricky parms in order to - // tell the sub-jaunter which channel to listen on. - -string VECTOR_SEPARATOR = "|"; - // how we separate components of vectors from each other. -string DB_SEPARATOR = "``"; // separating items in lists. - -////////////// end jaunt base API - -integer MAX_DEST_NAME = 24; // the longest name that we store. - -float NORMAL_TIMER_PERIOD = 1.0; // our normal timer rate. - -string RESET_COMMAND = "jreset"; // forget everything and start over. -string SHOW_COMMAND = "show"; // describe the known destinations. -string RECON_COMMAND = "recon"; // tells the jaunter to run reconnaissance on destinations. - -float POSITION_CHECKING_INTERVAL = 0.11; - // how frequently the waiting for arrival state will check where we are. - -integer MAXIMUM_SLACKNESS = 108; - // how many timer hits we'll allow before reverting to the default state. - -integer FREE_MEM_REQUIRED = 1600; - // we need at least this much memory before adding new targets. - -// somewhere between two and 10 minutes (default) will elapse before first recon testing. -float MIN_RECON_SNOOZE = 120; -float MAX_RECON_SNOOZE = 1200; - -// the actions that can be held in the action queue. -integer AQ_SHOW_DEST_RECORD = 23; // a record to be shown to the user. -integer AQ_FINISH_SHOW_DESTS = 24; // last record in a jaunt destinations list. -integer AQ_CLICK_ACTION_REQUEST = 25; // the response should set our click action. -integer AQ_SELECT_DESTINATION = 27; // the user has chosen a different destination. -integer AQ_DONE_CONFIGURING = 28; // the last step of the configuration process has finished. - -string OUR_COW_TAG = "jwkrz_dc"; // unique id for this script to talk to the data cow with. - -////////////// - -// global variables. - -integer private_chat_channel; // where sub-jaunters communicate with root. -integer conveyance_mode; /// = TWO_WAY_TRIP; - // default is a standard two way trip, there and back again. note that the object - // will fail to return if any lands in between are blocking object entry. those - // situations should use an auto-rez jaunter, which is specified by prefixing the - // target vectors with AR. -integer last_verification_state; // the verification state of the last destination we asked for. -string last_pathway; // similar, but the last pathway we heard. -integer current_target_index; // the location in the list that we would currently jaunt to. - -integer good_destinations; // computed during the recon process. - -// jaunter target configuration... -list global_names; // the names for each destination. - -// jaunt trip variables... -vector eventual_destination; // where we're headed, if we're headed anywhere. -integer slackness_counter; // snoozes had while waiting for destination. -list full_journey; // the full pathway we expect to jaunt on. -integer jaunt_responses_awaited; // number of pending jumps in progress. - -// root jaunter variables... -integer child_needs_setup; - // true when a child has been rezzed and still needs to be filled with the script. - -integer recon_started_yet = FALSE; - // true if we've finished running through the reconnaissance process yet. - -////////////// - -// makes our click action change to the type requested, and sends the request -// out to all our sub-prims also. -set_click_action(integer action) -{ - llSetClickAction(action); - // secret message to other prims to change click action. - llMessageLinked(LINK_SET, CHANGE_CLICK_ACTION_HUFFWARE_ID, "", (string)action); -} - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -// show the list of options for someone who used the click-hold feature. -show_jaunt_menu(key last_toucher) -{ - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - "jm" + HUFFWARE_PARM_SEPARATOR - + "Jaunt to..." + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(global_names) - + HUFFWARE_PARM_SEPARATOR - + (string)random_channel() + HUFFWARE_PARM_SEPARATOR - + (string)last_toucher); -} - -// respond to the user's choice. -react_to_menu(string which_choice) -{ - integer indy; - // find the specified destination and select it. - indy = llListFindList(global_names, [which_choice]); - if (indy >= 0) { - current_target_index = indy; - select_destination(current_target_index); - } -} - -// asks the jaunting library to take us to the target using a list of waypoints. -request_jaunt(list journey, integer forwards) -{ - // ask for a jump. - jaunt_responses_awaited++; - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, - wrap_item_list(journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); - // stops the jaunter in its tracks. - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); -} - -// this function returns TRUE if we are close enough to the "destination". -integer close_enough(vector destination) -{ - float PROXIMITY_REQUIRED = 0.1; - // how close we must be to the target location to call it done. - // matches current jaunting library proximity. - return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); -} - -// returns appropriate sit text for our current jaunt mode. -string sit_text() -{ - if (conveyance_mode == AUTOREZ_JAUNTER) return "Rez Ride"; - return "Jaunt"; -} - -// plops a new destination on the end of the lists. -add_destination(string name, string path, integer verif) -{ -// if (DEBUGGING) log_it("adding " + name + " with path " + path); - global_names += [ name ]; - // send our new information to the data cow. we store the information encoded as - // two separated items, where the first element is the destination and the second - // is the verification state. - string new_entry = wrap_item_list([path, verif]); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, - wrap_parameters([name, new_entry])); -} - -// sets up the initial state, if this script has just started, or it -// cleans up the state, if the script was already running. -initialize_jaunter() -{ - llSetTimerEvent(0.0); // cancel any existing timers. - - // reset all the important variables. - global_names = []; - current_target_index = 0; - good_destinations = 0; - - llSitTarget(<0, 0, 0.1>, ZERO_ROTATION); - // set a rudimentary sit target or opensim won't give us our changed events. - // load up an arrival sound if any exist. - if (llGetInventoryNumber(INVENTORY_SOUND)) - llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); - // reset the parallel processing scripts since we've restarted. - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, RESET_LIST_COMMAND, ""); - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, RESET_REZOLATOR, ""); - - // see if we can load our configuration from notecards and landmarks. - // we pick a private channel that fits in between our rez parm ranges. - private_chat_channel = (integer)randomize_within_range(-MAXIMUM_PRIV_CHAN, -1, FALSE); - // request that all the config get loaded up. - llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID, LOAD_ALL_CONFIGURATIONS, - wrap_parameters([private_chat_channel, conveyance_mode])); - // during a normal trip, we will make sure the notecard reading doesn't stall. - // the recon and one way jaunters don't need this; they're temporary. - // we allow this number of seconds before notecard reader is awol. - llSetTimerEvent(94); - - conveyance_mode = TWO_WAY_TRIP; // default init in opensim friendly way. - - // set up some of the object properties... - string msg; - if (SHOW_TEXT) msg = "?..."; - llSetText(msg, (vector)TEXT_COLOR, 1.0); // initial floating text for jaunter. - llSetSitText(sit_text()); // change to the proper text for our mode. -} - -init_normal_runtime() -{ - child_needs_setup = FALSE; - // listen to the general public for commands. - llListen(0, "", NULL_KEY, ""); - // set up a root jaunter. - recon_started_yet = FALSE; - llSetTimerEvent(randomize_within_range(MIN_RECON_SNOOZE, MAX_RECON_SNOOZE, FALSE)); -} - -// signal that we are where we were going. -proclaim_arrival() -{ - if (conveyance_mode == TWO_WAY_TRIP) { - // sing a little song, if there's a sound to use. - if (llGetInventoryNumber(INVENTORY_SOUND)) - llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), 1.0); - } -} - -string verification_name(integer enumtype) -{ - if (enumtype == VERIFY_SAFE) return "ok"; - else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; - else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; - // catch-all, including untested. - return "?"; -} - -// returns true if the slackness counter awaiting things has elapsed. -integer check_for_timeout() -{ - if (slackness_counter++ > MAXIMUM_SLACKNESS) { - // go back to the main state. we took too long. - log_it("timed out!"); - llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. - llSetTimerEvent(0.0); - return TRUE; - } - return FALSE; -} - -////////////// - -// action queue for postponed activities. the first field held in a list item here -// is an integer action code. the format of the remaining parameters is up to the -// caller, and they can be used as the final parameters for when the queued action -// gets handled. -list action_queue; - -// looks at the action code at the head of the queue without removing the action. -integer peek_action_code() -{ - list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - return extract_action_code(fields); -} - -// extracts the action code from a retrieved list. -integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } - -// removes the current head of the action queue and returns it. -list pop_action_record() -{ - if (llGetListLength(action_queue) == 0) { -// if (DEBUGGING) log_it("failure in action q: no entries."); - return []; - } - list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); - action_queue = llDeleteSubList(action_queue, 0, 0); - jaunt_responses_awaited--; // one less thing to wait for. - return top_action; -} - -// adds a new action to the end of the action queue. -push_action_record(integer action, list added_parms) -{ - action_queue += [ wrap_parameters([action] + added_parms) ]; - jaunt_responses_awaited++; // add one counter to our pending responses. -} - -////////////// - -string show_buffer; // used by the destination list showing code below. - -// requests a dump of all the jaunt destinations so we can show them to the user. -get_destination_records() -{ - show_buffer = "[mem " + (string)llGetFreeMemory() + "]"; // set the first line in the output. - - integer indy; - for (indy = 0; indy < llGetListLength(global_names); indy++) { - string curr = llList2String(global_names, indy); - // ask for this destination record. - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, curr])); - integer action = AQ_SHOW_DEST_RECORD; - if (indy == llGetListLength(global_names) - 1) { - // if it's the last item, make sure we signal that. - action = AQ_FINISH_SHOW_DESTS; - } - push_action_record(action, []); - } -} - -// displays the list of destinations in normal chat that the data cow is handing us. -show_destination_record(string loc_name, string pathway, integer verif, integer action) -{ - integer MAX_CHAT = 512; // the largest we let the buffer get before saying it. - show_buffer += " " + loc_name + " (" - + verification_name(verif) + ") ↣ " + pathway; - // if we're done, add a note about quality of targets. - if (action == AQ_FINISH_SHOW_DESTS) { - show_buffer += "\n (" + (string)good_destinations + " safe & " - + (string)(llGetListLength(global_names) - good_destinations) - + " tough ones)"; - } - - // if we're done or if the string gets too big, print and reset it. - if ( (action == AQ_FINISH_SHOW_DESTS) || (llStringLength(show_buffer) >= MAX_CHAT) ) { - llWhisper(0, show_buffer); - show_buffer = ""; - } -} - -// returns the value of a boolean variable definition. -integer parse_bool_def(string def) -{ return !(llGetSubString(def, find_substring(def, "=") + 1, -1) == "0"); } - -// processes a configuration option from the notecard. -handle_config_item(string item) -{ - item = llGetSubString(item, 1, -1); // chop the command signifier character. - if (is_prefix(item, "show_text")) { - // they are controlling whether to show the text label or not. - SHOW_TEXT = parse_bool_def(item); - } else if (is_prefix(item, "add_name")) { - ADD_NAME = parse_bool_def(item); - } -} - -// processes items coming from the configuration library. -consume_configuration_items(string msg, string id) -{ - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - integer mem_okay = llGetFreeMemory() >= FREE_MEM_REQUIRED; // false if we're low on memory. - if (!mem_okay) return; - integer indy; - for (indy = 0; indy < llGetListLength(parms); indy += 2) { - string name = llList2String(parms, indy); - if (is_prefix(name, ":")) { - handle_config_item(name); - indy--; // skip back so we continue looking for destinations. - } else { - // this should be a normal pair of destination vector and name. - integer verif_state = VERIFY_UNTESTED; - // check if it's a wacky location. - string map_coord = llList2String(parms, indy + 1); - list chewed = chewed_destination(map_coord); - if (outside_of_sim((vector)llList2String(chewed, 0))) { - if (DEBUGGING) log_it("ruled map_coor " + (string)map_coord + " out of sim."); - // make sure we consider the tp location "unsafe", since we can't run in-sim - // reconnaissance against it. also, we must postpone marking it until - // the destination is listed, given current implementation. - verif_state = VERIFY_UNSAFE_DECIDED; - } - add_destination(name, llList2String(parms, indy + 1), verif_state); - } - } -} - -// handles responses about our list coming back from the data cow. -integer answer_to_the_cow(string msg, string id, list parms) -{ - string tag = llList2String(parms, 0); - if (tag != OUR_COW_TAG) return FALSE; // was not for us. - parms = llDeleteSubList(parms, 0, 0); // trim out the tag. - list action_record = pop_action_record(); - integer actyo = extract_action_code(action_record); - list split = llParseString2List(llList2String(parms, 1), [HUFFWARE_ITEM_SEPARATOR], []); - if ( (actyo == AQ_SHOW_DEST_RECORD) || (actyo == AQ_FINISH_SHOW_DESTS) ) { - show_destination_record(llList2String(parms, 0), llList2String(split, 0), - llList2Integer(split, 1), actyo); - } else if (actyo == AQ_CLICK_ACTION_REQUEST) { - // make sure we're in the right mode for clicking based on how - // many destinations we have. if there's only one, we might as - // well make this jaunter just go there. - // note: just discovered that we cannot set the click action if the jaunter - // is multiple prims. that's totally fubar. it means we cannot correctly - // set the jaunter main body to show 'sit' as the option, even when jaunting - // directly to the destination is possible. freaking lindens. maybe osgrid - // will fix this someday. - if (llGetListLength(global_names) == 1) { - if (llList2Integer(split, 1) != VERIFY_UNSAFE_DECIDED) - set_click_action(CLICK_ACTION_SIT); - else - // we have a non-local jaunter, so set up for map clicking. - set_click_action(CLICK_ACTION_TOUCH); - } else set_click_action(CLICK_ACTION_TOUCH); - } else if (actyo == AQ_SELECT_DESTINATION) { - integer verif = llList2Integer(split, 1); - // we only switch conveyance mode if we have not been told to - // do the one-way trip or recon. - if (verif == VERIFY_SAFE) conveyance_mode = TWO_WAY_TRIP; - else conveyance_mode = AUTOREZ_JAUNTER; - llSetSitText(sit_text()); // change to the proper text for our mode. - full_journey = [ vector_chop(llGetPos()) ] + chewed_destination(llList2String(split, 0)); - integer last_selecting_index = llList2Integer(action_record, 1); - string destname = llList2String(global_names, last_selecting_index); - llWhisper(0, "Next stop: " + destname); - text_label_for_destination(destname); - last_verification_state = verif; - last_pathway = llList2String(split, 0); - } else if (actyo == AQ_DONE_CONFIGURING) { - // done with notecard reading, but we still need reconnaissance. - // we'll do that in the normal runtime state. - return TRUE; - } - return FALSE; // unknown request or a fall-through. -} - -// asks the data cow for our current set of configured destinations and their -// requisite click actions. -request_destinations() -{ - push_action_record(AQ_CLICK_ACTION_REQUEST, []); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)])); -} - -// processes link messages received from support libraries. -integer handle_link_message(integer which, integer num, string msg, string id) -{ - // is it an answer about our configuration? - if (num == JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE) { - if (msg == JAUNT_CFG_DATA_EVENT) { - // eat these configuration items we were given. - consume_configuration_items(msg, id); - } else if (msg == JAUNT_CFG_EOF) { - // we have finished up on the configuration. - completed_configuration(); - } - return FALSE; - } - - // is it a jaunting library response? - if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { - jaunt_responses_awaited--; // one less response being awaited. - if (jaunt_responses_awaited < 0) { - if (DEBUGGING) log_it("error: j-rsp-awtd<0"); - jaunt_responses_awaited = 0; - } - return FALSE; - } - - // is it an event from the rezolator script? - if (num == JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == REZOLATOR_EVENT_REZZED_CHILD) { - // we know the child is ready for us now. - child_needs_setup = FALSE; -// if (DEBUGGING) log_it("setting journey to rez place " + vector_chop(llGetPos())); - full_journey = [ vector_chop(llGetPos()), llList2String(parms, 0) ]; - if (DEBUGGING) log_it("heard kid is ready, helping."); - request_jaunt(full_journey, TRUE); - eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - } else if (msg == REZOLATOR_EVENT_RECON_FINISHED) { - good_destinations = llList2Integer(parms, 0); - if (DEBUGGING) log_it("recon finished, total=" + llGetListLength(global_names) + " good=" + good_destinations); - request_destinations(); - select_destination(current_target_index); - } - return FALSE; - } - - // is this a menu response from the user? - if (num == MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) { - // all we care about in our parms is the choice made. - react_to_menu(llList2String(llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []), 1)); - return FALSE; - } - // or maybe it's a piece of data from the data cow. - if (num == DATA_COW_HUFFWARE_ID + REPLY_DISTANCE) { - return answer_to_the_cow(msg, id, llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], [])); - } - // perhaps it's a click on a button. - if (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) { - if (msg == BUTTON_PUSHED_ALERT) { - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (llList2String(parms, 0) == JAUNT_NEXT_BUTTON_NAME) { - select_next_destination(); - } else if (llList2String(parms, 0) == JAUNT_MENU_BUTTON_NAME) { - show_jaunt_menu(llList2String(parms, 1)); - } - } - } - - return FALSE; -} - -// make some noise about getting configured right. -completed_configuration() -{ - current_target_index = 0; // set proper index. - get_destination_records(); - - // set up the first destination. - select_destination(current_target_index); - - // schedule the request asking how many destinations there are. - request_destinations(); -/* push_action_record(AQ_CLICK_ACTION_REQUEST, []); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)]));*/ - - // add an item in the queue to actually begin jaunt services. - push_action_record(AQ_DONE_CONFIGURING, []); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)])); -} - -// process what we hear in open chat and on our special channels. -// this function should always return FALSE unless it's been given enough info -// to enter a new state, in which case it should return true. -integer listen_to_voices(integer channel, string name, key id, string message) -{ - if (channel == 0) { - // provide common command handling. - if (message == SHOW_COMMAND) { - // anyone can use this command. - get_destination_records(); - return FALSE; - } - // the rest of the commands only listen to the owner. - if (id != llGetOwner()) return FALSE; - if (message == RESET_COMMAND) llResetScript(); - else if (message == RECON_COMMAND) { - // if they want a recon, we'll do it right away. - recon_started_yet = FALSE; - // we want to reset the rezolator's state, in case it had done this before. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, RESET_REZOLATOR, ""); - llSetTimerEvent(0.4); - } - return FALSE; - } - - return FALSE; // we do not want to go to next state; stay in current one. -} - -// shows our next target for jaunting above the object. -text_label_for_destination(string target) -{ - string msg; - if (SHOW_TEXT) { - if (ADD_NAME) msg += llGetObjectName() + ":\n"; - msg += "↣ " + target; - } - llSetText(msg, (vector)TEXT_COLOR, 1.0); -} - -select_next_destination() -{ - // picks the next place in the list for the destination, or wraps around. - current_target_index++; - if (current_target_index >= llGetListLength(global_names)) - current_target_index = 0; - select_destination(current_target_index); -} - -touchy_feely() -{ - // check the safety of the target and show the map if the conditions are right. - vector check_posn = (vector)llList2String(chewed_destination(last_pathway), 0); -/// if (outside_of_sim(check_posn)) { - /////old && (llGetListLength(global_names) == 1) ) { - // bring up the map; maybe we can't get there from here. definitely out of sim. - llMapDestination(llGetRegionName(), check_posn, ZERO_VECTOR); - proclaim_arrival(); -/// } -} - -// if the string "to_chew" looks like an offset vector, we return the calculated position. -// otherwise we just convert the string to a list of vectors. -list chewed_destination(string dests) -{ - -//hmmm: document this!!! -// as in, we support the offset format! - - // look for our special start character for offsets. - if (is_prefix(dests, "o")) - return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; - -// if (DEBUGGING) log_it("decided for normal jaunt instead."); - // jaunt to list of absolute coordinates. - return llParseString2List(dests, [VECTOR_SEPARATOR], []); -} - -// sets the current destination to the vector at "which_index". -select_destination(integer which_index) -{ - push_action_record(AQ_SELECT_DESTINATION, [which_index]); - llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, - wrap_parameters([OUR_COW_TAG, llList2String(global_names, which_index)])); -} - -// processes the timer events from normal runtime. -handle_normal_runtime_timer() -{ - if (!recon_started_yet) { - if (DEBUGGING) log_it("moving on to recon finally."); - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZ_CHILD_NOW, - wrap_parameters( [llGetInventoryName(INVENTORY_OBJECT, 1), - RECONNAISSANCE_TRIP, private_chat_channel, - "n", // don't care about a particular name. - llGetListLength(global_names), - "n" // no particular path. - ])); - recon_started_yet = TRUE; // well, started really. - } - llSetTimerEvent(0.0); // stop coming here. -} - -////////////// - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -/////////////// - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -// returns TRUE if the "to_check" vector is a location outside of the current sim. -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -// returns text for a floating point number, but includes only -// two digits after the decimal point. -string float_chop(float to_show) -{ - integer mant = llAbs(llRound(to_show * 100.0) / 100); - string neg_sign; - if (to_show < 0.0) neg_sign = "-"; - string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); - dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); - // strip off all trailing zeros. - while (llGetSubString(dec_s, -1, -1) == "0") - dec_s = llDeleteSubString(dec_s, -1, -1); - string to_return = neg_sign + (string)mant; - if (llStringLength(dec_s)) to_return += "." + dec_s; - return to_return; -} - -// returns a prettier form for vector text, with chopped floats. -string vector_chop(vector to_show) -{ - return "<" + float_chop(to_show.x) + "," - + float_chop(to_show.y) + "," - + float_chop(to_show.z) + ">"; -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ - string full_lower = llToLower(full_string); - return llSubStringIndex(full_lower, pattern); -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -////////////// - -// default state scrounges for information in a notecard and looks for landmarks in -// inventory to add as destinations. -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - if (DEBUGGING) log_it("=> default, mem=" + (string)llGetFreeMemory()); - initialize_jaunter(); - } - - timer() { - // config loading timed out. - log_it("config timeout; resetting."); - llResetScript(); - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) { - if (handle_link_message(which, num, msg, id)) { - state normal_runtime; - } - } - - on_rez(integer parm) { state default; } // start-up from scratch. -} - -// the normal state is pretty calm; the jaunter just sits there waiting for -// an avatar who needs it to do something. -state normal_runtime -{ - state_entry() { - if (DEBUGGING) log_it("=> normal"); - init_normal_runtime(); - } - - listen(integer channel, string name, key id, string message) { - if (listen_to_voices(channel, name, id, message)) { - // we're ready to take off now. - state jaunting_now; - } - } - - timer() { handle_normal_runtime_timer(); } - - touch_end(integer total_number) - { - if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; - touchy_feely(); - } - - changed(integer change) { - // always react to a change by resetting the label, in hopes we'll see - // the targeting arrow properly. - string destname = llList2String(global_names, current_target_index); - text_label_for_destination(destname); - // now do our 'real' activities for changes. - if (change & CHANGED_INVENTORY) { - log_it("inventory changed; restarting."); - llResetScript(); - } - if (!(change & CHANGED_LINK)) return; // don't care then. - if (llAvatarOnSitTarget() == NULL_KEY) return; // there is no one sitting now. - state jaunting_now; // sweet, we're off. - } - - // process the response from the menu library. - link_message(integer which, integer num, string msg, key id) { - handle_link_message(which, num, msg, id); - } - - on_rez(integer parm) { state default; } // start-up from scratch. -} - -// once someone is trying to jump to a target, this state processes the request. -state jaunting_now -{ - state_entry() { - if (DEBUGGING) log_it("=> jauntnow, posn=" + vector_chop(llGetPos())); - jaunt_responses_awaited = 0; // nothing pending right now. - slackness_counter = 0; - if (conveyance_mode == AUTOREZ_JAUNTER) { - // we're going to create a kid, so we will not change state until we hear from it. - child_needs_setup = TRUE; - // give the person a vehicle to ride to the unsafe locale. we assume the - // one way jaunter is the first inventory item. - llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZ_CHILD_NOW, - wrap_parameters([llGetInventoryName(INVENTORY_OBJECT, 0), - ONE_WAY_TRIP, private_chat_channel, - llList2String(global_names, current_target_index), - llGetListLength(global_names), - llDumpList2String(full_journey, VECTOR_SEPARATOR) ])); - } else { -// if (DEBUGGING) log_it("now going to first locat: " + (string)full_journey); - // patch the journey list for our most current location. - full_journey = [ vector_chop(llGetPos()) ] + llDeleteSubList(full_journey, 0, 0); - - // most jaunters go to at least the first location... - request_jaunt(full_journey, TRUE); - eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - } - } - - listen(integer channel, string name, key id, string message) { - listen_to_voices(channel, name, id, message); - } - - timer() { - if (jaunt_responses_awaited || child_needs_setup) { - // we are not quite there yet. - if (check_for_timeout()) state normal_runtime; // oops. - return; // not time yet. - } - // we got to where we were going, maybe. - // now unseat the avatar. this leaves her at the destination. - llUnSit(llAvatarOnSitTarget()); - state arrived_at_target; - } - - // process the response from the jaunting library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - on_rez(integer parm) { state default; } // start-up from scratch. -} - -// this state is activated when the first jaunt is complete. -state arrived_at_target -{ - state_entry() { - if (DEBUGGING) log_it("=> arv_targ, pos=" + vector_chop(llGetPos())); - // we are close enough; get back to work. - jaunt_responses_awaited = 0; // nothing pending right now. - if ( ///(conveyance_mode != RECONNAISSANCE_TRIP) && - (conveyance_mode != AUTOREZ_JAUNTER) ) - llWhisper(0, "↣ " + llList2String(global_names, current_target_index)); - - // we've gotten where we were going. - proclaim_arrival(); - - // reverse direction and head back without rider. - eventual_destination = (vector)llList2String(full_journey, 0); - request_jaunt(full_journey, FALSE); - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - slackness_counter = 0; - } - - timer() { - if (jaunt_responses_awaited) { - // we are not quite there yet. - if (check_for_timeout()) state normal_runtime; // oops. - return; // not time yet. - } - if (!close_enough(eventual_destination)) - log_it("far away, path okay?"); - state normal_runtime; - } - - // process the response from the jaunting library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - on_rez(integer parm) { state default; } // start-up from scratch. -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.txt b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.txt new file mode 100755 index 00000000..f8273c1d --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/jaunt_wik_rez_v86.3.txt @@ -0,0 +1,1205 @@ + +// huffware script: jaunt wik rez, by fred huffhines, released under GPL license. +// +// this is a jaunter (teleporter) script with some useful and uncommon features. +// it can work around certain types of complicated land permissions on neighboring land +// that might otherwise lead to blocked jaunts. +// the usage of "jaunt" for teleportation is inspired by the alfred bester novel, "the stars +// my destination". if you like science fiction and have not read this book, it is highly +// recommended. +// parts of this script are based on "Teleporter Script v 3.0 by Asira Sakai", from +// the LSL wiki. +// +// use jaunt wik rez by placing a notecard in the inventory of your jaunter object. the notecard +// should start with "#jaunt" on the first line and then should have alternating lines of +// (1) jaunt target (as a vector) and (2) readable target name, for example: +// #jaunt +// <23, 18, 92> +// gracy square +// <182, 32, 56> +// tourmaline palace +// <23, 18, 92>|<118, 19, 108>|<120, 33, 57> +// unblocked pathway, hurrah +// note the last destination; the script also supports a list of intermediate destinations. +// this feature can enable one to route a teleport around blocked lands by using waypoints +// that are still accessible. but since the current version of the script automatically +// finds routes for most destinations, this is not needed very frequently. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +integer DEBUGGING = FALSE; + // make true to print diagnostic logging. + +// configurable options (set in notecard): + +integer SHOW_TEXT = TRUE; + // if true, then the jaunter will show a text label for the destination. + // this can be configured from the notecard with ":show_text=0" to turn off, + // or 1 to turn on. +integer ADD_NAME = FALSE; + // if this is true, then the text shown will include the object's name. + +string TEXT_COLOR = "<0.3, 0.9, 0.7>"; + // set float text color to a nice color. +///hmmm: doesn't seem to be in the notecard yet! + +////////////// + +// the jaunter button pushing API. +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10029; + // a unique ID within the huffware system for this script. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was +string JAUNT_NEXT_BUTTON_NAME = "next"; +string JAUNT_MENU_BUTTON_NAME = "menu"; + +////////////// + +// requires the jaunt config API. +////////////// +// do not redefine these constants. +integer JAUNT_CONFIGURATION_HUFFWARE_ID = 10022; + // the unique id within the huffware system for this script's commands. + // it's used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available from the jaunt config library: +string LOAD_ALL_CONFIGURATIONS = "#rdcfg#"; + // this starts the process of loading jaunt destinations from the notecards and + // landmarks that we find in the object. the parms are: private channel + // and conveyance mode. +string JAUNT_CFG_DATA_EVENT = "#yodata#"; + // this event is generated from this script back to the caller. when we have some + // landmark data or configuration information, it's passed back in chunks. the + // deluge of pieces will continue until the JAUNT_CFG_EOF event is passed. the + // parameters include packed destination name and vector pairs (which form 2 elements + // in the list) and packed config variable definitions (where config items start + // with a colon, and the definition is only one element in the list). +string JAUNT_CFG_EOF = "#done#"; + // sent after all valid configuration items that we could find were processed. +// +////////////// + +// requires jaunting library API. +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +// commands available via the jaunting library: +string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a string in jaunt notecard format with vectors. + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// + +// requires menutini API. +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. + +// requires data cow library API. +////////////// +// do not redefine these constants. +integer DATA_COW_HUFFWARE_ID = 10017; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +////////////// +string RESET_LIST_COMMAND = "reset_L"; + // flushes out the currently held list. does not send a reply. +string ADD_ITEM_COMMAND = "add_I"; + // adds items to the list. this is a list of pairs of name/value, where the name is + // how the item will be looked up from the list, and the value is the contents to be stored. + // this command has no reply. +string GET_COW_LENGTH = "get_Lc"; + // returns a single integer which is the length of the cow's list currently. +//string REMOVE_ITEM_COMMAND = "rm_I"; + // accepts a list of names for items. all the mentioned ones will be removed from the list. + // this command also has no reply. +//string GET_ITEM_COMMAND = "get_I"; + // retrieves the item's contents for a given name. first parm is the name. if there + // are other parameters, then they are taken as other items to return also. + // the return data will be pairs of for each of the names in the request. + // if the data was not located, then the entry will be empty. +string TAGGED_GET_ITEM_COMMAND = "get_T"; + // like get item, except the first parameter is an identifier that the caller wants to + // use to tag this request. the other parameters are still taken as names. the response + // will contain the tag as the first item, then the pairs that were found. + +////////////// + +// requires click action API... +////////////// +integer CHANGE_CLICK_ACTION_HUFFWARE_ID = 10024; + // a unique ID within the huffware system for this script. +// the API only supports the service number; there are no commands to pass in the "msg" +// parameter. the id does accept a parameter, which is the type of click action to begin +// using for this prim. +////////////// + +// the API for this library script to be used in other scripts. +////////////// +// do not redefine these constants. +integer JAUNT_REZOLATOR_HUFFWARE_ID = 10025; + // the unique id within the huffware system for this script's commands. + // it's used in llMessageLinked as the num parameter. +////////////// +// commands available from the library: +string RESET_REZOLATOR = "#reset"; + // tells the script to stop any previous efforts to rez children. +string REZ_CHILD_NOW = "#rezkd#"; + // requests this script to create a new child object. this requires several + // parameters to succeed: 1) object to rez, 2) conveyance mode for the rezzed object + // to implement, 3) the chat channel to listen for and speak to new child on, + // 4) the destination name for where the child should go, 5) a count of the full + // set of known destinations, 6) the target where the jaunt should arrive at. +////////////// +// events generated by the library: +string REZOLATOR_EVENT_REZZED_CHILD = "#donekd"; + // an event generated for a previous rez child request. this lets the caller know that + // the child has been created and told what to do. the single parameter is where the + // jaunter has been rezzed. +string REZOLATOR_EVENT_RECON_FINISHED = "#rzcnfn"; + // an event generated when the recon process has concluded. this includes parms: + // number of good destinations. +// +////////////// + +// important constants used internally... these should not be changed willy nilly. + +////////////// jaunt base API + +// the following constants define how the script should behave (i.e., its conveyance mode). +// TWO_WAY_TRIP: the script jaunts using the current target vectors to get somewhere +// and then takes the same pathway back, but in reverse order. +// AUTOREZ_JAUNTER: the script rezzes the first regular object in its inventory next to +// the root telehub. that object is loaded with the destination notecard and this script. +// the rezzed object can then be used for the next few minutes to jaunt to the selected +// destination. the temporary object will use the ONE_WAY_TRIP mode. +// ONE_WAY_TRIP: the object containing this script will take the user to a particular +// destination, but the object does not survive the trip. it self-destructs after +// reaching the destination. this mode is used in conjunction with the AUTOREZ_JAUNTER +// mode and should generally never be used on its own. +// RECONNAISSANCE_TRIP: a survey run to test out a particular path to get to a +// destination. +integer TWO_WAY_TRIP = 1; +integer AUTOREZ_JAUNTER = 2; +integer ONE_WAY_TRIP = 3; +integer RECONNAISSANCE_TRIP = 4; + +// values used to represent different stages of verification. +integer VERIFY_UNTESTED = -3; // don't know destinations state yet. +integer VERIFY_SAFE = -4; // the destination last tested safe. +integer VERIFY_UNSAFE_SO_FAR = -5; // this cannot be done with simple jaunt. +integer VERIFY_UNSAFE_DECIDED = -6; // this means the destination seems intractable. + +integer MAXIMUM_PRIV_CHAN = 90000; + // the largest amount we will ever subtract from the tricky parms in order to + // tell the sub-jaunter which channel to listen on. + +string VECTOR_SEPARATOR = "|"; + // how we separate components of vectors from each other. +string DB_SEPARATOR = "``"; // separating items in lists. + +////////////// end jaunt base API + +integer MAX_DEST_NAME = 24; // the longest name that we store. + +float NORMAL_TIMER_PERIOD = 1.0; // our normal timer rate. + +string RESET_COMMAND = "jreset"; // forget everything and start over. +string SHOW_COMMAND = "show"; // describe the known destinations. +string RECON_COMMAND = "recon"; // tells the jaunter to run reconnaissance on destinations. + +float POSITION_CHECKING_INTERVAL = 0.11; + // how frequently the waiting for arrival state will check where we are. + +integer MAXIMUM_SLACKNESS = 108; + // how many timer hits we'll allow before reverting to the default state. + +integer FREE_MEM_REQUIRED = 1600; + // we need at least this much memory before adding new targets. + +// somewhere between two and 10 minutes (default) will elapse before first recon testing. +float MIN_RECON_SNOOZE = 120; +float MAX_RECON_SNOOZE = 1200; + +// the actions that can be held in the action queue. +integer AQ_SHOW_DEST_RECORD = 23; // a record to be shown to the user. +integer AQ_FINISH_SHOW_DESTS = 24; // last record in a jaunt destinations list. +integer AQ_CLICK_ACTION_REQUEST = 25; // the response should set our click action. +integer AQ_SELECT_DESTINATION = 27; // the user has chosen a different destination. +integer AQ_DONE_CONFIGURING = 28; // the last step of the configuration process has finished. + +string OUR_COW_TAG = "jwkrz_dc"; // unique id for this script to talk to the data cow with. + +////////////// + +// global variables. + +integer private_chat_channel; // where sub-jaunters communicate with root. +integer conveyance_mode; /// = TWO_WAY_TRIP; + // default is a standard two way trip, there and back again. note that the object + // will fail to return if any lands in between are blocking object entry. those + // situations should use an auto-rez jaunter, which is specified by prefixing the + // target vectors with AR. +integer last_verification_state; // the verification state of the last destination we asked for. +string last_pathway; // similar, but the last pathway we heard. +integer current_target_index; // the location in the list that we would currently jaunt to. + +integer good_destinations; // computed during the recon process. + +// jaunter target configuration... +list global_names; // the names for each destination. + +// jaunt trip variables... +vector eventual_destination; // where we're headed, if we're headed anywhere. +integer slackness_counter; // snoozes had while waiting for destination. +list full_journey; // the full pathway we expect to jaunt on. +integer jaunt_responses_awaited; // number of pending jumps in progress. + +// root jaunter variables... +integer child_needs_setup; + // true when a child has been rezzed and still needs to be filled with the script. + +integer recon_started_yet = FALSE; + // true if we've finished running through the reconnaissance process yet. + +////////////// + +// makes our click action change to the type requested, and sends the request +// out to all our sub-prims also. +set_click_action(integer action) +{ + llSetClickAction(action); + // secret message to other prims to change click action. + llMessageLinked(LINK_SET, CHANGE_CLICK_ACTION_HUFFWARE_ID, "", (string)action); +} + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +// show the list of options for someone who used the click-hold feature. +show_jaunt_menu(key last_toucher) +{ + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + "jm" + HUFFWARE_PARM_SEPARATOR + + "Jaunt to..." + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(global_names) + + HUFFWARE_PARM_SEPARATOR + + (string)random_channel() + HUFFWARE_PARM_SEPARATOR + + (string)last_toucher); +} + +// respond to the user's choice. +react_to_menu(string which_choice) +{ + integer indy; + // find the specified destination and select it. + indy = llListFindList(global_names, [which_choice]); + if (indy >= 0) { + current_target_index = indy; + select_destination(current_target_index); + } +} + +// asks the jaunting library to take us to the target using a list of waypoints. +request_jaunt(list journey, integer forwards) +{ + // ask for a jump. + jaunt_responses_awaited++; + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, + wrap_item_list(journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); + // stops the jaunter in its tracks. + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, FULL_STOP_COMMAND, ""); +} + +// this function returns TRUE if we are close enough to the "destination". +integer close_enough(vector destination) +{ + float PROXIMITY_REQUIRED = 0.1; + // how close we must be to the target location to call it done. + // matches current jaunting library proximity. + return (llVecDist(llGetPos(), destination) <= PROXIMITY_REQUIRED); +} + +// returns appropriate sit text for our current jaunt mode. +string sit_text() +{ + if (conveyance_mode == AUTOREZ_JAUNTER) return "Rez Ride"; + return "Jaunt"; +} + +// plops a new destination on the end of the lists. +add_destination(string name, string path, integer verif) +{ +// if (DEBUGGING) log_it("adding " + name + " with path " + path); + global_names += [ name ]; + // send our new information to the data cow. we store the information encoded as + // two separated items, where the first element is the destination and the second + // is the verification state. + string new_entry = wrap_item_list([path, verif]); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, ADD_ITEM_COMMAND, + wrap_parameters([name, new_entry])); +} + +// sets up the initial state, if this script has just started, or it +// cleans up the state, if the script was already running. +initialize_jaunter() +{ + llSetTimerEvent(0.0); // cancel any existing timers. + + // reset all the important variables. + global_names = []; + current_target_index = 0; + good_destinations = 0; + + llSitTarget(<0, 0, 0.1>, ZERO_ROTATION); + // set a rudimentary sit target or opensim won't give us our changed events. + // load up an arrival sound if any exist. + if (llGetInventoryNumber(INVENTORY_SOUND)) + llPreloadSound(llGetInventoryName(INVENTORY_SOUND, 0)); + // reset the parallel processing scripts since we've restarted. + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, RESET_LIST_COMMAND, ""); + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, RESET_REZOLATOR, ""); + + // see if we can load our configuration from notecards and landmarks. + // we pick a private channel that fits in between our rez parm ranges. + private_chat_channel = (integer)randomize_within_range(-MAXIMUM_PRIV_CHAN, -1, FALSE); + // request that all the config get loaded up. + llMessageLinked(LINK_THIS, JAUNT_CONFIGURATION_HUFFWARE_ID, LOAD_ALL_CONFIGURATIONS, + wrap_parameters([private_chat_channel, conveyance_mode])); + // during a normal trip, we will make sure the notecard reading doesn't stall. + // the recon and one way jaunters don't need this; they're temporary. + // we allow this number of seconds before notecard reader is awol. + llSetTimerEvent(94); + + conveyance_mode = TWO_WAY_TRIP; // default init in opensim friendly way. + + // set up some of the object properties... + string msg; + if (SHOW_TEXT) msg = "?..."; + llSetText(msg, (vector)TEXT_COLOR, 1.0); // initial floating text for jaunter. + llSetSitText(sit_text()); // change to the proper text for our mode. +} + +init_normal_runtime() +{ + child_needs_setup = FALSE; + // listen to the general public for commands. + llListen(0, "", NULL_KEY, ""); + // set up a root jaunter. + recon_started_yet = FALSE; + llSetTimerEvent(randomize_within_range(MIN_RECON_SNOOZE, MAX_RECON_SNOOZE, FALSE)); +} + +// signal that we are where we were going. +proclaim_arrival() +{ + if (conveyance_mode == TWO_WAY_TRIP) { + // sing a little song, if there's a sound to use. + if (llGetInventoryNumber(INVENTORY_SOUND)) + llTriggerSound(llGetInventoryName(INVENTORY_SOUND, 0), 1.0); + } +} + +string verification_name(integer enumtype) +{ + if (enumtype == VERIFY_SAFE) return "ok"; + else if (enumtype == VERIFY_UNSAFE_SO_FAR) return "uhh"; + else if (enumtype == VERIFY_UNSAFE_DECIDED) return "far"; + // catch-all, including untested. + return "?"; +} + +// returns true if the slackness counter awaiting things has elapsed. +integer check_for_timeout() +{ + if (slackness_counter++ > MAXIMUM_SLACKNESS) { + // go back to the main state. we took too long. + log_it("timed out!"); + llUnSit(llAvatarOnSitTarget()); // don't hang onto the avatar for this error. + llSetTimerEvent(0.0); + return TRUE; + } + return FALSE; +} + +////////////// + +// action queue for postponed activities. the first field held in a list item here +// is an integer action code. the format of the remaining parameters is up to the +// caller, and they can be used as the final parameters for when the queued action +// gets handled. +list action_queue; + +// looks at the action code at the head of the queue without removing the action. +integer peek_action_code() +{ + list fields = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + return extract_action_code(fields); +} + +// extracts the action code from a retrieved list. +integer extract_action_code(list to_parse) { return llList2Integer(to_parse, 0); } + +// removes the current head of the action queue and returns it. +list pop_action_record() +{ + if (llGetListLength(action_queue) == 0) { +// if (DEBUGGING) log_it("failure in action q: no entries."); + return []; + } + list top_action = llParseString2List(llList2String(action_queue, 0), [HUFFWARE_PARM_SEPARATOR], []); + action_queue = llDeleteSubList(action_queue, 0, 0); + jaunt_responses_awaited--; // one less thing to wait for. + return top_action; +} + +// adds a new action to the end of the action queue. +push_action_record(integer action, list added_parms) +{ + action_queue += [ wrap_parameters([action] + added_parms) ]; + jaunt_responses_awaited++; // add one counter to our pending responses. +} + +////////////// + +string show_buffer; // used by the destination list showing code below. + +// requests a dump of all the jaunt destinations so we can show them to the user. +get_destination_records() +{ + show_buffer = "[mem " + (string)llGetFreeMemory() + "]"; // set the first line in the output. + + integer indy; + for (indy = 0; indy < llGetListLength(global_names); indy++) { + string curr = llList2String(global_names, indy); + // ask for this destination record. + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, curr])); + integer action = AQ_SHOW_DEST_RECORD; + if (indy == llGetListLength(global_names) - 1) { + // if it's the last item, make sure we signal that. + action = AQ_FINISH_SHOW_DESTS; + } + push_action_record(action, []); + } +} + +// displays the list of destinations in normal chat that the data cow is handing us. +show_destination_record(string loc_name, string pathway, integer verif, integer action) +{ + integer MAX_CHAT = 512; // the largest we let the buffer get before saying it. + show_buffer += " " + loc_name + " (" + + verification_name(verif) + ") ↣ " + pathway; + // if we're done, add a note about quality of targets. + if (action == AQ_FINISH_SHOW_DESTS) { + show_buffer += "\n (" + (string)good_destinations + " safe & " + + (string)(llGetListLength(global_names) - good_destinations) + + " tough ones)"; + } + + // if we're done or if the string gets too big, print and reset it. + if ( (action == AQ_FINISH_SHOW_DESTS) || (llStringLength(show_buffer) >= MAX_CHAT) ) { + llWhisper(0, show_buffer); + show_buffer = ""; + } +} + +// returns the value of a boolean variable definition. +integer parse_bool_def(string def) +{ return !(llGetSubString(def, find_substring(def, "=") + 1, -1) == "0"); } + +// processes a configuration option from the notecard. +handle_config_item(string item) +{ + item = llGetSubString(item, 1, -1); // chop the command signifier character. + if (is_prefix(item, "show_text")) { + // they are controlling whether to show the text label or not. + SHOW_TEXT = parse_bool_def(item); + } else if (is_prefix(item, "add_name")) { + ADD_NAME = parse_bool_def(item); + } +} + +// processes items coming from the configuration library. +consume_configuration_items(string msg, string id) +{ + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + integer mem_okay = llGetFreeMemory() >= FREE_MEM_REQUIRED; // false if we're low on memory. + if (!mem_okay) return; + integer indy; + for (indy = 0; indy < llGetListLength(parms); indy += 2) { + string name = llList2String(parms, indy); + if (is_prefix(name, ":")) { + handle_config_item(name); + indy--; // skip back so we continue looking for destinations. + } else { + // this should be a normal pair of destination vector and name. + integer verif_state = VERIFY_UNTESTED; + // check if it's a wacky location. + string map_coord = llList2String(parms, indy + 1); + list chewed = chewed_destination(map_coord); + if (outside_of_sim((vector)llList2String(chewed, 0))) { + if (DEBUGGING) log_it("ruled map_coor " + (string)map_coord + " out of sim."); + // make sure we consider the tp location "unsafe", since we can't run in-sim + // reconnaissance against it. also, we must postpone marking it until + // the destination is listed, given current implementation. + verif_state = VERIFY_UNSAFE_DECIDED; + } + add_destination(name, llList2String(parms, indy + 1), verif_state); + } + } +} + +// handles responses about our list coming back from the data cow. +integer answer_to_the_cow(string msg, string id, list parms) +{ + string tag = llList2String(parms, 0); + if (tag != OUR_COW_TAG) return FALSE; // was not for us. + parms = llDeleteSubList(parms, 0, 0); // trim out the tag. + list action_record = pop_action_record(); + integer actyo = extract_action_code(action_record); + list split = llParseString2List(llList2String(parms, 1), [HUFFWARE_ITEM_SEPARATOR], []); + if ( (actyo == AQ_SHOW_DEST_RECORD) || (actyo == AQ_FINISH_SHOW_DESTS) ) { + show_destination_record(llList2String(parms, 0), llList2String(split, 0), + llList2Integer(split, 1), actyo); + } else if (actyo == AQ_CLICK_ACTION_REQUEST) { + // make sure we're in the right mode for clicking based on how + // many destinations we have. if there's only one, we might as + // well make this jaunter just go there. + // note: just discovered that we cannot set the click action if the jaunter + // is multiple prims. that's totally fubar. it means we cannot correctly + // set the jaunter main body to show 'sit' as the option, even when jaunting + // directly to the destination is possible. freaking lindens. maybe osgrid + // will fix this someday. + if (llGetListLength(global_names) == 1) { + if (llList2Integer(split, 1) != VERIFY_UNSAFE_DECIDED) + set_click_action(CLICK_ACTION_SIT); + else + // we have a non-local jaunter, so set up for map clicking. + set_click_action(CLICK_ACTION_TOUCH); + } else set_click_action(CLICK_ACTION_TOUCH); + } else if (actyo == AQ_SELECT_DESTINATION) { + integer verif = llList2Integer(split, 1); + // we only switch conveyance mode if we have not been told to + // do the one-way trip or recon. + if (verif == VERIFY_SAFE) conveyance_mode = TWO_WAY_TRIP; + else conveyance_mode = AUTOREZ_JAUNTER; + llSetSitText(sit_text()); // change to the proper text for our mode. + full_journey = [ vector_chop(llGetPos()) ] + chewed_destination(llList2String(split, 0)); + integer last_selecting_index = llList2Integer(action_record, 1); + string destname = llList2String(global_names, last_selecting_index); + llWhisper(0, "Next stop: " + destname); + text_label_for_destination(destname); + last_verification_state = verif; + last_pathway = llList2String(split, 0); + } else if (actyo == AQ_DONE_CONFIGURING) { + // done with notecard reading, but we still need reconnaissance. + // we'll do that in the normal runtime state. + return TRUE; + } + return FALSE; // unknown request or a fall-through. +} + +// asks the data cow for our current set of configured destinations and their +// requisite click actions. +request_destinations() +{ + push_action_record(AQ_CLICK_ACTION_REQUEST, []); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)])); +} + +// processes link messages received from support libraries. +integer handle_link_message(integer which, integer num, string msg, string id) +{ + // is it an answer about our configuration? + if (num == JAUNT_CONFIGURATION_HUFFWARE_ID + REPLY_DISTANCE) { + if (msg == JAUNT_CFG_DATA_EVENT) { + // eat these configuration items we were given. + consume_configuration_items(msg, id); + } else if (msg == JAUNT_CFG_EOF) { + // we have finished up on the configuration. + completed_configuration(); + } + return FALSE; + } + + // is it a jaunting library response? + if (num == JAUNT_HUFFWARE_ID + REPLY_DISTANCE) { + jaunt_responses_awaited--; // one less response being awaited. + if (jaunt_responses_awaited < 0) { + if (DEBUGGING) log_it("error: j-rsp-awtd<0"); + jaunt_responses_awaited = 0; + } + return FALSE; + } + + // is it an event from the rezolator script? + if (num == JAUNT_REZOLATOR_HUFFWARE_ID + REPLY_DISTANCE) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == REZOLATOR_EVENT_REZZED_CHILD) { + // we know the child is ready for us now. + child_needs_setup = FALSE; +// if (DEBUGGING) log_it("setting journey to rez place " + vector_chop(llGetPos())); + full_journey = [ vector_chop(llGetPos()), llList2String(parms, 0) ]; + if (DEBUGGING) log_it("heard kid is ready, helping."); + request_jaunt(full_journey, TRUE); + eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + } else if (msg == REZOLATOR_EVENT_RECON_FINISHED) { + good_destinations = llList2Integer(parms, 0); + if (DEBUGGING) log_it("recon finished, total=" + llGetListLength(global_names) + " good=" + good_destinations); + request_destinations(); + select_destination(current_target_index); + } + return FALSE; + } + + // is this a menu response from the user? + if (num == MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) { + // all we care about in our parms is the choice made. + react_to_menu(llList2String(llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []), 1)); + return FALSE; + } + // or maybe it's a piece of data from the data cow. + if (num == DATA_COW_HUFFWARE_ID + REPLY_DISTANCE) { + return answer_to_the_cow(msg, id, llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], [])); + } + // perhaps it's a click on a button. + if (num == BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE) { + if (msg == BUTTON_PUSHED_ALERT) { + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (llList2String(parms, 0) == JAUNT_NEXT_BUTTON_NAME) { + select_next_destination(); + } else if (llList2String(parms, 0) == JAUNT_MENU_BUTTON_NAME) { + show_jaunt_menu(llList2String(parms, 1)); + } + } + } + + return FALSE; +} + +// make some noise about getting configured right. +completed_configuration() +{ + current_target_index = 0; // set proper index. + get_destination_records(); + + // set up the first destination. + select_destination(current_target_index); + + // schedule the request asking how many destinations there are. + request_destinations(); +/* push_action_record(AQ_CLICK_ACTION_REQUEST, []); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)]));*/ + + // add an item in the queue to actually begin jaunt services. + push_action_record(AQ_DONE_CONFIGURING, []); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, llList2String(global_names, 0)])); +} + +// process what we hear in open chat and on our special channels. +// this function should always return FALSE unless it's been given enough info +// to enter a new state, in which case it should return true. +integer listen_to_voices(integer channel, string name, key id, string message) +{ + if (channel == 0) { + // provide common command handling. + if (message == SHOW_COMMAND) { + // anyone can use this command. + get_destination_records(); + return FALSE; + } + // the rest of the commands only listen to the owner. + if (id != llGetOwner()) return FALSE; + if (message == RESET_COMMAND) llResetScript(); + else if (message == RECON_COMMAND) { + // if they want a recon, we'll do it right away. + recon_started_yet = FALSE; + // we want to reset the rezolator's state, in case it had done this before. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, RESET_REZOLATOR, ""); + llSetTimerEvent(0.4); + } + return FALSE; + } + + return FALSE; // we do not want to go to next state; stay in current one. +} + +// shows our next target for jaunting above the object. +text_label_for_destination(string target) +{ + string msg; + if (SHOW_TEXT) { + if (ADD_NAME) msg += llGetObjectName() + ":\n"; + msg += "↣ " + target; + } + llSetText(msg, (vector)TEXT_COLOR, 1.0); +} + +select_next_destination() +{ + // picks the next place in the list for the destination, or wraps around. + current_target_index++; + if (current_target_index >= llGetListLength(global_names)) + current_target_index = 0; + select_destination(current_target_index); +} + +touchy_feely() +{ + // check the safety of the target and show the map if the conditions are right. + vector check_posn = (vector)llList2String(chewed_destination(last_pathway), 0); +/// if (outside_of_sim(check_posn)) { + /////old && (llGetListLength(global_names) == 1) ) { + // bring up the map; maybe we can't get there from here. definitely out of sim. + llMapDestination(llGetRegionName(), check_posn, ZERO_VECTOR); + proclaim_arrival(); +/// } +} + +// if the string "to_chew" looks like an offset vector, we return the calculated position. +// otherwise we just convert the string to a list of vectors. +list chewed_destination(string dests) +{ + +//hmmm: document this!!! +// as in, we support the offset format! + + // look for our special start character for offsets. + if (is_prefix(dests, "o")) + return [ (vector)llDeleteSubString(dests, 0, find_substring(dests, "<") - 1) + llGetPos() ]; + +// if (DEBUGGING) log_it("decided for normal jaunt instead."); + // jaunt to list of absolute coordinates. + return llParseString2List(dests, [VECTOR_SEPARATOR], []); +} + +// sets the current destination to the vector at "which_index". +select_destination(integer which_index) +{ + push_action_record(AQ_SELECT_DESTINATION, [which_index]); + llMessageLinked(LINK_THIS, DATA_COW_HUFFWARE_ID, TAGGED_GET_ITEM_COMMAND, + wrap_parameters([OUR_COW_TAG, llList2String(global_names, which_index)])); +} + +// processes the timer events from normal runtime. +handle_normal_runtime_timer() +{ + if (!recon_started_yet) { + if (DEBUGGING) log_it("moving on to recon finally."); + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZ_CHILD_NOW, + wrap_parameters( [llGetInventoryName(INVENTORY_OBJECT, 1), + RECONNAISSANCE_TRIP, private_chat_channel, + "n", // don't care about a particular name. + llGetListLength(global_names), + "n" // no particular path. + ])); + recon_started_yet = TRUE; // well, started really. + } + llSetTimerEvent(0.0); // stop coming here. +} + +////////////// + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +/////////////// + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +// returns TRUE if the "to_check" vector is a location outside of the current sim. +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +// returns text for a floating point number, but includes only +// two digits after the decimal point. +string float_chop(float to_show) +{ + integer mant = llAbs(llRound(to_show * 100.0) / 100); + string neg_sign; + if (to_show < 0.0) neg_sign = "-"; + string dec_s = (string)((llRound(to_show * 100.0) - mant * 100) / 100.0); + dec_s = llGetSubString(llGetSubString(dec_s, find_substring(dec_s, ".") + 1, -1), 0, 2); + // strip off all trailing zeros. + while (llGetSubString(dec_s, -1, -1) == "0") + dec_s = llDeleteSubString(dec_s, -1, -1); + string to_return = neg_sign + (string)mant; + if (llStringLength(dec_s)) to_return += "." + dec_s; + return to_return; +} + +// returns a prettier form for vector text, with chopped floats. +string vector_chop(vector to_show) +{ + return "<" + float_chop(to_show.x) + "," + + float_chop(to_show.y) + "," + + float_chop(to_show.z) + ">"; +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ + string full_lower = llToLower(full_string); + return llSubStringIndex(full_lower, pattern); +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +////////////// + +// default state scrounges for information in a notecard and looks for landmarks in +// inventory to add as destinations. +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + if (DEBUGGING) log_it("=> default, mem=" + (string)llGetFreeMemory()); + initialize_jaunter(); + } + + timer() { + // config loading timed out. + log_it("config timeout; resetting."); + llResetScript(); + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) { + if (handle_link_message(which, num, msg, id)) { + state normal_runtime; + } + } + + on_rez(integer parm) { state default; } // start-up from scratch. +} + +// the normal state is pretty calm; the jaunter just sits there waiting for +// an avatar who needs it to do something. +state normal_runtime +{ + state_entry() { + if (DEBUGGING) log_it("=> normal"); + init_normal_runtime(); + } + + listen(integer channel, string name, key id, string message) { + if (listen_to_voices(channel, name, id, message)) { + // we're ready to take off now. + state jaunting_now; + } + } + + timer() { handle_normal_runtime_timer(); } + + touch_end(integer total_number) + { + if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; + touchy_feely(); + } + + changed(integer change) { + // always react to a change by resetting the label, in hopes we'll see + // the targeting arrow properly. + string destname = llList2String(global_names, current_target_index); + text_label_for_destination(destname); + // now do our 'real' activities for changes. + if (change & CHANGED_INVENTORY) { + log_it("inventory changed; restarting."); + llResetScript(); + } + if (!(change & CHANGED_LINK)) return; // don't care then. + if (llAvatarOnSitTarget() == NULL_KEY) return; // there is no one sitting now. + state jaunting_now; // sweet, we're off. + } + + // process the response from the menu library. + link_message(integer which, integer num, string msg, key id) { + handle_link_message(which, num, msg, id); + } + + on_rez(integer parm) { state default; } // start-up from scratch. +} + +// once someone is trying to jump to a target, this state processes the request. +state jaunting_now +{ + state_entry() { + if (DEBUGGING) log_it("=> jauntnow, posn=" + vector_chop(llGetPos())); + jaunt_responses_awaited = 0; // nothing pending right now. + slackness_counter = 0; + if (conveyance_mode == AUTOREZ_JAUNTER) { + // we're going to create a kid, so we will not change state until we hear from it. + child_needs_setup = TRUE; + // give the person a vehicle to ride to the unsafe locale. we assume the + // one way jaunter is the first inventory item. + llMessageLinked(LINK_THIS, JAUNT_REZOLATOR_HUFFWARE_ID, REZ_CHILD_NOW, + wrap_parameters([llGetInventoryName(INVENTORY_OBJECT, 0), + ONE_WAY_TRIP, private_chat_channel, + llList2String(global_names, current_target_index), + llGetListLength(global_names), + llDumpList2String(full_journey, VECTOR_SEPARATOR) ])); + } else { +// if (DEBUGGING) log_it("now going to first locat: " + (string)full_journey); + // patch the journey list for our most current location. + full_journey = [ vector_chop(llGetPos()) ] + llDeleteSubList(full_journey, 0, 0); + + // most jaunters go to at least the first location... + request_jaunt(full_journey, TRUE); + eventual_destination = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + } + } + + listen(integer channel, string name, key id, string message) { + listen_to_voices(channel, name, id, message); + } + + timer() { + if (jaunt_responses_awaited || child_needs_setup) { + // we are not quite there yet. + if (check_for_timeout()) state normal_runtime; // oops. + return; // not time yet. + } + // we got to where we were going, maybe. + // now unseat the avatar. this leaves her at the destination. + llUnSit(llAvatarOnSitTarget()); + state arrived_at_target; + } + + // process the response from the jaunting library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + on_rez(integer parm) { state default; } // start-up from scratch. +} + +// this state is activated when the first jaunt is complete. +state arrived_at_target +{ + state_entry() { + if (DEBUGGING) log_it("=> arv_targ, pos=" + vector_chop(llGetPos())); + // we are close enough; get back to work. + jaunt_responses_awaited = 0; // nothing pending right now. + if ( ///(conveyance_mode != RECONNAISSANCE_TRIP) && + (conveyance_mode != AUTOREZ_JAUNTER) ) + llWhisper(0, "↣ " + llList2String(global_names, current_target_index)); + + // we've gotten where we were going. + proclaim_arrival(); + + // reverse direction and head back without rider. + eventual_destination = (vector)llList2String(full_journey, 0); + request_jaunt(full_journey, FALSE); + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + slackness_counter = 0; + } + + timer() { + if (jaunt_responses_awaited) { + // we are not quite there yet. + if (check_for_timeout()) state normal_runtime; // oops. + return; // not time yet. + } + if (!close_enough(eventual_destination)) + log_it("far away, path okay?"); + state normal_runtime; + } + + // process the response from the jaunting library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + on_rez(integer parm) { state default; } // start-up from scratch. +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.lsl b/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.lsl deleted file mode 100755 index 9b5e315f..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.lsl +++ /dev/null @@ -1,123 +0,0 @@ - -// huffware script: jaunter button pusher, by fred huffhines -// -// the button pusher script warped into service for jaunters. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -string JAUNT_NEXT_BUTTON_NAME = "next"; -string JAUNT_MENU_BUTTON_NAME = "menu"; - -// the button pushing API. -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10029; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was pushed. -////////////// - -float MENU_TIMER_FOR_TOUCH = 0.8; // click hold delay before we decide they want the menu. - -key last_toucher; // the last person who touched the jaunter. - -integer sent_menu_event = FALSE; // true when we just sent out a menu event. - -////////////// - -handle_timer() -{ - if (last_toucher != NULL_KEY) { -//log_it("decided to send menu event!"); - // this is a timer elapsing for a touch-hold menu event. - send_menu_button_event(); - last_toucher = NULL_KEY; - llSetTimerEvent(0.0); - sent_menu_event = TRUE; - return; - } -} - -// generates our next button alert, once the user has finished clicking on the button. -send_next_button_event() -{ - llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, - BUTTON_PUSHED_ALERT, JAUNT_NEXT_BUTTON_NAME); -} - -// tells the jaunter to show the menu of places. -send_menu_button_event() -{ - llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, - BUTTON_PUSHED_ALERT, wrap_parameters([JAUNT_MENU_BUTTON_NAME, last_toucher])); -} - - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -/////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - } - - touch_start(integer total_number) { - if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; -//log_it("touch start"); - llSetTimerEvent(MENU_TIMER_FOR_TOUCH); - // how long before "hold touch" kicks in and we show the destination menu. - last_toucher = llDetectedKey(0); - } - - timer() { handle_timer(); } - - touch_end(integer total_number) - { - if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; -//log_it("touch end"); - if (sent_menu_event) { - // don't send a click event if we popped the menu. - sent_menu_event = FALSE; - return; - } - // clear timer since we got to here. - llSetTimerEvent(0.0); - last_toucher = NULL_KEY; - send_next_button_event(); - } -} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.txt b/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.txt new file mode 100755 index 00000000..9b5e315f --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/jaunter_button_pusher_v0.8.txt @@ -0,0 +1,123 @@ + +// huffware script: jaunter button pusher, by fred huffhines +// +// the button pusher script warped into service for jaunters. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +string JAUNT_NEXT_BUTTON_NAME = "next"; +string JAUNT_MENU_BUTTON_NAME = "menu"; + +// the button pushing API. +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10029; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was pushed. +////////////// + +float MENU_TIMER_FOR_TOUCH = 0.8; // click hold delay before we decide they want the menu. + +key last_toucher; // the last person who touched the jaunter. + +integer sent_menu_event = FALSE; // true when we just sent out a menu event. + +////////////// + +handle_timer() +{ + if (last_toucher != NULL_KEY) { +//log_it("decided to send menu event!"); + // this is a timer elapsing for a touch-hold menu event. + send_menu_button_event(); + last_toucher = NULL_KEY; + llSetTimerEvent(0.0); + sent_menu_event = TRUE; + return; + } +} + +// generates our next button alert, once the user has finished clicking on the button. +send_next_button_event() +{ + llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, + BUTTON_PUSHED_ALERT, JAUNT_NEXT_BUTTON_NAME); +} + +// tells the jaunter to show the menu of places. +send_menu_button_event() +{ + llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, + BUTTON_PUSHED_ALERT, wrap_parameters([JAUNT_MENU_BUTTON_NAME, last_toucher])); +} + + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +/////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + } + + touch_start(integer total_number) { + if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; +//log_it("touch start"); + llSetTimerEvent(MENU_TIMER_FOR_TOUCH); + // how long before "hold touch" kicks in and we show the destination menu. + last_toucher = llDetectedKey(0); + } + + timer() { handle_timer(); } + + touch_end(integer total_number) + { + if (llDetectedLinkNumber(0) != llGetLinkNumber()) return; +//log_it("touch end"); + if (sent_menu_event) { + // don't send a click event if we popped the menu. + sent_menu_event = FALSE; + return; + } + // clear timer since we got to here. + llSetTimerEvent(0.0); + last_toucher = NULL_KEY; + send_next_button_event(); + } +} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.lsl b/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.lsl deleted file mode 100755 index 4d65cee3..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.lsl +++ /dev/null @@ -1,551 +0,0 @@ - -// huffware script: jaunting library, by fred huffhines, released under GPL-v3 license. -// -// this script is a library of useful teleportation and movement calls. it should be added -// into an object along with other scripts that use the library. the jaunting library -// responds to linked messages as commands. -// parts of this script are based on warpPos from "Teleporter Script v 3.0 by Asira Sakai", -// which was found at the LSL wiki. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -float PROXIMITY_REQUIRED = 0.1; - // how close we must be to the target location to call the jaunt done. - // we make this fairly low accuracy since we don't want jumps in space to immediately - // be counted as failures. - -// the most jumps the script will try to take. the overall distance from the start -// to the end can be 10 * MAXIMUM_JUMPS_PER_CALL meters. -integer MAXIMUM_JUMPS_PER_CALL = 84; - -// global variables... - -vector last_posn; // used to calculate jump distances. - -// jaunting library link message API... -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -string FULL_STOP_COMMAND = "#fullstop#"; - // command used to bring object to a halt. -string REVERSE_VELOCITY_COMMAND = "#reverse#"; - // makes the object reverse its velocity and travel back from whence it came. -string SET_VELOCITY_COMMAND = "#setvelocity#"; - // makes the velocity equal to the vector passed as the first parameter. -string JAUNT_UP_COMMAND = "#jauntup#"; -string JAUNT_DOWN_COMMAND = "#jauntdown#"; - // commands for height adjustment. pass a float for number of meters to move. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a list of vectors as the first parameter; this list - // should be in the jaunter notecard format (separated by pipe characters). - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -////////////// - -// returns what we consider to be safe to do in one big jump. -float distance_safe_to_jaunt() { return (float)(MAXIMUM_JUMPS_PER_CALL - 4) * 10.0; } - -// tests whether the destination is safe for an object to enter. -integer safe_for_entry(vector where) -{ - if (outside_of_sim(where)) { - // that's an obvious wrong idea; it tends to break us. - return FALSE; - } - return TRUE; -} - -// helper function for warp_across_list. this adds one jump vector to the -// list of rules as long as the destination is interesting. -list process_warp_item(vector next_jump) -{ -//log_it("mem: " + (string)llGetFreeMemory()); - // calculate the number of jumps needed. - integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; - last_posn = next_jump; // record for next check. - // set up our list which we'll replicate. - list rules = [ PRIM_POSITION, next_jump ]; - // Try and avoid stack/heap collisions. - if (jumps > MAXIMUM_JUMPS_PER_CALL - 1) jumps = MAXIMUM_JUMPS_PER_CALL; - // add the rules repeatedly to get the effective overall jump done. - integer count = 1; - while ( (count = count << 1) < jumps) - rules += rules; - // magnify the rule list before really adding it. this gets us to the proper - // final number of jumps. - return rules + llList2List(rules, (count - jumps) << 1 - 2, count); -} - -// originally based on warpPos from lsl wiki but drastically modified. -// uses a set of transfer points instead of a single target. -list warp_across_list(list full_journey, integer forwards) -{ - // make sure the list didn't run out. - if (llGetListLength(full_journey) == 0) return []; - if (forwards) { - // forwards traversal of the list. - vector next_jump = (vector)llList2String(full_journey, 0); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 1, - llGetListLength(full_journey) - 1), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); - } else { - // reverse traversal of the list. - vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); - // shortcut the jumps if we're already there. - if (next_jump == llGetPos()) - return warp_across_list(chop_list(full_journey, 0, - llGetListLength(full_journey) - 2), forwards); - // calculate our trajectory for the next jump and add in all subsequent jumps. - return process_warp_item(next_jump) - + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); - } -} - -// the main function that performs the jaunting process. -// now also supports adding a rotation into the mix to avoid paying the extra delay -// cost of calling llSetRot. -jaunt(list full_journey, integer forwards, string command_used, - integer use_rotation, rotation rot, integer reply_to_request) -{ -//log_it("jaunt: fullj=" + (string)full_journey + " forew=" + (string)forwards); - // set up our global variables... - last_posn = llGetPos(); - // calculate the trip and run it. - list rot_add; - if (use_rotation) - rot_add = [ PRIM_ROTATION, rot ]; - llSetPrimitiveParams(warp_across_list(full_journey, forwards) + rot_add); - if (reply_to_request) { - // pick out the last target in the list based on the direction we're moving. - integer last_indy = 0; - if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; - vector last_jump = (vector)llList2String(full_journey, last_indy); - // final judge of success here is how close we got to the target. - integer landed_there = (llVecDist(llGetPos(), last_jump) <= PROXIMITY_REQUIRED); - send_reply(LINK_THIS, [landed_there, llGetPos()], command_used); - } -} - -////////////// - -// sets the object's speed to "new_velocity". -// if "local_axis" is TRUE, then it will be relative to the object's -// own local coordinates. -set_velocity(vector new_velocity, integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - new_velocity -= current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -// attempts to bring the object to a complete stop. -full_stop() -{ - llSetForce(<0,0,0>, FALSE); - set_velocity(<0,0,0>, FALSE); -} - -// sends an object back along its trajectory. -reverse_velocity(integer local_axis) -{ - vector current_velocity = llGetVel(); - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - vector new_velocity = -2 * current_velocity; - new_velocity *= llGetMass(); - llApplyImpulse(new_velocity, local_axis); -} - -// teleports to the new "location", if possible. does not change object's phantom / physical -// states. this will do the jaunt in multiple steps if the distance from here to "location" -// is too large. -apportioned_jaunt(vector location, string command_used, integer use_rotation, rotation rot, - integer should_send_reply) -{ - if (!safe_for_entry(location)) { - // that's not good. we should not allow the script to get broken. - if (should_send_reply) - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; - } - // go to position specified, by leapfrogs if too long. - integer chunk_of_jump; - integer MAX_CHUNKS = 200; // multiplies the distance a single jaunt can cover. - for (chunk_of_jump = 0; chunk_of_jump < MAX_CHUNKS; chunk_of_jump++) { - vector interim_vec = location - llGetPos(); - float jump_dist = llVecDist(llGetPos(), location); - integer reply_needed = TRUE; - if (jump_dist > distance_safe_to_jaunt()) { - // the entire distance cannot be jumped. do the part of it that fits. - float proportion_can_do = distance_safe_to_jaunt() / jump_dist; - interim_vec *= proportion_can_do; - reply_needed = FALSE; // don't reply when this is not full jump. - } - interim_vec += llGetPos(); // bias jump back to where we are. -//log_it("jumping from " + (string)llGetPos() + " to " + (string)interim_vec); - jaunt([llGetPos(), interim_vec], TRUE, command_used, use_rotation, rot, - reply_needed && should_send_reply); - float dist_now = llVecDist(llGetPos(), interim_vec); - if (dist_now > PROXIMITY_REQUIRED) { -//log_it("failed to make interim jump, dist left is " + (string)dist_now); - // bail out. we failed to get as far as we thought we should. - chunk_of_jump = MAX_CHUNKS + 10; - if (!reply_needed) { - // we need to send the reply we hadn't sent yet. - if (should_send_reply) - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - } - } else if (llVecDist(llGetPos(), location) <= PROXIMITY_REQUIRED) { - // leave loop for a different reason; we got there. - chunk_of_jump = MAX_CHUNKS + 10; - if (!reply_needed) { - // we need to send the reply we hadn't sent yet. - if (should_send_reply) - send_reply(LINK_THIS, [TRUE, llGetPos()], command_used); - } - } - } -} - -// the entire distance embodied in the list of targets. this is a little smart, -// in that if there's only one target, we assume we're going from "here" to that -// one target. -float total_jaunt_distance(list targets) -{ - if (!llGetListLength(targets)) return 0.0; - // add in "this" location if they omitted it. - if (llGetListLength(targets) < 2) - targets = [ llGetPos() ] + targets; - integer disindy; - float total_dist = 0.0; - vector prev = (vector)llList2String(targets, 0); - for (disindy = 1; disindy < llGetListLength(targets); disindy++) { - vector next = (vector)llList2String(targets, disindy); - total_dist += llVecDist(prev, next); - prev = next; - } - return total_dist; -} - -// jaunts to a target via a set of intermediate locations. can either go forwards -// through the list or backwards. -phantom_jaunt_to_list(list targets, integer forwards, string command_used, - integer use_rotation, rotation rot) -{ - vector final_loc; - if (forwards) final_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); - else final_loc = (vector)llList2String(targets, 0); - -//hmmm: check each destination in list?? - if (!safe_for_entry(final_loc)) { - // that's not good. we should not allow the script to get broken. - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; - } - - // this turns off the physics property for the object, so that jaunt and - // llSetPos will still work. this became necessary due to havok4. - integer original_phantomosity = llGetStatus(STATUS_PHANTOM); - integer original_physicality = llGetStatus(STATUS_PHYSICS); - if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, FALSE); - if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, TRUE); - - integer send_reply_still = TRUE; // true if we should send a reply when done. - - // iterate through our list of targets and either we will jaunt to the next - // place directly or we will have to wrap a few destinations due to sim crossing. - while (llGetListLength(targets) > 0) { - vector next_loc; - if (forwards) next_loc = (vector)llList2String(targets, 0); - else next_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); - if (outside_of_sim(next_loc)) { - log_it("bad jaunt path: first target is out of sim."); - send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); - return; // skip that badness. - } - - // check how much total distance we have in the path that's left. if it's under our - // limit, then we'll just take it in one jump. - float total_dist = total_jaunt_distance(targets); - - // if we're below the threshold, we'll just jump now. - integer already_jumped = FALSE; - if (total_dist < distance_safe_to_jaunt()) { - jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); - targets = []; // reset the list now. - send_reply_still = FALSE; // we have already sent the reply in jaunt(). - already_jumped = TRUE; // don't do anything else. - } - if (!already_jumped) { - vector next_plus_1 = ZERO_VECTOR; // default cannot fail our "is inside sim" check. - if (llGetListLength(targets) > 1) { - if (forwards) next_plus_1 = (vector)llList2String(targets, 1); - else next_plus_1 = (vector)llList2String(targets, llGetListLength(targets) - 2); - } - if (outside_of_sim(next_plus_1)) { -//hmmm: eventually find all the negative ones in a row and do them in combo, rather than -// just giving up here and doing a jaunt to the rest.. - jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); - targets = []; // reset the list now. - send_reply_still = FALSE; // we have already sent the reply in jaunt(). - } else { - // we've passed the negativity test, so we can at least jump to the next place. - - // zap the next location, since we're about to jump there. - integer zap_pos = 0; - if (!forwards) zap_pos = llGetListLength(targets) - 1; - targets = llDeleteSubList(targets, zap_pos, zap_pos); - - // only bother jumping if we're not already there. - if (llVecDist(next_loc, llGetPos()) > PROXIMITY_REQUIRED) { - apportioned_jaunt(next_loc, command_used, use_rotation, rot, FALSE); - } - } - } - } - - if (send_reply_still) { - integer yippee = TRUE; // assume we succeeded until we prove otherwise. - if (llVecDist(final_loc, llGetPos()) > PROXIMITY_REQUIRED) - yippee = FALSE; - send_reply(LINK_THIS, [yippee, llGetPos()], command_used); - } - - // return to prior characteristics. - if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, original_phantomosity); - if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, original_physicality); -} - -// implements our API for jumping around. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - // separate the list out - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - if (msg == JAUNT_COMMAND) { - // use list to string to avoid non-conversions. - vector v = (vector)llList2String(parms, 0); - rotation rot = <0.0, 0.0, 0.0, 1.0>; - integer gave_rot = llGetListLength(parms) > 1; - if (gave_rot) rot = (rotation)llList2String(parms, 1); // ooh, they gave us a rotational value also. -// log_it("gave rot? " + (string)gave_rot + " rot=" + (string)rot); - phantom_jaunt_to_list([llGetPos(), v], TRUE, msg, gave_rot, rot); - } else if (msg == FULL_STOP_COMMAND) { - full_stop(); - } else if (msg == REVERSE_VELOCITY_COMMAND) { - reverse_velocity(FALSE); - } else if (msg == SET_VELOCITY_COMMAND) { - vector v = (vector)llList2String(parms, 0); -//log_it("jaunting lib received set velocity request for " + (string)v); - set_velocity(v, FALSE); - } else if (msg == JAUNT_UP_COMMAND) { - phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, llList2Float(parms, 0)> ], - TRUE, msg, FALSE, ZERO_ROTATION); - } else if (msg == JAUNT_DOWN_COMMAND) { - phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, -llList2Float(parms, 0)> ], - TRUE, msg, FALSE, ZERO_ROTATION); - } else if (msg == JAUNT_LIST_COMMAND) { - string destination_list = llList2String(parms, 0); - list targets = llParseString2List(destination_list, [HUFFWARE_ITEM_SEPARATOR], []); - destination_list = ""; - integer forwards = TRUE; - // snag the directionality for the list, if specified. - if (llGetListLength(parms) > 1) forwards = llList2Integer(parms, 1); - rotation rot = <0.0, 0.0, 0.0, 1.0>; - integer gave_rot = llGetListLength(parms) > 2; - if (gave_rot) rot = llList2Rot(parms, 2); // ooh, they gave us a rotational value also. - phantom_jaunt_to_list(targets, forwards, msg, gave_rot, rot); - targets = []; - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); -} -////////////// - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply(integer destination, list parms, string command) -{ - llMessageLinked(destination, JAUNT_HUFFWARE_ID + REPLY_DISTANCE, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. -integer valid_sim_value(float to_check) -{ - if (to_check < 0.0) return FALSE; - if (to_check >= 257.0) return FALSE; - return TRUE; -} - -integer outside_of_sim(vector to_check) -{ - return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); -} - -/////////////// - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - link_message(integer sender, integer huff_id, string msg, key id) { - if (huff_id != JAUNT_HUFFWARE_ID) return; // not our responsibility. - handle_link_message(sender, huff_id, msg, id); - } -} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.txt b/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.txt new file mode 100755 index 00000000..4d65cee3 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/jaunting_library_v15.9.txt @@ -0,0 +1,551 @@ + +// huffware script: jaunting library, by fred huffhines, released under GPL-v3 license. +// +// this script is a library of useful teleportation and movement calls. it should be added +// into an object along with other scripts that use the library. the jaunting library +// responds to linked messages as commands. +// parts of this script are based on warpPos from "Teleporter Script v 3.0 by Asira Sakai", +// which was found at the LSL wiki. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +float PROXIMITY_REQUIRED = 0.1; + // how close we must be to the target location to call the jaunt done. + // we make this fairly low accuracy since we don't want jumps in space to immediately + // be counted as failures. + +// the most jumps the script will try to take. the overall distance from the start +// to the end can be 10 * MAXIMUM_JUMPS_PER_CALL meters. +integer MAXIMUM_JUMPS_PER_CALL = 84; + +// global variables... + +vector last_posn; // used to calculate jump distances. + +// jaunting library link message API... +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +string FULL_STOP_COMMAND = "#fullstop#"; + // command used to bring object to a halt. +string REVERSE_VELOCITY_COMMAND = "#reverse#"; + // makes the object reverse its velocity and travel back from whence it came. +string SET_VELOCITY_COMMAND = "#setvelocity#"; + // makes the velocity equal to the vector passed as the first parameter. +string JAUNT_UP_COMMAND = "#jauntup#"; +string JAUNT_DOWN_COMMAND = "#jauntdown#"; + // commands for height adjustment. pass a float for number of meters to move. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a list of vectors as the first parameter; this list + // should be in the jaunter notecard format (separated by pipe characters). + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +////////////// + +// returns what we consider to be safe to do in one big jump. +float distance_safe_to_jaunt() { return (float)(MAXIMUM_JUMPS_PER_CALL - 4) * 10.0; } + +// tests whether the destination is safe for an object to enter. +integer safe_for_entry(vector where) +{ + if (outside_of_sim(where)) { + // that's an obvious wrong idea; it tends to break us. + return FALSE; + } + return TRUE; +} + +// helper function for warp_across_list. this adds one jump vector to the +// list of rules as long as the destination is interesting. +list process_warp_item(vector next_jump) +{ +//log_it("mem: " + (string)llGetFreeMemory()); + // calculate the number of jumps needed. + integer jumps = (integer)(llVecDist(next_jump, last_posn) / 10.0) + 1; + last_posn = next_jump; // record for next check. + // set up our list which we'll replicate. + list rules = [ PRIM_POSITION, next_jump ]; + // Try and avoid stack/heap collisions. + if (jumps > MAXIMUM_JUMPS_PER_CALL - 1) jumps = MAXIMUM_JUMPS_PER_CALL; + // add the rules repeatedly to get the effective overall jump done. + integer count = 1; + while ( (count = count << 1) < jumps) + rules += rules; + // magnify the rule list before really adding it. this gets us to the proper + // final number of jumps. + return rules + llList2List(rules, (count - jumps) << 1 - 2, count); +} + +// originally based on warpPos from lsl wiki but drastically modified. +// uses a set of transfer points instead of a single target. +list warp_across_list(list full_journey, integer forwards) +{ + // make sure the list didn't run out. + if (llGetListLength(full_journey) == 0) return []; + if (forwards) { + // forwards traversal of the list. + vector next_jump = (vector)llList2String(full_journey, 0); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 1, + llGetListLength(full_journey) - 1), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 1, llGetListLength(full_journey) - 1), forwards); + } else { + // reverse traversal of the list. + vector next_jump = (vector)llList2String(full_journey, llGetListLength(full_journey) - 1); + // shortcut the jumps if we're already there. + if (next_jump == llGetPos()) + return warp_across_list(chop_list(full_journey, 0, + llGetListLength(full_journey) - 2), forwards); + // calculate our trajectory for the next jump and add in all subsequent jumps. + return process_warp_item(next_jump) + + warp_across_list(chop_list(full_journey, 0, llGetListLength(full_journey) - 2), forwards); + } +} + +// the main function that performs the jaunting process. +// now also supports adding a rotation into the mix to avoid paying the extra delay +// cost of calling llSetRot. +jaunt(list full_journey, integer forwards, string command_used, + integer use_rotation, rotation rot, integer reply_to_request) +{ +//log_it("jaunt: fullj=" + (string)full_journey + " forew=" + (string)forwards); + // set up our global variables... + last_posn = llGetPos(); + // calculate the trip and run it. + list rot_add; + if (use_rotation) + rot_add = [ PRIM_ROTATION, rot ]; + llSetPrimitiveParams(warp_across_list(full_journey, forwards) + rot_add); + if (reply_to_request) { + // pick out the last target in the list based on the direction we're moving. + integer last_indy = 0; + if (forwards == TRUE) last_indy = llGetListLength(full_journey) - 1; + vector last_jump = (vector)llList2String(full_journey, last_indy); + // final judge of success here is how close we got to the target. + integer landed_there = (llVecDist(llGetPos(), last_jump) <= PROXIMITY_REQUIRED); + send_reply(LINK_THIS, [landed_there, llGetPos()], command_used); + } +} + +////////////// + +// sets the object's speed to "new_velocity". +// if "local_axis" is TRUE, then it will be relative to the object's +// own local coordinates. +set_velocity(vector new_velocity, integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + new_velocity -= current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +// attempts to bring the object to a complete stop. +full_stop() +{ + llSetForce(<0,0,0>, FALSE); + set_velocity(<0,0,0>, FALSE); +} + +// sends an object back along its trajectory. +reverse_velocity(integer local_axis) +{ + vector current_velocity = llGetVel(); + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + vector new_velocity = -2 * current_velocity; + new_velocity *= llGetMass(); + llApplyImpulse(new_velocity, local_axis); +} + +// teleports to the new "location", if possible. does not change object's phantom / physical +// states. this will do the jaunt in multiple steps if the distance from here to "location" +// is too large. +apportioned_jaunt(vector location, string command_used, integer use_rotation, rotation rot, + integer should_send_reply) +{ + if (!safe_for_entry(location)) { + // that's not good. we should not allow the script to get broken. + if (should_send_reply) + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; + } + // go to position specified, by leapfrogs if too long. + integer chunk_of_jump; + integer MAX_CHUNKS = 200; // multiplies the distance a single jaunt can cover. + for (chunk_of_jump = 0; chunk_of_jump < MAX_CHUNKS; chunk_of_jump++) { + vector interim_vec = location - llGetPos(); + float jump_dist = llVecDist(llGetPos(), location); + integer reply_needed = TRUE; + if (jump_dist > distance_safe_to_jaunt()) { + // the entire distance cannot be jumped. do the part of it that fits. + float proportion_can_do = distance_safe_to_jaunt() / jump_dist; + interim_vec *= proportion_can_do; + reply_needed = FALSE; // don't reply when this is not full jump. + } + interim_vec += llGetPos(); // bias jump back to where we are. +//log_it("jumping from " + (string)llGetPos() + " to " + (string)interim_vec); + jaunt([llGetPos(), interim_vec], TRUE, command_used, use_rotation, rot, + reply_needed && should_send_reply); + float dist_now = llVecDist(llGetPos(), interim_vec); + if (dist_now > PROXIMITY_REQUIRED) { +//log_it("failed to make interim jump, dist left is " + (string)dist_now); + // bail out. we failed to get as far as we thought we should. + chunk_of_jump = MAX_CHUNKS + 10; + if (!reply_needed) { + // we need to send the reply we hadn't sent yet. + if (should_send_reply) + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + } + } else if (llVecDist(llGetPos(), location) <= PROXIMITY_REQUIRED) { + // leave loop for a different reason; we got there. + chunk_of_jump = MAX_CHUNKS + 10; + if (!reply_needed) { + // we need to send the reply we hadn't sent yet. + if (should_send_reply) + send_reply(LINK_THIS, [TRUE, llGetPos()], command_used); + } + } + } +} + +// the entire distance embodied in the list of targets. this is a little smart, +// in that if there's only one target, we assume we're going from "here" to that +// one target. +float total_jaunt_distance(list targets) +{ + if (!llGetListLength(targets)) return 0.0; + // add in "this" location if they omitted it. + if (llGetListLength(targets) < 2) + targets = [ llGetPos() ] + targets; + integer disindy; + float total_dist = 0.0; + vector prev = (vector)llList2String(targets, 0); + for (disindy = 1; disindy < llGetListLength(targets); disindy++) { + vector next = (vector)llList2String(targets, disindy); + total_dist += llVecDist(prev, next); + prev = next; + } + return total_dist; +} + +// jaunts to a target via a set of intermediate locations. can either go forwards +// through the list or backwards. +phantom_jaunt_to_list(list targets, integer forwards, string command_used, + integer use_rotation, rotation rot) +{ + vector final_loc; + if (forwards) final_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); + else final_loc = (vector)llList2String(targets, 0); + +//hmmm: check each destination in list?? + if (!safe_for_entry(final_loc)) { + // that's not good. we should not allow the script to get broken. + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; + } + + // this turns off the physics property for the object, so that jaunt and + // llSetPos will still work. this became necessary due to havok4. + integer original_phantomosity = llGetStatus(STATUS_PHANTOM); + integer original_physicality = llGetStatus(STATUS_PHYSICS); + if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, FALSE); + if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, TRUE); + + integer send_reply_still = TRUE; // true if we should send a reply when done. + + // iterate through our list of targets and either we will jaunt to the next + // place directly or we will have to wrap a few destinations due to sim crossing. + while (llGetListLength(targets) > 0) { + vector next_loc; + if (forwards) next_loc = (vector)llList2String(targets, 0); + else next_loc = (vector)llList2String(targets, llGetListLength(targets) - 1); + if (outside_of_sim(next_loc)) { + log_it("bad jaunt path: first target is out of sim."); + send_reply(LINK_THIS, [FALSE, llGetPos()], command_used); + return; // skip that badness. + } + + // check how much total distance we have in the path that's left. if it's under our + // limit, then we'll just take it in one jump. + float total_dist = total_jaunt_distance(targets); + + // if we're below the threshold, we'll just jump now. + integer already_jumped = FALSE; + if (total_dist < distance_safe_to_jaunt()) { + jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); + targets = []; // reset the list now. + send_reply_still = FALSE; // we have already sent the reply in jaunt(). + already_jumped = TRUE; // don't do anything else. + } + if (!already_jumped) { + vector next_plus_1 = ZERO_VECTOR; // default cannot fail our "is inside sim" check. + if (llGetListLength(targets) > 1) { + if (forwards) next_plus_1 = (vector)llList2String(targets, 1); + else next_plus_1 = (vector)llList2String(targets, llGetListLength(targets) - 2); + } + if (outside_of_sim(next_plus_1)) { +//hmmm: eventually find all the negative ones in a row and do them in combo, rather than +// just giving up here and doing a jaunt to the rest.. + jaunt(targets, forwards, command_used, use_rotation, rot, TRUE); + targets = []; // reset the list now. + send_reply_still = FALSE; // we have already sent the reply in jaunt(). + } else { + // we've passed the negativity test, so we can at least jump to the next place. + + // zap the next location, since we're about to jump there. + integer zap_pos = 0; + if (!forwards) zap_pos = llGetListLength(targets) - 1; + targets = llDeleteSubList(targets, zap_pos, zap_pos); + + // only bother jumping if we're not already there. + if (llVecDist(next_loc, llGetPos()) > PROXIMITY_REQUIRED) { + apportioned_jaunt(next_loc, command_used, use_rotation, rot, FALSE); + } + } + } + } + + if (send_reply_still) { + integer yippee = TRUE; // assume we succeeded until we prove otherwise. + if (llVecDist(final_loc, llGetPos()) > PROXIMITY_REQUIRED) + yippee = FALSE; + send_reply(LINK_THIS, [yippee, llGetPos()], command_used); + } + + // return to prior characteristics. + if (original_phantomosity != TRUE) llSetStatus(STATUS_PHANTOM, original_phantomosity); + if (original_physicality != FALSE) llSetStatus(STATUS_PHYSICS, original_physicality); +} + +// implements our API for jumping around. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + // separate the list out + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + if (msg == JAUNT_COMMAND) { + // use list to string to avoid non-conversions. + vector v = (vector)llList2String(parms, 0); + rotation rot = <0.0, 0.0, 0.0, 1.0>; + integer gave_rot = llGetListLength(parms) > 1; + if (gave_rot) rot = (rotation)llList2String(parms, 1); // ooh, they gave us a rotational value also. +// log_it("gave rot? " + (string)gave_rot + " rot=" + (string)rot); + phantom_jaunt_to_list([llGetPos(), v], TRUE, msg, gave_rot, rot); + } else if (msg == FULL_STOP_COMMAND) { + full_stop(); + } else if (msg == REVERSE_VELOCITY_COMMAND) { + reverse_velocity(FALSE); + } else if (msg == SET_VELOCITY_COMMAND) { + vector v = (vector)llList2String(parms, 0); +//log_it("jaunting lib received set velocity request for " + (string)v); + set_velocity(v, FALSE); + } else if (msg == JAUNT_UP_COMMAND) { + phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, llList2Float(parms, 0)> ], + TRUE, msg, FALSE, ZERO_ROTATION); + } else if (msg == JAUNT_DOWN_COMMAND) { + phantom_jaunt_to_list([ llGetPos(), llGetPos() + <0.0, 0.0, -llList2Float(parms, 0)> ], + TRUE, msg, FALSE, ZERO_ROTATION); + } else if (msg == JAUNT_LIST_COMMAND) { + string destination_list = llList2String(parms, 0); + list targets = llParseString2List(destination_list, [HUFFWARE_ITEM_SEPARATOR], []); + destination_list = ""; + integer forwards = TRUE; + // snag the directionality for the list, if specified. + if (llGetListLength(parms) > 1) forwards = llList2Integer(parms, 1); + rotation rot = <0.0, 0.0, 0.0, 1.0>; + integer gave_rot = llGetListLength(parms) > 2; + if (gave_rot) rot = llList2Rot(parms, 2); // ooh, they gave us a rotational value also. + phantom_jaunt_to_list(targets, forwards, msg, gave_rot, rot); + targets = []; + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); +} +////////////// + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply(integer destination, list parms, string command) +{ + llMessageLinked(destination, JAUNT_HUFFWARE_ID + REPLY_DISTANCE, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// returns TRUE if the value in "to_check" specifies a legal x or y value in a sim. +integer valid_sim_value(float to_check) +{ + if (to_check < 0.0) return FALSE; + if (to_check >= 257.0) return FALSE; + return TRUE; +} + +integer outside_of_sim(vector to_check) +{ + return !valid_sim_value(to_check.x) || !valid_sim_value(to_check.y); +} + +/////////////// + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + link_message(integer sender, integer huff_id, string msg, key id) { + if (huff_id != JAUNT_HUFFWARE_ID) return; // not our responsibility. + handle_link_message(sender, huff_id, msg, id); + } +} diff --git a/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.lsl b/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.lsl deleted file mode 100755 index abd27116..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.lsl +++ /dev/null @@ -1,436 +0,0 @@ - -// huffware script: menutini library, by fred huffhines. -// -// this is a library script for menuing that provides a way to remote control the -// menu, somewhat. another script can zing link messages at this script and a menu -// will be shown based on the specified description and buttons. when the user -// selects an answer, that result is sent back in a link message reply. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// useful constants you might want to change: - -integer TIMEOUT_FOR_MENU = 42; - // timeout for the menu in seconds. -//hmmm: may want this to be selectable from menu request. -// or may even want to never time out! -// if we managed a list of ongoing menus, that would work. -// currently it cannot. - -integer DEBUGGING = FALSE; - // if this is true, then extra info will be printed when handling a menu. - -string NEXT_MENU_TEXT = "Next >>"; - // what the next item will say for showing next menu page. - -// menutini link message API... -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. - // the reply will include: the menu name, the choice made and the key for - // the avatar. -// -////////////// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -// -////////////// - -// global variables... - -list _private_global_buttons; // holds onto the active set of menu options. -string _private_global_av_key; // the key for the avatar who clicks the menu. -string _private_global_title; // holds onto current title text. - -integer _menu_base_start = 0; // position in the items of the current menu. - -integer listening_id = 0; - // the current id of our listening for the menu. it's an id returned by LSL - // that we need to track so we can cancel the listen. - -integer menu_system_channel = 0; - // messages come back to us from this channel when user clicks the dialog. - // this is set later and the default is meaningless. - -string global_menu_name = ""; - // hangs onto the current menu's name. - -//hmmm: note; to manage multiple concurrent menus on different channels, -// we must make these into lists. then the timeouts should apply -// individually to these instead of overall (if we even do timeouts; -// it's nicer if menus never stop being active). - - -// displays the menu requested. it's "menu_name" is an internal name that is -// not displayed to the user. the "title" is the content shown in the main area -// of the menu. "commands_in" is the list of menu items to show as buttons. -// the "menu_channel" is where the user's clicked response will be sent. the -// "listen_to" key is the avatar expected to click the menu, which is needed to -// listen to his response. -show_menu(string menu_name, string title, list buttons, - integer menu_channel, key listen_to) -{ - // save our new parms. - global_menu_name = menu_name; - _private_global_title = title; - _private_global_buttons = buttons; - menu_system_channel = menu_channel; - _private_global_av_key = listen_to; - if (DEBUGGING) { - log_it("menu name: " + global_menu_name); - log_it("title: " + _private_global_title); - log_it("buttons: " + (string)buttons); - log_it("channel: " + (string)menu_system_channel); - log_it("listen key: " + (string)listen_to); - } - - integer add_next = FALSE; // true if we should add a next menu item. - - // the math here incorporates current button position. - integer current = _menu_base_start; - integer max_buttons = llGetListLength(buttons) - current; - - if (max_buttons > 12) { - // limitation of SL: menus have a max of 12 buttons. - max_buttons = 12; - add_next = TRUE; - } else if (llGetListLength(buttons) > 12) { - // we already have been adding next. let's make sure this gets - // a wrap-around next button. - add_next = TRUE; - } - // chop out what we can use in a menu. - list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); - if (add_next) { - // we were asked to add a menu item for the next screen. - trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; - } - - listening_id = llListen(menu_channel, "", listen_to, ""); - list commands; - integer i; - // take only the prefix of the string, to avoid getting a length complaint. - for (i = 0; i < llGetListLength(trunc_buttons); i++) { - string curr = llList2String(trunc_buttons, i); - integer last_pos = 23; // default maximum, highest possible is 24. - if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; - curr = llGetSubString(curr, 0, last_pos); - commands += curr; - } - llDialog(listen_to, title, commands, menu_channel); - llSetTimerEvent(TIMEOUT_FOR_MENU); -} - -// shuts down any connection we might have had with any active menu. we will not -// send any responses after this point (although we might already have responded when -// the user clicked the menu). -clear_menu() -{ - llListenRemove(listening_id); - llSetTimerEvent(0.0); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -// ours do differ from normal in that we send back the channel as the number parameter -// instead of enforcing that being MENU_HUFFWARE_ID. -send_reply(integer destination, integer channel, list parms, string command) -{ - llMessageLinked(destination, channel, command, - llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); -} - -// processes the menu requests. -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - if (huff_id != MENUTINI_HUFFWARE_ID) return; // not for us. - - if (msg == SHOW_MENU_COMMAND) { - _menu_base_start = 0; // reset the position in the menus. - // separate the list out. -//log_it("id showing: " + id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - // toss any existing menu info. - clear_menu(); -//log_it("key here early: " + llList2String(parms, 4)); - show_menu(llList2String(parms, 0), llList2String(parms, 1), - llParseString2List(llList2String(parms, 2), - [HUFFWARE_ITEM_SEPARATOR], []), - (integer)llList2String(parms, 3), - (key)llList2String(parms, 4)); - } -} - -// process the response when the user chooses a menu item. this causes our -// caller to be told what was selected. -process_menu_response(integer channel, string name, key id, string message) -{ - if (channel != menu_system_channel) return; // not for us. - - if (message == NEXT_MENU_TEXT) { - // this is the special choice, so we need to go to the next page. - _menu_base_start += 11; - if (_menu_base_start > llGetListLength(_private_global_buttons)) { - // we have wrapped around the list. go to the start again. - _menu_base_start = 0; - } - show_menu(global_menu_name, _private_global_title, - _private_global_buttons, menu_system_channel, - _private_global_av_key); - return; // handled by opening a new menu. - } - - string calculated_name; - integer indy; - // first try for an exact match. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (curr == message) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - if (calculated_name == "") { - // try an imprecise match if the exact matching didn't work. - for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { - string curr = llList2String(_private_global_buttons, indy); - if (is_prefix(curr, message)) { - // correct the answer based on the full button string. - calculated_name = curr; - } - } - } - if (calculated_name != "") { - // only send a response if that menu choice made sense to us. - send_reply(LINK_THIS, MENUTINI_HUFFWARE_ID + REPLY_DISTANCE, - [ global_menu_name, calculated_name, _private_global_av_key ], - SHOW_MENU_COMMAND); - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -////////////// - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -//hmmm: extract this code to a menutini example! - -////////////// -// how to invoke a menu (assuming menutini is in same prim as calling script): -// -list buttons; // holds onto the set of menu options. -// -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } -// -example_invocation() -{ - string menu_name = "grumfazoid"; - string title = "These united colors of ben's futon have unfortunately run."; - buttons = [ "garp out", "sklonar", "fuzzlenog" ]; - integer menu_channel = random_channel(); - key listen_to = llGetOwner(); - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR - + (string)menu_channel + HUFFWARE_PARM_SEPARATOR - + (string)listen_to); -} -// -// how to handle the response message when the user chooses a button. -// -react_to_menu(string menu_name, string which_choice) -{ - // one might use the menu_name when dealing with multiple different menus. - - integer indy = 0; - // find the specified item and process it. - while (indy < llGetListLength(buttons)) { - // see if the current destination matches. - if (llSubStringIndex(llList2String(buttons, indy), which_choice) == 0) { - // this is the chosen item. -// process_menu_item(indy); // using numerical numbering. -// this function must be implemented in your own code; it is what handles the -// user picking a particular button on the menu. - return; - } - indy++; - } - llSay(0, "did not find menu option"); -} - -// an example for menu handling. this gets the response from menutini library -// and calls the menu processing method "react_to_menu". -example_handle_link_message(integer sender, integer num, string msg, key id) -{ - if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. - if (msg != SHOW_MENU_COMMAND) return; // also not for us. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string which_choice = llList2String(parms, 1); - react_to_menu(menu_name, which_choice); -} - -// then inside a state, you need an event handler like so: -// -// link_message(integer sender, integer num, string msg, key id) -// { example_handle_link_message(sender, num, msg, id); } - -// -// end invocation sample code... -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - link_message(integer sender, integer huff_id, string msg, key id) - { handle_link_message(sender, huff_id, msg, id); } - - listen(integer channel, string name, key id, string message) - { process_menu_response(channel, name, id, message); } - - // if the timer goes off, then the user has ignored the menu for longer than the - // timeout. we need to turn off our listen and ignore that menu. - timer() { clear_menu(); } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.txt b/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.txt new file mode 100755 index 00000000..abd27116 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/menutini_library_v5.9.txt @@ -0,0 +1,436 @@ + +// huffware script: menutini library, by fred huffhines. +// +// this is a library script for menuing that provides a way to remote control the +// menu, somewhat. another script can zing link messages at this script and a menu +// will be shown based on the specified description and buttons. when the user +// selects an answer, that result is sent back in a link message reply. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// useful constants you might want to change: + +integer TIMEOUT_FOR_MENU = 42; + // timeout for the menu in seconds. +//hmmm: may want this to be selectable from menu request. +// or may even want to never time out! +// if we managed a list of ongoing menus, that would work. +// currently it cannot. + +integer DEBUGGING = FALSE; + // if this is true, then extra info will be printed when handling a menu. + +string NEXT_MENU_TEXT = "Next >>"; + // what the next item will say for showing next menu page. + +// menutini link message API... +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. + // the reply will include: the menu name, the choice made and the key for + // the avatar. +// +////////////// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +// +////////////// + +// global variables... + +list _private_global_buttons; // holds onto the active set of menu options. +string _private_global_av_key; // the key for the avatar who clicks the menu. +string _private_global_title; // holds onto current title text. + +integer _menu_base_start = 0; // position in the items of the current menu. + +integer listening_id = 0; + // the current id of our listening for the menu. it's an id returned by LSL + // that we need to track so we can cancel the listen. + +integer menu_system_channel = 0; + // messages come back to us from this channel when user clicks the dialog. + // this is set later and the default is meaningless. + +string global_menu_name = ""; + // hangs onto the current menu's name. + +//hmmm: note; to manage multiple concurrent menus on different channels, +// we must make these into lists. then the timeouts should apply +// individually to these instead of overall (if we even do timeouts; +// it's nicer if menus never stop being active). + + +// displays the menu requested. it's "menu_name" is an internal name that is +// not displayed to the user. the "title" is the content shown in the main area +// of the menu. "commands_in" is the list of menu items to show as buttons. +// the "menu_channel" is where the user's clicked response will be sent. the +// "listen_to" key is the avatar expected to click the menu, which is needed to +// listen to his response. +show_menu(string menu_name, string title, list buttons, + integer menu_channel, key listen_to) +{ + // save our new parms. + global_menu_name = menu_name; + _private_global_title = title; + _private_global_buttons = buttons; + menu_system_channel = menu_channel; + _private_global_av_key = listen_to; + if (DEBUGGING) { + log_it("menu name: " + global_menu_name); + log_it("title: " + _private_global_title); + log_it("buttons: " + (string)buttons); + log_it("channel: " + (string)menu_system_channel); + log_it("listen key: " + (string)listen_to); + } + + integer add_next = FALSE; // true if we should add a next menu item. + + // the math here incorporates current button position. + integer current = _menu_base_start; + integer max_buttons = llGetListLength(buttons) - current; + + if (max_buttons > 12) { + // limitation of SL: menus have a max of 12 buttons. + max_buttons = 12; + add_next = TRUE; + } else if (llGetListLength(buttons) > 12) { + // we already have been adding next. let's make sure this gets + // a wrap-around next button. + add_next = TRUE; + } + // chop out what we can use in a menu. + list trunc_buttons = llList2List(buttons, current, current + max_buttons - 1); + if (add_next) { + // we were asked to add a menu item for the next screen. + trunc_buttons = llList2List(trunc_buttons, 0, 10) + NEXT_MENU_TEXT; + } + + listening_id = llListen(menu_channel, "", listen_to, ""); + list commands; + integer i; + // take only the prefix of the string, to avoid getting a length complaint. + for (i = 0; i < llGetListLength(trunc_buttons); i++) { + string curr = llList2String(trunc_buttons, i); + integer last_pos = 23; // default maximum, highest possible is 24. + if (llStringLength(curr) - 1 < last_pos) last_pos = llStringLength(curr) - 1; + curr = llGetSubString(curr, 0, last_pos); + commands += curr; + } + llDialog(listen_to, title, commands, menu_channel); + llSetTimerEvent(TIMEOUT_FOR_MENU); +} + +// shuts down any connection we might have had with any active menu. we will not +// send any responses after this point (although we might already have responded when +// the user clicked the menu). +clear_menu() +{ + llListenRemove(listening_id); + llSetTimerEvent(0.0); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +// ours do differ from normal in that we send back the channel as the number parameter +// instead of enforcing that being MENU_HUFFWARE_ID. +send_reply(integer destination, integer channel, list parms, string command) +{ + llMessageLinked(destination, channel, command, + llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); +} + +// processes the menu requests. +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + if (huff_id != MENUTINI_HUFFWARE_ID) return; // not for us. + + if (msg == SHOW_MENU_COMMAND) { + _menu_base_start = 0; // reset the position in the menus. + // separate the list out. +//log_it("id showing: " + id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + // toss any existing menu info. + clear_menu(); +//log_it("key here early: " + llList2String(parms, 4)); + show_menu(llList2String(parms, 0), llList2String(parms, 1), + llParseString2List(llList2String(parms, 2), + [HUFFWARE_ITEM_SEPARATOR], []), + (integer)llList2String(parms, 3), + (key)llList2String(parms, 4)); + } +} + +// process the response when the user chooses a menu item. this causes our +// caller to be told what was selected. +process_menu_response(integer channel, string name, key id, string message) +{ + if (channel != menu_system_channel) return; // not for us. + + if (message == NEXT_MENU_TEXT) { + // this is the special choice, so we need to go to the next page. + _menu_base_start += 11; + if (_menu_base_start > llGetListLength(_private_global_buttons)) { + // we have wrapped around the list. go to the start again. + _menu_base_start = 0; + } + show_menu(global_menu_name, _private_global_title, + _private_global_buttons, menu_system_channel, + _private_global_av_key); + return; // handled by opening a new menu. + } + + string calculated_name; + integer indy; + // first try for an exact match. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (curr == message) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + if (calculated_name == "") { + // try an imprecise match if the exact matching didn't work. + for (indy = 0; indy < llGetListLength(_private_global_buttons); indy++) { + string curr = llList2String(_private_global_buttons, indy); + if (is_prefix(curr, message)) { + // correct the answer based on the full button string. + calculated_name = curr; + } + } + } + if (calculated_name != "") { + // only send a response if that menu choice made sense to us. + send_reply(LINK_THIS, MENUTINI_HUFFWARE_ID + REPLY_DISTANCE, + [ global_menu_name, calculated_name, _private_global_av_key ], + SHOW_MENU_COMMAND); + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +////////////// + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +//hmmm: extract this code to a menutini example! + +////////////// +// how to invoke a menu (assuming menutini is in same prim as calling script): +// +list buttons; // holds onto the set of menu options. +// +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } +// +example_invocation() +{ + string menu_name = "grumfazoid"; + string title = "These united colors of ben's futon have unfortunately run."; + buttons = [ "garp out", "sklonar", "fuzzlenog" ]; + integer menu_channel = random_channel(); + key listen_to = llGetOwner(); + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR + + (string)menu_channel + HUFFWARE_PARM_SEPARATOR + + (string)listen_to); +} +// +// how to handle the response message when the user chooses a button. +// +react_to_menu(string menu_name, string which_choice) +{ + // one might use the menu_name when dealing with multiple different menus. + + integer indy = 0; + // find the specified item and process it. + while (indy < llGetListLength(buttons)) { + // see if the current destination matches. + if (llSubStringIndex(llList2String(buttons, indy), which_choice) == 0) { + // this is the chosen item. +// process_menu_item(indy); // using numerical numbering. +// this function must be implemented in your own code; it is what handles the +// user picking a particular button on the menu. + return; + } + indy++; + } + llSay(0, "did not find menu option"); +} + +// an example for menu handling. this gets the response from menutini library +// and calls the menu processing method "react_to_menu". +example_handle_link_message(integer sender, integer num, string msg, key id) +{ + if (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) return; // not for us. + if (msg != SHOW_MENU_COMMAND) return; // also not for us. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string which_choice = llList2String(parms, 1); + react_to_menu(menu_name, which_choice); +} + +// then inside a state, you need an event handler like so: +// +// link_message(integer sender, integer num, string msg, key id) +// { example_handle_link_message(sender, num, msg, id); } + +// +// end invocation sample code... +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + link_message(integer sender, integer huff_id, string msg, key id) + { handle_link_message(sender, huff_id, msg, id); } + + listen(integer channel, string name, key id, string message) + { process_menu_response(channel, name, id, message); } + + // if the timer goes off, then the user has ignored the menu for longer than the + // timeout. we need to turn off our listen and ignore that menu. + timer() { clear_menu(); } +} + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.lsl b/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.lsl deleted file mode 100755 index 4d56bac0..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.lsl +++ /dev/null @@ -1,541 +0,0 @@ - -// huffware script: noteworthy library, by fred huffhines. -// -// a handy approach to reading a notecard. this version supports requiring -// a 'signature' in the notecard's first line, so that multiple notecards can -// exist in an object without being misinterpreted. the script is accessed via -// its link message API, so it can be used in an object without all this code -// needing to be embedded in another script. it also supports queuing up requests -// to read notecards, so multiple scripts can use it to read their specific -// notecards without any special handling (besides waiting a bit longer). -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants that can be adapted to your needs... - -integer DEBUGGING = FALSE; - // if this is true, then a lot of extra noise is generated when notecards are read. - -float TIME_OUT_ON_ONE_NOTECARD = 42.0; - // we allow one line of a notecard this long to be read before we decide it's hosed. - // some sims are very very slow, and a time-out of one minute has been found lacking; - // we saw at least one case where the first notecard line to be read took longer than - // 60 seconds. that's why we kept cranking this time-out up... - -// constants that should not be changed... - -// outcomes from handling a line in a notecard. -integer STILL_READING = -8; // the notecard seems good, but isn't finished. -integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. -integer DONE_READING = -10; // the notecard is finished being read. - -integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. - -integer MAXIMUM_LINES_USED = 4; - // we will read this many lines at a time from the appropriate notecard. - -// this is the noteworthy library's API that is available via link messages. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. - -//STRIKE THIS from everywhere. -//string BUSY_READING_INDICATOR = "busy_already"; -// // this return value indicates that the script is already in use by some other script. -// // the calling script should try again later. - -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// global variables... - -string requested_signature = ""; - // if this is non-empty, then it must be found in the first line of the script. - -integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. - -string global_notecard_name; // the name of the card we're reading now. -key global_query_id = NULL_KEY; // the identifier of our data query. -integer current_response_code = 0; // the code that our client uses for its reading. -list global_query_contents; // the lines we have read from the notecard. - -integer line_number = 0; // which line are we at in notecard? - -integer found_signature_line = FALSE; // did we find our first line in a notecard yet? - -integer trying_notecard_at = -1; // where we are currently looking for a good notecard. - -list pending_signatures; // signatures from queued requests for reading. -list pending_response_codes; // response codes for the queued requests. -list pending_notecard_names; // card names if it's a specific request. - -////////////// - -startup_initialize() -{ - pending_signatures = []; - pending_response_codes = []; - pending_notecard_names = []; - current_response_code = 0; - llSetTimerEvent(0.0); -} - -reset_for_reading(string signature, integer response_code) -{ - requested_signature = signature; - current_response_code = response_code; - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. - global_query_contents = []; - global_notecard_name = ""; - line_number = 0; - found_signature_line = FALSE; - trying_notecard_at = -1; - global_query_id = NULL_KEY; -} - -// use the existing global notecard setting to start reading. -select_specific_notecard() -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - line_number = 0; // reset line number again. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// picks the notecard at the "index" (from 0 to num_notecards - 1) and -// starts reading it. -select_notecard(integer index) -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); - if (card_specified == "") return; // not good. bad index. - global_notecard_name = card_specified; - line_number = 0; // reset line number again. - // we have a new file name, so load up the destinations, hopefully. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// increments our index in the count of notecards that the object has, and start -// reading the next notecard (at the index). -integer try_next_notecard() -{ - if (only_read_one_notecard) { - return FALSE; // we were only going to try one. - } - // reset some values that might have applied before. - global_notecard_name = ""; - // skip to the next card. - trying_notecard_at++; - // make sure we're not over the count of cards. - if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { - // this is a problem. we didn't find anything suitable. - return FALSE; - } - // so, now we'll try the next notecard to look for our signature. - select_notecard(trying_notecard_at); - return TRUE; -} - -// process a line of text that we received from the current notecard. -integer handle_notecard_line(key query_id, string data) -{ - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - // there's more to read in the notecard still. - if (data != "") { - // make sure we even have a signature to look for. - if (!found_signature_line && (requested_signature == "")) { - // no signature means that we always find it. - found_signature_line = TRUE; - } - // did we already get our signature? if not, see if this is it. - if (!found_signature_line && (data != requested_signature) ) { - // this is a bad notecard. skip it. - if (!try_next_notecard()) { - // we have no more to work with. - return BAD_NOTECARD; - } - return STILL_READING; // we'll keep going. - } else if (!found_signature_line && (data == requested_signature) ) { - // this is a good signature line, so record that and then skip it. - found_signature_line = TRUE; - } else { - if (DEBUGGING - && ( ( (requested_signature == "") && (line_number == 0) ) - || ( (requested_signature != "") && (line_number == 1) ) ) ) { - log_it("started reading " + global_notecard_name + "..."); - } - // don't record any lines that are comments. - if ( (llGetSubString(data, 0, 0) != "#") - && (llGetSubString(data, 0, 0) != ";") ) { - // add the non-blank line to our list. - global_query_contents += data; - // make sure we still have enough space to keep going. - if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { - // ooh, make sure we pause before blowing our heap&stack. - send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, - current_response_code ], READ_NOTECARD_COMMAND, TRUE); - } - } - } - } - line_number++; // increase the line count. - // reset the timer rather than timing out, if we actually got some data. - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); - // request the next line from the notecard. - global_query_id = llGetNotecardLine(global_notecard_name, line_number); - if (global_query_id == NULL_KEY) { -//log_it("failed to restart notecard reading."); - return DONE_READING; -//is that the best outcome? - } - return STILL_READING; - } else { - // that's the end of the notecard. we need some minimal verification that it - // wasn't full of garbage. - if (!found_signature_line) { - if (DEBUGGING) log_it("never found signature in " + global_notecard_name); - if (!try_next_notecard()) { - return BAD_NOTECARD; // we failed to find a good line? - } else { - // the next notecard's coming through now. - return STILL_READING; - } - } else { -// if (DEBUGGING) log_it("found signature."); - // saw the signature line, so this is a good one. - return DONE_READING; - } - } -} - -// only sends reply; does not reset notecard process. -send_reply(integer destination, list parms, string command, - integer include_query) -{ -//integer items = llGetListLength(parms); -//if (include_query) items += llGetListLength(global_query_contents); -//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); - - if (!include_query) { - llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - } else { - llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, - llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); - } - global_query_contents = []; -//log_it("post-sending, mem=" + (string)llGetFreeMemory()); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply_and_reset(integer destination, list parms, string command, - integer include_query) -{ - llSetTimerEvent(0.0); // stop the timer, since we're about to reply. - send_reply(destination, parms, command, include_query); - current_response_code = 0; // reset back to default so we can start another read. - global_query_id = NULL_KEY; // reset so we accept no more data. -} - -// if there are other pending notecard reads, this goes to the next one listed. -dequeue_next_request() -{ - if (llGetListLength(pending_signatures)) { - // get the info from the next pending item. - string sig = llList2String(pending_signatures, 0); - integer response_code = llList2Integer(pending_response_codes, 0); - string notecard = llList2String(pending_notecard_names, 0); - // whack the head of the queue since we grabbed the info. - pending_signatures = llDeleteSubList(pending_signatures, 0, 0); - pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); - pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); - if (llStringLength(notecard)) { - global_notecard_name = notecard; - select_specific_notecard(); - } else { - reset_for_reading(sig, response_code); - } - } -} - -// deals with one data server answer from the notecard. -process_notecard_line(key query_id, string data) -{ - // try to consume a line from the notecard. - integer outcome = handle_notecard_line(query_id, data); - if (outcome == DONE_READING) { - // that was a valid notecard and we read all of it. - if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); - // send back the results. - send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], - READ_NOTECARD_COMMAND, TRUE); - } else if (outcome == BAD_NOTECARD) { - // bail; this problem must be addressed by other means. - if (DEBUGGING) log_it("failed to find an appropriate notecard"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } else if (outcome == STILL_READING) { - // we have a good card and are still processing it. - return; - } else { - if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); - // again, bail out. we have no idea what happened with this. - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } - // if we have reached here, we should crank up the next queued notecard reading. - dequeue_next_request(); -} - -// processes requests from our users. -handle_link_message(integer which, integer num, string msg, key id) -{ - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - - if (msg == READ_NOTECARD_COMMAND) { - only_read_one_notecard = FALSE; // general inquiry for any card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read notecard--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code = llList2Integer(parms, 1); -//log_it("got signature " + signature + " and respcode " + (string)response_code); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code); - if (!try_next_notecard()) { - if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code ], - READ_NOTECARD_COMMAND, FALSE); - return; - } -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code; -//holding: pending_notecard_names += ""; -//holding: } - } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { - only_read_one_notecard = TRUE; // they want one particular card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read specific--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code = llList2Integer(parms, 1); - string notecard_name = llList2String(parms, 2); -//log_it("got signature " + signature + " and respcode " + (string)response_code); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code); - global_notecard_name = notecard_name; // set our global. - select_specific_notecard(); -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code; -//holding: pending_notecard_names += notecard_name; -//holding: } - } -} - - -/////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, (string)debug_num + "- " + to_say); -} - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - startup_initialize(); - } - - state_exit() { - llSetTimerEvent(0); - } - - // we don't do anything until we're given a command to read a notecard. - link_message(integer which, integer num, string msg, key id) - { - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - handle_link_message(which, num, msg, id); - } - - on_rez(integer parm) { state rerun; } - - timer() { - llSetTimerEvent(0.0); // stop any timer now. - // let the caller know this has failed out. -// if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - current_response_code = 0; // we gave up on that one. - dequeue_next_request(); // get next reading started if we have anything to read. - } - - dataserver(key query_id, string data) { - // make sure this data is for us. - if (global_query_id != query_id) return; - // yep, seems to be. - process_notecard_line(query_id, data); - } -} - - - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.txt b/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.txt new file mode 100755 index 00000000..4d56bac0 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/noteworthy_library_v12.4.txt @@ -0,0 +1,541 @@ + +// huffware script: noteworthy library, by fred huffhines. +// +// a handy approach to reading a notecard. this version supports requiring +// a 'signature' in the notecard's first line, so that multiple notecards can +// exist in an object without being misinterpreted. the script is accessed via +// its link message API, so it can be used in an object without all this code +// needing to be embedded in another script. it also supports queuing up requests +// to read notecards, so multiple scripts can use it to read their specific +// notecards without any special handling (besides waiting a bit longer). +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants that can be adapted to your needs... + +integer DEBUGGING = FALSE; + // if this is true, then a lot of extra noise is generated when notecards are read. + +float TIME_OUT_ON_ONE_NOTECARD = 42.0; + // we allow one line of a notecard this long to be read before we decide it's hosed. + // some sims are very very slow, and a time-out of one minute has been found lacking; + // we saw at least one case where the first notecard line to be read took longer than + // 60 seconds. that's why we kept cranking this time-out up... + +// constants that should not be changed... + +// outcomes from handling a line in a notecard. +integer STILL_READING = -8; // the notecard seems good, but isn't finished. +integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. +integer DONE_READING = -10; // the notecard is finished being read. + +integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. + +integer MAXIMUM_LINES_USED = 4; + // we will read this many lines at a time from the appropriate notecard. + +// this is the noteworthy library's API that is available via link messages. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. + +//STRIKE THIS from everywhere. +//string BUSY_READING_INDICATOR = "busy_already"; +// // this return value indicates that the script is already in use by some other script. +// // the calling script should try again later. + +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// global variables... + +string requested_signature = ""; + // if this is non-empty, then it must be found in the first line of the script. + +integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. + +string global_notecard_name; // the name of the card we're reading now. +key global_query_id = NULL_KEY; // the identifier of our data query. +integer current_response_code = 0; // the code that our client uses for its reading. +list global_query_contents; // the lines we have read from the notecard. + +integer line_number = 0; // which line are we at in notecard? + +integer found_signature_line = FALSE; // did we find our first line in a notecard yet? + +integer trying_notecard_at = -1; // where we are currently looking for a good notecard. + +list pending_signatures; // signatures from queued requests for reading. +list pending_response_codes; // response codes for the queued requests. +list pending_notecard_names; // card names if it's a specific request. + +////////////// + +startup_initialize() +{ + pending_signatures = []; + pending_response_codes = []; + pending_notecard_names = []; + current_response_code = 0; + llSetTimerEvent(0.0); +} + +reset_for_reading(string signature, integer response_code) +{ + requested_signature = signature; + current_response_code = response_code; + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. + global_query_contents = []; + global_notecard_name = ""; + line_number = 0; + found_signature_line = FALSE; + trying_notecard_at = -1; + global_query_id = NULL_KEY; +} + +// use the existing global notecard setting to start reading. +select_specific_notecard() +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + line_number = 0; // reset line number again. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// picks the notecard at the "index" (from 0 to num_notecards - 1) and +// starts reading it. +select_notecard(integer index) +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); + if (card_specified == "") return; // not good. bad index. + global_notecard_name = card_specified; + line_number = 0; // reset line number again. + // we have a new file name, so load up the destinations, hopefully. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// increments our index in the count of notecards that the object has, and start +// reading the next notecard (at the index). +integer try_next_notecard() +{ + if (only_read_one_notecard) { + return FALSE; // we were only going to try one. + } + // reset some values that might have applied before. + global_notecard_name = ""; + // skip to the next card. + trying_notecard_at++; + // make sure we're not over the count of cards. + if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { + // this is a problem. we didn't find anything suitable. + return FALSE; + } + // so, now we'll try the next notecard to look for our signature. + select_notecard(trying_notecard_at); + return TRUE; +} + +// process a line of text that we received from the current notecard. +integer handle_notecard_line(key query_id, string data) +{ + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + // there's more to read in the notecard still. + if (data != "") { + // make sure we even have a signature to look for. + if (!found_signature_line && (requested_signature == "")) { + // no signature means that we always find it. + found_signature_line = TRUE; + } + // did we already get our signature? if not, see if this is it. + if (!found_signature_line && (data != requested_signature) ) { + // this is a bad notecard. skip it. + if (!try_next_notecard()) { + // we have no more to work with. + return BAD_NOTECARD; + } + return STILL_READING; // we'll keep going. + } else if (!found_signature_line && (data == requested_signature) ) { + // this is a good signature line, so record that and then skip it. + found_signature_line = TRUE; + } else { + if (DEBUGGING + && ( ( (requested_signature == "") && (line_number == 0) ) + || ( (requested_signature != "") && (line_number == 1) ) ) ) { + log_it("started reading " + global_notecard_name + "..."); + } + // don't record any lines that are comments. + if ( (llGetSubString(data, 0, 0) != "#") + && (llGetSubString(data, 0, 0) != ";") ) { + // add the non-blank line to our list. + global_query_contents += data; + // make sure we still have enough space to keep going. + if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { + // ooh, make sure we pause before blowing our heap&stack. + send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, + current_response_code ], READ_NOTECARD_COMMAND, TRUE); + } + } + } + } + line_number++; // increase the line count. + // reset the timer rather than timing out, if we actually got some data. + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); + // request the next line from the notecard. + global_query_id = llGetNotecardLine(global_notecard_name, line_number); + if (global_query_id == NULL_KEY) { +//log_it("failed to restart notecard reading."); + return DONE_READING; +//is that the best outcome? + } + return STILL_READING; + } else { + // that's the end of the notecard. we need some minimal verification that it + // wasn't full of garbage. + if (!found_signature_line) { + if (DEBUGGING) log_it("never found signature in " + global_notecard_name); + if (!try_next_notecard()) { + return BAD_NOTECARD; // we failed to find a good line? + } else { + // the next notecard's coming through now. + return STILL_READING; + } + } else { +// if (DEBUGGING) log_it("found signature."); + // saw the signature line, so this is a good one. + return DONE_READING; + } + } +} + +// only sends reply; does not reset notecard process. +send_reply(integer destination, list parms, string command, + integer include_query) +{ +//integer items = llGetListLength(parms); +//if (include_query) items += llGetListLength(global_query_contents); +//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); + + if (!include_query) { + llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + } else { + llMessageLinked(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, + llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); + } + global_query_contents = []; +//log_it("post-sending, mem=" + (string)llGetFreeMemory()); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply_and_reset(integer destination, list parms, string command, + integer include_query) +{ + llSetTimerEvent(0.0); // stop the timer, since we're about to reply. + send_reply(destination, parms, command, include_query); + current_response_code = 0; // reset back to default so we can start another read. + global_query_id = NULL_KEY; // reset so we accept no more data. +} + +// if there are other pending notecard reads, this goes to the next one listed. +dequeue_next_request() +{ + if (llGetListLength(pending_signatures)) { + // get the info from the next pending item. + string sig = llList2String(pending_signatures, 0); + integer response_code = llList2Integer(pending_response_codes, 0); + string notecard = llList2String(pending_notecard_names, 0); + // whack the head of the queue since we grabbed the info. + pending_signatures = llDeleteSubList(pending_signatures, 0, 0); + pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); + pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); + if (llStringLength(notecard)) { + global_notecard_name = notecard; + select_specific_notecard(); + } else { + reset_for_reading(sig, response_code); + } + } +} + +// deals with one data server answer from the notecard. +process_notecard_line(key query_id, string data) +{ + // try to consume a line from the notecard. + integer outcome = handle_notecard_line(query_id, data); + if (outcome == DONE_READING) { + // that was a valid notecard and we read all of it. + if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); + // send back the results. + send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], + READ_NOTECARD_COMMAND, TRUE); + } else if (outcome == BAD_NOTECARD) { + // bail; this problem must be addressed by other means. + if (DEBUGGING) log_it("failed to find an appropriate notecard"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } else if (outcome == STILL_READING) { + // we have a good card and are still processing it. + return; + } else { + if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); + // again, bail out. we have no idea what happened with this. + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } + // if we have reached here, we should crank up the next queued notecard reading. + dequeue_next_request(); +} + +// processes requests from our users. +handle_link_message(integer which, integer num, string msg, key id) +{ + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + + if (msg == READ_NOTECARD_COMMAND) { + only_read_one_notecard = FALSE; // general inquiry for any card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read notecard--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code = llList2Integer(parms, 1); +//log_it("got signature " + signature + " and respcode " + (string)response_code); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code); + if (!try_next_notecard()) { + if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code ], + READ_NOTECARD_COMMAND, FALSE); + return; + } +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code; +//holding: pending_notecard_names += ""; +//holding: } + } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { + only_read_one_notecard = TRUE; // they want one particular card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read specific--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code = llList2Integer(parms, 1); + string notecard_name = llList2String(parms, 2); +//log_it("got signature " + signature + " and respcode " + (string)response_code); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code); + global_notecard_name = notecard_name; // set our global. + select_specific_notecard(); +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code; +//holding: pending_notecard_names += notecard_name; +//holding: } + } +} + + +/////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, (string)debug_num + "- " + to_say); +} + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + startup_initialize(); + } + + state_exit() { + llSetTimerEvent(0); + } + + // we don't do anything until we're given a command to read a notecard. + link_message(integer which, integer num, string msg, key id) + { + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + handle_link_message(which, num, msg, id); + } + + on_rez(integer parm) { state rerun; } + + timer() { + llSetTimerEvent(0.0); // stop any timer now. + // let the caller know this has failed out. +// if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + current_response_code = 0; // we gave up on that one. + dequeue_next_request(); // get next reading started if we have anything to read. + } + + dataserver(key query_id, string data) { + // make sure this data is for us. + if (global_query_id != query_id) return; + // yep, seems to be. + process_notecard_line(query_id, data); + } +} + + + diff --git a/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.lsl b/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.lsl deleted file mode 100755 index 57a1e641..00000000 --- a/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.lsl +++ /dev/null @@ -1,237 +0,0 @@ - -// huffware script: texture mover, by fred huffhines -// -// moves a texture across the object, either by smooth animation or brute force offsetting. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -integer USE_TEXTURE_ANIMATION = TRUE; - // by default, we use texture animation which is a lower-lag way to - // make the texture move. if this is false, then we use a timed update - // to move the texture instead. - // note: these modes are actually really different. the texture animation - // is included here because i wanted to smooth out some objects that used - // texture movement. - -// used in both types... - -float TIMER_INTERVAL = 0.2; // how fast do we move texture? - -// for timed movement... - -vector OFFSET_MOVEMENT = ZERO_VECTOR; // no movement. -//vector OFFSET_MOVEMENT = <0.0, -0.02, 0.0>; - // how much to move the texture by in x,y,z directions. - -//float OFFSET_ROTATION = 0.0; // in degrees. -float OFFSET_ROTATION = -1.0; // in degrees. - -// for texture animations... - -float MOVER_TIMER_DIVISOR = 30.0; - // makes the movement comparable to timed method. - -float ROTATER_TIMER_DIVISOR = 7.0; - // makes the rotation comparable to timed method. - -// iterative movement of texture. -move_texture(vector offset) -{ - vector current = llGetTextureOffset(ALL_SIDES); - current += offset; - if (current.x > 1.0) current.x = -1.0; - if (current.x < -1.0) current.x = 1.0; - if (current.y > 1.0) current.y = -1.0; - if (current.y < -1.0) current.y = 1.0; - llOffsetTexture(current.x, current.y, ALL_SIDES); -} - -// iterative rotation of texture. "spin" is measured in degrees. -spin_texture(float spin) -{ - float rot = llGetTextureRot(ALL_SIDES); // get our current state. - rot += spin * DEG_TO_RAD; // add some rotation. - llRotateTexture(rot, ALL_SIDES); //rotate the object -} - -initialize_texture_mover() -{ - if (!USE_TEXTURE_ANIMATION) { - // we're stuck with the timed update style for movement. - llSetTimerEvent(TIMER_INTERVAL); - // turn off previous animation. - llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); - } else { - // we can just set the texture movement here and be done with it. - integer x_frames = 1; - integer y_frames = 1; - llSetTimerEvent(0); // we don't use a timer. - -//hmmm: how do we combine rotation and offsets? currently mutually exclusive. - - if (OFFSET_MOVEMENT != ZERO_VECTOR) { - float timer_interval = TIMER_INTERVAL / MOVER_TIMER_DIVISOR; -log_it("getting x_frames=" + (string)x_frames -+ " y_frames=" + (string)y_frames -+ " timer_intvl=" + (string)timer_interval); - - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, - x_frames, y_frames, - 0, 100, timer_interval); - } else if (OFFSET_ROTATION != 0.0) { - float timer_interval = TIMER_INTERVAL / ROTATER_TIMER_DIVISOR; - // we're actually not using the rotation at all here, except for - // the sign. that seems pretty busted. - if (OFFSET_ROTATION < 0) timer_interval *= -1.0; - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, ALL_SIDES, - 0, 0, - 0, TWO_PI, timer_interval); - } - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} -// -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize_texture_mover(); - } - - timer() { - // the timed approach is the only one so far that allows both a - // movement of the texture and a rotation. - if (OFFSET_MOVEMENT != ZERO_VECTOR) move_texture(OFFSET_MOVEMENT); - if (OFFSET_ROTATION != 0.0) spin_texture(OFFSET_ROTATION); - } -} - diff --git a/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.txt b/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.txt new file mode 100755 index 00000000..57a1e641 --- /dev/null +++ b/huffware/huffotronic_jaunter_updater_v5.1/texture_mover_v3.0.txt @@ -0,0 +1,237 @@ + +// huffware script: texture mover, by fred huffhines +// +// moves a texture across the object, either by smooth animation or brute force offsetting. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +integer USE_TEXTURE_ANIMATION = TRUE; + // by default, we use texture animation which is a lower-lag way to + // make the texture move. if this is false, then we use a timed update + // to move the texture instead. + // note: these modes are actually really different. the texture animation + // is included here because i wanted to smooth out some objects that used + // texture movement. + +// used in both types... + +float TIMER_INTERVAL = 0.2; // how fast do we move texture? + +// for timed movement... + +vector OFFSET_MOVEMENT = ZERO_VECTOR; // no movement. +//vector OFFSET_MOVEMENT = <0.0, -0.02, 0.0>; + // how much to move the texture by in x,y,z directions. + +//float OFFSET_ROTATION = 0.0; // in degrees. +float OFFSET_ROTATION = -1.0; // in degrees. + +// for texture animations... + +float MOVER_TIMER_DIVISOR = 30.0; + // makes the movement comparable to timed method. + +float ROTATER_TIMER_DIVISOR = 7.0; + // makes the rotation comparable to timed method. + +// iterative movement of texture. +move_texture(vector offset) +{ + vector current = llGetTextureOffset(ALL_SIDES); + current += offset; + if (current.x > 1.0) current.x = -1.0; + if (current.x < -1.0) current.x = 1.0; + if (current.y > 1.0) current.y = -1.0; + if (current.y < -1.0) current.y = 1.0; + llOffsetTexture(current.x, current.y, ALL_SIDES); +} + +// iterative rotation of texture. "spin" is measured in degrees. +spin_texture(float spin) +{ + float rot = llGetTextureRot(ALL_SIDES); // get our current state. + rot += spin * DEG_TO_RAD; // add some rotation. + llRotateTexture(rot, ALL_SIDES); //rotate the object +} + +initialize_texture_mover() +{ + if (!USE_TEXTURE_ANIMATION) { + // we're stuck with the timed update style for movement. + llSetTimerEvent(TIMER_INTERVAL); + // turn off previous animation. + llSetTextureAnim(0, ALL_SIDES, 0, 0, 0, 0, 0); + } else { + // we can just set the texture movement here and be done with it. + integer x_frames = 1; + integer y_frames = 1; + llSetTimerEvent(0); // we don't use a timer. + +//hmmm: how do we combine rotation and offsets? currently mutually exclusive. + + if (OFFSET_MOVEMENT != ZERO_VECTOR) { + float timer_interval = TIMER_INTERVAL / MOVER_TIMER_DIVISOR; +log_it("getting x_frames=" + (string)x_frames ++ " y_frames=" + (string)y_frames ++ " timer_intvl=" + (string)timer_interval); + + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, + x_frames, y_frames, + 0, 100, timer_interval); + } else if (OFFSET_ROTATION != 0.0) { + float timer_interval = TIMER_INTERVAL / ROTATER_TIMER_DIVISOR; + // we're actually not using the rotation at all here, except for + // the sign. that seems pretty busted. + if (OFFSET_ROTATION < 0) timer_interval *= -1.0; + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, ALL_SIDES, + 0, 0, + 0, TWO_PI, timer_interval); + } + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} +// +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize_texture_mover(); + } + + timer() { + // the timed approach is the only one so far that allows both a + // movement of the texture and a rotation. + if (OFFSET_MOVEMENT != ZERO_VECTOR) move_texture(OFFSET_MOVEMENT); + if (OFFSET_ROTATION != 0.0) spin_texture(OFFSET_ROTATION); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.lsl b/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.lsl deleted file mode 100755 index 7027c395..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.lsl +++ /dev/null @@ -1,109 +0,0 @@ - -// huffware script: hour hand, modified by fred huffhines. -// -// expanded to support time zones by fred huffhines, december 2009. -// -// noticed this in arcadia asylum's great hobo cuckoo clock. -// this script is licensed by Beezle Warburton: -// "I released those 'into the wild' years ago,do what you like, -// I just ask that people don't resell the scripts by themselves." -// -// fred's changes licensed by: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. - -// Optional second hand will be a much simpler script that will be -// unrelated to real-time. -// -// note - to reduce load, this script only calculates once a minute, so -// this provides a jump style minute hand, rather than a smoothy rotating one. -// This (and rounding) makes the clock's accuracy +/- 1 minute. -// It's a prim clock anyways, so digital accuracy is just excessive. -// -// It would probably be more elegant to use link messages rather than each -// hand having it's own script, however, this method allows for less caution -// when linking/unlinking parts of the clock. - -// To not mess up timekeeping, please keep chime sounds under 4 seconds long. - -integer time; -integer hours; -integer minutes; - -float anglehours; -float angleminutes; - -integer chime; -integer numrings; - -string chimesound = "CuckooClock"; -float chimevolume = 1.0; - -// this is what might be adjusted. -integer LOCAL_TIME_ZONE_OFFSET = -5; //-5 is EST, -8 is PST. - -// the code used in linked messages for us. -integer SECRET_TIME_ZONE_ADJUSTER_ID = -2091823; -string TIME_ZONE_ADJUST_COMMAND = "tzadjust"; - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - // we want to calculate once a minute. - llSetTimerEvent(60.0); - } - timer() { - llSetTimerEvent(0); - time = (integer)llGetGMTclock(); // seconds since midnight - // adjust the hours for the time zone. this will work for most time zones that - // go through daylight saving time, like the pacific zone where SL is rooted. - hours = (time / 3600) + LOCAL_TIME_ZONE_OFFSET; - // convert from 24 to 12 hour time - if (hours > 11) { - hours = hours - 12; - } else if (hours < 0) { - hours = hours + 12; - } - minutes = (time % 3600) / 60; - - numrings = (integer)hours; - if (numrings == 0) { - numrings = 12; - } - - // the extra addition here makes a smooth hour hand - // for example, at 6:30, the hour hand should actually - // be halfway between 6 and 7 on the clock dial - - anglehours = - (((float)hours / 12) + (((float)minutes / 720))) * TWO_PI; -//incompatible with opensim: llSetSoundQueueing(TRUE); - llRotateTexture(anglehours, ALL_SIDES); - if (minutes == 0) { - llMessageLinked(-1,numrings,"chime",NULL_KEY); - //for (chime = 0; chime < numrings; chime++) { - // llPlaySound(chimesound, chimevolume); - // llSleep(3.0); - //} - } - llSetTimerEvent(60.0); - } - - link_message(integer sender, integer num, string msg, key id) { - if ( (num != SECRET_TIME_ZONE_ADJUSTER_ID) || (msg != TIME_ZONE_ADJUST_COMMAND) ) - return; // not for us. - // this should be a time zone for us to use. - LOCAL_TIME_ZONE_OFFSET = (integer)((string)id); -//llSay(0, "got a new time zone of " + (string)LOCAL_TIME_ZONE_OFFSET ); - // handle this update as soon as possible. - llSetTimerEvent(0.1); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.txt b/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.txt new file mode 100755 index 00000000..7027c395 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/Hour_Hand_v0.5.txt @@ -0,0 +1,109 @@ + +// huffware script: hour hand, modified by fred huffhines. +// +// expanded to support time zones by fred huffhines, december 2009. +// +// noticed this in arcadia asylum's great hobo cuckoo clock. +// this script is licensed by Beezle Warburton: +// "I released those 'into the wild' years ago,do what you like, +// I just ask that people don't resell the scripts by themselves." +// +// fred's changes licensed by: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. + +// Optional second hand will be a much simpler script that will be +// unrelated to real-time. +// +// note - to reduce load, this script only calculates once a minute, so +// this provides a jump style minute hand, rather than a smoothy rotating one. +// This (and rounding) makes the clock's accuracy +/- 1 minute. +// It's a prim clock anyways, so digital accuracy is just excessive. +// +// It would probably be more elegant to use link messages rather than each +// hand having it's own script, however, this method allows for less caution +// when linking/unlinking parts of the clock. + +// To not mess up timekeeping, please keep chime sounds under 4 seconds long. + +integer time; +integer hours; +integer minutes; + +float anglehours; +float angleminutes; + +integer chime; +integer numrings; + +string chimesound = "CuckooClock"; +float chimevolume = 1.0; + +// this is what might be adjusted. +integer LOCAL_TIME_ZONE_OFFSET = -5; //-5 is EST, -8 is PST. + +// the code used in linked messages for us. +integer SECRET_TIME_ZONE_ADJUSTER_ID = -2091823; +string TIME_ZONE_ADJUST_COMMAND = "tzadjust"; + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + // we want to calculate once a minute. + llSetTimerEvent(60.0); + } + timer() { + llSetTimerEvent(0); + time = (integer)llGetGMTclock(); // seconds since midnight + // adjust the hours for the time zone. this will work for most time zones that + // go through daylight saving time, like the pacific zone where SL is rooted. + hours = (time / 3600) + LOCAL_TIME_ZONE_OFFSET; + // convert from 24 to 12 hour time + if (hours > 11) { + hours = hours - 12; + } else if (hours < 0) { + hours = hours + 12; + } + minutes = (time % 3600) / 60; + + numrings = (integer)hours; + if (numrings == 0) { + numrings = 12; + } + + // the extra addition here makes a smooth hour hand + // for example, at 6:30, the hour hand should actually + // be halfway between 6 and 7 on the clock dial + + anglehours = - (((float)hours / 12) + (((float)minutes / 720))) * TWO_PI; +//incompatible with opensim: llSetSoundQueueing(TRUE); + llRotateTexture(anglehours, ALL_SIDES); + if (minutes == 0) { + llMessageLinked(-1,numrings,"chime",NULL_KEY); + //for (chime = 0; chime < numrings; chime++) { + // llPlaySound(chimesound, chimevolume); + // llSleep(3.0); + //} + } + llSetTimerEvent(60.0); + } + + link_message(integer sender, integer num, string msg, key id) { + if ( (num != SECRET_TIME_ZONE_ADJUSTER_ID) || (msg != TIME_ZONE_ADJUST_COMMAND) ) + return; // not for us. + // this should be a time zone for us to use. + LOCAL_TIME_ZONE_OFFSET = (integer)((string)id); +//llSay(0, "got a new time zone of " + (string)LOCAL_TIME_ZONE_OFFSET ); + // handle this update as soon as possible. + llSetTimerEvent(0.1); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.lsl b/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.lsl deleted file mode 100755 index 76b517a3..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.lsl +++ /dev/null @@ -1,41 +0,0 @@ - -// huffware script: minute hand, modified by fred huffhines. -// -// noticed this in arcadia asylum's great hobo cuckoo clock. -// this script is licensed by Beezle Warburton: -// "I released those 'into the wild' years ago,do what you like, -// I just ask that people don't resell the scripts by themselves." -// -// fred's changes licensed by: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer time; -integer hours; -integer minutes; - -float anglehours; -float angleminutes; - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - // we want to calculate once a minute. - llSetTimerEvent(60.0); - } - - timer() { - time = (integer)llGetGMTclock(); // seconds since midnight - minutes = (time % 3600) / 60; - angleminutes = -(TWO_PI * (float)minutes / 60); - llRotateTexture(angleminutes, ALL_SIDES); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.txt b/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.txt new file mode 100755 index 00000000..76b517a3 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/Minute_Hand_v0.4.txt @@ -0,0 +1,41 @@ + +// huffware script: minute hand, modified by fred huffhines. +// +// noticed this in arcadia asylum's great hobo cuckoo clock. +// this script is licensed by Beezle Warburton: +// "I released those 'into the wild' years ago,do what you like, +// I just ask that people don't resell the scripts by themselves." +// +// fred's changes licensed by: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer time; +integer hours; +integer minutes; + +float anglehours; +float angleminutes; + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + // we want to calculate once a minute. + llSetTimerEvent(60.0); + } + + timer() { + time = (integer)llGetGMTclock(); // seconds since midnight + minutes = (time % 3600) / 60; + angleminutes = -(TWO_PI * (float)minutes / 60); + llRotateTexture(angleminutes, ALL_SIDES); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.lsl b/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.lsl deleted file mode 100755 index 60a6a3c0..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.lsl +++ /dev/null @@ -1,392 +0,0 @@ - -// huffware script: stay at home, by fred huffhines -// -// this script attempts to keep an object at home, which is to say, near where -// it was rezzed. it is not perfect, and if the object quickly crosses a region -// boundary, the object may get away. there is an automatic termination option -// for cases where the object is taken away and cannot get back; otherwise the -// object will bleat its position out at regular intevals. -// this script mainly makes sense for physical objects, since non-physical -// objects are not as prone to being pushed around by other avatars. in addition, -// it really makes the most sense for an object that allows anyone to move it. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants to be adjusted as needed... - -float MAXIMUM_ROAMING_RANGE = 12.0; - // this is the farthest that we let them drag our object away, in meters. - -integer AUTO_TERMINATE = FALSE; - // if the object crosses a region boundary (exits sim, enters new one), then - // it will zap itself if this flag is set to true. it will also go poof if - // it reaches escape velocity and travels off world. - -integer KEEP_IT_PHYSICAL = TRUE; - // if this is true, then the object's state as physical is continually - // refreshed. - -integer ROTATE_TO_TARGET = FALSE; - // if this is true, the object will try to rotate to a set position. - -integer ONLY_ROTATE_FIXED_AXES = FALSE; - // if this is true and rotate to target is true, then we will only try to - // set the rotation on the axes that are specified as "fixed" below. - -vector TARGETED_ROTATION = <0.0, 0.0, 0.0>; - // if the control rotation flag is true, the object will try to reattain - // this value for its rotation. - -// if these are set to true, the no rotation is allowed around the axis. -// note that this decision is totally independent of whether the object has -// a targeted rotation or not. -integer FIXATE_X_AXIS = FALSE; -integer FIXATE_Y_AXIS = FALSE; -integer FIXATE_Z_AXIS = FALSE; - -integer MAXIMUM_FAILED_JUMPS = 200; - // if we are having to make this many attempts to get home, something is - // really wrong. treat it like leaving the region; totally awol. - -float POSITION_CHECKING_INTERVAL = 8.0; - // how frequently the object will check where it is, in seconds. - -float PANIC_EVERY_N_HOURS = 4.0; - // this is the number of hours between panic mewling at the owner, if the object - // did not get told to self-terminate upon leaving the region. - -integer DEBUGGING = FALSE; - // if this is true, then the object will tell about it's problems when it - // goes off world or into another sim. note that an object that is not - // set to auto-terminate is considered important enough to tell the owner; - // if you don't want to hear from lost objects, always turn on auto-terminate - // and turn off debugging. - -// these mysterious values control how the object rotates to its target. -float ROT_STRENGTH = 1.0; -float ROT_DAMPING = 0.25; -//these values don't work that great, but neither did any other ones. -// the rotlookat stuff seems overpowered by the physical nature of an object. - -// global variables... - -vector home_place; - // where the object starts out inside the sim. we will try to get back - // to here if we exceed our maximum distance from home. - -vector home_region; - // which sim we start out in, in terms of the region corners. if this changes, - // the object has left the sim. - -integer homeward_jump_attempts = 0; - // tracks how many jumps home we've tried to make. - -integer last_alerted = 0; - // when the script last told the user about having gone missing. - // if this is zero, we presumably haven't been lost recently. - -// requires jaunting library v10.5 or greater. -////////////// -// do not redefine these constants. -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -// commands available via the jaunting library: -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. pass a vector with the location. -string JAUNT_LIST_COMMAND = "#jauntlist#"; - // like regular jaunt, but expects a list of vectors as the first parameter; this list - // should be in the jaunter notecard format (separated by pipe characters). - // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -// -// encases a list of vectors in the expected character for the jaunting library. -string wrap_vector_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -////////////// - -// asks the jaunting library to take us to the target using a list of waypoints. -request_jaunt(list full_journey, integer forwards) -{ -// jaunt_responses_awaited++; - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, - wrap_vector_list(full_journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); -} - -// jaunts back to our home location. -attempt_to_go_home() -{ - // jump back to home. - request_jaunt([llGetPos(), home_place], TRUE); -} - -// we panic at the user this frequently, in seconds. -float panic_interval() { return PANIC_EVERY_N_HOURS * 60.0 * 60.0; } - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. - // we just woke up here. remember where we started out. - home_place = llGetPos(); - home_region = llGetRegionCorner(); - if (AUTO_TERMINATE) { - // make the object go kerflooey if it leaves the world entirely. - llSetStatus(STATUS_DIE_AT_EDGE, TRUE); - } - // disallow rotation if we were requested to. - llSetStatus(STATUS_ROTATE_X, !FIXATE_X_AXIS); - llSetStatus(STATUS_ROTATE_Y, !FIXATE_Y_AXIS); - llSetStatus(STATUS_ROTATE_Z, !FIXATE_Z_AXIS); - - if (ROTATE_TO_TARGET) { -//hmmm: maybe still offer gradual form as an option also? - - // set our rotational target to the configured position. -// llRotTarget(llEuler2Rot(TARGETED_ROTATION), 0.01); - // if we're supposed to rotate, we need to start that movement - // towards our target rotation. -// llRotLookAt(llEuler2Rot(TARGETED_ROTATION), ROT_STRENGTH, ROT_DAMPING); - } - // start the timer that checks on our position. - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - } - - on_rez(integer parm) { - llResetScript(); // a cop-out; just reroutes rezzing into a script reset. - } - - timer() { - - if (ROTATE_TO_TARGET) { - vector real_rot_target = TARGETED_ROTATION; - vector curr_rot = llRot2Euler(llGetRot()); - - if (ONLY_ROTATE_FIXED_AXES) { - // set our rotation to the target, but only for fixed axes. - if (!FIXATE_X_AXIS) real_rot_target.x = curr_rot.x; - if (!FIXATE_Y_AXIS) real_rot_target.y = curr_rot.y; - if (!FIXATE_Z_AXIS) real_rot_target.z = curr_rot.z; - } - - // see if we even need to do any rotation. - if (curr_rot != real_rot_target) { - // yes, we need to move back to the preferred rotation for at least one axis. - llSetStatus(STATUS_PHYSICS, FALSE); // physics property gets fixed in next block. - llSetRot(llEuler2Rot(real_rot_target)); - } - } - - if (KEEP_IT_PHYSICAL) { - // remind the object that it's physical, or set it if it wasn't. sometimes - // a physical object can get jinxed when bouncing into other people's lands - // and lose its status as a physical object. we correct for that here. - llSetStatus(STATUS_PHYSICS, TRUE); - } - - integer time_to_panic = FALSE; // set to true if we should panic now. - - // check whether the object is still in the appropriate region. - integer region_okay = (home_region == llGetRegionCorner()); - - // check to see if we're watching for a specific time. - if (last_alerted != 0) { - // ooh, we've already hit panicky conditions in the past. let's see if - // it's time to tell the owner about it. - if (panic_interval() <= llAbs(llGetUnixTime() - last_alerted)) { - // time to tell them about this, oh yes. - time_to_panic = TRUE; - } - } else { - // evaluate whether we are in the right condition (right sim and - // without being boxed in). - if (!region_okay || (homeward_jump_attempts > MAXIMUM_FAILED_JUMPS)) { - // this is not a good situation. we will now set the last alerted - // timer so as to force a panic message next time through the timer - // loop. - last_alerted = llAbs(llGetUnixTime() - (integer)panic_interval() - 1000); - // decide when to fire the timer next. - if (AUTO_TERMINATE) { - llSetTimerEvent(0.1); // fire very soon to zap. - } else { - llSetTimerEvent(POSITION_CHECKING_INTERVAL * 5); - // slow the checking down a bit, since we don't expect to - // magically get back to our sim (although it could happen!). - } - } - } - - // time to panic just means that we should tell the owner about our problematic - // location, or auto-terminate if configured that way. - if (time_to_panic) { - // well, we've got to say something about this dire situation. - string reason = "trapped by unfriendly turf"; - if (!region_okay) reason = "crossed region boundary"; - if (AUTO_TERMINATE) { - // enforce the rules; we left the building and we have no ticket back. - if (DEBUGGING) { - llOwnerSay(reason + " -- object death -- was in " - + llGetRegionName() + " at " + (string)llGetPos()); - } - llDie(); - } - // whew, we ducked that deadly issue. let the owner know that we - // don't like this place. - llOwnerSay(reason + "; please come get me:\nlast in " - + llGetRegionName() + " at " + (string)llGetPos()); - last_alerted = llGetUnixTime(); // reset, since we just alerted. - return; // don't bother trying to move anywhere. - } - - if (region_okay && (last_alerted != 0) ) { - // hmmm, did we recover our position? - if (homeward_jump_attempts <= MAXIMUM_FAILED_JUMPS) { - // we didn't expend too many jumps, so try going home again. - last_alerted = 0; - // also go back to our normal timing cycle. - llSetTimerEvent(POSITION_CHECKING_INTERVAL); - } - } - - if (!region_okay || (homeward_jump_attempts > MAXIMUM_FAILED_JUMPS) - || (last_alerted != 0) ) { - // we said our piece, if any. we can't be fuddling around here. - return; - } - - // we're still in the right region, so check how far we are from the starting - // place. we'll try to move back if someone dragged us too far away from it. - float distance = llVecDist(llGetPos(), home_place); - if (distance > MAXIMUM_ROAMING_RANGE) { - // this is not good; we need to get back to our starting point. - attempt_to_go_home(); - homeward_jump_attempts++; - } else { - // reset our counter, since we are close enough to home. - homeward_jump_attempts = 0; - } - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.txt b/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.txt new file mode 100755 index 00000000..60a6a3c0 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/NC_stay_at_home_v5.2.txt @@ -0,0 +1,392 @@ + +// huffware script: stay at home, by fred huffhines +// +// this script attempts to keep an object at home, which is to say, near where +// it was rezzed. it is not perfect, and if the object quickly crosses a region +// boundary, the object may get away. there is an automatic termination option +// for cases where the object is taken away and cannot get back; otherwise the +// object will bleat its position out at regular intevals. +// this script mainly makes sense for physical objects, since non-physical +// objects are not as prone to being pushed around by other avatars. in addition, +// it really makes the most sense for an object that allows anyone to move it. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants to be adjusted as needed... + +float MAXIMUM_ROAMING_RANGE = 12.0; + // this is the farthest that we let them drag our object away, in meters. + +integer AUTO_TERMINATE = FALSE; + // if the object crosses a region boundary (exits sim, enters new one), then + // it will zap itself if this flag is set to true. it will also go poof if + // it reaches escape velocity and travels off world. + +integer KEEP_IT_PHYSICAL = TRUE; + // if this is true, then the object's state as physical is continually + // refreshed. + +integer ROTATE_TO_TARGET = FALSE; + // if this is true, the object will try to rotate to a set position. + +integer ONLY_ROTATE_FIXED_AXES = FALSE; + // if this is true and rotate to target is true, then we will only try to + // set the rotation on the axes that are specified as "fixed" below. + +vector TARGETED_ROTATION = <0.0, 0.0, 0.0>; + // if the control rotation flag is true, the object will try to reattain + // this value for its rotation. + +// if these are set to true, the no rotation is allowed around the axis. +// note that this decision is totally independent of whether the object has +// a targeted rotation or not. +integer FIXATE_X_AXIS = FALSE; +integer FIXATE_Y_AXIS = FALSE; +integer FIXATE_Z_AXIS = FALSE; + +integer MAXIMUM_FAILED_JUMPS = 200; + // if we are having to make this many attempts to get home, something is + // really wrong. treat it like leaving the region; totally awol. + +float POSITION_CHECKING_INTERVAL = 8.0; + // how frequently the object will check where it is, in seconds. + +float PANIC_EVERY_N_HOURS = 4.0; + // this is the number of hours between panic mewling at the owner, if the object + // did not get told to self-terminate upon leaving the region. + +integer DEBUGGING = FALSE; + // if this is true, then the object will tell about it's problems when it + // goes off world or into another sim. note that an object that is not + // set to auto-terminate is considered important enough to tell the owner; + // if you don't want to hear from lost objects, always turn on auto-terminate + // and turn off debugging. + +// these mysterious values control how the object rotates to its target. +float ROT_STRENGTH = 1.0; +float ROT_DAMPING = 0.25; +//these values don't work that great, but neither did any other ones. +// the rotlookat stuff seems overpowered by the physical nature of an object. + +// global variables... + +vector home_place; + // where the object starts out inside the sim. we will try to get back + // to here if we exceed our maximum distance from home. + +vector home_region; + // which sim we start out in, in terms of the region corners. if this changes, + // the object has left the sim. + +integer homeward_jump_attempts = 0; + // tracks how many jumps home we've tried to make. + +integer last_alerted = 0; + // when the script last told the user about having gone missing. + // if this is zero, we presumably haven't been lost recently. + +// requires jaunting library v10.5 or greater. +////////////// +// do not redefine these constants. +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +// commands available via the jaunting library: +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. pass a vector with the location. +string JAUNT_LIST_COMMAND = "#jauntlist#"; + // like regular jaunt, but expects a list of vectors as the first parameter; this list + // should be in the jaunter notecard format (separated by pipe characters). + // the second parameter, if any, should be 1 for forwards traversal and 0 for backwards. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +// +// encases a list of vectors in the expected character for the jaunting library. +string wrap_vector_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +////////////// + +// asks the jaunting library to take us to the target using a list of waypoints. +request_jaunt(list full_journey, integer forwards) +{ +// jaunt_responses_awaited++; + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_LIST_COMMAND, + wrap_vector_list(full_journey) + HUFFWARE_PARM_SEPARATOR + (string)forwards); +} + +// jaunts back to our home location. +attempt_to_go_home() +{ + // jump back to home. + request_jaunt([llGetPos(), home_place], TRUE); +} + +// we panic at the user this frequently, in seconds. +float panic_interval() { return PANIC_EVERY_N_HOURS * 60.0 * 60.0; } + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. + // we just woke up here. remember where we started out. + home_place = llGetPos(); + home_region = llGetRegionCorner(); + if (AUTO_TERMINATE) { + // make the object go kerflooey if it leaves the world entirely. + llSetStatus(STATUS_DIE_AT_EDGE, TRUE); + } + // disallow rotation if we were requested to. + llSetStatus(STATUS_ROTATE_X, !FIXATE_X_AXIS); + llSetStatus(STATUS_ROTATE_Y, !FIXATE_Y_AXIS); + llSetStatus(STATUS_ROTATE_Z, !FIXATE_Z_AXIS); + + if (ROTATE_TO_TARGET) { +//hmmm: maybe still offer gradual form as an option also? + + // set our rotational target to the configured position. +// llRotTarget(llEuler2Rot(TARGETED_ROTATION), 0.01); + // if we're supposed to rotate, we need to start that movement + // towards our target rotation. +// llRotLookAt(llEuler2Rot(TARGETED_ROTATION), ROT_STRENGTH, ROT_DAMPING); + } + // start the timer that checks on our position. + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + } + + on_rez(integer parm) { + llResetScript(); // a cop-out; just reroutes rezzing into a script reset. + } + + timer() { + + if (ROTATE_TO_TARGET) { + vector real_rot_target = TARGETED_ROTATION; + vector curr_rot = llRot2Euler(llGetRot()); + + if (ONLY_ROTATE_FIXED_AXES) { + // set our rotation to the target, but only for fixed axes. + if (!FIXATE_X_AXIS) real_rot_target.x = curr_rot.x; + if (!FIXATE_Y_AXIS) real_rot_target.y = curr_rot.y; + if (!FIXATE_Z_AXIS) real_rot_target.z = curr_rot.z; + } + + // see if we even need to do any rotation. + if (curr_rot != real_rot_target) { + // yes, we need to move back to the preferred rotation for at least one axis. + llSetStatus(STATUS_PHYSICS, FALSE); // physics property gets fixed in next block. + llSetRot(llEuler2Rot(real_rot_target)); + } + } + + if (KEEP_IT_PHYSICAL) { + // remind the object that it's physical, or set it if it wasn't. sometimes + // a physical object can get jinxed when bouncing into other people's lands + // and lose its status as a physical object. we correct for that here. + llSetStatus(STATUS_PHYSICS, TRUE); + } + + integer time_to_panic = FALSE; // set to true if we should panic now. + + // check whether the object is still in the appropriate region. + integer region_okay = (home_region == llGetRegionCorner()); + + // check to see if we're watching for a specific time. + if (last_alerted != 0) { + // ooh, we've already hit panicky conditions in the past. let's see if + // it's time to tell the owner about it. + if (panic_interval() <= llAbs(llGetUnixTime() - last_alerted)) { + // time to tell them about this, oh yes. + time_to_panic = TRUE; + } + } else { + // evaluate whether we are in the right condition (right sim and + // without being boxed in). + if (!region_okay || (homeward_jump_attempts > MAXIMUM_FAILED_JUMPS)) { + // this is not a good situation. we will now set the last alerted + // timer so as to force a panic message next time through the timer + // loop. + last_alerted = llAbs(llGetUnixTime() - (integer)panic_interval() - 1000); + // decide when to fire the timer next. + if (AUTO_TERMINATE) { + llSetTimerEvent(0.1); // fire very soon to zap. + } else { + llSetTimerEvent(POSITION_CHECKING_INTERVAL * 5); + // slow the checking down a bit, since we don't expect to + // magically get back to our sim (although it could happen!). + } + } + } + + // time to panic just means that we should tell the owner about our problematic + // location, or auto-terminate if configured that way. + if (time_to_panic) { + // well, we've got to say something about this dire situation. + string reason = "trapped by unfriendly turf"; + if (!region_okay) reason = "crossed region boundary"; + if (AUTO_TERMINATE) { + // enforce the rules; we left the building and we have no ticket back. + if (DEBUGGING) { + llOwnerSay(reason + " -- object death -- was in " + + llGetRegionName() + " at " + (string)llGetPos()); + } + llDie(); + } + // whew, we ducked that deadly issue. let the owner know that we + // don't like this place. + llOwnerSay(reason + "; please come get me:\nlast in " + + llGetRegionName() + " at " + (string)llGetPos()); + last_alerted = llGetUnixTime(); // reset, since we just alerted. + return; // don't bother trying to move anywhere. + } + + if (region_okay && (last_alerted != 0) ) { + // hmmm, did we recover our position? + if (homeward_jump_attempts <= MAXIMUM_FAILED_JUMPS) { + // we didn't expend too many jumps, so try going home again. + last_alerted = 0; + // also go back to our normal timing cycle. + llSetTimerEvent(POSITION_CHECKING_INTERVAL); + } + } + + if (!region_okay || (homeward_jump_attempts > MAXIMUM_FAILED_JUMPS) + || (last_alerted != 0) ) { + // we said our piece, if any. we can't be fuddling around here. + return; + } + + // we're still in the right region, so check how far we are from the starting + // place. we'll try to move back if someone dragged us too far away from it. + float distance = llVecDist(llGetPos(), home_place); + if (distance > MAXIMUM_ROAMING_RANGE) { + // this is not good; we need to get back to our starting point. + attempt_to_go_home(); + homeward_jump_attempts++; + } else { + // reset our counter, since we are close enough to home. + homeward_jump_attempts = 0; + } + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.lsl b/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.lsl deleted file mode 100755 index ab8aca15..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.lsl +++ /dev/null @@ -1,426 +0,0 @@ - -// huffware script: vote for me, by fred huffhines. -// -// original author: ChuChu Ricardo January 14, 2010 -// numerous mods: Fred Huffhines, March 2010 [including but not limited to refactoring -// existing functions and fixing payment behavior] -// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -string LINDEN_MARK = "L$"; // the money symbol for linden dollars. -integer MINIMUM_FREE_MEMORY = 3400; // the least memory we can get by with. - -// a set of menu items we'll be displaying on the voter menu. -string ITEM_VOTEME = "Vote for Me"; -string ITEM_STATUS = "Show Info"; -string ITEM_NOT_NOW = "Not Now"; -// items for the owner menu only. -string ITEM_RESET = "Reset"; -string ITEM_GIVE_NOTE = "Give Note"; -string ITEM_NO_NOTE = "No Notecard"; -string ITEM_GIVE_OBJ = "Give Gift"; -string ITEM_NO_OBJ = "No Gift"; - -integer ONE_MINUTE; // number of seconds in a minute. initialized later. -integer ONE_HOUR; // number of seconds in an hour. initialized later. -integer FULL_DAY; // number of seconds in a day. initialized later. - -// these are the textures we'll show when it's time to register the average vote. -list TEXTURE_UUIDS = [ - "8dfc709a-c37d-6103-2670-d287e871f0e7", // zero average. - "14278369-1db4-4497-13ef-5dc75a1017f0", // lowest rating (red, many bars). - "8a891c33-1070-6c6b-148b-919651323b5e", - "25f8618d-181d-9af3-720e-01a3a0fa1861", - "3f89b392-b70a-8a63-f09f-b51f6d91b437", - "a6d02c4e-7b8c-0fd9-47a5-08cb61159bfa", - "b7fb64db-5658-547d-560d-3ca86ff77e37", - "bc8057e8-61f2-1919-74f9-59ea5b731bc7", - "ec54863f-665c-9dc0-ab64-051fe96750af", - "2acaa661-db7a-1035-d4e4-0ed50304887c", - "53f1465d-7f39-d1cc-6ade-4610ec053646", - "c868135f-0ad1-20ea-a85b-0c48a780ea7f", - "78215a59-c52b-1886-0cae-bce11592e9b1", - "ffa2ed36-df97-4889-4903-06dca758336d", - "f1a625cb-4346-91b2-8e48-9290be22ec90", - "6301df4e-d3bf-2b41-9738-a6e4b7f10715", - "a3f566fa-0e2e-68dc-92ac-a60258717525", - "83088c7a-8397-404d-1285-54def3ff179e", - "cde91186-7365-02c1-fe79-740cc82bc01a", - "08d22575-0848-b7c4-1dfb-665216165831" // highest rating (green, no bars) -]; - -// the secret channel where the user can change the text shown on title. -integer COMMAND_CHANNEL = 9; - -// global variables... - -key last_owner; // the last person who owned this object. -string persistent_message; // additional text for the title bar. -integer voter_dialog_channel; // where the voter (non-owner) menu will be heard. -integer owner_dialog_channel; // where the owner's big menu will be heard. -integer vote_price = 10; // amount of lindens paid per vote, with default value. -integer give_notecards = TRUE; // should we hand out notecards for a vote? -integer give_objects = TRUE; // should we hand out objects for a vote? - -// these four variables need to reset daily... -list voter_ids; // the identities of the voters. -list vote_magnitudes; // the value (on the likes-me scale) of each vote cast. -float average_score; // Average score computed so far. -integer last_reset_time; // the last time we did a vote reset. - -// perform initialization tasks. -setup_voteme() -{ - // initialize our "constants" here, since LSL doesn't like generated constants. - ONE_MINUTE = 60; - ONE_HOUR = 60 * ONE_MINUTE; - FULL_DAY = 24 * ONE_HOUR; - - last_owner = llGetOwner(); // remember so we can know when changing hands. - last_reset_time = llGetUnixTime(); // track when we cranked up. - - // default add-in for titler is the avatar's name. - persistent_message = llKey2Name(llGetOwner()); - - llSetText("VoteME: "+ persistent_message, <1,1,1>, 1.0); - - set_faces_to_texture((key)llList2String(TEXTURE_UUIDS, 0)); - - llRequestPermissions(llGetOwner(), PERMISSION_DEBIT); - - // set up the menu dialog channel so we will hear what they picked. - owner_dialog_channel = -(integer)(llFrand(999999) + 250); - voter_dialog_channel = owner_dialog_channel + 1; - llListen(owner_dialog_channel, "", llGetOwner(), ""); - llListen(voter_dialog_channel, "", NULL_KEY, ""); - - // listen on our special command channel. - llListen(COMMAND_CHANNEL, "", llGetOwner(), ""); - - llSetTimerEvent(ONE_MINUTE); -} - -// looks for the voter to see if they've already voted today. -// true is returned if the "id" is found. -integer seek_voter(key id) { return llListFindList(voter_ids, [id]) >= 0; } - -// adds a record for the voter with key "id", if they are not already present. -// true is returned if this is a new voter. -integer add_voter(key id) -{ - if (llGetFreeMemory() < MINIMUM_FREE_MEMORY) { - llOwnerSay("omitting vote due to low memory."); - return FALSE; - } - // if the entry's not there already, add it. - if (seek_voter(id)) return FALSE; // that one was there. - // if we got to here, then the voter was not there yet. - voter_ids += [ id ]; - return TRUE; -} - -// creates a string out of the time in "decode_time" which is expected to -// be compatible with llGetWallClock() values. -string time_string(integer decode_time) -{ - integer hours = decode_time / ONE_HOUR; - decode_time -= hours * ONE_HOUR; - integer minutes = decode_time / ONE_MINUTE; - decode_time -= minutes * ONE_MINUTE; - integer seconds = decode_time; - return (string)hours + ":" + (string)minutes + ":" + (string)seconds; -} - -// sets all the x/y faces of the object to the texture key specified. -// the top and bottom are unchanged. -set_faces_to_texture(key texture_id) -{ - integer i; - for (i = 1; i <= 4; i++) { - llSetTexture(texture_id, i); - } -} - -// pops up the menu for the owner's use. -show_owner_menu() -{ - string msg0 = "You can choose the amount you want voters to pay,\nor configure giving out notecards and/or gifts to your voters."; - list menu0_btns = [ - // first row at bottom. - ITEM_GIVE_NOTE, ITEM_NO_NOTE, ITEM_STATUS, - ITEM_GIVE_OBJ, ITEM_NO_OBJ, ITEM_RESET, - LINDEN_MARK + "10", LINDEN_MARK + "20", LINDEN_MARK + "50", - // last row at top. - LINDEN_MARK + "100" - ]; - - llDialog(llGetOwner(), msg0, menu0_btns, owner_dialog_channel); -} - -// lets the avatar know we can't process their vote right now. -apologize_but_refuse_vote() -{ - llSay(0, "Sorry, You have already voted for " + llKey2Name(llGetOwner()) + " today."); -} - -key last_toucher; // the last person that clicked the voter object. -//move this! - -// handles a particular avatar that has touched the voter. -process_toucher(integer which) -{ - string voter_id = llDetectedKey(which); - string voter_name = llDetectedName(which); - // see if this was the owner touching the object. - if (voter_id == llGetOwner()) { - show_owner_menu(); - return; // done with owner touch handling. - } - // handle when someone other than the owner touches the voter. - if (!seek_voter(voter_id)) { - // new voter. - if (last_toucher != voter_id) { - llSay(0, "Hello " + voter_name + "... please Vote for Me."); - last_toucher = voter_id; - if (give_notecards == TRUE) { - string card_name = llGetInventoryName(INVENTORY_NOTECARD, 0); - if (card_name != "") llGiveInventory(voter_id, card_name); - } - } - string msg1 = "Please Choose to Vote for me.\nYou can also choose to see my current voting status."; - list menu1_btns = [ ITEM_VOTEME, ITEM_STATUS, ITEM_NOT_NOW ]; - llDialog(voter_id, msg1, menu1_btns, voter_dialog_channel); - } else { - // they had already voted, so we don't give them the whole menu. - string msg1 = "Thanks for your vote! You can check my status, but you cannot vote again until tomorrow."; - list menu1_btns = [ ITEM_STATUS ]; - llDialog(voter_id, msg1, menu1_btns, voter_dialog_channel); - } -} - -// processes when an avatar touches the voter. -handle_touches(integer total_number) -{ - // run through all the people that touched the voter this time. - integer i; - for (i = 0; i < total_number; i++) { process_toucher(i); } -} - -// deals with people throwing money at us. -handle_monetary_gift(key giver, integer amount) -{ - if (giver == llGetOwner()) { - // fine, genius, you gave yourself some money. you don't get to vote. - return; - } - if (amount != vote_price) { - // refund the amount paid, since this was not the right vote cost. - llSay(0, "Oops! That's not the right amount for the vote; SL is hosing up or something. Here's a refund."); - llGiveMoney(giver, amount); - return; - } - if (seek_voter(giver)) { - // they've already voted so they're not allowed again. - apologize_but_refuse_vote(); - llGiveMoney(giver, amount); - return; - } - add_voter(giver); - - llSay(0, "Thanks for the " + LINDEN_MARK + (string)amount + ", " + llKey2Name(giver) - + ". Your voting menu will open shortly."); - - string msg3 = "Voting Key:\n1-means you like me a little\n10-means you really adore me\nThank You!"; - list menu3_btns = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ]; - llDialog(giver, msg3, menu3_btns, voter_dialog_channel); -} - -// announces how the owner is doing so far. -show_status() -{ - integer count = llGetListLength(voter_ids); - llSay(0, "My name is " + llKey2Name(llGetOwner()) + " and I have received " - + (string)count + " votes.\n" - + "My average score per vote is " + (string)average_score + "."); - -integer since_reset = llGetUnixTime() - last_reset_time; -llOwnerSay("last reset " + time_string(since_reset) + " H:M:S ago."); - -} - -// processes responses from menus and deals with spoken commands. -hear_voices(integer channel, string speaker_name, key id, string message) -{ - // see if this is from the owner about what to show on the voter. - if ( (channel == COMMAND_CHANNEL) && (id == llGetOwner()) ) { -//hmmm: undocumented! - persistent_message = message; - llOwnerSay("Changed title bar to add \"" + persistent_message + "\"."); - llSetText("VoteME: " + persistent_message, <1,1,1>, 1.0); - return; - } - - // check if the message comes from the owner's dialog. - if (channel == owner_dialog_channel) { - if (message == ITEM_STATUS) { - show_status(); - return; - } else if (message == ITEM_RESET) { -//hmmm: is this in the menu??? - llOwnerSay("Resetting now..."); - llResetScript(); - } else if (llGetSubString(message, 0, 1) == LINDEN_MARK) { - vote_price = (integer)llGetSubString(message,2,-1); - llOwnerSay("Voting for you will now cost avatars " - + LINDEN_MARK + (string)vote_price + "."); - llSetPayPrice(PAY_HIDE, [vote_price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); - } else if (message == ITEM_GIVE_OBJ) { - llOwnerSay("Gift giving enabled."); - give_objects = TRUE; - } else if (message == ITEM_NO_OBJ) { - llOwnerSay("Gift giving disabled."); - give_objects = FALSE; - } else if (message == ITEM_GIVE_NOTE) { - llOwnerSay("Notecard giving enabled."); - give_notecards = TRUE; - } else if (message == ITEM_NO_NOTE) { - llOwnerSay("Notecard giving disabled."); - give_notecards = FALSE; - } - // assume for the choices that fall through that they want to see the menu again. - show_owner_menu(); - return; // done handling our own dialog. - } - - // see if this is the dialog for the voting person. - if (channel == voter_dialog_channel) { - if (message == ITEM_VOTEME) { - string msg2 = "To show your confidence in me, pay me " - + LINDEN_MARK + (string)vote_price + ".\n" - + "Then rate me from 1 to 10 after you pay.\n" - + "1 = You like me a little bit\n10 = You really adore me\n" - + "Ready? Right-click this object and pick \"Pay\". Thanks very much!"; - list menu2_btns = [ "Understood" ]; - llDialog(id, msg2, menu2_btns, voter_dialog_channel); - } else if (message == ITEM_STATUS) { - show_status(); - } else if (message == ITEM_NOT_NOW) { - llSay(0, "Thanks for the interest anyhow, " + llKey2Name(id) + "."); - } else if ((integer)message > 0 && (integer)message <= 10) { - if (give_notecards == TRUE) { - string name = llGetInventoryName(INVENTORY_NOTECARD, 0); - if (name != "") llGiveInventory(id, name); - } - if (give_objects == TRUE) { - string name = llGetInventoryName(INVENTORY_OBJECT, 0); - if (name != "") llGiveInventory(id, name); - } - register_vote((integer)message); - } - } -} - -// deals with our timer clicks. -handle_timer() -{ - integer wall_clock = (integer)llGetWallclock(); - -//llOwnerSay("tick: " + time_string(wall_clock)); - - // see if it seems like time to reset. we'll do this when the clock has just passed - // midnight (that is, we're in the first hour after midnight), or if the device had - // possibly been taken out of commission a long time ago (meaning more time has passed - // since the last reset than has elapsed today so far). - integer reset_it = FALSE; - integer time_since_reset = llGetUnixTime() - last_reset_time; - // is it the first hour of midnight, and we didn't just reset? - if ( (wall_clock < ONE_HOUR) && (time_since_reset > ONE_HOUR) ) reset_it = TRUE; - // or, is it a really long time since we did reset? longer than when the hour turned? - if (time_since_reset > wall_clock) reset_it = TRUE; - - if (reset_it) { - // aha, we've decided it's that time. - llOwnerSay("Resetting voters and average, since the clock rolled over."); - voter_ids = []; - vote_magnitudes = []; - average_score = 0; - last_reset_time = llGetUnixTime(); - register_vote(0); // just recalculate average and show texture. - } -} - -// tracks that they've made a vote. -register_vote(integer this_vote_value) -{ - // zero is a special value that just makes us recalculate the average. - if (this_vote_value != 0) vote_magnitudes += [ this_vote_value ]; - -//move this to an averager method. - integer sum = 0; - integer n = llGetListLength(vote_magnitudes); - integer i = 0; - for(i = 0;i= 20) tex_num = 19; //We dont have all green texture - - set_faces_to_texture((key)llList2String(TEXTURE_UUIDS, tex_num)); -} - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -// main state machine. -state real_default -{ - state_entry() { setup_voteme(); } - - on_rez(integer parm) { - if (last_owner != llGetOwner()) { - llOwnerSay("Now configuring for " + llKey2Name(llGetOwner())); - llResetScript(); - } - } - - run_time_permissions(integer perm) { - if (perm & PERMISSION_DEBIT) { -//llOwnerSay("got permission for debits, will set price to " + (string)vote_price); - llSetPayPrice(PAY_HIDE, [vote_price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); - } else { - llOwnerSay("We were denied debit permission and cannot function without it. Use the menu and select \"" + ITEM_RESET + "\" to fix this."); - } - } - - timer() { handle_timer(); } - - touch_start(integer total_number) { handle_touches(total_number); } - - money(key giver, integer amount) { handle_monetary_gift(giver, amount); } - - listen(integer channel, string name, key id, string message) - { hear_voices(channel, name, id, message); } -} - - -//feature ideas: -// have the voter track the highest paying guy? -// actually no, the owner sets that limit. rats. -// but what about the highest voting guy!? the guy/gal who thought the most could be tracked. - -//hmmm: need a helper notecard function for owner! - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.txt b/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.txt new file mode 100755 index 00000000..ab8aca15 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/Vote_for_me_v4.2.txt @@ -0,0 +1,426 @@ + +// huffware script: vote for me, by fred huffhines. +// +// original author: ChuChu Ricardo January 14, 2010 +// numerous mods: Fred Huffhines, March 2010 [including but not limited to refactoring +// existing functions and fixing payment behavior] +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +string LINDEN_MARK = "L$"; // the money symbol for linden dollars. +integer MINIMUM_FREE_MEMORY = 3400; // the least memory we can get by with. + +// a set of menu items we'll be displaying on the voter menu. +string ITEM_VOTEME = "Vote for Me"; +string ITEM_STATUS = "Show Info"; +string ITEM_NOT_NOW = "Not Now"; +// items for the owner menu only. +string ITEM_RESET = "Reset"; +string ITEM_GIVE_NOTE = "Give Note"; +string ITEM_NO_NOTE = "No Notecard"; +string ITEM_GIVE_OBJ = "Give Gift"; +string ITEM_NO_OBJ = "No Gift"; + +integer ONE_MINUTE; // number of seconds in a minute. initialized later. +integer ONE_HOUR; // number of seconds in an hour. initialized later. +integer FULL_DAY; // number of seconds in a day. initialized later. + +// these are the textures we'll show when it's time to register the average vote. +list TEXTURE_UUIDS = [ + "8dfc709a-c37d-6103-2670-d287e871f0e7", // zero average. + "14278369-1db4-4497-13ef-5dc75a1017f0", // lowest rating (red, many bars). + "8a891c33-1070-6c6b-148b-919651323b5e", + "25f8618d-181d-9af3-720e-01a3a0fa1861", + "3f89b392-b70a-8a63-f09f-b51f6d91b437", + "a6d02c4e-7b8c-0fd9-47a5-08cb61159bfa", + "b7fb64db-5658-547d-560d-3ca86ff77e37", + "bc8057e8-61f2-1919-74f9-59ea5b731bc7", + "ec54863f-665c-9dc0-ab64-051fe96750af", + "2acaa661-db7a-1035-d4e4-0ed50304887c", + "53f1465d-7f39-d1cc-6ade-4610ec053646", + "c868135f-0ad1-20ea-a85b-0c48a780ea7f", + "78215a59-c52b-1886-0cae-bce11592e9b1", + "ffa2ed36-df97-4889-4903-06dca758336d", + "f1a625cb-4346-91b2-8e48-9290be22ec90", + "6301df4e-d3bf-2b41-9738-a6e4b7f10715", + "a3f566fa-0e2e-68dc-92ac-a60258717525", + "83088c7a-8397-404d-1285-54def3ff179e", + "cde91186-7365-02c1-fe79-740cc82bc01a", + "08d22575-0848-b7c4-1dfb-665216165831" // highest rating (green, no bars) +]; + +// the secret channel where the user can change the text shown on title. +integer COMMAND_CHANNEL = 9; + +// global variables... + +key last_owner; // the last person who owned this object. +string persistent_message; // additional text for the title bar. +integer voter_dialog_channel; // where the voter (non-owner) menu will be heard. +integer owner_dialog_channel; // where the owner's big menu will be heard. +integer vote_price = 10; // amount of lindens paid per vote, with default value. +integer give_notecards = TRUE; // should we hand out notecards for a vote? +integer give_objects = TRUE; // should we hand out objects for a vote? + +// these four variables need to reset daily... +list voter_ids; // the identities of the voters. +list vote_magnitudes; // the value (on the likes-me scale) of each vote cast. +float average_score; // Average score computed so far. +integer last_reset_time; // the last time we did a vote reset. + +// perform initialization tasks. +setup_voteme() +{ + // initialize our "constants" here, since LSL doesn't like generated constants. + ONE_MINUTE = 60; + ONE_HOUR = 60 * ONE_MINUTE; + FULL_DAY = 24 * ONE_HOUR; + + last_owner = llGetOwner(); // remember so we can know when changing hands. + last_reset_time = llGetUnixTime(); // track when we cranked up. + + // default add-in for titler is the avatar's name. + persistent_message = llKey2Name(llGetOwner()); + + llSetText("VoteME: "+ persistent_message, <1,1,1>, 1.0); + + set_faces_to_texture((key)llList2String(TEXTURE_UUIDS, 0)); + + llRequestPermissions(llGetOwner(), PERMISSION_DEBIT); + + // set up the menu dialog channel so we will hear what they picked. + owner_dialog_channel = -(integer)(llFrand(999999) + 250); + voter_dialog_channel = owner_dialog_channel + 1; + llListen(owner_dialog_channel, "", llGetOwner(), ""); + llListen(voter_dialog_channel, "", NULL_KEY, ""); + + // listen on our special command channel. + llListen(COMMAND_CHANNEL, "", llGetOwner(), ""); + + llSetTimerEvent(ONE_MINUTE); +} + +// looks for the voter to see if they've already voted today. +// true is returned if the "id" is found. +integer seek_voter(key id) { return llListFindList(voter_ids, [id]) >= 0; } + +// adds a record for the voter with key "id", if they are not already present. +// true is returned if this is a new voter. +integer add_voter(key id) +{ + if (llGetFreeMemory() < MINIMUM_FREE_MEMORY) { + llOwnerSay("omitting vote due to low memory."); + return FALSE; + } + // if the entry's not there already, add it. + if (seek_voter(id)) return FALSE; // that one was there. + // if we got to here, then the voter was not there yet. + voter_ids += [ id ]; + return TRUE; +} + +// creates a string out of the time in "decode_time" which is expected to +// be compatible with llGetWallClock() values. +string time_string(integer decode_time) +{ + integer hours = decode_time / ONE_HOUR; + decode_time -= hours * ONE_HOUR; + integer minutes = decode_time / ONE_MINUTE; + decode_time -= minutes * ONE_MINUTE; + integer seconds = decode_time; + return (string)hours + ":" + (string)minutes + ":" + (string)seconds; +} + +// sets all the x/y faces of the object to the texture key specified. +// the top and bottom are unchanged. +set_faces_to_texture(key texture_id) +{ + integer i; + for (i = 1; i <= 4; i++) { + llSetTexture(texture_id, i); + } +} + +// pops up the menu for the owner's use. +show_owner_menu() +{ + string msg0 = "You can choose the amount you want voters to pay,\nor configure giving out notecards and/or gifts to your voters."; + list menu0_btns = [ + // first row at bottom. + ITEM_GIVE_NOTE, ITEM_NO_NOTE, ITEM_STATUS, + ITEM_GIVE_OBJ, ITEM_NO_OBJ, ITEM_RESET, + LINDEN_MARK + "10", LINDEN_MARK + "20", LINDEN_MARK + "50", + // last row at top. + LINDEN_MARK + "100" + ]; + + llDialog(llGetOwner(), msg0, menu0_btns, owner_dialog_channel); +} + +// lets the avatar know we can't process their vote right now. +apologize_but_refuse_vote() +{ + llSay(0, "Sorry, You have already voted for " + llKey2Name(llGetOwner()) + " today."); +} + +key last_toucher; // the last person that clicked the voter object. +//move this! + +// handles a particular avatar that has touched the voter. +process_toucher(integer which) +{ + string voter_id = llDetectedKey(which); + string voter_name = llDetectedName(which); + // see if this was the owner touching the object. + if (voter_id == llGetOwner()) { + show_owner_menu(); + return; // done with owner touch handling. + } + // handle when someone other than the owner touches the voter. + if (!seek_voter(voter_id)) { + // new voter. + if (last_toucher != voter_id) { + llSay(0, "Hello " + voter_name + "... please Vote for Me."); + last_toucher = voter_id; + if (give_notecards == TRUE) { + string card_name = llGetInventoryName(INVENTORY_NOTECARD, 0); + if (card_name != "") llGiveInventory(voter_id, card_name); + } + } + string msg1 = "Please Choose to Vote for me.\nYou can also choose to see my current voting status."; + list menu1_btns = [ ITEM_VOTEME, ITEM_STATUS, ITEM_NOT_NOW ]; + llDialog(voter_id, msg1, menu1_btns, voter_dialog_channel); + } else { + // they had already voted, so we don't give them the whole menu. + string msg1 = "Thanks for your vote! You can check my status, but you cannot vote again until tomorrow."; + list menu1_btns = [ ITEM_STATUS ]; + llDialog(voter_id, msg1, menu1_btns, voter_dialog_channel); + } +} + +// processes when an avatar touches the voter. +handle_touches(integer total_number) +{ + // run through all the people that touched the voter this time. + integer i; + for (i = 0; i < total_number; i++) { process_toucher(i); } +} + +// deals with people throwing money at us. +handle_monetary_gift(key giver, integer amount) +{ + if (giver == llGetOwner()) { + // fine, genius, you gave yourself some money. you don't get to vote. + return; + } + if (amount != vote_price) { + // refund the amount paid, since this was not the right vote cost. + llSay(0, "Oops! That's not the right amount for the vote; SL is hosing up or something. Here's a refund."); + llGiveMoney(giver, amount); + return; + } + if (seek_voter(giver)) { + // they've already voted so they're not allowed again. + apologize_but_refuse_vote(); + llGiveMoney(giver, amount); + return; + } + add_voter(giver); + + llSay(0, "Thanks for the " + LINDEN_MARK + (string)amount + ", " + llKey2Name(giver) + + ". Your voting menu will open shortly."); + + string msg3 = "Voting Key:\n1-means you like me a little\n10-means you really adore me\nThank You!"; + list menu3_btns = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ]; + llDialog(giver, msg3, menu3_btns, voter_dialog_channel); +} + +// announces how the owner is doing so far. +show_status() +{ + integer count = llGetListLength(voter_ids); + llSay(0, "My name is " + llKey2Name(llGetOwner()) + " and I have received " + + (string)count + " votes.\n" + + "My average score per vote is " + (string)average_score + "."); + +integer since_reset = llGetUnixTime() - last_reset_time; +llOwnerSay("last reset " + time_string(since_reset) + " H:M:S ago."); + +} + +// processes responses from menus and deals with spoken commands. +hear_voices(integer channel, string speaker_name, key id, string message) +{ + // see if this is from the owner about what to show on the voter. + if ( (channel == COMMAND_CHANNEL) && (id == llGetOwner()) ) { +//hmmm: undocumented! + persistent_message = message; + llOwnerSay("Changed title bar to add \"" + persistent_message + "\"."); + llSetText("VoteME: " + persistent_message, <1,1,1>, 1.0); + return; + } + + // check if the message comes from the owner's dialog. + if (channel == owner_dialog_channel) { + if (message == ITEM_STATUS) { + show_status(); + return; + } else if (message == ITEM_RESET) { +//hmmm: is this in the menu??? + llOwnerSay("Resetting now..."); + llResetScript(); + } else if (llGetSubString(message, 0, 1) == LINDEN_MARK) { + vote_price = (integer)llGetSubString(message,2,-1); + llOwnerSay("Voting for you will now cost avatars " + + LINDEN_MARK + (string)vote_price + "."); + llSetPayPrice(PAY_HIDE, [vote_price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); + } else if (message == ITEM_GIVE_OBJ) { + llOwnerSay("Gift giving enabled."); + give_objects = TRUE; + } else if (message == ITEM_NO_OBJ) { + llOwnerSay("Gift giving disabled."); + give_objects = FALSE; + } else if (message == ITEM_GIVE_NOTE) { + llOwnerSay("Notecard giving enabled."); + give_notecards = TRUE; + } else if (message == ITEM_NO_NOTE) { + llOwnerSay("Notecard giving disabled."); + give_notecards = FALSE; + } + // assume for the choices that fall through that they want to see the menu again. + show_owner_menu(); + return; // done handling our own dialog. + } + + // see if this is the dialog for the voting person. + if (channel == voter_dialog_channel) { + if (message == ITEM_VOTEME) { + string msg2 = "To show your confidence in me, pay me " + + LINDEN_MARK + (string)vote_price + ".\n" + + "Then rate me from 1 to 10 after you pay.\n" + + "1 = You like me a little bit\n10 = You really adore me\n" + + "Ready? Right-click this object and pick \"Pay\". Thanks very much!"; + list menu2_btns = [ "Understood" ]; + llDialog(id, msg2, menu2_btns, voter_dialog_channel); + } else if (message == ITEM_STATUS) { + show_status(); + } else if (message == ITEM_NOT_NOW) { + llSay(0, "Thanks for the interest anyhow, " + llKey2Name(id) + "."); + } else if ((integer)message > 0 && (integer)message <= 10) { + if (give_notecards == TRUE) { + string name = llGetInventoryName(INVENTORY_NOTECARD, 0); + if (name != "") llGiveInventory(id, name); + } + if (give_objects == TRUE) { + string name = llGetInventoryName(INVENTORY_OBJECT, 0); + if (name != "") llGiveInventory(id, name); + } + register_vote((integer)message); + } + } +} + +// deals with our timer clicks. +handle_timer() +{ + integer wall_clock = (integer)llGetWallclock(); + +//llOwnerSay("tick: " + time_string(wall_clock)); + + // see if it seems like time to reset. we'll do this when the clock has just passed + // midnight (that is, we're in the first hour after midnight), or if the device had + // possibly been taken out of commission a long time ago (meaning more time has passed + // since the last reset than has elapsed today so far). + integer reset_it = FALSE; + integer time_since_reset = llGetUnixTime() - last_reset_time; + // is it the first hour of midnight, and we didn't just reset? + if ( (wall_clock < ONE_HOUR) && (time_since_reset > ONE_HOUR) ) reset_it = TRUE; + // or, is it a really long time since we did reset? longer than when the hour turned? + if (time_since_reset > wall_clock) reset_it = TRUE; + + if (reset_it) { + // aha, we've decided it's that time. + llOwnerSay("Resetting voters and average, since the clock rolled over."); + voter_ids = []; + vote_magnitudes = []; + average_score = 0; + last_reset_time = llGetUnixTime(); + register_vote(0); // just recalculate average and show texture. + } +} + +// tracks that they've made a vote. +register_vote(integer this_vote_value) +{ + // zero is a special value that just makes us recalculate the average. + if (this_vote_value != 0) vote_magnitudes += [ this_vote_value ]; + +//move this to an averager method. + integer sum = 0; + integer n = llGetListLength(vote_magnitudes); + integer i = 0; + for(i = 0;i= 20) tex_num = 19; //We dont have all green texture + + set_faces_to_texture((key)llList2String(TEXTURE_UUIDS, tex_num)); +} + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +// main state machine. +state real_default +{ + state_entry() { setup_voteme(); } + + on_rez(integer parm) { + if (last_owner != llGetOwner()) { + llOwnerSay("Now configuring for " + llKey2Name(llGetOwner())); + llResetScript(); + } + } + + run_time_permissions(integer perm) { + if (perm & PERMISSION_DEBIT) { +//llOwnerSay("got permission for debits, will set price to " + (string)vote_price); + llSetPayPrice(PAY_HIDE, [vote_price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); + } else { + llOwnerSay("We were denied debit permission and cannot function without it. Use the menu and select \"" + ITEM_RESET + "\" to fix this."); + } + } + + timer() { handle_timer(); } + + touch_start(integer total_number) { handle_touches(total_number); } + + money(key giver, integer amount) { handle_monetary_gift(giver, amount); } + + listen(integer channel, string name, key id, string message) + { hear_voices(channel, name, id, message); } +} + + +//feature ideas: +// have the voter track the highest paying guy? +// actually no, the owner sets that limit. rats. +// but what about the highest voting guy!? the guy/gal who thought the most could be tracked. + +//hmmm: need a helper notecard function for owner! + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.lsl b/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.lsl deleted file mode 100755 index ef201cf7..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.lsl +++ /dev/null @@ -1,940 +0,0 @@ - -// huffware script: huff-update server, by fred huffhines. -// -// this script is the server side of the update process. it should reside in an object that -// has all the newest versions of scripts and objects that will be updated. when rezzed, and -// at periodic intervals, it announces on a private chat channel that updates are available. -// when objects respond that they might like an update, it tells them the scripts that it has -// stored inside of it. if any of those scripts are an older version inside the client -// (update requesting) object, then the client will request the newer versions. the server -// object will stuff them into it and tell them to start running. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. - -integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. - - - -// updater dependency section: -// should be moved to a notecard!!! -// -// format is a list of strings, where each string has a pair wrapped by the -// huffware item separators. the pair contains (1) the basename of a script -// that has a new dependency and (2) the basename of that new dependency. -list known_script_dependencies; - - - - -load_script_deps() -{ - known_script_dependencies = [ - llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), - llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), - llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), - llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), - llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), - llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), - - -//special purpose -- removes the updater from the elevator buttons... -//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), -// => do not uncomment unless you want your elevators to shed their ability to update. - - - // this allows us to add or remove items above at will without complaints about comma. - llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) - ]; -} - - - - -// global constants... - -integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. - -float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. -string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. -string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. - -integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. - -integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. - -float LONGEST_SLACK_PER_CLIENT = 84.0; - // we allow a client to be out of touch with us for this many seconds. after that, - // we decide it's deceased and remove it from our list. - -integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). - -float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. - -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -float CHANGED_INVENTORY_SNOOZER = 7.0; - // the number of seconds we sleep once we see an inventory change. we don't want to - // react to this immediately. this overrides the normal announcement cycle until it's - // dealt with by the timer. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string UPDATER_BASE_NAME = "huff-update client"; - // the name of the updater script that keeps everything in sync. - -////////////// - -// global variables... - -list scripts_available; // the list of scripts we have in our inventory for distribution. -list objects_available; // list of objects for handing out. - -list active_clients; // list of keys for clients that are updating currently. -list active_update_channels; // active conversations on client chosen channels. -list active_listen_ids; // the ids for the listener on those channels. -list active_timestamps; // tracks when the client was last active. - -integer inventory_request_channel; // our personal channel that the update client should talk with. - -integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. - -// displays the status of the update server. -show_status(key who_says) -{ - string title = "[mem free=" + (string)llGetFreeMemory() + "]"; - title = "Listening for requests on channel " + (string)inventory_request_channel; - if (llGetListLength(active_update_channels)) - title += "\nactive channels=" - + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); - else - title += "\nNo channels active."; - - if (llGetListLength(active_clients)) - title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); - else - title += "\nNo clients active."; - - if (llGetOwner() == who_says) { - string addition = " "; - if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; - title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " - + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " - + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; - } - - llWhisper(0, title); -} - -// plink a quietous string of resonance... -squonk(integer indy) -{ - string snd = llGetInventoryName(INVENTORY_SOUND, indy); - if (snd != "") llTriggerSound(snd, 1.0); -} - -// list out the scripts that the server's object contains. -show_scripts() -{ - string title = (string)llGetListLength(scripts_available) + " scripts available:"; - show_list(title, scripts_available); - title = (string)llGetListLength(objects_available) + " objects available:"; - show_list(title, objects_available); -} - -// lets the client know that we're here and have some scripts available. -announce_presence() -{ - if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { - // only announce if we're not already booked up. - llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); - } -} - -// lifted from "clear text and effects" script; should be nearly identical -// to that, except that we set the texture animation. -reset_all_effects() -{ - llSetText("", <0,0,0>, 0); // clear any text above object. - llSetSitText("Sit Here"); // reset sit text to default state. - llSetTouchText("Touch"); // similarly for touch. - llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. - llParticleSystem([]); // turn off all particles. - llSensorRemove(); // stop any running sensors. - llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. - llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. - // keep it from being physical and from disapparating. - llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, - PRIM_PHANTOM, TRUE]); - llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. - - // - // the following are specific to the huffotronic update server. - // - - // we re-assert our special texture set here, in case some wayward scripts have - // messed with us. - integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); - integer indy; - for (indy = 0; indy < textures_held; indy++) { - string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); - // we have a simple scheme for putting textures on the updater. - // we have an inside, an outside and the ends. - if (is_prefix(curr_tex, "~~s0")) { - llSetTexture(curr_tex, ALL_SIDES); - } else if (is_prefix(curr_tex, "~~s1")) { - llSetTexture(curr_tex, 1); - } else if (is_prefix(curr_tex, "~~s2")) { - llSetTexture(curr_tex, 0); - llSetTexture(curr_tex, 3); - } - } - - // re-assert our texture animation also. - llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, - ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); -} - -// set up the update server object. -initialize_root() -{ - // set up our particular "look". - reset_all_effects(); - - // shut down any competing scripts in this object. - // we try to swat any other script that's been added before we let them do weird - // stuff. for example, a pet script might start acting like one. this - // function is not guaranteed to run before that bad stuff can happen, - // and that's maybe the one major issue with this approach. as long as - // the contained scripts aren't evil (like if they jump someplace else - // as soon as they start), then there shouldn't be any serious problems. - knock_down_other_scripts(); - - // reset our variables. - active_update_channels = []; - active_listen_ids = []; - active_clients = []; - active_timestamps = []; - scripts_available = []; - objects_available = []; - dealing_with_change = FALSE; // not handling any inventory changes. - - // make sure we know about any scripts that have new dependencies. - load_script_deps(); - - // clean out any older versions of the scripts before we make our - // inventory. - destroy_older_versions(); - - // now accumulate the list of scripts in our inventory. - integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); - integer indy; - for (indy = 0; indy < items_held; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - // we don't provide our own script for updating; it must be kept from - // floating around, like into other objects that are not updaters. -//// if (curr_script != llGetScriptName()) - scripts_available += curr_script; - } - items_held = llGetInventoryNumber(INVENTORY_OBJECT); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); -//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); - } - items_held = llGetInventoryNumber(INVENTORY_NOTECARD); - for (indy = 0; indy < items_held; indy++) { - objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); -//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); - } - - // listen to the owner. - llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); - // listen for any requests from our loyal clients. - inventory_request_channel = random_channel(); - llListen(inventory_request_channel, "", NULL_KEY, ""); - // listen for older clients too. - llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); - - // set up the periodic announcements. - llSetTimerEvent(ANNOUNCEMENT_PERIOD); -} - -handle_timer() -{ - if (dealing_with_change) { - dealing_with_change = FALSE; - state rerun; // zoom back to the starting point. - } - integer indy; - integer timecheck = llGetUnixTime(); // use for whole loop. - for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { - integer last_time = llList2Integer(active_timestamps, indy); - if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { - // we need to clear out this item. we know we can whack the client - // at the same index and that will take care of this slacker. - key curr_key = llList2Key(active_clients, indy); - log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); - remove_client(curr_key); - } - } - - // let the objects nearby know that we are open for business by - // announcing the script inventory. - announce_presence(); -} - -// turns a list into a nicely formatted string. -string dump_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string cursc = llList2String(to_show, indy); - msg += cursc; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// similar to dump_keyed_list, but only shows the names, each on their own line. -string dump_names_for_keys(list to_show) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we only line break after the first entry. - if (indy > 0) msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr); - } - return msg; -} - -// similar to dump_list -string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) -{ - string msg; - integer indy; - for (indy = 0; indy < llGetListLength(to_show); indy++) { - // we break every Nth entry, but not if it's the first line and - // they said to not have the initial line break. - if ( !(indy % entries_per_line) && (indy || initial_line_break) ) - msg += "\n"; - string keystr = llList2String(to_show, indy); - msg += llKey2Name(keystr) + " (" + keystr + ")"; - // add commas where needed. - if (indy < llGetListLength(to_show) - 1) - msg += ", "; - } - return msg; -} - -// shows the list specified in a compact manner. -show_list(string title, list to_show) -{ - string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); - // flush some memory. - title = ""; - to_show = []; - integer indy; - // say the output in pieces to avoid over-clogging chat. - for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { - integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; - string addition; - if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; - llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); - } -} - -// stops all the scripts besides this one. -knock_down_other_scripts() -{ - // set all scripts but this to not be running. - integer indy; - string self_script = llGetScriptName(); - list split = compute_basename_and_version(self_script); - string self_base = llList2String(split, 0); - self_script = ""; split = []; // free memory. - integer count = llGetInventoryNumber(INVENTORY_SCRIPT); - // we set all other scripts that are not versions of this script to not be running. - for (indy = 0; indy < count; indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if (!is_prefix(curr_script, self_base) - && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { - llSetScriptState(curr_script, FALSE); - } - } -} - -// set a text label on the updater with the list of clients. -set_our_label() -{ - string label = ""; - if (llGetListLength(active_clients) > 0) label = "[updating]\n"; - llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); -} - -// clean out a client that we should be done with. -remove_client(key id) -{ - // locate said client of deceased nature... - integer indy = find_in_list(active_clients, id); - if (indy < 0) { -// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); - return; - } - active_clients = llDeleteSubList(active_clients, indy, indy); - // also clean out the channel and stop listening to it. -integer act_chan = llList2Integer(active_update_channels, indy); - active_update_channels = llDeleteSubList(active_update_channels, indy, indy); - integer listen_to_remove = llList2Integer(active_listen_ids, indy); -//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); - llListenRemove(listen_to_remove); - active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); - active_timestamps = llDeleteSubList(active_timestamps, indy, indy); - set_our_label(); -} - -// fix a partial match to a script name if we can't find the exact item. -string backpatch_script_name(string partial) -{ - if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. - integer dep_indy; - for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { - string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); - if (is_prefix(curr_name, partial)) { -// log_it("found real name " + curr_name + " for part: " + partial); - return curr_name; - } - } -// log_it("no matches for partial script name!"); - return ""; // no matches! -} - -// moves the upgrade process with "id" along to the next step given the request in -// the message. -propel_upgrade_process(integer channel, key id, string message) -{ - if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); - if (message == REQUEST_SCRIPT_UPDATE) { - // begins the update process with the client. - llSay(channel, SHUT_THEM_DOWN); - } else if (is_prefix(message, READY_TO_UPDATE)) { - // whack the prefix so we can get the list they want. - message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); - list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); - message = ""; - // send over the scripts the client asked for, since it seems to be ready for them. - if (llGetListLength(requests)) { - show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); - integer indy; - for (indy = 0; indy < llGetListLength(requests); indy++) { - string curr = llList2String(requests, indy); - if (find_in_list(objects_available, curr) >= 0) { -//log_it("handing object over: " + curr); - // it's an object, so treat it that way. - llGiveInventory(id, curr); - } else { -//log_it("handing script over: " + curr); - // assume it's a script, and use script pin to stuff it. - curr = backpatch_script_name(curr); - if (curr != "") { -// integer starting_state = FALSE; -// second life was okay with scripts being plugged in unstarted. opensim is not. -// and second life appears to be unhappy with scripts plugged in as started. so we -// have an impasse. -// this should be: true for opensim, and false for second life. - integer starting_state = IS_OPENSIM; -// if (DEBUGGING) log_it("installing script using updater pin."); - llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); - } - } - } - } - } else if (message == SCRIPTS_ARE_CURRENT) { - // the client thinks it's ready to get back up and running. -//log_it("heard client is ready!"); - llSay(channel, START_THEM_UP); - // kludge for older clients (pre 10.4 version) to try to help them start up. -//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); - remove_client(id); - } else if (message == DONE_UPDATING) { - // this client has nothing to do for now. -//log_it("heard client is done: " + (string)id); - remove_client(id); - } else { -//log_it("weird note from client: " + message); - return; // not used. - } - -} - -// blasts out the inventory list to a curious client. -spew_inventory_list(integer channel, string message, key id) -{ - if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { - - // this is an old style update alert that we still use at startup of the client - // to ensure that finishing replacement of the updater script is never unnoticed. - if (is_prefix(message, DONE_UPDATING)) { -// if (DEBUGGING) log_it("found very special message from startup of updater."); - propel_upgrade_process(channel, id, message); - } - - // argh, this is not the right kind of message on our channel. - return; - } - string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); - integer new_update_channel = (integer)chan_str; - if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { - // got to tell them "not right now". we'll pretend we have no - // scripts; they'll know what we mean if the update client is - // recent enough. really old clients will just go to sleep until later. - if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); - llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); - return; - } - - // looks like we're going to try to handle the request for them. - if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); - -//log_it("add client convo chan " + (string)new_update_channel); - integer existing_indy = find_in_list(active_clients, id); - if (existing_indy < 0) { - active_clients += id; - active_update_channels += new_update_channel; - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); - active_listen_ids += new_listen_id; - active_timestamps += llGetUnixTime(); - set_our_label(); - } else { -// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); - // delete old listener so we don't leave it dangling. - integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); -//log_it("remove old listen " + (string)old_listen_id); - llListenRemove(old_listen_id); - // update the channel and listener id for the new registration. - active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) - + [ new_update_channel ] - + chop_list(active_update_channels, existing_indy + 1, - llGetListLength(active_update_channels) - 1); - integer new_listen_id = llListen(new_update_channel, "", id, ""); -//log_it("add new listen " + (string)new_listen_id); - active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_listen_ids, existing_indy + 1, - llGetListLength(active_listen_ids) - 1); - active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) - + [ new_listen_id ] - + chop_list(active_timestamps, existing_indy + 1, - llGetListLength(active_timestamps) - 1); - } - - // our report name is always called available scripts, but it can actually have - // script dependency definitions, script names and object names. - string msg = REPORT_AVAILABLE_SCRIPTS; - string curr; // temp. - - // add in the huff updater, since that's the most crucial that they know we have. - integer posn; - string UPDATE_CLIENT_SCRIPT = "huff-update client"; - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - == UPDATE_CLIENT_SCRIPT) { -//log_it("found " + curr); - msg += curr + UPDATER_PARM_SEPARATOR; - posn = 99999; // jump out. - } - if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { - log_it("epic fail, found no updater client script."); - } - } - - // speak about the dependencies that we know. - for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { - msg += SCRIPT_DEPENDENCY_MARK - + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // tell this new client what scripts we have. - for (posn = 0; posn < llGetListLength(scripts_available); posn++) { - curr = llList2String(scripts_available, posn); - if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) - != UPDATE_CLIENT_SCRIPT) { - // add in the next item, along with the parameter separator. - msg += curr + UPDATER_PARM_SEPARATOR; -//log_it("adding " + curr); - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { - // stop sending the list to them since they may not know how - // to interpret a multiple part update list. - return; - } - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - } - // mention any objects that are available. - for (posn = 0; posn < llGetListLength(objects_available); posn++) { - // add in the next item, along with the parameter separator. - msg += llList2String(objects_available, posn) - + UPDATER_PARM_SEPARATOR; - if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { - llSay(new_update_channel, msg + CONTINUANCE_MARKER); -//log_it(msg + CONTINUANCE_MARKER); - llSleep(SCRIPT_LIST_PAUSE_INTERVAL); - msg = REPORT_AVAILABLE_SCRIPTS; - } - } - // say final bit, even if it's mostly blank. we need to let them know - // that we're done and not adding that continuation flag string. - llSay(new_update_channel, msg); -} - -// handles verbal commands from objects that want updates. -process_verbal_requests(integer channel, string name, key id, string message) -{ - if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { - spew_inventory_list(channel, message, id); - return; - } else if (channel == USER_COMMAND_CHANNEL) { -if (DEBUGGING) log_it("heard orders: " + message); - // simple verbal commands. - if (message == RESTART_UPDATER_COMMAND) { - log_it("Restarting now."); - llResetScript(); - } else if (message == SHOW_SCRIPTS_COMMAND) { - show_scripts(); - } else if (message == SHUTDOWN_COMMAND) { - // we will de-rez now (i.e., die) if we are not one of the special names that is undying. - if (!matches_substring(llGetObjectName(), "keeper")) { -// log_it("server " + (string)inventory_request_channel + " now disintegrating."); - squonk(1); - llDie(); - } - } - return; - } - - integer indy; - // see if the channel is for one of our valid updates that's in progress. - for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { - integer cur_chan = llList2Integer(active_update_channels, indy); - if (cur_chan == channel) { - // yes, this is really for that guy. - propel_upgrade_process(channel, id, message); - return; - } - } -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. -// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// a random channel for the first interaction with the client. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } - - if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { - log_it("now restarting to avoid opensim late updating change event."); - llResetScript(); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.4. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -default -{ - state_entry() - { - auto_retire(); - initialize_root(); // get set up to start answering requests. - llWhisper(0, llGetScriptName() + " started... touch for more info."); - squonk(0); - } - - state_exit() { llSetTimerEvent(0); } - - on_rez(integer parm) { - state rerun; - } - - timer() { handle_timer(); } - - touch_start(integer count) { - show_status(llDetectedKey(0)); - } - - listen(integer channel, string name, key id, string message) { - // make sure that the object is something we should even talk to. - if (llGetOwnerKey(id) != llGetOwner()) { - return; - } - // looks okay, let's see if this is useful communication. - process_verbal_requests(channel, name, id, message); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { - log_it("inventory changed, scheduled a restart."); - // sleep a little bit; otherwise we get SL noise about scripts not being - // there when it told us they were there. this can lead to some scripts - // doing bizarre things if they are running when added. - dealing_with_change = TRUE; - llSetTimerEvent(0.0); // kludge to get around second life bug. - llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); - } - } -} - -state rerun { state_entry() { state default; } } - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.txt b/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.txt new file mode 100755 index 00000000..ef201cf7 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/a_huffotronic_update_server_v23.2.txt @@ -0,0 +1,940 @@ + +// huffware script: huff-update server, by fred huffhines. +// +// this script is the server side of the update process. it should reside in an object that +// has all the newest versions of scripts and objects that will be updated. when rezzed, and +// at periodic intervals, it announces on a private chat channel that updates are available. +// when objects respond that they might like an update, it tells them the scripts that it has +// stored inside of it. if any of those scripts are an older version inside the client +// (update requesting) object, then the client will request the newer versions. the server +// object will stuff them into it and tell them to start running. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer IS_OPENSIM = TRUE; // must be set to true for opensim, false for second life. + +integer DEBUGGING = FALSE; // set this to true for noisier diagnostics. + + + +// updater dependency section: +// should be moved to a notecard!!! +// +// format is a list of strings, where each string has a pair wrapped by the +// huffware item separators. the pair contains (1) the basename of a script +// that has a new dependency and (2) the basename of that new dependency. +list known_script_dependencies; + + + + +load_script_deps() +{ + known_script_dependencies = [ + llDumpList2String(["jaunt wik rez", "jaunt config funcs"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "data cow"], ITEM_LIST_SEPARATOR), + llDumpList2String(["jaunt wik rez", "jaunt rezolator"], ITEM_LIST_SEPARATOR), + llDumpList2String(["remotely personable", "inventory exchanger"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "exchange driver hudimation"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar timer manager"], ITEM_LIST_SEPARATOR), + llDumpList2String(["animote main driver", "avatar choice memory"], ITEM_LIST_SEPARATOR), + llDumpList2String(["giftorse", "particle projector"], ITEM_LIST_SEPARATOR), + llDumpList2String(["huff-search brainiac", "searchbert armature"], ITEM_LIST_SEPARATOR), + + +//special purpose -- removes the updater from the elevator buttons... +//llDumpList2String(["comfortable sitting", "zap updater from elevators"], ITEM_LIST_SEPARATOR), +// => do not uncomment unless you want your elevators to shed their ability to update. + + + // this allows us to add or remove items above at will without complaints about comma. + llDumpList2String(["xyzzy", "hopefully-never-matches"], ITEM_LIST_SEPARATOR) + ]; +} + + + + +// global constants... + +integer USER_COMMAND_CHANNEL = 4; // channel where we listen to user commands. + +float ANNOUNCEMENT_PERIOD = 14.0; // how often we tell other objects that we have tasty treats. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +string RESTART_UPDATER_COMMAND = "#restart"; // said in open chat to recrank the updater. +string SHOW_SCRIPTS_COMMAND = "#show"; // said in open chat to list out the scripts. +string SHUTDOWN_COMMAND = "#destroy"; // shuts down object and destroys it. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. + +integer ENTRIES_PER_LINE = 4; // number of items from a list shown on one line of text. + +integer MAXIMUM_ACTIVE_CLIENTS = 5; // number of conversations we will allow at a time. + +float LONGEST_SLACK_PER_CLIENT = 84.0; + // we allow a client to be out of touch with us for this many seconds. after that, + // we decide it's deceased and remove it from our list. + +integer MESSAGE_SIZE_LIMIT = 800; // longest thing that can be safely said without clipping (guess). + +float SCRIPT_LIST_PAUSE_INTERVAL = 1.4; // pause between large chunks of update text. + +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +float CHANGED_INVENTORY_SNOOZER = 7.0; + // the number of seconds we sleep once we see an inventory change. we don't want to + // react to this immediately. this overrides the normal announcement cycle until it's + // dealt with by the timer. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string UPDATER_BASE_NAME = "huff-update client"; + // the name of the updater script that keeps everything in sync. + +////////////// + +// global variables... + +list scripts_available; // the list of scripts we have in our inventory for distribution. +list objects_available; // list of objects for handing out. + +list active_clients; // list of keys for clients that are updating currently. +list active_update_channels; // active conversations on client chosen channels. +list active_listen_ids; // the ids for the listener on those channels. +list active_timestamps; // tracks when the client was last active. + +integer inventory_request_channel; // our personal channel that the update client should talk with. + +integer dealing_with_change; // has the inventory changed? we will deal with this in the timer. + +// displays the status of the update server. +show_status(key who_says) +{ + string title = "[mem free=" + (string)llGetFreeMemory() + "]"; + title = "Listening for requests on channel " + (string)inventory_request_channel; + if (llGetListLength(active_update_channels)) + title += "\nactive channels=" + + dump_list(active_update_channels, FALSE, ENTRIES_PER_LINE); + else + title += "\nNo channels active."; + + if (llGetListLength(active_clients)) + title += "\nactive clients=" + dump_keyed_list(active_clients, TRUE, 2); + else + title += "\nNo clients active."; + + if (llGetOwner() == who_says) { + string addition = " "; + if (USER_COMMAND_CHANNEL != 0) addition = "/" + (string)USER_COMMAND_CHANNEL + " "; + title += "\n[ \"" + addition + SHOW_SCRIPTS_COMMAND + "\" lists all the scripts, " + + "\"" + addition + SHUTDOWN_COMMAND + "\" zaps the updater, " + + "\"" + addition + RESTART_UPDATER_COMMAND + "\" refreshes the updater ]"; + } + + llWhisper(0, title); +} + +// plink a quietous string of resonance... +squonk(integer indy) +{ + string snd = llGetInventoryName(INVENTORY_SOUND, indy); + if (snd != "") llTriggerSound(snd, 1.0); +} + +// list out the scripts that the server's object contains. +show_scripts() +{ + string title = (string)llGetListLength(scripts_available) + " scripts available:"; + show_list(title, scripts_available); + title = (string)llGetListLength(objects_available) + " objects available:"; + show_list(title, objects_available); +} + +// lets the client know that we're here and have some scripts available. +announce_presence() +{ + if (llGetListLength(active_clients) < MAXIMUM_ACTIVE_CLIENTS) { + // only announce if we're not already booked up. + llWhisper(UPDATE_ANNOUNCEMENT_CHANNEL, UPDATE_ANNOUNCEMENT_PREFIX + (string)inventory_request_channel); + } +} + +// lifted from "clear text and effects" script; should be nearly identical +// to that, except that we set the texture animation. +reset_all_effects() +{ + llSetText("", <0,0,0>, 0); // clear any text above object. + llSetSitText("Sit Here"); // reset sit text to default state. + llSetTouchText("Touch"); // similarly for touch. + llSitTarget(ZERO_VECTOR, ZERO_ROTATION); // reset sit target position. + llParticleSystem([]); // turn off all particles. + llSensorRemove(); // stop any running sensors. + llTargetOmega(<0.0, 0.0, 0.0>, 0, 1.0); // stop rotations of object. + llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); // turn off any transparency. + // keep it from being physical and from disapparating. + llSetPrimitiveParams([PRIM_TEMP_ON_REZ, FALSE, PRIM_PHYSICS, FALSE, + PRIM_PHANTOM, TRUE]); + llSetLinkColor(LINK_SET, <1.0, 1.0, 1.0>, ALL_SIDES); // reset color to white. + + // + // the following are specific to the huffotronic update server. + // + + // we re-assert our special texture set here, in case some wayward scripts have + // messed with us. + integer textures_held = llGetInventoryNumber(INVENTORY_TEXTURE); + integer indy; + for (indy = 0; indy < textures_held; indy++) { + string curr_tex = llGetInventoryName(INVENTORY_TEXTURE, indy); + // we have a simple scheme for putting textures on the updater. + // we have an inside, an outside and the ends. + if (is_prefix(curr_tex, "~~s0")) { + llSetTexture(curr_tex, ALL_SIDES); + } else if (is_prefix(curr_tex, "~~s1")) { + llSetTexture(curr_tex, 1); + } else if (is_prefix(curr_tex, "~~s2")) { + llSetTexture(curr_tex, 0); + llSetTexture(curr_tex, 3); + } + } + + // re-assert our texture animation also. + llSetTextureAnim(ANIM_ON | LOOP | SMOOTH | ROTATE, + ALL_SIDES, 0, 0, 0, TWO_PI, 1.0 / 36.0); +} + +// set up the update server object. +initialize_root() +{ + // set up our particular "look". + reset_all_effects(); + + // shut down any competing scripts in this object. + // we try to swat any other script that's been added before we let them do weird + // stuff. for example, a pet script might start acting like one. this + // function is not guaranteed to run before that bad stuff can happen, + // and that's maybe the one major issue with this approach. as long as + // the contained scripts aren't evil (like if they jump someplace else + // as soon as they start), then there shouldn't be any serious problems. + knock_down_other_scripts(); + + // reset our variables. + active_update_channels = []; + active_listen_ids = []; + active_clients = []; + active_timestamps = []; + scripts_available = []; + objects_available = []; + dealing_with_change = FALSE; // not handling any inventory changes. + + // make sure we know about any scripts that have new dependencies. + load_script_deps(); + + // clean out any older versions of the scripts before we make our + // inventory. + destroy_older_versions(); + + // now accumulate the list of scripts in our inventory. + integer items_held = llGetInventoryNumber(INVENTORY_SCRIPT); + integer indy; + for (indy = 0; indy < items_held; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + // we don't provide our own script for updating; it must be kept from + // floating around, like into other objects that are not updaters. +//// if (curr_script != llGetScriptName()) + scripts_available += curr_script; + } + items_held = llGetInventoryNumber(INVENTORY_OBJECT); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_OBJECT, indy); +//log_it("added obj: " + llGetInventoryName(INVENTORY_OBJECT, indy)); + } + items_held = llGetInventoryNumber(INVENTORY_NOTECARD); + for (indy = 0; indy < items_held; indy++) { + objects_available += llGetInventoryName(INVENTORY_NOTECARD, indy); +//log_it("added note: " + llGetInventoryName(INVENTORY_NOTECARD, indy)); + } + + // listen to the owner. + llListen(USER_COMMAND_CHANNEL, "", llGetOwner(), ""); + // listen for any requests from our loyal clients. + inventory_request_channel = random_channel(); + llListen(inventory_request_channel, "", NULL_KEY, ""); + // listen for older clients too. + llListen(OLD_REQUEST_INVENTORY_CHANNEL, "", NULL_KEY, ""); + + // set up the periodic announcements. + llSetTimerEvent(ANNOUNCEMENT_PERIOD); +} + +handle_timer() +{ + if (dealing_with_change) { + dealing_with_change = FALSE; + state rerun; // zoom back to the starting point. + } + integer indy; + integer timecheck = llGetUnixTime(); // use for whole loop. + for (indy = llGetListLength(active_timestamps) - 1; indy >= 0; indy--) { + integer last_time = llList2Integer(active_timestamps, indy); + if (llAbs(last_time - timecheck) > LONGEST_SLACK_PER_CLIENT) { + // we need to clear out this item. we know we can whack the client + // at the same index and that will take care of this slacker. + key curr_key = llList2Key(active_clients, indy); + log_it("timed-out client: " + llKey2Name(curr_key) + " [" + (string)curr_key + "]"); + remove_client(curr_key); + } + } + + // let the objects nearby know that we are open for business by + // announcing the script inventory. + announce_presence(); +} + +// turns a list into a nicely formatted string. +string dump_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string cursc = llList2String(to_show, indy); + msg += cursc; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// similar to dump_keyed_list, but only shows the names, each on their own line. +string dump_names_for_keys(list to_show) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we only line break after the first entry. + if (indy > 0) msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr); + } + return msg; +} + +// similar to dump_list +string dump_keyed_list(list to_show, integer initial_line_break, integer entries_per_line) +{ + string msg; + integer indy; + for (indy = 0; indy < llGetListLength(to_show); indy++) { + // we break every Nth entry, but not if it's the first line and + // they said to not have the initial line break. + if ( !(indy % entries_per_line) && (indy || initial_line_break) ) + msg += "\n"; + string keystr = llList2String(to_show, indy); + msg += llKey2Name(keystr) + " (" + keystr + ")"; + // add commas where needed. + if (indy < llGetListLength(to_show) - 1) + msg += ", "; + } + return msg; +} + +// shows the list specified in a compact manner. +show_list(string title, list to_show) +{ + string to_say = title + dump_list(to_show, TRUE, ENTRIES_PER_LINE); + // flush some memory. + title = ""; + to_show = []; + integer indy; + // say the output in pieces to avoid over-clogging chat. + for (indy = 0; indy < llStringLength(to_say); indy += MESSAGE_SIZE_LIMIT) { + integer last_indy = indy + MESSAGE_SIZE_LIMIT - 1; + string addition; + if (last_indy < llStringLength(to_say)) addition = CONTINUANCE_MARKER; + llWhisper(0, llGetSubString(to_say, indy, last_indy) + addition); + } +} + +// stops all the scripts besides this one. +knock_down_other_scripts() +{ + // set all scripts but this to not be running. + integer indy; + string self_script = llGetScriptName(); + list split = compute_basename_and_version(self_script); + string self_base = llList2String(split, 0); + self_script = ""; split = []; // free memory. + integer count = llGetInventoryNumber(INVENTORY_SCRIPT); + // we set all other scripts that are not versions of this script to not be running. + for (indy = 0; indy < count; indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if (!is_prefix(curr_script, self_base) + && !is_prefix(curr_script, UPDATER_BASE_NAME) ) { + llSetScriptState(curr_script, FALSE); + } + } +} + +// set a text label on the updater with the list of clients. +set_our_label() +{ + string label = ""; + if (llGetListLength(active_clients) > 0) label = "[updating]\n"; + llSetText(label + dump_names_for_keys(active_clients), <0.8, 0.95, 0.92>, 1.0); +} + +// clean out a client that we should be done with. +remove_client(key id) +{ + // locate said client of deceased nature... + integer indy = find_in_list(active_clients, id); + if (indy < 0) { +// if (DEBUGGING) log_it("failure to find client to remove: " + (string)id); + return; + } + active_clients = llDeleteSubList(active_clients, indy, indy); + // also clean out the channel and stop listening to it. +integer act_chan = llList2Integer(active_update_channels, indy); + active_update_channels = llDeleteSubList(active_update_channels, indy, indy); + integer listen_to_remove = llList2Integer(active_listen_ids, indy); +//log_it("remove listen " + (string)listen_to_remove + " on chan " + (string)act_chan); + llListenRemove(listen_to_remove); + active_listen_ids = llDeleteSubList(active_listen_ids, indy, indy); + active_timestamps = llDeleteSubList(active_timestamps, indy, indy); + set_our_label(); +} + +// fix a partial match to a script name if we can't find the exact item. +string backpatch_script_name(string partial) +{ + if (llGetInventoryType(partial) == INVENTORY_SCRIPT) return partial; // all set. + integer dep_indy; + for (dep_indy = 0; dep_indy < llGetInventoryNumber(INVENTORY_SCRIPT); dep_indy++) { + string curr_name = llGetInventoryName(INVENTORY_SCRIPT, dep_indy); + if (is_prefix(curr_name, partial)) { +// log_it("found real name " + curr_name + " for part: " + partial); + return curr_name; + } + } +// log_it("no matches for partial script name!"); + return ""; // no matches! +} + +// moves the upgrade process with "id" along to the next step given the request in +// the message. +propel_upgrade_process(integer channel, key id, string message) +{ + if (DEBUGGING) log_it("got upgrade note from " + (string)id + " with msg=" + message); + if (message == REQUEST_SCRIPT_UPDATE) { + // begins the update process with the client. + llSay(channel, SHUT_THEM_DOWN); + } else if (is_prefix(message, READY_TO_UPDATE)) { + // whack the prefix so we can get the list they want. + message = llDeleteSubString(message, 0, llStringLength(READY_TO_UPDATE) - 1); + list requests = llParseString2List(message, [UPDATER_PARM_SEPARATOR], []); + message = ""; + // send over the scripts the client asked for, since it seems to be ready for them. + if (llGetListLength(requests)) { + show_list("updating " + llKey2Name(id) + " (key " + (string)id + ") with", requests); + integer indy; + for (indy = 0; indy < llGetListLength(requests); indy++) { + string curr = llList2String(requests, indy); + if (find_in_list(objects_available, curr) >= 0) { +//log_it("handing object over: " + curr); + // it's an object, so treat it that way. + llGiveInventory(id, curr); + } else { +//log_it("handing script over: " + curr); + // assume it's a script, and use script pin to stuff it. + curr = backpatch_script_name(curr); + if (curr != "") { +// integer starting_state = FALSE; +// second life was okay with scripts being plugged in unstarted. opensim is not. +// and second life appears to be unhappy with scripts plugged in as started. so we +// have an impasse. +// this should be: true for opensim, and false for second life. + integer starting_state = IS_OPENSIM; +// if (DEBUGGING) log_it("installing script using updater pin."); + llRemoteLoadScriptPin(id, curr, UPDATER_SCRIPT_PIN, starting_state, 0); + } + } + } + } + } else if (message == SCRIPTS_ARE_CURRENT) { + // the client thinks it's ready to get back up and running. +//log_it("heard client is ready!"); + llSay(channel, START_THEM_UP); + // kludge for older clients (pre 10.4 version) to try to help them start up. +//old and not useful. llSleep(0.2); llSay(channel, START_THEM_UP); llSleep(0.2); llSay(channel, START_THEM_UP); + remove_client(id); + } else if (message == DONE_UPDATING) { + // this client has nothing to do for now. +//log_it("heard client is done: " + (string)id); + remove_client(id); + } else { +//log_it("weird note from client: " + message); + return; // not used. + } + +} + +// blasts out the inventory list to a curious client. +spew_inventory_list(integer channel, string message, key id) +{ + if (!is_prefix(message, REQUEST_INVENTORY_PREFIX)) { + + // this is an old style update alert that we still use at startup of the client + // to ensure that finishing replacement of the updater script is never unnoticed. + if (is_prefix(message, DONE_UPDATING)) { +// if (DEBUGGING) log_it("found very special message from startup of updater."); + propel_upgrade_process(channel, id, message); + } + + // argh, this is not the right kind of message on our channel. + return; + } + string chan_str = llDeleteSubString(message, 0, llStringLength(REQUEST_INVENTORY_PREFIX) - 1); + integer new_update_channel = (integer)chan_str; + if (llGetListLength(active_clients) >= MAXIMUM_ACTIVE_CLIENTS) { + // got to tell them "not right now". we'll pretend we have no + // scripts; they'll know what we mean if the update client is + // recent enough. really old clients will just go to sleep until later. + if (DEBUGGING) log_it("having to disallow new client '" + llKey2Name(id) + "', too many now."); + llSay(new_update_channel, REPORT_AVAILABLE_SCRIPTS + BUSY_BUSY); + return; + } + + // looks like we're going to try to handle the request for them. + if (DEBUGGING) log_it("server heard update req on chan " + (string)channel + " from: " + llKey2Name(id)); + +//log_it("add client convo chan " + (string)new_update_channel); + integer existing_indy = find_in_list(active_clients, id); + if (existing_indy < 0) { + active_clients += id; + active_update_channels += new_update_channel; + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add listen " + (string)new_listen_id + " on chan " + (string)new_update_channel); + active_listen_ids += new_listen_id; + active_timestamps += llGetUnixTime(); + set_our_label(); + } else { +// if (DEBUGGING) log_it("same client came back before finishing previous upgrade, rolling with it."); + // delete old listener so we don't leave it dangling. + integer old_listen_id = llList2Integer(active_listen_ids, existing_indy); +//log_it("remove old listen " + (string)old_listen_id); + llListenRemove(old_listen_id); + // update the channel and listener id for the new registration. + active_update_channels = chop_list(active_update_channels, 0, existing_indy - 1) + + [ new_update_channel ] + + chop_list(active_update_channels, existing_indy + 1, + llGetListLength(active_update_channels) - 1); + integer new_listen_id = llListen(new_update_channel, "", id, ""); +//log_it("add new listen " + (string)new_listen_id); + active_listen_ids = chop_list(active_listen_ids, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_listen_ids, existing_indy + 1, + llGetListLength(active_listen_ids) - 1); + active_timestamps = chop_list(active_timestamps, 0, existing_indy - 1) + + [ new_listen_id ] + + chop_list(active_timestamps, existing_indy + 1, + llGetListLength(active_timestamps) - 1); + } + + // our report name is always called available scripts, but it can actually have + // script dependency definitions, script names and object names. + string msg = REPORT_AVAILABLE_SCRIPTS; + string curr; // temp. + + // add in the huff updater, since that's the most crucial that they know we have. + integer posn; + string UPDATE_CLIENT_SCRIPT = "huff-update client"; + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + == UPDATE_CLIENT_SCRIPT) { +//log_it("found " + curr); + msg += curr + UPDATER_PARM_SEPARATOR; + posn = 99999; // jump out. + } + if (DEBUGGING && (posn == llGetListLength(scripts_available) - 1) ) { + log_it("epic fail, found no updater client script."); + } + } + + // speak about the dependencies that we know. + for (posn = 0; posn < llGetListLength(known_script_dependencies); posn++) { + msg += SCRIPT_DEPENDENCY_MARK + + llList2String(known_script_dependencies, posn) + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // tell this new client what scripts we have. + for (posn = 0; posn < llGetListLength(scripts_available); posn++) { + curr = llList2String(scripts_available, posn); + if (llDeleteSubString(curr, llStringLength(UPDATE_CLIENT_SCRIPT), -1) + != UPDATE_CLIENT_SCRIPT) { + // add in the next item, along with the parameter separator. + msg += curr + UPDATER_PARM_SEPARATOR; +//log_it("adding " + curr); + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + if (channel == OLD_REQUEST_INVENTORY_CHANNEL) { + // stop sending the list to them since they may not know how + // to interpret a multiple part update list. + return; + } + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + } + // mention any objects that are available. + for (posn = 0; posn < llGetListLength(objects_available); posn++) { + // add in the next item, along with the parameter separator. + msg += llList2String(objects_available, posn) + + UPDATER_PARM_SEPARATOR; + if (llStringLength(msg) > MESSAGE_SIZE_LIMIT - 50) { + llSay(new_update_channel, msg + CONTINUANCE_MARKER); +//log_it(msg + CONTINUANCE_MARKER); + llSleep(SCRIPT_LIST_PAUSE_INTERVAL); + msg = REPORT_AVAILABLE_SCRIPTS; + } + } + // say final bit, even if it's mostly blank. we need to let them know + // that we're done and not adding that continuation flag string. + llSay(new_update_channel, msg); +} + +// handles verbal commands from objects that want updates. +process_verbal_requests(integer channel, string name, key id, string message) +{ + if ( (channel == OLD_REQUEST_INVENTORY_CHANNEL) || (channel == inventory_request_channel) ) { + spew_inventory_list(channel, message, id); + return; + } else if (channel == USER_COMMAND_CHANNEL) { +if (DEBUGGING) log_it("heard orders: " + message); + // simple verbal commands. + if (message == RESTART_UPDATER_COMMAND) { + log_it("Restarting now."); + llResetScript(); + } else if (message == SHOW_SCRIPTS_COMMAND) { + show_scripts(); + } else if (message == SHUTDOWN_COMMAND) { + // we will de-rez now (i.e., die) if we are not one of the special names that is undying. + if (!matches_substring(llGetObjectName(), "keeper")) { +// log_it("server " + (string)inventory_request_channel + " now disintegrating."); + squonk(1); + llDie(); + } + } + return; + } + + integer indy; + // see if the channel is for one of our valid updates that's in progress. + for (indy = 0; indy < llGetListLength(active_update_channels); indy++) { + integer cur_chan = llList2Integer(active_update_channels, indy); + if (cur_chan == channel) { + // yes, this is really for that guy. + propel_upgrade_process(channel, id, message); + return; + } + } +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. +// llOwnerSay(llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +llWhisper(0, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetDate() + ": " + llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// a random channel for the first interaction with the client. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } + + if (IS_OPENSIM && (llGetListLength(removal_list) > 0) ) { + log_it("now restarting to avoid opensim late updating change event."); + llResetScript(); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.4. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +default +{ + state_entry() + { + auto_retire(); + initialize_root(); // get set up to start answering requests. + llWhisper(0, llGetScriptName() + " started... touch for more info."); + squonk(0); + } + + state_exit() { llSetTimerEvent(0); } + + on_rez(integer parm) { + state rerun; + } + + timer() { handle_timer(); } + + touch_start(integer count) { + show_status(llDetectedKey(0)); + } + + listen(integer channel, string name, key id, string message) { + // make sure that the object is something we should even talk to. + if (llGetOwnerKey(id) != llGetOwner()) { + return; + } + // looks okay, let's see if this is useful communication. + process_verbal_requests(channel, name, id, message); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { + log_it("inventory changed, scheduled a restart."); + // sleep a little bit; otherwise we get SL noise about scripts not being + // there when it told us they were there. this can lead to some scripts + // doing bizarre things if they are running when added. + dealing_with_change = TRUE; + llSetTimerEvent(0.0); // kludge to get around second life bug. + llSetTimerEvent(CHANGED_INVENTORY_SNOOZER); + } + } +} + +state rerun { state_entry() { state default; } } + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.lsl b/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.lsl deleted file mode 100755 index e08b3b41..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.lsl +++ /dev/null @@ -1,186 +0,0 @@ - -// huffware script: a jumping bean, by fred huffhines -// -// an object will hop around randomly when it has this script. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -float MINIMUM_IMPULSE_MULTIPLIER = 0.05; - // the smallest amount we will allow the object to be bumped, relative to its mass. -float Z_IMPULSE_MULTIPLIER = 3.4; - // we push the object upwards relative to its mass by this amount (or less, since - // we randomly choose a value up to this large). -float X_IMPULSE_MULTIPLIER = 0.8; -float Y_IMPULSE_MULTIPLIER = 0.8; - // there are smaller x and y components possible. - -float MINIMUM_ROTATION_MULTIPLIER = 0.001; -// multipliers for rotation. -float X_ROTATION_MULTIPLIER = 0.08; -float Y_ROTATION_MULTIPLIER = 0.08; -float Z_ROTATION_MULTIPLIER = 0.08; - -////////////// -// from hufflets... -// -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} -// -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - llSetTimerEvent(0.3); - } - - timer() - { - if (llFrand(1.0) > 0.5) { - vector impulsive = ; - llApplyImpulse(llGetMass() * impulsive, FALSE); - impulsive = ; - llApplyRotationalImpulse(impulsive, FALSE); - } - } - - changed(integer change) { - if (change & CHANGED_LINK) { - key av = llAvatarOnSitTarget(); - if (av != NULL_KEY) { - // someone sat down; let's animate them to make them tuck into the - // bean, if possible. - llStartAnimation("crouch"); - } - } - } - -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.txt b/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.txt new file mode 100755 index 00000000..e08b3b41 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/a_jumping_bean_v2.7.txt @@ -0,0 +1,186 @@ + +// huffware script: a jumping bean, by fred huffhines +// +// an object will hop around randomly when it has this script. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +float MINIMUM_IMPULSE_MULTIPLIER = 0.05; + // the smallest amount we will allow the object to be bumped, relative to its mass. +float Z_IMPULSE_MULTIPLIER = 3.4; + // we push the object upwards relative to its mass by this amount (or less, since + // we randomly choose a value up to this large). +float X_IMPULSE_MULTIPLIER = 0.8; +float Y_IMPULSE_MULTIPLIER = 0.8; + // there are smaller x and y components possible. + +float MINIMUM_ROTATION_MULTIPLIER = 0.001; +// multipliers for rotation. +float X_ROTATION_MULTIPLIER = 0.08; +float Y_ROTATION_MULTIPLIER = 0.08; +float Z_ROTATION_MULTIPLIER = 0.08; + +////////////// +// from hufflets... +// +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} +// +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + llSetTimerEvent(0.3); + } + + timer() + { + if (llFrand(1.0) > 0.5) { + vector impulsive = ; + llApplyImpulse(llGetMass() * impulsive, FALSE); + impulsive = ; + llApplyRotationalImpulse(impulsive, FALSE); + } + } + + changed(integer change) { + if (change & CHANGED_LINK) { + key av = llAvatarOnSitTarget(); + if (av != NULL_KEY) { + // someone sat down; let's animate them to make them tuck into the + // bean, if possible. + llStartAnimation("crouch"); + } + } + } + +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.lsl b/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.lsl deleted file mode 100755 index 74830f01..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.lsl +++ /dev/null @@ -1,156 +0,0 @@ - -// huffware script: altitudinator, by fred huffhines -// -// displays an altimeter reading in the object's text. -// modified by fred huffhines, originally from LSL scripting library. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - llSetTimerEvent(.01); // How often your timer() event updates - } - - timer() - { - vector pos = llGetPos(); // Gets your current position - vector size = llGetAgentSize(llGetOwner()); // Get the dimensions of your agent - size.z = size.z / 2.0; // Halve the height element of your agent, get altitude from feet - float aboveground = ((float)pos.z - llGround(<0.0,0.0,0.0>) - size.z); // Distance above ground - if (aboveground < 0.0) // If it thinks your feet are below ground - { - aboveground = llSqrt(aboveground * aboveground); // - flip it - } - if (aboveground < 0.09) // Check the margin of error for zeroing - you can redefine this - { - aboveground = 0.0; // Zero it out - } - vector Speed = llGetVel(); // LSL function that should be fixed in next release. - float RealSpeed = llVecMag(Speed); // Convert it to velocity you can use. - float abovewater = llWater(<0.0,0.0,0.0>) - pos.z; // difference between yourwater height - if (pos.z >= llWater(<0.0,0.0,0.0>)) // If at or above water - { - abovewater = llSqrt(abovewater * abovewater); - } - if (pos.z < llWater(<0.0,0.0,0.0>)) // If underwater - { - abovewater = abovewater - (abovewater * 2.0); // Push the number into the negative range - } -// string current = llGetText(); - llSetText("Sea Lvl ALT: " + (string)abovewater + "\n" + "Grnd Lvl ALT: " - + (string)(aboveground) + "\nSpeed: " + (string)RealSpeed, <0.1,0.8,0.3>, 1.0); // Emit string - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.txt b/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.txt new file mode 100755 index 00000000..74830f01 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/altitudinator_v1.1.txt @@ -0,0 +1,156 @@ + +// huffware script: altitudinator, by fred huffhines +// +// displays an altimeter reading in the object's text. +// modified by fred huffhines, originally from LSL scripting library. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + llSetTimerEvent(.01); // How often your timer() event updates + } + + timer() + { + vector pos = llGetPos(); // Gets your current position + vector size = llGetAgentSize(llGetOwner()); // Get the dimensions of your agent + size.z = size.z / 2.0; // Halve the height element of your agent, get altitude from feet + float aboveground = ((float)pos.z - llGround(<0.0,0.0,0.0>) - size.z); // Distance above ground + if (aboveground < 0.0) // If it thinks your feet are below ground + { + aboveground = llSqrt(aboveground * aboveground); // - flip it + } + if (aboveground < 0.09) // Check the margin of error for zeroing - you can redefine this + { + aboveground = 0.0; // Zero it out + } + vector Speed = llGetVel(); // LSL function that should be fixed in next release. + float RealSpeed = llVecMag(Speed); // Convert it to velocity you can use. + float abovewater = llWater(<0.0,0.0,0.0>) - pos.z; // difference between yourwater height + if (pos.z >= llWater(<0.0,0.0,0.0>)) // If at or above water + { + abovewater = llSqrt(abovewater * abovewater); + } + if (pos.z < llWater(<0.0,0.0,0.0>)) // If underwater + { + abovewater = abovewater - (abovewater * 2.0); // Push the number into the negative range + } +// string current = llGetText(); + llSetText("Sea Lvl ALT: " + (string)abovewater + "\n" + "Grnd Lvl ALT: " + + (string)(aboveground) + "\nSpeed: " + (string)RealSpeed, <0.1,0.8,0.3>, 1.0); // Emit string + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/ama_omega_et_al_vendor_owner-only_v0.5.lsl b/huffware/huffotronic_tools_n_testers_v6.1/ama_omega_et_al_vendor_owner-only_v0.5.lsl deleted file mode 100755 index 784fdc3f..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/ama_omega_et_al_vendor_owner-only_v0.5.lsl +++ /dev/null @@ -1,261 +0,0 @@ -//Multi Vendor by Adelle Fitzgerald -//Based on the Ama Omega Vendor Script v0.3.1 06/2004 - - -//Licenced under Creative Commons Attribution-Share Alike 3.0 Unported - http://creativecommons.org/licenses/by-sa/3.0/ - - -//You are free: - -// * to Share — to copy, distribute and transmit the work -// * to Remix — to adapt the work - -//Under the following conditions: - -// * Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). - -// * Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. - -//With the understanding that: - -// * Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. -// * Public Domain — Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. -// * Other Rights — In no way are any of the following rights affected by the license: -// o Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; -// o The author's moral rights; -// o Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. -// * Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. - -//Disclaimer - -//The Commons Deed is not a license. It is simply a handy reference for understanding the Legal Code (the full license) — it is a human-readable expression of some of its key terms. Think of it as the user-friendly interface to the Legal Code beneath. This Deed itself has no legal value, and its contents do not appear in the actual license. - -//Creative Commons is not a law firm and does not provide legal services. Distributing of, displaying of, or linking to this Commons Deed does not create an attorney-client relationship. - - -integer gChannel; -integer handle; -string name = "Vendor "; -integer display; -list pics; -list desc; -list items; -list sold; -list info; -key gUser; -key k; -list temp; -integer line; -integer l; -string s; -string hText; -integer totItems; -string button; - - -incSold(integer i) -{ - sold = llListInsertList(llDeleteSubList(sold,i,i),[(integer)(llList2Integer(sold,i) + 1)],i); -} - -doMenu() -{ - //llSay(0,(string)gChannel + " : " + (string)gUser); //say gChannel - llSetTimerEvent(30); - llDialog(gUser, "Settings:", ["Cancel", "Report", "Get Item", "Reset"], gChannel); -} - -doCancel() -{ - llListenControl(handle, FALSE); - llSetTimerEvent(0); -} - -next() -{ - display += 1; - if (display >= llGetListLength(items)) display = 0; - llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); - llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); - llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); - llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); -} - -prev() -{ - display -= 1; - if (display < 0) display = llGetListLength(items) - 1; - llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); - llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); - llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); - llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); -} - -init() -{ - display = 0; - if (display < 0) display = llGetListLength(items) - 1; - llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); - llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); - llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); - llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); -} - - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() - { - state - readCard; - } -} - -state running -{ - state_entry() - { - gChannel = (integer)llFrand(2147423647) + 10000; - handle = llListen(gChannel, "", llGetOwner(), ""); - llListenControl(handle, FALSE); - init(); - } - - on_rez(integer param) - { - llResetScript(); - } - - listen(integer chan, string name, key id, string mes) - { - if (id != llGetOwner()) { - llWhisper(0, "Sorry, this vendor is restricted for use by its owner."); - return; - } - if (mes == "Reset") - { - doCancel(); - state readCard; - } - else if (mes == "Report") - { - integer i; - for(i=0;i= llGetListLength(items)) display = 0; + llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); + llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); + llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); + llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); +} + +prev() +{ + display -= 1; + if (display < 0) display = llGetListLength(items) - 1; + llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); + llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); + llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); + llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); +} + +init() +{ + display = 0; + if (display < 0) display = llGetListLength(items) - 1; + llSetText("Item: " + (string)(display + 1) + " of " + (string)totItems + "\n" + llList2String(items,display) + "\n" + llList2String(desc,display),<1,1,1>,1); + llMessageLinked(LINK_SET,1,"PIC",llGetInventoryKey((key)llList2String(pics,display))); + llMessageLinked(LINK_SET,1,"LOADNEXT",llGetInventoryKey((key)llList2String(pics,display + 1))); + llMessageLinked(LINK_SET,1,"LOADPREV",llGetInventoryKey((key)llList2String(pics,display - 1))); +} + + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() + { + state + readCard; + } +} + +state running +{ + state_entry() + { + gChannel = (integer)llFrand(2147423647) + 10000; + handle = llListen(gChannel, "", llGetOwner(), ""); + llListenControl(handle, FALSE); + init(); + } + + on_rez(integer param) + { + llResetScript(); + } + + listen(integer chan, string name, key id, string mes) + { + if (id != llGetOwner()) { + llWhisper(0, "Sorry, this vendor is restricted for use by its owner."); + return; + } + if (mes == "Reset") + { + doCancel(); + state readCard; + } + else if (mes == "Report") + { + integer i; + for(i=0;i; // minimum jitter amount, in degrees. -vector MAX_ANGULAR_POSITION = <1.0, 1.0, 4.0>; // maximum jitter amount, in degrees. - -float TIMER_FREQUENCY = 0.20; - // this is the fastest that prim changes can happen anyhow, - // so we fire the timer at this rate. - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "--" + (string)debug_num + ": " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns a random vector where x,y,z will be between "minimums" and "maximums" -// x,y,z components. if "allow_negative" is true, then any component will -// randomly be negative or positive. -vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) -{ - return ; -} - -// returns a vector whose components are between minimum and maximum. -// if allow_negative is true, then they can be either positive or negative. -vector random_vector(float minimum, float maximum, integer allow_negative) -{ - return random_bound_vector(, - , allow_negative); -} - -// returns TRUE if a is less than b in any component. -integer vector_less_than(vector a, vector b) -{ return (a.x < b.x) || (a.y < b.y) || (a.z < b.z); } - -// returns TRUE if a is greater than b in any component. -integer vector_greater_than(vector a, vector b) -{ return (a.x > b.x) || (a.y > b.y) || (a.z > b.z); } - -// returns a list with two components; a new vector and a boolean. -// the new vector starts from "starting_point". it will have a vector -// between "minimum_addition" and "maximum_addition" added to it. -// if it is over the "minimum_allowed" or the "maximum_allowed", then -// it is reset to whichever it would have crossed over. two booleans -// are also returned to indicate when the lower and upper limits were -// exceeded (in that order). -list limit_and_add(vector starting_point, - vector minimum_allowed, vector maximum_allowed, - vector minimum_addition, vector maximum_addition) -{ - integer too_low = FALSE; - integer too_high = FALSE; - vector new_location = starting_point; - vector addition = random_bound_vector(minimum_addition, maximum_addition, FALSE); -//log_it("start=" + (string)starting_point + " addin=" + (string)addition); - new_location += addition; - if (vector_less_than(new_location, minimum_allowed)) { - too_low = TRUE; - new_location = minimum_allowed; - } else if (vector_greater_than(new_location, maximum_allowed)) { - too_high = TRUE; - new_location = maximum_allowed; - } - return [ new_location, too_low, too_high ]; -} - -////////////// - -// variables used during the script. - -vector rez_position; - // set at time of object rez from object's current location. - -vector rez_rotation; - // set at time of object rez from object's current rotation. - -vector current_position_addin = <0.0, 0.0, 0.0>; - // the amount that we're adding to the rider's position right now. - -vector current_rotation_addin = <0.0, 0.0, 0.0>; - // randomly assigned to if JITTER_EFFECT is true. - -vector current_direction = <1.0, 1.0, 1.0>; - // we start out by adding to all axes. - -// provides a random vector that could be negative or positive for -// any of the values. the range is given by the two constants -// MIN_ADDITION and MAX_ADDITION. -vector rando_vector() -{ - return random_bound_vector(MIN_ANGULAR_POSITION * DEG_TO_RAD, - MAX_ANGULAR_POSITION * DEG_TO_RAD, TRUE); -} - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - rez_position = llGetPos(); - rez_rotation = llRot2Euler(llGetRot()); -//vector calc_rot = rez_rotation * RAD_TO_DEG; -//log_it("rotation at start is " + (string)calc_rot); - llSetTimerEvent(TIMER_FREQUENCY); - } - - on_rez(integer parm) { llResetScript(); } - - timer() - { - if (USE_X_AXIS) { - list add_result = limit_and_add(current_position_addin, - , - , - , - ); - current_position_addin = llList2Vector(add_result, 0); - integer too_low = llList2Integer(add_result, 1); - integer too_high = llList2Integer(add_result, 2); - if (too_low) current_direction.x = 1.0; - else if (too_high) current_direction.x = -1.0; - } - if (USE_Y_AXIS) { - list add_result = limit_and_add(current_position_addin, - , - , - <0.0, current_direction.y * MIN_POSITION_ADJUSTMENT, 0.0>, - <0.0, current_direction.y * MAX_POSITION_ADJUSTMENT, 0.0>); - current_position_addin = llList2Vector(add_result, 0); - integer too_low = llList2Integer(add_result, 1); - integer too_high = llList2Integer(add_result, 2); - if (too_low) current_direction.y = 1.0; - else if (too_high) current_direction.y = -1.0; - } - if (USE_Z_AXIS) { - list add_result = limit_and_add(current_position_addin, - , - , - <0.0, 0.0, current_direction.z * MIN_POSITION_ADJUSTMENT>, - <0.0, 0.0, current_direction.z * MAX_POSITION_ADJUSTMENT>); - current_position_addin = llList2Vector(add_result, 0); - integer too_low = llList2Integer(add_result, 1); - integer too_high = llList2Integer(add_result, 2); - if (too_low) current_direction.z = 1.0; - else if (too_high) current_direction.z = -1.0; - } - -//logic below for randomness is a bit odd. - // change the jitter position if we get a chance. - float starter = 0.420; // where we start looking for change. - float change_cap = starter + CHANCE_FOR_JITTER; - float randomness = llFrand(1.000); - if ( (randomness <= change_cap) && (randomness >= starter) ) { - // time for a change in the rotation. - if (JITTER_EFFECT) { - current_rotation_addin = rando_vector(); - } - } - - llSetPrimitiveParams([ - PRIM_POSITION, rez_position + current_position_addin, - PRIM_ROTATION, llEuler2Rot(rez_rotation + current_rotation_addin) - ]); - - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/axis_rider_v2.9.txt b/huffware/huffotronic_tools_n_testers_v6.1/axis_rider_v2.9.txt new file mode 100755 index 00000000..c26062cd --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/axis_rider_v2.9.txt @@ -0,0 +1,324 @@ + +// huffware script: axis rider, by fred huffhines. +// +// causes an object to move up and down on the z axis, although that and +// other parameters can be modified. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// these two control how far from the original position the object may travel. +float MIN_POSITION = -0.3; +float MAX_POSITION = 1.0; +// these specify which axis to modify and compare on. +integer USE_X_AXIS = FALSE; +integer USE_Y_AXIS = FALSE; +integer USE_Z_AXIS = TRUE; +// these are the limits on how much the object can move during one timer click. +float MIN_POSITION_ADJUSTMENT = 0.05; +float MAX_POSITION_ADJUSTMENT = 0.07; + +// jitter is the capability for the object to not be aligned on a straight +// up and down axis. +integer JITTER_EFFECT = TRUE; + // if this is true, then the rider will move unevenly at various angles. +float CHANCE_FOR_JITTER = 0.60; + // this is the probability of changing the current direction (0.0 to 1.0). +vector MIN_ANGULAR_POSITION = <0.0, 0.0, 0.0>; // minimum jitter amount, in degrees. +vector MAX_ANGULAR_POSITION = <1.0, 1.0, 4.0>; // maximum jitter amount, in degrees. + +float TIMER_FREQUENCY = 0.20; + // this is the fastest that prim changes can happen anyhow, + // so we fire the timer at this rate. + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "--" + (string)debug_num + ": " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "--" + (string)debug_num + ": " + to_say); +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns a random vector where x,y,z will be between "minimums" and "maximums" +// x,y,z components. if "allow_negative" is true, then any component will +// randomly be negative or positive. +vector random_bound_vector(vector minimums, vector maximums, integer allow_negative) +{ + return ; +} + +// returns a vector whose components are between minimum and maximum. +// if allow_negative is true, then they can be either positive or negative. +vector random_vector(float minimum, float maximum, integer allow_negative) +{ + return random_bound_vector(, + , allow_negative); +} + +// returns TRUE if a is less than b in any component. +integer vector_less_than(vector a, vector b) +{ return (a.x < b.x) || (a.y < b.y) || (a.z < b.z); } + +// returns TRUE if a is greater than b in any component. +integer vector_greater_than(vector a, vector b) +{ return (a.x > b.x) || (a.y > b.y) || (a.z > b.z); } + +// returns a list with two components; a new vector and a boolean. +// the new vector starts from "starting_point". it will have a vector +// between "minimum_addition" and "maximum_addition" added to it. +// if it is over the "minimum_allowed" or the "maximum_allowed", then +// it is reset to whichever it would have crossed over. two booleans +// are also returned to indicate when the lower and upper limits were +// exceeded (in that order). +list limit_and_add(vector starting_point, + vector minimum_allowed, vector maximum_allowed, + vector minimum_addition, vector maximum_addition) +{ + integer too_low = FALSE; + integer too_high = FALSE; + vector new_location = starting_point; + vector addition = random_bound_vector(minimum_addition, maximum_addition, FALSE); +//log_it("start=" + (string)starting_point + " addin=" + (string)addition); + new_location += addition; + if (vector_less_than(new_location, minimum_allowed)) { + too_low = TRUE; + new_location = minimum_allowed; + } else if (vector_greater_than(new_location, maximum_allowed)) { + too_high = TRUE; + new_location = maximum_allowed; + } + return [ new_location, too_low, too_high ]; +} + +////////////// + +// variables used during the script. + +vector rez_position; + // set at time of object rez from object's current location. + +vector rez_rotation; + // set at time of object rez from object's current rotation. + +vector current_position_addin = <0.0, 0.0, 0.0>; + // the amount that we're adding to the rider's position right now. + +vector current_rotation_addin = <0.0, 0.0, 0.0>; + // randomly assigned to if JITTER_EFFECT is true. + +vector current_direction = <1.0, 1.0, 1.0>; + // we start out by adding to all axes. + +// provides a random vector that could be negative or positive for +// any of the values. the range is given by the two constants +// MIN_ADDITION and MAX_ADDITION. +vector rando_vector() +{ + return random_bound_vector(MIN_ANGULAR_POSITION * DEG_TO_RAD, + MAX_ANGULAR_POSITION * DEG_TO_RAD, TRUE); +} + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + rez_position = llGetPos(); + rez_rotation = llRot2Euler(llGetRot()); +//vector calc_rot = rez_rotation * RAD_TO_DEG; +//log_it("rotation at start is " + (string)calc_rot); + llSetTimerEvent(TIMER_FREQUENCY); + } + + on_rez(integer parm) { llResetScript(); } + + timer() + { + if (USE_X_AXIS) { + list add_result = limit_and_add(current_position_addin, + , + , + , + ); + current_position_addin = llList2Vector(add_result, 0); + integer too_low = llList2Integer(add_result, 1); + integer too_high = llList2Integer(add_result, 2); + if (too_low) current_direction.x = 1.0; + else if (too_high) current_direction.x = -1.0; + } + if (USE_Y_AXIS) { + list add_result = limit_and_add(current_position_addin, + , + , + <0.0, current_direction.y * MIN_POSITION_ADJUSTMENT, 0.0>, + <0.0, current_direction.y * MAX_POSITION_ADJUSTMENT, 0.0>); + current_position_addin = llList2Vector(add_result, 0); + integer too_low = llList2Integer(add_result, 1); + integer too_high = llList2Integer(add_result, 2); + if (too_low) current_direction.y = 1.0; + else if (too_high) current_direction.y = -1.0; + } + if (USE_Z_AXIS) { + list add_result = limit_and_add(current_position_addin, + , + , + <0.0, 0.0, current_direction.z * MIN_POSITION_ADJUSTMENT>, + <0.0, 0.0, current_direction.z * MAX_POSITION_ADJUSTMENT>); + current_position_addin = llList2Vector(add_result, 0); + integer too_low = llList2Integer(add_result, 1); + integer too_high = llList2Integer(add_result, 2); + if (too_low) current_direction.z = 1.0; + else if (too_high) current_direction.z = -1.0; + } + +//logic below for randomness is a bit odd. + // change the jitter position if we get a chance. + float starter = 0.420; // where we start looking for change. + float change_cap = starter + CHANCE_FOR_JITTER; + float randomness = llFrand(1.000); + if ( (randomness <= change_cap) && (randomness >= starter) ) { + // time for a change in the rotation. + if (JITTER_EFFECT) { + current_rotation_addin = rando_vector(); + } + } + + llSetPrimitiveParams([ + PRIM_POSITION, rez_position + current_position_addin, + PRIM_ROTATION, llEuler2Rot(rez_rotation + current_rotation_addin) + ]); + + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.lsl deleted file mode 100755 index 23a39dce..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.lsl +++ /dev/null @@ -1,217 +0,0 @@ - -// add-in... huffware script: notecard library, by fred huffhines -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// items controlled by the notecard... - -string NOTECARD_SIGNATURE = "#hoopy"; // the first line of the notecard must be this. - -string current_notecard_name = ""; // the name of the card we're reading now. -key current_query_id = NULL_KEY; // the query ID for the current notecard. -list query_contents; // the lines we have read from the notecard. -integer line_number; // which line are we at in notecard? -integer debug = FALSE; - -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. - -initialize() -{ - // we keep the same notecard name, in case it's still good. we want to - // avoid re-reading the notecard unless we see an inventory change. - current_query_id = NULL_KEY; - query_contents = []; - line_number = 0; -} - -// returns a non-empty string if "to_check" defines contents for "variable_name". -string defines_variable(string to_check, string variable_name) -{ - // clean initial spaces. - while (llGetSubString(to_check, 0, 0) == " ") - to_check = llDeleteSubString(to_check, 0, 0); - if (!is_prefix(to_check, variable_name)) return ""; - to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); - // clean any spaces or valid assignment characters. - while ( (llGetSubString(to_check, 0, 0) == " ") - || (llGetSubString(to_check, 0, 0) == "=") - || (llGetSubString(to_check, 0, 0) == ",") ) - to_check = llDeleteSubString(to_check, 0, 0); - if (debug) - log_it("set " + variable_name + " = " + to_check); - // return what's left of the string. - return to_check; -} - -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - string texture_name; // temporary used in reading texture name. - -//etc. -// if ( (content = defines_variable(to_parse, "debug")) != "") -// debug = (integer)content; - -} - -process_particle_settings(list particle_definitions) -{ - integer current_item = 0; - integer max_items = llGetListLength(particle_definitions); - while (current_item < max_items) { - string curr_line = llList2String(particle_definitions, current_item); - parse_variable_definition(curr_line); - current_item++; - } -} - -check_for_notecard() -{ - if (current_notecard_name != "") return; - current_notecard_name = llGetInventoryName(INVENTORY_NOTECARD, 0); - // if the notecard is real, then we will start reading it. - if (current_notecard_name != "") { - line_number = 0; - query_contents = []; - current_query_id = llGetNotecardLine(current_notecard_name, 0); - } -} - -////////////// -// from hufflets... - -////////////// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -////////////// - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// handles when blank strings need to come through the pipe. -string wrap_blank_string(string to_wrap) -{ - if (llStringLength(to_wrap)) return to_wrap; // that one is okay. - return "\"\""; // return a quoted nothing as a signal for a blank. -} - -// undoes a previously wrapped blank string. -string interpret_blank_string(string to_unwrap) -{ - if (to_unwrap == "\"\"") return ""; // that was an encoded blank. - return to_unwrap; // no encoding. -} - -////////////// - -// returns a number at most maximum and at least minimum. -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { -// auto_retire(); - initialize(); - check_for_notecard(); - } - - changed(integer change_type) { - if (change_type != CHANGED_INVENTORY) { - // we only care about inventory changes here. - return; - } - if (current_query_id != NULL_KEY) { - // we're already reading a card right now. - return; - } - // make sure we reset the old name. - current_notecard_name = ""; - check_for_notecard(); - } - - dataserver(key query_id, string data) { - if (query_id != current_query_id) { -log_it("not our query id somehow?"); -//log_it("weird query had: " + (string)data); - return; - } - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - if (!line_number) { - if (data != NOTECARD_SIGNATURE) { - // this card has the wrong signature at the top. quit bothering - // with it now. - return; - } - log_it("starting to read notecard " + current_notecard_name + "..."); - } - if (data != "") { - // add the non-blank line to our destination list. - query_contents += data; -//log_it("line " + (string)line_number + ": data=" + data); - } - line_number++; // increase the line count. - // request the next line from the notecard. - current_query_id = llGetNotecardLine(current_notecard_name, line_number); - } else { - // no more data, so we're done with this card. - current_query_id = NULL_KEY; - if (!llGetListLength(query_contents)) { - // nothing was read? the heck with this card. - current_notecard_name = ""; // toss bad card. - return; - } -log_it("notecard said:\n" + (string)(query_contents)); - log_it("done reading notecard " + current_notecard_name + "."); - } - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.txt new file mode 100755 index 00000000..23a39dce --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/base_note_read_v0.3.txt @@ -0,0 +1,217 @@ + +// add-in... huffware script: notecard library, by fred huffhines +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// items controlled by the notecard... + +string NOTECARD_SIGNATURE = "#hoopy"; // the first line of the notecard must be this. + +string current_notecard_name = ""; // the name of the card we're reading now. +key current_query_id = NULL_KEY; // the query ID for the current notecard. +list query_contents; // the lines we have read from the notecard. +integer line_number; // which line are we at in notecard? +integer debug = FALSE; + +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. + +initialize() +{ + // we keep the same notecard name, in case it's still good. we want to + // avoid re-reading the notecard unless we see an inventory change. + current_query_id = NULL_KEY; + query_contents = []; + line_number = 0; +} + +// returns a non-empty string if "to_check" defines contents for "variable_name". +string defines_variable(string to_check, string variable_name) +{ + // clean initial spaces. + while (llGetSubString(to_check, 0, 0) == " ") + to_check = llDeleteSubString(to_check, 0, 0); + if (!is_prefix(to_check, variable_name)) return ""; + to_check = llDeleteSubString(to_check, 0, llStringLength(variable_name) - 1); + // clean any spaces or valid assignment characters. + while ( (llGetSubString(to_check, 0, 0) == " ") + || (llGetSubString(to_check, 0, 0) == "=") + || (llGetSubString(to_check, 0, 0) == ",") ) + to_check = llDeleteSubString(to_check, 0, 0); + if (debug) + log_it("set " + variable_name + " = " + to_check); + // return what's left of the string. + return to_check; +} + +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + string texture_name; // temporary used in reading texture name. + +//etc. +// if ( (content = defines_variable(to_parse, "debug")) != "") +// debug = (integer)content; + +} + +process_particle_settings(list particle_definitions) +{ + integer current_item = 0; + integer max_items = llGetListLength(particle_definitions); + while (current_item < max_items) { + string curr_line = llList2String(particle_definitions, current_item); + parse_variable_definition(curr_line); + current_item++; + } +} + +check_for_notecard() +{ + if (current_notecard_name != "") return; + current_notecard_name = llGetInventoryName(INVENTORY_NOTECARD, 0); + // if the notecard is real, then we will start reading it. + if (current_notecard_name != "") { + line_number = 0; + query_contents = []; + current_query_id = llGetNotecardLine(current_notecard_name, 0); + } +} + +////////////// +// from hufflets... + +////////////// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +////////////// + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// handles when blank strings need to come through the pipe. +string wrap_blank_string(string to_wrap) +{ + if (llStringLength(to_wrap)) return to_wrap; // that one is okay. + return "\"\""; // return a quoted nothing as a signal for a blank. +} + +// undoes a previously wrapped blank string. +string interpret_blank_string(string to_unwrap) +{ + if (to_unwrap == "\"\"") return ""; // that was an encoded blank. + return to_unwrap; // no encoding. +} + +////////////// + +// returns a number at most maximum and at least minimum. +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { +// auto_retire(); + initialize(); + check_for_notecard(); + } + + changed(integer change_type) { + if (change_type != CHANGED_INVENTORY) { + // we only care about inventory changes here. + return; + } + if (current_query_id != NULL_KEY) { + // we're already reading a card right now. + return; + } + // make sure we reset the old name. + current_notecard_name = ""; + check_for_notecard(); + } + + dataserver(key query_id, string data) { + if (query_id != current_query_id) { +log_it("not our query id somehow?"); +//log_it("weird query had: " + (string)data); + return; + } + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + if (!line_number) { + if (data != NOTECARD_SIGNATURE) { + // this card has the wrong signature at the top. quit bothering + // with it now. + return; + } + log_it("starting to read notecard " + current_notecard_name + "..."); + } + if (data != "") { + // add the non-blank line to our destination list. + query_contents += data; +//log_it("line " + (string)line_number + ": data=" + data); + } + line_number++; // increase the line count. + // request the next line from the notecard. + current_query_id = llGetNotecardLine(current_notecard_name, line_number); + } else { + // no more data, so we're done with this card. + current_query_id = NULL_KEY; + if (!llGetListLength(query_contents)) { + // nothing was read? the heck with this card. + current_notecard_name = ""; // toss bad card. + return; + } +log_it("notecard said:\n" + (string)(query_contents)); + log_it("done reading notecard " + current_notecard_name + "."); + } + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.lsl b/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.lsl deleted file mode 100755 index 2f6c27bc..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.lsl +++ /dev/null @@ -1,229 +0,0 @@ - -// huffware script: begging bowl, by fred huffhines. -// -// handles gifts from visitors at our shop. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants. - -integer BEGGING_INTERVAL = 8; - // the period (in seconds) of our asking the avatar for money. - // keeping this reasonably high ensures that the begging jar isn't - // too noisy if someone is whanging away at it to play the sound or - // see the explosion. - -// variables, some with initializers. - -integer last_begging_time; // when we last pleaded for additional funding. - -integer tip_amount; // the amount given to us just recently. -integer total_tips = 638; - // 108 -- aug 30 2008 or so. 214 -- nov 28 2008. 342 -- dec 28 2008. - // 486 -- mar 21 2009. 589 -- may 12 2009. 632 -- aug 02 2009. - // 638 -- aug 31 2009. -key tippers_key = NULL_KEY; // the key for the avatar that has tipped us. -string last_tipper; // the name of the last tipper. - -show_label() -{ - string msg = "{ eepaw tipster }\ntouch for more info...\n.\nL$" - + (string)total_tips + " donated so far--thanks!"; - if (last_tipper != "") - msg += "\nLast recvd L$" + (string)tip_amount + " from " + last_tipper + ", yay!"; - llSetText(msg, <0.8, 0.6, 0.9>, 1); -} - -initialize_begging_bowl() -{ - show_label(); - llOwnerSay("ready to receive tips from customers..."); - llParticleSystem([]); - last_begging_time = llGetUnixTime(); // reset just to have some kindo value. - show_label(); -} - -thank_tipper_and_give_gifts(string name) -{ - llSay(0, "eepaw shop and its workers thank you for the tip, " + name + "!"); - last_tipper = name; // store this for our text. - string first_name = llDeleteSubString(name, llSubStringIndex(name, " "), -1); - llInstantMessage(tippers_key, first_name + ", thank you very much for your tip of L$" - + (string)tip_amount + ", from all of us at eepaw shop."); - llOwnerSay("received tip from " + name + " of L$" + (string)tip_amount + "."); - if (llGetInventoryNumber(INVENTORY_SOUND)) { - // we will only play one sound currently. - llPlaySound(llGetInventoryName(INVENTORY_SOUND, 0 ), 1.0); - } - - // give out pictures, notecards and objects that are hiding in the object. - integer indy; - list all_to_give; // the full set of gifts. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) - all_to_give += llGetInventoryName(INVENTORY_TEXTURE, indy); - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) - all_to_give += llGetInventoryName(INVENTORY_NOTECARD, indy); - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) - all_to_give += llGetInventoryName(INVENTORY_OBJECT, indy); - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) - all_to_give += llGetInventoryName(INVENTORY_SOUND, indy); - // pick a semi-meaningful folder name. - string gift_folder_name = "eepaw thanky! (you gave us L$" - + (string)tip_amount + " on " + llGetDate() + ")"; - // then gift it over. - llGiveInventoryList(tippers_key, gift_folder_name, all_to_give); - // record the tip. - total_tips += tip_amount; - llOwnerSay("tips so far: L$" + (string)total_tips + "."); - show_label(); // refresh our text label. -} - -handle_being_touched(integer num) { - // make sure we've waited enough time before begging again. - if (llAbs(llGetUnixTime() - last_begging_time) > BEGGING_INTERVAL) { - llSay(0, - "\nIt would be awesome if you could tip our hardworking widget gnomes.\n" - + "If you right-click this object, you can 'Pay' it a tip, which will\n" - + "go directly to the eepaw shop personnel. Thanks much!"); - // update our last begging time so we don't beg too often. - last_begging_time = llGetUnixTime(); - } - // explode the textures just a little bit, if we have any on hand. - integer indy; - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) { - llMakeExplosion(14, .4, 0.5, 4, 0.8, - llGetInventoryName(INVENTORY_TEXTURE, indy), <0.0, 0.0, 0.0>); - } - // play the last sound that we happen to have, if any at all. - llPlaySound(llGetInventoryName(INVENTORY_SOUND, llGetInventoryNumber(INVENTORY_SOUND) - 1), 1.0); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize_begging_bowl(); - } - - touch_start(integer num) { - handle_being_touched(num); - } - - money(key id, integer payment) { - tip_amount = payment; - tippers_key = id; - llRequestAgentData(id, DATA_NAME); - } - - dataserver(key query, string name) { thank_tipper_and_give_gifts(name); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.txt b/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.txt new file mode 100755 index 00000000..2f6c27bc --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/begging_bowl_v4.4.txt @@ -0,0 +1,229 @@ + +// huffware script: begging bowl, by fred huffhines. +// +// handles gifts from visitors at our shop. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants. + +integer BEGGING_INTERVAL = 8; + // the period (in seconds) of our asking the avatar for money. + // keeping this reasonably high ensures that the begging jar isn't + // too noisy if someone is whanging away at it to play the sound or + // see the explosion. + +// variables, some with initializers. + +integer last_begging_time; // when we last pleaded for additional funding. + +integer tip_amount; // the amount given to us just recently. +integer total_tips = 638; + // 108 -- aug 30 2008 or so. 214 -- nov 28 2008. 342 -- dec 28 2008. + // 486 -- mar 21 2009. 589 -- may 12 2009. 632 -- aug 02 2009. + // 638 -- aug 31 2009. +key tippers_key = NULL_KEY; // the key for the avatar that has tipped us. +string last_tipper; // the name of the last tipper. + +show_label() +{ + string msg = "{ eepaw tipster }\ntouch for more info...\n.\nL$" + + (string)total_tips + " donated so far--thanks!"; + if (last_tipper != "") + msg += "\nLast recvd L$" + (string)tip_amount + " from " + last_tipper + ", yay!"; + llSetText(msg, <0.8, 0.6, 0.9>, 1); +} + +initialize_begging_bowl() +{ + show_label(); + llOwnerSay("ready to receive tips from customers..."); + llParticleSystem([]); + last_begging_time = llGetUnixTime(); // reset just to have some kindo value. + show_label(); +} + +thank_tipper_and_give_gifts(string name) +{ + llSay(0, "eepaw shop and its workers thank you for the tip, " + name + "!"); + last_tipper = name; // store this for our text. + string first_name = llDeleteSubString(name, llSubStringIndex(name, " "), -1); + llInstantMessage(tippers_key, first_name + ", thank you very much for your tip of L$" + + (string)tip_amount + ", from all of us at eepaw shop."); + llOwnerSay("received tip from " + name + " of L$" + (string)tip_amount + "."); + if (llGetInventoryNumber(INVENTORY_SOUND)) { + // we will only play one sound currently. + llPlaySound(llGetInventoryName(INVENTORY_SOUND, 0 ), 1.0); + } + + // give out pictures, notecards and objects that are hiding in the object. + integer indy; + list all_to_give; // the full set of gifts. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) + all_to_give += llGetInventoryName(INVENTORY_TEXTURE, indy); + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_NOTECARD); indy++) + all_to_give += llGetInventoryName(INVENTORY_NOTECARD, indy); + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) + all_to_give += llGetInventoryName(INVENTORY_OBJECT, indy); + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_OBJECT); indy++) + all_to_give += llGetInventoryName(INVENTORY_SOUND, indy); + // pick a semi-meaningful folder name. + string gift_folder_name = "eepaw thanky! (you gave us L$" + + (string)tip_amount + " on " + llGetDate() + ")"; + // then gift it over. + llGiveInventoryList(tippers_key, gift_folder_name, all_to_give); + // record the tip. + total_tips += tip_amount; + llOwnerSay("tips so far: L$" + (string)total_tips + "."); + show_label(); // refresh our text label. +} + +handle_being_touched(integer num) { + // make sure we've waited enough time before begging again. + if (llAbs(llGetUnixTime() - last_begging_time) > BEGGING_INTERVAL) { + llSay(0, + "\nIt would be awesome if you could tip our hardworking widget gnomes.\n" + + "If you right-click this object, you can 'Pay' it a tip, which will\n" + + "go directly to the eepaw shop personnel. Thanks much!"); + // update our last begging time so we don't beg too often. + last_begging_time = llGetUnixTime(); + } + // explode the textures just a little bit, if we have any on hand. + integer indy; + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_TEXTURE); indy++) { + llMakeExplosion(14, .4, 0.5, 4, 0.8, + llGetInventoryName(INVENTORY_TEXTURE, indy), <0.0, 0.0, 0.0>); + } + // play the last sound that we happen to have, if any at all. + llPlaySound(llGetInventoryName(INVENTORY_SOUND, llGetInventoryNumber(INVENTORY_SOUND) - 1), 1.0); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize_begging_bowl(); + } + + touch_start(integer num) { + handle_being_touched(num); + } + + money(key id, integer payment) { + tip_amount = payment; + tippers_key = id; + llRequestAgentData(id, DATA_NAME); + } + + dataserver(key query, string name) { thank_tipper_and_give_gifts(name); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.lsl deleted file mode 100755 index e91d410e..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.lsl +++ /dev/null @@ -1,206 +0,0 @@ - -// huffware script: bouncer, by fred huffhines. -// -// this script repels an object or avatar that slams into it. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer PUSH_UPWARDS = TRUE; - // if this is true, the velocity is reflected upwards. this is sort of - // a trampoline effect. -integer PUSH_DIRECTLY_BACK = TRUE; - // if this is true, then the object's velocity is reflected directly back. - // this is not a realistic bounce since it is like every bounce hits the - // object at a tangent rather than having the angle be rotated as a - // reflection. - -integer AVATARS_ONLY = FALSE; - // if true, then the bouncer will only react to people and not things. - -float PUSH_MULTIPLIER = 32.0; - // increase the object's velocity by this factor, as part of how we - // help it along when it collides with us. - -integer LOCAL_AXIS = FALSE; - // use the axis relative to the object's rotation? - -// originally came from reverse_velocity from concussive script. -push_back(key act_upon, integer local_axis) -{ - list details = llGetObjectDetails(act_upon, [ OBJECT_VELOCITY ]); - vector current_velocity = llList2Vector(details, 0); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - // here's where we return the velocity exactly backwards along - // its own axis. this is not really very true to physics. - vector new_velocity = -PUSH_MULTIPLIER * current_velocity; - new_velocity *= llGetMass(); - llPushObject(act_upon, new_velocity, ZERO_VECTOR, local_axis); -} - -// causes the object to be thrown up into the air and magnifies their -// velocity. -push_up(key act_upon, integer local_axis) -{ - list details = llGetObjectDetails(act_upon, [ OBJECT_VELOCITY ]); - vector current_velocity = llList2Vector(details, 0); - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - // another example that's like the trampoline... -// vector new_velocity = PUSH_MULTIPLIER * llRot2Up(llGetRot()); - vector new_velocity = current_velocity; - new_velocity.z = -PUSH_MULTIPLIER * new_velocity.z; - new_velocity *= llGetMass(); - llPushObject(act_upon, new_velocity, ZERO_VECTOR, local_axis); -} - -// a newer method that can be used to 'continue' the velocity away from -// the bouncer but more upwards from an elastic collision than back at the av. -/////not implemented yet. -// needs good physics normal vector implementation. - -// called by the collision event handler when we detect something -// bumping into us. -handle_collisions(integer count) -{ - integer i; - for (i = 0; i < count; i++) { - if ( (AVATARS_ONLY && (llDetectedType(i) & AGENT) ) - || !AVATARS_ONLY) { - if (PUSH_UPWARDS) - push_up(llDetectedKey(i), LOCAL_AXIS); - if (PUSH_DIRECTLY_BACK) - push_back(llDetectedKey(i), LOCAL_AXIS); - } - } -} - -////////////// -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { auto_retire(); } - - collision(integer count) { handle_collisions(count); } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.txt new file mode 100755 index 00000000..e91d410e --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/bouncer_v2.0.txt @@ -0,0 +1,206 @@ + +// huffware script: bouncer, by fred huffhines. +// +// this script repels an object or avatar that slams into it. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer PUSH_UPWARDS = TRUE; + // if this is true, the velocity is reflected upwards. this is sort of + // a trampoline effect. +integer PUSH_DIRECTLY_BACK = TRUE; + // if this is true, then the object's velocity is reflected directly back. + // this is not a realistic bounce since it is like every bounce hits the + // object at a tangent rather than having the angle be rotated as a + // reflection. + +integer AVATARS_ONLY = FALSE; + // if true, then the bouncer will only react to people and not things. + +float PUSH_MULTIPLIER = 32.0; + // increase the object's velocity by this factor, as part of how we + // help it along when it collides with us. + +integer LOCAL_AXIS = FALSE; + // use the axis relative to the object's rotation? + +// originally came from reverse_velocity from concussive script. +push_back(key act_upon, integer local_axis) +{ + list details = llGetObjectDetails(act_upon, [ OBJECT_VELOCITY ]); + vector current_velocity = llList2Vector(details, 0); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + // here's where we return the velocity exactly backwards along + // its own axis. this is not really very true to physics. + vector new_velocity = -PUSH_MULTIPLIER * current_velocity; + new_velocity *= llGetMass(); + llPushObject(act_upon, new_velocity, ZERO_VECTOR, local_axis); +} + +// causes the object to be thrown up into the air and magnifies their +// velocity. +push_up(key act_upon, integer local_axis) +{ + list details = llGetObjectDetails(act_upon, [ OBJECT_VELOCITY ]); + vector current_velocity = llList2Vector(details, 0); + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + // another example that's like the trampoline... +// vector new_velocity = PUSH_MULTIPLIER * llRot2Up(llGetRot()); + vector new_velocity = current_velocity; + new_velocity.z = -PUSH_MULTIPLIER * new_velocity.z; + new_velocity *= llGetMass(); + llPushObject(act_upon, new_velocity, ZERO_VECTOR, local_axis); +} + +// a newer method that can be used to 'continue' the velocity away from +// the bouncer but more upwards from an elastic collision than back at the av. +/////not implemented yet. +// needs good physics normal vector implementation. + +// called by the collision event handler when we detect something +// bumping into us. +handle_collisions(integer count) +{ + integer i; + for (i = 0; i < count; i++) { + if ( (AVATARS_ONLY && (llDetectedType(i) & AGENT) ) + || !AVATARS_ONLY) { + if (PUSH_UPWARDS) + push_up(llDetectedKey(i), LOCAL_AXIS); + if (PUSH_DIRECTLY_BACK) + push_back(llDetectedKey(i), LOCAL_AXIS); + } + } +} + +////////////// +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { auto_retire(); } + + collision(integer count) { handle_collisions(count); } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.lsl b/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.lsl deleted file mode 100755 index cd297f29..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.lsl +++ /dev/null @@ -1,188 +0,0 @@ - -// huffware script: box mover, by fred huffhines. -// -// a really simple script to make a box jump out of one's way. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - - -//hmmm: fix this to use a notecard for dimensions and members. - - -// modifiable constants. - -vector jump_offset = <4.0, -3.0, 0.0>; // how far to jump away from the starting place. - -list allowed_avatars = [ "fred huffhines", "Chronical Koolhoven", "Mojopickle Haystack", - "Zeno Olifone", "After9 NightFire", "Wam7c Macchi" ]; - -// variables below. - -vector home; // where do we live normally? - -// makes our list of allowed keys into uniform lower case. -fix_list_items() -{ - integer i; - list fixed_list; - for (i = 0; i < llGetListLength(allowed_avatars); i++) { - string curr = llList2String(allowed_avatars, i); - curr = llToLower(curr); - fixed_list += [curr]; - } - allowed_avatars = fixed_list; -//llOwnerSay("got a new list of: " + (string)allowed_avatars); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. - fix_list_items(); // make sure entries are lower case. - home = llGetPos(); - } - - touch_start(integer total_number) { -llOwnerSay("touched by " + llDetectedName(0)); - // if we're not the owner, then we've got a few extra requirements before - // we do anything at all. - if (llDetectedKey(0) != llGetOwner()) { - list lowname = [ llToLower(llDetectedName(0)) ]; - if (llListFindList(allowed_avatars, lowname) < 0) { - // this guy is not in our access list. -llOwnerSay("denying " + llDetectedName(0) + " because not in list and not owner."); - return; - } - } - float max_drift = 0.01; - // are we considered close enough to home? not if farther than this amount. - vector diff = llGetPos() - home; - if (diff.x < 0.0) diff = ; - if (diff.y < 0.0) diff = ; - if (diff.z < 0.0) diff = ; - // this all is not really a vector difference, but more a check on each component. - if ( (diff.x > max_drift) || (diff.y > max_drift) || (diff.z > max_drift) ) { - // we're far away from home, so let's jump back there. - llSetPos(home); - } else { - // we are at home, so we're jumping away. - llSetPos(home - jump_offset); - llSetTimerEvent(14.0); // reset the position in a few secs. - } - } - timer() { - llSetPos(home); - llSetTimerEvent(0.0); // reset timer. - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.txt b/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.txt new file mode 100755 index 00000000..cd297f29 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/box_mover_v1.7.txt @@ -0,0 +1,188 @@ + +// huffware script: box mover, by fred huffhines. +// +// a really simple script to make a box jump out of one's way. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + + +//hmmm: fix this to use a notecard for dimensions and members. + + +// modifiable constants. + +vector jump_offset = <4.0, -3.0, 0.0>; // how far to jump away from the starting place. + +list allowed_avatars = [ "fred huffhines", "Chronical Koolhoven", "Mojopickle Haystack", + "Zeno Olifone", "After9 NightFire", "Wam7c Macchi" ]; + +// variables below. + +vector home; // where do we live normally? + +// makes our list of allowed keys into uniform lower case. +fix_list_items() +{ + integer i; + list fixed_list; + for (i = 0; i < llGetListLength(allowed_avatars); i++) { + string curr = llList2String(allowed_avatars, i); + curr = llToLower(curr); + fixed_list += [curr]; + } + allowed_avatars = fixed_list; +//llOwnerSay("got a new list of: " + (string)allowed_avatars); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. + fix_list_items(); // make sure entries are lower case. + home = llGetPos(); + } + + touch_start(integer total_number) { +llOwnerSay("touched by " + llDetectedName(0)); + // if we're not the owner, then we've got a few extra requirements before + // we do anything at all. + if (llDetectedKey(0) != llGetOwner()) { + list lowname = [ llToLower(llDetectedName(0)) ]; + if (llListFindList(allowed_avatars, lowname) < 0) { + // this guy is not in our access list. +llOwnerSay("denying " + llDetectedName(0) + " because not in list and not owner."); + return; + } + } + float max_drift = 0.01; + // are we considered close enough to home? not if farther than this amount. + vector diff = llGetPos() - home; + if (diff.x < 0.0) diff = ; + if (diff.y < 0.0) diff = ; + if (diff.z < 0.0) diff = ; + // this all is not really a vector difference, but more a check on each component. + if ( (diff.x > max_drift) || (diff.y > max_drift) || (diff.z > max_drift) ) { + // we're far away from home, so let's jump back there. + llSetPos(home); + } else { + // we are at home, so we're jumping away. + llSetPos(home - jump_offset); + llSetTimerEvent(14.0); // reset the position in a few secs. + } + } + timer() { + llSetPos(home); + llSetTimerEvent(0.0); // reset timer. + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.lsl b/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.lsl deleted file mode 100755 index 393918b8..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.lsl +++ /dev/null @@ -1,57 +0,0 @@ - -// huffware script: button pusher, by fred huffhines -// -// a simple API for reporting when buttons are pushed. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// this is a kludgy thing, but this must be hard-coded to have the right button -// name for what the rest of the device is expecting. it should vary depending on -// the actual button prim that this script is placed in. -string BUTTON_NAME = "next"; - -// the button pushing API. -////////////// -integer BUTTON_PUSHER_HUFFWARE_ID = 10035; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string BUTTON_PUSHED_ALERT = "#btnp"; - // this event is generated when the button is pushed. the number parameter will be - // the huffware id plus the reply distance. the id parameter in the link message will - // contain the name of the button that was pushed. -////////////// - -// generates our button pressed alert, when the user has finished clicking on the button. -send_button_event() -{ -//llOwnerSay("user clicked on button " + BUTTON_NAME); - llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, - BUTTON_PUSHED_ALERT, BUTTON_NAME); -} - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - } - - touch_end(integer count) { - if (llDetectedLinkNumber(0) == llGetLinkNumber()) - send_button_event(); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.txt b/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.txt new file mode 100755 index 00000000..393918b8 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/button_pusher_v0.5.txt @@ -0,0 +1,57 @@ + +// huffware script: button pusher, by fred huffhines +// +// a simple API for reporting when buttons are pushed. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// this is a kludgy thing, but this must be hard-coded to have the right button +// name for what the rest of the device is expecting. it should vary depending on +// the actual button prim that this script is placed in. +string BUTTON_NAME = "next"; + +// the button pushing API. +////////////// +integer BUTTON_PUSHER_HUFFWARE_ID = 10035; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string BUTTON_PUSHED_ALERT = "#btnp"; + // this event is generated when the button is pushed. the number parameter will be + // the huffware id plus the reply distance. the id parameter in the link message will + // contain the name of the button that was pushed. +////////////// + +// generates our button pressed alert, when the user has finished clicking on the button. +send_button_event() +{ +//llOwnerSay("user clicked on button " + BUTTON_NAME); + llMessageLinked(LINK_SET, BUTTON_PUSHER_HUFFWARE_ID + REPLY_DISTANCE, + BUTTON_PUSHED_ALERT, BUTTON_NAME); +} + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + } + + touch_end(integer count) { + if (llDetectedLinkNumber(0) == llGetLinkNumber()) + send_button_event(); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.lsl deleted file mode 100755 index 50c0ef10..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.lsl +++ /dev/null @@ -1,263 +0,0 @@ - -// huffware script: chaos picks a number, by fred huffhines. -// (was formerly called "raffles asks chaos a question") -// -// produces a random number between 0 and the MAXIMUM_VALUE defined below. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer MAXIMUM_VALUE = 100; - // this is the highest number the generator will produce. - // the range is from zero, a very poor pick, to the number above - // (the best pick), inclusive. - -/////////////// - -// from hufflets... - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// variables used in the script... - -list participants = []; - // the people who have already received a number in this drawing. - -integer highest_picked = 0; - // the highest picked so far. - -string winner_so_far = ""; - // the name of the person who got the highest number to this point. - -integer lottery_finished = FALSE; - // true when the lottery has been completed. - -initialize() -{ - highest_picked = 0; - participants = []; - winner_so_far = ""; - lottery_finished = FALSE; - llSay(0, "ready to draw random numbers from 0 to " - + (string)MAXIMUM_VALUE + "..."); - llListen(0, "", llGetOwner(), ""); -} - -// reports the winner, but adds "prefix" to the front of our text and -// will say 'so far' if "provisional" flag is true. -call_winner(string prefix, integer provisional) -{ - string disclaimer = ""; // extra text if not final result. - if (provisional) disclaimer = "so far "; - string winner = winner_so_far; - if (!llStringLength(winner)) winner = "no one(!)"; - llSay(0, prefix + "winner " + disclaimer + "is " + winner - + " who picked " + (string)highest_picked + "."); -} - -announce_final_winner() -{ - call_winner("The **final** ", FALSE); -} - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - initialize(); - } - - on_rez(integer param) { llResetScript(); } - - touch_start(integer total_number) - { - integer which_picker; - for (which_picker = 0; which_picker < total_number; which_picker++) { - if (llDetectedKey(which_picker) == llGetOwner()) { - llOwnerSay("as owner you can say\n'#winner' to hear the current winner,\n'#final' to close the drawing and,\n'#reset lottery' to start a new drawing."); - call_winner("the ", TRUE); - return; - } - - if (lottery_finished) { - // just report that this one's finished. - announce_final_winner(); - return; - } - - // if we got to here, this is a normal person (not the owner) who - // might still be allowed to participate in an active drawing. - - // get a random number between 0 and almost up to the max. - float rando = llFrand(MAXIMUM_VALUE); - // convert to int, which makes the range from zero to the max inclusive. - integer int_rando = llRound(rando); - string letter = ""; // default is no extra letter. - // pick the right article for english. - if ( (int_rando == 8) - || (int_rando == 11) - || (int_rando == 18) - || (int_rando / 10 == 8) ) { - // these cases like an "an" instead of an "a". - // e.g., an eleven, an eight, an eighty-three, an eighteen. - letter = "n"; - } - - // make sure this person hasn't already played. - string name = llDetectedName(which_picker); - if (find_in_list(participants, name) >= 0) { - call_winner(name + " already picked a number,\nand the ", TRUE); - return; - } - - // add the new participant to the list. - participants += [ name ]; - // list kludge for better memory usage. - llSay(0, name + " drew a" + letter + " " + (string)int_rando + "."); - if (highest_picked < int_rando) { - llSay(0, name + " has the new highest number!!!"); - highest_picked = int_rando; - winner_so_far = name; - } else if (highest_picked == int_rando) { - call_winner("oh, so close; " + name + " tied with the ", FALSE); - } else { - call_winner("that's not quite enough " + name + ", since\nthe ", TRUE); - } - } - } - - listen(integer channel, string name, key id, string msg) { - if (msg == "#reset lottery") { - llSay(0, "resetting the drawing now..."); - if (winner_so_far != "") - call_winner("forgetting previous ", FALSE); - initialize(); - } else if (msg == "#winner") { - call_winner("the ", TRUE); - } else if (msg == "#final") { - lottery_finished = TRUE; - announce_final_winner(); - } - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.txt new file mode 100755 index 00000000..50c0ef10 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/chaos_picks_a_number_v3.0.txt @@ -0,0 +1,263 @@ + +// huffware script: chaos picks a number, by fred huffhines. +// (was formerly called "raffles asks chaos a question") +// +// produces a random number between 0 and the MAXIMUM_VALUE defined below. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer MAXIMUM_VALUE = 100; + // this is the highest number the generator will produce. + // the range is from zero, a very poor pick, to the number above + // (the best pick), inclusive. + +/////////////// + +// from hufflets... + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// variables used in the script... + +list participants = []; + // the people who have already received a number in this drawing. + +integer highest_picked = 0; + // the highest picked so far. + +string winner_so_far = ""; + // the name of the person who got the highest number to this point. + +integer lottery_finished = FALSE; + // true when the lottery has been completed. + +initialize() +{ + highest_picked = 0; + participants = []; + winner_so_far = ""; + lottery_finished = FALSE; + llSay(0, "ready to draw random numbers from 0 to " + + (string)MAXIMUM_VALUE + "..."); + llListen(0, "", llGetOwner(), ""); +} + +// reports the winner, but adds "prefix" to the front of our text and +// will say 'so far' if "provisional" flag is true. +call_winner(string prefix, integer provisional) +{ + string disclaimer = ""; // extra text if not final result. + if (provisional) disclaimer = "so far "; + string winner = winner_so_far; + if (!llStringLength(winner)) winner = "no one(!)"; + llSay(0, prefix + "winner " + disclaimer + "is " + winner + + " who picked " + (string)highest_picked + "."); +} + +announce_final_winner() +{ + call_winner("The **final** ", FALSE); +} + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + initialize(); + } + + on_rez(integer param) { llResetScript(); } + + touch_start(integer total_number) + { + integer which_picker; + for (which_picker = 0; which_picker < total_number; which_picker++) { + if (llDetectedKey(which_picker) == llGetOwner()) { + llOwnerSay("as owner you can say\n'#winner' to hear the current winner,\n'#final' to close the drawing and,\n'#reset lottery' to start a new drawing."); + call_winner("the ", TRUE); + return; + } + + if (lottery_finished) { + // just report that this one's finished. + announce_final_winner(); + return; + } + + // if we got to here, this is a normal person (not the owner) who + // might still be allowed to participate in an active drawing. + + // get a random number between 0 and almost up to the max. + float rando = llFrand(MAXIMUM_VALUE); + // convert to int, which makes the range from zero to the max inclusive. + integer int_rando = llRound(rando); + string letter = ""; // default is no extra letter. + // pick the right article for english. + if ( (int_rando == 8) + || (int_rando == 11) + || (int_rando == 18) + || (int_rando / 10 == 8) ) { + // these cases like an "an" instead of an "a". + // e.g., an eleven, an eight, an eighty-three, an eighteen. + letter = "n"; + } + + // make sure this person hasn't already played. + string name = llDetectedName(which_picker); + if (find_in_list(participants, name) >= 0) { + call_winner(name + " already picked a number,\nand the ", TRUE); + return; + } + + // add the new participant to the list. + participants += [ name ]; + // list kludge for better memory usage. + llSay(0, name + " drew a" + letter + " " + (string)int_rando + "."); + if (highest_picked < int_rando) { + llSay(0, name + " has the new highest number!!!"); + highest_picked = int_rando; + winner_so_far = name; + } else if (highest_picked == int_rando) { + call_winner("oh, so close; " + name + " tied with the ", FALSE); + } else { + call_winner("that's not quite enough " + name + ", since\nthe ", TRUE); + } + } + } + + listen(integer channel, string name, key id, string msg) { + if (msg == "#reset lottery") { + llSay(0, "resetting the drawing now..."); + if (winner_so_far != "") + call_winner("forgetting previous ", FALSE); + initialize(); + } else if (msg == "#winner") { + call_winner("the ", TRUE); + } else if (msg == "#final") { + lottery_finished = TRUE; + announce_final_winner(); + } + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.lsl deleted file mode 100755 index e513fc12..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.lsl +++ /dev/null @@ -1,150 +0,0 @@ - -// huffware script: collider, by fred huffhines -// -// a simple script that plays sounds in the inventory when a collision occurs. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -float SOUND_VOLUME = 0.3; - // how loudly to play the sounds we find. - -integer TIME_BETWEEN_PLAYS = 3; - // we only make the sound every X seconds. - -integer last_played = 0; - // records the last time we hit the sound. - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - - integer i; - for (i = 0; i < llGetInventoryNumber(INVENTORY_SOUND); i++) - llPreloadSound(llGetInventoryName(INVENTORY_SOUND, i)); - } - - collision_start(integer total_number) { - if (llGetUnixTime() - last_played < TIME_BETWEEN_PLAYS) return; - last_played = llGetUnixTime(); - integer i; - for (i = 0; i < llGetInventoryNumber(INVENTORY_SOUND); i++) { - float vol = SOUND_VOLUME; - if (llGetInventoryName(INVENTORY_SOUND, i) == "water-flowing3") - vol /= 2.0; // not so loud for this one. - llTriggerSound(llGetInventoryName(INVENTORY_SOUND, i), vol); -//llSay(0, "vol is " + (string)vol); - } - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.txt new file mode 100755 index 00000000..e513fc12 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/collider_v1.3.txt @@ -0,0 +1,150 @@ + +// huffware script: collider, by fred huffhines +// +// a simple script that plays sounds in the inventory when a collision occurs. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +float SOUND_VOLUME = 0.3; + // how loudly to play the sounds we find. + +integer TIME_BETWEEN_PLAYS = 3; + // we only make the sound every X seconds. + +integer last_played = 0; + // records the last time we hit the sound. + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + + integer i; + for (i = 0; i < llGetInventoryNumber(INVENTORY_SOUND); i++) + llPreloadSound(llGetInventoryName(INVENTORY_SOUND, i)); + } + + collision_start(integer total_number) { + if (llGetUnixTime() - last_played < TIME_BETWEEN_PLAYS) return; + last_played = llGetUnixTime(); + integer i; + for (i = 0; i < llGetInventoryNumber(INVENTORY_SOUND); i++) { + float vol = SOUND_VOLUME; + if (llGetInventoryName(INVENTORY_SOUND, i) == "water-flowing3") + vol /= 2.0; // not so loud for this one. + llTriggerSound(llGetInventoryName(INVENTORY_SOUND, i), vol); +//llSay(0, "vol is " + (string)vol); + } + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.lsl b/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.lsl deleted file mode 100755 index 202c58f7..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.lsl +++ /dev/null @@ -1,882 +0,0 @@ - -// huffware script: comfortable sitting, by fred huffhines. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// - -// global constants... - -string NOTEWORTHY_SIGNATURE = "#sitting"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -////////////// - -// global variables that are loaded from a notecard. - -vector AVATAR_ROTATION = <0, 0, -90>; // star chair. -//vector AVATAR_ROTATION = <0, 0, 0>; - // the euler vector for rotation of the avatar after sitting, in degrees. - // the rotation vector should be tailored to the object. - -vector AVATAR_POSITION = <-0.1, -0.28, -0.1>; // star chair. -//vector AVATAR_POSITION = <0.34, 0, 0>; - // the position of the sitting offset from the object center. also needs to be - // tailored to the particular object. - -integer GOTO_WHICH_FLOOR = 1; - // when serving as an elevator, this is a way to cause the teleport offset - // to go to a particular floor. the real z position is calculated from - // this times the floor size in meters. note that floors are numbered - // starting at 1 (one). - -float FLOOR_SIZE_IN_METERS = 0.0; - // when the script is used in an elevator, this specifies the height of the - // floors. our current scheme will only work if that is constant between - // the floors. - -float BASE_FLOOR_HEIGHT = 0.0; - // the position of the first floor in meters. this will not affect the - // position calculations unless floor size is non-zero. - -integer UNSEAT_AFTERWARDS = FALSE; - // if this is true, then the avatar is unseated just after sitting down. - -float PAUSE_BEFORE_EVICTION = 0.28; - // the number of seconds that the avatars get to sit before we pop them - // out of the chair/teleporter/whatever. - -vector CAMERA_EYE_OFFSET = <3, 2, 1.5>; // star chair. - // the offset for the camera after the avatar sits down. -//relative to the avatar? - -vector CAMERA_TARGET = <-3, 0, 1>; // star chair. - // the location where the camera is looking at once the avatar sits down. -//relative to the avatar? - -////////////// - -// global variables used in processing notecards... - -integer pending_response_id; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -////////////// - -// interfaces for library scripts we rely on... - -// requires noteworthy library. -// in this odd case, where we are trying to shrink script count, the noteworthy library -// is embedded inside here. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be blank. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was - // found) and as subsequent elements an embedded list that was read from the - // notecard. this necessarily limits the size of the notecards that we can read - // and return. -string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; - // like the read notecard command, but specifies the notecard name to use. only that - // specific notecard file will be consulted. first and second parm are still signature - // and response code, third parm is the notecard name. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// establishes the sitting parameters including camera offsets. -setup_seating_arrangements() -{ - llUnSit(llAvatarOnSitTarget()); // no one gets to ignore a script change. - vector new_rot = AVATAR_ROTATION; - new_rot *= DEG_TO_RAD; // convert to radians. - rotation quat = llEuler2Rot(new_rot); // convert to quaternion. - // get our position set up and take into account the elevator position. - vector position = AVATAR_POSITION; -//rename that variable to be "which floor to go to" - if (FLOOR_SIZE_IN_METERS != 0) { - vector temp = llGetPos(); - integer my_floor = (integer) ((temp.z - BASE_FLOOR_HEIGHT ) / FLOOR_SIZE_IN_METERS) + 1; -//log_it("my floor is " + (string)my_floor); - float add_in = (float)(GOTO_WHICH_FLOOR - my_floor) * FLOOR_SIZE_IN_METERS; -//log_it("decided to add in z: " + (string)add_in); - position += <0, 0, add_in>; - } - // also we make this absolute by taking out the object's own rotation. - // it's hard enough in life for z components to not mean z axis. - position /= llGetRot(); - llSitTarget(position, quat / llGetRot()); -//hmmm: do we need same rot treatment on camera things? -//hmmm: trying it. - // now set the camera position to avoid having random viewpoint. - llSetCameraEyeOffset(CAMERA_EYE_OFFSET / llGetRot()); - llSetCameraAtOffset(CAMERA_TARGET / llGetRot()); -} - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - // try to find a notecard with our configuration. - pending_response_id = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([NOTEWORTHY_SIGNATURE, pending_response_id]); -//call direct into noteworthy. -noteworthy_handle_link_message(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, parms_sent); - -// llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, -// parms_sent); -} - -// processes link messages received from the noteworthy library. -handle_link_message(integer which, integer num, string msg, key id) -{ - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) - return; // not for us. -//log_it("handl: msg=" + msg + " id=" + id); - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); -//log_it("raw is " + llList2String(parms, 1)); - integer response_for = llList2Integer(parms, 1); -//log_it("resp cod=" + pending_response_id + " but this for=" + response_for); -//if (response_for != pending_response_id) log_it("bad response code???"); - if (response_for != pending_response_id) return; // oops, this isn't for us. - if (notecard_name == BAD_NOTECARD_INDICATOR) { - // we hated the notecards we found, or there were none. - log_it("We apologize; there seem to be no notecards with a first line of '" - + NOTEWORTHY_SIGNATURE - + "'. We can't read any configuration until that situation improves."); - } else { -//log_it("got to handle link"); - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - // make sure we shouldn't keep going. - if (notecard_name != NOTECARD_READ_CONTINUATION) { - // a valid notecard has been found. - global_config_index = 0; // we are starting over in the config list. -// log_it("read notecard \"" + notecard_name + "\":"); - // and process the file as a set of definitions. - process_ini_config(); - // now that we have a new set of parameters, use them. - setup_seating_arrangements(); - } - } -} - -/////////////// - -// consumes the notecard in a very application specific way to retrieve our configuration items. -// the example script only looks for two variables: name and description. if those are found in -// the sample card, then they are proudly shown. -parse_variable_definition(string to_parse) -{ - string content; // filled after finding a variable name. - if ( (content = get_variable_value(to_parse, "avatar_rotation")) != "") { - AVATAR_ROTATION = (vector)content; -// log_it("** got avatar_rotation of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "avatar_position")) != "") { - AVATAR_POSITION = (vector)content; -// log_it("** got avatar_position of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "goto_which_floor")) != "") { - GOTO_WHICH_FLOOR = (integer)content; -// log_it("** got GOTO_WHICH_FLOOR of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "floor_size_in_meters")) != "") { - FLOOR_SIZE_IN_METERS = (float)content; -// log_it("** got FLOOR_SIZE_IN_METERS of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "base_floor_height")) != "") { - BASE_FLOOR_HEIGHT = (float)content; -// log_it("** got BASE_FLOOR_HEIGHT of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "unseat_afterwards")) != "") { - UNSEAT_AFTERWARDS = (integer)content; -// log_it("** got unseat_afterwards of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "pause_before_eviction")) != "") { - PAUSE_BEFORE_EVICTION = (float)content; -// log_it("** got pause_before_eviction of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "camera_eye_offset")) != "") { - CAMERA_EYE_OFFSET = (vector)content; -// log_it("** got camera_eye_offset of '" + content + "'"); - } else if ( (content = get_variable_value(to_parse, "camera_target")) != "") { - CAMERA_TARGET = (vector)content; -// log_it("** got camera_target of '" + content + "'"); -// } else { -// log_it("unknown variable seen: " + to_parse); - } -} - -initialize() -{ - // reset our relevant variables. - global_config_list = []; - global_config_index = 0; - - // announce that we're open for business. -/// log_it("started, free mem=" + (string)llGetFreeMemory()); - - // request that the noteworthy library start looking for our notecard. - request_configuration(); - - integer indy = 32; - while (indy >= 0) { - indy = find_in_inventory_partial("noteworthy", INVENTORY_SCRIPT); - if (indy >= 0) { - llRemoveInventory(llGetInventoryName(INVENTORY_SCRIPT, indy)); - } - } - -} - -////////////// -// from hufflets... -// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ strip_spaces(x), strip_spaces(y) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ -// log_it("scanning notecard for variable definitions..."); - integer indy; - integer count = llGetListLength(global_config_list); - string section_name; // set later if we see one. - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - section_name = llGetSubString(line, 1, -2); - log_it("reading section: " + section_name); - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - indy = sec_indy; // track that we've passed this line. - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory_partial(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) - return inv; - } - return -2; // failed to find it. -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 1.9. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// -// example usage of the auto-retirement script: -// -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - if ((float)inv_version_string < (float)version_string) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. - - string basename = to_chop_up; // script name with no version attached. - - integer posn; - // minimum script name is 2 characters plus version. - for (posn = llStringLength(to_chop_up) - 1; - (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); - posn--) { - // find the space. do nothing else. - } - if (posn < 2) return []; // no space found. - string full_suffix = llGetSubString(to_chop_up, posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets -////////////// - -////////////// -// from noteworthy: - -// huffware script: noteworthy library, by fred huffhines. -// -// a handy approach to reading a notecard. this version supports requiring -// a 'signature' in the notecard's first line, so that multiple notecards can -// exist in an object without being misinterpreted. the script is accessed via -// its link message API, so it can be used in an object without all this code -// needing to be embedded in another script. it also supports queuing up requests -// to read notecards, so multiple scripts can use it to read their specific -// notecards without any special handling (besides waiting a bit longer). -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants that can be adapted to your needs... - -integer DEBUGGING = FALSE; - // if this is true, then a lot of extra noise is generated when notecards are read. - -float TIME_OUT_ON_ONE_NOTECARD = 120.0; - // we allow one line of a notecard this long to be read before we decide it's hosed. - // some sims are very very slow, and a time-out of one minute has been found lacking; - // we saw at least one case where the first notecard line to be read took longer than - // 60 seconds. that's why we keep cranking this time-out up... - -// constants that should not be changed... - -// outcomes from handling a line in a notecard. -integer STILL_READING = -8; // the notecard seems good, but isn't finished. -integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. -integer DONE_READING = -10; // the notecard is finished being read. - -integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. - -integer MAXIMUM_LINES_USED = 4; - // we will read this many lines at a time from the appropriate notecard. -// global variables... - -string requested_signature = ""; - // if this is non-empty, then it must be found in the first line of the script. - -integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. - -string global_notecard_name; // the name of the card we're reading now. -key global_query_id = NULL_KEY; // the identifier of our data query. -integer current_response_code = 0; // the code that our client uses for its reading. -list global_query_contents; // the lines we have read from the notecard. - -integer line_number = 0; // which line are we at in notecard? - -integer found_signature_line = FALSE; // did we find our first line in a notecard yet? - -integer trying_notecard_at = -1; // where we are currently looking for a good notecard. - -list pending_signatures; // signatures from queued requests for reading. -list pending_response_codes; // response codes for the queued requests. -list pending_notecard_names; // card names if it's a specific request. - -////////////// - -startup_initialize() -{ - llSetTimerEvent(0.0); - pending_signatures = []; - pending_response_codes = []; - pending_notecard_names = []; - current_response_code = 0; -} - -reset_for_reading(string signature, integer response_code_in) -{ - requested_signature = signature; - current_response_code = response_code_in; - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. - global_query_contents = []; - global_notecard_name = ""; - line_number = 0; - found_signature_line = FALSE; - trying_notecard_at = -1; - global_query_id = NULL_KEY; -} - -// use the existing global notecard setting to start reading. -select_specific_notecard() -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - line_number = 0; // reset line number again. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// picks the notecard at the "index" (from 0 to num_notecards - 1) and -// starts reading it. -select_notecard(integer index) -{ - global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. - string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); - if (card_specified == "") return; // not good. bad index. - global_notecard_name = card_specified; - line_number = 0; // reset line number again. - // we have a new file name, so load up the destinations, hopefully. - global_query_id = llGetNotecardLine(global_notecard_name, 0); -} - -// increments our index in the count of notecards that the object has, and start -// reading the next notecard (at the index). -integer try_next_notecard() -{ - if (only_read_one_notecard) { - return FALSE; // we were only going to try one. - } - // reset some values that might have applied before. - global_notecard_name = ""; - // skip to the next card. - trying_notecard_at++; - // make sure we're not over the count of cards. - if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { - // this is a problem. we didn't find anything suitable. - return FALSE; - } - // so, now we'll try the next notecard to look for our signature. - select_notecard(trying_notecard_at); - return TRUE; -} - -// process a line of text that we received from the current notecard. -integer handle_notecard_line(key query_id, string data) -{ - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - // there's more to read in the notecard still. - if (data != "") { - // make sure we even have a signature to look for. - if (!found_signature_line && (requested_signature == "")) { - // no signature means that we always find it. - found_signature_line = TRUE; - } - // did we already get our signature? if not, see if this is it. - if (!found_signature_line && (data != requested_signature) ) { - // this is a bad notecard. skip it. - if (!try_next_notecard()) { - // we have no more to work with. - return BAD_NOTECARD; - } - return STILL_READING; // we'll keep going. - } else if (!found_signature_line && (data == requested_signature) ) { - // this is a good signature line, so record that and then skip it. - found_signature_line = TRUE; - } else { - if (DEBUGGING - && ( ( (requested_signature == "") && (line_number == 0) ) - || ( (requested_signature != "") && (line_number == 1) ) ) ) { - log_it("started reading " + global_notecard_name + "..."); - } - // don't record any lines that are comments. - if ( (llGetSubString(data, 0, 0) != "#") - && (llGetSubString(data, 0, 0) != ";") ) { - // add the non-blank line to our list. - global_query_contents += data; - // make sure we still have enough space to keep going. - if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { - // ooh, make sure we pause before blowing our heap&stack. - send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, - current_response_code ], READ_NOTECARD_COMMAND, TRUE); - } - } - } - } - line_number++; // increase the line count. - // reset the timer rather than timing out, if we actually got some data. - llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); - // request the next line from the notecard. - global_query_id = llGetNotecardLine(global_notecard_name, line_number); - if (global_query_id == NULL_KEY) { -//log_it("failed to restart notecard reading."); - return DONE_READING; -//is that the best outcome? - } - return STILL_READING; - } else { - // that's the end of the notecard. we need some minimal verification that it - // wasn't full of garbage. - if (!found_signature_line) { - if (DEBUGGING) log_it("never found signature in " + global_notecard_name); - if (!try_next_notecard()) { - return BAD_NOTECARD; // we failed to find a good line? - } else { - // the next notecard's coming through now. - return STILL_READING; - } - } else { -// if (DEBUGGING) log_it("found signature."); - // saw the signature line, so this is a good one. - return DONE_READING; - } - } -} - -// only sends reply; does not reset notecard process. -send_reply(integer destination, list parms, string command, - integer include_query) -{ -//log_it("froyo: curre code=" + current_response_code); -//integer items = llGetListLength(parms); -//if (include_query) items += llGetListLength(global_query_contents); -//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); - - if (!include_query) { - handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); - } else { - handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, - command, - llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); - } - global_query_contents = []; -//log_it("post-sending, mem=" + (string)llGetFreeMemory()); -} - -// a simple version of a reply for a command that has been executed. the parameters -// might contain an outcome or result of the operation that was requested. -send_reply_and_reset(integer destination, list parms, string command, - integer include_query) -{ - llSetTimerEvent(0.0); // stop the timer, since we're about to reply. - send_reply(destination, parms, command, include_query); -//log_it("about to reset response code"); - current_response_code = 0; // reset back to default so we can start another read. - global_query_id = NULL_KEY; // reset so we accept no more data. -} - -// if there are other pending notecard reads, this goes to the next one listed. -dequeue_next_request() -{ - if (llGetListLength(pending_signatures)) { - // get the info from the next pending item. - string sig = llList2String(pending_signatures, 0); - integer response_code_temp = llList2Integer(pending_response_codes, 0); - string notecard = llList2String(pending_notecard_names, 0); - // whack the head of the queue since we grabbed the info. - pending_signatures = llDeleteSubList(pending_signatures, 0, 0); - pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); - pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); - if (llStringLength(notecard)) { - global_notecard_name = notecard; - select_specific_notecard(); - } else { - reset_for_reading(sig, response_code_temp); - } - } -} - -// deals with one data server answer from the notecard. -process_notecard_line(key query_id, string data) -{ - // try to consume a line from the notecard. - integer outcome = handle_notecard_line(query_id, data); - if (outcome == DONE_READING) { - // that was a valid notecard and we read all of it. - if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); - // send back the results. - send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], - READ_NOTECARD_COMMAND, TRUE); - } else if (outcome == BAD_NOTECARD) { - // bail; this problem must be addressed by other means. - if (DEBUGGING) log_it("failed to find an appropriate notecard"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } else if (outcome == STILL_READING) { - // we have a good card and are still processing it. - return; - } else { - if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); - // again, bail out. we have no idea what happened with this. - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - } - // if we have reached here, we should crank up the next queued notecard reading. - dequeue_next_request(); -} - -// processes requests from our users. -noteworthy_handle_link_message(integer which, integer num, string msg, key id) -{ - if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. - - if (msg == READ_NOTECARD_COMMAND) { - only_read_one_notecard = FALSE; // general inquiry for any card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read notecard--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code_temp = llList2Integer(parms, 1); -//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code_temp); - if (!try_next_notecard()) { - if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code_temp ], - READ_NOTECARD_COMMAND, FALSE); - return; - } -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code_temp; -//holding: pending_notecard_names += ""; -//holding: } - } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { - only_read_one_notecard = TRUE; // they want one particular card. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); -//log_it("read specific--parms are: " + (string)parms); - string signature = llList2String(parms, 0); - integer response_code_temp = llList2Integer(parms, 1); - string notecard_name = llList2String(parms, 2); -//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); -//holding: if (!current_response_code) { - // go ahead and process this request; we aren't busy. - reset_for_reading(signature, response_code_temp); - global_notecard_name = notecard_name; // set our global. - select_specific_notecard(); -//holding: } else { -//holding: // we're already busy. -//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], -//holding:// READ_NOTECARD_COMMAND, FALSE); -//holding: // stack this request; another is in progress. -//holding: pending_signatures += signature; -//holding: pending_response_codes += response_code_temp; -//holding: pending_notecard_names += notecard_name; -//holding: } - } -} - - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); // make sure newest addition is only version of script. -/////not needed now llSleep(1.0); // snooze just a bit to let noteworthy start up? - startup_initialize(); - initialize(); // start asking about the notecards. - setup_seating_arrangements(); // use our current defaults for sitting posn. - } - - on_rez(integer parm) { llResetScript(); } - - changed(integer change) { - if (change & CHANGED_INVENTORY) { -// llSleep(3.14159265358); // delay to avoid interfering with upgrade. - llResetScript(); - } - if (!(change & CHANGED_LINK)) return; // don't care. - if (!UNSEAT_AFTERWARDS) return; // nothing else below is needed. - if (llAvatarOnSitTarget() == NULL_KEY) return; // no one there, so ditto. - // now give them a bit of time to rest before dumping them. - llSetTimerEvent(PAUSE_BEFORE_EVICTION); - } - - timer() { - if (current_response_code != 0) { - llSetTimerEvent(0.0); // stop any timer now. - // let the caller know this has failed out. - if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); - send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], - READ_NOTECARD_COMMAND, FALSE); - current_response_code = 0; // we gave up on that one. - dequeue_next_request(); // get next reading started if we have anything to read. - } else { - // perform short range teleport, effectively... - llUnSit(llAvatarOnSitTarget()); // ha, got that guy back up. - llSetTimerEvent(0.0); // reset timer. - } - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } - - dataserver(key query_id, string data) { - // make sure this data is for us. - if (global_query_id != query_id) return; - // yep, seems to be. - process_notecard_line(query_id, data); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.txt b/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.txt new file mode 100755 index 00000000..202c58f7 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/comfortable_sitting_v7.5.txt @@ -0,0 +1,882 @@ + +// huffware script: comfortable sitting, by fred huffhines. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// + +// global constants... + +string NOTEWORTHY_SIGNATURE = "#sitting"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +////////////// + +// global variables that are loaded from a notecard. + +vector AVATAR_ROTATION = <0, 0, -90>; // star chair. +//vector AVATAR_ROTATION = <0, 0, 0>; + // the euler vector for rotation of the avatar after sitting, in degrees. + // the rotation vector should be tailored to the object. + +vector AVATAR_POSITION = <-0.1, -0.28, -0.1>; // star chair. +//vector AVATAR_POSITION = <0.34, 0, 0>; + // the position of the sitting offset from the object center. also needs to be + // tailored to the particular object. + +integer GOTO_WHICH_FLOOR = 1; + // when serving as an elevator, this is a way to cause the teleport offset + // to go to a particular floor. the real z position is calculated from + // this times the floor size in meters. note that floors are numbered + // starting at 1 (one). + +float FLOOR_SIZE_IN_METERS = 0.0; + // when the script is used in an elevator, this specifies the height of the + // floors. our current scheme will only work if that is constant between + // the floors. + +float BASE_FLOOR_HEIGHT = 0.0; + // the position of the first floor in meters. this will not affect the + // position calculations unless floor size is non-zero. + +integer UNSEAT_AFTERWARDS = FALSE; + // if this is true, then the avatar is unseated just after sitting down. + +float PAUSE_BEFORE_EVICTION = 0.28; + // the number of seconds that the avatars get to sit before we pop them + // out of the chair/teleporter/whatever. + +vector CAMERA_EYE_OFFSET = <3, 2, 1.5>; // star chair. + // the offset for the camera after the avatar sits down. +//relative to the avatar? + +vector CAMERA_TARGET = <-3, 0, 1>; // star chair. + // the location where the camera is looking at once the avatar sits down. +//relative to the avatar? + +////////////// + +// global variables used in processing notecards... + +integer pending_response_id; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +////////////// + +// interfaces for library scripts we rely on... + +// requires noteworthy library. +// in this odd case, where we are trying to shrink script count, the noteworthy library +// is embedded inside here. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be blank. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or BAD_NOTECARD_INDICATOR if none was + // found) and as subsequent elements an embedded list that was read from the + // notecard. this necessarily limits the size of the notecards that we can read + // and return. +string READ_SPECIFIC_NOTECARD_COMMAND = "#read_thisun#"; + // like the read notecard command, but specifies the notecard name to use. only that + // specific notecard file will be consulted. first and second parm are still signature + // and response code, third parm is the notecard name. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// establishes the sitting parameters including camera offsets. +setup_seating_arrangements() +{ + llUnSit(llAvatarOnSitTarget()); // no one gets to ignore a script change. + vector new_rot = AVATAR_ROTATION; + new_rot *= DEG_TO_RAD; // convert to radians. + rotation quat = llEuler2Rot(new_rot); // convert to quaternion. + // get our position set up and take into account the elevator position. + vector position = AVATAR_POSITION; +//rename that variable to be "which floor to go to" + if (FLOOR_SIZE_IN_METERS != 0) { + vector temp = llGetPos(); + integer my_floor = (integer) ((temp.z - BASE_FLOOR_HEIGHT ) / FLOOR_SIZE_IN_METERS) + 1; +//log_it("my floor is " + (string)my_floor); + float add_in = (float)(GOTO_WHICH_FLOOR - my_floor) * FLOOR_SIZE_IN_METERS; +//log_it("decided to add in z: " + (string)add_in); + position += <0, 0, add_in>; + } + // also we make this absolute by taking out the object's own rotation. + // it's hard enough in life for z components to not mean z axis. + position /= llGetRot(); + llSitTarget(position, quat / llGetRot()); +//hmmm: do we need same rot treatment on camera things? +//hmmm: trying it. + // now set the camera position to avoid having random viewpoint. + llSetCameraEyeOffset(CAMERA_EYE_OFFSET / llGetRot()); + llSetCameraAtOffset(CAMERA_TARGET / llGetRot()); +} + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + // try to find a notecard with our configuration. + pending_response_id = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([NOTEWORTHY_SIGNATURE, pending_response_id]); +//call direct into noteworthy. +noteworthy_handle_link_message(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, parms_sent); + +// llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, +// parms_sent); +} + +// processes link messages received from the noteworthy library. +handle_link_message(integer which, integer num, string msg, key id) +{ + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) + return; // not for us. +//log_it("handl: msg=" + msg + " id=" + id); + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); +//log_it("raw is " + llList2String(parms, 1)); + integer response_for = llList2Integer(parms, 1); +//log_it("resp cod=" + pending_response_id + " but this for=" + response_for); +//if (response_for != pending_response_id) log_it("bad response code???"); + if (response_for != pending_response_id) return; // oops, this isn't for us. + if (notecard_name == BAD_NOTECARD_INDICATOR) { + // we hated the notecards we found, or there were none. + log_it("We apologize; there seem to be no notecards with a first line of '" + + NOTEWORTHY_SIGNATURE + + "'. We can't read any configuration until that situation improves."); + } else { +//log_it("got to handle link"); + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + // make sure we shouldn't keep going. + if (notecard_name != NOTECARD_READ_CONTINUATION) { + // a valid notecard has been found. + global_config_index = 0; // we are starting over in the config list. +// log_it("read notecard \"" + notecard_name + "\":"); + // and process the file as a set of definitions. + process_ini_config(); + // now that we have a new set of parameters, use them. + setup_seating_arrangements(); + } + } +} + +/////////////// + +// consumes the notecard in a very application specific way to retrieve our configuration items. +// the example script only looks for two variables: name and description. if those are found in +// the sample card, then they are proudly shown. +parse_variable_definition(string to_parse) +{ + string content; // filled after finding a variable name. + if ( (content = get_variable_value(to_parse, "avatar_rotation")) != "") { + AVATAR_ROTATION = (vector)content; +// log_it("** got avatar_rotation of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "avatar_position")) != "") { + AVATAR_POSITION = (vector)content; +// log_it("** got avatar_position of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "goto_which_floor")) != "") { + GOTO_WHICH_FLOOR = (integer)content; +// log_it("** got GOTO_WHICH_FLOOR of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "floor_size_in_meters")) != "") { + FLOOR_SIZE_IN_METERS = (float)content; +// log_it("** got FLOOR_SIZE_IN_METERS of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "base_floor_height")) != "") { + BASE_FLOOR_HEIGHT = (float)content; +// log_it("** got BASE_FLOOR_HEIGHT of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "unseat_afterwards")) != "") { + UNSEAT_AFTERWARDS = (integer)content; +// log_it("** got unseat_afterwards of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "pause_before_eviction")) != "") { + PAUSE_BEFORE_EVICTION = (float)content; +// log_it("** got pause_before_eviction of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "camera_eye_offset")) != "") { + CAMERA_EYE_OFFSET = (vector)content; +// log_it("** got camera_eye_offset of '" + content + "'"); + } else if ( (content = get_variable_value(to_parse, "camera_target")) != "") { + CAMERA_TARGET = (vector)content; +// log_it("** got camera_target of '" + content + "'"); +// } else { +// log_it("unknown variable seen: " + to_parse); + } +} + +initialize() +{ + // reset our relevant variables. + global_config_list = []; + global_config_index = 0; + + // announce that we're open for business. +/// log_it("started, free mem=" + (string)llGetFreeMemory()); + + // request that the noteworthy library start looking for our notecard. + request_configuration(); + + integer indy = 32; + while (indy >= 0) { + indy = find_in_inventory_partial("noteworthy", INVENTORY_SCRIPT); + if (indy >= 0) { + llRemoveInventory(llGetInventoryName(INVENTORY_SCRIPT, indy)); + } + } + +} + +////////////// +// from hufflets... +// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ strip_spaces(x), strip_spaces(y) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ +// log_it("scanning notecard for variable definitions..."); + integer indy; + integer count = llGetListLength(global_config_list); + string section_name; // set later if we see one. + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + section_name = llGetSubString(line, 1, -2); + log_it("reading section: " + section_name); + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + indy = sec_indy; // track that we've passed this line. + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory_partial(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) + return inv; + } + return -2; // failed to find it. +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 1.9. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// +// example usage of the auto-retirement script: +// +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + if ((float)inv_version_string < (float)version_string) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. + + string basename = to_chop_up; // script name with no version attached. + + integer posn; + // minimum script name is 2 characters plus version. + for (posn = llStringLength(to_chop_up) - 1; + (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); + posn--) { + // find the space. do nothing else. + } + if (posn < 2) return []; // no space found. + string full_suffix = llGetSubString(to_chop_up, posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets +////////////// + +////////////// +// from noteworthy: + +// huffware script: noteworthy library, by fred huffhines. +// +// a handy approach to reading a notecard. this version supports requiring +// a 'signature' in the notecard's first line, so that multiple notecards can +// exist in an object without being misinterpreted. the script is accessed via +// its link message API, so it can be used in an object without all this code +// needing to be embedded in another script. it also supports queuing up requests +// to read notecards, so multiple scripts can use it to read their specific +// notecards without any special handling (besides waiting a bit longer). +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants that can be adapted to your needs... + +integer DEBUGGING = FALSE; + // if this is true, then a lot of extra noise is generated when notecards are read. + +float TIME_OUT_ON_ONE_NOTECARD = 120.0; + // we allow one line of a notecard this long to be read before we decide it's hosed. + // some sims are very very slow, and a time-out of one minute has been found lacking; + // we saw at least one case where the first notecard line to be read took longer than + // 60 seconds. that's why we keep cranking this time-out up... + +// constants that should not be changed... + +// outcomes from handling a line in a notecard. +integer STILL_READING = -8; // the notecard seems good, but isn't finished. +integer BAD_NOTECARD = -9; // this notecard doesn't have our signature. +integer DONE_READING = -10; // the notecard is finished being read. + +integer LIST_ELEMENT_GUESS = 200; // guess at how many bytes average list element uses. + +integer MAXIMUM_LINES_USED = 4; + // we will read this many lines at a time from the appropriate notecard. +// global variables... + +string requested_signature = ""; + // if this is non-empty, then it must be found in the first line of the script. + +integer only_read_one_notecard = FALSE; // true if just one specific notecard should be used. + +string global_notecard_name; // the name of the card we're reading now. +key global_query_id = NULL_KEY; // the identifier of our data query. +integer current_response_code = 0; // the code that our client uses for its reading. +list global_query_contents; // the lines we have read from the notecard. + +integer line_number = 0; // which line are we at in notecard? + +integer found_signature_line = FALSE; // did we find our first line in a notecard yet? + +integer trying_notecard_at = -1; // where we are currently looking for a good notecard. + +list pending_signatures; // signatures from queued requests for reading. +list pending_response_codes; // response codes for the queued requests. +list pending_notecard_names; // card names if it's a specific request. + +////////////// + +startup_initialize() +{ + llSetTimerEvent(0.0); + pending_signatures = []; + pending_response_codes = []; + pending_notecard_names = []; + current_response_code = 0; +} + +reset_for_reading(string signature, integer response_code_in) +{ + requested_signature = signature; + current_response_code = response_code_in; + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); // don't allow a read to happen forever. + global_query_contents = []; + global_notecard_name = ""; + line_number = 0; + found_signature_line = FALSE; + trying_notecard_at = -1; + global_query_id = NULL_KEY; +} + +// use the existing global notecard setting to start reading. +select_specific_notecard() +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + line_number = 0; // reset line number again. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// picks the notecard at the "index" (from 0 to num_notecards - 1) and +// starts reading it. +select_notecard(integer index) +{ + global_query_id = NULL_KEY; // reset the query id so we don't get bogus answers. + string card_specified = llGetInventoryName(INVENTORY_NOTECARD, index); + if (card_specified == "") return; // not good. bad index. + global_notecard_name = card_specified; + line_number = 0; // reset line number again. + // we have a new file name, so load up the destinations, hopefully. + global_query_id = llGetNotecardLine(global_notecard_name, 0); +} + +// increments our index in the count of notecards that the object has, and start +// reading the next notecard (at the index). +integer try_next_notecard() +{ + if (only_read_one_notecard) { + return FALSE; // we were only going to try one. + } + // reset some values that might have applied before. + global_notecard_name = ""; + // skip to the next card. + trying_notecard_at++; + // make sure we're not over the count of cards. + if (trying_notecard_at >= llGetInventoryNumber(INVENTORY_NOTECARD)) { + // this is a problem. we didn't find anything suitable. + return FALSE; + } + // so, now we'll try the next notecard to look for our signature. + select_notecard(trying_notecard_at); + return TRUE; +} + +// process a line of text that we received from the current notecard. +integer handle_notecard_line(key query_id, string data) +{ + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + // there's more to read in the notecard still. + if (data != "") { + // make sure we even have a signature to look for. + if (!found_signature_line && (requested_signature == "")) { + // no signature means that we always find it. + found_signature_line = TRUE; + } + // did we already get our signature? if not, see if this is it. + if (!found_signature_line && (data != requested_signature) ) { + // this is a bad notecard. skip it. + if (!try_next_notecard()) { + // we have no more to work with. + return BAD_NOTECARD; + } + return STILL_READING; // we'll keep going. + } else if (!found_signature_line && (data == requested_signature) ) { + // this is a good signature line, so record that and then skip it. + found_signature_line = TRUE; + } else { + if (DEBUGGING + && ( ( (requested_signature == "") && (line_number == 0) ) + || ( (requested_signature != "") && (line_number == 1) ) ) ) { + log_it("started reading " + global_notecard_name + "..."); + } + // don't record any lines that are comments. + if ( (llGetSubString(data, 0, 0) != "#") + && (llGetSubString(data, 0, 0) != ";") ) { + // add the non-blank line to our list. + global_query_contents += data; + // make sure we still have enough space to keep going. + if (llGetListLength(global_query_contents) >= MAXIMUM_LINES_USED) { + // ooh, make sure we pause before blowing our heap&stack. + send_reply(LINK_THIS, [ NOTECARD_READ_CONTINUATION, + current_response_code ], READ_NOTECARD_COMMAND, TRUE); + } + } + } + } + line_number++; // increase the line count. + // reset the timer rather than timing out, if we actually got some data. + llSetTimerEvent(TIME_OUT_ON_ONE_NOTECARD); + // request the next line from the notecard. + global_query_id = llGetNotecardLine(global_notecard_name, line_number); + if (global_query_id == NULL_KEY) { +//log_it("failed to restart notecard reading."); + return DONE_READING; +//is that the best outcome? + } + return STILL_READING; + } else { + // that's the end of the notecard. we need some minimal verification that it + // wasn't full of garbage. + if (!found_signature_line) { + if (DEBUGGING) log_it("never found signature in " + global_notecard_name); + if (!try_next_notecard()) { + return BAD_NOTECARD; // we failed to find a good line? + } else { + // the next notecard's coming through now. + return STILL_READING; + } + } else { +// if (DEBUGGING) log_it("found signature."); + // saw the signature line, so this is a good one. + return DONE_READING; + } + } +} + +// only sends reply; does not reset notecard process. +send_reply(integer destination, list parms, string command, + integer include_query) +{ +//log_it("froyo: curre code=" + current_response_code); +//integer items = llGetListLength(parms); +//if (include_query) items += llGetListLength(global_query_contents); +//log_it("pre-sending " + (string)items + " items, mem=" + (string)llGetFreeMemory()); + + if (!include_query) { + handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, llDumpList2String(parms, HUFFWARE_PARM_SEPARATOR)); + } else { + handle_link_message(destination, NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE, + command, + llDumpList2String(parms + global_query_contents, HUFFWARE_PARM_SEPARATOR)); + } + global_query_contents = []; +//log_it("post-sending, mem=" + (string)llGetFreeMemory()); +} + +// a simple version of a reply for a command that has been executed. the parameters +// might contain an outcome or result of the operation that was requested. +send_reply_and_reset(integer destination, list parms, string command, + integer include_query) +{ + llSetTimerEvent(0.0); // stop the timer, since we're about to reply. + send_reply(destination, parms, command, include_query); +//log_it("about to reset response code"); + current_response_code = 0; // reset back to default so we can start another read. + global_query_id = NULL_KEY; // reset so we accept no more data. +} + +// if there are other pending notecard reads, this goes to the next one listed. +dequeue_next_request() +{ + if (llGetListLength(pending_signatures)) { + // get the info from the next pending item. + string sig = llList2String(pending_signatures, 0); + integer response_code_temp = llList2Integer(pending_response_codes, 0); + string notecard = llList2String(pending_notecard_names, 0); + // whack the head of the queue since we grabbed the info. + pending_signatures = llDeleteSubList(pending_signatures, 0, 0); + pending_response_codes = llDeleteSubList(pending_response_codes, 0, 0); + pending_notecard_names = llDeleteSubList(pending_notecard_names, 0, 0); + if (llStringLength(notecard)) { + global_notecard_name = notecard; + select_specific_notecard(); + } else { + reset_for_reading(sig, response_code_temp); + } + } +} + +// deals with one data server answer from the notecard. +process_notecard_line(key query_id, string data) +{ + // try to consume a line from the notecard. + integer outcome = handle_notecard_line(query_id, data); + if (outcome == DONE_READING) { + // that was a valid notecard and we read all of it. + if (DEBUGGING) log_it("finished reading " + global_notecard_name + "."); + // send back the results. + send_reply_and_reset(LINK_THIS, [ global_notecard_name, current_response_code ], + READ_NOTECARD_COMMAND, TRUE); + } else if (outcome == BAD_NOTECARD) { + // bail; this problem must be addressed by other means. + if (DEBUGGING) log_it("failed to find an appropriate notecard"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } else if (outcome == STILL_READING) { + // we have a good card and are still processing it. + return; + } else { + if (DEBUGGING) log_it("unknown outcome from handle_notecard_line"); + // again, bail out. we have no idea what happened with this. + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + } + // if we have reached here, we should crank up the next queued notecard reading. + dequeue_next_request(); +} + +// processes requests from our users. +noteworthy_handle_link_message(integer which, integer num, string msg, key id) +{ + if (num != NOTEWORTHY_HUFFWARE_ID) return; // not for us. + + if (msg == READ_NOTECARD_COMMAND) { + only_read_one_notecard = FALSE; // general inquiry for any card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read notecard--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code_temp = llList2Integer(parms, 1); +//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code_temp); + if (!try_next_notecard()) { + if (DEBUGGING) log_it("failed to find any appropriate notecards at all."); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, response_code_temp ], + READ_NOTECARD_COMMAND, FALSE); + return; + } +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code_temp; +//holding: pending_notecard_names += ""; +//holding: } + } else if (msg == READ_SPECIFIC_NOTECARD_COMMAND) { + only_read_one_notecard = TRUE; // they want one particular card. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); +//log_it("read specific--parms are: " + (string)parms); + string signature = llList2String(parms, 0); + integer response_code_temp = llList2Integer(parms, 1); + string notecard_name = llList2String(parms, 2); +//log_it("got signature " + signature + " and respcode " + (string)response_code_temp); +//holding: if (!current_response_code) { + // go ahead and process this request; we aren't busy. + reset_for_reading(signature, response_code_temp); + global_notecard_name = notecard_name; // set our global. + select_specific_notecard(); +//holding: } else { +//holding: // we're already busy. +//holding:// send_reply_and_reset(LINK_THIS, [ BUSY_READING_INDICATOR, response_code_temp ], +//holding:// READ_NOTECARD_COMMAND, FALSE); +//holding: // stack this request; another is in progress. +//holding: pending_signatures += signature; +//holding: pending_response_codes += response_code_temp; +//holding: pending_notecard_names += notecard_name; +//holding: } + } +} + + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); // make sure newest addition is only version of script. +/////not needed now llSleep(1.0); // snooze just a bit to let noteworthy start up? + startup_initialize(); + initialize(); // start asking about the notecards. + setup_seating_arrangements(); // use our current defaults for sitting posn. + } + + on_rez(integer parm) { llResetScript(); } + + changed(integer change) { + if (change & CHANGED_INVENTORY) { +// llSleep(3.14159265358); // delay to avoid interfering with upgrade. + llResetScript(); + } + if (!(change & CHANGED_LINK)) return; // don't care. + if (!UNSEAT_AFTERWARDS) return; // nothing else below is needed. + if (llAvatarOnSitTarget() == NULL_KEY) return; // no one there, so ditto. + // now give them a bit of time to rest before dumping them. + llSetTimerEvent(PAUSE_BEFORE_EVICTION); + } + + timer() { + if (current_response_code != 0) { + llSetTimerEvent(0.0); // stop any timer now. + // let the caller know this has failed out. + if (DEBUGGING) log_it("time out processing '" + requested_signature + "'"); + send_reply_and_reset(LINK_THIS, [ BAD_NOTECARD_INDICATOR, current_response_code ], + READ_NOTECARD_COMMAND, FALSE); + current_response_code = 0; // we gave up on that one. + dequeue_next_request(); // get next reading started if we have anything to read. + } else { + // perform short range teleport, effectively... + llUnSit(llAvatarOnSitTarget()); // ha, got that guy back up. + llSetTimerEvent(0.0); // reset timer. + } + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } + + dataserver(key query_id, string data) { + // make sure this data is for us. + if (global_query_id != query_id) return; + // yep, seems to be. + process_notecard_line(query_id, data); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.lsl deleted file mode 100755 index b0d5a44a..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.lsl +++ /dev/null @@ -1,34 +0,0 @@ - - -// huffware script: die on demand, by fred huffhines. -// -// a super simple script that merely makes an object subject to self-termination -// if it is told a secret phrase. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// API for the die on demand feature. saying the message below on the channel -// referenced will cause any listening object to zap itself out of the grid. -string DIE_ON_DEMAND_MESSAGE = "die-on-demand"; -integer DIE_ON_DEMAND_CHANNEL = 4826; -////////////// - -default -{ - state_entry() - { - llListen(DIE_ON_DEMAND_CHANNEL, "", NULL_KEY, "die-on-demand"); - } - - listen(integer channel, string name, key id, string message) { - if ( (channel == DIE_ON_DEMAND_CHANNEL) - && (llGetOwnerKey(id) == llGetOwnerKey(llGetKey())) - && (message == DIE_ON_DEMAND_MESSAGE) ) { - llWhisper(0, "removing object."); - llDie(); - } - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.txt new file mode 100755 index 00000000..b0d5a44a --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/die_on_demand_v0.3.txt @@ -0,0 +1,34 @@ + + +// huffware script: die on demand, by fred huffhines. +// +// a super simple script that merely makes an object subject to self-termination +// if it is told a secret phrase. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// API for the die on demand feature. saying the message below on the channel +// referenced will cause any listening object to zap itself out of the grid. +string DIE_ON_DEMAND_MESSAGE = "die-on-demand"; +integer DIE_ON_DEMAND_CHANNEL = 4826; +////////////// + +default +{ + state_entry() + { + llListen(DIE_ON_DEMAND_CHANNEL, "", NULL_KEY, "die-on-demand"); + } + + listen(integer channel, string name, key id, string message) { + if ( (channel == DIE_ON_DEMAND_CHANNEL) + && (llGetOwnerKey(id) == llGetOwnerKey(llGetKey())) + && (message == DIE_ON_DEMAND_MESSAGE) ) { + llWhisper(0, "removing object."); + llDie(); + } + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.lsl deleted file mode 100755 index 16d198a2..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.lsl +++ /dev/null @@ -1,381 +0,0 @@ - -// huffware script: email notecards, by fred huffhines. -// -// this script allows us to export notecards out of the grids. it reads every notecard -// that's dropped into the object, and then emails it to the specified recipient. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. - - -//hmmm: need a command to clean up the inventory... -// among things that are not notecards, we need a way to clean up all inventory -// except the huffotronic updater and this script itself. - - -// configure these for your own purposes: - -// the list of emails that should receive the notecard content. -list EMAIL_LIST_FOR_NOTECARDS = [ - "fred@spork.com" -]; - -// global constants... - -integer DEBUGGING = FALSE; // if true, will make the run a lot noisier. - -float TIMER_PERIOD = 2.0; // period for the timer to check on any pending notecards. - -// we'll keep our emails at or under this length. -integer MAXIMUM_STRING_BUFFER = 3200; - // older versions of opensim have email limit of 1024 for sum of subject and body length. - // the documented behavior for lsl email is a max of 4096 for sum of subject and body length. - -vector TEXT_COLOR = <0.9, 0.7, 0.5>; // the color the object's text will be painted with. - -// global variables.... - -key current_query_id = NULL_KEY; // the query ID for the current notecard. - -integer line_number; // which line are we at in notecard? - -string current_notecard_name; // we are reading a notecard named this, possibly. - -list pending_notecards; // notecards that are going to be read eventually. - -integer processing_a_notecard = FALSE; // are we currently reading and emailing a notecard? - -integer need_to_scan_notecards = FALSE; // should the list of notecards be re-scanned? - -///// -//hmmm: add to hufflets... - -// basic email sending, with some extra info passed along. -send_email(string recipient, string subject, string content) -{ - if (DEBUGGING) log_it("before sending an email: " + subject); - llEmail(recipient, subject + " [via " + llKey2Name(llGetOwner()) + "]", content); - if (DEBUGGING) log_it("after sending an email: " + subject); -} - -list __email_buffer; // contents to send in email should pile up here. - -// sends out all the email that's pending in the __email_buffer variable. -send_buffered_email(string subject) -{ - string temp_buffer; // used to build up the email. - integer chunk_number = 1; // tracks which part of the message this is. - integer i; - for (i = 0; i < llGetListLength(EMAIL_LIST_FOR_NOTECARDS); i++) { - string recip = llList2String(EMAIL_LIST_FOR_NOTECARDS, i); - temp_buffer = ""; - integer j; - for (j = 0; j < llGetListLength(__email_buffer); j++) { - string line = llList2String(__email_buffer, j); - if (llStringLength(temp_buffer) + llStringLength(line) >= MAXIMUM_STRING_BUFFER) { - // we're over our limit per email. send out what we have and - // then freshen our buffer. - if (DEBUGGING) - log_it("part " + chunk_number + " is " + llStringLength(temp_buffer) + " bytes."); - send_email(recip, subject + " (part " + chunk_number + ")", temp_buffer); - temp_buffer = ""; - chunk_number++; - } - temp_buffer += llList2String(__email_buffer, j); - } - if (llStringLength(temp_buffer) > 0) { - // send the last piece of the email out. - if (DEBUGGING) - log_it("part " + chunk_number + " is " + llStringLength(temp_buffer) + " bytes."); - send_email(recip, subject + " (part " + chunk_number + ")", temp_buffer); - } - } - __email_buffer = []; // clear the buffer now that the email is flying out. -} -////// add to hufflets end. -//// - - -// reset any important variables and set up our assets and timers anat. -initialize() -{ - current_query_id = NULL_KEY; - __email_buffer = []; - line_number = 0; - - llAllowInventoryDrop(TRUE); // allow people to drop things into us. - - // slap a title on the object. - string recip_list; - integer i; - for (i = 0; i < llGetListLength(EMAIL_LIST_FOR_NOTECARDS); i++) { - recip_list += "\n" + llList2String(EMAIL_LIST_FOR_NOTECARDS, i); - } - llSetText("Drop notecards into me\nto email them to:" + recip_list, TEXT_COLOR, 1.0); - - // set the timer to processing notecards that are pending. - reset_timer(TIMER_PERIOD); -} - -//hmmm: add to hufflets? -// safely reschedules the timer for a duration specified. -// this gets around a gnarly SL bug where the timer stops working if not stopped first. -reset_timer(float period) -{ - llSetTimerEvent(0.0); - llSetTimerEvent(period); -} - -// starts reading the current notecard name, which should have been set elsewhere. -consume_notecard() -{ - if (current_notecard_name == "") { - log_it("somehow we do not have a notecard to read in consume_notecard."); - return; - } - line_number = 0; - __email_buffer = []; - current_query_id = llGetNotecardLine(current_notecard_name, 0); -} - -// when the timer goes off, this checks our ongoing processes and kicks them -// down the road a bit if they need it. -handle_timer_pong() -{ - if (processing_a_notecard) return; // already busy. - if (need_to_scan_notecards) { - queue_up_any_new_notecards(); - need_to_scan_notecards = FALSE; - } - - if (llGetListLength(pending_notecards) < 1) return; // nothing to do. - processing_a_notecard = TRUE; - current_notecard_name = llList2String(pending_notecards, 0); - if (DEBUGGING) log_it("scheduling notecard: " + current_notecard_name); - consume_notecard(); -} - -// processes the data chunks coming in from our notecard reading. -handle_data_arriving(key query_id, string data) -{ - if (query_id != current_query_id) { - if (DEBUGGING) log_it("not our query id somehow?"); - return; - } - // if we're not at the end of the notecard we're reading... - if (data != EOF) { - if (!line_number) { - if (DEBUGGING) log_it("starting to read notecard " + current_notecard_name + "..."); - } - // add the line to our destination list. - if (is_prefix(data, "From")) data = "#" + data; // voodoo. - __email_buffer += [ data + "\n" ]; - if (DEBUGGING) log_it("line " + (string)line_number + ": data=" + data); - line_number++; // increase the line count. - // request the next line from the notecard. - current_query_id = llGetNotecardLine(current_notecard_name, line_number); - } else { - // no more data, so we're done with this card. - current_query_id = NULL_KEY; - // blast out the notecard's content in an email. - llSay(0, "Sending \"" + current_notecard_name + "\" with " + line_number + " lines.\n"); - send_buffered_email(current_notecard_name); - // chop that name out of our current pending cards too. - integer where = llListFindList(pending_notecards, [current_notecard_name]); -//log_it("found the notecard to remove at index " + where); - if (where >= 0) { - pending_notecards = llDeleteSubList(pending_notecards, where, where); - } - // done with it, so eat the current note card. - llRemoveInventory(current_notecard_name); - llSay(0, "Done with notecard \"" + current_notecard_name + "\"; now removing it."); - // reset our flag to signal that we're ready to eat another notecard. - processing_a_notecard = FALSE; - current_notecard_name = ""; - // make sure we have all current notecards queued. - need_to_scan_notecards = TRUE; - // push timer out. - reset_timer(TIMER_PERIOD); - } -} - -// look through our inventory and if there are any notecards we don't know about, -// add them to the list for processing. -queue_up_any_new_notecards() -{ - integer i; - for (i = 0; i < llGetInventoryNumber(INVENTORY_NOTECARD); i++) { - string note_name = llGetInventoryName(INVENTORY_NOTECARD, i); - // don't add the notecard if the name is already listed. - integer where = llListFindList(pending_notecards, [ note_name ]); - if (where >= 0) { -// if (DEBUGGING) log_it("notecard already present; skipping: " + note_name); - } else { - // schedule notecard reading by adding to queue. - pending_notecards += [ note_name ]; -// if (DEBUGGING) log_it("notecard added to pending: " + note_name); - } - } -} - -////////////// - -// borrowed from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -////////////// - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end from hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - initialize(); - } - - changed(integer mask) { - if (mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY)) { - need_to_scan_notecards = TRUE; - pending_notecards = []; // reset the list so we re-add all and drop any dead ones. - reset_timer(TIMER_PERIOD); - } - } - - timer() { handle_timer_pong(); } - - dataserver(key query_id, string data) { handle_data_arriving(query_id, data); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.txt new file mode 100755 index 00000000..16d198a2 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/email_notecards_v6.0.txt @@ -0,0 +1,381 @@ + +// huffware script: email notecards, by fred huffhines. +// +// this script allows us to export notecards out of the grids. it reads every notecard +// that's dropped into the object, and then emails it to the specified recipient. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. + + +//hmmm: need a command to clean up the inventory... +// among things that are not notecards, we need a way to clean up all inventory +// except the huffotronic updater and this script itself. + + +// configure these for your own purposes: + +// the list of emails that should receive the notecard content. +list EMAIL_LIST_FOR_NOTECARDS = [ + "fred@spork.com" +]; + +// global constants... + +integer DEBUGGING = FALSE; // if true, will make the run a lot noisier. + +float TIMER_PERIOD = 2.0; // period for the timer to check on any pending notecards. + +// we'll keep our emails at or under this length. +integer MAXIMUM_STRING_BUFFER = 3200; + // older versions of opensim have email limit of 1024 for sum of subject and body length. + // the documented behavior for lsl email is a max of 4096 for sum of subject and body length. + +vector TEXT_COLOR = <0.9, 0.7, 0.5>; // the color the object's text will be painted with. + +// global variables.... + +key current_query_id = NULL_KEY; // the query ID for the current notecard. + +integer line_number; // which line are we at in notecard? + +string current_notecard_name; // we are reading a notecard named this, possibly. + +list pending_notecards; // notecards that are going to be read eventually. + +integer processing_a_notecard = FALSE; // are we currently reading and emailing a notecard? + +integer need_to_scan_notecards = FALSE; // should the list of notecards be re-scanned? + +///// +//hmmm: add to hufflets... + +// basic email sending, with some extra info passed along. +send_email(string recipient, string subject, string content) +{ + if (DEBUGGING) log_it("before sending an email: " + subject); + llEmail(recipient, subject + " [via " + llKey2Name(llGetOwner()) + "]", content); + if (DEBUGGING) log_it("after sending an email: " + subject); +} + +list __email_buffer; // contents to send in email should pile up here. + +// sends out all the email that's pending in the __email_buffer variable. +send_buffered_email(string subject) +{ + string temp_buffer; // used to build up the email. + integer chunk_number = 1; // tracks which part of the message this is. + integer i; + for (i = 0; i < llGetListLength(EMAIL_LIST_FOR_NOTECARDS); i++) { + string recip = llList2String(EMAIL_LIST_FOR_NOTECARDS, i); + temp_buffer = ""; + integer j; + for (j = 0; j < llGetListLength(__email_buffer); j++) { + string line = llList2String(__email_buffer, j); + if (llStringLength(temp_buffer) + llStringLength(line) >= MAXIMUM_STRING_BUFFER) { + // we're over our limit per email. send out what we have and + // then freshen our buffer. + if (DEBUGGING) + log_it("part " + chunk_number + " is " + llStringLength(temp_buffer) + " bytes."); + send_email(recip, subject + " (part " + chunk_number + ")", temp_buffer); + temp_buffer = ""; + chunk_number++; + } + temp_buffer += llList2String(__email_buffer, j); + } + if (llStringLength(temp_buffer) > 0) { + // send the last piece of the email out. + if (DEBUGGING) + log_it("part " + chunk_number + " is " + llStringLength(temp_buffer) + " bytes."); + send_email(recip, subject + " (part " + chunk_number + ")", temp_buffer); + } + } + __email_buffer = []; // clear the buffer now that the email is flying out. +} +////// add to hufflets end. +//// + + +// reset any important variables and set up our assets and timers anat. +initialize() +{ + current_query_id = NULL_KEY; + __email_buffer = []; + line_number = 0; + + llAllowInventoryDrop(TRUE); // allow people to drop things into us. + + // slap a title on the object. + string recip_list; + integer i; + for (i = 0; i < llGetListLength(EMAIL_LIST_FOR_NOTECARDS); i++) { + recip_list += "\n" + llList2String(EMAIL_LIST_FOR_NOTECARDS, i); + } + llSetText("Drop notecards into me\nto email them to:" + recip_list, TEXT_COLOR, 1.0); + + // set the timer to processing notecards that are pending. + reset_timer(TIMER_PERIOD); +} + +//hmmm: add to hufflets? +// safely reschedules the timer for a duration specified. +// this gets around a gnarly SL bug where the timer stops working if not stopped first. +reset_timer(float period) +{ + llSetTimerEvent(0.0); + llSetTimerEvent(period); +} + +// starts reading the current notecard name, which should have been set elsewhere. +consume_notecard() +{ + if (current_notecard_name == "") { + log_it("somehow we do not have a notecard to read in consume_notecard."); + return; + } + line_number = 0; + __email_buffer = []; + current_query_id = llGetNotecardLine(current_notecard_name, 0); +} + +// when the timer goes off, this checks our ongoing processes and kicks them +// down the road a bit if they need it. +handle_timer_pong() +{ + if (processing_a_notecard) return; // already busy. + if (need_to_scan_notecards) { + queue_up_any_new_notecards(); + need_to_scan_notecards = FALSE; + } + + if (llGetListLength(pending_notecards) < 1) return; // nothing to do. + processing_a_notecard = TRUE; + current_notecard_name = llList2String(pending_notecards, 0); + if (DEBUGGING) log_it("scheduling notecard: " + current_notecard_name); + consume_notecard(); +} + +// processes the data chunks coming in from our notecard reading. +handle_data_arriving(key query_id, string data) +{ + if (query_id != current_query_id) { + if (DEBUGGING) log_it("not our query id somehow?"); + return; + } + // if we're not at the end of the notecard we're reading... + if (data != EOF) { + if (!line_number) { + if (DEBUGGING) log_it("starting to read notecard " + current_notecard_name + "..."); + } + // add the line to our destination list. + if (is_prefix(data, "From")) data = "#" + data; // voodoo. + __email_buffer += [ data + "\n" ]; + if (DEBUGGING) log_it("line " + (string)line_number + ": data=" + data); + line_number++; // increase the line count. + // request the next line from the notecard. + current_query_id = llGetNotecardLine(current_notecard_name, line_number); + } else { + // no more data, so we're done with this card. + current_query_id = NULL_KEY; + // blast out the notecard's content in an email. + llSay(0, "Sending \"" + current_notecard_name + "\" with " + line_number + " lines.\n"); + send_buffered_email(current_notecard_name); + // chop that name out of our current pending cards too. + integer where = llListFindList(pending_notecards, [current_notecard_name]); +//log_it("found the notecard to remove at index " + where); + if (where >= 0) { + pending_notecards = llDeleteSubList(pending_notecards, where, where); + } + // done with it, so eat the current note card. + llRemoveInventory(current_notecard_name); + llSay(0, "Done with notecard \"" + current_notecard_name + "\"; now removing it."); + // reset our flag to signal that we're ready to eat another notecard. + processing_a_notecard = FALSE; + current_notecard_name = ""; + // make sure we have all current notecards queued. + need_to_scan_notecards = TRUE; + // push timer out. + reset_timer(TIMER_PERIOD); + } +} + +// look through our inventory and if there are any notecards we don't know about, +// add them to the list for processing. +queue_up_any_new_notecards() +{ + integer i; + for (i = 0; i < llGetInventoryNumber(INVENTORY_NOTECARD); i++) { + string note_name = llGetInventoryName(INVENTORY_NOTECARD, i); + // don't add the notecard if the name is already listed. + integer where = llListFindList(pending_notecards, [ note_name ]); + if (where >= 0) { +// if (DEBUGGING) log_it("notecard already present; skipping: " + note_name); + } else { + // schedule notecard reading by adding to queue. + pending_notecards += [ note_name ]; +// if (DEBUGGING) log_it("notecard added to pending: " + note_name); + } + } +} + +////////////// + +// borrowed from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +////////////// + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end from hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + initialize(); + } + + changed(integer mask) { + if (mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY)) { + need_to_scan_notecards = TRUE; + pending_notecards = []; // reset the list so we re-add all and drop any dead ones. + reset_timer(TIMER_PERIOD); + } + } + + timer() { handle_timer_pong(); } + + dataserver(key query_id, string data) { handle_data_arriving(query_id, data); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.lsl b/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.lsl deleted file mode 100755 index 163bc382..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.lsl +++ /dev/null @@ -1,38 +0,0 @@ - -// huffware script: hamster sound effects, by fred huffhines -// -// a randomizing sound player, originally used to replace a sound -// playing script with bad perms in a freebie hamster. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -list all_sounds; - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() { - llStopSound(); - integer indy; - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SOUND); indy++) { - all_sounds += [ llGetInventoryName(INVENTORY_SOUND, indy) ]; - } - } - - touch_start(integer cnt) { - all_sounds = llListRandomize(all_sounds, 1); - llTriggerSound(llList2String(all_sounds, 0), 1.0); - } - - changed(integer change) { - if (change & CHANGED_INVENTORY) llResetScript(); // reset when sounds might have changed. - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.txt b/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.txt new file mode 100755 index 00000000..163bc382 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/hamster_sound_effects_v0.8.txt @@ -0,0 +1,38 @@ + +// huffware script: hamster sound effects, by fred huffhines +// +// a randomizing sound player, originally used to replace a sound +// playing script with bad perms in a freebie hamster. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +list all_sounds; + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() { + llStopSound(); + integer indy; + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SOUND); indy++) { + all_sounds += [ llGetInventoryName(INVENTORY_SOUND, indy) ]; + } + } + + touch_start(integer cnt) { + all_sounds = llListRandomize(all_sounds, 1); + llTriggerSound(llList2String(all_sounds, 0), 1.0); + } + + changed(integer change) { + if (change & CHANGED_INVENTORY) llResetScript(); // reset when sounds might have changed. + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.lsl b/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.lsl deleted file mode 100755 index 1edb2fd6..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.lsl +++ /dev/null @@ -1,131 +0,0 @@ - -// huffware script: html onna prim, by fred huffhines. -// -// sets the land's media to a web site. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer initted = FALSE; - -////////////// -// huffware script: auto-retire, by fred huffhines, version 1.9. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// -// example usage of the auto-retirement script: -// -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - if ((float)inv_version_string < (float)version_string) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. - - string basename = to_chop_up; // script name with no version attached. - - integer posn; - // minimum script name is 2 characters plus version. - for (posn = llStringLength(to_chop_up) - 1; - (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); - posn--) { - // find the space. do nothing else. - } - if (posn < 2) return []; // no space found. - string full_suffix = llGetSubString(to_chop_up, posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - - } - - on_rez(integer parm) { - llResetScript(); - } - - touch_start(integer count) { - if ( llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]) == [] ) { - llSay(0, "Lacking permission to set/query parcel media. This object has to be owned by/deeded to the land owner."); - return; - } - if (!initted) { - string texture_name = llGetInventoryName(INVENTORY_TEXTURE, 0); - // sets the media texture to the first texture found in our inventory. - llParcelMediaCommandList( [ - PARCEL_MEDIA_COMMAND_URL, "http://gruntose.com", - PARCEL_MEDIA_COMMAND_TYPE, "text/html", - PARCEL_MEDIA_COMMAND_TEXTURE, llGetInventoryKey(texture_name), - PARCEL_MEDIA_COMMAND_PLAY ] ); - llSetTexture(texture_name, ALL_SIDES); - initted = TRUE; - } - - // zap it again. - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); - llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PLAY]); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.txt b/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.txt new file mode 100755 index 00000000..1edb2fd6 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/html_onna_prim_v1.6.txt @@ -0,0 +1,131 @@ + +// huffware script: html onna prim, by fred huffhines. +// +// sets the land's media to a web site. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer initted = FALSE; + +////////////// +// huffware script: auto-retire, by fred huffhines, version 1.9. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// +// example usage of the auto-retirement script: +// +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + if ((float)inv_version_string < (float)version_string) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. + + string basename = to_chop_up; // script name with no version attached. + + integer posn; + // minimum script name is 2 characters plus version. + for (posn = llStringLength(to_chop_up) - 1; + (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); + posn--) { + // find the space. do nothing else. + } + if (posn < 2) return []; // no space found. + string full_suffix = llGetSubString(to_chop_up, posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + + } + + on_rez(integer parm) { + llResetScript(); + } + + touch_start(integer count) { + if ( llParcelMediaQuery([PARCEL_MEDIA_COMMAND_TEXTURE]) == [] ) { + llSay(0, "Lacking permission to set/query parcel media. This object has to be owned by/deeded to the land owner."); + return; + } + if (!initted) { + string texture_name = llGetInventoryName(INVENTORY_TEXTURE, 0); + // sets the media texture to the first texture found in our inventory. + llParcelMediaCommandList( [ + PARCEL_MEDIA_COMMAND_URL, "http://gruntose.com", + PARCEL_MEDIA_COMMAND_TYPE, "text/html", + PARCEL_MEDIA_COMMAND_TEXTURE, llGetInventoryKey(texture_name), + PARCEL_MEDIA_COMMAND_PLAY ] ); + llSetTexture(texture_name, ALL_SIDES); + initted = TRUE; + } + + // zap it again. + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]); + llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PLAY]); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.lsl b/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.lsl deleted file mode 100755 index 4a458bb5..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.lsl +++ /dev/null @@ -1,826 +0,0 @@ - -// huffware script: huff-update client, by fred huffhines. -// -// this script is the client side of the update process. it should reside in an object that -// has scripts which should be automatically updated. it will listen for announcements by -// an update server and communicate with the server to ensure that all of its scripts are -// the most up to date available with the server. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -integer DEBUGGING = FALSE; // if TRUE, the script will output status information. - -integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. - -integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. - -integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. -integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. - -string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. -string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. -string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. -string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. -string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. -string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. -string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. -string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. -string DONE_UPDATING = "#finito#"; // the client is done updating. -string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. - -float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. - -integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. - -///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. - -string UPDATER_PARM_SEPARATOR = "~~~"; - // three tildes is an uncommon thing to have otherwise, so we use it to separate - // our commands in linked messages. - -string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. -string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. - -integer MAXIMUM_SERVERS_TRACKED = 32; - // we will listen to this many servers before we decide to remove one. - -string CONTINUANCE_MARKER = "..."; - // a string sent when the update list is too long and needs to be continued in another chat. - -string SERVER_SCRIPT = "a huffotronic update server"; - // the prefix of our server script that hands out updates. - -// global variables... - -integer inventory_request_channel; // used for newer version servers to cut down cross chatter. -list updaters_heard; // the update servers we've heard from recently. -list last_interactions; // times of the last update process engaged with the updater. -integer update_channel; // current channel for interaction with specific server. -key current_server; // the updater that is active right now, if any. -integer update_start_time; // when the last update process began. -list updates_needed; // stores the set of scripts that are in need of an update. -list known_script_dependencies; // stores the list of dependency info. - -careful_crankup() -{ - knock_around_other_scripts(TRUE); - // clean out the older items and scripts. we do this after getting everyone running - // since we might be whacking ourselves. - destroy_older_versions(); -} - -// reset our variables. -initialize() -{ - updaters_heard = []; - last_interactions = []; - inventory_request_channel = 0; - update_channel = 0; - current_server = NULL_KEY; - llSetTimerEvent(0.0); - llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); - // a new enhancements; tells the server that this guy has finished an update cycle. this - // only comes into play when the updater script itself has just been updated, but it's - // nice for the server to avoid claiming erroneous timeouts occurred. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); - llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. - llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); -} - -whack_updater_record(key id) -{ - integer prev_indy = find_in_list(updaters_heard, id); - if (prev_indy < 0) return; // not there. - updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) - + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); - last_interactions = chop_list(last_interactions, 0, prev_indy - 1) - + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); -} - -// note that this new, lower memory version, depends on the inventory functions returning -// items in alphabetical order. -scrub_items_by_type(string this_guy, integer inventory_type) -{ - list removal_list; - integer outer; - for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { - string curr = llGetInventoryName(inventory_type, outer); - list split = compute_basename_and_version(curr); - // make sure there was a comparable version number in this name. - if ( (curr != this_guy) && llGetListLength(split)) { - string curr_base = llList2String(split, 0); - float curr_ver = (float)llList2String(split, 1); -//log_it("outer: " + curr_base + " / " + (string)curr_ver); - integer inner; - for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { - string next_guy = llGetInventoryName(inventory_type, inner); - list comp_split = compute_basename_and_version(next_guy); - if (llGetListLength(comp_split)) { - string comp_base = llList2String(comp_split, 0); - float comp_ver = (float)llList2String(comp_split, 1); - // okay, now we can actually compare. - if (curr_base != comp_base) { - // break out of inner loop. we are past where the names can matter. - inner = 2 * llGetInventoryNumber(inventory_type); - } else { -//log_it("inner: " + comp_base + " / " + (string)comp_ver); - if (curr_ver <= comp_ver) { - // the script at inner index is comparable or better than - // the script at the outer index. - removal_list += curr; - } else { - // this inner script must be inferior to the outer one, - // somehow, which defies our expectation of alphabetical ordering. - removal_list += next_guy; - } - } - } - } - } - } - - // now actually do the deletions. - for (outer = 0; outer < llGetListLength(removal_list); outer++) { - string to_whack = llList2String(removal_list, outer); - if (DEBUGGING) - log_it("removing older asset: " + to_whack); - llRemoveInventory(to_whack); - } -} - -// ensures that only the latest version of any script or object is kept in our inventory. -destroy_older_versions() -{ - // firstly, iterate across scripts to clean out older versions. - scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); - // secondly, try to clean out the objects. - scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); - // thirdly, try to clean out the notecards. - scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); -} - -// sets the object to be listening for update info. -// if "just_owner" is true, then we will not listen on the general announcement channel. -listen_for_orders(integer just_owner) -{ - if (!just_owner) { - // try to hear an update being announced. - llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); - } - - // super secret owner controls. - llListen(0, "", llGetOwner(), ""); -} - -// returns true if this object is a huffotronic updater of some sort. -integer inside_of_updater() -{ - return find_substring(llGetObjectName(), "huffotronic") >= 0; -} - -// returns true if a script is a version of our update server. -integer matches_server_script(string to_check) -{ - return is_prefix(to_check, SERVER_SCRIPT); -} - -// stops all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - integer insider = inside_of_updater(); - if (running_state == TRUE) { - // make sure we crank up the scripts that are new first. we want to reset them - // as well, which we don't want to do for any existing scripts. - integer crank_indy; - for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { - string crankee = llList2String(updates_needed, crank_indy); - if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { - if (!insider || matches_server_script(crankee)) { - // allow it to run again. - llSetScriptState(crankee, TRUE); - // reset it, to make sure it starts at the top. - llResetOtherScript(crankee); - } - } - } - } - - integer indy; - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if ( (curr_script != self_script) - && (!insider || matches_server_script(curr_script)) ) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -// a random channel for the interaction with the server. -integer random_channel() { return -(integer)(llFrand(800000) + 20000); } - -// make sure that any dependencies for the script with "basename" are added to the list -// of requests we make during an update. -list add_dependencies(string basename) -{ - list to_return; - integer indy; - for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { - list deps = llParseString2List(llList2String(known_script_dependencies, indy), - [ITEM_LIST_SEPARATOR], []); -//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); - if (basename == llList2String(deps, 0)) { - // first off, is this item with new dependencies actually present? - integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); - if (where >= 0) { - // we do use the script with deps, but is the dependent item really missing? - where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); - if (where < 0) { - // we found a dependency match for this script, so we'll ask for the missing item. - if (DEBUGGING) - log_it("missing dep: " + llList2String(deps, 1)); - to_return += [ llList2String(deps, 1) ]; - } - } - } - } - return to_return; -} - -// complains if memory seems to be getting tight. -test_memory() -{ - if (llGetFreeMemory() < 4096) - log_it("mem_free = " + (string)llGetFreeMemory()); -} - -// starts an update given a list of scripts that the server has available, encoded as -// a string in the "encoded_list". -integer initiate_update(string encoded_list) -{ - list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); - integer continue_listening_for_scripts = FALSE; - // if true, we aren't done hearing about available scripts yet. - encoded_list = ""; - // figure out which scripts we need by comparing the list available from the server - // against our current inventory. we only want scripts with newer version numbers. - integer sindy; - for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { - string curr = llList2String(scripts_avail, sindy); - if (curr == CONTINUANCE_MARKER) { - // this is a special continuation signal. we need to hear the rest of the list. - continue_listening_for_scripts = TRUE; - } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { - // we've found a dependency item. - known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; -//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); - } else { - list split = compute_basename_and_version(curr); - if (llGetListLength(split) == 2) { - string basename = llList2String(split, 0); - string version = llList2String(split, 1); - split = []; - integer oy_indy; -//replace common code with func. - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { -// if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); -// } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { - list srv_split = compute_basename_and_version - (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); - if ( (llGetListLength(srv_split) == 2) - && (basename == llList2String(srv_split, 0)) - && ((float)version > (float)llList2String(srv_split, 1)) ) { - if (DEBUGGING) { - log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); - } - test_memory(); - updates_needed += [ curr ]; - } - } - updates_needed += add_dependencies(basename); - } - } - } - // we skip the next step if we're still waiting to hear about more. - if (continue_listening_for_scripts) { -//log_it("still listening for more updates..."); - return FALSE; - } - if (llGetListLength(updates_needed)) { -//log_it("update chan=" + (string)update_channel); - llSay(update_channel, REQUEST_SCRIPT_UPDATE); - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i need updating."); - } - } else { - if (DEBUGGING) { - log_it("told server " + (string)inventory_request_channel + " that i am done updating."); - } - llSay(update_channel, DONE_UPDATING); - } - return TRUE; -} - -// this alerts the server to our most desired scripts. -tell_server_our_wish_list() -{ - llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); -} - -// checks whether all of the updates needed are present yet. -integer check_on_update_presence() -{ - integer indy; - for (indy = 0; indy < llGetListLength(updates_needed); indy++) { - integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); - // any single missing guy means they aren't up to date yet. - if (found < 0) { - if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); - return FALSE; - } - } - // nothing was detected as missing anymore. - return TRUE; -} - -// respond to spoken commands from the server. -integer process_update_news(integer channel, string name, key id, string message) -{ - if (!channel) { - // this is a command. - if (message == "ureset") { - llResetScript(); // start over. - } - if (message == "ushow") { - integer sindy; - integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); - list script_list = [ "scripts--" ]; // first item is just a header. - for (sindy = 0; sindy < script_count; sindy++) { - script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; - } - dump_list_to_log(script_list); - } - return FALSE; // nothing to do here. - } - if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { -/* never seen. if (id == llGetKey()) { -if (DEBUGGING) log_it("ignoring update from self."); - return FALSE; // ack, that's our very object. - } -*/ - if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { - // this is a new style update message. we can set a different request channel. - string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); - inventory_request_channel = (integer)just_chan; - } - integer prev_indy = find_in_list(updaters_heard, id); - // find the talker in our list. - if (prev_indy >= 0) { - // that guy was already heard from. check when last interacted. - integer last_heard = llList2Integer(last_interactions, prev_indy); - if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { - return FALSE; // not time to update with this guy again yet. - } -// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } - // make sure we think of this as a new updater now. - whack_updater_record(id); - } - - if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } - // record our new server. - current_server = id; - // make a random pause so not all updaters try to crank up at same time. - llSleep(randomize_within_range(2.8, 18.2, FALSE)); - - if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { - // oops, this is not good. we have too many servers now. -//hmmm: room for improvement here by tossing out the server that is oldest. - updaters_heard = llDeleteSubList(updaters_heard, 0, 0); - last_interactions = llDeleteSubList(last_interactions, 0, 0); - } - - // add the talker to our list. - updaters_heard += id; - last_interactions += llGetUnixTime(); - - // begin the update interaction with this guy. - update_channel = random_channel(); - return TRUE; - } - if (update_channel && (channel == update_channel) ) { - if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { - // tasty, this is a list of scripts that can be had. - message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); - if (message == BUSY_BUSY) { - // server has signified that it's too busy (or its owner is a moron) because it is - // claiming it has no scripts at all. - if (DEBUGGING) { - log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); - } - // make it seem like we need to do this one again sooner than normal. - whack_updater_record(id); - // busy server means move no further forward. - return FALSE; - } - return initiate_update(message); - } else if (is_prefix(message, SHUT_THEM_DOWN)) { - if (DEBUGGING) { log_it("stopping other scripts."); } - knock_around_other_scripts(FALSE); - // now that we know for sure the server's ready to update us, - // we tell it what we need. - tell_server_our_wish_list(); - return FALSE; - } else if (is_prefix(message, START_THEM_UP)) { - // let the server know that we've finished, for all intents and purposes. - llSay(update_channel, DONE_UPDATING); - // we pause a random bit first; we want to ensure we aren't swamping - // SL with our inventory loading. - llSleep(randomize_within_range(2.5, 8.2, FALSE)); - if (DEBUGGING) { log_it("starting other scripts."); } - careful_crankup(); - return TRUE; // change state now. -// } else { -//log_it("unknown command on update channel: " + message); - } - } - return FALSE; -} - -////////////// -// from hufflets... - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) - return inv; - else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) - return inv; - } - return -2; // failed to find it. -} - -////////////// - -integer MAX_CHAT_LINE = 900; - // the most characters we'll try to say in one chat. - -dump_list_to_log(list to_show) -{ - string text = dump_list(to_show); // get some help from the other version. - integer len = llStringLength(text); - integer i; - for (i = 0; i < len; i += MAX_CHAT_LINE) { - integer last_bit = i + MAX_CHAT_LINE - 1; - if (last_bit >= len) last_bit = len - 1; - string next_line = llGetSubString(text, i, last_bit); - llWhisper(0, next_line); - } -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "\"" + next_line + "\""; - } - text = text + next_line; - if (i < len - 1) text = text + " "; - } - return text; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end hufflets. -////////////// - -// no huffotronic trap state for startup, because this script will actually -// run (and is expected) inside a huffotronic updater object. - -default -{ - state_entry() - { - auto_retire(); // only allow the most recent revision. - initialize(); - state awaiting_commands; - } -} - -state awaiting_commands -{ - state_entry() - { - if (DEBUGGING) log_it(""); - careful_crankup(); // we always start by getting everyone running. - current_server = NULL_KEY; // forget previous server. - listen_for_orders(FALSE); - inventory_request_channel = 0; // no inventory request channel either. - update_channel = 0; // no channel currently. - updates_needed = []; // we know of no needs right now. - known_script_dependencies = []; // no deps either. - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) - state establish_private_channel; - } -} - -state establish_private_channel -{ - state_entry() - { - if (DEBUGGING) log_it(""); - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (inventory_request_channel) - llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); - else - llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); - llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); - } - - state_exit() { llSetTimerEvent(0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // ready for a state change, but what kind? - if (llGetListLength(updates_needed)) { -//log_it("have a list of updates now."); - state performing_update; - } else { -//log_it("no updates needed in list, going back"); - state awaiting_commands; - } - } - } - - timer() { - if (DEBUGGING) { - log_it("timed out establishing channel with server " + (string)inventory_request_channel); - } - whack_updater_record(current_server); - state awaiting_commands; - } - - on_rez(integer parm) { state default; } -} - -state performing_update -{ - state_entry() - { - // must re-listen after a state change. - llListen(update_channel, "", current_server, ""); - listen_for_orders(TRUE); - if (DEBUGGING) log_it(""); - llSetTimerEvent(UPDATE_TIMER_INTERVAL); - update_start_time = llGetUnixTime(); - } - - state_exit() { llSetTimerEvent(0.0); } - - listen(integer channel, string name, key id, string message) - { - if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { - return; // must be same owner to ensure proper perms. - } - if (process_update_news(channel, name, id, message)) { - // normal finish of update process. - state awaiting_commands; - } - } - - timer() { - if (llGetListLength(updates_needed) == 0) { -//log_it("nothing to update, leaving perform state."); - state awaiting_commands; // we've got nothing to do. - } else { - // see if all our requested scripts are there yet; if not, we're not done updating. - integer ready = check_on_update_presence(); - if (ready) { - if (DEBUGGING) log_it("reporting scripts are current."); - llSay(update_channel, SCRIPTS_ARE_CURRENT); - } - } - if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { - if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } - whack_updater_record(current_server); - state awaiting_commands; - } - } - - on_rez(integer parm) { state default; } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.txt b/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.txt new file mode 100755 index 00000000..4a458bb5 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/huff-update_client_v20.1.txt @@ -0,0 +1,826 @@ + +// huffware script: huff-update client, by fred huffhines. +// +// this script is the client side of the update process. it should reside in an object that +// has scripts which should be automatically updated. it will listen for announcements by +// an update server and communicate with the server to ensure that all of its scripts are +// the most up to date available with the server. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +integer DEBUGGING = FALSE; // if TRUE, the script will output status information. + +integer SERVER_IGNORE_TIME = 1200; // number of seconds between performing an upgrade with the same server. + +integer MAXIMUM_UPDATE_TIME_ALLOWED = 140; // we allow one upgrade process to take this long overall. + +integer UPDATE_ANNOUNCEMENT_CHANNEL = -420108; // used by server to brag about itself. +integer OLD_REQUEST_INVENTORY_CHANNEL = -421008; // used by clients to request an update list. + +string UPDATE_ANNOUNCEMENT_PREFIX = "#huff-update#"; // first part of any announcement. +string REQUEST_INVENTORY_PREFIX = "#huff-reqinv#"; // first part of request for inventory list. +string REPORT_AVAILABLE_SCRIPTS = "#scripts#"; // server's keyword to let client know script inventory. +string REQUEST_SCRIPT_UPDATE = "#updatego#"; // keyword used by client to request some updates. +string SHUT_THEM_DOWN = "#huffdown#"; // server tells client to stop any non-updater scripts. +string READY_TO_UPDATE = "#listoneeds#"; // the client tells the server the scripts it wants. +string SCRIPTS_ARE_CURRENT = "#gottemthx#"; // client says this when all new scripts are in place. +string START_THEM_UP = "#huffup#"; // server tells client to start up other scripts again. +string DONE_UPDATING = "#finito#"; // the client is done updating. +string BUSY_BUSY = "#busymuch#"; // a signal that the server is too busy to update us. + +float UPDATE_TIMER_INTERVAL = 2.0; // interval between checks on our update status. + +integer UPDATER_SCRIPT_PIN = -1231008; // the hook for our scripts to be modified. + +///float BUSY_SERVER_PAUSE_TIME = 38.0; // num seconds to delay when server says it's too busy. + +string UPDATER_PARM_SEPARATOR = "~~~"; + // three tildes is an uncommon thing to have otherwise, so we use it to separate + // our commands in linked messages. + +string SCRIPT_DEPENDENCY_MARK = "DEP"; // signals that a dependency is coming. +string ITEM_LIST_SEPARATOR = "``"; // separates dependencies. + +integer MAXIMUM_SERVERS_TRACKED = 32; + // we will listen to this many servers before we decide to remove one. + +string CONTINUANCE_MARKER = "..."; + // a string sent when the update list is too long and needs to be continued in another chat. + +string SERVER_SCRIPT = "a huffotronic update server"; + // the prefix of our server script that hands out updates. + +// global variables... + +integer inventory_request_channel; // used for newer version servers to cut down cross chatter. +list updaters_heard; // the update servers we've heard from recently. +list last_interactions; // times of the last update process engaged with the updater. +integer update_channel; // current channel for interaction with specific server. +key current_server; // the updater that is active right now, if any. +integer update_start_time; // when the last update process began. +list updates_needed; // stores the set of scripts that are in need of an update. +list known_script_dependencies; // stores the list of dependency info. + +careful_crankup() +{ + knock_around_other_scripts(TRUE); + // clean out the older items and scripts. we do this after getting everyone running + // since we might be whacking ourselves. + destroy_older_versions(); +} + +// reset our variables. +initialize() +{ + updaters_heard = []; + last_interactions = []; + inventory_request_channel = 0; + update_channel = 0; + current_server = NULL_KEY; + llSetTimerEvent(0.0); + llSetRemoteScriptAccessPin(UPDATER_SCRIPT_PIN); + // a new enhancements; tells the server that this guy has finished an update cycle. this + // only comes into play when the updater script itself has just been updated, but it's + // nice for the server to avoid claiming erroneous timeouts occurred. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); + llSleep(0.4); // snooze and repeat to overcome occasionally lossy chats. + llSay(OLD_REQUEST_INVENTORY_CHANNEL, DONE_UPDATING); +} + +whack_updater_record(key id) +{ + integer prev_indy = find_in_list(updaters_heard, id); + if (prev_indy < 0) return; // not there. + updaters_heard = chop_list(updaters_heard, 0, prev_indy - 1) + + chop_list(updaters_heard, prev_indy + 1, llGetListLength(updaters_heard) - 1); + last_interactions = chop_list(last_interactions, 0, prev_indy - 1) + + chop_list(last_interactions, prev_indy + 1, llGetListLength(last_interactions) - 1); +} + +// note that this new, lower memory version, depends on the inventory functions returning +// items in alphabetical order. +scrub_items_by_type(string this_guy, integer inventory_type) +{ + list removal_list; + integer outer; + for (outer = 0; outer < llGetInventoryNumber(inventory_type); outer++) { + string curr = llGetInventoryName(inventory_type, outer); + list split = compute_basename_and_version(curr); + // make sure there was a comparable version number in this name. + if ( (curr != this_guy) && llGetListLength(split)) { + string curr_base = llList2String(split, 0); + float curr_ver = (float)llList2String(split, 1); +//log_it("outer: " + curr_base + " / " + (string)curr_ver); + integer inner; + for (inner = outer + 1; inner < llGetInventoryNumber(inventory_type); inner++) { + string next_guy = llGetInventoryName(inventory_type, inner); + list comp_split = compute_basename_and_version(next_guy); + if (llGetListLength(comp_split)) { + string comp_base = llList2String(comp_split, 0); + float comp_ver = (float)llList2String(comp_split, 1); + // okay, now we can actually compare. + if (curr_base != comp_base) { + // break out of inner loop. we are past where the names can matter. + inner = 2 * llGetInventoryNumber(inventory_type); + } else { +//log_it("inner: " + comp_base + " / " + (string)comp_ver); + if (curr_ver <= comp_ver) { + // the script at inner index is comparable or better than + // the script at the outer index. + removal_list += curr; + } else { + // this inner script must be inferior to the outer one, + // somehow, which defies our expectation of alphabetical ordering. + removal_list += next_guy; + } + } + } + } + } + } + + // now actually do the deletions. + for (outer = 0; outer < llGetListLength(removal_list); outer++) { + string to_whack = llList2String(removal_list, outer); + if (DEBUGGING) + log_it("removing older asset: " + to_whack); + llRemoveInventory(to_whack); + } +} + +// ensures that only the latest version of any script or object is kept in our inventory. +destroy_older_versions() +{ + // firstly, iterate across scripts to clean out older versions. + scrub_items_by_type(llGetScriptName(), INVENTORY_SCRIPT); + // secondly, try to clean out the objects. + scrub_items_by_type(llGetScriptName(), INVENTORY_OBJECT); + // thirdly, try to clean out the notecards. + scrub_items_by_type(llGetScriptName(), INVENTORY_NOTECARD); +} + +// sets the object to be listening for update info. +// if "just_owner" is true, then we will not listen on the general announcement channel. +listen_for_orders(integer just_owner) +{ + if (!just_owner) { + // try to hear an update being announced. + llListen(UPDATE_ANNOUNCEMENT_CHANNEL, "", NULL_KEY, ""); + } + + // super secret owner controls. + llListen(0, "", llGetOwner(), ""); +} + +// returns true if this object is a huffotronic updater of some sort. +integer inside_of_updater() +{ + return find_substring(llGetObjectName(), "huffotronic") >= 0; +} + +// returns true if a script is a version of our update server. +integer matches_server_script(string to_check) +{ + return is_prefix(to_check, SERVER_SCRIPT); +} + +// stops all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + integer insider = inside_of_updater(); + if (running_state == TRUE) { + // make sure we crank up the scripts that are new first. we want to reset them + // as well, which we don't want to do for any existing scripts. + integer crank_indy; + for (crank_indy = 0; crank_indy < llGetListLength(updates_needed); crank_indy++) { + string crankee = llList2String(updates_needed, crank_indy); + if (find_in_inventory(crankee, INVENTORY_SCRIPT, TRUE) >= 0) { + if (!insider || matches_server_script(crankee)) { + // allow it to run again. + llSetScriptState(crankee, TRUE); + // reset it, to make sure it starts at the top. + llResetOtherScript(crankee); + } + } + } + } + + integer indy; + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if ( (curr_script != self_script) + && (!insider || matches_server_script(curr_script)) ) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +// a random channel for the interaction with the server. +integer random_channel() { return -(integer)(llFrand(800000) + 20000); } + +// make sure that any dependencies for the script with "basename" are added to the list +// of requests we make during an update. +list add_dependencies(string basename) +{ + list to_return; + integer indy; + for (indy = 0; indy < llGetListLength(known_script_dependencies); indy++) { + list deps = llParseString2List(llList2String(known_script_dependencies, indy), + [ITEM_LIST_SEPARATOR], []); +//log_it("base=" + llList2String(dep, 0) + " lastver=" + llList2String(dep, 1) + " newdep=" + llList2String(dep, 2)); + if (basename == llList2String(deps, 0)) { + // first off, is this item with new dependencies actually present? + integer where = find_in_inventory(basename, INVENTORY_SCRIPT, FALSE); + if (where >= 0) { + // we do use the script with deps, but is the dependent item really missing? + where = find_in_inventory(llList2String(deps, 1), INVENTORY_SCRIPT, FALSE); + if (where < 0) { + // we found a dependency match for this script, so we'll ask for the missing item. + if (DEBUGGING) + log_it("missing dep: " + llList2String(deps, 1)); + to_return += [ llList2String(deps, 1) ]; + } + } + } + } + return to_return; +} + +// complains if memory seems to be getting tight. +test_memory() +{ + if (llGetFreeMemory() < 4096) + log_it("mem_free = " + (string)llGetFreeMemory()); +} + +// starts an update given a list of scripts that the server has available, encoded as +// a string in the "encoded_list". +integer initiate_update(string encoded_list) +{ + list scripts_avail = llParseString2List(encoded_list, [UPDATER_PARM_SEPARATOR], []); + integer continue_listening_for_scripts = FALSE; + // if true, we aren't done hearing about available scripts yet. + encoded_list = ""; + // figure out which scripts we need by comparing the list available from the server + // against our current inventory. we only want scripts with newer version numbers. + integer sindy; + for (sindy = 0; sindy < llGetListLength(scripts_avail); sindy++) { + string curr = llList2String(scripts_avail, sindy); + if (curr == CONTINUANCE_MARKER) { + // this is a special continuation signal. we need to hear the rest of the list. + continue_listening_for_scripts = TRUE; + } else if (is_prefix(curr, SCRIPT_DEPENDENCY_MARK)) { + // we've found a dependency item. + known_script_dependencies += [ llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1) ]; +//log_it("script dep: " + llGetSubString(curr, llStringLength(SCRIPT_DEPENDENCY_MARK), -1)); + } else { + list split = compute_basename_and_version(curr); + if (llGetListLength(split) == 2) { + string basename = llList2String(split, 0); + string version = llList2String(split, 1); + split = []; + integer oy_indy; +//replace common code with func. + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_OBJECT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_OBJECT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { +// if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); +// } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_NOTECARD); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_NOTECARD, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + for (oy_indy = 0; oy_indy < llGetInventoryNumber(INVENTORY_SCRIPT); oy_indy++) { + list srv_split = compute_basename_and_version + (llGetInventoryName(INVENTORY_SCRIPT, oy_indy)); + if ( (llGetListLength(srv_split) == 2) + && (basename == llList2String(srv_split, 0)) + && ((float)version > (float)llList2String(srv_split, 1)) ) { + if (DEBUGGING) { + log_it("i need '" + curr + "' from server " + (string)inventory_request_channel); + } + test_memory(); + updates_needed += [ curr ]; + } + } + updates_needed += add_dependencies(basename); + } + } + } + // we skip the next step if we're still waiting to hear about more. + if (continue_listening_for_scripts) { +//log_it("still listening for more updates..."); + return FALSE; + } + if (llGetListLength(updates_needed)) { +//log_it("update chan=" + (string)update_channel); + llSay(update_channel, REQUEST_SCRIPT_UPDATE); + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i need updating."); + } + } else { + if (DEBUGGING) { + log_it("told server " + (string)inventory_request_channel + " that i am done updating."); + } + llSay(update_channel, DONE_UPDATING); + } + return TRUE; +} + +// this alerts the server to our most desired scripts. +tell_server_our_wish_list() +{ + llSay(update_channel, READY_TO_UPDATE + wrap_parameters(updates_needed)); +} + +// checks whether all of the updates needed are present yet. +integer check_on_update_presence() +{ + integer indy; + for (indy = 0; indy < llGetListLength(updates_needed); indy++) { + integer found = find_in_inventory(llList2String(updates_needed, indy), INVENTORY_ALL, TRUE); + // any single missing guy means they aren't up to date yet. + if (found < 0) { + if (DEBUGGING) log_it(llList2String(updates_needed, indy) + " not seen as updated yet."); + return FALSE; + } + } + // nothing was detected as missing anymore. + return TRUE; +} + +// respond to spoken commands from the server. +integer process_update_news(integer channel, string name, key id, string message) +{ + if (!channel) { + // this is a command. + if (message == "ureset") { + llResetScript(); // start over. + } + if (message == "ushow") { + integer sindy; + integer script_count = llGetInventoryNumber(INVENTORY_SCRIPT); + list script_list = [ "scripts--" ]; // first item is just a header. + for (sindy = 0; sindy < script_count; sindy++) { + script_list += [ llGetInventoryName(INVENTORY_SCRIPT, sindy) ]; + } + dump_list_to_log(script_list); + } + return FALSE; // nothing to do here. + } + if (!update_channel && (channel == UPDATE_ANNOUNCEMENT_CHANNEL)) { +/* never seen. if (id == llGetKey()) { +if (DEBUGGING) log_it("ignoring update from self."); + return FALSE; // ack, that's our very object. + } +*/ + if (llStringLength(message) > llStringLength(UPDATE_ANNOUNCEMENT_PREFIX)) { + // this is a new style update message. we can set a different request channel. + string just_chan = llDeleteSubString(message, 0, llStringLength(UPDATE_ANNOUNCEMENT_PREFIX) - 1); + inventory_request_channel = (integer)just_chan; + } + integer prev_indy = find_in_list(updaters_heard, id); + // find the talker in our list. + if (prev_indy >= 0) { + // that guy was already heard from. check when last interacted. + integer last_heard = llList2Integer(last_interactions, prev_indy); + if (llAbs(llGetUnixTime() - last_heard) < SERVER_IGNORE_TIME) { + return FALSE; // not time to update with this guy again yet. + } +// if (DEBUGGING) { log_it("started listening again to server " + (string)id); } + // make sure we think of this as a new updater now. + whack_updater_record(id); + } + + if (DEBUGGING) { log_it("heard server " + (string)inventory_request_channel + "'s announcement."); } + // record our new server. + current_server = id; + // make a random pause so not all updaters try to crank up at same time. + llSleep(randomize_within_range(2.8, 18.2, FALSE)); + + if (llGetListLength(updaters_heard) > MAXIMUM_SERVERS_TRACKED) { + // oops, this is not good. we have too many servers now. +//hmmm: room for improvement here by tossing out the server that is oldest. + updaters_heard = llDeleteSubList(updaters_heard, 0, 0); + last_interactions = llDeleteSubList(last_interactions, 0, 0); + } + + // add the talker to our list. + updaters_heard += id; + last_interactions += llGetUnixTime(); + + // begin the update interaction with this guy. + update_channel = random_channel(); + return TRUE; + } + if (update_channel && (channel == update_channel) ) { + if (is_prefix(message, REPORT_AVAILABLE_SCRIPTS)) { + // tasty, this is a list of scripts that can be had. + message = llDeleteSubString(message, 0, llStringLength(REPORT_AVAILABLE_SCRIPTS) - 1); + if (message == BUSY_BUSY) { + // server has signified that it's too busy (or its owner is a moron) because it is + // claiming it has no scripts at all. + if (DEBUGGING) { + log_it("server " + (string)inventory_request_channel + " is too busy to update us now."); + } + // make it seem like we need to do this one again sooner than normal. + whack_updater_record(id); + // busy server means move no further forward. + return FALSE; + } + return initiate_update(message); + } else if (is_prefix(message, SHUT_THEM_DOWN)) { + if (DEBUGGING) { log_it("stopping other scripts."); } + knock_around_other_scripts(FALSE); + // now that we know for sure the server's ready to update us, + // we tell it what we need. + tell_server_our_wish_list(); + return FALSE; + } else if (is_prefix(message, START_THEM_UP)) { + // let the server know that we've finished, for all intents and purposes. + llSay(update_channel, DONE_UPDATING); + // we pause a random bit first; we want to ensure we aren't swamping + // SL with our inventory loading. + llSleep(randomize_within_range(2.5, 8.2, FALSE)); + if (DEBUGGING) { log_it("starting other scripts."); } + careful_crankup(); + return TRUE; // change state now. +// } else { +//log_it("unknown command on update channel: " + message); + } + } + return FALSE; +} + +////////////// +// from hufflets... + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + llWhisper(0, llGetScriptName() + " [" + (string)debug_num + "] (" + (string)llGetFreeMemory() + ") " + to_say); +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, UPDATER_PARM_SEPARATOR); } + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type, integer exact_match) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (exact_match && (llGetInventoryName(inv_type, inv) == name_to_find) ) + return inv; + else if (!exact_match && is_prefix(llGetInventoryName(inv_type, inv), name_to_find)) + return inv; + } + return -2; // failed to find it. +} + +////////////// + +integer MAX_CHAT_LINE = 900; + // the most characters we'll try to say in one chat. + +dump_list_to_log(list to_show) +{ + string text = dump_list(to_show); // get some help from the other version. + integer len = llStringLength(text); + integer i; + for (i = 0; i < len; i += MAX_CHAT_LINE) { + integer last_bit = i + MAX_CHAT_LINE - 1; + if (last_bit >= len) last_bit = len - 1; + string next_line = llGetSubString(text, i, last_bit); + llWhisper(0, next_line); + } +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "\"" + next_line + "\""; + } + text = text + next_line; + if (i < len - 1) text = text + " "; + } + return text; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end hufflets. +////////////// + +// no huffotronic trap state for startup, because this script will actually +// run (and is expected) inside a huffotronic updater object. + +default +{ + state_entry() + { + auto_retire(); // only allow the most recent revision. + initialize(); + state awaiting_commands; + } +} + +state awaiting_commands +{ + state_entry() + { + if (DEBUGGING) log_it(""); + careful_crankup(); // we always start by getting everyone running. + current_server = NULL_KEY; // forget previous server. + listen_for_orders(FALSE); + inventory_request_channel = 0; // no inventory request channel either. + update_channel = 0; // no channel currently. + updates_needed = []; // we know of no needs right now. + known_script_dependencies = []; // no deps either. + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) + state establish_private_channel; + } +} + +state establish_private_channel +{ + state_entry() + { + if (DEBUGGING) log_it(""); + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (inventory_request_channel) + llSay(inventory_request_channel, REQUEST_INVENTORY_PREFIX + (string)update_channel); + else + llSay(OLD_REQUEST_INVENTORY_CHANNEL, REQUEST_INVENTORY_PREFIX + (string)update_channel); + llSetTimerEvent(MAXIMUM_UPDATE_TIME_ALLOWED); + } + + state_exit() { llSetTimerEvent(0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // ready for a state change, but what kind? + if (llGetListLength(updates_needed)) { +//log_it("have a list of updates now."); + state performing_update; + } else { +//log_it("no updates needed in list, going back"); + state awaiting_commands; + } + } + } + + timer() { + if (DEBUGGING) { + log_it("timed out establishing channel with server " + (string)inventory_request_channel); + } + whack_updater_record(current_server); + state awaiting_commands; + } + + on_rez(integer parm) { state default; } +} + +state performing_update +{ + state_entry() + { + // must re-listen after a state change. + llListen(update_channel, "", current_server, ""); + listen_for_orders(TRUE); + if (DEBUGGING) log_it(""); + llSetTimerEvent(UPDATE_TIMER_INTERVAL); + update_start_time = llGetUnixTime(); + } + + state_exit() { llSetTimerEvent(0.0); } + + listen(integer channel, string name, key id, string message) + { + if ((id != llGetOwner()) && (llGetOwnerKey(id) != llGetOwner())) { + return; // must be same owner to ensure proper perms. + } + if (process_update_news(channel, name, id, message)) { + // normal finish of update process. + state awaiting_commands; + } + } + + timer() { + if (llGetListLength(updates_needed) == 0) { +//log_it("nothing to update, leaving perform state."); + state awaiting_commands; // we've got nothing to do. + } else { + // see if all our requested scripts are there yet; if not, we're not done updating. + integer ready = check_on_update_presence(); + if (ready) { + if (DEBUGGING) log_it("reporting scripts are current."); + llSay(update_channel, SCRIPTS_ARE_CURRENT); + } + } + if (llAbs(update_start_time - llGetUnixTime()) >= MAXIMUM_UPDATE_TIME_ALLOWED) { + if (DEBUGGING) { log_it("timeout during update process with server " + (string)inventory_request_channel); } + whack_updater_record(current_server); + state awaiting_commands; + } + } + + on_rez(integer parm) { state default; } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.lsl b/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.lsl deleted file mode 100755 index f44b36f8..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.lsl +++ /dev/null @@ -1,151 +0,0 @@ - -// huffware script: invisiprim, by fred huffhines. -// -// a click on and off invisibility script. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - llSetTexture("e97cf410-8e61-7005-ec06-629eba4cd1fb", ALL_SIDES); - // This is one of the invisiprim textures. - llSetAlpha(1.0, ALL_SIDES); - } - touch(integer num) { - if (llDetectedKey(0) == llGetOwner()) { - // When touched, it will go back to a non-invisiprim. - state blank; - } - } -} - -state blank -{ - state_entry() { - llSetTexture("4c1ce202-4196-f1c1-0409-367b3a71543e", ALL_SIDES); - // This is the 'Blank' texture - llSetAlpha(1.0, ALL_SIDES); - } - touch(integer num) { - if (llDetectedKey(0) == llGetOwner()) { - // When touched, it will go back to an invisiprim. - state default; - } - } - on_rez(integer parm) { llResetScript(); } -} - -// attributions: -// invisiprim original version created by Opus Beck 9 aug 2007 diff --git a/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.txt b/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.txt new file mode 100755 index 00000000..f44b36f8 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/invisiprim_v0.8.txt @@ -0,0 +1,151 @@ + +// huffware script: invisiprim, by fred huffhines. +// +// a click on and off invisibility script. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + llSetTexture("e97cf410-8e61-7005-ec06-629eba4cd1fb", ALL_SIDES); + // This is one of the invisiprim textures. + llSetAlpha(1.0, ALL_SIDES); + } + touch(integer num) { + if (llDetectedKey(0) == llGetOwner()) { + // When touched, it will go back to a non-invisiprim. + state blank; + } + } +} + +state blank +{ + state_entry() { + llSetTexture("4c1ce202-4196-f1c1-0409-367b3a71543e", ALL_SIDES); + // This is the 'Blank' texture + llSetAlpha(1.0, ALL_SIDES); + } + touch(integer num) { + if (llDetectedKey(0) == llGetOwner()) { + // When touched, it will go back to an invisiprim. + state default; + } + } + on_rez(integer parm) { llResetScript(); } +} + +// attributions: +// invisiprim original version created by Opus Beck 9 aug 2007 diff --git a/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.lsl b/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.lsl deleted file mode 100755 index 0e6fd666..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.lsl +++ /dev/null @@ -1,122 +0,0 @@ - -// huffware script: link reporter, by fred huffhines. -// -// a simple helper script that reports which link number this prim has. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - llSay(0, "This link is #" + (string)llGetLinkNumber()); - } - - on_rez(integer parm) { llResetScript(); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.txt b/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.txt new file mode 100755 index 00000000..0e6fd666 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/link_reporter_v0.5.txt @@ -0,0 +1,122 @@ + +// huffware script: link reporter, by fred huffhines. +// +// a simple helper script that reports which link number this prim has. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + llSay(0, "This link is #" + (string)llGetLinkNumber()); + } + + on_rez(integer parm) { llResetScript(); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.lsl b/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.lsl deleted file mode 100755 index aa0c30cd..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.lsl +++ /dev/null @@ -1,561 +0,0 @@ - -// logic system master script -// copyright john jamison, imagilearning? -// created by xyz -// modified by fred huffhines / chris koeritz. -// -// - -// defaults... -vector TEXT_COLOR = <0.6, 0.84, 0.8>; // label color. -float RADARTIME = 10.0; // how frequently radar fires. -float RANGE = 50.0; // range of the sensor sweeps. -integer MAX_AVATAR_AWOLS = 5; - // number of times the avatar is allowed to be missed by sensor. - // we have seen some unreliability of sensors, so a single miss is not a definite problem. -list RESET = ["Restart", "CANCEL"]; // used in a menu someplace? -string Choicetimer = "2"; // how long they get to make their choice? - -// global variables... -integer current_awols; -key user = NULL_KEY; -key lquery = NULL_KEY; -list dialog; -string CHOICE1; -string CHOICE2; -string CHOICE3; -string CHOICE4; -string CHOICE5; -string CHOICE6; -string CHOICE7; -string CHOICE8; -string CHOICE1TEXT; -string CHOICE2TEXT; -string CHOICE3TEXT; -string CHOICE4TEXT; -string CHOICE5TEXT; -string CHOICE6TEXT; -string CHOICE7TEXT; -string CHOICE8TEXT; -integer CHOICE1POINTS; -integer CHOICE2POINTS; -integer CHOICE3POINTS; -integer CHOICE4POINTS; -integer CHOICE5POINTS; -integer CHOICE6POINTS; -integer CHOICE7POINTS; -integer CHOICE8POINTS; -integer TotalScore; -string DIALOG = " "; -string CurrentNoteCard; -string resettext = " "; -list CHOICE; -integer line = 0; -integer eof = 0; -integer CHANNEL; - -initialize() -{ - CHOICE = [ CHOICE1TEXT, CHOICE2TEXT, CHOICE3TEXT, CHOICE4TEXT ]; - llSetText("[System Ready]", TEXT_COLOR, 1); - eof = 0; -} - -// leave the current setup and completely restart the script. -reboot(string reason) -{ -llSay(0, "restarting now because " + reason); - llResetScript(); -} - -// starts looking for our registered user. -start_sensor_sweeps() -{ - llSensorRemove(); // clear any existing sensor. -//llSay(0, "sweeping for " + user + " aka " + llKey2Name(user)); - llSensorRepeat("", user, AGENT, RANGE, 2 * PI, RADARTIME); // look for our customer. -} - -// what this did before made no sense... -// but now it serves to reset the device if the avatar wandered off. -handle_sensor(integer numDetected) -{ - integer proceed = FALSE; - integer i; - for (i = 0; i < numDetected; i++) { - if (llDetectedKey(i) == user) proceed = TRUE; - } - if (proceed) return; // keep running like we were. - else reboot("we no longer saw our user here."); // reboot, since we don't see our user. -} - -// processes commands coming from other scripts or other parts of the object. -handle_link_message(string str, key id) -{ - if (str == "user") { - user = id; - llSetText ("System in use by " + llKey2Name (id), TEXT_COLOR, 1); - CurrentNoteCard = llGetObjectDesc(); - CHANNEL = llRound (llFrand (-394304)); - llListen (CHANNEL, "", NULL_KEY, ""); - start_sensor_sweeps(); - lquery = llGetNotecardLine (CurrentNoteCard, line); - } -} - -// handles notecard data as it is read. -process_incoming_data(key query_id, string data) -{ - list split_data = llParseString2List (data, [":"], []); - string cmd = llToLower(llList2String(split_data, 0)); - -//hmmm: terribly repetitive code here. clean up, shorten. - if (cmd == "choicetimer") { - Choicetimer = llList2String (split_data, 1); - } - if (cmd == "chat") { - llSay(0, llList2String (split_data, 1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "whisper") { - llWhisper(0, llList2String (split_data, 1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "givenotecard") { - llGiveInventory (user, llList2String (split_data, 1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "channelsay") { - llSay((integer) llList2String (split_data, 1), llList2String (split_data, 2)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "channelshout") { - llShout ((integer) llList2String (split_data, 1), - llList2String (split_data, 2)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "channelwhisper") { - llSay((integer) llList2String (split_data, 1), llList2String (split_data, 2)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "resettext") { - resettext = llList2String (split_data, 1); - - } - if (cmd == "end") { -/// CurrentNoteCard = llGetObjectDesc(); -/// line = 0; - reboot("notecard said to end processing."); - } - - if (cmd == "giveobject") { - llGiveInventory (user, llList2String (split_data, 1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } -///TALK TO VB AS THIS NEXT PART NEEDS A MEDIA RELAY FOR IT TO WORK - if (cmd == "videourl") { - if (llList2String (split_data, 3) != "") { - llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_URL, - llList2String (split_data, 1) + ":" + - llList2String (split_data, 2) + ":" + - llList2String (split_data, 3) + - llList2String (split_data, 4)]); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - else { - llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_URL, - llList2String (split_data, 1) + ":" + - llList2String (split_data, 2)]); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - //llSay(-840,llList2String(dat,1)); - //llSay(-848,llList2String(dat,1)); - } - if (cmd == "mediatexture") { - llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_TEXTURE, - (key) llList2String (split_data, 1)]); - //llSay(-849,llList2String(dat,1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "sleep") { - llSleep (llList2Float (split_data, 1)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "audiourl") { -llSay(0, "got to audio url"); - if (llList2String (split_data, 3) != "") { - llSetParcelMusicURL (llList2String (split_data, 1) + ":" + - llList2String (split_data, 2) + ":" + - llList2String (split_data, 3) + llList2String (split_data, 4)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - - else { - llSetParcelMusicURL (llList2String (split_data, 1) + ":" + - llList2String (split_data, 2)); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - //llSay(-840,llList2String(dat,1)); - } - //THIS IS OPTION A// - if (cmd == "weburl") { - llLoadURL (user, llList2String (split_data, 1), - llList2String (split_data, 2) + llList2String (split_data, - 3) + - llList2String (split_data, 4)); - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - - - if (cmd == "dialog") { - DIALOG = llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice1") { - CHOICE1TEXT = llList2String (split_data, 1); - CHOICE1 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - if (cmd == "choice2") { - CHOICE2TEXT = llList2String (split_data, 1); - CHOICE2 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice3") { - CHOICE3TEXT = llList2String (split_data, 1); - CHOICE3 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice4") { - CHOICE4TEXT = llList2String (split_data, 1); - CHOICE4 = llList2String (split_data, 2); - - dialog = dialog +[llList2String (split_data, 1)]; - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice5") { - CHOICE5TEXT = llList2String (split_data, 1); - CHOICE5 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - if (cmd == "choice6") { - CHOICE6TEXT = llList2String (split_data, 1); - CHOICE6 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - - if (cmd == "choice7") { - CHOICE7TEXT = llList2String (split_data, 1); - CHOICE7 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - - if (cmd == "choice8") { - CHOICE8TEXT = llList2String (split_data, 1); - CHOICE8 = llList2String (split_data, 2); - dialog = dialog +[llList2String (split_data, 1)]; - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - - if (cmd == "choice1points") { - CHOICE1POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - - } - - if (cmd == "choice2points") { - CHOICE2POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice3points") { - CHOICE3POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice4points") { - CHOICE4POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice5points") { - CHOICE5POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice6points") { - CHOICE6POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice7points") { - CHOICE7POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "choice8points") { - CHOICE8POINTS = (integer) llList2String (split_data, 1); - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "email") { - llEmail (llList2String (split_data, 1), - llKey2Name (user) + " Scored " + (string) TotalScore + - " On " + llGetObjectDesc (), - llKey2Name (user) + " Scored " + (string) TotalScore + - " On " + llGetObjectDesc () + "Score As Of " + - CurrentNoteCard); - - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (cmd == "imuser") { - llInstantMessage (user, llList2String (split_data, 1)); - } - - if (cmd == "im") { - llInstantMessage (llList2String (split_data, 1), llList2String (split_data, 2)); - } - if (cmd == "deadusertime") { - RADARTIME = (integer) llList2String (split_data, 1); - } - - if (cmd == "deadrange") { - RANGE = (integer) llList2String (split_data, 1); - start_sensor_sweeps(); - } - - if (cmd == "finalscore") { - llSay (0, - "You Scored " + (string) TotalScore + "/" + - llList2String (split_data, 1)); - } - if (cmd == "playsounduuid") { - llPreloadSound (llList2String (split_data, 1)); - llPlaySound (llList2String (split_data, 1), - (integer) llList2String (split_data, 2)); - } - - if (cmd == "debug") { - llSay (2147483647, - "System Debug Info follows " + "/n " + - (string) "key user = " + (string) user + - (string) " key lquery = " + (string) lquery + - (string) " integer DEADTIME = " + (string) RADARTIME + - "string CHOICE1 = " + CHOICE1 + "string CHOICE2 = " + - CHOICE2 + "string CHOICE3 = " + CHOICE3 + - "string CHOICE4 = " + CHOICE4 + "string CHOICE1TEXT = " + - CHOICE1TEXT + "string CHOICE2TEXT = " + CHOICE2TEXT + - "string CHOICE3TEXT= " + CHOICE3TEXT + - "string CHOICE4TEXT= " + CHOICE4TEXT + - "integer CHOICE1POINTS" + (string) CHOICE1POINTS + - "integer CHOICE2POINTS" + (string) CHOICE2POINTS + - "integer CHOICE3POINTS" + (string) CHOICE3POINTS + - "integer CHOICE4POINTS" + (string) CHOICE4POINTS + - "integer Choicetimer = " + (string) Choicetimer + - "integer TotalScore =" + (string) TotalScore + - "string DIOALOGE = " + DIALOG + - "string CurrentNoteCard = " + CurrentNoteCard + - "string resettext = " + resettext + - "list RESET = [Restart,CANCEL]" + "list CHOICE = " + - (string) CHOICE + "integer line = " + (string) line); - - } - - if (data == EOF) { - if (eof != 2 | eof == 1) { - eof = 2; - llSetTimerEvent ((float) Choicetimer); - } - } else { - line++; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } -} - -// process what the device hears spoken nearby. -hear_voices(integer channel, string name, key id, string message) -{ -//hmmm: bunkum. do this as a list. - if (message == CHOICE1TEXT) { - CurrentNoteCard = CHOICE1; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE1POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE2TEXT) { - CurrentNoteCard = CHOICE2; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE2POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE3TEXT) { - CurrentNoteCard = CHOICE3; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE3POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE4TEXT) { - CurrentNoteCard = CHOICE4; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE4POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE5TEXT) { - CurrentNoteCard = CHOICE5; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE5POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE6TEXT) { - CurrentNoteCard = CHOICE6; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE6POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE7TEXT) { - CurrentNoteCard = CHOICE7; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE7POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == CHOICE8TEXT) { - CurrentNoteCard = CHOICE8; - dialog =[]; - eof = 0; - line = 0; - TotalScore = TotalScore + CHOICE8POINTS; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } - if (message == "Restart") { - eof = 0; - line = 0; - lquery = llGetNotecardLine (CurrentNoteCard, line); - } -} - -////////////// - -// ensure stops running if kept in updater object. -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -// main state engine. -state real_default -{ - state_entry () { - initialize(); - } - - on_rez (integer i) { - reboot("object just rezzed."); - } - - no_sensor () { - current_awols++; -//llSay(0, "sensor missed avatar."); - if (current_awols > MAX_AVATAR_AWOLS) { - reboot("avatar was missed by sensor sweep too many times."); - } - } - - sensor (integer numDetected) { - current_awols = 0; -//llSay(0, "sensor saw avatar."); - handle_sensor(numDetected); - } - - link_message (integer sender_num, integer num, string str, key id) { - handle_link_message(str, id); - } - - touch_start (integer total_number) { - integer i; - for (i = 0; i < total_number; i++) { - if (llDetectedKey(i) == user) { - llDialog (user, resettext, RESET, CHANNEL); - return; - } - } - } - - listen (integer channel, string name, key id, string message) { - hear_voices(channel, name, id, message); - } - - dataserver (key query_id, string data) { - process_incoming_data(query_id, data); - } - - collision_start(integer total_number) - { - if (user == NULL_KEY) { -//llSay(0, "sending startup link message."); - handle_link_message("user", llDetectedKey(0)); - } - } - - timer () { - llDialog (user, DIALOG, dialog, CHANNEL); - llSetTimerEvent (0); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.txt b/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.txt new file mode 100755 index 00000000..aa0c30cd --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/logic_system_main_v1.8.txt @@ -0,0 +1,561 @@ + +// logic system master script +// copyright john jamison, imagilearning? +// created by xyz +// modified by fred huffhines / chris koeritz. +// +// + +// defaults... +vector TEXT_COLOR = <0.6, 0.84, 0.8>; // label color. +float RADARTIME = 10.0; // how frequently radar fires. +float RANGE = 50.0; // range of the sensor sweeps. +integer MAX_AVATAR_AWOLS = 5; + // number of times the avatar is allowed to be missed by sensor. + // we have seen some unreliability of sensors, so a single miss is not a definite problem. +list RESET = ["Restart", "CANCEL"]; // used in a menu someplace? +string Choicetimer = "2"; // how long they get to make their choice? + +// global variables... +integer current_awols; +key user = NULL_KEY; +key lquery = NULL_KEY; +list dialog; +string CHOICE1; +string CHOICE2; +string CHOICE3; +string CHOICE4; +string CHOICE5; +string CHOICE6; +string CHOICE7; +string CHOICE8; +string CHOICE1TEXT; +string CHOICE2TEXT; +string CHOICE3TEXT; +string CHOICE4TEXT; +string CHOICE5TEXT; +string CHOICE6TEXT; +string CHOICE7TEXT; +string CHOICE8TEXT; +integer CHOICE1POINTS; +integer CHOICE2POINTS; +integer CHOICE3POINTS; +integer CHOICE4POINTS; +integer CHOICE5POINTS; +integer CHOICE6POINTS; +integer CHOICE7POINTS; +integer CHOICE8POINTS; +integer TotalScore; +string DIALOG = " "; +string CurrentNoteCard; +string resettext = " "; +list CHOICE; +integer line = 0; +integer eof = 0; +integer CHANNEL; + +initialize() +{ + CHOICE = [ CHOICE1TEXT, CHOICE2TEXT, CHOICE3TEXT, CHOICE4TEXT ]; + llSetText("[System Ready]", TEXT_COLOR, 1); + eof = 0; +} + +// leave the current setup and completely restart the script. +reboot(string reason) +{ +llSay(0, "restarting now because " + reason); + llResetScript(); +} + +// starts looking for our registered user. +start_sensor_sweeps() +{ + llSensorRemove(); // clear any existing sensor. +//llSay(0, "sweeping for " + user + " aka " + llKey2Name(user)); + llSensorRepeat("", user, AGENT, RANGE, 2 * PI, RADARTIME); // look for our customer. +} + +// what this did before made no sense... +// but now it serves to reset the device if the avatar wandered off. +handle_sensor(integer numDetected) +{ + integer proceed = FALSE; + integer i; + for (i = 0; i < numDetected; i++) { + if (llDetectedKey(i) == user) proceed = TRUE; + } + if (proceed) return; // keep running like we were. + else reboot("we no longer saw our user here."); // reboot, since we don't see our user. +} + +// processes commands coming from other scripts or other parts of the object. +handle_link_message(string str, key id) +{ + if (str == "user") { + user = id; + llSetText ("System in use by " + llKey2Name (id), TEXT_COLOR, 1); + CurrentNoteCard = llGetObjectDesc(); + CHANNEL = llRound (llFrand (-394304)); + llListen (CHANNEL, "", NULL_KEY, ""); + start_sensor_sweeps(); + lquery = llGetNotecardLine (CurrentNoteCard, line); + } +} + +// handles notecard data as it is read. +process_incoming_data(key query_id, string data) +{ + list split_data = llParseString2List (data, [":"], []); + string cmd = llToLower(llList2String(split_data, 0)); + +//hmmm: terribly repetitive code here. clean up, shorten. + if (cmd == "choicetimer") { + Choicetimer = llList2String (split_data, 1); + } + if (cmd == "chat") { + llSay(0, llList2String (split_data, 1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "whisper") { + llWhisper(0, llList2String (split_data, 1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "givenotecard") { + llGiveInventory (user, llList2String (split_data, 1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "channelsay") { + llSay((integer) llList2String (split_data, 1), llList2String (split_data, 2)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "channelshout") { + llShout ((integer) llList2String (split_data, 1), + llList2String (split_data, 2)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "channelwhisper") { + llSay((integer) llList2String (split_data, 1), llList2String (split_data, 2)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "resettext") { + resettext = llList2String (split_data, 1); + + } + if (cmd == "end") { +/// CurrentNoteCard = llGetObjectDesc(); +/// line = 0; + reboot("notecard said to end processing."); + } + + if (cmd == "giveobject") { + llGiveInventory (user, llList2String (split_data, 1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } +///TALK TO VB AS THIS NEXT PART NEEDS A MEDIA RELAY FOR IT TO WORK + if (cmd == "videourl") { + if (llList2String (split_data, 3) != "") { + llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_URL, + llList2String (split_data, 1) + ":" + + llList2String (split_data, 2) + ":" + + llList2String (split_data, 3) + + llList2String (split_data, 4)]); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + else { + llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_URL, + llList2String (split_data, 1) + ":" + + llList2String (split_data, 2)]); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + //llSay(-840,llList2String(dat,1)); + //llSay(-848,llList2String(dat,1)); + } + if (cmd == "mediatexture") { + llParcelMediaCommandList ([PARCEL_MEDIA_COMMAND_TEXTURE, + (key) llList2String (split_data, 1)]); + //llSay(-849,llList2String(dat,1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "sleep") { + llSleep (llList2Float (split_data, 1)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "audiourl") { +llSay(0, "got to audio url"); + if (llList2String (split_data, 3) != "") { + llSetParcelMusicURL (llList2String (split_data, 1) + ":" + + llList2String (split_data, 2) + ":" + + llList2String (split_data, 3) + llList2String (split_data, 4)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + + else { + llSetParcelMusicURL (llList2String (split_data, 1) + ":" + + llList2String (split_data, 2)); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + //llSay(-840,llList2String(dat,1)); + } + //THIS IS OPTION A// + if (cmd == "weburl") { + llLoadURL (user, llList2String (split_data, 1), + llList2String (split_data, 2) + llList2String (split_data, + 3) + + llList2String (split_data, 4)); + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + + + if (cmd == "dialog") { + DIALOG = llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice1") { + CHOICE1TEXT = llList2String (split_data, 1); + CHOICE1 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + if (cmd == "choice2") { + CHOICE2TEXT = llList2String (split_data, 1); + CHOICE2 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice3") { + CHOICE3TEXT = llList2String (split_data, 1); + CHOICE3 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice4") { + CHOICE4TEXT = llList2String (split_data, 1); + CHOICE4 = llList2String (split_data, 2); + + dialog = dialog +[llList2String (split_data, 1)]; + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice5") { + CHOICE5TEXT = llList2String (split_data, 1); + CHOICE5 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + if (cmd == "choice6") { + CHOICE6TEXT = llList2String (split_data, 1); + CHOICE6 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + + if (cmd == "choice7") { + CHOICE7TEXT = llList2String (split_data, 1); + CHOICE7 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + + if (cmd == "choice8") { + CHOICE8TEXT = llList2String (split_data, 1); + CHOICE8 = llList2String (split_data, 2); + dialog = dialog +[llList2String (split_data, 1)]; + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + + if (cmd == "choice1points") { + CHOICE1POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + + } + + if (cmd == "choice2points") { + CHOICE2POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice3points") { + CHOICE3POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice4points") { + CHOICE4POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice5points") { + CHOICE5POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice6points") { + CHOICE6POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice7points") { + CHOICE7POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "choice8points") { + CHOICE8POINTS = (integer) llList2String (split_data, 1); + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "email") { + llEmail (llList2String (split_data, 1), + llKey2Name (user) + " Scored " + (string) TotalScore + + " On " + llGetObjectDesc (), + llKey2Name (user) + " Scored " + (string) TotalScore + + " On " + llGetObjectDesc () + "Score As Of " + + CurrentNoteCard); + + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (cmd == "imuser") { + llInstantMessage (user, llList2String (split_data, 1)); + } + + if (cmd == "im") { + llInstantMessage (llList2String (split_data, 1), llList2String (split_data, 2)); + } + if (cmd == "deadusertime") { + RADARTIME = (integer) llList2String (split_data, 1); + } + + if (cmd == "deadrange") { + RANGE = (integer) llList2String (split_data, 1); + start_sensor_sweeps(); + } + + if (cmd == "finalscore") { + llSay (0, + "You Scored " + (string) TotalScore + "/" + + llList2String (split_data, 1)); + } + if (cmd == "playsounduuid") { + llPreloadSound (llList2String (split_data, 1)); + llPlaySound (llList2String (split_data, 1), + (integer) llList2String (split_data, 2)); + } + + if (cmd == "debug") { + llSay (2147483647, + "System Debug Info follows " + "/n " + + (string) "key user = " + (string) user + + (string) " key lquery = " + (string) lquery + + (string) " integer DEADTIME = " + (string) RADARTIME + + "string CHOICE1 = " + CHOICE1 + "string CHOICE2 = " + + CHOICE2 + "string CHOICE3 = " + CHOICE3 + + "string CHOICE4 = " + CHOICE4 + "string CHOICE1TEXT = " + + CHOICE1TEXT + "string CHOICE2TEXT = " + CHOICE2TEXT + + "string CHOICE3TEXT= " + CHOICE3TEXT + + "string CHOICE4TEXT= " + CHOICE4TEXT + + "integer CHOICE1POINTS" + (string) CHOICE1POINTS + + "integer CHOICE2POINTS" + (string) CHOICE2POINTS + + "integer CHOICE3POINTS" + (string) CHOICE3POINTS + + "integer CHOICE4POINTS" + (string) CHOICE4POINTS + + "integer Choicetimer = " + (string) Choicetimer + + "integer TotalScore =" + (string) TotalScore + + "string DIOALOGE = " + DIALOG + + "string CurrentNoteCard = " + CurrentNoteCard + + "string resettext = " + resettext + + "list RESET = [Restart,CANCEL]" + "list CHOICE = " + + (string) CHOICE + "integer line = " + (string) line); + + } + + if (data == EOF) { + if (eof != 2 | eof == 1) { + eof = 2; + llSetTimerEvent ((float) Choicetimer); + } + } else { + line++; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } +} + +// process what the device hears spoken nearby. +hear_voices(integer channel, string name, key id, string message) +{ +//hmmm: bunkum. do this as a list. + if (message == CHOICE1TEXT) { + CurrentNoteCard = CHOICE1; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE1POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE2TEXT) { + CurrentNoteCard = CHOICE2; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE2POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE3TEXT) { + CurrentNoteCard = CHOICE3; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE3POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE4TEXT) { + CurrentNoteCard = CHOICE4; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE4POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE5TEXT) { + CurrentNoteCard = CHOICE5; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE5POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE6TEXT) { + CurrentNoteCard = CHOICE6; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE6POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE7TEXT) { + CurrentNoteCard = CHOICE7; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE7POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == CHOICE8TEXT) { + CurrentNoteCard = CHOICE8; + dialog =[]; + eof = 0; + line = 0; + TotalScore = TotalScore + CHOICE8POINTS; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } + if (message == "Restart") { + eof = 0; + line = 0; + lquery = llGetNotecardLine (CurrentNoteCard, line); + } +} + +////////////// + +// ensure stops running if kept in updater object. +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +// main state engine. +state real_default +{ + state_entry () { + initialize(); + } + + on_rez (integer i) { + reboot("object just rezzed."); + } + + no_sensor () { + current_awols++; +//llSay(0, "sensor missed avatar."); + if (current_awols > MAX_AVATAR_AWOLS) { + reboot("avatar was missed by sensor sweep too many times."); + } + } + + sensor (integer numDetected) { + current_awols = 0; +//llSay(0, "sensor saw avatar."); + handle_sensor(numDetected); + } + + link_message (integer sender_num, integer num, string str, key id) { + handle_link_message(str, id); + } + + touch_start (integer total_number) { + integer i; + for (i = 0; i < total_number; i++) { + if (llDetectedKey(i) == user) { + llDialog (user, resettext, RESET, CHANNEL); + return; + } + } + } + + listen (integer channel, string name, key id, string message) { + hear_voices(channel, name, id, message); + } + + dataserver (key query_id, string data) { + process_incoming_data(query_id, data); + } + + collision_start(integer total_number) + { + if (user == NULL_KEY) { +//llSay(0, "sending startup link message."); + handle_link_message("user", llDetectedKey(0)); + } + } + + timer () { + llDialog (user, DIALOG, dialog, CHANNEL); + llSetTimerEvent (0); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.lsl deleted file mode 100755 index c83303cb..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.lsl +++ /dev/null @@ -1,33 +0,0 @@ - -// Megaprim! (auxiliary script if your viewer doesn't support custom size megaprims yet) -// Fill in x, y, z with the values you need for your prim. They should be less or equal than 64. - -/////// -// defaults are not very mega-primish, and instead are nice for our huffotronic updaters. -// --fred huffhines. -/////// - -float x = .42; -float y = .42; -float z = .6; - -/* - -original author's note: - -Even if your viewer does not support yet the ability to create the new megas that are now available in the RC servers (the regions running the software for mesh, which you can check in Help: About in your viewer), a simple script, attached to this notice, will help you. - -Edit the script, change x, y, z with the values you want for the size, *up to 64 meters*, save it, and drop it into your prim. The script will do the work for you. These new megas will work in ANY sim when your rez them. Spread the love! - -Auryn Beorn - -*/ - -default -{ - state_entry() - { - llSetPrimitiveParams([PRIM_SIZE, ]); -//nooo... we don't always want this. llRemoveInventory(llGetScriptName()); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.txt new file mode 100755 index 00000000..c83303cb --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/megaprim_v0.3.txt @@ -0,0 +1,33 @@ + +// Megaprim! (auxiliary script if your viewer doesn't support custom size megaprims yet) +// Fill in x, y, z with the values you need for your prim. They should be less or equal than 64. + +/////// +// defaults are not very mega-primish, and instead are nice for our huffotronic updaters. +// --fred huffhines. +/////// + +float x = .42; +float y = .42; +float z = .6; + +/* + +original author's note: + +Even if your viewer does not support yet the ability to create the new megas that are now available in the RC servers (the regions running the software for mesh, which you can check in Help: About in your viewer), a simple script, attached to this notice, will help you. + +Edit the script, change x, y, z with the values you want for the size, *up to 64 meters*, save it, and drop it into your prim. The script will do the work for you. These new megas will work in ANY sim when your rez them. Spread the love! + +Auryn Beorn + +*/ + +default +{ + state_entry() + { + llSetPrimitiveParams([PRIM_SIZE, ]); +//nooo... we don't always want this. llRemoveInventory(llGetScriptName()); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.lsl deleted file mode 100755 index 52b22916..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.lsl +++ /dev/null @@ -1,634 +0,0 @@ - -// huffware script: mu tester, by fred huffhines. -// -// a script that puts the set comparator library through its paces -// while providing a textual method for creating and comparing sets. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// these are the commands a user can say: -string DEFINE_WORD = "create"; -string DELETE_WORD = "delete"; -string LIST_WORD = "list"; -string GET_WORD = "get"; -string ADD_TO_WORD = "add"; -string CUT_FROM_WORD = "cut"; -string INTERSECT_WORD = "intersect"; -string UNION_WORD = "union"; -string DIFFERENCE_WORD = "differ"; -string MU_WORD = "mu"; -string CLEAR_ALL_WORD = "clearall"; -string RESET_WORD = "reset!"; - -integer NOISY_OY = FALSE; - // produces more chatty logging when set to TRUE. this is adjusted during - // startup to be off. - -// requires set comparator 2.8 or better. -// API for set operations. -////////////// -integer SET_COMPARATOR_HUFFWARE_ID = 10020; - // a unique ID within the huffware system for this script. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string DEFINE_SET_CMD = "#def-set"; - // adds a new set or replaces existing one with same name. first parm is name of set, - // second parm is a wrapped list of elements that should be in the set. return value - // is a boolean for success. -string REMOVE_SET_CMD = "#rm-set"; - // trashes a named set. first parm is the name. returns a bool for success. -string ADD_ELEMENTS_CMD = "#add-elem"; - // adds more elements to an existing set. first parm is the name, second is a wrapped - // list of new elements. set must already exist. returns a bool for success. -string CUT_ELEMENTS_CMD = "#cut-elem"; - // removes a set of elements from an existing set. first parm is set name, second is - // wrapped list of elements to remove. set must already exist. returns bool. -string INTERSECT_CMD = "#inter-set"; - // reports the set of elements in the intersection of two sets. first and second parm - // are the set names. returns a wrapped list of elements that are common members of both sets. -string UNION_CMD = "#union-set"; - // returns the union of two named sets. results sent similar to intersection. -string DIFFERENCE_CMD = "#diff-set"; - // returns the difference of set A (parm 1) minus set B (parm 2). results are similar - // to intersection. -string WHAT_MU_CMD = "#mu-set"; - // returns one of the possibility values below to describe the relationship between - // two sets. -string GET_SET_CMD = "#get-set"; - // retrieves the contents of the set named in first parameter. -string LIST_SET_NAMES_CMD = "#whichunz"; - // retrieves the list of set names that exist. -string CLEAR_ALL_CMD = "#clearall"; - // throws out all set definitions. -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// requires noteworthy library v8.4 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or "bad_notecard" if none was found) and - // as subsequent elements an embedded list that was read from the notecard. this - // necessarily limits the size of the notecards that we can read and return. -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string BUSY_READING_INDICATOR = "busy_already"; - // this return value indicates that the script is already in use by some other script. - // the calling script should try again later. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// -////////////// - -string MU_SIGNATURE = "#mu"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -// global variables... - -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -show_instructions() -{ - string c = ", "; // speed of light. - string help_text = "\nThis object will operate on a collection of sets and understands the following commands:\n"; - help_text += " " + DEFINE_WORD + c + DELETE_WORD + c + CLEAR_ALL_WORD + c + ADD_TO_WORD + c - + CUT_FROM_WORD + c + INTERSECT_WORD + c + UNION_WORD + c + DIFFERENCE_WORD + c + GET_WORD + c - + LIST_WORD + c + RESET_WORD + c + "and " + MU_WORD + ".\n"; - help_text += "Generally each command takes a set name or two, and sometimes a list of items.\n"; - help_text += "If an item or set name has a space in it, surround it in quote characters.\n"; - help_text += "For Example:\n"; - help_text += " " + DEFINE_WORD + " \"jed yo\" upsa dooba gorp : create a set named \"jed yo\" with three items.\n"; - help_text += " " + INTERSECT_WORD + " jed pfaltzgraff : returns the intersection of the two sets.\n"; - help_text += " " + ADD_TO_WORD + " foon a \"b c\" d e : adds four elements to the set \"foon\".\n"; - help_text += "(Free Memory=" + (string)llGetFreeMemory() + ")\n"; - llSay(0, help_text); -} - -// makes a request of the set comparator. -send_command(string msg, list parms) -{ llMessageLinked(LINK_THIS, SET_COMPARATOR_HUFFWARE_ID, msg, wrap_parameters(parms)); } - -// processes verbal commands. -hearing_some_voices(integer chan, string name, key id, string msg_in) -{ - // clean up the string before starting. - msg_in = llStringTrim(msg_in, STRING_TRIM); // remove leading and trailing spaces. - msg_in = compress_spaces(msg_in); // turn multiple spaces into a single one. - // separate out the separate words in what was said. - list members = parse_quoted_strings(msg_in); -//log_it("got membs as: " + dump_list(members)); - // break out the first few to make the below cases easier. - string first_word = llList2String(members, 0); - string second_word = llList2String(members, 1); - string third_word = llList2String(members, 2); - - if (first_word == DEFINE_WORD) { - send_command(DEFINE_SET_CMD, llDeleteSubList(members, 0, 0)); - } else if (first_word == DELETE_WORD) { - send_command(REMOVE_SET_CMD, [ second_word ]); - } else if (first_word == GET_WORD) { - send_command(GET_SET_CMD, [ second_word ]); - } else if (first_word == LIST_WORD) { - send_command(LIST_SET_NAMES_CMD, []); - } else if (first_word == ADD_TO_WORD) { - send_command(ADD_ELEMENTS_CMD, llDeleteSubList(members, 0, 0)); - } else if (first_word == CUT_FROM_WORD) { - send_command(CUT_ELEMENTS_CMD, llDeleteSubList(members, 0, 0)); - } else if (first_word == INTERSECT_WORD) { - send_command(INTERSECT_CMD, [ second_word, third_word ]); - } else if (first_word == UNION_WORD) { - send_command(UNION_CMD, [ second_word, third_word ]); - } else if (first_word == DIFFERENCE_WORD) { - send_command(DIFFERENCE_CMD, [ second_word, third_word ]); - } else if (first_word == MU_WORD) { - send_command(WHAT_MU_CMD, [ second_word, third_word ]); - } else if (first_word == CLEAR_ALL_WORD) { - send_command(CLEAR_ALL_CMD, []); - } else if (first_word == RESET_WORD) { - if (id != llGetOwner()) { - llSay(0, "Sorry, only the owner is allowed to reset this object."); - } else { - // tell the set manager to drop any contents also. - send_command(CLEAR_ALL_CMD, []); - llResetScript(); - } - } - // we cannot have a catch-all here for if we didn't understand; that will always be - // getting hit whenever anyone talks nearby. -} - -handle_link_message(integer sender, integer huff_id, string msg, key id) -{ - if (huff_id != SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE) { - handle_notecard_message(sender, huff_id, msg, id); - return; - } - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string to_show; // what to tell the user. - if (llGetListLength(parms) == 1) { - // mono-syllabic responses. - string arf = llList2String(parms, 0); - if (arf == "0") { - to_show = "request failed"; - } else if (arf == "1") { - to_show = "successful request"; - } else if (msg != WHAT_MU_CMD) { - // don't know this one; assume it's a list. - to_show = "[ " + arf + " ]"; - } else { - // otherwise we assume it's a well-known answer we should just emit. - to_show = arf; - } - } else { - to_show = "[ " + dump_list(parms) + " ]"; - } - if (NOISY_OY) log_it("reply says: " + to_show); -} - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - log_it("reading configuration..."); - global_notecard_name = ""; // reset any previous card. - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([MU_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from the noteworthy library. -handle_notecard_message(integer which, integer num, string msg, key id) -{ - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) - return; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return; // oops, this isn't for us. -//log_it("read more from: " + notecard_name); - if (notecard_name == NOTECARD_READ_CONTINUATION) { - // just save these items for now. - global_config_list += llList2List(parms, 2, -1); - } else if (notecard_name != BAD_NOTECARD_INDICATOR) { - // a valid notecard has been found. - global_notecard_name = notecard_name; // record its name for later use. - global_config_index = 0; // we are starting over in the config list. - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - process_ini_config(); - log_it("now configured."); - llSetTimerEvent(6); // pause a bit before turning chat back on. - } else { - // we hated the notecards we found, or there were none. - log_it("There seem to be no notecards with a first line of '" - + MU_SIGNATURE - + "', so no additional sets are defined."); - } -} - -/////////////// - -// eats a file with section names in square brackets, where every line defines a set element. -process_ini_config() -{ - integer indy; - integer count = llGetListLength(global_config_list); - string section_name; - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - section_name = llGetSubString(line, 1, -2); - if (NOISY_OY) log_it("set '" + section_name + "' is being defined."); - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - if (NOISY_OY) log_it(line); - hearing_some_voices(0, llGetScriptName(), llGetOwner(), line); - indy = sec_indy; // track that we've passed this line. - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -////////////// -// from hufflets: - -integer debug_num = 0; -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. -// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. - llSay(0, to_say); -} - -// the string processing methods are not case sensitive. - -// returns TRUE if the "pattern" is found in the "full_string". -integer matches_substring(string full_string, string pattern) -{ return (find_substring(full_string, pattern) >= 0); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "\"" + next_line + "\""; - } - text += next_line; - if (i < len - 1) text += " "; - } - return text; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ llStringTrim(x, STRING_TRIM), llStringTrim(y, STRING_TRIM) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// extracts space separated elements from a string, and honors quoting of either -// variety as long as the quotes come in pairs. this enables the inclusion of -// spaces in the elements of the set. note that this function requires a well-formed -// string where there are no multiple space characters in a row. -list parse_quoted_strings(string to_parse) -{ - list to_return; // will pile up what we find in the string. - integer quoting = FALSE; // are we inside quotes? - string curr_quote = ""; // what is current quote char, if any? - string accum; // accumulates parts of the current element. - // loop over the string and apply our rules. - integer i; - for (i = 0; i < llStringLength(to_parse); i++) { - string c = llGetSubString(to_parse, i, i); - if (!quoting && (c == " ")) { - // this space marks the end of a word. - if (llStringLength(accum) > 0) { -//log_it("space adding to set: " + accum); - to_return += [ accum ]; - accum = ""; - } - } else if (quoting && (c == curr_quote)) { - quoting = FALSE; - } else if (!quoting && ( (c == "'") || (c == "\"") ) ) { - // we've started into quoting mode. - quoting = TRUE; - curr_quote = c; - } else { - // if no condition applies, just add this to the accumulator. - accum += c; - } - } - // add the last thing we accumulated. - if (llStringLength(accum) > 0) { -//log_it("last add to set: " + accum); - to_return += [ accum ]; - } - return to_return; -} - -// returns the portion of the list between start and end, but only if they are -// valid compared with the list length. an attempt to use negative start or -// end values also returns a blank list. -list chop_list(list to_chop, integer start, integer end) -{ - integer last_len = llGetListLength(to_chop) - 1; - if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; - return llList2List(to_chop, start, end); -} - -// takes any redundant space characters out of the string. -string compress_spaces(string s) -{ - string to_return; - integer in_space = FALSE; - integer i; - for (i = 0; i < llStringLength(s); i++) { - string chunk = llGetSubString(s, i, i); - if (chunk == " ") { - if (in_space) { - // we're have already seen a space. don't keep this too. - //continue; no such keyword in lsl. - } else { - in_space = TRUE; - to_return += chunk; - } - } else { - // the current character was not a space, so just add it. - in_space = FALSE; - to_return += chunk; - } - } - return to_return; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// end from hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - auto_retire(); - NOISY_OY = FALSE; - // reset our relevant variables. - global_notecard_name = ""; - global_config_list = []; - global_config_index = 0; - // request that the noteworthy library start looking for our notecard. - request_configuration(); - // listen for commands from people. - llListen(0, "", NULL_KEY, ""); - NOISY_OY = FALSE; - } - - state_exit() { llSetTimerEvent(0.0); } - - touch_start(integer total_number) { show_instructions(); } - - listen(integer chan, string name, key id, string msg) - { hearing_some_voices(chan, name, id, msg); } - - link_message(integer sender, integer num, string msg, key id) { - if ( (num != SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE) - && (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) ) - return; // not for us. - handle_link_message(sender, num, msg, id); - } - - timer() { - NOISY_OY = TRUE; // assume we can now chat with the user. config is done hopefully. - llSetTimerEvent(0.0); // turn off timer now. - } - - on_rez(integer parm) { show_instructions(); state rerun; } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.txt new file mode 100755 index 00000000..52b22916 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/mu_tester_v6.0.txt @@ -0,0 +1,634 @@ + +// huffware script: mu tester, by fred huffhines. +// +// a script that puts the set comparator library through its paces +// while providing a textual method for creating and comparing sets. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// these are the commands a user can say: +string DEFINE_WORD = "create"; +string DELETE_WORD = "delete"; +string LIST_WORD = "list"; +string GET_WORD = "get"; +string ADD_TO_WORD = "add"; +string CUT_FROM_WORD = "cut"; +string INTERSECT_WORD = "intersect"; +string UNION_WORD = "union"; +string DIFFERENCE_WORD = "differ"; +string MU_WORD = "mu"; +string CLEAR_ALL_WORD = "clearall"; +string RESET_WORD = "reset!"; + +integer NOISY_OY = FALSE; + // produces more chatty logging when set to TRUE. this is adjusted during + // startup to be off. + +// requires set comparator 2.8 or better. +// API for set operations. +////////////// +integer SET_COMPARATOR_HUFFWARE_ID = 10020; + // a unique ID within the huffware system for this script. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string DEFINE_SET_CMD = "#def-set"; + // adds a new set or replaces existing one with same name. first parm is name of set, + // second parm is a wrapped list of elements that should be in the set. return value + // is a boolean for success. +string REMOVE_SET_CMD = "#rm-set"; + // trashes a named set. first parm is the name. returns a bool for success. +string ADD_ELEMENTS_CMD = "#add-elem"; + // adds more elements to an existing set. first parm is the name, second is a wrapped + // list of new elements. set must already exist. returns a bool for success. +string CUT_ELEMENTS_CMD = "#cut-elem"; + // removes a set of elements from an existing set. first parm is set name, second is + // wrapped list of elements to remove. set must already exist. returns bool. +string INTERSECT_CMD = "#inter-set"; + // reports the set of elements in the intersection of two sets. first and second parm + // are the set names. returns a wrapped list of elements that are common members of both sets. +string UNION_CMD = "#union-set"; + // returns the union of two named sets. results sent similar to intersection. +string DIFFERENCE_CMD = "#diff-set"; + // returns the difference of set A (parm 1) minus set B (parm 2). results are similar + // to intersection. +string WHAT_MU_CMD = "#mu-set"; + // returns one of the possibility values below to describe the relationship between + // two sets. +string GET_SET_CMD = "#get-set"; + // retrieves the contents of the set named in first parameter. +string LIST_SET_NAMES_CMD = "#whichunz"; + // retrieves the list of set names that exist. +string CLEAR_ALL_CMD = "#clearall"; + // throws out all set definitions. +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// requires noteworthy library v8.4 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or "bad_notecard" if none was found) and + // as subsequent elements an embedded list that was read from the notecard. this + // necessarily limits the size of the notecards that we can read and return. +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string BUSY_READING_INDICATOR = "busy_already"; + // this return value indicates that the script is already in use by some other script. + // the calling script should try again later. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// +////////////// + +string MU_SIGNATURE = "#mu"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +// global variables... + +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +show_instructions() +{ + string c = ", "; // speed of light. + string help_text = "\nThis object will operate on a collection of sets and understands the following commands:\n"; + help_text += " " + DEFINE_WORD + c + DELETE_WORD + c + CLEAR_ALL_WORD + c + ADD_TO_WORD + c + + CUT_FROM_WORD + c + INTERSECT_WORD + c + UNION_WORD + c + DIFFERENCE_WORD + c + GET_WORD + c + + LIST_WORD + c + RESET_WORD + c + "and " + MU_WORD + ".\n"; + help_text += "Generally each command takes a set name or two, and sometimes a list of items.\n"; + help_text += "If an item or set name has a space in it, surround it in quote characters.\n"; + help_text += "For Example:\n"; + help_text += " " + DEFINE_WORD + " \"jed yo\" upsa dooba gorp : create a set named \"jed yo\" with three items.\n"; + help_text += " " + INTERSECT_WORD + " jed pfaltzgraff : returns the intersection of the two sets.\n"; + help_text += " " + ADD_TO_WORD + " foon a \"b c\" d e : adds four elements to the set \"foon\".\n"; + help_text += "(Free Memory=" + (string)llGetFreeMemory() + ")\n"; + llSay(0, help_text); +} + +// makes a request of the set comparator. +send_command(string msg, list parms) +{ llMessageLinked(LINK_THIS, SET_COMPARATOR_HUFFWARE_ID, msg, wrap_parameters(parms)); } + +// processes verbal commands. +hearing_some_voices(integer chan, string name, key id, string msg_in) +{ + // clean up the string before starting. + msg_in = llStringTrim(msg_in, STRING_TRIM); // remove leading and trailing spaces. + msg_in = compress_spaces(msg_in); // turn multiple spaces into a single one. + // separate out the separate words in what was said. + list members = parse_quoted_strings(msg_in); +//log_it("got membs as: " + dump_list(members)); + // break out the first few to make the below cases easier. + string first_word = llList2String(members, 0); + string second_word = llList2String(members, 1); + string third_word = llList2String(members, 2); + + if (first_word == DEFINE_WORD) { + send_command(DEFINE_SET_CMD, llDeleteSubList(members, 0, 0)); + } else if (first_word == DELETE_WORD) { + send_command(REMOVE_SET_CMD, [ second_word ]); + } else if (first_word == GET_WORD) { + send_command(GET_SET_CMD, [ second_word ]); + } else if (first_word == LIST_WORD) { + send_command(LIST_SET_NAMES_CMD, []); + } else if (first_word == ADD_TO_WORD) { + send_command(ADD_ELEMENTS_CMD, llDeleteSubList(members, 0, 0)); + } else if (first_word == CUT_FROM_WORD) { + send_command(CUT_ELEMENTS_CMD, llDeleteSubList(members, 0, 0)); + } else if (first_word == INTERSECT_WORD) { + send_command(INTERSECT_CMD, [ second_word, third_word ]); + } else if (first_word == UNION_WORD) { + send_command(UNION_CMD, [ second_word, third_word ]); + } else if (first_word == DIFFERENCE_WORD) { + send_command(DIFFERENCE_CMD, [ second_word, third_word ]); + } else if (first_word == MU_WORD) { + send_command(WHAT_MU_CMD, [ second_word, third_word ]); + } else if (first_word == CLEAR_ALL_WORD) { + send_command(CLEAR_ALL_CMD, []); + } else if (first_word == RESET_WORD) { + if (id != llGetOwner()) { + llSay(0, "Sorry, only the owner is allowed to reset this object."); + } else { + // tell the set manager to drop any contents also. + send_command(CLEAR_ALL_CMD, []); + llResetScript(); + } + } + // we cannot have a catch-all here for if we didn't understand; that will always be + // getting hit whenever anyone talks nearby. +} + +handle_link_message(integer sender, integer huff_id, string msg, key id) +{ + if (huff_id != SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE) { + handle_notecard_message(sender, huff_id, msg, id); + return; + } + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string to_show; // what to tell the user. + if (llGetListLength(parms) == 1) { + // mono-syllabic responses. + string arf = llList2String(parms, 0); + if (arf == "0") { + to_show = "request failed"; + } else if (arf == "1") { + to_show = "successful request"; + } else if (msg != WHAT_MU_CMD) { + // don't know this one; assume it's a list. + to_show = "[ " + arf + " ]"; + } else { + // otherwise we assume it's a well-known answer we should just emit. + to_show = arf; + } + } else { + to_show = "[ " + dump_list(parms) + " ]"; + } + if (NOISY_OY) log_it("reply says: " + to_show); +} + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + log_it("reading configuration..."); + global_notecard_name = ""; // reset any previous card. + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([MU_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from the noteworthy library. +handle_notecard_message(integer which, integer num, string msg, key id) +{ + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) + return; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return; // oops, this isn't for us. +//log_it("read more from: " + notecard_name); + if (notecard_name == NOTECARD_READ_CONTINUATION) { + // just save these items for now. + global_config_list += llList2List(parms, 2, -1); + } else if (notecard_name != BAD_NOTECARD_INDICATOR) { + // a valid notecard has been found. + global_notecard_name = notecard_name; // record its name for later use. + global_config_index = 0; // we are starting over in the config list. + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + process_ini_config(); + log_it("now configured."); + llSetTimerEvent(6); // pause a bit before turning chat back on. + } else { + // we hated the notecards we found, or there were none. + log_it("There seem to be no notecards with a first line of '" + + MU_SIGNATURE + + "', so no additional sets are defined."); + } +} + +/////////////// + +// eats a file with section names in square brackets, where every line defines a set element. +process_ini_config() +{ + integer indy; + integer count = llGetListLength(global_config_list); + string section_name; + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + section_name = llGetSubString(line, 1, -2); + if (NOISY_OY) log_it("set '" + section_name + "' is being defined."); + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + if (NOISY_OY) log_it(line); + hearing_some_voices(0, llGetScriptName(), llGetOwner(), line); + indy = sec_indy; // track that we've passed this line. + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +////////////// +// from hufflets: + +integer debug_num = 0; +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. +// llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. + llSay(0, to_say); +} + +// the string processing methods are not case sensitive. + +// returns TRUE if the "pattern" is found in the "full_string". +integer matches_substring(string full_string, string pattern) +{ return (find_substring(full_string, pattern) >= 0); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "\"" + next_line + "\""; + } + text += next_line; + if (i < len - 1) text += " "; + } + return text; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ llStringTrim(x, STRING_TRIM), llStringTrim(y, STRING_TRIM) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// extracts space separated elements from a string, and honors quoting of either +// variety as long as the quotes come in pairs. this enables the inclusion of +// spaces in the elements of the set. note that this function requires a well-formed +// string where there are no multiple space characters in a row. +list parse_quoted_strings(string to_parse) +{ + list to_return; // will pile up what we find in the string. + integer quoting = FALSE; // are we inside quotes? + string curr_quote = ""; // what is current quote char, if any? + string accum; // accumulates parts of the current element. + // loop over the string and apply our rules. + integer i; + for (i = 0; i < llStringLength(to_parse); i++) { + string c = llGetSubString(to_parse, i, i); + if (!quoting && (c == " ")) { + // this space marks the end of a word. + if (llStringLength(accum) > 0) { +//log_it("space adding to set: " + accum); + to_return += [ accum ]; + accum = ""; + } + } else if (quoting && (c == curr_quote)) { + quoting = FALSE; + } else if (!quoting && ( (c == "'") || (c == "\"") ) ) { + // we've started into quoting mode. + quoting = TRUE; + curr_quote = c; + } else { + // if no condition applies, just add this to the accumulator. + accum += c; + } + } + // add the last thing we accumulated. + if (llStringLength(accum) > 0) { +//log_it("last add to set: " + accum); + to_return += [ accum ]; + } + return to_return; +} + +// returns the portion of the list between start and end, but only if they are +// valid compared with the list length. an attempt to use negative start or +// end values also returns a blank list. +list chop_list(list to_chop, integer start, integer end) +{ + integer last_len = llGetListLength(to_chop) - 1; + if ( (start < 0) || (end < 0) || (start > last_len) || (end > last_len) ) return []; + return llList2List(to_chop, start, end); +} + +// takes any redundant space characters out of the string. +string compress_spaces(string s) +{ + string to_return; + integer in_space = FALSE; + integer i; + for (i = 0; i < llStringLength(s); i++) { + string chunk = llGetSubString(s, i, i); + if (chunk == " ") { + if (in_space) { + // we're have already seen a space. don't keep this too. + //continue; no such keyword in lsl. + } else { + in_space = TRUE; + to_return += chunk; + } + } else { + // the current character was not a space, so just add it. + in_space = FALSE; + to_return += chunk; + } + } + return to_return; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// end from hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + auto_retire(); + NOISY_OY = FALSE; + // reset our relevant variables. + global_notecard_name = ""; + global_config_list = []; + global_config_index = 0; + // request that the noteworthy library start looking for our notecard. + request_configuration(); + // listen for commands from people. + llListen(0, "", NULL_KEY, ""); + NOISY_OY = FALSE; + } + + state_exit() { llSetTimerEvent(0.0); } + + touch_start(integer total_number) { show_instructions(); } + + listen(integer chan, string name, key id, string msg) + { hearing_some_voices(chan, name, id, msg); } + + link_message(integer sender, integer num, string msg, key id) { + if ( (num != SET_COMPARATOR_HUFFWARE_ID + REPLY_DISTANCE) + && (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) ) + return; // not for us. + handle_link_message(sender, num, msg, id); + } + + timer() { + NOISY_OY = TRUE; // assume we can now chat with the user. config is done hopefully. + llSetTimerEvent(0.0); // turn off timer now. + } + + on_rez(integer parm) { show_instructions(); state rerun; } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.lsl deleted file mode 100755 index 485b57fd..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.lsl +++ /dev/null @@ -1,137 +0,0 @@ - -// huffware script: no sitting on vendor, by fred huffhines. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// this message will be displayed when someone sits on the vendor. -string AVATAR_MESSAGE = "You cannot sit here; I am a vendor, not a chair. Please touch me for a notecard, or pay me to purchase the product. Thanks!"; - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - llSitTarget(ZERO_VECTOR, ZERO_ROTATION); - } - - changed(integer change) - { - key id = llAvatarOnSitTarget(); - if (change & CHANGED_LINK) { - if (id != NULL_KEY) { - llUnSit(id); - llDialog(id, AVATAR_MESSAGE, [], -981238); - // we don't listen for the response. - } - } - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.txt new file mode 100755 index 00000000..485b57fd --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/no_sitting_on_vendor_v1.0.txt @@ -0,0 +1,137 @@ + +// huffware script: no sitting on vendor, by fred huffhines. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// this message will be displayed when someone sits on the vendor. +string AVATAR_MESSAGE = "You cannot sit here; I am a vendor, not a chair. Please touch me for a notecard, or pay me to purchase the product. Thanks!"; + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + llSitTarget(ZERO_VECTOR, ZERO_ROTATION); + } + + changed(integer change) + { + key id = llAvatarOnSitTarget(); + if (change & CHANGED_LINK) { + if (id != NULL_KEY) { + llUnSit(id); + llDialog(id, AVATAR_MESSAGE, [], -981238); + // we don't listen for the response. + } + } + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.lsl b/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.lsl deleted file mode 100755 index f955b64b..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.lsl +++ /dev/null @@ -1,324 +0,0 @@ - -// huffware script: noteworthy example usage, by fred huffhines -// -// shows how to use the noteworthy script as a configuration helper. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -string EXAMPLE_NOTEWORTHY_SIGNATURE = "#example_noteworthy"; - // the notecard must begin with this as its first line for it to be - // recognized as our configuration card. - -// global variables... - -string global_notecard_name; // name of our notecard in the object's inventory. -integer response_code; // set to uniquely identify the notecard read in progress. -list global_config_list; // a collection of configuration parameters from our notecard. -integer global_config_index; // allows wrap-around feature, which we don't use here. - -// requires noteworthy library v8.3 or better. -////////////// -// do not redefine these constants. -integer NOTEWORTHY_HUFFWARE_ID = 10010; - // the unique id within the huffware system for the noteworthy script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string BAD_NOTECARD_INDICATOR = "bad_notecard"; - // indicates that the notecard reading process has failed to find an appropriate one. -string BUSY_READING_INDICATOR = "busy_already"; - // this return value indicates that the script is already in use by some other script. - // the calling script should try again later. -string NOTECARD_READ_CONTINUATION = "continue!"; - // returned as first parameter if there is still more data to handle. -// commands available via the noteworthy library: -string READ_NOTECARD_COMMAND = "#read_note#"; - // command used to tell the script to read notecards. needs a signature to find - // in the card as the first parameter, and a randomly generated response code for - // the second parameter. the response code is used to uniquely identify a set of - // pending notecard readings (hopefully). the signature can be empty or missing. - // the results will be fired back as the string value returned, which will have - // as first element the notecard's name (or "bad_notecard" if none was found) and - // as subsequent elements an embedded list that was read from the notecard. this - // necessarily limits the size of the notecards that we can read and return. -// -////////////// -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } -////////////// - -// this function fires off a request to the noteworthy library via a link message. -// noteworthy will look for a notecard with our particular signature in it and -// if it finds one, it will read the configuration therein. an empty string is -// returned if noteworthy couldn't find anything. -request_configuration() -{ - global_notecard_name = ""; // reset any previous card. - // try to find a notecard with our configuration. - response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); - string parms_sent = wrap_parameters([EXAMPLE_NOTEWORTHY_SIGNATURE, response_code]); - llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, - parms_sent); -} - -// processes link messages received from the noteworthy library. -handle_link_message(integer which, integer num, string msg, key id) -{ - if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != READ_NOTECARD_COMMAND) ) - return; // not for us. - // process the result of reading the notecard. - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string notecard_name = llList2String(parms, 0); - integer response_for = llList2Integer(parms, 1); - if (response_for != response_code) return; // oops, this isn't for us. - if (notecard_name == BAD_NOTECARD_INDICATOR) { - // we hated the notecards we found, or there were none. - log_it("We apologize; there seem to be no notecards with a first line of '" - + EXAMPLE_NOTEWORTHY_SIGNATURE - + "'. We can't read any configuration until that situation improves."); - } else { - // snag all but the first two elements for our config now. - global_config_list += llList2List(parms, 2, -1); - // make sure we shouldn't keep going. - if (notecard_name != NOTECARD_READ_CONTINUATION) { - // a valid notecard has been found. - global_notecard_name = notecard_name; // record its name for later use. - global_config_index = 0; // we are starting over in the config list. - // now echo the card we received... - log_it("read notecard \"" + global_notecard_name + "\":"); - integer lines_to_say = llGetListLength(global_config_list); - if (lines_to_say > 8) - lines_to_say = 8; // limit how much text is spoken. - integer indy; - for (indy = 0; indy < lines_to_say; indy++) - log_it("line #" + (string)(indy + 1) + ": " + llList2String(global_config_list, indy)); - if (lines_to_say != llGetListLength(global_config_list)) - log_it("...and so forth...."); - // and process the file as a set of definitions. - process_ini_config(); - } - } -} - -/////////////// - -// consumes the notecard in a very application specific way to retrieve our configuration items. -// the example script only looks for two variables: name and description. if those are found in -// the sample card, then they are proudly shown. -parse_variable_definition(string to_parse) -{ -// string content; // filled after finding a variable name. -// if ( (content = get_variable_value(to_parse, "name")) != "") -// log_it("** got a name of '" + content + "'"); -// else if ( (content = get_variable_value(to_parse, "description")) != "") -// log_it("** got a description of '" + content + "'"); -} - -initialize() -{ - // reset our relevant variables. - global_notecard_name = ""; - global_config_list = []; - global_config_index = 0; - - // announce that we're open for business. - log_it("example noteworthy usage is started, free mem=" + (string)llGetFreeMemory()); - - // request that the noteworthy library start looking for our notecard. - request_configuration(); -} - -////////////// -// from hufflets... -// - -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// locates the string "text" in the list to "search_in". -integer find_in_list(list search_in, string text) -{ - integer len = llGetListLength(search_in); - integer i; - for (i = 0; i < len; i++) { - if (llList2String(search_in, i) == text) - return i; - } - return -1; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return (llSubStringIndex(compare_with, prefix) == 0); } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -// strips the spaces off of the beginning and end of a string. -string strip_spaces(string to_strip) -{ - // clean out initial spaces. - while (llGetSubString(to_strip, 0, 0) == " ") - to_strip = llDeleteSubString(to_strip, 0, 0); - // clean out ending spaces. - while (llGetSubString(to_strip, -1, -1) == " ") - to_strip = llDeleteSubString(to_strip, -1, -1); - return to_strip; -} - -// parses a variable definition to find the name of the variable and its value. -// this returns two strings [X, Y], if "to_split" is in the form X=Y. -list separate_variable_definition(string to_split) -{ - integer equals_indy = llSubStringIndex(to_split, "="); - // we don't support missing an equals sign, and we don't support it as the first character. - if (equals_indy <= 0) return []; // no match. - string x = llGetSubString(to_split, 0, equals_indy - 1); - string y = llGetSubString(to_split, equals_indy + 1, -1); - to_split = ""; // save space. - return [ strip_spaces(x), strip_spaces(y) ]; -} - -// returns a non-empty string if "to_check" defines a value for "variable_name". -// this must be in the form "X=Y", where X is the variable_name and Y is the value. -string get_variable_value(string to_check, string variable_name) -{ - list x_y = separate_variable_definition(to_check); - if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. - if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. - return llList2String(x_y, 1); // a match! -} - -// examines all entries that we got from the notecard to see if any contain definitions. -// this is basically an INI file reader, but it uses a list instead of a file. -// ini files provide a format with multiple sections of config information, like so: -// [section_1] -// name1=value1 -// name2=value2 ...etc... -// [section_2] -// name1=value1 ...etc... -process_ini_config() -{ - log_it("scanning notecard for variable definitions..."); - integer indy; - integer count = llGetListLength(global_config_list); - string section_name; // set later if we see one. - - // iterate across the items in our configuration to look for ones that are not done yet. - for (indy = global_config_index; indy < count; indy++) { - string line = llList2String(global_config_list, indy); - // search for a section beginning. - if (llGetSubString(line, 0, 0) == "[") { - // we found the start of a section name. now read the contents. - indy++; // skip section line. - section_name = llGetSubString(line, 1, -2); - log_it("reading section: " + section_name); - } - integer sec_indy; - for (sec_indy = indy; sec_indy < count; sec_indy++) { - // read the lines in the section. - line = llList2String(global_config_list, sec_indy); - if (llGetSubString(line, 0, 0) != "[") { - // try to interpret this line as a variable setting. this is just - // one example of a way to handle the config file; one might instead - // want to do something below once a whole section is read. - parse_variable_definition(line); - indy = sec_indy; // track that we've passed this line. - } else { - // we're at the beginning of a new section now, so start processing its - // configuration in the outer loop. - indy = sec_indy - 1; // set indy to proper beginning of section. - global_config_index = indy; // remember where we had read to. - sec_indy = count + 3; // skip remainder of inner loop. - } - } - } - - global_config_index = 0; // reset outer position if want to re-read. -} - -// locates the item with "name_to_find" in the inventory items with the "type". -// a value from 0 to N-1 is returned if it's found, where N is the number of -// items in the inventory. -integer find_in_inventory(string name_to_find, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer inv; - for (inv = 0; inv < num_inv; inv++) { - if (llGetInventoryName(inv_type, inv) == name_to_find) - return inv; - } - return -2; // failed to find it. -} -// end hufflets -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - initialize(); - } - - on_rez(integer parm) { llResetScript(); } - - touch_start(integer count) { - log_it("re-initializing script now to read card again..."); - initialize(); - } - - // reset when we see changes to our notecard configuration. - changed(integer change) { - if (change & CHANGED_INVENTORY) { - llSleep(3.14159265358); // delay to avoid interfering with upgrade. - llResetScript(); - } - } - - // process the response from the noteworthy library. - link_message(integer which, integer num, string msg, key id) - { handle_link_message(which, num, msg, id); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.txt b/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.txt new file mode 100755 index 00000000..f955b64b --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/noteworthy_example_usage_v3.6.txt @@ -0,0 +1,324 @@ + +// huffware script: noteworthy example usage, by fred huffhines +// +// shows how to use the noteworthy script as a configuration helper. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +string EXAMPLE_NOTEWORTHY_SIGNATURE = "#example_noteworthy"; + // the notecard must begin with this as its first line for it to be + // recognized as our configuration card. + +// global variables... + +string global_notecard_name; // name of our notecard in the object's inventory. +integer response_code; // set to uniquely identify the notecard read in progress. +list global_config_list; // a collection of configuration parameters from our notecard. +integer global_config_index; // allows wrap-around feature, which we don't use here. + +// requires noteworthy library v8.3 or better. +////////////// +// do not redefine these constants. +integer NOTEWORTHY_HUFFWARE_ID = 10010; + // the unique id within the huffware system for the noteworthy script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string BAD_NOTECARD_INDICATOR = "bad_notecard"; + // indicates that the notecard reading process has failed to find an appropriate one. +string BUSY_READING_INDICATOR = "busy_already"; + // this return value indicates that the script is already in use by some other script. + // the calling script should try again later. +string NOTECARD_READ_CONTINUATION = "continue!"; + // returned as first parameter if there is still more data to handle. +// commands available via the noteworthy library: +string READ_NOTECARD_COMMAND = "#read_note#"; + // command used to tell the script to read notecards. needs a signature to find + // in the card as the first parameter, and a randomly generated response code for + // the second parameter. the response code is used to uniquely identify a set of + // pending notecard readings (hopefully). the signature can be empty or missing. + // the results will be fired back as the string value returned, which will have + // as first element the notecard's name (or "bad_notecard" if none was found) and + // as subsequent elements an embedded list that was read from the notecard. this + // necessarily limits the size of the notecards that we can read and return. +// +////////////// +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } +////////////// + +// this function fires off a request to the noteworthy library via a link message. +// noteworthy will look for a notecard with our particular signature in it and +// if it finds one, it will read the configuration therein. an empty string is +// returned if noteworthy couldn't find anything. +request_configuration() +{ + global_notecard_name = ""; // reset any previous card. + // try to find a notecard with our configuration. + response_code = -1 * (integer)randomize_within_range(23, 80000, FALSE); + string parms_sent = wrap_parameters([EXAMPLE_NOTEWORTHY_SIGNATURE, response_code]); + llMessageLinked(LINK_THIS, NOTEWORTHY_HUFFWARE_ID, READ_NOTECARD_COMMAND, + parms_sent); +} + +// processes link messages received from the noteworthy library. +handle_link_message(integer which, integer num, string msg, key id) +{ + if ( (num != NOTEWORTHY_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != READ_NOTECARD_COMMAND) ) + return; // not for us. + // process the result of reading the notecard. + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string notecard_name = llList2String(parms, 0); + integer response_for = llList2Integer(parms, 1); + if (response_for != response_code) return; // oops, this isn't for us. + if (notecard_name == BAD_NOTECARD_INDICATOR) { + // we hated the notecards we found, or there were none. + log_it("We apologize; there seem to be no notecards with a first line of '" + + EXAMPLE_NOTEWORTHY_SIGNATURE + + "'. We can't read any configuration until that situation improves."); + } else { + // snag all but the first two elements for our config now. + global_config_list += llList2List(parms, 2, -1); + // make sure we shouldn't keep going. + if (notecard_name != NOTECARD_READ_CONTINUATION) { + // a valid notecard has been found. + global_notecard_name = notecard_name; // record its name for later use. + global_config_index = 0; // we are starting over in the config list. + // now echo the card we received... + log_it("read notecard \"" + global_notecard_name + "\":"); + integer lines_to_say = llGetListLength(global_config_list); + if (lines_to_say > 8) + lines_to_say = 8; // limit how much text is spoken. + integer indy; + for (indy = 0; indy < lines_to_say; indy++) + log_it("line #" + (string)(indy + 1) + ": " + llList2String(global_config_list, indy)); + if (lines_to_say != llGetListLength(global_config_list)) + log_it("...and so forth...."); + // and process the file as a set of definitions. + process_ini_config(); + } + } +} + +/////////////// + +// consumes the notecard in a very application specific way to retrieve our configuration items. +// the example script only looks for two variables: name and description. if those are found in +// the sample card, then they are proudly shown. +parse_variable_definition(string to_parse) +{ +// string content; // filled after finding a variable name. +// if ( (content = get_variable_value(to_parse, "name")) != "") +// log_it("** got a name of '" + content + "'"); +// else if ( (content = get_variable_value(to_parse, "description")) != "") +// log_it("** got a description of '" + content + "'"); +} + +initialize() +{ + // reset our relevant variables. + global_notecard_name = ""; + global_config_list = []; + global_config_index = 0; + + // announce that we're open for business. + log_it("example noteworthy usage is started, free mem=" + (string)llGetFreeMemory()); + + // request that the noteworthy library start looking for our notecard. + request_configuration(); +} + +////////////// +// from hufflets... +// + +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// locates the string "text" in the list to "search_in". +integer find_in_list(list search_in, string text) +{ + integer len = llGetListLength(search_in); + integer i; + for (i = 0; i < len; i++) { + if (llList2String(search_in, i) == text) + return i; + } + return -1; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return (llSubStringIndex(compare_with, prefix) == 0); } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +// strips the spaces off of the beginning and end of a string. +string strip_spaces(string to_strip) +{ + // clean out initial spaces. + while (llGetSubString(to_strip, 0, 0) == " ") + to_strip = llDeleteSubString(to_strip, 0, 0); + // clean out ending spaces. + while (llGetSubString(to_strip, -1, -1) == " ") + to_strip = llDeleteSubString(to_strip, -1, -1); + return to_strip; +} + +// parses a variable definition to find the name of the variable and its value. +// this returns two strings [X, Y], if "to_split" is in the form X=Y. +list separate_variable_definition(string to_split) +{ + integer equals_indy = llSubStringIndex(to_split, "="); + // we don't support missing an equals sign, and we don't support it as the first character. + if (equals_indy <= 0) return []; // no match. + string x = llGetSubString(to_split, 0, equals_indy - 1); + string y = llGetSubString(to_split, equals_indy + 1, -1); + to_split = ""; // save space. + return [ strip_spaces(x), strip_spaces(y) ]; +} + +// returns a non-empty string if "to_check" defines a value for "variable_name". +// this must be in the form "X=Y", where X is the variable_name and Y is the value. +string get_variable_value(string to_check, string variable_name) +{ + list x_y = separate_variable_definition(to_check); + if (llGetListLength(x_y) != 2) return ""; // failure to parse a variable def at all. + if (!is_prefix(llList2String(x_y, 0), variable_name)) return ""; // no match. + return llList2String(x_y, 1); // a match! +} + +// examines all entries that we got from the notecard to see if any contain definitions. +// this is basically an INI file reader, but it uses a list instead of a file. +// ini files provide a format with multiple sections of config information, like so: +// [section_1] +// name1=value1 +// name2=value2 ...etc... +// [section_2] +// name1=value1 ...etc... +process_ini_config() +{ + log_it("scanning notecard for variable definitions..."); + integer indy; + integer count = llGetListLength(global_config_list); + string section_name; // set later if we see one. + + // iterate across the items in our configuration to look for ones that are not done yet. + for (indy = global_config_index; indy < count; indy++) { + string line = llList2String(global_config_list, indy); + // search for a section beginning. + if (llGetSubString(line, 0, 0) == "[") { + // we found the start of a section name. now read the contents. + indy++; // skip section line. + section_name = llGetSubString(line, 1, -2); + log_it("reading section: " + section_name); + } + integer sec_indy; + for (sec_indy = indy; sec_indy < count; sec_indy++) { + // read the lines in the section. + line = llList2String(global_config_list, sec_indy); + if (llGetSubString(line, 0, 0) != "[") { + // try to interpret this line as a variable setting. this is just + // one example of a way to handle the config file; one might instead + // want to do something below once a whole section is read. + parse_variable_definition(line); + indy = sec_indy; // track that we've passed this line. + } else { + // we're at the beginning of a new section now, so start processing its + // configuration in the outer loop. + indy = sec_indy - 1; // set indy to proper beginning of section. + global_config_index = indy; // remember where we had read to. + sec_indy = count + 3; // skip remainder of inner loop. + } + } + } + + global_config_index = 0; // reset outer position if want to re-read. +} + +// locates the item with "name_to_find" in the inventory items with the "type". +// a value from 0 to N-1 is returned if it's found, where N is the number of +// items in the inventory. +integer find_in_inventory(string name_to_find, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer inv; + for (inv = 0; inv < num_inv; inv++) { + if (llGetInventoryName(inv_type, inv) == name_to_find) + return inv; + } + return -2; // failed to find it. +} +// end hufflets +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + initialize(); + } + + on_rez(integer parm) { llResetScript(); } + + touch_start(integer count) { + log_it("re-initializing script now to read card again..."); + initialize(); + } + + // reset when we see changes to our notecard configuration. + changed(integer change) { + if (change & CHANGED_INVENTORY) { + llSleep(3.14159265358); // delay to avoid interfering with upgrade. + llResetScript(); + } + } + + // process the response from the noteworthy library. + link_message(integer which, integer num, string msg, key id) + { handle_link_message(which, num, msg, id); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.lsl deleted file mode 100755 index 5e265429..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.lsl +++ /dev/null @@ -1,78 +0,0 @@ - -// huffware script: report to merchants, by fred huffhines. -// -// this script lets merchants know that one of their items has been rezzed or attached. -// it only reports this the first time it happens. - -// global constants... - -integer SCRIPT_ZAPS_SELF_AFTER_REPORT = FALSE; - // if this is true, the script will destroy itself once it reports the object rez or attach. - -// the list of UUIDs for reporting the customer event. -list IDS_TO_ALERT = [ -// "addfa58f-e42e-4dde-9eb0-755bbf4e23ec", // damara's alt. - "71649242-6abe-4288-b45b-a057621d35ea" // fred. -]; - -// the list of emails that should be alerted. -list EMAILS_TO_ALERT = [ -// "damradbruch@hotmail.com", // damara's alt email. - "fred@gruntose.com" // fred. -]; - -// global variables... - -integer REPORTED_ABOUT_REZ = FALSE; // did we tell the merchants yet? - -key CURRENT_OWNER = NULL_KEY; // the guy who owns the hud right now. - -// helper functions... - -// let the merchants who sold this product know that it was either rezzed or attached. -// either event should cause a nice report to them. -alert_the_merchants(string word) -{ - integer i; - if (CURRENT_OWNER != llGetOwner()) { - // if the owner has changed, then we always believe that we need to report. - REPORTED_ABOUT_REZ = FALSE; - CURRENT_OWNER = llGetOwner(); - } - if (!REPORTED_ABOUT_REZ) { - // we have not reported before (for this owner), so we can tell the merchants now. - REPORTED_ABOUT_REZ = TRUE; - string message_for_merchants = "Your product '" + llGetObjectName() + "' was " - + word + " by " + llKey2Name(llGetOwner()) - + " in " + llGetRegionName() - + " at " + llGetTimestamp(); - // send instant messages about this event. - for (i = 0; i < llGetListLength(IDS_TO_ALERT); i++) { - key id = (key)llList2String(IDS_TO_ALERT, i); - llInstantMessage(id, message_for_merchants); - } - // send emails about it too. - for (i = 0; i < llGetListLength(EMAILS_TO_ALERT); i++) { - string addr = llList2String(EMAILS_TO_ALERT, i); - llEmail(addr, "customer event for " + llKey2Name(llGetOwner()) - + " regarding " + llGetObjectName(), - message_for_merchants); - } - // see if the script should go away now. - if (SCRIPT_ZAPS_SELF_AFTER_REPORT) { - llRemoveInventory(llGetScriptName()); - } - } -} - -default -{ - state_entry() { CURRENT_OWNER = llGetOwner(); } - - attach(key id) { - if (id != NULL_KEY) { alert_the_merchants("attached"); } - } - - on_rez(integer start_parm) { alert_the_merchants("rezzed"); } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.txt new file mode 100755 index 00000000..5e265429 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/report_to_merchants_v1.3.txt @@ -0,0 +1,78 @@ + +// huffware script: report to merchants, by fred huffhines. +// +// this script lets merchants know that one of their items has been rezzed or attached. +// it only reports this the first time it happens. + +// global constants... + +integer SCRIPT_ZAPS_SELF_AFTER_REPORT = FALSE; + // if this is true, the script will destroy itself once it reports the object rez or attach. + +// the list of UUIDs for reporting the customer event. +list IDS_TO_ALERT = [ +// "addfa58f-e42e-4dde-9eb0-755bbf4e23ec", // damara's alt. + "71649242-6abe-4288-b45b-a057621d35ea" // fred. +]; + +// the list of emails that should be alerted. +list EMAILS_TO_ALERT = [ +// "damradbruch@hotmail.com", // damara's alt email. + "fred@gruntose.com" // fred. +]; + +// global variables... + +integer REPORTED_ABOUT_REZ = FALSE; // did we tell the merchants yet? + +key CURRENT_OWNER = NULL_KEY; // the guy who owns the hud right now. + +// helper functions... + +// let the merchants who sold this product know that it was either rezzed or attached. +// either event should cause a nice report to them. +alert_the_merchants(string word) +{ + integer i; + if (CURRENT_OWNER != llGetOwner()) { + // if the owner has changed, then we always believe that we need to report. + REPORTED_ABOUT_REZ = FALSE; + CURRENT_OWNER = llGetOwner(); + } + if (!REPORTED_ABOUT_REZ) { + // we have not reported before (for this owner), so we can tell the merchants now. + REPORTED_ABOUT_REZ = TRUE; + string message_for_merchants = "Your product '" + llGetObjectName() + "' was " + + word + " by " + llKey2Name(llGetOwner()) + + " in " + llGetRegionName() + + " at " + llGetTimestamp(); + // send instant messages about this event. + for (i = 0; i < llGetListLength(IDS_TO_ALERT); i++) { + key id = (key)llList2String(IDS_TO_ALERT, i); + llInstantMessage(id, message_for_merchants); + } + // send emails about it too. + for (i = 0; i < llGetListLength(EMAILS_TO_ALERT); i++) { + string addr = llList2String(EMAILS_TO_ALERT, i); + llEmail(addr, "customer event for " + llKey2Name(llGetOwner()) + + " regarding " + llGetObjectName(), + message_for_merchants); + } + // see if the script should go away now. + if (SCRIPT_ZAPS_SELF_AFTER_REPORT) { + llRemoveInventory(llGetScriptName()); + } + } +} + +default +{ + state_entry() { CURRENT_OWNER = llGetOwner(); } + + attach(key id) { + if (id != NULL_KEY) { alert_the_merchants("attached"); } + } + + on_rez(integer start_parm) { alert_the_merchants("rezzed"); } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.lsl b/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.lsl deleted file mode 100755 index 2ac6589c..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.lsl +++ /dev/null @@ -1,130 +0,0 @@ - -// huffware script: set roundy, by fred huffhines. -// -// establishes properties for an object based on our ideal template. -// really just a helper for the shop where we want to change a whole bunch of -// product packages without recreating them. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() - { - auto_retire(); - - llSetPrimitiveParams([ PRIM_SIZE, <1.4, .164, 1.4>, - PRIM_TYPE, PRIM_TYPE_CYLINDER, 0, <0.0, 1.0, 0.0>, 0.0, - <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, -/// <0.0, 0.0, 0.0>, <0.0, 1.0, 0.0>, - PRIM_TEXTURE, ALL_SIDES, "c3c4ea17-90fd-d4e8-57e7-b39a47e1cea6", - <2, 1, 0>, <0.5, 0, 0>, 0 -// PRIM_CHIPOPY - ]); - } - - on_rez(integer parm) { llResetScript(); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.txt b/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.txt new file mode 100755 index 00000000..2ac6589c --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/set_roundy_v0.6.txt @@ -0,0 +1,130 @@ + +// huffware script: set roundy, by fred huffhines. +// +// establishes properties for an object based on our ideal template. +// really just a helper for the shop where we want to change a whole bunch of +// product packages without recreating them. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() + { + auto_retire(); + + llSetPrimitiveParams([ PRIM_SIZE, <1.4, .164, 1.4>, + PRIM_TYPE, PRIM_TYPE_CYLINDER, 0, <0.0, 1.0, 0.0>, 0.0, + <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, +/// <0.0, 0.0, 0.0>, <0.0, 1.0, 0.0>, + PRIM_TEXTURE, ALL_SIDES, "c3c4ea17-90fd-d4e8-57e7-b39a47e1cea6", + <2, 1, 0>, <0.5, 0, 0>, 0 +// PRIM_CHIPOPY + ]); + } + + on_rez(integer parm) { llResetScript(); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.lsl deleted file mode 100755 index 5dd99652..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.lsl +++ /dev/null @@ -1,26 +0,0 @@ - -// huffware script: simple map tp, by fred huffhines. -// -// an inglorious little script for jumping somewhere else. - -string region = "hippocampus"; - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - } - - touch_start(integer count) - { - llWhisper(0, "Showing map of " + region + " for teleport..."); - llMapDestination(region, <130, 130, 24>, ZERO_VECTOR); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.txt new file mode 100755 index 00000000..5dd99652 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/simple_map_tp_v0.3.txt @@ -0,0 +1,26 @@ + +// huffware script: simple map tp, by fred huffhines. +// +// an inglorious little script for jumping somewhere else. + +string region = "hippocampus"; + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + } + + touch_start(integer count) + { + llWhisper(0, "Showing map of " + region + " for teleport..."); + llMapDestination(region, <130, 130, 24>, ZERO_VECTOR); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.lsl b/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.lsl deleted file mode 100755 index fa7549f4..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.lsl +++ /dev/null @@ -1,174 +0,0 @@ - -// huffware script: simple follower script, by fred huffhines. -// -// this has been condensed from other pet scripts but still retains all the vitamins! -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// global constants... - -float HEIGHT_ABOVE_AVATAR = 0.3; // how far above the av do we float. -float ROOM_FOR_ERROR = 0.1; // how far away from the target locale can we roam. -float MAXIMUM_VELOCITY = 200.0; // the fastest the object can zoom towards us. -float SENSOR_PERIOD = 1.0; // how frequently we look for the avatar. -float SENSOR_RANGE = 64.0; // the farthest away we will try to look for the avatar. - -// global variables... - -vector last_detected_position; // where the avatar was last detected. -integer target_identifier; // the id assigned when we registered our target. -integer last_physics_state; // this remembers if physics should be enabled currently. -vector perch_position; // place we inhabit near the owner. - -// returns the location where we should perch, given the target's location. -vector target_to_perch(key av, vector target) -{ - vector av_bounds = llGetAgentSize(av); - return ; -} - -// returns the location of the target given where we're trying to aim at. -vector perch_to_target(key av, vector perch) -{ - vector av_bounds = llGetAgentSize(av); - return ; -} -//hmmm: the two target and perch funcs both assume we don't want any lateral offset. -// and currently they're only taking into account the avatar's size in the z direction. - - -// makes the pet completely stop travelling around and just sit there. -cease_movement() -{ - llStopMoveToTarget(); - llTargetRemove(target_identifier); - full_stop(); - llSetStatus(STATUS_PHYSICS, FALSE); - last_physics_state = FALSE; - // if we're not quite there, jump to the perch. - if (llVecDist(perch_position, llGetPos()) > ROOM_FOR_ERROR) { - // we're not close enough so make a flying leap. -//llOwnerSay("jumping to perch at " + (string)perch_position + ", was at " + (string)llGetPos()); - llSetPos(perch_position); // make us very accurate until something changes. - } -} - -// tells the pet to target the avatar "av" at the location "pos". this will assume -// the avatar is actually present in the same sim when it calculates the avatar's size. -// we use that size in calculating where to perch nearby the avatar. -move_toward_target(key av, vector destination) -{ - // first of all we'll remember where we're supposed to go. - perch_position = target_to_perch(av, destination); - // now see how far away we are from that. - float distance = llVecDist(perch_position, llGetPos()); - if (distance < 1.0) { - // we're close enough; stop moving for a bit. -//llOwnerSay("dist small enough to go non-phys: " + (string)distance); - cease_movement(); - return; - } - // well, now we know that we need to move somewhere. let's set up a - // physics target and head that way. - llSetStatus(STATUS_PHYSICS, TRUE); - last_physics_state = TRUE; - llTargetRemove(target_identifier); - float time = distance / MAXIMUM_VELOCITY; - // if we go too low, then SL will ignore the move to target request. - if (time < 0.14) time = 0.14; -//llOwnerSay("tau=" + (string)time); - target_identifier = llTarget(perch_position, ROOM_FOR_ERROR); - llMoveToTarget(perch_position, time); -} - -// startup the object. -initialize() -{ - llSetStatus(STATUS_PHYSICS, TRUE); - last_physics_state = TRUE; - llSetBuoyancy(1.0); - llSetStatus(STATUS_PHANTOM, TRUE); - llSensorRemove(); - // start looking for the owner. - llSensorRepeat("", llGetOwner(), AGENT, SENSOR_RANGE, PI * 2, SENSOR_PERIOD); -} - -// sets the object's speed to "new_velocity". -// if "local_axis" is TRUE, then it will be relative to the object's -// own local coordinates. -set_velocity(vector new_velocity, integer local_axis) -{ - vector current_velocity = llGetVel(); - - if (local_axis) { - rotation rot = llGetRot(); - current_velocity /= rot; // undo the rotation. - } - - new_velocity -= current_velocity; - new_velocity *= llGetMass(); - - llApplyImpulse(new_velocity, local_axis); -} - -// attempts to bring the object to a complete stop. -full_stop() -{ - llSetForce(<0,0,0>, FALSE); - set_velocity(<0,0,0>, FALSE); -} - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { initialize(); } - - on_rez(integer param) { llResetScript(); } - - sensor(integer num_detected) - { - // save where we saw the av just now. - last_detected_position = llDetectedPos(0); - // move closer if we're not near enough to our beloved owner. - move_toward_target(llGetOwner(), last_detected_position); - // if we find that our rotation is incorrect, we'll fix that here. - // we only reorient on the sensor period, since that's slower - // than hitting our target. plus we try to ensure we never get - // out of place again. - vector curr_rot = llRot2Euler(llGetRot()); - if ( (curr_rot.x != 0.0 ) || (curr_rot.y != 0.0) ) { - // we are out of rotational goodness right now even. fix that. - llSetStatus(STATUS_PHYSICS, FALSE); - llSetStatus(STATUS_ROTATE_X, FALSE); - llSetStatus(STATUS_ROTATE_Y, FALSE); - // save the z value before correcting the rotation. - vector new_rot = ZERO_VECTOR; - new_rot.z = curr_rot.z; - llSetRot(llEuler2Rot(new_rot)); - llSetStatus(STATUS_PHYSICS, last_physics_state); - } - } - - no_sensor() - { - // we lost track of the avatar. turn off phyics and wait. - cease_movement(); - } - - at_target(integer number, vector targetpos, vector ourpos) - { - // wait until we see the av again before picking a new target. -///??seems bad cease_movement(); - } - - not_at_target() - { - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.txt b/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.txt new file mode 100755 index 00000000..fa7549f4 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/simpy_pet_v3.7.txt @@ -0,0 +1,174 @@ + +// huffware script: simple follower script, by fred huffhines. +// +// this has been condensed from other pet scripts but still retains all the vitamins! +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// global constants... + +float HEIGHT_ABOVE_AVATAR = 0.3; // how far above the av do we float. +float ROOM_FOR_ERROR = 0.1; // how far away from the target locale can we roam. +float MAXIMUM_VELOCITY = 200.0; // the fastest the object can zoom towards us. +float SENSOR_PERIOD = 1.0; // how frequently we look for the avatar. +float SENSOR_RANGE = 64.0; // the farthest away we will try to look for the avatar. + +// global variables... + +vector last_detected_position; // where the avatar was last detected. +integer target_identifier; // the id assigned when we registered our target. +integer last_physics_state; // this remembers if physics should be enabled currently. +vector perch_position; // place we inhabit near the owner. + +// returns the location where we should perch, given the target's location. +vector target_to_perch(key av, vector target) +{ + vector av_bounds = llGetAgentSize(av); + return ; +} + +// returns the location of the target given where we're trying to aim at. +vector perch_to_target(key av, vector perch) +{ + vector av_bounds = llGetAgentSize(av); + return ; +} +//hmmm: the two target and perch funcs both assume we don't want any lateral offset. +// and currently they're only taking into account the avatar's size in the z direction. + + +// makes the pet completely stop travelling around and just sit there. +cease_movement() +{ + llStopMoveToTarget(); + llTargetRemove(target_identifier); + full_stop(); + llSetStatus(STATUS_PHYSICS, FALSE); + last_physics_state = FALSE; + // if we're not quite there, jump to the perch. + if (llVecDist(perch_position, llGetPos()) > ROOM_FOR_ERROR) { + // we're not close enough so make a flying leap. +//llOwnerSay("jumping to perch at " + (string)perch_position + ", was at " + (string)llGetPos()); + llSetPos(perch_position); // make us very accurate until something changes. + } +} + +// tells the pet to target the avatar "av" at the location "pos". this will assume +// the avatar is actually present in the same sim when it calculates the avatar's size. +// we use that size in calculating where to perch nearby the avatar. +move_toward_target(key av, vector destination) +{ + // first of all we'll remember where we're supposed to go. + perch_position = target_to_perch(av, destination); + // now see how far away we are from that. + float distance = llVecDist(perch_position, llGetPos()); + if (distance < 1.0) { + // we're close enough; stop moving for a bit. +//llOwnerSay("dist small enough to go non-phys: " + (string)distance); + cease_movement(); + return; + } + // well, now we know that we need to move somewhere. let's set up a + // physics target and head that way. + llSetStatus(STATUS_PHYSICS, TRUE); + last_physics_state = TRUE; + llTargetRemove(target_identifier); + float time = distance / MAXIMUM_VELOCITY; + // if we go too low, then SL will ignore the move to target request. + if (time < 0.14) time = 0.14; +//llOwnerSay("tau=" + (string)time); + target_identifier = llTarget(perch_position, ROOM_FOR_ERROR); + llMoveToTarget(perch_position, time); +} + +// startup the object. +initialize() +{ + llSetStatus(STATUS_PHYSICS, TRUE); + last_physics_state = TRUE; + llSetBuoyancy(1.0); + llSetStatus(STATUS_PHANTOM, TRUE); + llSensorRemove(); + // start looking for the owner. + llSensorRepeat("", llGetOwner(), AGENT, SENSOR_RANGE, PI * 2, SENSOR_PERIOD); +} + +// sets the object's speed to "new_velocity". +// if "local_axis" is TRUE, then it will be relative to the object's +// own local coordinates. +set_velocity(vector new_velocity, integer local_axis) +{ + vector current_velocity = llGetVel(); + + if (local_axis) { + rotation rot = llGetRot(); + current_velocity /= rot; // undo the rotation. + } + + new_velocity -= current_velocity; + new_velocity *= llGetMass(); + + llApplyImpulse(new_velocity, local_axis); +} + +// attempts to bring the object to a complete stop. +full_stop() +{ + llSetForce(<0,0,0>, FALSE); + set_velocity(<0,0,0>, FALSE); +} + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { initialize(); } + + on_rez(integer param) { llResetScript(); } + + sensor(integer num_detected) + { + // save where we saw the av just now. + last_detected_position = llDetectedPos(0); + // move closer if we're not near enough to our beloved owner. + move_toward_target(llGetOwner(), last_detected_position); + // if we find that our rotation is incorrect, we'll fix that here. + // we only reorient on the sensor period, since that's slower + // than hitting our target. plus we try to ensure we never get + // out of place again. + vector curr_rot = llRot2Euler(llGetRot()); + if ( (curr_rot.x != 0.0 ) || (curr_rot.y != 0.0) ) { + // we are out of rotational goodness right now even. fix that. + llSetStatus(STATUS_PHYSICS, FALSE); + llSetStatus(STATUS_ROTATE_X, FALSE); + llSetStatus(STATUS_ROTATE_Y, FALSE); + // save the z value before correcting the rotation. + vector new_rot = ZERO_VECTOR; + new_rot.z = curr_rot.z; + llSetRot(llEuler2Rot(new_rot)); + llSetStatus(STATUS_PHYSICS, last_physics_state); + } + } + + no_sensor() + { + // we lost track of the avatar. turn off phyics and wait. + cease_movement(); + } + + at_target(integer number, vector targetpos, vector ourpos) + { + // wait until we see the av again before picking a new target. +///??seems bad cease_movement(); + } + + not_at_target() + { + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.lsl b/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.lsl deleted file mode 100755 index 35445c83..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.lsl +++ /dev/null @@ -1,49 +0,0 @@ - -// testing of an opensim bug, where there was a new requirement that -// the object have a sit target before any changed events will be fired. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -integer link_changes = 0; - - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() - { - llSitTarget(<0, 0, 0.1>, ZERO_ROTATION); -//above line makes things work. comment it out, and put in new object, and -// the object will not get changed events. - llSay(0, "sit to run the test..."); - } - - on_rez(integer count) { llResetScript(); } - - changed(integer chang) { - llSay(0, "got into changed event..."); - if (! (chang & CHANGED_LINK) ) { - llSay(0, "change was not a link, leaving."); - return; // not for us. - } - llSay(0, "into changed event, CHANGED_LINK..."); - link_changes++; - key av_sitting = llAvatarOnSitTarget(); - if (av_sitting == NULL_KEY) { - llSay(0, "avatar stood up since key is null"); - } else { - llSay(0, "avatar sat down: " + llDetectedName(0)); - } - } - - touch_start(integer count) { - llSay(0, "there have been " + (string)link_changes - + " 'changed' events for links since the last reset."); - } -} \ No newline at end of file diff --git a/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.txt b/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.txt new file mode 100755 index 00000000..35445c83 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/sit_testing_v0.6.txt @@ -0,0 +1,49 @@ + +// testing of an opensim bug, where there was a new requirement that +// the object have a sit target before any changed events will be fired. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +integer link_changes = 0; + + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() + { + llSitTarget(<0, 0, 0.1>, ZERO_ROTATION); +//above line makes things work. comment it out, and put in new object, and +// the object will not get changed events. + llSay(0, "sit to run the test..."); + } + + on_rez(integer count) { llResetScript(); } + + changed(integer chang) { + llSay(0, "got into changed event..."); + if (! (chang & CHANGED_LINK) ) { + llSay(0, "change was not a link, leaving."); + return; // not for us. + } + llSay(0, "into changed event, CHANGED_LINK..."); + link_changes++; + key av_sitting = llAvatarOnSitTarget(); + if (av_sitting == NULL_KEY) { + llSay(0, "avatar stood up since key is null"); + } else { + llSay(0, "avatar sat down: " + llDetectedName(0)); + } + } + + touch_start(integer count) { + llSay(0, "there have been " + (string)link_changes + + " 'changed' events for links since the last reset."); + } +} \ No newline at end of file diff --git a/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.lsl b/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.lsl deleted file mode 100755 index d71062eb..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.lsl +++ /dev/null @@ -1,193 +0,0 @@ - -//huffware script: swiveller, modified by fred huffhines. - -//original docs: -// This script is as end-user friendly as possible. Moving the swing will make it reset to it's new position and orientation. Occasionally JUST rotating it won't work, so in that case you will need to nudge it sideways just a little (1mm will do). This is a quirk of LSL and it intermittent. -// Put this script in the pivot - the thing the swing swings around (it doesn't have to be a long rod). That needs to be the root of the prim set that actually swings - if you want/need a frame that needs to be a separate item. SL doesn't yet allow us hierarchical linking. -// -// fred's modifications are licensed by: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// configuration variables -- these control how the swing behaves. - -integer is_swinging = FALSE; // if set to FALSE, then the swing is not running when rezzed. - -float SWING_PERIOD = 0.4; - // the delay between changing the swing's position. decrease this number to increase - // speed of swinging. - -integer SWING_STEPS = 12; - // The total number of steps in the swing's path. More steps makes for a - // smoother swing. More steps (alone) means slower swinging also--time for - // a complete swing cycle is SWING_STEPS * swing_period. - -integer SWING_ANGLE_DEGREES = 10; - // How far from the vertical the swing will move. -//This is in both directions? - -///// - -integer swing_step = 1; - // the current swing position. - -float swingRad; - -vector normal; - -rotation Inverse(rotation r) { return <-r.x, -r.y, -r.z, r.s>; } - -rotation GetParentRot() { return Inverse(llGetLocalRot()) * llGetRot(); } - -SetLocalRot(rotation x) { llSetRot(x*Inverse(GetParentRot())); } - - -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - normal = llRot2Euler(llGetRot()); - swingRad = SWING_ANGLE_DEGREES * DEG_TO_RAD; - llSetTouchText("Swing"); - } - touch_start(integer num) - { - if (is_swinging) { - is_swinging = FALSE; - llSetTouchText("Swing"); - } else { - is_swinging = TRUE; - llSetTouchText("Stop swing"); - llSetTimerEvent(SWING_PERIOD); - } - } - timer() - { - float stepOffset = (float)swing_step / SWING_STEPS * TWO_PI; - if (swing_step > SWING_STEPS) swing_step = 1; - if (!is_swinging && (swing_step>=SWING_STEPS || swing_step==SWING_STEPS/2)) { - llSetTimerEvent(0.0); - SetLocalRot(llEuler2Rot()); - } else { - SetLocalRot(llEuler2Rot()); - swing_step++; - } - } - moving_end() - { - normal = llRot2Euler(llGetRot()); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.txt b/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.txt new file mode 100755 index 00000000..d71062eb --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/swiveller_v1.1.txt @@ -0,0 +1,193 @@ + +//huffware script: swiveller, modified by fred huffhines. + +//original docs: +// This script is as end-user friendly as possible. Moving the swing will make it reset to it's new position and orientation. Occasionally JUST rotating it won't work, so in that case you will need to nudge it sideways just a little (1mm will do). This is a quirk of LSL and it intermittent. +// Put this script in the pivot - the thing the swing swings around (it doesn't have to be a long rod). That needs to be the root of the prim set that actually swings - if you want/need a frame that needs to be a separate item. SL doesn't yet allow us hierarchical linking. +// +// fred's modifications are licensed by: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// configuration variables -- these control how the swing behaves. + +integer is_swinging = FALSE; // if set to FALSE, then the swing is not running when rezzed. + +float SWING_PERIOD = 0.4; + // the delay between changing the swing's position. decrease this number to increase + // speed of swinging. + +integer SWING_STEPS = 12; + // The total number of steps in the swing's path. More steps makes for a + // smoother swing. More steps (alone) means slower swinging also--time for + // a complete swing cycle is SWING_STEPS * swing_period. + +integer SWING_ANGLE_DEGREES = 10; + // How far from the vertical the swing will move. +//This is in both directions? + +///// + +integer swing_step = 1; + // the current swing position. + +float swingRad; + +vector normal; + +rotation Inverse(rotation r) { return <-r.x, -r.y, -r.z, r.s>; } + +rotation GetParentRot() { return Inverse(llGetLocalRot()) * llGetRot(); } + +SetLocalRot(rotation x) { llSetRot(x*Inverse(GetParentRot())); } + + +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + normal = llRot2Euler(llGetRot()); + swingRad = SWING_ANGLE_DEGREES * DEG_TO_RAD; + llSetTouchText("Swing"); + } + touch_start(integer num) + { + if (is_swinging) { + is_swinging = FALSE; + llSetTouchText("Swing"); + } else { + is_swinging = TRUE; + llSetTouchText("Stop swing"); + llSetTimerEvent(SWING_PERIOD); + } + } + timer() + { + float stepOffset = (float)swing_step / SWING_STEPS * TWO_PI; + if (swing_step > SWING_STEPS) swing_step = 1; + if (!is_swinging && (swing_step>=SWING_STEPS || swing_step==SWING_STEPS/2)) { + llSetTimerEvent(0.0); + SetLocalRot(llEuler2Rot()); + } else { + SetLocalRot(llEuler2Rot()); + swing_step++; + } + } + moving_end() + { + normal = llRot2Euler(llGetRot()); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.lsl b/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.lsl deleted file mode 100755 index 688a3a9c..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.lsl +++ /dev/null @@ -1,146 +0,0 @@ - -// huffware script: tester for inventory exchanger, by fred huffhines. -// -// makes sure that the inventory exchanger is working, although this currently -// needs some manual inspection to be sure that the items are properly exchanged -// with the child prims. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// requires inventory exchanger version 2.0 or better. -////////////// -// do not redefine these constants. -integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via the library: -string REGISTER_ASSETS_COMMAND = "#regis#"; - // makes the root prim's inventory exchanger track a set of items which each participating - // child prim should have. this command is only available to the root prim; child prims - // cannot register any assets but instead can get updates on the assets. the parameter - // required is a list of asset definitions, wrapped by the huffware item separator. each - // asset definition is in turn a two part list wrapped with the asset field separator. -string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. -string WILDCARD_INVENTORY_NAME = "ALL"; - // this keyword can be used to register all of the inventory items available of the - // specified type. this should be passed as the inventory item name in the second half of - // an asset definition list. -string WHACK_INVENTORY_SIGNAL = "DEL*"; - // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. -string AVAILABLE_ASSETS_EVENT = "#gotz#"; - // the root prim publishes this event to list out what items it has available. the child - // prims need to ask for anything that they're currently missing. the included parameters - // are in the same format as the register assets command, but no wildcards will be present; - // all asset names will be fully expanded. -string REQUEST_UPDATES = "#nupd#"; - // used by the child prim to request an updated version of an asset or assets. the parameters - // should follow the register assets command. -string FINISHED_UPDATING = "#donq#"; - // a signal sent from the root prim to the child prim when the root has finished updating - // the assets requested. this lets the child know that it can clean out any outdated versions - // of items which got an update. there are no parameters to this, because the child prim - // should have at most one update outstanding at a time. -////////////// - -// looks for an inventory item with the same prefix as the "basename_to_seek". -integer find_basename_in_inventory(string basename_to_seek, integer inv_type) -{ - integer num_inv = llGetInventoryNumber(inv_type); - if (num_inv == 0) return -1; // nothing there! - integer indy; - for (indy = 0; indy < num_inv; indy++) { - if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) - return indy; - } - return -2; // failed to find it. -} - -// returns the name of the inventory exchange script, if one is present. we don't worry -// about there being more than one present; that's a different script's problem rather -// than one from the inventory exchanger. -string get_exchangers_name() -{ - integer found = find_basename_in_inventory("inventory exchanger", INVENTORY_SCRIPT); - if (found < 0) { - return ""; - } - return llGetInventoryName(INVENTORY_SCRIPT, found); -} - -// tell the root prim's inventory exchanger what to monitor. -post_exchangeable_assets() -{ - llMessageLinked(LINK_THIS, INVENTORY_EXCHANGER_HUFFWARE_ID, REGISTER_ASSETS_COMMAND, - wrap_parameters([ - (string)INVENTORY_LANDMARK + ASSET_FIELD_SEPARATOR + "ALL", - (string)INVENTORY_SOUND + ASSET_FIELD_SEPARATOR + "ALL", - (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR + get_exchangers_name(), - (string)INVENTORY_TEXTURE + ASSET_FIELD_SEPARATOR + "ALL" - ])); -} - -////////////// -// from hufflets... - -integer debug_num = 0; -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on an unusual channel for chat if it's not intended for general public. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat that anyone can hear. we take off the bling for this one. -// llSay(0, to_say); -} - -// joins a list of parameters using the parameter sentinel for the library. -string wrap_parameters(list to_flatten) -{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// end hufflets. -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default { - state_entry() - { - llSetTimerEvent(14); // pretty fast update cycle will push the exchange events. - post_exchangeable_assets(); - } - - // this tester has no link message responsibilities. once it tells the root prim's - // inventory exchanger what to do, that's all it needs to say. -// link_message(integer link_num, integer service, string cmd, key parms) {} - - timer() { - // repost all the assets we care about. this ensures that we're up to date if the - // inventory changes. - post_exchangeable_assets(); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.txt b/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.txt new file mode 100755 index 00000000..688a3a9c --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/tester_for_inventory_exchanger_v1.0.txt @@ -0,0 +1,146 @@ + +// huffware script: tester for inventory exchanger, by fred huffhines. +// +// makes sure that the inventory exchanger is working, although this currently +// needs some manual inspection to be sure that the items are properly exchanged +// with the child prims. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// requires inventory exchanger version 2.0 or better. +////////////// +// do not redefine these constants. +integer INVENTORY_EXCHANGER_HUFFWARE_ID = 10021; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +//string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via the library: +string REGISTER_ASSETS_COMMAND = "#regis#"; + // makes the root prim's inventory exchanger track a set of items which each participating + // child prim should have. this command is only available to the root prim; child prims + // cannot register any assets but instead can get updates on the assets. the parameter + // required is a list of asset definitions, wrapped by the huffware item separator. each + // asset definition is in turn a two part list wrapped with the asset field separator. +string ASSET_FIELD_SEPARATOR = "&&"; // separates the type from the name in our list. +string WILDCARD_INVENTORY_NAME = "ALL"; + // this keyword can be used to register all of the inventory items available of the + // specified type. this should be passed as the inventory item name in the second half of + // an asset definition list. +string WHACK_INVENTORY_SIGNAL = "DEL*"; + // ensures that the child prim doesn't maintain *any* of the inventory of the type specified. +string AVAILABLE_ASSETS_EVENT = "#gotz#"; + // the root prim publishes this event to list out what items it has available. the child + // prims need to ask for anything that they're currently missing. the included parameters + // are in the same format as the register assets command, but no wildcards will be present; + // all asset names will be fully expanded. +string REQUEST_UPDATES = "#nupd#"; + // used by the child prim to request an updated version of an asset or assets. the parameters + // should follow the register assets command. +string FINISHED_UPDATING = "#donq#"; + // a signal sent from the root prim to the child prim when the root has finished updating + // the assets requested. this lets the child know that it can clean out any outdated versions + // of items which got an update. there are no parameters to this, because the child prim + // should have at most one update outstanding at a time. +////////////// + +// looks for an inventory item with the same prefix as the "basename_to_seek". +integer find_basename_in_inventory(string basename_to_seek, integer inv_type) +{ + integer num_inv = llGetInventoryNumber(inv_type); + if (num_inv == 0) return -1; // nothing there! + integer indy; + for (indy = 0; indy < num_inv; indy++) { + if (is_prefix(llGetInventoryName(inv_type, indy), basename_to_seek)) + return indy; + } + return -2; // failed to find it. +} + +// returns the name of the inventory exchange script, if one is present. we don't worry +// about there being more than one present; that's a different script's problem rather +// than one from the inventory exchanger. +string get_exchangers_name() +{ + integer found = find_basename_in_inventory("inventory exchanger", INVENTORY_SCRIPT); + if (found < 0) { + return ""; + } + return llGetInventoryName(INVENTORY_SCRIPT, found); +} + +// tell the root prim's inventory exchanger what to monitor. +post_exchangeable_assets() +{ + llMessageLinked(LINK_THIS, INVENTORY_EXCHANGER_HUFFWARE_ID, REGISTER_ASSETS_COMMAND, + wrap_parameters([ + (string)INVENTORY_LANDMARK + ASSET_FIELD_SEPARATOR + "ALL", + (string)INVENTORY_SOUND + ASSET_FIELD_SEPARATOR + "ALL", + (string)INVENTORY_SCRIPT + ASSET_FIELD_SEPARATOR + get_exchangers_name(), + (string)INVENTORY_TEXTURE + ASSET_FIELD_SEPARATOR + "ALL" + ])); +} + +////////////// +// from hufflets... + +integer debug_num = 0; +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on an unusual channel for chat if it's not intended for general public. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat that anyone can hear. we take off the bling for this one. +// llSay(0, to_say); +} + +// joins a list of parameters using the parameter sentinel for the library. +string wrap_parameters(list to_flatten) +{ return llDumpList2String(to_flatten, HUFFWARE_PARM_SEPARATOR); } + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// end hufflets. +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default { + state_entry() + { + llSetTimerEvent(14); // pretty fast update cycle will push the exchange events. + post_exchangeable_assets(); + } + + // this tester has no link message responsibilities. once it tells the root prim's + // inventory exchanger what to do, that's all it needs to say. +// link_message(integer link_num, integer service, string cmd, key parms) {} + + timer() { + // repost all the assets we care about. this ensures that we're up to date if the + // inventory changes. + post_exchangeable_assets(); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.lsl b/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.lsl deleted file mode 100755 index b4356452..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.lsl +++ /dev/null @@ -1,222 +0,0 @@ - -// huffware script: time zone picker, by fred huffhines. -// -// allows the user to select a different time zone than the default. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// constants... - -// secret codes to control the time zone. -integer SECRET_TIME_ZONE_ADJUSTER_ID = -2091823; -string TIME_ZONE_ADJUST_COMMAND = "tzadjust"; - -// requires menutini v3.9 or better... -////////////// -// do not redefine these constants. -integer MENUTINI_HUFFWARE_ID = 10009; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -// commands available via menutini: -string SHOW_MENU_COMMAND = "#menu#"; - // the command that tells menutini to show a menu defined by parameters - // that are passed along. these must be: the menu name, the menu's title - // (which is really the info to show as content in the main box of the menu), - // the wrapped list of commands to show as menu buttons, the menu system - // channel's for listening, and the key to listen to. -// -////////////// -// joins a list of sub-items using the item sentinel for the library. -string wrap_item_list(list to_wrap) -{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } -// -////////////// - -integer random_channel() { return -(integer)(llFrand(40000) + 20000); } - -simply_display_menu(string menu_name, string title, list buttons) -{ - integer menu_channel = random_channel(); - key listen_to = llGetOwner(); - llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, - menu_name + HUFFWARE_PARM_SEPARATOR - + title + HUFFWARE_PARM_SEPARATOR - + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR - + (string)menu_channel + HUFFWARE_PARM_SEPARATOR - + (string)listen_to); -} - -// handles the response message when the user chooses a button. -react_to_menu(string menu_name, string av_key, string which_choice) -{ - log_it("You selected a time zone offset of " + which_choice); - llMessageLinked(LINK_SET, SECRET_TIME_ZONE_ADJUSTER_ID, TIME_ZONE_ADJUST_COMMAND, which_choice); -} - -// processes a message from a link. some of this must be handled -// by the driver script that handles our configuration. -handle_link_message(integer sender, integer num, string msg, key id) -{ - if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) - || (msg != SHOW_MENU_COMMAND) ) return; // not for us. - -//log_it("menu reply: sndr=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); - list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); - string menu_name = llList2String(parms, 0); - string which_choice = llList2String(parms, 1); - key av_key = llList2String(parms, 2); - react_to_menu(menu_name, av_key, which_choice); -} - -////////////// -// from hufflets... -// -integer debug_num = 0; - -// a debugging output method. can be disabled entirely in one place. -log_it(string to_say) -{ - debug_num++; - // tell this to the owner. - llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); - // say this on open chat, but use an unusual channel. -// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); -} - -// -// end hufflets -////////////// - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - } - - touch_start(integer touchers) { - if (llDetectedKey(0) != llGetOwner()) return; // only listen to owner for setting time zone. - simply_display_menu("tz", "Select your time zone offset from GMT:\nGMT is 0, EST is -5, PST is -8, etc.", - [ -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] ); - } - - link_message(integer sender, integer num, string msg, key id) - { handle_link_message(sender, num, msg, id); } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.txt b/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.txt new file mode 100755 index 00000000..b4356452 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/time_zone_picker_v0.6.txt @@ -0,0 +1,222 @@ + +// huffware script: time zone picker, by fred huffhines. +// +// allows the user to select a different time zone than the default. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// constants... + +// secret codes to control the time zone. +integer SECRET_TIME_ZONE_ADJUSTER_ID = -2091823; +string TIME_ZONE_ADJUST_COMMAND = "tzadjust"; + +// requires menutini v3.9 or better... +////////////// +// do not redefine these constants. +integer MENUTINI_HUFFWARE_ID = 10009; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +// commands available via menutini: +string SHOW_MENU_COMMAND = "#menu#"; + // the command that tells menutini to show a menu defined by parameters + // that are passed along. these must be: the menu name, the menu's title + // (which is really the info to show as content in the main box of the menu), + // the wrapped list of commands to show as menu buttons, the menu system + // channel's for listening, and the key to listen to. +// +////////////// +// joins a list of sub-items using the item sentinel for the library. +string wrap_item_list(list to_wrap) +{ return llDumpList2String(to_wrap, HUFFWARE_ITEM_SEPARATOR); } +// +////////////// + +integer random_channel() { return -(integer)(llFrand(40000) + 20000); } + +simply_display_menu(string menu_name, string title, list buttons) +{ + integer menu_channel = random_channel(); + key listen_to = llGetOwner(); + llMessageLinked(LINK_THIS, MENUTINI_HUFFWARE_ID, SHOW_MENU_COMMAND, + menu_name + HUFFWARE_PARM_SEPARATOR + + title + HUFFWARE_PARM_SEPARATOR + + wrap_item_list(buttons) + HUFFWARE_PARM_SEPARATOR + + (string)menu_channel + HUFFWARE_PARM_SEPARATOR + + (string)listen_to); +} + +// handles the response message when the user chooses a button. +react_to_menu(string menu_name, string av_key, string which_choice) +{ + log_it("You selected a time zone offset of " + which_choice); + llMessageLinked(LINK_SET, SECRET_TIME_ZONE_ADJUSTER_ID, TIME_ZONE_ADJUST_COMMAND, which_choice); +} + +// processes a message from a link. some of this must be handled +// by the driver script that handles our configuration. +handle_link_message(integer sender, integer num, string msg, key id) +{ + if ( (num != MENUTINI_HUFFWARE_ID + REPLY_DISTANCE) + || (msg != SHOW_MENU_COMMAND) ) return; // not for us. + +//log_it("menu reply: sndr=" + (string)sender + " num=" + (string)num + " msg=" + msg + " id=" + (string)id); + list parms = llParseString2List(id, [HUFFWARE_PARM_SEPARATOR], []); + string menu_name = llList2String(parms, 0); + string which_choice = llList2String(parms, 1); + key av_key = llList2String(parms, 2); + react_to_menu(menu_name, av_key, which_choice); +} + +////////////// +// from hufflets... +// +integer debug_num = 0; + +// a debugging output method. can be disabled entirely in one place. +log_it(string to_say) +{ + debug_num++; + // tell this to the owner. + llOwnerSay(llGetScriptName() + "[" + (string)debug_num + "] " + to_say); + // say this on open chat, but use an unusual channel. +// llSay(108, llGetScriptName() + "[" + (string)debug_num + "] " + to_say); +} + +// +// end hufflets +////////////// + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + } + + touch_start(integer touchers) { + if (llDetectedKey(0) != llGetOwner()) return; // only listen to owner for setting time zone. + simply_display_menu("tz", "Select your time zone offset from GMT:\nGMT is 0, EST is -5, PST is -8, etc.", + [ -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] ); + } + + link_message(integer sender, integer num, string msg, key id) + { handle_link_message(sender, num, msg, id); } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.lsl b/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.lsl deleted file mode 100755 index c3fe9649..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.lsl +++ /dev/null @@ -1,159 +0,0 @@ - -// huffware script: timed expiration, by fred huffhines. -// -// this ensures that an object only lives a set amount of time before de-rezzing. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -float PRODUCT_LIFETIME = 0.9; // time allowed before the object terminates, in minutes. - // since we now make the object temporary, this has to be less than a minute - // for our own dying scene to take place. otherwise the object just disappears. - -float EXPIRY_VOLUME = 0.25; - // we have found that this volume level is generally good, since you don't want - // the object screaming like crazy as it evaporates. - - -////////////// -// huffware script: auto-retire, by fred huffhines, version 1.9. -// distributed under BSD-like license. -// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. -// the function auto_retire() should be added *inside* a version numbered script that -// you wish to give the capability of self-upgrading. -// this script supports a notation for versions embedded in script names where a 'v' -// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". -// when the containing script is dropped into an object with a different version, the -// most recent version eats any existing ones. -// keep in mind that this code must be *copied* into your script you wish to add -// auto-retirement capability to. -// -// example usage of the auto-retirement script: -// -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - if ((float)inv_version_string < (float)version_string) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. - - string basename = to_chop_up; // script name with no version attached. - - integer posn; - // minimum script name is 2 characters plus version. - for (posn = llStringLength(to_chop_up) - 1; - (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); - posn--) { - // find the space. do nothing else. - } - if (posn < 2) return []; // no space found. - string full_suffix = llGetSubString(to_chop_up, posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// how many times the timer is hit per minute. -float TICKS_PER_MINUTE = 20.0; - -float ticks_to_live; // how long this particular object has left. - -show_time_left() -{ -// integer secs_left = (integer)(60.0 * ticks_to_live / TICKS_PER_MINUTE); -// llWhisper(14, (string)secs_left + " seconds before expiration."); -} - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() { - llParticleSystem([]); // kill any old particles running. - auto_retire(); -//llWhisper(0, "starting up " + llGetObjectName()); - ticks_to_live = PRODUCT_LIFETIME * TICKS_PER_MINUTE; - llSetTimerEvent(60.0 / TICKS_PER_MINUTE); // check avatar's state periodically. - // make sure this is a temporary object. - llSetPrimitiveParams([PRIM_TEMP_ON_REZ, TRUE]); - show_time_left(); - } - - timer() { - // make sure we don't wait too long to reset our temporariness. - integer time_now = llGetUnixTime(); - // check whether we should stay alive or not. - if (--ticks_to_live <= 0.0) { -// llWhisper(0, llGetObjectName() + " is terminating now."); - string first_sound = llGetInventoryName(INVENTORY_SOUND, 0); - if (first_sound != "") - llTriggerSound(first_sound, EXPIRY_VOLUME); - string first_pic = llGetInventoryName(INVENTORY_TEXTURE, 0); - if (first_pic != "") - llMakeExplosion(20, 1.0, 5, 3.0, 1.0, first_pic, ZERO_VECTOR); - llDie(); - // resetting this since if we're here, we don't want to keep blowing up. - ticks_to_live = PRODUCT_LIFETIME * TICKS_PER_MINUTE; - } else { - show_time_left(); - } - } - - on_rez(integer param) { - // make sure we start over when this is a new object. - llResetScript(); - } - - touch_start(integer total_number) - { - ticks_to_live += TICKS_PER_MINUTE; // add a minute to its life. -// llWhisper(0, "Object gets another minute to live."); - } - -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.txt b/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.txt new file mode 100755 index 00000000..c3fe9649 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/timed_expiration_v2.9_(toxic)_.txt @@ -0,0 +1,159 @@ + +// huffware script: timed expiration, by fred huffhines. +// +// this ensures that an object only lives a set amount of time before de-rezzing. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +float PRODUCT_LIFETIME = 0.9; // time allowed before the object terminates, in minutes. + // since we now make the object temporary, this has to be less than a minute + // for our own dying scene to take place. otherwise the object just disappears. + +float EXPIRY_VOLUME = 0.25; + // we have found that this volume level is generally good, since you don't want + // the object screaming like crazy as it evaporates. + + +////////////// +// huffware script: auto-retire, by fred huffhines, version 1.9. +// distributed under BSD-like license. +// partly based on the self-upgrading scripts from markov brodsky and jippen faddoul. +// the function auto_retire() should be added *inside* a version numbered script that +// you wish to give the capability of self-upgrading. +// this script supports a notation for versions embedded in script names where a 'v' +// is followed by a number in the form "major.minor", e.g. "grunkle script by ted v8.2". +// when the containing script is dropped into an object with a different version, the +// most recent version eats any existing ones. +// keep in mind that this code must be *copied* into your script you wish to add +// auto-retirement capability to. +// +// example usage of the auto-retirement script: +// +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + if ((float)inv_version_string < (float)version_string) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + if (llSubStringIndex(to_chop_up, " ") < 0) return []; // no space found, not a valid name to work on. + + string basename = to_chop_up; // script name with no version attached. + + integer posn; + // minimum script name is 2 characters plus version. + for (posn = llStringLength(to_chop_up) - 1; + (posn >= 2) && (llGetSubString(to_chop_up, posn, posn) != " "); + posn--) { + // find the space. do nothing else. + } + if (posn < 2) return []; // no space found. + string full_suffix = llGetSubString(to_chop_up, posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// how many times the timer is hit per minute. +float TICKS_PER_MINUTE = 20.0; + +float ticks_to_live; // how long this particular object has left. + +show_time_left() +{ +// integer secs_left = (integer)(60.0 * ticks_to_live / TICKS_PER_MINUTE); +// llWhisper(14, (string)secs_left + " seconds before expiration."); +} + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() { + llParticleSystem([]); // kill any old particles running. + auto_retire(); +//llWhisper(0, "starting up " + llGetObjectName()); + ticks_to_live = PRODUCT_LIFETIME * TICKS_PER_MINUTE; + llSetTimerEvent(60.0 / TICKS_PER_MINUTE); // check avatar's state periodically. + // make sure this is a temporary object. + llSetPrimitiveParams([PRIM_TEMP_ON_REZ, TRUE]); + show_time_left(); + } + + timer() { + // make sure we don't wait too long to reset our temporariness. + integer time_now = llGetUnixTime(); + // check whether we should stay alive or not. + if (--ticks_to_live <= 0.0) { +// llWhisper(0, llGetObjectName() + " is terminating now."); + string first_sound = llGetInventoryName(INVENTORY_SOUND, 0); + if (first_sound != "") + llTriggerSound(first_sound, EXPIRY_VOLUME); + string first_pic = llGetInventoryName(INVENTORY_TEXTURE, 0); + if (first_pic != "") + llMakeExplosion(20, 1.0, 5, 3.0, 1.0, first_pic, ZERO_VECTOR); + llDie(); + // resetting this since if we're here, we don't want to keep blowing up. + ticks_to_live = PRODUCT_LIFETIME * TICKS_PER_MINUTE; + } else { + show_time_left(); + } + } + + on_rez(integer param) { + // make sure we start over when this is a new object. + llResetScript(); + } + + touch_start(integer total_number) + { + ticks_to_live += TICKS_PER_MINUTE; // add a minute to its life. +// llWhisper(0, "Object gets another minute to live."); + } + +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.lsl b/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.lsl deleted file mode 100755 index 7aeaed86..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.lsl +++ /dev/null @@ -1,19 +0,0 @@ - -// -// used to control the door into the inner chamber of the old garleon -// land, where we had a basement with a crypt door. this was in the rocks -// near the door. it actually will work with any tl linked door script set -// to our 108 channel, but it currently shouts, which will fling all the nearby -// doors open. - -default -{ - state_entry() - { - } - - touch_start(integer total_number) - { - if (llSameGroup(llDetectedKey(0))) llShout(108, "toggle"); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.txt b/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.txt new file mode 100755 index 00000000..7aeaed86 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/touchy_feely_doro_v0.4.txt @@ -0,0 +1,19 @@ + +// +// used to control the door into the inner chamber of the old garleon +// land, where we had a basement with a crypt door. this was in the rocks +// near the door. it actually will work with any tl linked door script set +// to our 108 channel, but it currently shouts, which will fling all the nearby +// doors open. + +default +{ + state_entry() + { + } + + touch_start(integer total_number) + { + if (llSameGroup(llDetectedKey(0))) llShout(108, "toggle"); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.lsl b/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.lsl deleted file mode 100755 index a233a40f..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.lsl +++ /dev/null @@ -1,247 +0,0 @@ - -// huffware script: turbo lifter, by fred huffhines - -// constants you may want to adjust... - -float minimum_height = 0.5; - // the lowest that the lifter will move -- relative to ground height. - -float maximum_height = 1007.5; - // the highest that the platform will move in absolute height (not relative to ground!). - -// the rationale for having the minimum be based on ground height and the maximum be based -// on absolute heights is that it is often the case that one wants to have the elevator meet -// people at the ground, and then take them high up in the clouds. given that main usage -// pattern, we've found it way more convenient to reckon the base against ground but leave -// the top absolute so we can match sky houses et al. - -float movement_per_cycle = 100.0; - // how much change in height occurs per timer hit. - -integer SLEEP_DURATION = 28; - // how long the elevator pauses at the stations. - -integer PAUSE_DURATION = 14; - // the delay added when a user clicks on the elevator. - -integer COUNTDOWN_INTERVAL = 8; - // the frequency of the countdown message about departure. - -integer WHISPER_COUNTDOWN = FALSE; - // if TRUE, the elevator will count down its departure schedule. - -////////////// - -// requires: jaunting library v14.0 or higher. -////////////// -integer JAUNT_HUFFWARE_ID = 10008; - // the unique id within the huffware system for the jaunt script to - // accept commands on. this is used in llMessageLinked as the num parameter. -string HUFFWARE_PARM_SEPARATOR = "{~~~}"; - // this pattern is an uncommon thing to see in text, so we use it to separate - // our commands in link messages. -string HUFFWARE_ITEM_SEPARATOR = "{|||}"; - // used to separate lists of items from each other when stored inside a parameter. - // this allows lists to be passed as single string parameters if needed. -integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. -////////////// -string JAUNT_COMMAND = "#jaunt#"; - // command used to tell jaunt script to move object. -////////////// - -////////////// - -// global variables and their default values... - -integer going_up = FALSE; - // remembers which direction the platform is moving. - -integer next_movement; - // when the lift should next move. delayed for stations and - // when user chooses to delay take-off. - -////////////// - -float height_above_ground() -{ - vector position = llGetPos(); - vector size = llGetAgentSize(llGetOwner()); - return position.z - llGround(<0.0,0.0,0.0>) - size.z; -} - -jaunt_to_target(vector target) -{ - llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, (string)target); -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); - // initialize the next movement so elevator doesn't just zoom off. - next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; - // we move at one second intervals due to our use of unix time, - // which has a resolution of seconds. - llSetTimerEvent(1.0); - } - -//need commands, like start, or call to come down. -// need elevator system that would call it. -// if elevator style deal, needs to not delay so silly like. -// when jaunting, go go go. - - timer() - { - integer time_now = llGetUnixTime(); - // make sure it's time to do something. - if (time_now < next_movement) { - integer time_left = next_movement - time_now; - if ( (time_left <= 2) || !(time_left % COUNTDOWN_INTERVAL) ) { - if (WHISPER_COUNTDOWN) { -//hmmm: abstract pluralizer out as separate function. - string plural = "s"; - if (time_left == 1) plural = ""; - llWhisper(0, "Time remaining before departure: " - + (string)time_left + " second" + plural + "."); - } - } - return; // not time to move yet. - } - // set the next movement time to be without any delay, until we know better. - next_movement = llGetUnixTime(); - // compute where we should jump to next. - vector next_location = llGetPos(); - // add in the appropriate amount to our height. - if (going_up) next_location += <0.0, 0.0, movement_per_cycle>; - else next_location -= <0.0, 0.0, movement_per_cycle>; - // check whether we've hit one of our extremes. - if (next_location.z >= maximum_height) { - going_up = FALSE; // start going down. - next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; - next_location.z = maximum_height; - } else if (next_location.z <= minimum_height + llGround(<0.0,0.0,0.0>)) { - going_up = TRUE; // begin going up. - next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; - next_location.z = minimum_height + llGround(<0.0,0.0,0.0>); - } - // now actually go to where we decided. - jaunt_to_target(next_location); - } - - touch_start(integer total_number) - { - next_movement += (integer)PAUSE_DURATION; - llWhisper(0, "Your click delays departure by " + (string)PAUSE_DURATION + " seconds."); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.txt b/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.txt new file mode 100755 index 00000000..a233a40f --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/turbo_lifter_v5.7.txt @@ -0,0 +1,247 @@ + +// huffware script: turbo lifter, by fred huffhines + +// constants you may want to adjust... + +float minimum_height = 0.5; + // the lowest that the lifter will move -- relative to ground height. + +float maximum_height = 1007.5; + // the highest that the platform will move in absolute height (not relative to ground!). + +// the rationale for having the minimum be based on ground height and the maximum be based +// on absolute heights is that it is often the case that one wants to have the elevator meet +// people at the ground, and then take them high up in the clouds. given that main usage +// pattern, we've found it way more convenient to reckon the base against ground but leave +// the top absolute so we can match sky houses et al. + +float movement_per_cycle = 100.0; + // how much change in height occurs per timer hit. + +integer SLEEP_DURATION = 28; + // how long the elevator pauses at the stations. + +integer PAUSE_DURATION = 14; + // the delay added when a user clicks on the elevator. + +integer COUNTDOWN_INTERVAL = 8; + // the frequency of the countdown message about departure. + +integer WHISPER_COUNTDOWN = FALSE; + // if TRUE, the elevator will count down its departure schedule. + +////////////// + +// requires: jaunting library v14.0 or higher. +////////////// +integer JAUNT_HUFFWARE_ID = 10008; + // the unique id within the huffware system for the jaunt script to + // accept commands on. this is used in llMessageLinked as the num parameter. +string HUFFWARE_PARM_SEPARATOR = "{~~~}"; + // this pattern is an uncommon thing to see in text, so we use it to separate + // our commands in link messages. +string HUFFWARE_ITEM_SEPARATOR = "{|||}"; + // used to separate lists of items from each other when stored inside a parameter. + // this allows lists to be passed as single string parameters if needed. +integer REPLY_DISTANCE = 100008; // offset added to service's huffware id in reply IDs. +////////////// +string JAUNT_COMMAND = "#jaunt#"; + // command used to tell jaunt script to move object. +////////////// + +////////////// + +// global variables and their default values... + +integer going_up = FALSE; + // remembers which direction the platform is moving. + +integer next_movement; + // when the lift should next move. delayed for stations and + // when user chooses to delay take-off. + +////////////// + +float height_above_ground() +{ + vector position = llGetPos(); + vector size = llGetAgentSize(llGetOwner()); + return position.z - llGround(<0.0,0.0,0.0>) - size.z; +} + +jaunt_to_target(vector target) +{ + llMessageLinked(LINK_THIS, JAUNT_HUFFWARE_ID, JAUNT_COMMAND, (string)target); +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); + // initialize the next movement so elevator doesn't just zoom off. + next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; + // we move at one second intervals due to our use of unix time, + // which has a resolution of seconds. + llSetTimerEvent(1.0); + } + +//need commands, like start, or call to come down. +// need elevator system that would call it. +// if elevator style deal, needs to not delay so silly like. +// when jaunting, go go go. + + timer() + { + integer time_now = llGetUnixTime(); + // make sure it's time to do something. + if (time_now < next_movement) { + integer time_left = next_movement - time_now; + if ( (time_left <= 2) || !(time_left % COUNTDOWN_INTERVAL) ) { + if (WHISPER_COUNTDOWN) { +//hmmm: abstract pluralizer out as separate function. + string plural = "s"; + if (time_left == 1) plural = ""; + llWhisper(0, "Time remaining before departure: " + + (string)time_left + " second" + plural + "."); + } + } + return; // not time to move yet. + } + // set the next movement time to be without any delay, until we know better. + next_movement = llGetUnixTime(); + // compute where we should jump to next. + vector next_location = llGetPos(); + // add in the appropriate amount to our height. + if (going_up) next_location += <0.0, 0.0, movement_per_cycle>; + else next_location -= <0.0, 0.0, movement_per_cycle>; + // check whether we've hit one of our extremes. + if (next_location.z >= maximum_height) { + going_up = FALSE; // start going down. + next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; + next_location.z = maximum_height; + } else if (next_location.z <= minimum_height + llGround(<0.0,0.0,0.0>)) { + going_up = TRUE; // begin going up. + next_movement = llGetUnixTime() + (integer)SLEEP_DURATION; + next_location.z = minimum_height + llGround(<0.0,0.0,0.0>); + } + // now actually go to where we decided. + jaunt_to_target(next_location); + } + + touch_start(integer total_number) + { + next_movement += (integer)PAUSE_DURATION; + llWhisper(0, "Your click delays departure by " + (string)PAUSE_DURATION + " seconds."); + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.lsl deleted file mode 100755 index d9479ad9..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.lsl +++ /dev/null @@ -1,24 +0,0 @@ - -// huffware script: uuid shower, by fred huffhines -// -// a simple script that shows an avatar their universally unique ID. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. - -default -{ - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() {} - - touch_start(integer total_number) - { - llSay(0, "Hello " + llDetectedName(0) + ", your UUID is " + (string)llDetectedKey(0)); - } -} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.txt new file mode 100755 index 00000000..d9479ad9 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/uuid_shower_mat_v0.3.txt @@ -0,0 +1,24 @@ + +// huffware script: uuid shower, by fred huffhines +// +// a simple script that shows an avatar their universally unique ID. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. + +default +{ + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() {} + + touch_start(integer total_number) + { + llSay(0, "Hello " + llDetectedName(0) + ", your UUID is " + (string)llDetectedKey(0)); + } +} diff --git a/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.lsl b/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.lsl deleted file mode 100755 index 320bc719..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.lsl +++ /dev/null @@ -1,458 +0,0 @@ - -// huffware script: vendor sales manager, by fred huffhines. -// -// handles the vending of one set of items which are contained inside the vendor -// object. when the customer pays for it, they get a copy in a folder named after -// the object, and the owner gets an instant message describing the purchase. -// -// parts of this script were gratefully snagged from Ilse's Basic Vendor version 1.3, by Ilse Mannonen. -// -// fred's changes are licensed by: -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - -// usage notes: -// -// the config notecard is hopefully pretty self explanatory. -// here's an example config for a random gift vendor... -// price=<18, 37, 0> -// seller_name=gorp -// thank_you=Thank you very much fer your purchase! -// emails=foop@norgrufextorp.cog -// single=random -// text=Random Prize Machine\nPay the random price and get a random prize! -// -// here's an example config for a normal vendor (that gives out all of -// the contents to a customer on purchase)... -// price=82 -// seller_name=gorp -// thank_you=Thank you very much fer your purchase! -// emails=foop@norgrufextorp.cog -// text=Buy an anti-ape machine for your garage! -// -// the split notecard requires a set of lines in the format: -// KEY|PERCENT -// for example: 0000000000bad|30 would give 30 percent of purchases to -// the bogus key. be sure to find out the real keys involved. - -// initial defaults; these need to be overridden by the notecard. -integer price = 9999; -string str_thank_you = "Default thank you message. Thanks."; -string seller_name = "Frodo's Rings"; -string emails = ""; - -// if we're allowed to randomly charge in a range, then this records our range. -integer lowest_price = 0; -integer highest_price = 0; - -// variables for split notecard. -integer splitline = 0; -key splitrequestid; - -// variables for config notecard. -integer configline = 0; -key configrequestid; - -// keys and percentages that profits should be split with. -list splitkeys; -list splitpercents; - -// this is set to true if the vendor should select a single item -// at random from the contents and give it to the customer. -integer single_random_give = FALSE; - -list current_giving_list; // if there is a transaction occurring, this has the contents to be given. - -float REPRICING_PERIOD = 20.0; // how frequently we redo the price of the object, if it's random. - -// lets the potential customer know what is being sold. -describe_product() -{ - if (lowest_price != 0) - llSay(0, "Cost is random and will be between L$" + (string)lowest_price - + " and L$" + (string)highest_price + "."); - else - llSay(0, "Cost is L$" + (string)price + "."); - if (single_random_give) - llSay(0, "This vendor is in random grab-bag mode; purchasers will receive one random object from the contents."); -} - -// process the customer's attempt to hand us their money. -take_their_moolah(key customer, integer amount) -{ - // check the amount they paid. - if ( (amount == price) || ( (lowest_price != 0) && (amount > lowest_price) ) ) { - integer worked = give_objects_appropriately(customer); - if (!worked) { - llSay(0, "Oh my, this is not good. There were no objects left to give out. We'll refund your money now."); - llGiveMoney(customer, amount); - return; - } - - // thank the purchaser. - llSay(0, str_thank_you); - // IM the seller. - llInstantMessage(llGetOwner(), "Yay! " + llKey2Name(customer) - + " just paid me L$" + (string)amount - + " in " + llGetRegionName() + "."); - // do the split. - integer n; - for (n = 0; n < llGetListLength(splitkeys); n++) { - float percentage = llList2Float(splitpercents, n) / 100.0; - integer payout = llRound(price * percentage); - key payee = llList2Key(splitkeys, n); - llInstantMessage(llGetOwner(), "Paying L$" + (string)payout - + " to key " + (string)payee + " in commission."); - llGiveMoney(payee,payout); - string text_percentage = (string)((integer)(percentage * 1000.0) / 10); - llInstantMessage(payee, "Woot! You have been paid a L$" - + (string)payout - + " (" + text_percentage + "%) commission for a sale in " - + llGetRegionName() - + "--customer name is " + llKey2Name(customer) - + "."); - } - // send out email alerts if there are any recipients. - list email_addrs = llParseString2List(emails, ["|"], []); - for (n = 0; n < llGetListLength(email_addrs); n++) { - string curr = llList2String(email_addrs, n); - llEmail(curr, llGetObjectName() + " made a sale in " + llGetRegionName(), - "Wheee, there was a sale in " + llGetRegionName() + " of these items " - + dump_list(current_giving_list) + " to a customer named " - + llKey2Name(customer) + "."); - } - } else { - // oops, something stupid. give it all back. - llInstantMessage(customer, "I'm sorry, but you paid L$" + (string)amount + ", and this item costs only L$" + (string)price + ". We'll refund your money right away."); - llGiveMoney(customer, amount); - } - - if (lowest_price != 0) { - // reset the timer to fire soon and change the price. - llSetTimerEvent(0.5); - } -} - -// hands out objects according to the configured process. -integer give_objects_appropriately(key customer) -{ - current_giving_list = []; // clear out last gifts. - if (!single_random_give) { - // this mode is only for the normal non random picker. - // if it's right, give everything but scripts and config notecards. - integer m; - for (m = 0; m < llGetInventoryNumber(INVENTORY_ALL); m++) { - string itemname = llGetInventoryName(INVENTORY_ALL, m); - if (llGetInventoryType(itemname) == INVENTORY_NOTECARD) { - //only add notecards if they don't start with ~ - if (llGetSubString(itemname, 0, 0) != "~") { - current_giving_list += [itemname]; - } - } else { - if (llGetInventoryType(itemname) != INVENTORY_SCRIPT) { - current_giving_list += [itemname]; - } - } - } - } else { - // aha, the freaky random gift giving model. - if (llGetInventoryNumber(INVENTORY_OBJECT) >= 1) { - // we made sure we have something to give out. - integer which = (integer)randomize_within_range(0, llGetInventoryNumber(INVENTORY_OBJECT) - 1, FALSE); - if (which >= 0) { - current_giving_list += [ llGetInventoryName(INVENTORY_OBJECT, which) ]; - } - } - } - -//llOwnerSay("about to give out " + (string)current_giving_list); - if (llGetListLength(current_giving_list) > 0) { - if (single_random_give) - llGiveInventory(customer, llList2String(current_giving_list, 0)); - else - llGiveInventoryList(customer, seller_name + " - " + llGetObjectName(), current_giving_list); - return TRUE; - } else return FALSE; // oops. -} - -// a wrapper for setting the object's text, but handling carriage returns. -set_text(string object_label) -{ - // reset the label to a decorated version of object name if it was default. - if (object_label == "default") object_label = llGetObjectName(); - integer indy; - integer keep_going = TRUE; - while (keep_going) { - indy = find_substring(object_label, "\\n"); - if (indy < 0) { - keep_going = FALSE; - } else { - object_label = llGetSubString(object_label, 0, indy - 1) - + "\n" + llGetSubString(object_label, indy + 2, -1); - } - } -//log_it("setting text: " + object_label); - llSetText(object_label, <0.4, 0.7, 0.95>, 1.0); -} - -// eats config items that are read from the notecard. -process_configuration_items(string data) -{ - string token = llList2String(llParseString2List(data, ["="], []), 0); - string value = llList2String(llParseString2List(data, ["="], []), 1); - if (token == "price") { - if (is_prefix(value, "<")) { - // we have a random price range definition. - vector ranger = (vector)value; - lowest_price = (integer)ranger.x; - highest_price = (integer)ranger.y; - price = lowest_price; - // we run a timer to keep the price fluctuating for the user. - if (lowest_price != 0) { - // zap the timer event really soon. - llSetTimerEvent(0.5); - } - } else { - // this is hopefully a simple price definition. - price = (integer)value; - lowest_price = 0; // reset so no one gets wrong ideas. - } - if (price == 0) { - llOwnerSay("Failure in setting price; object will be defective until config is fixed."); - } else { - llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); - llMessageLinked(LINK_SET, price, "price", NULL_KEY); - describe_product(); - } - } else if (token == "thank_you") { - str_thank_you = value; - } else if (token == "seller_name") { - seller_name = value; - } else if (token == "emails") { - emails = value; - } else if (token == "single") { - if (value == "random") { - single_random_give = TRUE; - describe_product(); - } - } else if (token == "text") { - set_text(value); -// llSetText(value, <.4, .9, .7>, 1.0); - } - configline++; - configrequestid = llGetNotecardLine("~CONFIG", configline); -} - -////////////// -// from hufflets... - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns a printable form of the list. -string dump_list(list to_show) -{ - integer len = llGetListLength(to_show); - integer i; - string text; - for (i = 0; i < len; i++) { - string next_line = llList2String(to_show, i); - if (find_substring(next_line, " ") >= 0) { - // this guy has a space in it, so quote it. - next_line = "'" + next_line + "'"; - } - text += next_line; - if (i < len - 1) text += " "; - } - return text; -} - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// returns a number at most "maximum" and at least "minimum". -// if "allow_negative" is TRUE, then the return may be positive or negative. -float randomize_within_range(float minimum, float maximum, integer allow_negative) -{ - if (minimum > maximum) { - // flip the two if they are reversed. - float temp = minimum; minimum = maximum; maximum = temp; - } - float to_return = minimum + llFrand(maximum - minimum); - if (allow_negative) { - if (llFrand(1.0) < 0.5) to_return *= -1.0; - } - return to_return; -} - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.5. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { -//log_it("invpo=" + (string)posn); - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. -//log_it("pos=" + (string)space_v_posn); - } - if (space_v_posn < 2) return []; // no space found. -//log_it("space v@" + (string)space_v_posn); - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { -//log_it("indy=" + (string)space_v_posn); - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); -//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -default { - state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } - on_rez(integer parm) { state rerun; } -} -state rerun { state_entry() { state default; } } - -state real_default -{ - state_entry() - { - auto_retire(); // make sure newest addition is only version of script. - splitrequestid = llGetNotecardLine("~SPLIT", splitline); - configrequestid = llGetNotecardLine("~CONFIG", configline); - llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); - llSetText("garp", <0, 0, 0>, 0); - } - - on_rez(integer start_param) { llResetScript(); } - - timer() { - llSetTimerEvent(0); - price = (integer)randomize_within_range(lowest_price, highest_price, FALSE); - llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); - llSetTimerEvent(REPRICING_PERIOD); - } - - money(key customer, integer amount) { take_their_moolah(customer, amount); } - - // restart if something was added to the vendor. - changed(integer change) { - if (change & CHANGED_INVENTORY) { llSleep(3.14159265358); llResetScript(); } - } - - touch_start(integer total_number) - { - // give the first non-config notecard. - integer n; - for (n = 0; n < llGetInventoryNumber(INVENTORY_NOTECARD); n++) { - if (llGetSubString(llGetInventoryName(INVENTORY_NOTECARD, n), 0, 0) != "~") { - llGiveInventory(llDetectedKey(0), llGetInventoryName(INVENTORY_NOTECARD, n)); - return; - } - } - describe_product(); - } - - // read the two configuration notecards. - dataserver(key queryid, string data) - { - if ( (queryid == splitrequestid) && (data != EOF) ) { - list tmp = llParseString2List(data, ["|"], [""]); - if (llGetListLength(tmp) > 1) { - splitpercents += llList2Integer(tmp,1); - splitkeys += llList2Key(tmp,0); - if (splitline == 0) { - llRequestPermissions(llGetOwner(), PERMISSION_DEBIT); - } - splitline++; - splitrequestid = llGetNotecardLine("~SPLIT",splitline); - } - } else if ( (queryid == configrequestid) && (data != EOF) ) { - process_configuration_items(data); - } - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.txt b/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.txt new file mode 100755 index 00000000..320bc719 --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/vendor_sales_manager_v3.1.txt @@ -0,0 +1,458 @@ + +// huffware script: vendor sales manager, by fred huffhines. +// +// handles the vending of one set of items which are contained inside the vendor +// object. when the customer pays for it, they get a copy in a folder named after +// the object, and the owner gets an instant message describing the purchase. +// +// parts of this script were gratefully snagged from Ilse's Basic Vendor version 1.3, by Ilse Mannonen. +// +// fred's changes are licensed by: +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + +// usage notes: +// +// the config notecard is hopefully pretty self explanatory. +// here's an example config for a random gift vendor... +// price=<18, 37, 0> +// seller_name=gorp +// thank_you=Thank you very much fer your purchase! +// emails=foop@norgrufextorp.cog +// single=random +// text=Random Prize Machine\nPay the random price and get a random prize! +// +// here's an example config for a normal vendor (that gives out all of +// the contents to a customer on purchase)... +// price=82 +// seller_name=gorp +// thank_you=Thank you very much fer your purchase! +// emails=foop@norgrufextorp.cog +// text=Buy an anti-ape machine for your garage! +// +// the split notecard requires a set of lines in the format: +// KEY|PERCENT +// for example: 0000000000bad|30 would give 30 percent of purchases to +// the bogus key. be sure to find out the real keys involved. + +// initial defaults; these need to be overridden by the notecard. +integer price = 9999; +string str_thank_you = "Default thank you message. Thanks."; +string seller_name = "Frodo's Rings"; +string emails = ""; + +// if we're allowed to randomly charge in a range, then this records our range. +integer lowest_price = 0; +integer highest_price = 0; + +// variables for split notecard. +integer splitline = 0; +key splitrequestid; + +// variables for config notecard. +integer configline = 0; +key configrequestid; + +// keys and percentages that profits should be split with. +list splitkeys; +list splitpercents; + +// this is set to true if the vendor should select a single item +// at random from the contents and give it to the customer. +integer single_random_give = FALSE; + +list current_giving_list; // if there is a transaction occurring, this has the contents to be given. + +float REPRICING_PERIOD = 20.0; // how frequently we redo the price of the object, if it's random. + +// lets the potential customer know what is being sold. +describe_product() +{ + if (lowest_price != 0) + llSay(0, "Cost is random and will be between L$" + (string)lowest_price + + " and L$" + (string)highest_price + "."); + else + llSay(0, "Cost is L$" + (string)price + "."); + if (single_random_give) + llSay(0, "This vendor is in random grab-bag mode; purchasers will receive one random object from the contents."); +} + +// process the customer's attempt to hand us their money. +take_their_moolah(key customer, integer amount) +{ + // check the amount they paid. + if ( (amount == price) || ( (lowest_price != 0) && (amount > lowest_price) ) ) { + integer worked = give_objects_appropriately(customer); + if (!worked) { + llSay(0, "Oh my, this is not good. There were no objects left to give out. We'll refund your money now."); + llGiveMoney(customer, amount); + return; + } + + // thank the purchaser. + llSay(0, str_thank_you); + // IM the seller. + llInstantMessage(llGetOwner(), "Yay! " + llKey2Name(customer) + + " just paid me L$" + (string)amount + + " in " + llGetRegionName() + "."); + // do the split. + integer n; + for (n = 0; n < llGetListLength(splitkeys); n++) { + float percentage = llList2Float(splitpercents, n) / 100.0; + integer payout = llRound(price * percentage); + key payee = llList2Key(splitkeys, n); + llInstantMessage(llGetOwner(), "Paying L$" + (string)payout + + " to key " + (string)payee + " in commission."); + llGiveMoney(payee,payout); + string text_percentage = (string)((integer)(percentage * 1000.0) / 10); + llInstantMessage(payee, "Woot! You have been paid a L$" + + (string)payout + + " (" + text_percentage + "%) commission for a sale in " + + llGetRegionName() + + "--customer name is " + llKey2Name(customer) + + "."); + } + // send out email alerts if there are any recipients. + list email_addrs = llParseString2List(emails, ["|"], []); + for (n = 0; n < llGetListLength(email_addrs); n++) { + string curr = llList2String(email_addrs, n); + llEmail(curr, llGetObjectName() + " made a sale in " + llGetRegionName(), + "Wheee, there was a sale in " + llGetRegionName() + " of these items " + + dump_list(current_giving_list) + " to a customer named " + + llKey2Name(customer) + "."); + } + } else { + // oops, something stupid. give it all back. + llInstantMessage(customer, "I'm sorry, but you paid L$" + (string)amount + ", and this item costs only L$" + (string)price + ". We'll refund your money right away."); + llGiveMoney(customer, amount); + } + + if (lowest_price != 0) { + // reset the timer to fire soon and change the price. + llSetTimerEvent(0.5); + } +} + +// hands out objects according to the configured process. +integer give_objects_appropriately(key customer) +{ + current_giving_list = []; // clear out last gifts. + if (!single_random_give) { + // this mode is only for the normal non random picker. + // if it's right, give everything but scripts and config notecards. + integer m; + for (m = 0; m < llGetInventoryNumber(INVENTORY_ALL); m++) { + string itemname = llGetInventoryName(INVENTORY_ALL, m); + if (llGetInventoryType(itemname) == INVENTORY_NOTECARD) { + //only add notecards if they don't start with ~ + if (llGetSubString(itemname, 0, 0) != "~") { + current_giving_list += [itemname]; + } + } else { + if (llGetInventoryType(itemname) != INVENTORY_SCRIPT) { + current_giving_list += [itemname]; + } + } + } + } else { + // aha, the freaky random gift giving model. + if (llGetInventoryNumber(INVENTORY_OBJECT) >= 1) { + // we made sure we have something to give out. + integer which = (integer)randomize_within_range(0, llGetInventoryNumber(INVENTORY_OBJECT) - 1, FALSE); + if (which >= 0) { + current_giving_list += [ llGetInventoryName(INVENTORY_OBJECT, which) ]; + } + } + } + +//llOwnerSay("about to give out " + (string)current_giving_list); + if (llGetListLength(current_giving_list) > 0) { + if (single_random_give) + llGiveInventory(customer, llList2String(current_giving_list, 0)); + else + llGiveInventoryList(customer, seller_name + " - " + llGetObjectName(), current_giving_list); + return TRUE; + } else return FALSE; // oops. +} + +// a wrapper for setting the object's text, but handling carriage returns. +set_text(string object_label) +{ + // reset the label to a decorated version of object name if it was default. + if (object_label == "default") object_label = llGetObjectName(); + integer indy; + integer keep_going = TRUE; + while (keep_going) { + indy = find_substring(object_label, "\\n"); + if (indy < 0) { + keep_going = FALSE; + } else { + object_label = llGetSubString(object_label, 0, indy - 1) + + "\n" + llGetSubString(object_label, indy + 2, -1); + } + } +//log_it("setting text: " + object_label); + llSetText(object_label, <0.4, 0.7, 0.95>, 1.0); +} + +// eats config items that are read from the notecard. +process_configuration_items(string data) +{ + string token = llList2String(llParseString2List(data, ["="], []), 0); + string value = llList2String(llParseString2List(data, ["="], []), 1); + if (token == "price") { + if (is_prefix(value, "<")) { + // we have a random price range definition. + vector ranger = (vector)value; + lowest_price = (integer)ranger.x; + highest_price = (integer)ranger.y; + price = lowest_price; + // we run a timer to keep the price fluctuating for the user. + if (lowest_price != 0) { + // zap the timer event really soon. + llSetTimerEvent(0.5); + } + } else { + // this is hopefully a simple price definition. + price = (integer)value; + lowest_price = 0; // reset so no one gets wrong ideas. + } + if (price == 0) { + llOwnerSay("Failure in setting price; object will be defective until config is fixed."); + } else { + llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); + llMessageLinked(LINK_SET, price, "price", NULL_KEY); + describe_product(); + } + } else if (token == "thank_you") { + str_thank_you = value; + } else if (token == "seller_name") { + seller_name = value; + } else if (token == "emails") { + emails = value; + } else if (token == "single") { + if (value == "random") { + single_random_give = TRUE; + describe_product(); + } + } else if (token == "text") { + set_text(value); +// llSetText(value, <.4, .9, .7>, 1.0); + } + configline++; + configrequestid = llGetNotecardLine("~CONFIG", configline); +} + +////////////// +// from hufflets... + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns a printable form of the list. +string dump_list(list to_show) +{ + integer len = llGetListLength(to_show); + integer i; + string text; + for (i = 0; i < len; i++) { + string next_line = llList2String(to_show, i); + if (find_substring(next_line, " ") >= 0) { + // this guy has a space in it, so quote it. + next_line = "'" + next_line + "'"; + } + text += next_line; + if (i < len - 1) text += " "; + } + return text; +} + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// returns a number at most "maximum" and at least "minimum". +// if "allow_negative" is TRUE, then the return may be positive or negative. +float randomize_within_range(float minimum, float maximum, integer allow_negative) +{ + if (minimum > maximum) { + // flip the two if they are reversed. + float temp = minimum; minimum = maximum; maximum = temp; + } + float to_return = minimum + llFrand(maximum - minimum); + if (allow_negative) { + if (llFrand(1.0) < 0.5) to_return *= -1.0; + } + return to_return; +} + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.5. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { +//log_it("invpo=" + (string)posn); + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. +//log_it("pos=" + (string)space_v_posn); + } + if (space_v_posn < 2) return []; // no space found. +//log_it("space v@" + (string)space_v_posn); + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { +//log_it("indy=" + (string)space_v_posn); + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); +//log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +default { + state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; } + on_rez(integer parm) { state rerun; } +} +state rerun { state_entry() { state default; } } + +state real_default +{ + state_entry() + { + auto_retire(); // make sure newest addition is only version of script. + splitrequestid = llGetNotecardLine("~SPLIT", splitline); + configrequestid = llGetNotecardLine("~CONFIG", configline); + llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); + llSetText("garp", <0, 0, 0>, 0); + } + + on_rez(integer start_param) { llResetScript(); } + + timer() { + llSetTimerEvent(0); + price = (integer)randomize_within_range(lowest_price, highest_price, FALSE); + llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]); + llSetTimerEvent(REPRICING_PERIOD); + } + + money(key customer, integer amount) { take_their_moolah(customer, amount); } + + // restart if something was added to the vendor. + changed(integer change) { + if (change & CHANGED_INVENTORY) { llSleep(3.14159265358); llResetScript(); } + } + + touch_start(integer total_number) + { + // give the first non-config notecard. + integer n; + for (n = 0; n < llGetInventoryNumber(INVENTORY_NOTECARD); n++) { + if (llGetSubString(llGetInventoryName(INVENTORY_NOTECARD, n), 0, 0) != "~") { + llGiveInventory(llDetectedKey(0), llGetInventoryName(INVENTORY_NOTECARD, n)); + return; + } + } + describe_product(); + } + + // read the two configuration notecards. + dataserver(key queryid, string data) + { + if ( (queryid == splitrequestid) && (data != EOF) ) { + list tmp = llParseString2List(data, ["|"], [""]); + if (llGetListLength(tmp) > 1) { + splitpercents += llList2Integer(tmp,1); + splitkeys += llList2Key(tmp,0); + if (splitline == 0) { + llRequestPermissions(llGetOwner(), PERMISSION_DEBIT); + } + splitline++; + splitrequestid = llGetNotecardLine("~SPLIT",splitline); + } + } else if ( (queryid == configrequestid) && (data != EOF) ) { + process_configuration_items(data); + } + } +} + diff --git a/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.lsl b/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.lsl deleted file mode 100755 index 6dee724d..00000000 --- a/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.lsl +++ /dev/null @@ -1,187 +0,0 @@ - -// huffware script: zap updater from elevators, by fred huffhines -// -// this script is an evil little assassin that is supposed to remove the updater -// script from the objects it's added to. it should not remove that script from -// any huffotronic devices though. -// this is an attempt to quell some SL stability problems due to some seeming -// combination of numbers of objects and numbers of scripts. -// we hope to be able to add the updater back in automatically later because the -// script pin should still be set. let's see if osgrid has that behavior the same -// as second life did. -// -// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html -// do not use it in objects without fully realizing you are implicitly accepting that license. -// - - -// from hufflets... - -////////////// -// huffware script: auto-retire, by fred huffhines, version 2.8. -// distributed under BSD-like license. -// !! keep in mind that this code must be *copied* into another -// !! script that you wish to add auto-retirement capability to. -// when a script has auto_retire in it, it can be dropped into an -// object and the most recent version of the script will destroy -// all older versions. -// -// the version numbers are embedded into the script names themselves. -// the notation for versions uses a letter 'v', followed by two numbers -// in the form "major.minor". -// major and minor versions are implicitly considered as a floating point -// number that increases with each newer version of the script. thus, -// "hazmap v0.1" might be the first script in the "hazmap" script continuum, -// and "hazmap v3.2" is a more recent version. -// -// example usage of the auto-retirement script: -// default { -// state_entry() { -// auto_retire(); // make sure newest addition is only version of script. -// } -// } -// this script is partly based on the self-upgrading scripts from markov brodsky -// and jippen faddoul. -////////////// -auto_retire() { - string self = llGetScriptName(); // the name of this script. - list split = compute_basename_and_version(self); - if (llGetListLength(split) != 2) return; // nothing to do for this script. - string basename = llList2String(split, 0); // script name with no version attached. - string version_string = llList2String(split, 1); // the version found. - integer posn; - // find any scripts that match the basename. they are variants of this script. - for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); - if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { - // found a basic match at least. - list inv_split = compute_basename_and_version(curr_script); - if (llGetListLength(inv_split) == 2) { - // see if this script is more ancient. - string inv_version_string = llList2String(inv_split, 1); // the version found. - // must make sure that the retiring script is completely the identical basename; - // just matching in the front doesn't make it a relative. - if ( (llList2String(inv_split, 0) == basename) - && ((float)inv_version_string < (float)version_string) ) { - // remove script with same name from inventory that has inferior version. - llRemoveInventory(curr_script); - } - } - } - } -} -// -// separates the base script name and version number. used by auto_retire. -list compute_basename_and_version(string to_chop_up) -{ - // minimum script name is 2 characters plus a version. - integer space_v_posn; - // find the last useful space and 'v' combo. - for (space_v_posn = llStringLength(to_chop_up) - 3; - (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); - space_v_posn--) { - // look for space and v but do nothing else. - } - if (space_v_posn < 2) return []; // no space found. - // now we zoom through the stuff after our beloved v character and find any evil - // space characters, which are most likely from SL having found a duplicate item - // name and not so helpfully renamed it for us. - integer indy; - for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { - if (llGetSubString(to_chop_up, indy, indy) == " ") { - // found one; zap it. since we're going backwards we don't need to - // adjust the loop at all. - to_chop_up = llDeleteSubString(to_chop_up, indy, indy); - } - } - string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); - // ditch the space character for our numerical check. - string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); - // strip out a 'v' if there is one. - if (llGetSubString(chop_suffix, 0, 0) == "v") - chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); - // if valid floating point number and greater than zero, that works for our version. - string basename = to_chop_up; // script name with no version attached. - if ((float)chop_suffix > 0.0) { - // this is a big success right here. - basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); - return [ basename, chop_suffix ]; - } - // seems like we found nothing useful. - return []; -} -// -////////////// - -// returns the index of the first occurrence of "pattern" inside -// the "full_string". if it is not found, then a negative number is returned. -integer find_substring(string full_string, string pattern) -{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } - -// returns TRUE if the "prefix" string is the first part of "compare_with". -integer is_prefix(string compare_with, string prefix) -{ return find_substring(compare_with, prefix) == 0; } - -// returns true if this object is a huffotronic updater of some sort. -integer inside_of_updater() -{ - return find_substring(llGetObjectName(), "huffotronic") >= 0; -} - -// stops all the scripts besides this one. -knock_around_other_scripts(integer running_state) -{ - integer indy; - integer insider = inside_of_updater(); - string self_script = llGetScriptName(); - // we set all other scripts to the running state requested. - for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { - string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); - if ( (curr_script != self_script) - && (!insider || matches_server_script(curr_script)) ) { - // this one seems ripe for being set to the state requested. - llSetScriptState(curr_script, running_state); - } - } -} - -string SERVER_SCRIPT = "huffotronic update server"; - // the prefix of our server script that hands out updates. - -// returns true if a script is a version of our update server. -integer matches_server_script(string to_check) -{ - return is_prefix(to_check, SERVER_SCRIPT); -} - -// end hufflets. -////////////// - -default -{ - state_entry() - { - auto_retire(); - if (inside_of_updater()) return; // do nothing else. - - llWhisper(0, "hello, i'm jeeves. pleased to meet you."); - llSleep(32); - - string gotta_zap = "huff-update client v"; - integer i; - for (i = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; i >= 0; i--) { - string cur = llGetInventoryName(INVENTORY_SCRIPT, i); - if (is_prefix(cur, gotta_zap)) { - llWhisper(0, "i, jeeves, will now clean out this script: " + cur); - llRemoveInventory(cur); - } - } - llSleep(14); - knock_around_other_scripts(TRUE); - llSleep(4); - llWhisper(0, "i'm sorry to say sir that i now must bid you adieu, as i am removing myself from the world."); - llSleep(1); - llRemoveInventory(llGetScriptName()); - } -} - diff --git a/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.txt b/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.txt new file mode 100755 index 00000000..6dee724d --- /dev/null +++ b/huffware/huffotronic_tools_n_testers_v6.1/zap_updater_from_elevators_v1.3.txt @@ -0,0 +1,187 @@ + +// huffware script: zap updater from elevators, by fred huffhines +// +// this script is an evil little assassin that is supposed to remove the updater +// script from the objects it's added to. it should not remove that script from +// any huffotronic devices though. +// this is an attempt to quell some SL stability problems due to some seeming +// combination of numbers of objects and numbers of scripts. +// we hope to be able to add the updater back in automatically later because the +// script pin should still be set. let's see if osgrid has that behavior the same +// as second life did. +// +// this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html +// do not use it in objects without fully realizing you are implicitly accepting that license. +// + + +// from hufflets... + +////////////// +// huffware script: auto-retire, by fred huffhines, version 2.8. +// distributed under BSD-like license. +// !! keep in mind that this code must be *copied* into another +// !! script that you wish to add auto-retirement capability to. +// when a script has auto_retire in it, it can be dropped into an +// object and the most recent version of the script will destroy +// all older versions. +// +// the version numbers are embedded into the script names themselves. +// the notation for versions uses a letter 'v', followed by two numbers +// in the form "major.minor". +// major and minor versions are implicitly considered as a floating point +// number that increases with each newer version of the script. thus, +// "hazmap v0.1" might be the first script in the "hazmap" script continuum, +// and "hazmap v3.2" is a more recent version. +// +// example usage of the auto-retirement script: +// default { +// state_entry() { +// auto_retire(); // make sure newest addition is only version of script. +// } +// } +// this script is partly based on the self-upgrading scripts from markov brodsky +// and jippen faddoul. +////////////// +auto_retire() { + string self = llGetScriptName(); // the name of this script. + list split = compute_basename_and_version(self); + if (llGetListLength(split) != 2) return; // nothing to do for this script. + string basename = llList2String(split, 0); // script name with no version attached. + string version_string = llList2String(split, 1); // the version found. + integer posn; + // find any scripts that match the basename. they are variants of this script. + for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn); + if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) { + // found a basic match at least. + list inv_split = compute_basename_and_version(curr_script); + if (llGetListLength(inv_split) == 2) { + // see if this script is more ancient. + string inv_version_string = llList2String(inv_split, 1); // the version found. + // must make sure that the retiring script is completely the identical basename; + // just matching in the front doesn't make it a relative. + if ( (llList2String(inv_split, 0) == basename) + && ((float)inv_version_string < (float)version_string) ) { + // remove script with same name from inventory that has inferior version. + llRemoveInventory(curr_script); + } + } + } + } +} +// +// separates the base script name and version number. used by auto_retire. +list compute_basename_and_version(string to_chop_up) +{ + // minimum script name is 2 characters plus a version. + integer space_v_posn; + // find the last useful space and 'v' combo. + for (space_v_posn = llStringLength(to_chop_up) - 3; + (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v"); + space_v_posn--) { + // look for space and v but do nothing else. + } + if (space_v_posn < 2) return []; // no space found. + // now we zoom through the stuff after our beloved v character and find any evil + // space characters, which are most likely from SL having found a duplicate item + // name and not so helpfully renamed it for us. + integer indy; + for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) { + if (llGetSubString(to_chop_up, indy, indy) == " ") { + // found one; zap it. since we're going backwards we don't need to + // adjust the loop at all. + to_chop_up = llDeleteSubString(to_chop_up, indy, indy); + } + } + string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1); + // ditch the space character for our numerical check. + string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1); + // strip out a 'v' if there is one. + if (llGetSubString(chop_suffix, 0, 0) == "v") + chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1); + // if valid floating point number and greater than zero, that works for our version. + string basename = to_chop_up; // script name with no version attached. + if ((float)chop_suffix > 0.0) { + // this is a big success right here. + basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1); + return [ basename, chop_suffix ]; + } + // seems like we found nothing useful. + return []; +} +// +////////////// + +// returns the index of the first occurrence of "pattern" inside +// the "full_string". if it is not found, then a negative number is returned. +integer find_substring(string full_string, string pattern) +{ return llSubStringIndex(llToLower(full_string), llToLower(pattern)); } + +// returns TRUE if the "prefix" string is the first part of "compare_with". +integer is_prefix(string compare_with, string prefix) +{ return find_substring(compare_with, prefix) == 0; } + +// returns true if this object is a huffotronic updater of some sort. +integer inside_of_updater() +{ + return find_substring(llGetObjectName(), "huffotronic") >= 0; +} + +// stops all the scripts besides this one. +knock_around_other_scripts(integer running_state) +{ + integer indy; + integer insider = inside_of_updater(); + string self_script = llGetScriptName(); + // we set all other scripts to the running state requested. + for (indy = 0; indy < llGetInventoryNumber(INVENTORY_SCRIPT); indy++) { + string curr_script = llGetInventoryName(INVENTORY_SCRIPT, indy); + if ( (curr_script != self_script) + && (!insider || matches_server_script(curr_script)) ) { + // this one seems ripe for being set to the state requested. + llSetScriptState(curr_script, running_state); + } + } +} + +string SERVER_SCRIPT = "huffotronic update server"; + // the prefix of our server script that hands out updates. + +// returns true if a script is a version of our update server. +integer matches_server_script(string to_check) +{ + return is_prefix(to_check, SERVER_SCRIPT); +} + +// end hufflets. +////////////// + +default +{ + state_entry() + { + auto_retire(); + if (inside_of_updater()) return; // do nothing else. + + llWhisper(0, "hello, i'm jeeves. pleased to meet you."); + llSleep(32); + + string gotta_zap = "huff-update client v"; + integer i; + for (i = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; i >= 0; i--) { + string cur = llGetInventoryName(INVENTORY_SCRIPT, i); + if (is_prefix(cur, gotta_zap)) { + llWhisper(0, "i, jeeves, will now clean out this script: " + cur); + llRemoveInventory(cur); + } + } + llSleep(14); + knock_around_other_scripts(TRUE); + llSleep(4); + llWhisper(0, "i'm sorry to say sir that i now must bid you adieu, as i am removing myself from the world."); + llSleep(1); + llRemoveInventory(llGetScriptName()); + } +} +