The helm contains three scripts:
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2022 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueGet(string k, string data) { if(llStringLength(data) == 0) return ""; if(llStringLength(k) == 0) return ""; list a = llParseStringKeepNulls(data, ["&", "="], []); integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); if(i != -1) return llList2String(a, 2*i+1); return ""; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueSet(string k, string v, string data) { if(llStringLength(k) == 0) return ""; if(llStringLength(v) == 0) return ""; if(llStringLength(data) == 0) return k + "=" + v; integer i = llListFindList( llList2ListStrided( llParseString2List(data, ["&", "="], []), 0, -1, 2 ), [ k ]); if(i != -1) return llDumpList2String( llListReplaceList( llParseString2List(data, ["&"], []), [ k + "=" + v ], i, i), "&"); return data + "&" + k + "=" + v; } animate(integer on) { list param = llGetLinkPrimitiveParams( LINK_THIS, [ PRIM_TYPE ] ); vector dimple = llList2Vector( param, 5 ); float cursor = dimple.x; if(on) { while((cursor -= .01) >= 0) { llSetLinkPrimitiveParamsFast( LINK_THIS, [ PRIM_TYPE, PRIM_TYPE_SPHERE, PRIM_HOLE_SQUARE, <0, 1, 0>, 70, ZERO_VECTOR, <cursor, .8, 0> ] ); } return; } while((cursor += .01) <= .78) { llSetLinkPrimitiveParamsFast( LINK_THIS, [ PRIM_TYPE, PRIM_TYPE_SPHERE, PRIM_HOLE_SQUARE, <0, 1, 0>, 70, ZERO_VECTOR, <cursor, .8, 0> ] ); } } // for notecard reading integer line; // key-value data will be read into this list list tuples; list colours; key owner; float step; float dampening; integer channel; integer handle; string exception; integer share; integer csh; string identify = "c148cf4"; integer arm = FALSE; default { state_entry() { llSetText( "", <1,1,1>, 1.0 ); llParticleSystem([]); if(llGetAttached() == 0) { exception = "Item not attached."; state fault; } owner = llGetOwner(); share = (integer)("0x8" + identify); integer status = (integer)wasKeyValueGet( "status", llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ); if(status) { state configure; } state off; } attach(key id) { owner = id; } } state configure { state_entry() { if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { exception = "No \"configuration\" notecard."; state fault; } line = 0; tuples = []; colours = []; llGetNotecardLine("configuration", line); } dataserver(key id, string data) { if(data == EOF) { // invariant, length(tuples) % 2 == 0 if(llGetListLength(tuples) % 2 != 0) { exception = "Configuration notecard broken."; state fault; } // retrieve the step size step = llList2Float( tuples, llListFindList( tuples, [ "step" ] ) + 1 ); dampening = llList2Float( tuples, llListFindList( tuples, [ "dampening" ] ) + 1 ); // add notecard colours to the list of colours integer i = llGetListLength(tuples) - 1; do { string n = llList2String(tuples, i); if(llSubStringIndex(n, "colour_") != -1) { list l = llParseString2List(n, ["_"], []); if(llList2String(l, 0) == "colour") { vector colour = (vector)llList2String( tuples, llListFindList( tuples, [ "colour_" + llList2String(l, 1) ] ) + 1 ); colours += colour; } } } while(--i > -1); vector colour = (vector)wasKeyValueGet( "colour", llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ); if(llListFindList(colours, [ colour ]) != -1) { while(llList2Vector(colours, -1) != colour) { vector car = llList2Vector(colours, 0); colours = llDeleteSubList(colours, 0, 0); colours += car; } state on; } llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "colour", (string)llList2Vector(colours, 0), llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); state on; } if(data == "") jump continue; integer i = llSubStringIndex(data, "#"); if(i != -1) data = llDeleteSubString(data, i, -1); list o = llParseString2List(data, ["="], []); // get rid of starting and ending quotes string k = llDumpList2String( llParseString2List( llStringTrim( llList2String( o, 0 ), STRING_TRIM), ["\""], [] ), "\""); string v = llDumpList2String( llParseString2List( llStringTrim( llList2String( o, 1 ), STRING_TRIM), ["\""], [] ), "\""); if(k == "" || v == "") jump continue; tuples += k; tuples += v; @continue; llGetNotecardLine("configuration", ++line); } attach(key id) { owner = id; } } state on { state_entry() { llParticleSystem([]); if(owner == NULL_KEY && llGetAttached() == 0) { exception = "Object not attached."; state fault; } llRequestPermissions( owner, PERMISSION_TAKE_CONTROLS ); } touch_start(integer num) { llParticleSystem([]); if(owner == NULL_KEY && llGetAttached() == 0) { exception = "Object not attached."; state fault; } vector car = llList2Vector(colours, 0); colours = llDeleteSubList(colours, 0, 0); colours += car; llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "colour", (string)car, llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); string md5 = llMD5String( (string)car, 0 ); channel = (integer)("0x8" + llGetSubString(md5, 0, 6)); llListenRemove(handle); handle = llListen( channel, "", "", "" ); llSetColor( car, ALL_SIDES ); } link_message(integer sender, integer num, string str, key id) { if(!num) { animate(FALSE); llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "status", (string)0, llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); string data = ""; data = wasKeyValueSet( "status", "off", data ); llRegionSay( share, data ); state off; } } listen(integer channel, string name, key id, string message) { llSetTimerEvent(1); llStopMoveToTarget(); key object = llList2Key( llGetObjectDetails( id, [ OBJECT_OWNER ] ), 0 ); if(object == owner) { string status = wasKeyValueGet( "status", message ); if(status == "off") { state off; } if(status == "on") { llRequestPermissions( owner, PERMISSION_TAKE_CONTROLS ); return; } } string action = wasKeyValueGet( "level", message ); if(action == "") { return; } if(!arm) { llParticleSystem( [ // Texture Parameters: //PSYS_SRC_TEXTURE, llGetInventoryName(INVENTORY_TEXTURE, 0), PSYS_PART_START_SCALE, <0.1, 0.1, 0>, PSYS_PART_END_SCALE, <0.1, 0.1, 0>, PSYS_PART_START_COLOR, <1.00,1.00,1.00>, PSYS_PART_END_COLOR, <1.00,1.00,1.00>, PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, 1.0, // Production Parameters: PSYS_SRC_BURST_PART_COUNT, 8, PSYS_SRC_BURST_RATE, 0.01, PSYS_PART_MAX_AGE, 2.0, // PSYS_SRC_MAX_AGE, 0.00, PSYS_SRC_TARGET_KEY, id, // Placement Parameters: PSYS_SRC_PATTERN, 4, // 1=DROP, 2=EXPLODE, 4=ANGLE, 8=CONE, // Placement Parameters (for any non-DROP pattern): PSYS_SRC_BURST_SPEED_MIN, 1.2, PSYS_SRC_BURST_SPEED_MAX, 1.2, PSYS_SRC_BURST_RADIUS, 00.1, // Placement Parameters (only for ANGLE & CONE patterns): // PSYS_SRC_ANGLE_BEGIN, 0.50 * PI, PSYS_SRC_ANGLE_END, 0.50 * PI, PSYS_SRC_OMEGA, <1.00, 00.00, 0.00>, // After-Effect & Influence Parameters: PSYS_SRC_ACCEL, <-1.00, -00.1, -00.1>, // PSYS_SRC_TARGET_KEY, (key) llGetLinkKey(llGetLinkNumber() + 1), PSYS_PART_FLAGS, ( 0 // Texture Options: | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK // After-effect & Influence Options: // | PSYS_PART_WIND_MASK // | PSYS_PART_BOUNCE_MASK // | PSYS_PART_FOLLOW_SRC_MASK | PSYS_PART_TARGET_POS_MASK // | PSYS_PART_TARGET_LINEAR_MASK ) //end of particle settings ] ); arm = TRUE; } key owner = llList2Key( llGetObjectDetails( id, [ OBJECT_OWNER ] ), 0 ); rotation turn = llList2Rot( llGetObjectDetails( owner, [ OBJECT_ROT ] ), 0 ); vector fwrd = llRot2Fwd(turn); vector left = llRot2Left(turn); vector position = llGetPos(); integer level = (integer)action; if (level & CONTROL_UP) { position += <0, 0, step>; } if (level & CONTROL_DOWN) { position += <0, 0, -step>; } if (level & CONTROL_FWD) { position = position + fwrd * step; } if (level & CONTROL_BACK) { position = position - fwrd * step; } if ((level & CONTROL_LEFT) || (level & CONTROL_ROT_LEFT)) { position = position + left * step; } if ((level & CONTROL_RIGHT) || (level & CONTROL_ROT_RIGHT)) { position = position - left * step; } llMoveToTarget( position, dampening ); } timer() { llSetTimerEvent(0); llParticleSystem([]); arm = FALSE; } control(key id, integer level, integer edge) { string data = ""; data = wasKeyValueSet( "level", (string)level, data ); llRegionSay( channel, data ); } run_time_permissions(integer permissions) { if (permissions & PERMISSION_TAKE_CONTROLS) { llTakeControls( CONTROL_FWD | CONTROL_BACK | CONTROL_LEFT | CONTROL_ROT_LEFT | CONTROL_RIGHT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN, TRUE, FALSE ); animate(TRUE); llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "status", (string)1, llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); vector colour = (vector)wasKeyValueGet( "colour", llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ); string md5 = llMD5String( (string)colour, 0 ); llSetColor( colour, ALL_SIDES ); channel = (integer)("0x8" + llGetSubString(md5, 0, 6)); llListenRemove(handle); handle = llListen( channel, "", "", "" ); string data = ""; data = wasKeyValueSet( "status", "on", data ); llRegionSay( share, data ); csh = llListen( share, "", "", "" ); } } attach(key id) { if(id != NULL_KEY && llGetAttached() != 0) { owner = id; llRequestPermissions( owner, PERMISSION_TAKE_CONTROLS ); return; } } state_exit() { llListenRemove(csh); llListenRemove(channel); } } state off { state_entry() { llParticleSystem([]); llReleaseControls(); animate(FALSE); llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "status", (string)0, llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); llSetColor( <1, 1, 1>, ALL_SIDES ); string data = ""; data = wasKeyValueSet( "status", "off", data ); llRegionSay( share, data ); csh = llListen( share, "", "", "" ); } listen(integer channel, string name, key id, string message) { key object = llList2Key( llGetObjectDetails( id, [ OBJECT_OWNER ] ), 0 ); if(object == owner) { string status = wasKeyValueGet( "status", message ); if(status == "on") { state on; } } } link_message(integer sender, integer num, string str, key id) { if(num) { vector colour = (vector)wasKeyValueGet( "colour", llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ); llSetColor( colour, ALL_SIDES ); animate(TRUE); llSetLinkPrimitiveParamsFast( 2, [ PRIM_DESC, wasKeyValueSet( "status", (string)1, llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ) ] ); string data = ""; data = wasKeyValueSet( "status", "on", data ); llRegionSay( share, data ); state on; } } attach(key id) { if(id != NULL_KEY && llGetAttached() != 0) { owner = id; return; } } state_exit() { llListenRemove(csh); } } state fault { state_entry() { llSetText(exception, <1,1,1>, 1.0); llParticleSystem( [ PSYS_SRC_TEXTURE, llGetInventoryName(0, 0), PSYS_PART_START_SCALE,<0.2, 0.2, 0>, PSYS_PART_END_SCALE,<0.2, 0.2, 0>, PSYS_PART_START_COLOR,<1, 1, 1>, PSYS_PART_END_COLOR,<1,1,1>, PSYS_PART_START_ALPHA,1, PSYS_PART_END_ALPHA, 1, PSYS_SRC_BURST_PART_COUNT, 1, 13, 0.5, PSYS_PART_MAX_AGE,.3, PSYS_SRC_MAX_AGE, 0.0, PSYS_SRC_PATTERN, 4, PSYS_SRC_BURST_SPEED_MIN, 0.0, 18, 0.0, 22, 0.03*3.141593, PSYS_SRC_ANGLE_END, 0*3.141593, 8,<0.0,0.0,0>, 0,(0|1|PSYS_PART_EMISSIVE_MASK) ] ); } on_rez(integer num) { llResetScript(); } attach(key id) { llResetScript(); } changed(integer change) { llResetScript(); } }
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2022 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueGet(string k, string data) { if(llStringLength(data) == 0) return ""; if(llStringLength(k) == 0) return ""; list a = llParseStringKeepNulls(data, ["&", "="], []); integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); if(i != -1) return llList2String(a, 2*i+1); return ""; } default { state_entry() { integer status = (integer)wasKeyValueGet( "status", llList2String( llGetLinkPrimitiveParams( 2, [ PRIM_DESC ] ), 0 ) ); if(status) { state on; } state off; } attach(key id) { llResetScript(); } } state on { state_entry() { llMoveToTarget( llGetPos() - <0, 0, .1>, 0.05 ); } link_message(integer sender, integer num, string str, key id) { if(!num) { state off; } } attach(key id) { if(id != NULL_KEY && llGetAttached() != 0) { llResetScript(); } } } state off { state_entry() { llStopMoveToTarget(); } link_message(integer sender, integer num, string str, key id) { if(num) { state on; } } attach(key id) { if(id != NULL_KEY && llGetAttached() != 0) { llResetScript(); } } }
integer o = FALSE; default { touch_start(integer total_number) { llMessageLinked(LINK_SET, o = !o, "", NULL_KEY); } }
The helm contains a notecard named configuration
that can be used to configure various parameters without editing the script.
step = .5 dampening = .1 colour_1 = <.5, 1, 1> colour_2 = <1, .5, 1> colour_3 = <1, 1, .5> colour_4 = <1, 1, 1> colour_5 = <1, .5, .0> colour_6 = <.5, 1, .5>
If the user wishes to display more colors on the helm, color vectors can be added to the notecard by following the color_
naming convention. For instance, following the sequence in the already existing notecard, the color black could be added by adding another line to the notecard:
colour_7 = <0, 0, 0>
Please make sure to leave an empty newline at the end of the notecard or the script will not be able to read it properly.