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

512 lines
15 KiB
Plaintext

// MLPV2 Version 2.3, by Learjeff Innis, based on
//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
// 15-color balls by Lizz Silverstar
// 2.3: sequences
// 6 avs
// Adjusting state
integer MAX_BALLS = 6;
string Version = "WELM v1.0";
integer b;
integer b0;
integer ballusers;
list BallColors;
integer ch;
integer chat = 1;
integer group;
integer i;
integer menu;
integer menuusers;
integer redo = 1;
integer swap;
integer visible;
integer BallCount;
integer SaneMenuOrder;
integer ReloadOnRez;
integer Adjusting;
string LastPose;
integer BallsNeeded;
float alpha;
string cmd;
string pose;
string Posemsg; // for 'AGAIN'
key owner;
key user;
key user0;
list buttons;
list buttonindex;
list commands;
list menus;
list balls;
list users;
list SoundNames;
list Sounds;
list LMButtons;
list LMParms;
list MenuStack = [0]; // indices to previous menus, for "BACK" command
integer MenuPage; // which page of current menu we're on, 0 for first
stop() {
sendStand(); //msg to pos/pose
llMessageLinked(LINK_THIS, 1, "STOP", (key)"");
llSleep(0.2);
killBalls();
swap = 0;
Adjusting = FALSE;
}
check_poses() {
llOwnerSay("Checking configs");
llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK1"); //msg to memory
integer ix;
string name;
for (ix = 0; ix < llGetListLength(buttons); ++ix) {
name = llList2String(buttons, ix);
if (((integer)llList2String(commands, ix)) != 0) {
llMessageLinked(LINK_THIS,0,"POSEB", (key)name); //msg to memory
}
}
llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK2"); //msg to memory
}
// Return a channel number that's based on the prim's key -- unique per object
integer channel() {
return (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));
}
// setup for a pose based on menu characteristics
setup_pose() {
if (BallsNeeded) { // if submenu includes balls:
if (BallCount != BallsNeeded) {
rezBalls(); // if not enough balls present: create balls
llSleep(0.5);
}
integer ix;
for (ix = 0; ix < BallsNeeded; ++ix) {
llSay(ch + ix, llList2String(BallColors, ix) // to ball: color, ballnum, adjusting
+ "|" + (string) ix
+ "|" + (string) Adjusting);
}
if (ballusers) setBalls("GROUP"); //if group access only
}
}
unauth(string button, string who) {
llDialog(user0, "\n" + button + " button allowed only for " + who, ["OK"], -1);
}
continMenu(string str) {
llDialog(user0, "\n"+str+llKey2Name(user)+" is using the menu, continue?", ["Yes","Cancel"], ch - 1);
}
mainMenu() {
MenuPage = 0;
menu = 0;
doMenu(FALSE);
}
//menu partly based on Menu Engine by Zonax Delorean (BSD License)
//llDialog(user, menuname, buttons(from index to nextindex-1), channel)
doMenu(integer inhibit_showing) {
integer colors = llList2Integer(balls,menu);
integer ix;
integer mask = 0xf;
integer shift = 0;
BallsNeeded = 0;
BallColors = [];
for (ix = 0; ix < MAX_BALLS; ++ix) {
integer bc = (colors & mask) >> ix*4;
BallColors += (list)bc;
if (bc) {
BallsNeeded += 1;
}
mask = mask << 4;
}
if (inhibit_showing) {
return;
}
b0 = llList2Integer(buttonindex, menu); //position of first butt on for this (sub)menu
b = llList2Integer(buttonindex, menu+1); //position of first button for next (sub)menu
b0 += MenuPage * 12;
if (b - b0 > 12) {
b = b0 + 12;
}
list buttons1 = llList2List(buttons, b0, b - 1);
if (SaneMenuOrder) {
buttons1 =
llList2List(buttons1, -3, -1)
+ llList2List(buttons1, -6, -4)
+ llList2List(buttons1, -9, -7)
+ llList2List(buttons1, -12, -10);
}
llDialog(user, Version + "\n\n" + llList2String(menus,menu), buttons1, ch - 1);
llResetTime();
}
say(string str) {
if (menuusers) llWhisper(0,str);
else llOwnerSay(str);
}
killBalls() {
integer ix;
for (ix = 0; ix < MAX_BALLS; ++ix) {
llSay(ch + ix, "DIE"); //msg to balls
}
BallCount = 0;
llSetTimerEvent(0.0);
}
setBalls(string cmd) {
integer ix;
for (ix = 0; ix < BallCount; ++ix) {
llSay(ch + ix, cmd); //msg to balls
}
}
rezBalls() {
integer current = BallCount;
if (BallsNeeded == BallCount) return;
if (BallCount == 0) {
killBalls(); // for reinitialization, if old balls are around
}
while (BallCount > BallsNeeded) {
--BallCount;
llSay(ch + BallCount, "DIE");
}
while (BallCount < BallsNeeded) {
llRezObject("~ball",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,ch+BallCount);
++BallCount;
}
// Only do this if there were no balls
if (! current) {
llMessageLinked(LINK_THIS,0,"REPOS",(key)""); //msg to pos
}
llSetTimerEvent(60.0);
}
sendStand() {
llMessageLinked(LINK_THIS,0,"POSE","0,"+(string)BallCount); //msg to pos/pose
llMessageLinked(LINK_THIS,0,"POSEB", "stand");
}
touched(integer same_group) {
if (user0 == owner || (menuusers == 1 && same_group) || menuusers == 2) { //0=owner 1=group 2=all
if (user0 != user) {
if (llGetTime() < 60.0 && user != (key)"") {
continMenu("");
return;
}
user = user0;
group = same_group;
}
mainMenu();
}
}
// return TRUE if caller should do menu
integer handle_cmd(string button, integer sequenced) {
b = llListFindList(buttons, (list) button); //find position of cmd
string cmd = llList2String(commands,b); //get command
if (cmd == "TOMENU") {
integer newmenu = llListFindList(menus,[ button ]); //find submenu
if (newmenu == -1) return FALSE;
if (sequenced) {
integer oldmenu = menu;
menu = newmenu;
doMenu(TRUE);
setup_pose();
menu = oldmenu;
return FALSE;
}
i = llList2Integer(users, newmenu);
if (user == owner || (i == 1 && group) || i == 2) { //0=owner 1=group 2=all
MenuStack = [] + (list)menu + MenuStack;
MenuPage = 0;
menu = newmenu;
doMenu(sequenced);
return FALSE;
}
if (i == 1) unauth(button, "group");
else unauth(button, "owner");
return FALSE;
} else if (cmd == "BACK") {
if (MenuPage) {
--MenuPage;
doMenu(sequenced);
return FALSE;
}
menu = llList2Integer(MenuStack,0);
MenuStack = llList2List(MenuStack,1,-1);
doMenu(sequenced);
return FALSE;
} else if (cmd == "MORE") {
++MenuPage;
doMenu(sequenced);
return FALSE;
} else if (cmd == "CHECK") {
check_poses();
} else if ((integer)cmd > 0) { //POSE
if (Adjusting && button != pose) {
llMessageLinked(LINK_THIS,0,"SAVE",pose); //msg to pos/pose
llSleep(5.);
}
setup_pose();
Posemsg = cmd + "," + (string) BallCount;
llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose
llMessageLinked(LINK_THIS,0,"POSEB", (key)button); //msg to memory
if (chat) say(button);
pose = button;
} else if (cmd == "SWAP") {
swap += 1;
llMessageLinked(LINK_THIS,0,"SWAP",(key)((string)swap)); //msg to pos/pose
} else if (cmd == "STAND") {
sendStand(); //msg to pos/pose
if (chat) say(button);
pose = "stand";
} else if (cmd == "STOP") {
if (chat) say(button);
stop();
return FALSE;
} else if (cmd == "ADJUST") {
Adjusting = ! Adjusting;
setBalls("ADJUST|" + (string)Adjusting);
} else if (cmd == "HIDE") {
setBalls("0");
} else if (cmd == "SHOW") {
setBalls("SHOW");
} else if (cmd == "DUMP") {
llMessageLinked(LINK_THIS,1,"DUMP",(key)"");
} else if (cmd == "INVISIBLE") {
visible = !visible;
llSetAlpha((float)visible*alpha, ALL_SIDES);
} else if (cmd == "REDO") {
redo = !redo;
if (redo) say(button+" ON"); else say(button+" OFF");
} else if (cmd == "CHAT") {
chat = !chat;
if (chat) say(button+" ON"); else say(button+" OFF");
} else if (cmd == "BALLUSERS") {
ballusers = !ballusers;
if (ballusers) {
llOwnerSay(button+" GROUP");
setBalls("GROUP");
} else {
llOwnerSay(button+" ALL");
setBalls("ALL");
}
} else if (cmd == "MENUUSERS") {
if (user == owner) {
if (!menuusers) {
menuusers = 1;
llOwnerSay(button+" GROUP");
} else if (menuusers == 1) {
menuusers = 2;
llOwnerSay(button+" ALL");
} else if (menuusers == 2) {
menuusers = 0;
llOwnerSay(button+" OWNER");
}
} else unauth(button, "owner");
} else if (cmd == "RESET" || cmd == "RELOAD" || cmd == "RESTART") {
stop();
if (chat) say(button);
if (cmd == "RESET") {
llResetScript();
} else {
llResetOtherScript("~memory");
if (cmd == "RESTART") {
llResetScript();
}
}
} else if (cmd == "OFF") {
sendStand(); //msg to pos/pose
stop();
if (user == owner) {
llOwnerSay(button);
llResetOtherScript("~run");
llResetScript();
}
unauth(button, "owner");
return FALSE;
} else if (llGetSubString(cmd, 0, 0) == "Z" || (cmd == "SAVE")) { //SAVE or Z-adjust
llMessageLinked(LINK_THIS,0,cmd,pose); //msg to pos/pose
doMenu(sequenced);
return FALSE;
} else if (cmd == "LINKMSG") {
// menu button to send LM to a non-MLPV2 script
integer ix = llListFindList(LMButtons, [button]);
if (ix != -1) {
list lmparms = llCSV2List(llList2String(LMParms, ix));
llMessageLinked(
llList2Integer(lmparms, 1), // destination link#
llList2Integer(lmparms, 2), // 'num' arg
llList2String(lmparms, 3), // 'str' arg
user0); // key arg
if (llList2Integer(lmparms,0)) { // inhibit remenu?
return FALSE; // yes, bug out
}
}
} else if (cmd == "SOUND") {
integer ix = llListFindList(SoundNames, (list)button);
if (ix >= 0) {
llPlaySound(llList2String(Sounds, ix), 1.);
}
}
return TRUE;
}
default {
state_entry() {
ch = channel();
killBalls();
llSleep(2.0); // give ~run a chance to shut us down
llResetOtherScript("~menucfg");
llResetOtherScript("~pos");
llResetOtherScript("~pose");
llResetOtherScript("~poser");
llResetOtherScript("~poser 1");
llResetOtherScript("~poser 2");
llResetOtherScript("~poser 3");
llResetOtherScript("~poser 4");
llResetOtherScript("~poser 5");
alpha = llGetAlpha(0); //store object transparancy (alpha)
if (alpha < 0.1) alpha = 0.5; else visible = 1; //if invisibl e store a visible alpha
}
link_message(integer from, integer num, string str, key id) {
if (from != llGetLinkNumber()) { return; }
if (num >= 0) { return;}
// LMs from ~memory, passing configuration
if (num == -1) {
buttons = llCSV2List(str);
} else if (num == -2) {
commands = llCSV2List(str);
} else if (num == -3) {
menus = llCSV2List(str);
} else if (num == -4) {
buttonindex = llCSV2List(str);
} else if (num == -5) {
balls = llCSV2List(str);
} else if (num == -6) {
users = llCSV2List(str);
} else if (num == -7) {
LMButtons = llCSV2List(str);
} else if (num == -8) {
LMParms = llParseStringKeepNulls(str, ["|"], []);
} else if (num == -9) {
SoundNames = llCSV2List(str);
} else if (num == -10) {
Sounds = llCSV2List(str);
} else if (num == -20) {
list args = llCSV2List(str);
redo = llList2Integer(args,0);
chat = llList2Integer(args,1);
ballusers = llList2Integer(args,2);
menuusers = llList2Integer(args,3);
SaneMenuOrder = llList2Integer(args,4);
ReloadOnRez = llList2Integer(args,5);
state on;
}
}
state_exit() {
llOwnerSay("("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
llWhisper(0, Version + ": READY");
}
}
state re_on {
state_entry() {
state on;
}
}
state on {
state_entry() {
ch = channel();
owner = llGetOwner();
llListen(ch - 1, "", NULL_KEY, ""); //listen for pressed buttons
// llWhisper(0, "Channel: " + (string)ch);
}
on_rez(integer arg) {
if (ReloadOnRez) {
llResetScript();
}
BallCount = 0;
llSetTimerEvent(0.0);
state re_on;
}
touch_start(integer tcount) {
user0 = llDetectedKey(0);
touched(llDetectedGroup(0));
}
listen(integer channel, string name, key id, string button) {
if (id != user) {
if (button == "Yes") {
user = id;
group = llSameGroup(user0);
mainMenu();
} else if (button != "Cancel") {
continMenu("Selection cancelled because ");
}
return;
}
if (handle_cmd(button, FALSE) && redo) doMenu(FALSE);
}
link_message(integer from, integer num, string str, key id) {
if (str == "PRIMTOUCH") {
user0 = id;
touched(num);
return;
}
if (num == 0 && str == "AGAIN") {
llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose
llMessageLinked(LINK_THIS,0,"POSEB", (key)pose); //msg to memory
return;
}
if (num == -12002) {
handle_cmd(str, TRUE);
return;
}
}
timer() {
setBalls("LIVE"); //msg to balls: stay alive
}
}