ARES-SDK/ARES/hardware/examples/passive/flicker/flicker-tetra-autoconf.lsl

366 lines
13 KiB
Plaintext

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