Files
LSL-Scripts/TGLM/~sequencer.lsl
Fred Beckhusen 169fb179da unpacked files
2023-02-14 12:08:06 -06:00

448 lines
11 KiB
Plaintext

//MPLV2 Version 2.3 by Learjeff Innis, based on
//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Mi ffy Fluffy (BSD License)
// Allow programmed sequences of poses
// This script resets whenever any of its config cards change.
integer MAX_AVS = 6;
list SeqNames; // name of each sequence
list SeqSteps; // CSV of steps for each seq, indexed as SeqNames
list CurSeqSteps;
string CurSeqName;
integer CurSeqStepIx;
string CurMenu;
string CurPose;
// debugs:
// 1 = sequence start/stop
// 2 = echo each step as executed
// 4 = av hop on/off
// 8 = avwait check
// 0x10 = debug config
integer Debug;
list DELIMS = [" | "," | "," | "," | "," |","| ","|"];
list COMMANDS = [
"MENU"
, "POSE"
, "WAIT"
, "REPEAT"
, "LABEL"
, "GOTO"
, "STOP"
, "WHISPER"
, "SAY"
, "AVWAIT"
];
config_init() {
SeqNames = [];
SeqSteps = [];
Debug = 0;
}
config_done() {
seq_save(); // save last sequence, if any
debug(0x10, "Names: " + llList2CSV(SeqNames));
}
parse_config_line(string data) {
if (llGetSubString(data,0,0) == "/" || llStringLength(data) == 0) { // skip comments and blank lines
return;
}
list ldata = llParseStringKeepNulls(data, DELIMS, []);
string cmd = llList2String(ldata, 0);
string arg1 = llList2String(ldata, 1);
string arg2 = llList2String(ldata, 2);
string arg3 = llList2String(ldata, 3);
if (cmd == "SEQUENCE") {
seq_save(); // save previous sequence, if any
CurSeqName = arg1;
CurSeqSteps = [];
} else if (llListFindList(COMMANDS, (list)cmd) >= 0) {
if (cmd == "LABEL") {
CurSeqSteps += (list) (cmd + "|" + arg1);
} else {
CurSeqSteps += (list) (cmd + "|" + arg1 + "|" + arg2 + "|" + arg3);
}
} else if (cmd == "debug") {
Debug += (integer)arg1;
} else {
llWhisper(0, "Unknown sequence command: '" + cmd + "' - ignoring");
}
}
list Avnames; // one for each ball
integer Avwait;
list AvwaitBalls;
// List of avatar names per ball: adding/removing/checking
addAv(string name, integer ballIx) {
Avnames = llListReplaceList(Avnames, (list)name, ballIx, ballIx);
if (Avwait && avs_seated()) {
Avwait = FALSE;
llSetTimerEvent(0.1);
}
}
removeAv(integer ballIx) {
addAv("", ballIx);
}
integer avs_seated() {
integer ix;
integer ball;
for (ix = llGetListLength(AvwaitBalls) - 1; ix >= 0; --ix) {
ball = llList2Integer(AvwaitBalls, ix);
if (llList2String(Avnames, ball) == "") {
debug(8, "Nobody on ball " + (string) ball);
return FALSE;
}
}
debug(8, "All avs seated");
return TRUE;
}
// In 'src', replace 'target' string with 'replacement' string,
// and return the result.
string replace_text(string src, string target, string replacement)
{
string text = src;
integer ix;
ix = llSubStringIndex(src, target);
if (ix >= 0) {
text = llDeleteSubString(text, ix, ix + llStringLength(target) - 1);
text = llInsertString(text, ix, replacement);
}
return (text);
}
string firstname(string name) {
return llList2String(llParseString2List(name, [" "], []), 0);
}
string customize(string src) {
integer avix;
string avname;
for (avix = 0; avix < MAX_AVS; ++avix) {
avname = firstname(llList2String(Avnames, avix));
if (avname == "") avname = "somebody";
src = replace_text(src, "/"+(string)avix, avname);
}
return src;
}
send_cmd(string cmd) {
llMessageLinked(LINK_THIS, -12002, cmd, (key)"");
}
seq_save() {
if (CurSeqName == "") {
return;
}
SeqNames += CurSeqName;
SeqSteps += llList2CSV(CurSeqSteps);
}
seq_start(string name) {
Avwait = FALSE;
integer ix = llListFindList(SeqNames, (list)name);
if (ix < 0) {
llWhisper(0, "No such sequence: '" + name + "'");
CurSeqSteps = [];
CurSeqStepIx = -1;
return;
}
debug(1, "Start sequence " + name);
CurSeqStepIx = 0;
CurSeqSteps = llCSV2List(llList2String(SeqSteps, ix));
seq_execute();
}
seq_advance() {
if (++CurSeqStepIx >= llGetListLength(CurSeqSteps)) {
seq_stop();
}
}
seq_execute() {
list step;
string cmd;
string arg1;
string arg2;
string arg3;
while (CurSeqStepIx >= 0) {
step = llParseString2List(llList2String(CurSeqSteps, CurSeqStepIx), DELIMS, []);
cmd = llList2String(step, 0);
arg1 = llList2String(step, 1);
arg2 = llList2String(step, 2);
arg3 = llList2String(step, 3);
debug(2, cmd + "|" + arg1);
if (cmd == "MENU") {
CurMenu = arg1;
send_cmd(CurMenu);
seq_advance();
} else if (cmd == "POSE") {
// llSleep(.5);
CurPose = arg1;
send_cmd(arg1);
if (arg3 != "") {
llWhisper((integer)arg2, customize(arg3));
}
seq_advance();
} else if (cmd == "WAIT") {
llSetTimerEvent((float) arg1);
seq_advance();
return;
} else if (cmd == "REPEAT") {
CurSeqStepIx = 0;
} else if (cmd == "LABEL") {
seq_advance();
} else if (cmd == "GOTO") {
CurSeqStepIx = llListFindList(CurSeqSteps, (list)("LABEL|" + arg1));
if (CurSeqStepIx < 0) {
llWhisper(0, "No such sequence label: '" + arg1 + "'");
seq_stop();
return;
}
} else if (cmd == "WHISPER") {
llWhisper((integer)arg1, customize(arg2));
seq_advance();
} else if (cmd == "SAY") {
llSay((integer)arg1, customize(arg2));
seq_advance();
} else if (cmd == "AVWAIT") {
integer argix;
integer ballix;
AvwaitBalls = [];
list balls = llParseString2List(arg1, [" "], []);
for (argix = llGetListLength(balls) - 1; argix >= 0; --argix) {
ballix = (integer)llList2String(balls, argix);
AvwaitBalls += (list)(ballix);
}
seq_advance();
if (! avs_seated()) {
llSetTimerEvent(0.); // just to be sure
if (arg2 != "") {
llWhisper(0, arg2);
}
Avwait = TRUE;
return;
}
} else {
send_cmd(cmd);
seq_advance();
}
}
}
seq_stop() {
Avwait = FALSE;
debug(1, "stopping sequence");
CurSeqStepIx = -1;
llSetTimerEvent(0.);
}
debug(integer level, string txt) {
if (Debug & level) {
llWhisper(0, llGetScriptName() + ": " + txt);
}
}
string plural(string singular, string plural, integer count) {
if (count != 1) {
return plural;
}
return singular;
}
announce()
{
integer count = llGetListLength(SeqNames);
llOwnerSay((string)count
+ plural(" sequence (", " sequences (", count)
+ llGetScriptName()
+ ": "
+ (string)llGetFreeMemory()
+ " bytes free)");
}
// Globals for reading card config
integer ConfigLineIndex;
list ConfigCards; // list of names of config cards
string ConfigCardName; // name of card being read
integer ConfigCardIndex; // index of next card to read
key ConfigQueryId;
string ConfigCardKeys; // to see if anything changed
string get_cards() {
ConfigCards = [];
string keys = "";
string item;
integer ix = llGetInventoryNumber(INVENTORY_NOTECARD);
while (ix-- > 0) {
item = llGetInventoryName(INVENTORY_NOTECARD, ix);
if (llSubStringIndex(item, ".SEQUENCES") >= 0) {
ConfigCards += (list) item;
keys += (string)llGetInventoryKey(item);
}
}
return keys;
}
integer next_card()
{
if (ConfigCardIndex >= llGetListLength(ConfigCards)) {
ConfigCards = [];
return (FALSE);
}
ConfigLineIndex = 0;
ConfigCardName = llList2String(ConfigCards, ConfigCardIndex);
ConfigCardIndex++;
ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex);
llOwnerSay("Reading " + ConfigCardName);
return (TRUE);
}
default {
state_entry() {
ConfigCardKeys = get_cards();
ConfigCardIndex = 0;
ConfigCards = llListSort(ConfigCards, 1, TRUE);
if (! next_card()) {
state on;
}
}
dataserver(key query_id, string data) {
if (query_id != ConfigQueryId) {
return;
}
if (data == EOF) {
if (next_card()) {
return;
}
state on;
}
parse_config_line(llStringTrim(data, STRING_TRIM));
++ConfigLineIndex;
ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); //read next line of positions notecard
}
state_exit() {
config_done();
announce();
}
}
state re_on
{
state_entry() {
state on;
}
}
state on {
state_entry() {
Avnames = [];
integer ix;
for (ix = 0; ix < MAX_AVS; ++ix) {
Avnames += (list)"";
}
}
on_rez(integer arg) {
state re_on;
}
link_message(integer from, integer num, string str, key dkey) {
if (str == "PRIMTOUCH") {
return;
}
if (num == 0 && str == "POSEB") {
if ((string)dkey != CurPose) {
seq_stop();
}
return;
}
if (num == 1 && str == "STOP") {
seq_stop();
return;
}
if (num == -11000) {
// av hopped on
list parms = llParseStringKeepNulls(str, ["|"], []);
integer ballnum = (integer)llList2String(parms, 0);
// string anim = llList2String(parms, 1); // anim name parameter, if desired
debug(4, llKey2Name(dkey) + ": on ball " + (string)ballnum);
addAv(llKey2Name(dkey), ballnum);
return;
} else if (num == -11001) {
// av hopped off
debug(4, llKey2Name(dkey) + ": off ball " + str);
removeAv((integer)str);
return;
} else if (num != -12001) {
return;
}
list ldata = llParseString2List(str, [" "], []);
string cmd = llList2String(ldata, 0);
if (cmd == "SEQUENCE") {
seq_start(llList2String(ldata, 1));
} else if (cmd == "PAUSE") {
debug(1, "pausing");
llSetTimerEvent(0.);
} else if (cmd == "RESUME") {
debug(1, "resuming");
llSetTimerEvent(.1);
}
}
timer() {
seq_execute();
}
changed(integer change) {
if (change & CHANGED_INVENTORY) {
if (get_cards() != ConfigCardKeys) {
llResetScript();
}
}
}
}