From 99482869f13bfc9bdb58aed88d0b334cf902c17b Mon Sep 17 00:00:00 2001 From: Samantha Wright Date: Wed, 23 Jul 2025 04:15:43 -0700 Subject: [PATCH] initial commit of examples --- ARES/hardware/examples/active/icon-mono.lsl | 344 ++++++++++++++ .../examples/charge/sit-anywhere-charger.lsl | 69 +++ .../charge/touch-to-charge-limited.lsl | 106 +++++ .../examples/charge/touch-to-charge.lsl | 58 +++ ARES/hardware/examples/passive/bolts.lsl | 70 +++ .../flicker/flicker-classic-full-linkset.lsl | 88 ++++ .../flicker/flicker-mono-autoconf-holo.lsl | 211 +++++++++ .../passive/flicker/flicker-mono-autoconf.lsl | 211 +++++++++ .../passive/flicker/flicker-mono-classic.lsl | 117 +++++ .../flicker/flicker-tetra-autoconf-holo.lsl | 426 ++++++++++++++++++ .../flicker/flicker-tetra-autoconf.lsl | 365 +++++++++++++++ .../flicker/sit-anywhere-flicker-mono.lsl | 103 +++++ ARES/hardware/examples/public/ping.lsl | 77 ++++ .../examples/repair/touch-to-repair.lsl | 176 ++++++++ ARES/hardware/examples/tesi/storage-tank.lsl | 405 +++++++++++++++++ ARES/hardware/examples/tesi/storage-tank.txt | 34 ++ 16 files changed, 2860 insertions(+) create mode 100644 ARES/hardware/examples/active/icon-mono.lsl create mode 100644 ARES/hardware/examples/charge/sit-anywhere-charger.lsl create mode 100644 ARES/hardware/examples/charge/touch-to-charge-limited.lsl create mode 100644 ARES/hardware/examples/charge/touch-to-charge.lsl create mode 100644 ARES/hardware/examples/passive/bolts.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-classic-full-linkset.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-mono-autoconf-holo.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-mono-autoconf.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-mono-classic.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf-holo.lsl create mode 100644 ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf.lsl create mode 100644 ARES/hardware/examples/passive/flicker/sit-anywhere-flicker-mono.lsl create mode 100644 ARES/hardware/examples/public/ping.lsl create mode 100644 ARES/hardware/examples/repair/touch-to-repair.lsl create mode 100644 ARES/hardware/examples/tesi/storage-tank.lsl create mode 100644 ARES/hardware/examples/tesi/storage-tank.txt diff --git a/ARES/hardware/examples/active/icon-mono.lsl b/ARES/hardware/examples/active/icon-mono.lsl new file mode 100644 index 0000000..c5eee8d --- /dev/null +++ b/ARES/hardware/examples/active/icon-mono.lsl @@ -0,0 +1,344 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2014–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Chromatic Communicator (Akashic Icon) Template (single-color version) + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +// edit line 83 to control which faces/prims light up + + +#include +#include + +#define ICON_VERSION "9.0" + +integer L_CONTROL = 0; +integer L_LIGHTS = 0; + +vector yes = <0.0, 1.0, 0.5>; +vector no = <1.0, 0.0, 0.5>; +vector love = <0.8, 0.0, 1.0>; + +vector victory = <0.8, 0.9, 1.0>; +vector particles = <0.4, 0.9, 1.0>; +vector defeat = <1.0, 0.0, 0.0>; +vector question = <0.0, 0.5, 1.0>; + +vector jeep = <0.5, 1.0, 0.0>; + +vector off = <0.0, 0.0, 0.0>; + +vector color = <0.7, 0.8, 1>; +// vector color = <0.388, 0.275, 0.796>; + +float min_glow = 0.1; +float max_glow = 0.4; + +#define C_CAPS 411 +#define C_PUBLIC -9999999 +integer C_CONTROL; +integer C_LIGHTS; + +integer power_on = 1; +integer broken = 0; +integer emitting = 0; + +integer SINK_PRIORITY = 200; + +integer current_si; +key kid; +string tex; + +key avatar; + +color_me(vector color, float level) { + setp(LINK_THIS, [ + PRIM_COLOR, ALL_SIDES, color * level, 1 + ]); +} + +startParticles() { + emitting = 1; + llParticleSystem([ + PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_TARGET_POS_MASK | PSYS_PART_INTERP_SCALE_MASK |PSYS_PART_INTERP_COLOR_MASK, + PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE, + PSYS_SRC_BURST_RADIUS, 0, + PSYS_PART_START_COLOR, color, + PSYS_PART_START_ALPHA, 0.1, + PSYS_PART_END_COLOR, color, + PSYS_PART_END_ALPHA, 0.2, + PSYS_PART_START_SCALE, <0.1, 0.1, 0>, + PSYS_PART_END_SCALE, <0.3, 0.3, 0>, + PSYS_PART_START_GLOW, 0.2, + PSYS_PART_END_GLOW, 0.3, + PSYS_PART_BLEND_FUNC_SOURCE, PSYS_PART_BF_SOURCE_ALPHA, + PSYS_PART_BLEND_FUNC_DEST, PSYS_PART_BF_ONE, + PSYS_SRC_ACCEL, <1, 0, 0> * llGetRot() + <0, 0, 0.4>, + PSYS_SRC_OMEGA, <0.01, 0.1, 0>, + PSYS_SRC_TEXTURE, tex, + PSYS_SRC_TARGET_KEY, kid + ]); +} + +default { + state_entry() { +// llScriptProfiler(TRUE); + avatar = llGetOwner(); + + C_CONTROL = 100 - (integer)("0x" + substr(avatar, 29, 35)); + L_CONTROL = llListen(C_CONTROL, "", "", ""); + + C_LIGHTS = 105 - (integer)("0x" + substr(avatar, 29, 35)); + L_LIGHTS = llListen(C_LIGHTS, "", "", ""); + + llListen(C_PUBLIC, "", "", ""); + llListen(C_CAPS, "", "", ""); + + power_on = 1; + + tell(avatar, C_LIGHTS, "add icon"); + + // llSetTextureAnim(FALSE, ALL_SIDES, 0, 0, 0.0, 0.0, 1.0); + // llSetTextureAnim(ANIM_ON | SMOOTH | LOOP | ROTATE , ALL_SIDES, 9, 9, 0.2, 0.6, -0.1); + +/* integer memlimit = llGetSPMaxMemory() + 1000; + while(!llSetMemoryLimit(memlimit)) { + memlimit *= 2; + } + llScriptProfiler(FALSE); + echo((string)memlimit + " bytes allocated.");*/ + } + + on_rez(integer n) { + avatar = llGetOwner(); + + C_CONTROL = 100 - (integer)("0x" + substr(avatar, 29, 35)); + llListenRemove(L_CONTROL); + L_CONTROL = llListen(C_CONTROL, "", "", ""); + + C_LIGHTS = 105 - (integer)("0x" + substr(avatar, 29, 35)); + llListenRemove(L_LIGHTS); + L_LIGHTS = llListen(C_LIGHTS, "", "", ""); + + power_on = 1; + + tell(avatar, C_LIGHTS, "add icon"); + + // llSetTextureAnim(ANIM_ON | SMOOTH | LOOP | ROTATE, ALL_SIDES, 9, 9, 0.2, 0.6, -0.1); + } + + listen(integer cc, string src, key id, string message) { + if(cc == C_CAPS) { + if(substr(message, 0, 4) == "info ") { + integer rc = (integer)delstring(message, 0, 4); + tell(id, rc, "hwc " + jsobject([ + "vendor", "Nanite Systems Consumer Products", + "version", ICON_VERSION, + "purpose", "light,comm", + "channel", jsobject(["lights", C_LIGHTS, "command", C_CONTROL, "public", C_PUBLIC, "caps", C_CAPS]), + "private", 1, + "busy", 0, + "usable", power_on, + "health", 1.0, + "info", "http://nanite-systems.com/icon" + ])); + } + } else if(cc == C_PUBLIC) { + if(message == "sink") { + llRegionSay(C_PUBLIC, (string)SINK_PRIORITY); + } else if(message == (string)((integer)message)) { + integer mi = (integer)message; +// echo("Found sink " + src + " with priority " + message); + if(llGetOwnerKey(id) == llGetOwnerKey(kid)) { + if(mi > current_si) { + current_si = mi; + kid = id; + } + } + } + } else if(cc == C_CONTROL) { + jump executive; + } else if(cc == C_LIGHTS) { + list argv = split(message, " "); + string cmd = gets(argv, 0); + + float gap; + if(message == "off") { + llParticleSystem([]); + gap = 0; + color_me(off, 1); + power_on = 0; + } else if(message == "on") { + power_on = 1; + color_me(color, 1); + } else if(message == "bolts on") { + echo("@detach=n"); + } else if(message == "bolts off") { + echo("@detach=y"); + } else if(message == "broken") { + gap = 0.05; + broken = 1; + } else if(message == "fixed") { + gap = 0; + broken = 0; + color_me(color, 1); + } else if(cmd == "light") { + color_me(color, 1); + power_on = 1; + } else if(cmd == "color") { + color = <(float)gets(argv, 1), (float)gets(argv, 2), (float)gets(argv, 3)>; + color_me(color, 1); + } else if(substr(message, 0, 4) == "name ") { + llSetObjectName(src + " (icon)"); + } else if(message == "probe") { + tell(id, C_LIGHTS, "add icon"); + } else if(message == "add-confirm") { + tell(id, C_LIGHTS, "add-command icon"); + tell(id, C_LIGHTS, "color-q"); + tell(id, C_LIGHTS, "power-q"); + } else if(cmd == "command") { + if(gets(argv, 2) == "icon") { + message = concat(delrange(argv, 0, 2), " "); + jump executive; + } + } + + llSetTimerEvent(gap); + } + + jump end; + @executive; + if(power_on == 0) { + echo("Can't blink: turned off."); + return; + } + + float x; + vector c; + for(x = 1.0; x > -0.1; x -= 0.1) { + color_me(color, x); + llSleep(0.01); + } + + if(message == "yes") { + llPlaySound("yes", 1.0); + c = yes; + } else if(message == "no") { + llPlaySound("no", 1.0); + c = no; + } else if(message == "love") { + llPlaySound("love", 1.0); + c = love; + } else if(substr(message, 0, 9) == "particles ") { + current_si = 0; + list parts = split(message, " "); + kid = (key)gets(parts, 1); + tell(kid, -9999999, "sink"); + // echo("Sent sink priority request."); + tex = "Scarf-Chirp"; + startParticles(); + llPlaySound("love", 1.0); + c = particles; + llSetTimerEvent(0.1); + } else if(message == "stop_particles") { + llParticleSystem([]); + emitting = 0; + c = particles; + if(broken == 0) + llSetTimerEvent(0); + else + llSetTimerEvent(0.15); + } else if(message == "victory") { + llPlaySound("victory", 1.0); + c = victory; + } else if(message == "defeat") { + llPlaySound("defeat", 1.0); + c = defeat; + } else if(message == "question") { + llPlaySound("question", 1.0); + c = question; + } else if(message == "explain") { + llPlaySound("yes", 1.0); + llWhisper(0, "This unit is equipped with a Nanite Systems Chromatic Communications Interface. Listen for the tone and observe the forehead light to determine what it wishes to indicate."); + c = <1.0, 1.0, 1.0>; + } else if(message == "jeep") { + llPlaySound("jeep", 1.0); + llWhisper(0, "Beep beep!"); + c = jeep; + } + + setp(LINK_THIS, [PRIM_GLOW, ALL_SIDES, max_glow]); + + for(x = 0.0; x < 1.0; x += 0.1) { + color_me(c, x); + llSleep(0.001); + } + + llSleep(0.4); + + for(x = 1.0; x > -0.1; x -= 0.1) { + color_me(c, x); + llSleep(0.03); + } + + setp(LINK_THIS, [PRIM_GLOW, ALL_SIDES, min_glow]); + + llSleep(0.2); + + for(x = 0.0; x < 1.0; x += 0.1) { + color_me(color, x); + llSleep(0.01); + } + @end; + } + + timer() { + if(broken) { + float t = 1; + if(llFrand(1.0) < 0.1) + t = llFrand(0.2); + + color_me(color, t); + } + + if(emitting) { + if(llFrand(1) < 0.333) + tex = "Scarf-Chirp"; + else if(llFrand(1 < 0.5)) + tex = "Scarf-Segment"; + else + tex = "Scarf-Sigil"; + + startParticles(); + } + } +} \ No newline at end of file diff --git a/ARES/hardware/examples/charge/sit-anywhere-charger.lsl b/ARES/hardware/examples/charge/sit-anywhere-charger.lsl new file mode 100644 index 0000000..45fc9ee --- /dev/null +++ b/ARES/hardware/examples/charge/sit-anywhere-charger.lsl @@ -0,0 +1,69 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2014–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * SitAnywhere Charger + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +float RATE = 20.0; // units to charge per hit +float FREQ = 1.0; // how often to charge! + +key sitter; + +default +{ + changed(integer change) { + if(change & CHANGED_LINK) { + key new_sitter = llAvatarOnSitTarget(); + if(new_sitter) { + llSetTimerEvent(FREQ); + llRegionSayTo(new_sitter, 0, "Unit connected. Beginning charge."); + llPlaySound("abf708b6-342b-3232-d621-46aec87b88ce", 1.0); + } else { + llRegionSayTo(new_sitter, 0, "Unit disconnected. Charging terminated."); + llPlaySound("068f47e4-65e6-e755-cc43-63472ab48409", 1.0); + llSetTimerEvent(0); + } + sitter = new_sitter; + } + } + + timer() { + if(llAvatarOnSitTarget()) { + llRegionSayTo(sitter, -9999999, "charge " + (string)RATE); + } else { + llRegionSayTo(sitter, 0, "Unit disconnected. Charging terminated."); + llPlaySound("459e376f-2870-d0ef-305c-17f324bb44ad", 1.0); + llSetTimerEvent(0); + sitter = NULL_KEY; + } + } +} diff --git a/ARES/hardware/examples/charge/touch-to-charge-limited.lsl b/ARES/hardware/examples/charge/touch-to-charge-limited.lsl new file mode 100644 index 0000000..eb3f824 --- /dev/null +++ b/ARES/hardware/examples/charge/touch-to-charge-limited.lsl @@ -0,0 +1,106 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2022–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Touch-To-Recharge Example (regenerating storage) + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +#include +#include + +#define DISCHARGE_RATE 400 +#define RECHARGE_RATE 400 +#define MAX_CHARGE 9000 +#define S_START "a6a6ac7d-c655-66d6-ac5c-93766e013068" +#define S_LOOP "f6210ab3-3c96-f2c8-7ce8-0e203eb3c27b" +#define S_EMPTY "b29b9860-1680-ddc4-31e7-68241e2deff3" +#define S_RECHARGED "a5dded13-1596-ff3b-cdb1-a0bb95b557e1" + +integer charge = 9000; +key user; +integer dispensing; +integer recharging; + +default { + state_entry() { + llStopSound(); + llSetSoundQueueing(FALSE); + llPlaySound(S_RECHARGED, 1); + if(llSetMemoryLimit(0x2000)) echo("OK."); + } + + touch_start(integer n) { + if(recharging) { + llTriggerSound(S_EMPTY, 1); + llSleep(1); + } else if(!dispensing) { + user = llDetectedKey(0); + dispensing = 1; + llPlaySound(S_START, 1); + llSleep(1); + llLoopSound(S_LOOP, 1); + llSetTimerEvent(0.5); + } + } + + touch_end(integer n) { + if(dispensing && user == llDetectedKey(0)) { + llStopSound(); + dispensing = 0; + recharging = 1; + } + } + + timer() { + if(dispensing) { + if(charge > 0) { + charge -= DISCHARGE_RATE; + tell(user, -9999999, "charge " + (string)DISCHARGE_RATE); + } + + if(charge <= 0) { + llStopSound(); + llPlaySound(S_EMPTY, 1); + charge = 0; + dispensing = 0; + recharging = 1; + } + } else if(recharging) { + charge += RECHARGE_RATE; + if(charge >= MAX_CHARGE) { + charge = MAX_CHARGE; + llPlaySound(S_RECHARGED, 1); + recharging = 0; + llSetTimerEvent(0); + } + } + } +} diff --git a/ARES/hardware/examples/charge/touch-to-charge.lsl b/ARES/hardware/examples/charge/touch-to-charge.lsl new file mode 100644 index 0000000..7035109 --- /dev/null +++ b/ARES/hardware/examples/charge/touch-to-charge.lsl @@ -0,0 +1,58 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2022–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Touch-To-Recharge Example (minimalist) + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +key who; + +default +{ + touch_start(integer total_number) + { + if(who) { + llSetTimerEvent(0); + who = NULL_KEY; + llStopSound(); + llTriggerSound("bcd1f878-2539-0354-9550-2b2910d8281a", 1); + } else { + who = llDetectedKey(0); + llSetTimerEvent(0.20); + llTriggerSound("22b6adc1-6095-49c9-6932-9ef4538f1500", 1); + } + } + + timer() { + llRegionSayTo(who, -9999999, "charge 20"); + llLoopSound("a2ff8cda-680a-d1d1-d005-07a1dae24ab8", 0.1); + } +} diff --git a/ARES/hardware/examples/passive/bolts.lsl b/ARES/hardware/examples/passive/bolts.lsl new file mode 100644 index 0000000..6bd41e4 --- /dev/null +++ b/ARES/hardware/examples/passive/bolts.lsl @@ -0,0 +1,70 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2017–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Safety Bolts Minimal Example + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +/* + Install, edit, and enjoy! You should need no more than one copy per attachment. + + Make sure you turn on the Firestorm LSL Preprocessor for best results. +*/ + +integer channel_lights; +integer ListenID; + +default +{ + + state_entry() + { + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + llRegionSay(channel_lights, "power-q"); + } + + on_rez(integer w) { + llListenRemove(ListenID); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + llRegionSay(channel_lights, "power-q"); + } + + listen(integer channel, string name, key id, string message) + { + if(message == "bolts off") { + llOwnerSay("@detach=y"); + } else if(message == "bolts on") { + llOwnerSay("@detach=n"); + } + } +} diff --git a/ARES/hardware/examples/passive/flicker/flicker-classic-full-linkset.lsl b/ARES/hardware/examples/passive/flicker/flicker-classic-full-linkset.lsl new file mode 100644 index 0000000..40caf84 --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-classic-full-linkset.lsl @@ -0,0 +1,88 @@ +/* + Generic Nanite Systems flicker template + + Install, edit, and enjoy! You should need no more than one copy per attachment. +*/ + +float gap = 0; + +integer frame = 0; + +integer broken = 0; + +integer channel_lights; + +integer ListenID; + +vector color = <0.8, 0.9, 1.0>; // default color. This will can be overridden by typing !recolor on the main controller. + +set_lights(float level) { + // to recolor everything, remove "//" from the following line: + + llSetLinkColor(LINK_SET, color * level, ALL_SIDES); + + // to recolor face 2 on object 1, remove "//" from the following line: + + // llSetLinkColor(1, color * level, 2); + + // generically, llSetLinkColor(, color * level, ); + + // You can copy and paste these lines as many times as you want. + + // If you want to set every face on a prim, use ALL_SIDES in the last parameter + + // If you want to modify every prim in the object, use LINK_SET as the first parameter + + // If you want to have an element that always glows even when power is turned off, change 'level' to 1.0 + // (or a smaller number for less bright parts) +} + +default +{ + + state_entry() + { + llSetTimerEvent(gap); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + } + + on_rez(integer w) { + llListenRemove(ListenID); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + } + + listen(integer channel, string name, key id, string message) + { + if (message == "off") { + gap = 0; + set_lights(0.1); + } else if(message == "broken") { + gap = 0.05; + broken = 1; + } else if(message == "fixed") { + gap = 0; + broken = 0; + set_lights(1.0); + } else if(llGetSubString(message, 0, 5) == "light ") { + set_lights(1.0); + } else if(llGetSubString(message, 0, 5) == "color ") { + list rgb = llParseString2List(llGetSubString(message, 6, -1), [" "], []); + color = ; + + set_lights(1.0); + } + + llSetTimerEvent(gap); + } + + timer() + { + float t = 1; + if(llFrand(1.0) < 0.1) + t = llFrand(2.0); + + set_lights(t); + } +} diff --git a/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf-holo.lsl b/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf-holo.lsl new file mode 100644 index 0000000..843e30e --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf-holo.lsl @@ -0,0 +1,211 @@ +/* + Nanite Systems Autoconf Lighting Engine (alpha support enabled) + + ALPHA ENABLED: This version is slightly slower but will preserve the opacity of your prims, even if they change. Please use it only when necessary. Special thanks to Linnefer Resident for the idea and initial implementation. + + This script reads linkset descriptions to determine how to light up the prim. + + To specify prim colorings, start the prim description with # (full brightness) or $ (low brightness, e.g. for gauge backgrounds) followed by a comma-separated list of faces to illuminate, or "-1" for all sides. A single prim cannot have both # and $. + + Optionally, you can put "L" at the start of the prim's description to specify that this prim should emit a point light, controllable with the 'lamp' command. Maximum of 1 per linkset. For example, "L#2,3" will fully illuminate faces 2 and 3 and add a light source. + + The "L" light will be affected by the controller's "!lamp on" and "!lamp off" commands (new in Companion 8.4) + + You should be able to use this script without editing it. Just reset it if you make changes to your linkset. + + If you're making a main controller, look at line 184 for an extra tweak needed for proper support of color-changing HUDs. + */ + +float gap = 0; + +integer frame = 0; + +integer broken = 0; + +integer channel_lights; + +integer ListenID; + +vector color = <1.0, 0.0, 0.5>; + +list on_state; +list off_state; + +float radius = 0.5; + +integer LIGHT; + +integer power_on; + +integer lamp_on; + +list high_intensity_faces; +list high_intensity_parts; +list low_intensity_faces; +list low_intensity_parts; + +set_lights(float level) { + list command; + integer x = llGetListLength(high_intensity_faces); + + vector c = color * level; + while(x--) { + integer p = llList2Integer(high_intensity_parts, x); + integer f = llList2Integer(high_intensity_faces, x); + command += [PRIM_LINK_TARGET, p, PRIM_COLOR, f, c, llList2Float(llGetLinkPrimitiveParams(p, [PRIM_COLOR, f]), 1)]; + } + + x = llGetListLength(low_intensity_faces); + + c *= 0.1; // low intensity (1/10th of normal brightness) + while(x--) { + integer p = llList2Integer(low_intensity_parts, x); + integer f = llList2Integer(low_intensity_faces, x); + command += [PRIM_LINK_TARGET, p, PRIM_COLOR, f, c, llList2Float(llGetLinkPrimitiveParams(p, [PRIM_COLOR, f]), 1)]; + } + + llSetLinkPrimitiveParamsFast(1, command); + + if(power_on) { + if(broken == 0) { + if(lamp_on) + llSetLinkPrimitiveParamsFast(LIGHT, on_state); + else + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } + } else { + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } +} + +#define STEP 0.25 + +default +{ + + state_entry() + { + integer i = llGetNumberOfPrims(); + while(i != 0) { + string d = llList2String(llGetLinkPrimitiveParams(i, [PRIM_DESC]), 0); + integer dstart = 0; + if(llGetSubString(d, dstart, dstart) == "L") { + LIGHT = i; + dstart = 1; + } + + integer cg = 0; + + string c = llGetSubString(d, dstart, dstart); + + if(c == "#") + cg = 1; + else if(c == "$") + cg = 2; + + if(cg) { + list faces = llParseString2List(llGetSubString(d, dstart + 1, -1), [","], []); + integer L = llGetListLength(faces); + list parts; + while(L--) + parts += i; + + if(cg == 1) { + high_intensity_faces += faces; + high_intensity_parts += parts; + } else { + low_intensity_faces += faces; + low_intensity_parts += parts; + } + } + --i; + } + + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + set_lights(0); + + llSetTimerEvent(gap); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + + llRegionSayTo(llGetOwner(), channel_lights, "power-q"); + llRegionSayTo(llGetOwner(), channel_lights, "color-q"); + + llOwnerSay("Lighting system initialized."); + } + + on_rez(integer w) { + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + llListenRemove(ListenID); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + + if(llGetAttached()) { + llRegionSayTo(llGetOwner(), channel_lights, "power-q"); + llRegionSayTo(llGetOwner(), channel_lights, "color-q"); + } + } + + listen(integer channel, string name, key id, string message) + { + if (message == "off") { + gap = 0; + power_on = 0; + set_lights(0.1); + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } else if(message == "broken") { + gap = 0.05; + broken = 1; + } else if(message == "fixed") { + gap = 0; + broken = 0; + power_on = 1; + set_lights(1.0); + } else if(message == "on") { + power_on = 1; + set_lights(1.0); + } else if(message == "lamp on") { + lamp_on = 1; + set_lights(1.0); + } else if(message == "lamp off") { + lamp_on = 0; + set_lights(1.0); + + } else if(llGetSubString(message, 0, 5) == "color ") { + list rgb = llParseString2List(llGetSubString(message, 6, -1), [" "], []); + + vector real_color = ; + + color = real_color; + + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + set_lights(1.0); + + // Uncomment this line if you're developing a custom controller housing: + + // llMessageLinked(LINK_ROOT, 28, llGetSubString(message, 6, -1), ""); // send screen handler to system memory + } else { + return; + } + + llSetTimerEvent(gap); + } + + timer() + { + float t = 1; + if(llFrand(1.0) < 0.1) + t = llFrand(2.0); + + set_lights(t); + + if(lamp_on) + llSetLinkPrimitiveParamsFast(LIGHT, [PRIM_POINT_LIGHT, 1, color, t, radius, 0.75]); + } +} diff --git a/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf.lsl b/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf.lsl new file mode 100644 index 0000000..843e30e --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-mono-autoconf.lsl @@ -0,0 +1,211 @@ +/* + Nanite Systems Autoconf Lighting Engine (alpha support enabled) + + ALPHA ENABLED: This version is slightly slower but will preserve the opacity of your prims, even if they change. Please use it only when necessary. Special thanks to Linnefer Resident for the idea and initial implementation. + + This script reads linkset descriptions to determine how to light up the prim. + + To specify prim colorings, start the prim description with # (full brightness) or $ (low brightness, e.g. for gauge backgrounds) followed by a comma-separated list of faces to illuminate, or "-1" for all sides. A single prim cannot have both # and $. + + Optionally, you can put "L" at the start of the prim's description to specify that this prim should emit a point light, controllable with the 'lamp' command. Maximum of 1 per linkset. For example, "L#2,3" will fully illuminate faces 2 and 3 and add a light source. + + The "L" light will be affected by the controller's "!lamp on" and "!lamp off" commands (new in Companion 8.4) + + You should be able to use this script without editing it. Just reset it if you make changes to your linkset. + + If you're making a main controller, look at line 184 for an extra tweak needed for proper support of color-changing HUDs. + */ + +float gap = 0; + +integer frame = 0; + +integer broken = 0; + +integer channel_lights; + +integer ListenID; + +vector color = <1.0, 0.0, 0.5>; + +list on_state; +list off_state; + +float radius = 0.5; + +integer LIGHT; + +integer power_on; + +integer lamp_on; + +list high_intensity_faces; +list high_intensity_parts; +list low_intensity_faces; +list low_intensity_parts; + +set_lights(float level) { + list command; + integer x = llGetListLength(high_intensity_faces); + + vector c = color * level; + while(x--) { + integer p = llList2Integer(high_intensity_parts, x); + integer f = llList2Integer(high_intensity_faces, x); + command += [PRIM_LINK_TARGET, p, PRIM_COLOR, f, c, llList2Float(llGetLinkPrimitiveParams(p, [PRIM_COLOR, f]), 1)]; + } + + x = llGetListLength(low_intensity_faces); + + c *= 0.1; // low intensity (1/10th of normal brightness) + while(x--) { + integer p = llList2Integer(low_intensity_parts, x); + integer f = llList2Integer(low_intensity_faces, x); + command += [PRIM_LINK_TARGET, p, PRIM_COLOR, f, c, llList2Float(llGetLinkPrimitiveParams(p, [PRIM_COLOR, f]), 1)]; + } + + llSetLinkPrimitiveParamsFast(1, command); + + if(power_on) { + if(broken == 0) { + if(lamp_on) + llSetLinkPrimitiveParamsFast(LIGHT, on_state); + else + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } + } else { + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } +} + +#define STEP 0.25 + +default +{ + + state_entry() + { + integer i = llGetNumberOfPrims(); + while(i != 0) { + string d = llList2String(llGetLinkPrimitiveParams(i, [PRIM_DESC]), 0); + integer dstart = 0; + if(llGetSubString(d, dstart, dstart) == "L") { + LIGHT = i; + dstart = 1; + } + + integer cg = 0; + + string c = llGetSubString(d, dstart, dstart); + + if(c == "#") + cg = 1; + else if(c == "$") + cg = 2; + + if(cg) { + list faces = llParseString2List(llGetSubString(d, dstart + 1, -1), [","], []); + integer L = llGetListLength(faces); + list parts; + while(L--) + parts += i; + + if(cg == 1) { + high_intensity_faces += faces; + high_intensity_parts += parts; + } else { + low_intensity_faces += faces; + low_intensity_parts += parts; + } + } + --i; + } + + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + set_lights(0); + + llSetTimerEvent(gap); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + + llRegionSayTo(llGetOwner(), channel_lights, "power-q"); + llRegionSayTo(llGetOwner(), channel_lights, "color-q"); + + llOwnerSay("Lighting system initialized."); + } + + on_rez(integer w) { + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + llListenRemove(ListenID); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + ListenID = llListen(channel_lights, "", "", ""); + + if(llGetAttached()) { + llRegionSayTo(llGetOwner(), channel_lights, "power-q"); + llRegionSayTo(llGetOwner(), channel_lights, "color-q"); + } + } + + listen(integer channel, string name, key id, string message) + { + if (message == "off") { + gap = 0; + power_on = 0; + set_lights(0.1); + llSetLinkPrimitiveParamsFast(LIGHT, off_state); + } else if(message == "broken") { + gap = 0.05; + broken = 1; + } else if(message == "fixed") { + gap = 0; + broken = 0; + power_on = 1; + set_lights(1.0); + } else if(message == "on") { + power_on = 1; + set_lights(1.0); + } else if(message == "lamp on") { + lamp_on = 1; + set_lights(1.0); + } else if(message == "lamp off") { + lamp_on = 0; + set_lights(1.0); + + } else if(llGetSubString(message, 0, 5) == "color ") { + list rgb = llParseString2List(llGetSubString(message, 6, -1), [" "], []); + + vector real_color = ; + + color = real_color; + + on_state = [PRIM_POINT_LIGHT, 1, color, 1.0, radius, 0.75]; + off_state = [PRIM_POINT_LIGHT, 0, color, 1.0, radius, 0.75]; + + set_lights(1.0); + + // Uncomment this line if you're developing a custom controller housing: + + // llMessageLinked(LINK_ROOT, 28, llGetSubString(message, 6, -1), ""); // send screen handler to system memory + } else { + return; + } + + llSetTimerEvent(gap); + } + + timer() + { + float t = 1; + if(llFrand(1.0) < 0.1) + t = llFrand(2.0); + + set_lights(t); + + if(lamp_on) + llSetLinkPrimitiveParamsFast(LIGHT, [PRIM_POINT_LIGHT, 1, color, t, radius, 0.75]); + } +} diff --git a/ARES/hardware/examples/passive/flicker/flicker-mono-classic.lsl b/ARES/hardware/examples/passive/flicker/flicker-mono-classic.lsl new file mode 100644 index 0000000..7342b15 --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-mono-classic.lsl @@ -0,0 +1,117 @@ +// NO NEED TO TOUCH THIS SECTION, IT SETS UP ALL THE BASIC REQUIREMENTS FOR THE SCRIPT TO FUNCTION +float gap = 0; + +integer broken = 0; + +integer channel_lights; + +integer ListenID; + +// END OF THE DEFINE STAGE, AGAIN TOUCH NOTHING ABOVE THIS LINE. + +vector color = <0.8, 0.9, 1.0>; + +set_lights(float level) { +// THIS IS THE SECTION YOU CAN MODIFY. +// PRESENTLY THIS IS SET UP WITH A CONDITIONAL FOR TESTING OFF AND ON STATES BASED ON THE VARIABLE 'level' +// IN THIS CONDITIONAL 0.1 IS USED AS THE MARKER FOR 'OFF' FOLLOW THE COMMENTS BELOW FOR INFO ON THE SPECIFICS +// THIS CONDITIONAL IS NOT REQUIRED, YOU CAN EITHER COMMENT IT OUT WITH // MARKS ONE PER LINE, OR DELETE IT AND USE THE SECTION BELOW IT + + if(level != 0.1) // Test for whether the level is the 'off' state 0.1. As long as it isn't, move to the first step + { + // If not 'offline' then this line will change the colour. In this example it also sets the glow to 0.1, full brights it. The -1 can be replaced + // with ALL_SIDES or the face number of the face in the linkset. + + // llSetLinkPrimitiveParamsFast is used to affect all prims in the set, by default, that means the whole object, you may wish to set this to a link number + // instead. The commands you send to that prim or set of prims is contained with square brackets. In this case PRIM_COLOR, which is then followed by the + // face on the prim, -1 or ALL_SIDES in this example, then color * level, followed by the level of transparency desired, 0.80 in this example. + // after thats set, it sets the PRIM_GLOW, and is optional in your case. Again same format, it is followed by the face, then the value to set. + // PRIM_FULLBRIGHT is another optional, followed by the face, and whether on 'TRUE' or off 'FALSE' This is then closed off with a square bracket, round + // bracket, and a semi colon + + llSetLinkPrimitiveParamsFast(LINK_SET,[PRIM_COLOR,-1,color * level,0.80,PRIM_GLOW,-1,0.1,PRIM_FULLBRIGHT,-1,TRUE]); + + } else + { + //See above example for an explanation of how this works, same deal, but for the state where your controller is 'off' + llSetLinkPrimitiveParamsFast(LINK_SET,[PRIM_COLOR,-1,<0,0,0>,0.0,PRIM_GLOW,-1,0.0,PRIM_FULLBRIGHT,-1,FALSE]); + + } + // Remove the // from the next line if you just want a simple flicker, like the orignal template. + // llSetLinkColor(LINK_SET, color * level, ALL_SIDES); + // generically, llSetLinkColor(, color * level, ); + + // You can copy and paste these lines as many times as you want. + + // If you want to set every face on a prim, use ALL_SIDES in the last parameter + + // If you want to modify every prim in the object, use LINK_SET as the first parameter + + // If you want to have an element that always glows even when power is turned off, change 'level' to 1.0 + // (or a smaller number for less bright parts) + + // It is worth learning to use llSetLinkPrimitiveParams and llSetLinkPrimitiveParamsFast, with PRIM_LINK_TARGET as this will make for far faster + // transitions, and will be noticable more during code runs like 'rainbow' when texturing multiple faces/prims, as LSL adds sleeps to some functions + // of about 0.1 second, which adds up the more you have. + +// NO NEED TO TOUCH ANYTHING BELOW THIS LINE, UNLESS YOU KNOW WHAT IT IS YOU ARE ALTERING. +} + +default +{ + + state_entry() + { +//DAOR SPECIFIC MOD: +// llSetTextureAnim(ANIM_ON | SMOOTH | LOOP, ALL_SIDES, 0,0, 0.0,1.0,0.5); +//END OF DAOR MOD. + llSetTimerEvent(gap); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + llWhisper(channel_lights, "power-q"); + ListenID = llListen(channel_lights, "", "", ""); + } + + on_rez(integer w) { + llListenRemove(ListenID); + channel_lights = -1 - (integer)("0x" + llGetSubString( (string) llGetOwner(), -7, -1) ) + 106; + llWhisper(channel_lights, "power-q"); + ListenID = llListen(channel_lights, "", "", ""); + } + + listen(integer channel, string name, key id, string message) + { + if (message == "off") { + gap = 0; + set_lights(0.1); + } else if (message == "on") { + if(broken) + gap = 0.05; + else + gap = 0; + set_lights(1); + } else if(message == "broken") { + gap = 0.05; + broken = 1; + } else if(message == "fixed") { + gap = 0; + broken = 0; + set_lights(1.0); + } else if(llGetSubString(message, 0, 5) == "color ") { + list rgb = llParseString2List(llGetSubString(message, 6, -1), [" "], []); + color = ; + set_lights(1.0); + } + + llSetTimerEvent(gap); + } + + timer() + { + float t = 1; + if(llFrand(1.0) < 0.1) + t = llFrand(2.0); + + set_lights(t); + } +} + diff --git a/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf-holo.lsl b/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf-holo.lsl new file mode 100644 index 0000000..1643389 --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf-holo.lsl @@ -0,0 +1,426 @@ +/* + FLICKER AUTOCONF, TETRA HOLO VERSION + + Public domain. + + Written by rhet0rica, Aug 17, 2021. + Last updated Aug 15, 2023. + + Allows linksets to use the NS lighting bus. Requires setting descriptions on all prims. + + For each link in your linkset, set the description as follows: + + 1. start with @ to indicate it is a flicker rule (otherwise it will be ignored) + 2. put an optional "L" to indicate this is your lamp prim + (each linkset may have up to 1 lamp prim, it will be a point lightsource) + 3. put an optional "H" to indicate the listed faces should be invisible when the unit is off or in a booth + (for holograms; supports block-holo) + 4. list the face numbers to modify, separated by commas + (-1 for all) + 5. before each face number, write one of the following flag letters: + + color/rule flags: + A = 0 = color A, full intensity + B = 1 = color B, full intensity + C = 2 = color C, full intensity + D = 3 = color D, full intensity + a = 32 = color A, low intensity + b = 33 = color B, low intensity + c = 34 = color C, low intensity + d = 35 = color D, low intensity + i = 40 = reactive, industrial type + p = 47 = reactive, pleasure type + w = 54 = reactive, working only (pulsates color D when working; other reactive types pulsate color A) + x = 55 = reactive, combat type + + Examples: + + "@LA-1" = this is a lamp prim (light source) + it always looks like color A on all sides, full intensity + + "@i2,p3,C5,C6" = industrial reactive on face 2, + pleasure reactive face 3, full-intensity color C on faces 5 and 6 + + "@Li2,p3,C5,C6" = as above, but sets a point light using color C + lamp color is determined by the last face listed + + "@Lp3,C5,C6,i2" = as above, but the light now uses "reactive, industrial type" rules + (face numbers don't have to be in order!) + + "@Lp3,C5,C6,i-10" = as above, but without setting any face to industrial + face -10 doesn't exist, but the lamp reads it anyway + + "@Hx-1" = all sides follow the "reactive, combat type" rules + entire prim disappers when powered off or in a booth + + "@LHi7,i6" = lamp prim using "reactive, industrial type" rules on face 6 and 7 + only the listed faces (face 6 and 7) will disappear when powered off + + This script preserves the alpha value of each face. However, if you use -1, then face 0's + alpha will be applied to the other faces of the same prim. To avoid this, list the faces + manually (e.g. "@A0,A1,A2,A3,A4,A5,A6,A7" instead of "@A-1") + + TO DEPLOY THIS SCRIPT, drag it into the Content tab of any prim in your linkset. + + TIPS + ==== + + The flag to turn faces holographic (H) applies to all faces listed. If you're creating a holographic + ornament that also includes a non-holographic light (e.g. on the emitter) then you should split + up your creation into multiple parts instead of exporting all the materials as one object. + + You may choose to restrict copy/modify/transfer; that's up to you. This is a public domain script. + + You are allowed to redistribute the NS Color HUD (bismuth) with any product that uses this script. + + To reload settings after changes are made, this script must be reset. If you have no idea how to do + that, just delete and re-add it. + + If you do not see the message "Memory Limit set at ##### bytes" after recompiling, the memory limit + is stuck at 64 KiB. Maybe it's time you got a simpler attachment? + + You can also try recompiling this with "Mono" disabled. It will run slower, but never exceed 16 KiB. + + TO USE THIS SCRIPT IN A CUSTOM MAIN CONTROLLER, search for the word "uncomment" near the bottom of this file. +*/ + +// how much glow to use for full intensity and reactive faces: +float glow_strength = 0.05; +// how much glow to use for low-intensity faces: +float glow_strength_low = 0.02; + +list prims; // prim, face, alpha, color+rule +integer rule_count; +integer light = -1; + +vector colorA = <1, 0, 1>; +vector colorB = <0, 1, 0>; +vector colorC = <1, 0, 0>; +vector colorD = <1, 1, 1>; + +integer lamp_on = 1; +integer power_on = 1; +integer broken = 0; +integer working = 0; +float integrity = 1.0; +float arousal = 0.0; +float rate = 780.0; +float battery = 1.0; + +integer arousal_used; // whether to respond to arousal +integer integrity_used; // whether to respond to integrity +integer basic_used; // whether to respond to working, rate, or power +integer holo_used; // whether we found any holographic faces + +key av; +integer CL; +integer LL; + +integer unblockable = FALSE; // set to TRUE to ignore holoblockers +list blockers; // if non-empty, holograms are currently hidden + +integer last_blocker_check; +float last_repaired_at; +float last_charged_at; +float last_damaged_at; +float current_timer_rate; + +float main_timer_rate = 0.1; // set smoothness + +colorize() { + // update timer if needed: + + float now = llGetTime(); + float last_rep_clock = now - last_repaired_at; + float last_chr_clock = now - last_charged_at; + float last_dmg_clock = now - last_damaged_at; + + if(!power_on && current_timer_rate != 0) { + llSetTimerEvent(current_timer_rate = 0); + } else if(broken) { + llSetTimerEvent(current_timer_rate = main_timer_rate * 0.5 + llFrand(2) * llFrand(2)); + } else if((current_timer_rate > 0) + && !((arousal > 0) + || (last_chr_clock < 1.0) + || (last_rep_clock < 1.0) + || (last_dmg_clock < 1.0) + || (working))) { + llSetTimerEvent(current_timer_rate = 0); + } else { + llSetTimerEvent(current_timer_rate = main_timer_rate); + } + + list rules; + integer current_prim = -1; + integer ri = rule_count; + + float intensity = power_on; + if(broken) + intensity *= 0.2 + (llFrand(1) > 0.3) * 0.8; + + float clocksignal; + + if(current_timer_rate) { + clocksignal = (now); // / TWO_PI; + clocksignal = llSin((clocksignal - (integer)clocksignal) * TWO_PI); // in range [-1, 1] + } + + while(ri--) { + integer radix = ri << 2; + integer p = llList2Integer(prims, radix); + + integer fx = llList2Integer(prims, radix + 3); + float g = 1.0; + vector c; + integer h = (fx & 0x100); + if(h) + fx = fx & 0xff; + + if(fx == 0 || fx == 32) { + c = colorA; + } else if(fx == 1 || fx == 33) { + c = colorB; + } else if(fx == 2 || fx == 34) { + c = colorC; + } else if(fx == 3 || fx == 35) { + c = colorD; + } else { // special colors; you may want to edit these rules: + if(last_dmg_clock < 1 && fx == 55) { // flash color C for 1 second after damage, rule x only + c = colorC; + } else if(last_rep_clock < 1 && fx == 55) { // flash color B for 1 second after repair, rule x only + c = colorB; + } else if(arousal > 0 && fx == 47) { // show arousal on rule p + c = colorB * (1.0 + clocksignal * arousal * 0.375 - arousal * 0.25); + g = 1.0 + clocksignal * arousal; + } else if(integrity < 0.5 && fx == 55) { // below 50% integrity on rule x + c = colorC; + } else if(last_chr_clock < 1.0 && fx != 54) { // show color B for 1 second after power received + c = colorB; + } else if(battery < 0.1 && fx != 54) { // show color C when battery below 10% + c = colorC; + } else if(battery < 0.2 && fx != 54) { // show color D when battery below 20% + c = colorD; + } else if(rate > 925.0 && fx != 54) { // show color D on most types when power usage over 925 W + c = colorD; + } else if(working) { + if(fx == 54) + c = colorD; + else + c = colorA; + + c *= (clocksignal * 0.25 + 0.75); + } else { // set the default color for all special faces + c = colorA; + } + } + + if(fx >= 32 && fx <= 35) { // dim colors + c *= 0.1; + g *= glow_strength_low * intensity; + } else { + g *= glow_strength * intensity; + } + + c *= intensity; + + if(p != current_prim) { + rules += [PRIM_LINK_TARGET, p]; + if(p == light) + rules += [PRIM_POINT_LIGHT, lamp_on, c, 1, 1, 1]; + } + + integer f = llList2Integer(prims, radix + 1); + float a = llList2Float(prims, radix + 2); + if(h) { + integer bi; + if(!power_on) { + a = 0; + g = 0; + } else if(bi = llGetListLength(blockers)) { + if(llGetUnixTime() - last_blocker_check > 3) { + while(bi--) { + key b = llList2Key(blockers, bi); + if(~llListFindList(llGetAttachedList(av), [b])) + jump blocked; + else if(b == llList2Key(llGetObjectDetails(av, [OBJECT_ROOT]), 0)) + jump blocked; + else + blockers = llDeleteSubList(blockers, bi, bi); + } + jump unblocked; + @blocked; + a = 0; + g = 0; + @unblocked; + last_blocker_check = llGetUnixTime(); + } + } + } + + if(f >= -1) + rules += [ + PRIM_COLOR, f, c, a, // liquidator brunt + PRIM_GLOW, f, g, + PRIM_FULLBRIGHT, f, (intensity > 0.5) + ]; + } + + llSetLinkPrimitiveParamsFast(!llGetLinkNumber(), rules); +} + +default { + state_entry() { + llScriptProfiler(TRUE); + LL = llListen(CL = 105 - (integer)("0x" + llGetSubString(av = llGetOwner(), 29, 35)), "", "", ""); + + integer L1 = llGetLinkNumber(); + integer pi = llGetNumberOfPrims() + L1; + while(pi > L1) { + --pi; + string d = llList2String(llGetLinkPrimitiveParams(pi, [PRIM_DESC]), 0); + if(llOrd(d, 0) == 0x40) { // '@' + if(llOrd(d, 1) == 0x4C) { // 'L' + light = pi; + d = llDeleteSubString(d, 0, 1); + } else { + d = llDeleteSubString(d, 0, 0); + } + + integer rule_boost = 0; + + if(llOrd(d, 0) == 0x48) { // 'H' + rule_boost = 0x100; + } + + list facecodes = llParseString2List(d, [","], []); + integer fi = llGetListLength(facecodes); + while(fi--) { + // prim, face, alpha, color+rule + string fs = llList2String(facecodes, fi); + integer fx = llOrd(fs, 0) - 0x41; // 'A' => 0 + integer fni = (integer)llDeleteSubString(fs, 0, 0); + + if(fx > 35) + basic_used = 1; + if(fx == 47) + arousal_used = 1; + if(fx == 55) + integrity_used = 1; + if(rule_boost == 0x100) + holo_used = 1; + + fx += rule_boost; + + // llOwnerSay("fni " + (string)fni + " is rule " + (string)fx + " (" + fs + ")"); + prims += [pi, fni, llList2Float(llGetLinkPrimitiveParams(pi, [PRIM_COLOR, fni]), 1), fx]; + + ++rule_count; + } + } + } + + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + + colorize(); + + llScriptProfiler(FALSE); + integer ml = llGetSPMaxMemory(); + llOwnerSay("SP memory limit: " + (string)ml + " bytes."); + if(llSetMemoryLimit(ml += 0x0400 * rule_count)) + llOwnerSay("Memory limit set at " + (string)ml + " bytes."); + } + + changed(integer c) { + if(c & CHANGED_OWNER) { + llListenRemove(LL); + LL = llListen(CL = 105 - (integer)("0x" + llGetSubString(av = llGetOwner(), 29, 35)), "", "", ""); + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + } + } + + on_rez(integer n) { + if(av == llGetOwner()) { + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + } + } + + listen(integer c, string n, key id, string m) { + if(m == "block-holo" && !unblockable && holo_used) { + if(llGetAttached()) + blockers += id; + } else if(m == "on") { + power_on = 1; + } else if(m == "off") { + power_on = 0; + } else if(m == "broken") { + broken = 1; + } else if(m == "error") { + broken = 2; + } else if(m == "fixed") { + broken = 0; + } else if(m == "working" && basic_used) { + working = 1; + } else if(m == "done" && basic_used) { + working = 0; + } else if(m == "bolts on") { + llOwnerSay("@detach=n"); + } else if(m == "bolts off") { + llOwnerSay("@detach=y"); + } else if(m == "lamp on" && ~light) { + lamp_on = 1; + } else if(m == "lamp off" && ~light) { + lamp_on = 0; + } else { + list argv = llParseString2List(m, [" "], []); + string cmd = llList2String(argv, 0); + if(cmd == "color") { + colorA = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + + // uncomment this line to use this as the lighting script for a main controller: + // llMessageLinked(LINK_ROOT, 28, llGetSubString(m, 6, -1), ""); + } else if(cmd == "color-2") { + colorB = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "color-3") { + colorC = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "color-4") { + colorD = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "rate" && basic_used) { + rate = (float)llList2String(argv, 1); + if(rate < 0) + last_charged_at = llGetTime(); + } else if(cmd == "arousal" && arousal_used) { + arousal = (float)llList2String(argv, 1); + } else if(cmd == "power" && basic_used) { + float new_battery = (float)llList2String(argv, 1); + if(new_battery > battery) + last_charged_at = llGetTime(); + battery = new_battery; + } else if(cmd == "integrity" && integrity_used) { + float new_integrity = (float)llList2String(argv, 1); + if(new_integrity > integrity) + last_repaired_at = llGetTime(); + else if(new_integrity < integrity) + last_damaged_at = llGetTime(); + integrity = new_integrity; + } else { + return; + } + } + colorize(); + } + + timer() { + colorize(); + } +} diff --git a/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf.lsl b/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf.lsl new file mode 100644 index 0000000..5a2eb9e --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf.lsl @@ -0,0 +1,365 @@ +/* + FLICKER AUTOCONF, TETRA VERSION + + Public domain. + + Written by rhet0rica, Aug 17, 2021. + + Allows linksets to use the NS lighting bus. Requires setting descriptions on all prims. + + For each link in your linkset, set the description as follows: + + 1. start with @ to indicate it is a flicker rule (otherwise it will be ignored) + 2. put an optional "L" to indicate this is your lamp prim + (each linkset may have up to 1 lamp prim, it will be a point lightsource) + 3. list the face numbers to modify, separated by commas + (-1 for all) + 4. before each face number, write one of the following flag letters: + + Alpha is always preserved UNLESS you use -1, in which case the alpha of one of the faces + may be propagated to the others in the same prim. + + color/rule flags: + A = 0 = color A, full intensity + B = 1 = color B, full intensity + C = 2 = color C, full intensity + D = 3 = color D, full intensity + a = 32 = color A, low intensity + b = 33 = color B, low intensity + c = 34 = color C, low intensity + d = 35 = color D, low intensity + i = 40 = reactive, industrial type + p = 47 = reactive, pleasure type + w = 54 = reactive, working only (pulsates color D when working; other reactive types pulsate color A) + x = 55 = reactive, combat type + + Examples: + + "@LA-1" = this is a lamp prim (light source) + it always looks like color A on all sides, full intensity + + "@i2,p3,C5,C6" = industrial reactive on face 2, + pleasure reactive face 3, full-intensity color C on faces 5 and 6 + + "@Li2,p3,C5,C6" = as above, but sets a point light using color C + lamp color is determined by the last face listed + + "@Lp3,C5,C6,i2" = as above, but the light now uses "reactive, industrial type" rules + (face numbers don't have to be in order!) + + "@Lp3,C5,C6,i-10" = as above, but without setting any face to industrial + face -10 doesn't exist, but the lamp reads it anyway + + TO DEPLOY THIS SCRIPT, drag it into the Content tab of any prim in your linkset. + + TIPS + ==== + + You may choose to restrict copy/modify/transfer; that's up to you. This is a public domain script. + + You are allowed to redistribute the NS Color HUD (bismuth) with any product that uses this script. + + To reload settings after changes are made, this script must be reset. If you have no idea how to do + that, just delete and re-add it. + + If you do not see the message "Memory Limit set at ##### bytes" after recompiling, the memory limit + is stuck at 64 KiB. Maybe it's time you got a simpler attachment? + + You can also try recompiling this with "Mono" disabled. It will run slower, but never exceed 16 KiB. + + TO USE THIS SCRIPT IN A CUSTOM MAIN CONTROLLER, search for the word "uncomment" near the bottom of this file. +*/ + +// how much glow to use for full intensity and reactive faces: +float glow_strength = 0.05; +// how much glow to use for low-intensity faces: +float glow_strength_low = 0.02; + +list prims; // prim, face, alpha, color+rule +integer rule_count; +integer light = -1; + +vector colorA = <1, 0, 1>; +vector colorB = <0, 1, 0>; +vector colorC = <1, 0, 0>; +vector colorD = <1, 1, 1>; + +integer lamp_on = 1; +integer power_on = 1; +integer broken = 0; +integer working = 0; +float integrity = 1.0; +float arousal = 0.0; +float rate = 780.0; +float battery = 1.0; + +integer arousal_used; // whether to respond to arousal +integer integrity_used; // whether to respond to integrity +integer basic_used; // whether to respond to working, rate, or power + +key av; +integer CL; +integer LL; + +float last_repaired_at; +float last_charged_at; +float last_damaged_at; +float current_timer_rate; + +float main_timer_rate = 0.1; // set smoothness + +colorize() { + // update timer if needed: + + float now = llGetTime(); + float last_rep_clock = now - last_repaired_at; + float last_chr_clock = now - last_charged_at; + float last_dmg_clock = now - last_damaged_at; + + if(!power_on && current_timer_rate != 0) { + llSetTimerEvent(current_timer_rate = 0); + } else if(broken) { + llSetTimerEvent(current_timer_rate = main_timer_rate * 0.5 + llFrand(2) * llFrand(2)); + } else if((current_timer_rate > 0) + && !((arousal > 0) + || (last_chr_clock < 1.0) + || (last_rep_clock < 1.0) + || (last_dmg_clock < 1.0) + || (working))) { + llSetTimerEvent(current_timer_rate = 0); + } else { + llSetTimerEvent(current_timer_rate = main_timer_rate); + } + + list rules; + integer current_prim = -1; + integer ri = rule_count; + + float intensity = power_on; + if(broken) + intensity *= 0.2 + (llFrand(1) > 0.3) * 0.8; + + float clocksignal; + + if(current_timer_rate) { + clocksignal = (now); // / TWO_PI; + clocksignal = llSin((clocksignal - (integer)clocksignal) * TWO_PI); // in range [-1, 1] + } + + while(ri--) { + integer radix = ri << 2; + integer p = llList2Integer(prims, radix); + + integer fx = llList2Integer(prims, radix + 3); + float g = 1.0; + vector c; + if(fx == 0 || fx == 32) { + c = colorA; + } else if(fx == 1 || fx == 33) { + c = colorB; + } else if(fx == 2 || fx == 34) { + c = colorC; + } else if(fx == 3 || fx == 35) { + c = colorD; + } else { // special colors; you may want to edit these rules: + if(last_dmg_clock < 1 && fx == 55) { // flash color C for 1 second after damage, rule x only + c = colorC; + } else if(last_rep_clock < 1 && fx == 55) { // flash color B for 1 second after repair, rule x only + c = colorB; + } else if(arousal > 0 && fx == 47) { // show arousal on rule p + c = colorB * (1.0 + clocksignal * arousal * 0.375 - arousal * 0.25); + g = 1.0 + clocksignal * arousal; + } else if(integrity < 0.5 && fx == 55) { // below 50% integrity on rule x + c = colorC; + } else if(last_chr_clock < 1.0 && fx != 54) { // show color B for 1 second after power received + c = colorB; + } else if(battery < 0.1 && fx != 54) { // show color C when battery below 10% + c = colorC; + } else if(battery < 0.2 && fx != 54) { // show color D when battery below 20% + c = colorD; + } else if(rate > 925.0 && fx != 54) { // show color D on most types when power usage over 925 W + c = colorD; + } else if(working) { + if(fx == 54) + c = colorD; + else + c = colorA; + + c *= (clocksignal * 0.25 + 0.75); + } else { // set the default color for all special faces + c = colorA; + } + } + + if(fx >= 32 && fx <= 35) { // dim colors + c *= 0.1; + g *= glow_strength_low * intensity; + } else { + g *= glow_strength * intensity; + } + + c *= intensity; + + if(p != current_prim) { + rules += [PRIM_LINK_TARGET, p]; + if(p == light) + rules += [PRIM_POINT_LIGHT, lamp_on, c, 1, 1, 1]; + } + + integer f = llList2Integer(prims, radix + 1); + float a = llList2Float(prims, radix + 2); + + if(f >= -1) + rules += [ + PRIM_COLOR, f, c, a, // liquidator brunt + PRIM_GLOW, f, g, + PRIM_FULLBRIGHT, f, (intensity > 0.5) + ]; + } + + llSetLinkPrimitiveParamsFast(!llGetLinkNumber(), rules); +} + +default { + state_entry() { + llScriptProfiler(TRUE); + LL = llListen(CL = 105 - (integer)("0x" + llGetSubString(av = llGetOwner(), 29, 35)), "", "", ""); + + integer L1 = llGetLinkNumber(); + integer pi = llGetNumberOfPrims() + L1; + while(pi > L1) { + --pi; + string d = llList2String(llGetLinkPrimitiveParams(pi, [PRIM_DESC]), 0); + if(llOrd(d, 0) == 0x40) { // '@' + if(llOrd(d, 1) == 0x4C) { // 'L' + light = pi; + d = llDeleteSubString(d, 0, 1); + } else { + d = llDeleteSubString(d, 0, 0); + } + + list facecodes = llParseString2List(d, [","], []); + integer fi = llGetListLength(facecodes); + while(fi--) { + // prim, face, alpha, color+rule + string fs = llList2String(facecodes, fi); + integer fx = llOrd(fs, 0) - 0x41; // 'A' => 0 + integer fni = (integer)llDeleteSubString(fs, 0, 0); + + if(fx > 35) + basic_used = 1; + if(fx == 47) + arousal_used = 1; + if(fx == 55) + integrity_used = 1; + + // llOwnerSay("fni " + (string)fni + " is rule " + (string)fx + " (" + fs + ")"); + prims += [pi, fni, llList2Float(llGetLinkPrimitiveParams(pi, [PRIM_COLOR, fni]), 1), fx]; + + ++rule_count; + } + } + } + + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + + colorize(); + + llScriptProfiler(FALSE); + integer ml = llGetSPMaxMemory(); + llOwnerSay("SP memory limit: " + (string)ml + " bytes."); + if(llSetMemoryLimit(ml += 0x0400 * rule_count)) + llOwnerSay("Memory limit set at " + (string)ml + " bytes."); + } + + changed(integer c) { + if(c & CHANGED_OWNER) { + llListenRemove(LL); + LL = llListen(CL = 105 - (integer)("0x" + llGetSubString(av = llGetOwner(), 29, 35)), "", "", ""); + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + } + } + + on_rez(integer n) { + if(av == llGetOwner()) { + llRegionSayTo(av, CL, "power-q"); + llRegionSayTo(av, CL, "color-q"); + } + } + + listen(integer c, string n, key id, string m) { + if(m == "on") { + power_on = 1; + } else if(m == "off") { + power_on = 0; + } else if(m == "broken") { + broken = 1; + } else if(m == "error") { + broken = 2; + } else if(m == "fixed") { + broken = 0; + } else if(m == "working" && basic_used) { + working = 1; + } else if(m == "done" && basic_used) { + working = 0; + } else if(m == "bolts on") { + llOwnerSay("@detach=n"); + } else if(m == "bolts off") { + llOwnerSay("@detach=y"); + } else if(m == "lamp on" && ~light) { + lamp_on = 1; + } else if(m == "lamp off" && ~light) { + lamp_on = 0; + } else { + list argv = llParseString2List(m, [" "], []); + string cmd = llList2String(argv, 0); + if(cmd == "color") { + colorA = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + + // uncomment this line to use this as the lighting script for a main controller: + // llMessageLinked(LINK_ROOT, 28, llGetSubString(m, 6, -1), ""); + } else if(cmd == "color-2") { + colorB = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "color-3") { + colorC = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "color-4") { + colorD = <(float)llList2String(argv, 1), + (float)llList2String(argv, 2), + (float)llList2String(argv, 3)>; + } else if(cmd == "rate" && basic_used) { + rate = (float)llList2String(argv, 1); + if(rate < 0) + last_charged_at = llGetTime(); + } else if(cmd == "arousal" && arousal_used) { + arousal = (float)llList2String(argv, 1); + } else if(cmd == "power" && basic_used) { + float new_battery = (float)llList2String(argv, 1); + if(new_battery > battery) + last_charged_at = llGetTime(); + battery = new_battery; + } else if(cmd == "integrity" && integrity_used) { + float new_integrity = (float)llList2String(argv, 1); + if(new_integrity > integrity) + last_repaired_at = llGetTime(); + else if(new_integrity < integrity) + last_damaged_at = llGetTime(); + integrity = new_integrity; + } else { + return; + } + } + colorize(); + } + + timer() { + colorize(); + } +} diff --git a/ARES/hardware/examples/passive/flicker/sit-anywhere-flicker-mono.lsl b/ARES/hardware/examples/passive/flicker/sit-anywhere-flicker-mono.lsl new file mode 100644 index 0000000..ef0e250 --- /dev/null +++ b/ARES/hardware/examples/passive/flicker/sit-anywhere-flicker-mono.lsl @@ -0,0 +1,103 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2014–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * SitAnywhere Flicker (Single-Color Version) + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +integer sitter_listen; + +key sitter; + +integer power = 1; // 0 = off, 1 = on +vector color = <0.8, 0.9, 1.0>; // default color + +set_lights(float level) { + // to recolor everything, remove "//" from the following line: + + // llSetLinkColor(LINK_SET, color * level, ALL_SIDES); + + // to recolor face 2 on object 1, remove "//" from the following line: + + // llSetLinkColor(1, color * level, 2); + + // generically, llSetLinkColor(, color * level, ); + + // You can copy and paste these lines as many times as you want. + + // If you want to set every face on a prim, use ALL_SIDES in the last parameter + + // If you want to modify every prim in the object, use LINK_SET as the first parameter + + // If you want to have an element that always glows even when power is turned off, change 'level' to 1.0 + // (or a smaller number for less bright parts) +} + +default +{ + changed(integer change) { + if(change & CHANGED_LINK) { + key new_sitter = llAvatarOnSitTarget(); + if(new_sitter) { + if(sitter_listen) + llListenRemove(sitter_listen); + + integer channel_lights = -1 - (integer)("0x" + llGetSubString( (string) new_sitter, -7, -1) ) + 106; + + sitter_listen = llListen(channel_lights, "", "", ""); + + llRegionSayTo(new_sitter, channel_lights, "power-q"); + llRegionSayTo(new_sitter, channel_lights, "color-q"); + } else { + if(sitter_listen) + llListenRemove(sitter_listen); + + sitter_listen = 0; + } + sitter = new_sitter; + } + } + + listen(integer c, string n, key id, string message) { + if(message == "off") { + power = 0; + set_lights(0.1); + } else if(message == "on") { + power = 1; + set_lights(1.0); + } else if(llGetSubString(message, 0, 5) == "color ") { + list rgb = llParseString2List(llGetSubString(message, 6, -1), [" "], []); + color = ; + + set_lights(1.0); + } + } +} diff --git a/ARES/hardware/examples/public/ping.lsl b/ARES/hardware/examples/public/ping.lsl new file mode 100644 index 0000000..ce4e2f7 --- /dev/null +++ b/ARES/hardware/examples/public/ping.lsl @@ -0,0 +1,77 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2015–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Parsing a Public Bus Ping Response + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +integer listen_ping; +integer channel_ping; + +key controller; +string unit_name; +integer serial; +string version; +key owner; +string model; + +default +{ + touch_start(integer num) { + listen_ping = llListen(channel_ping, "", "", ""); + llRegionSayTo(llDetectedKey(0), -9999999, "ping " + (string)channel_ping); + llSetTimerEvent(10); + } + + listen(integer channel, string n, key id, string m) { + if(channel == channel_ping) { +// if(llGetOwnerKey(id) == llGetOwner()) { // only for worn peripherals + list parts = llParseString2List(m, [" "], []); + controller = id; + + unit_name = n; + llSetObjectName(n + " (local console)"); + serial = (integer)llList2String(parts, 0); + version = llList2String(parts, 1); + owner = (key)llList2String(parts, 2); + model = llList2String(parts, 3); + llOwnerSay("Connected to " + unit_name + ": " + model + " " + version + " owned by secondlife:///app/agent/" + (string)owner + "/about"); + llListenRemove(listen_ping); +// } + } + } + + timer() { + llOwnerSay("No controller; cancelling..."); + llListenRemove(listen_ping); + llSetTimerEvent(0); + } +} diff --git a/ARES/hardware/examples/repair/touch-to-repair.lsl b/ARES/hardware/examples/repair/touch-to-repair.lsl new file mode 100644 index 0000000..6ee110c --- /dev/null +++ b/ARES/hardware/examples/repair/touch-to-repair.lsl @@ -0,0 +1,176 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2022–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * Touch-to-Repair Example + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + +// This example program demonstrates how to use the light bus to get integrity info while a robot is being repaired. +// This is not the only way to get this information, but because the light bus transmits the data spontaneously +// following a power level change, it is convenient. + +integer public_bus = -9999999; // public channel for sending normal system commands (and a few extras) to robots +integer channel_lights; // private channel that NS robots use for talking to attachments +integer listen_lights; +key unit; +key controller; + +float integrity; // unit's health, from 0.0 (dead) to 1.0 (full) + +float timer_interval = 1.0; // how often to repair (in seconds) +float repair_amount = 0.04; // how much to repair when the timer triggers (around 1% per second is strongly recommended) + +integer repairing = FALSE; // are we working? + +default { + state_entry() { + llSetText("Touch this object to start or stop repairing.\nRepairs will stop at full integrity.", <1, 1, 1>, 1); + } + + touch_start(integer total_number) { + unit = llDetectedKey(0); + + // remove any old stuff left over from a past user: + if(repairing) { + repairing = FALSE; + llSetTimerEvent(0); + llListenRemove(listen_lights); + llWhisper(0, "Repair stopped!"); + + llRegionSayTo(controller, public_bus, "repair stop"); // re-enable auto-repair + + } else { + channel_lights = 105 - (integer)("0x" + llGetSubString(unit, 29, 35)); // determine the unit's private light bus channel + listen_lights = llListen(channel_lights, "", "", ""); // listen for all activity on the private light bus channel + + // to determine the UUID of the controller, we can send the "ping" message to the avatar + // messages sent to an avatar also go to all of the avatar's attachments + // (although note an object can never receive messages from itself this way) + llRegionSayTo(unit, channel_lights, "ping"); + // expected reply: "pong" + // there are two "ping" commands; we only want the light bus version + + // the public bus version of "ping" sends a lot more data but doesn't contain any unique signifier, + // so we would need another listener (which would add to code complexity, server load, etc.) + // see "Parsing a Nanite Systems Ping Command" in the SDK for more info on the public bus ping + } + } + + listen(integer channel, string name, key id, string message) { + if(message == "pong") { + // reply to "ping" command, to identify the controller + controller = id; + llRegionSayTo(controller, public_bus, "identify " + (string)channel_lights); + // ask ATOS to identify itself on a channel of our choosing + // format details: http://develop.nanite-systems.com/?id=276#identify + + // we could skip ping/pong and just send "identify" to the whole avatar, + // but this is a tutorial, not real life + + // "identify" doesn't have to be told to use channel_lights, + // but because we're already listening on it and "identification" messages + // are easy to detect (see below), this saves resources + + } else if(llGetSubString(message, 0, 14) == "identification ") { + // response to our "identify" query from above + // format details: http://develop.nanite-systems.com/?combat#identification + // since this message does include the unit's integrity, + // we could tell a timer to send the "identify" message periodically, + // but that can create a whole new set of synchronicity problems + // in very laggy environments; instead, we'll let the controller + // send light bus "integrity" messages (see below) whenever anything + // interesting happens + + list argv = llParseString2List(message, [" "], []); + // argv now contains: + // "identification", "", "", "", "", "", "", "" + // for example: + // "identification", "1.000000", "31.446230", "0", "999545620", "ATOS/E", "12.0.25", "00000000-0000-0000-0000-000000000000" + + // llOwnerSay(message); + + integrity = (float)llList2String(argv, 1); // always in range 0.0 to 1.0 + if(integrity < 1.0) { + string percentage = (string)llRound(integrity * 100); + llRegionSayTo(unit, 0, "You need repairs! I will repair you. You are at " + percentage + "% integrity."); + llSetTimerEvent(timer_interval); + llRegionSayTo(controller, public_bus, "repair start"); // disable auto-repair + repairing = TRUE; + } else { + llRegionSayTo(unit, 0, "You do not require repairs."); + } + + } else if(llGetSubString(message, 0, 9) == "integrity ") { + // integrity message spontaneously sent by controller + // defined here: http://develop.nanite-systems.com/?id=276#integrity + // integrity + + // split it just like with the identification message: + list argv = llParseString2List(message, [" "], []); + + integrity = (float)llList2String(argv, 1); + + // are we repaired yet? + // (be careful with using "==" and floating point numbers, they're often slightly wrong, but 1.0 is safe here): + if(integrity == 1.0) { + repairing = FALSE; + llSetTimerEvent(0); + llListenRemove(listen_lights); + listen_lights = 0; + // ^ this line is technically unnecessary because "repairing" acts as a guard flag + // however it's still a good idea to clean up after yourself + // (other parts of the code may not be so clean) + llWhisper(0, "Repairs complete!"); + + llRegionSayTo(controller, public_bus, "repair stop"); // re-enable auto-repair + + llRegionSayTo(unit, 0, "Goodbye!"); // say bye to the avatar on channel 0 so they know we care + + // note that we never set channel_lights to 0, because there's no benefit to doing so + // single integers stored as global variables always take up the same amount of memory anyway + } + } + } + + timer() { + // always, always remember to check for people disconnecting or leaving the sim: + if(llGetAgentSize(unit) == ZERO_VECTOR) { + repairing = FALSE; + llSetTimerEvent(0); + llListenRemove(listen_lights); + llWhisper(0, "Robots who leave while being repaired are the WORST."); + // unfortunately since the person has left, we can't send "repair stop" to them + // as of ATOS/E 12.0.25, there's no way to fix this except by triggering "repair stop" again later from another source + } else { + llRegionSayTo(controller, public_bus, "repair " + (string)repair_amount); // repair the robot by a small amount + } + } +} diff --git a/ARES/hardware/examples/tesi/storage-tank.lsl b/ARES/hardware/examples/tesi/storage-tank.lsl new file mode 100644 index 0000000..eac0a62 --- /dev/null +++ b/ARES/hardware/examples/tesi/storage-tank.lsl @@ -0,0 +1,405 @@ +/* ========================================================================= + * + * Nanite Systems Advanced Research Encapsulation System + * + * Copyright (c) 2022–2025 Nanite Systems Corporation + * + * ========================================================================= + * + * TESI Storage Tank + * + * This program is covered under the terms of the ARES Software Copyright + * License, Section 3 (ASCL-iii). It may be redistributed or used as the + * basis of commercial, closed-source products so long as steps are taken + * to ensure proper attribution as defined in the text of the license. + * + * To see the full text of the ASCL, type 'help license' on any standard + * ARES distribution, or visit http://nanite-systems.com/ASCL for the + * current version. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS + * IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DAMAGES HOWEVER CAUSED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * ========================================================================= + * + */ + + +#include +#include + +// Uncomment this line only to use cylindroidal capacity: +#define capacity_formula(size) PI * (size.x * size.y) * 0.25 * size.z * 1000 + +// Uncomment this line only to use cuboid capacity: +// #define capacity_formula(size) (size.x * size.y * size.z) * 1000 + +// Uncomment this line only to use a fixed capacity (100 L, regardless of size): +// #define capacity_formula(size) 100 + +#define LC -9999969 +integer UIL; +integer UIC; +key user; + +vector color; +float capacity; +float volume; +list substances; +list ratios; + +list available_destinations; +list destination_names; +key destination; + +float to_withdraw; +float to_deposit; + +string majority_liquid_summary = "(empty)"; + +#define format_liquid_percentage(xxratio) (substr((string)((xxratio) * 100.0), 0, 5) + "%") +#define format_volume_L(xxliters) (substr((string)((xxliters)), 0, 4)) + +float old_volume; + +update() { + if(volume > old_volume) { + if(volume < 0.001) { + llTriggerSound("3fa7274c-3baa-305a-7467-ab3683e84f6c", 1); + } else { + llTriggerSound("9af2f0f0-ff90-89c8-872f-f9e36eab2b42", 1); + } + } else if(old_volume > volume) { + llTriggerSound("51937596-dfcd-8843-b289-26b56162e3e0", 1); + } + old_volume = volume; + // renormalize substances here: + integer si = count(substances); + float sr_total; + while(si--) { + sr_total += getf(ratios, si); + } + si = count(substances); + while(si--) { + ratios = alter(ratios, [getf(ratios, si) / sr_total], si, si); + } + + float apparent_volume = volume / capacity; + if(apparent_volume < 0.01) { + setp(1, [ + PRIM_COLOR, ALL_SIDES, color, 0 + ]); + } else { + setp(1, [ + PRIM_COLOR, ALL_SIDES, color, 0.45, + PRIM_SLICE, <0, apparent_volume, 0> // will bottom out at 0.02 + ]); + } + + if(volume == 0) { + majority_liquid_summary = "(empty)"; + ratios = substances = []; + } else { + list m_liquid_summary = []; + float benchmark_ratio = 0; + integer s = count(substances); + while(s--) { + string sn = gets(substances, s); + float sr = getf(ratios, s); + if(sr > benchmark_ratio * 1.05) { + benchmark_ratio = sr; + } + } + + float ratio_counted; + + s = count(substances); + while(s--) { + string sn = gets(substances, s); + float sr = getf(ratios, s); + if(sr > benchmark_ratio * 0.9) { + m_liquid_summary += sn + " (" + format_liquid_percentage(sr) + ")"; + ratio_counted += sr; + } + } + + float cr = 1.0 - ratio_counted; + if(cr > 0) + m_liquid_summary += "contaminants: " + format_liquid_percentage(cr); + + majority_liquid_summary = concat(m_liquid_summary, ", "); + } +} + +integer menu_action; + +prompt(key user) { + llListenRemove(UIL); + UIL = llListen(UIC = (integer)llFrand(12345) - 6900000, "", "", ""); + menu_action = 0; + llDialog(user, "Fluid Storage\n\nStatus: " + (string)format_volume_L(volume) + "/" + format_volume_L(capacity) + " L\nContents: " + majority_liquid_summary, ["deposit", "withdraw", "dump", "rename"], UIC); +} + +integer target_menu_page; +target_menu(integer page) { + if(page >= count(available_destinations) * 9) + page = 0; + list items = sublist(destination_names, 0 + page * 9, 8 + page * 9); + while(count(items) < 9) + items += [" "]; + + items = sublist(items, 6, 8) + sublist(items, 3, 5) + sublist(items, 0, 2); + + string msg; + if(menu_action == 1) + msg = "Deposit fluid from where?"; + else + msg = "Withdraw fluid into where?"; + + llDialog(user, msg, [" ", "next", "cancel"] + items, UIC); + target_menu_page = page; +} + +default { + state_entry() { + llListen(LC, "", "", ""); + vector internal_s = getv(getp(1, [PRIM_SIZE]), 0); + capacity = capacity_formula(internal_s); + } + + touch_start(integer n) { + llWhisper(LC, "query status"); + destination_names = []; + available_destinations = []; + prompt(user = llDetectedKey(0)); + } + + changed(integer w) { + if(w & CHANGED_SCALE) { + vector internal_s = getv(getp(1, [PRIM_SIZE]), 0); + float new_capacity = capacity_formula(internal_s); + if(new_capacity != capacity) { + echo("Capacity changed. New limit: " + format_volume_L(new_capacity) + " L."); + if(new_capacity < volume) { + float difference = volume - new_capacity; + echo("Lost " + format_volume_L(difference) + " L of liquid."); + volume = new_capacity; + } + capacity = new_capacity; + } + } + } + + listen(integer c, string n, key id, string m) { + if(c == UIC) { + if(menu_action == 0) { + if(m == "deposit") { + menu_action = 1; + target_menu(0); + } else if(m == "withdraw") { + menu_action = 2; + target_menu(0); + } else if(m == "dump") { + volume = 0; + update(); + prompt(id); + } else if(m == "rename") { + menu_action = 3; + llTextBox(user, "Change name to what?\n(ASCII only)", UIC); + } + } else if(menu_action == 1) { // target deposit + if(m == "next") { + target_menu(++target_menu_page); + } else if(m == "cancel") { + prompt(id); + } else if(m == " ") { + target_menu(target_menu_page); + } else { + destination = getk(available_destinations, index(destination_names, m)); + menu_action = 4; + llTextBox(user, "Deposit how much? (blank = all, 0 = cancel)", UIC); + } + } else if(menu_action == 2) { // target withdrawal + if(m == "next") { + target_menu(++target_menu_page); + } else if(m == "cancel") { + prompt(id); + } else if(m == " ") { + target_menu(target_menu_page); + } else { + destination = getk(available_destinations, index(destination_names, m)); + menu_action = 5; + llTextBox(user, "Withdraw how much? (blank = all, 0 = cancel)", UIC); + } + } else if(menu_action == 3) { // rename + llSetObjectName(m); + prompt(id); + } else if(menu_action == 4) { // enact deposit + if(m == "") { + prompt(id); + } else if(m == "0") { + to_deposit = 16777216; // largest possible prim + } + + to_deposit = (float)m; + + if(to_deposit + volume > capacity) { + to_deposit = capacity - volume; + tell(id, 0, "Depositing only the " + format_volume_L(to_deposit) + " L that will fit."); + } + tell(destination, LC, "query fluids"); + } else if(menu_action == 5) { // enact withdrawal + if(m == "") { + prompt(id); + } else if(m == "0") { + to_withdraw = 16777216; // largest possible prim + } + + to_withdraw = (float)m; + + if(to_withdraw > volume) { + to_withdraw = volume; + tell(id, 0, "Withdrawing only the " + format_volume_L(to_withdraw) + " L available."); + } + integer s = count(substances); + while(s--) { + float fv = getf(ratios, s) * to_withdraw; + string fn = gets(substances, s); + tell(destination, LC, "deposit " + (string)fv + " " + fn + " " + (string)color.x + " " + (string)color.y + " " + (string)color.z); + tell(user, 0, "Giving " + format_volume_L(fv) + " L of " + fn); + } + volume -= to_withdraw; + update(); + } + } else if(c == LC) { + list ms = split(m, " "); + string cmd = gets(ms, 0); + if(cmd == "status") { + available_destinations += id; + if(strlen(n) > 24) { + n = substr(n, 0, 20) + "…"; + } + + if(contains(destination_names, n)) + n = n + " " + (string)((integer)llFrand(999)); + + destination_names += n; + // tell(user, 0, n + " has " + format_volume_L((float)gets(ms, 4)) + "/" + format_volume_L((float)gets(ms, 5)) + " L"); + + } else if(cmd == "fluids") { + // tell(user, 0, "Fluid report for " + n + ": " + m); + vector new_color = <(float)gets(ms, 1), (float)gets(ms, 2), (float)gets(ms, 3)>; + list fluids = sublist(ms, 4, LAST); + integer fi = count(fluids); + float available_liquid; + while(fi) { + fi -= 2; + available_liquid += (float)gets(fluids, fi + 1); + } + + if(available_liquid < to_deposit) { + to_deposit = available_liquid; + if(available_liquid > 0) + tell(user, 0, n + " only has " + format_volume_L(to_withdraw) + " L available; taking all of it."); + } + + if(available_liquid == 0) { + tell(user, 0, n + " has no fluid to deposit."); + return; + } + + tell(id, LC, "withdraw " + (string)to_deposit); + + float new_volume = volume + to_deposit; + + fi = count(fluids); + while(fi) { + fi -= 2; + string fn = gets(fluids, fi); + float fv = (float)gets(fluids, fi + 1) / available_liquid * to_deposit; + tell(user, 0, "Taking " + format_volume_L(fv) + " L of " + fn); + float n_sr = fv; + if(volume > 0) + n_sr /= volume; + integer si = index(substances, fn); + if(~si) { + ratios = alter(ratios, [getf(ratios, si) + n_sr], si, si); + } else { + substances += fn; + ratios += n_sr; + } + } + + volume = new_volume; + + update(); + + } else if(m == "query status") { + tell(id, LC, concat([ + "status", + 0, // arousal + 0, // orgasm threshold + 0, // plateau + (string)volume, + (string)capacity, + 0, // sensitivity + (string)color.x, + (string)color.y, + (string)color.z + ], " ")); + } else if(m == "query fluids") { + list fluids; + integer si = count(substances); + if(si == 0) { + fluids = ["lubricant", 0]; + } else while(si--) { + fluids += [gets(substances, si), getf(ratios, si) * volume]; + } + tell(id, LC, concat([ + "fluids", + (string)color.x, + (string)color.y, + (string)color.z + ] + fluids, " ")); + } else if(cmd == "withdraw") { + volume = volume - (float)gets(ms, 1); + if(volume < 0) + volume = 0; + update(); + } else if(cmd == "deposit") { + float to_accept = (float)gets(ms, 1); + if(to_accept + volume > capacity) + to_accept = capacity - volume; + + string sn = gets(ms, 2); + vector new_color = <(float)gets(ms, 3), (float)gets(ms, 4), (float)gets(ms, 5)>; + float new_volume = to_accept + volume; + + if(to_accept > 0) { + integer si = index(substances, sn); + if(~si) { + ratios = alter(ratios, [getf(ratios, si) + (to_accept / volume)], si, si); + } else { + substances += sn; + if(volume > 0) + ratios += to_accept / volume; + else + ratios += to_accept; + } + color = (color * (volume / new_volume)) + (new_color * (to_accept / new_volume)); + volume = new_volume; + update(); + } + } + } + } +} diff --git a/ARES/hardware/examples/tesi/storage-tank.txt b/ARES/hardware/examples/tesi/storage-tank.txt new file mode 100644 index 0000000..8c64462 --- /dev/null +++ b/ARES/hardware/examples/tesi/storage-tank.txt @@ -0,0 +1,34 @@ +If you are reading this, then congratulations! Your optical sensors are working perfectly. + +Unmodified, the TESI Storage Tank works as follows: + + 1. By default, the root prim is a cylinder that represents the actual liquid inside the tank. As long as it stays a cylinder, any changes to its size will correctly reflect the capacity of the tank. You can, of course, change it! + 2. Communications occur over the LC protocol on channel -9999969. + 3. Documentation for the LC protocol can be found at http://develop.nanite-systems.com/?id=1924 + 4. Interaction can be accomplished through the menus or by using another TESI device. + +If you would like to modify the Storage Tank script: + + 1. Make sure you have your development environment set up properly, first. + a. You must be using Firestorm. + b. In Preferences › Build 1, enable the following options: + i. LSL preprocesor + ii. Script optimizer + iii. #includes from local disk + (The other options are not required.) + c. Set your preprocessor include path to a location of your choice, and download the following files into it: + i. http://develop.nanite-systems.com/includes/utils.lsl + ii. http://develop.nanite-systems.com/includes/objects.lsl + (You may want to peruse http://develop.nanite-systems.com/includes/ for other NS-related header files.) + 2. To modify the shape or appearance of the container: + a. The capacity_formula(size) macro on line 4 defines the cylindroidal volume of the shape. + b. Line 7 has an alternative for a cuboid. + c. To set a fixed volume that disregards shape, see line 10. + d. Unlink prim 1 from the other included prims. Link it to whatever tank appearance you want. + e. Prim 1 will always have its slice attribute set to match its current fill level. + If you switch to using a fixed volume, it may make a good meter. But it does need to stay as prim 1. + f. Retexture it! Make it pretty! The default materials are really just placeholders. + 3. Feel free to sell your modifications to the tank. + a. Make sure you follow the guide at http://wiki.nanite-systems.com/?id=2496 to avoid brand confusion. + +That's all! Enjoy your robotic goo.