2 //huffware script: swiveller, modified by fred huffhines.
5 // 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.
6 // 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.
8 // fred's modifications are licensed by:
9 // this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html
10 // do not use it in objects without fully realizing you are implicitly accepting that license.
13 // configuration variables -- these control how the swing behaves.
15 integer is_swinging = FALSE; // if set to FALSE, then the swing is not running when rezzed.
17 float SWING_PERIOD = 0.4;
18 // the delay between changing the swing's position. decrease this number to increase
21 integer SWING_STEPS = 12;
22 // The total number of steps in the swing's path. More steps makes for a
23 // smoother swing. More steps (alone) means slower swinging also--time for
24 // a complete swing cycle is SWING_STEPS * swing_period.
26 integer SWING_ANGLE_DEGREES = 10;
27 // How far from the vertical the swing will move.
28 //This is in both directions?
32 integer swing_step = 1;
33 // the current swing position.
39 rotation Inverse(rotation r) { return <-r.x, -r.y, -r.z, r.s>; }
41 rotation GetParentRot() { return Inverse(llGetLocalRot()) * llGetRot(); }
43 SetLocalRot(rotation x) { llSetRot(x*Inverse(GetParentRot())); }
49 // huffware script: auto-retire, by fred huffhines, version 2.5.
50 // distributed under BSD-like license.
51 // !! keep in mind that this code must be *copied* into another
52 // !! script that you wish to add auto-retirement capability to.
53 // when a script has auto_retire in it, it can be dropped into an
54 // object and the most recent version of the script will destroy
55 // all older versions.
57 // the version numbers are embedded into the script names themselves.
58 // the notation for versions uses a letter 'v', followed by two numbers
59 // in the form "major.minor".
60 // major and minor versions are implicitly considered as a floating point
61 // number that increases with each newer version of the script. thus,
62 // "hazmap v0.1" might be the first script in the "hazmap" script continuum,
63 // and "hazmap v3.2" is a more recent version.
65 // example usage of the auto-retirement script:
68 // auto_retire(); // make sure newest addition is only version of script.
71 // this script is partly based on the self-upgrading scripts from markov brodsky
72 // and jippen faddoul.
75 string self = llGetScriptName(); // the name of this script.
76 list split = compute_basename_and_version(self);
77 if (llGetListLength(split) != 2) return; // nothing to do for this script.
78 string basename = llList2String(split, 0); // script name with no version attached.
79 string version_string = llList2String(split, 1); // the version found.
81 // find any scripts that match the basename. they are variants of this script.
82 for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) {
83 //log_it("invpo=" + (string)posn);
84 string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn);
85 if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) {
86 // found a basic match at least.
87 list inv_split = compute_basename_and_version(curr_script);
88 if (llGetListLength(inv_split) == 2) {
89 // see if this script is more ancient.
90 string inv_version_string = llList2String(inv_split, 1); // the version found.
91 // must make sure that the retiring script is completely the identical basename;
92 // just matching in the front doesn't make it a relative.
93 if ( (llList2String(inv_split, 0) == basename)
94 && ((float)inv_version_string < (float)version_string) ) {
95 // remove script with same name from inventory that has inferior version.
96 llRemoveInventory(curr_script);
103 // separates the base script name and version number. used by auto_retire.
104 list compute_basename_and_version(string to_chop_up)
106 // minimum script name is 2 characters plus a version.
107 integer space_v_posn;
108 // find the last useful space and 'v' combo.
109 for (space_v_posn = llStringLength(to_chop_up) - 3;
110 (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v");
112 // look for space and v but do nothing else.
113 //log_it("pos=" + (string)space_v_posn);
115 if (space_v_posn < 2) return []; // no space found.
116 //log_it("space v@" + (string)space_v_posn);
117 // now we zoom through the stuff after our beloved v character and find any evil
118 // space characters, which are most likely from SL having found a duplicate item
119 // name and not so helpfully renamed it for us.
121 for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) {
122 //log_it("indy=" + (string)space_v_posn);
123 if (llGetSubString(to_chop_up, indy, indy) == " ") {
124 // found one; zap it. since we're going backwards we don't need to
125 // adjust the loop at all.
126 to_chop_up = llDeleteSubString(to_chop_up, indy, indy);
127 //log_it("saw case of previously redundant item, aieee. flattened: " + to_chop_up);
130 string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1);
131 // ditch the space character for our numerical check.
132 string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1);
133 // strip out a 'v' if there is one.
134 if (llGetSubString(chop_suffix, 0, 0) == "v")
135 chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1);
136 // if valid floating point number and greater than zero, that works for our version.
137 string basename = to_chop_up; // script name with no version attached.
138 if ((float)chop_suffix > 0.0) {
139 // this is a big success right here.
140 basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1);
141 return [ basename, chop_suffix ];
143 // seems like we found nothing useful.
151 state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; }
152 on_rez(integer parm) { state rerun; }
154 state rerun { state_entry() { state default; } }
160 normal = llRot2Euler(llGetRot());
161 swingRad = SWING_ANGLE_DEGREES * DEG_TO_RAD;
162 llSetTouchText("Swing");
164 touch_start(integer num)
168 llSetTouchText("Swing");
171 llSetTouchText("Stop swing");
172 llSetTimerEvent(SWING_PERIOD);
177 float stepOffset = (float)swing_step / SWING_STEPS * TWO_PI;
178 if (swing_step > SWING_STEPS) swing_step = 1;
179 if (!is_swinging && (swing_step>=SWING_STEPS || swing_step==SWING_STEPS/2)) {
180 llSetTimerEvent(0.0);
181 SetLocalRot(llEuler2Rot(<normal.x, normal.y,
182 normal.z + swingRad*llSin(stepOffset)>));
184 SetLocalRot(llEuler2Rot(<normal.x, normal.y,
185 normal.z + swingRad*llSin(stepOffset)>));
191 normal = llRot2Euler(llGetRot());