Table of Contents

Reference

Scripts

The helm contains three scripts:

Helm

///////////////////////////////////////////////////////////////////////////
//  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();
    }
}

Move-Lock

///////////////////////////////////////////////////////////////////////////
//  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();
        }
    }
}

Toggler

integer o = FALSE;
 
default {
    touch_start(integer total_number) {
        llMessageLinked(LINK_SET, o = !o, "", NULL_KEY);
    }
}

Notecard

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.

Texture

A texture is included that is displayed whenever the helm reaches an unexpected state.