451 lines
14 KiB
Text
451 lines
14 KiB
Text
/*
|
|
* [AV]sequence - Play sequences of poses.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright © the AVsitter Contributors (http://avsitter.github.io)
|
|
* AVsitter™ is a trademark. For trademark use policy see:
|
|
* https://avsitter.github.io/TRADEMARK.mediawiki
|
|
*
|
|
* Please consider supporting continued development of AVsitter and
|
|
* receive automatic updates and other benefits! All details and user
|
|
* instructions can be found at http://avsitter.github.io
|
|
*/
|
|
|
|
string product = "AVsitter™ sequence";
|
|
string #version = "2.2p04";
|
|
string main_script = "[AV]sitA";
|
|
list SITTERS;
|
|
integer DEBUG;
|
|
string notecard_name = "[AV]sequence_settings";
|
|
integer notecard_line;
|
|
key notecard_query;
|
|
key notecard_key;
|
|
list SEQUENCE_DATA_NAMES;
|
|
list SEQUENCE_DATA_ACTIONS;
|
|
list SEQUENCE_DATA_DATAS;
|
|
string CURRENT_SEQUENCE_NAME;
|
|
list CURRENT_SEQUENCE_ACTIONS;
|
|
list CURRENT_SEQUENCE_DATAS = [CURRENT_SEQUENCE_NAME]; //OSS::list CURRENT_SEQUENCE_DATAS; // Force error in LSO
|
|
integer SEQUENCE_LINKNUMBER = 90210;
|
|
integer SEQUENCE_POINTER = -1;
|
|
integer sequence_running;
|
|
key CONTROLLER;
|
|
key CONTROLLED;
|
|
integer menu_channel;
|
|
integer menu_handle;
|
|
integer playsounds = TRUE;
|
|
integer no_waits_yet;
|
|
integer verbose = 1;
|
|
|
|
Out(integer level, string out)
|
|
{
|
|
if (verbose >= level)
|
|
{
|
|
llOwnerSay(llGetScriptName() + "[" + version + "] " + out);
|
|
}
|
|
}
|
|
|
|
string strReplace(string str, string search, string replace)
|
|
{
|
|
return llDumpList2String(llParseStringKeepNulls(str, [search], []), replace);
|
|
}
|
|
|
|
DEBUGSay(integer level, string out)
|
|
{
|
|
if (DEBUG >= level)
|
|
{
|
|
llWhisper(0, out);
|
|
}
|
|
}
|
|
|
|
run_sequence()
|
|
{
|
|
while (SEQUENCE_POINTER >= 0)
|
|
{
|
|
string command = llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER);
|
|
string data = llList2String(CURRENT_SEQUENCE_DATAS, SEQUENCE_POINTER);
|
|
list data_list = llParseStringKeepNulls(data, ["|"], []);
|
|
if (command == "PLAY")
|
|
{
|
|
DEBUGSay(2, "Playing pose " + data);
|
|
llMessageLinked(LINK_THIS, 90003, data, "");
|
|
llSleep(0.5);
|
|
}
|
|
else if (command == "SAY")
|
|
{
|
|
llSay(0, parse_text(data));
|
|
}
|
|
else if (command == "WHISPER")
|
|
{
|
|
llWhisper(0, parse_text(data));
|
|
}
|
|
else if (command == "SOUND")
|
|
{
|
|
if (playsounds)
|
|
{
|
|
string sound = llList2String(data_list, 0);
|
|
float volume = (float)llList2String(data_list, 1);
|
|
llPlaySound(sound, volume);
|
|
DEBUGSay(2, "Playing sound " + sound + " at volume " + (string)volume);
|
|
}
|
|
}
|
|
else if (command == "LOOP")
|
|
{
|
|
no_waits_yet = FALSE;
|
|
if (SEQUENCE_POINTER == llGetListLength(CURRENT_SEQUENCE_ACTIONS) - 1)
|
|
{
|
|
SEQUENCE_POINTER = -1;
|
|
DEBUGSay(2, "Looping back to start of sequence");
|
|
if (sequence_running)
|
|
{
|
|
llSetTimerEvent(0.1);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else if (command == "WAIT")
|
|
{
|
|
if (sequence_running)
|
|
{
|
|
float time = (float)data;
|
|
DEBUGSay(2, "Waiting for " + (string)time + " seconds");
|
|
llSetTimerEvent(time);
|
|
if (time >= 2)
|
|
{
|
|
integer found;
|
|
integer next_POINTER = SEQUENCE_POINTER;
|
|
while (next_POINTER++ < llGetListLength(CURRENT_SEQUENCE_ACTIONS) && found == FALSE)
|
|
{
|
|
string next_command = llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER + 1);
|
|
if (next_command == "WAIT" || next_command == "SOUND")
|
|
{
|
|
found = TRUE;
|
|
if (next_command == "SOUND")
|
|
{
|
|
list next_data_list = llParseStringKeepNulls(llList2String(CURRENT_SEQUENCE_DATAS, next_POINTER), ["|"], []);
|
|
string sound = llList2String(next_data_list, 0);
|
|
DEBUGSay(2, "Preloading sound " + sound);
|
|
llPreloadSound(sound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
no_waits_yet = FALSE;
|
|
}
|
|
return;
|
|
}
|
|
if (++SEQUENCE_POINTER >= llGetListLength(CURRENT_SEQUENCE_ACTIONS))
|
|
{
|
|
integer index = llListFindList(CURRENT_SEQUENCE_ACTIONS, ["LOOP"]);
|
|
if (index != -1)
|
|
{
|
|
SEQUENCE_POINTER = index;
|
|
DEBUGSay(2, "Looping back to line " + (string)SEQUENCE_POINTER + " of sequence");
|
|
if (sequence_running)
|
|
{
|
|
llSetTimerEvent(0.1);
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
stop_sequence(FALSE);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
integer get_number_of_scripts()
|
|
{
|
|
integer i;
|
|
while (llGetInventoryType(main_script + " " + (string)(++i)) == INVENTORY_SCRIPT)
|
|
;
|
|
return i;
|
|
}
|
|
|
|
string parse_text(string say)
|
|
{
|
|
integer i;
|
|
for (i = 0; i < llGetListLength(SITTERS); i++)
|
|
{
|
|
string sitter_name = llList2String(llParseString2List(llKey2Name(llList2String(SITTERS, i)), [" "], []), 0);
|
|
if (sitter_name == "")
|
|
{
|
|
sitter_name = "nobody";
|
|
}
|
|
say = strReplace(say, "/" + (string)i, sitter_name);
|
|
}
|
|
return say;
|
|
}
|
|
|
|
start_sequence(integer index)
|
|
{
|
|
no_waits_yet = sequence_running = TRUE;
|
|
SEQUENCE_POINTER = 0;
|
|
CURRENT_SEQUENCE_NAME = llList2String(SEQUENCE_DATA_NAMES, index);
|
|
CURRENT_SEQUENCE_ACTIONS = llParseStringKeepNulls(llList2String(SEQUENCE_DATA_ACTIONS, index), ["◆"], []);
|
|
CURRENT_SEQUENCE_DATAS = llParseStringKeepNulls(llList2String(SEQUENCE_DATA_DATAS, index), ["◆"], []);
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Started!");
|
|
}
|
|
|
|
stop_sequence(integer stopSound)
|
|
{
|
|
if (sequence_running)
|
|
{
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Ended!");
|
|
}
|
|
sequence_running = FALSE;
|
|
SEQUENCE_POINTER = -1;
|
|
llSetTimerEvent(0);
|
|
if (stopSound && llListFindList(CURRENT_SEQUENCE_ACTIONS, ["SOUND"]) != -1)
|
|
{
|
|
llStopSound();
|
|
}
|
|
}
|
|
|
|
sequence_control()
|
|
{
|
|
llListenRemove(menu_handle);
|
|
menu_channel = ((integer)llFrand(0x7FFFFF80) + 1) * -1; // 7FFFFF80 = max float < 2^31
|
|
string pauseplay = "▶";
|
|
if (sequence_running)
|
|
{
|
|
pauseplay = "▮▮";
|
|
}
|
|
list menu_items = ["◀◀", pauseplay, "▶▶"];
|
|
menu_handle = llListen(menu_channel, "", CONTROLLER, "");
|
|
llDialog(CONTROLLER, product + " " + version + "\n\n[" + CURRENT_SEQUENCE_NAME + "]\n◀◀ = previous anim in sequence.\n▮▮ = pause sequence.\n▶▶ = skip to next anim in sequence.", order_buttons(["[BACK]"] + menu_items), menu_channel);
|
|
}
|
|
|
|
list order_buttons(list buttons)
|
|
{
|
|
return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4) + llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10);
|
|
}
|
|
|
|
commit_sequence_data()
|
|
{
|
|
SEQUENCE_DATA_NAMES += CURRENT_SEQUENCE_NAME;
|
|
SEQUENCE_DATA_ACTIONS += llDumpList2String(CURRENT_SEQUENCE_ACTIONS, "◆");
|
|
SEQUENCE_DATA_DATAS += llDumpList2String(CURRENT_SEQUENCE_DATAS, "◆");
|
|
}
|
|
|
|
default
|
|
{
|
|
state_entry()
|
|
{
|
|
notecard_key = llGetInventoryKey(notecard_name);
|
|
if (llGetInventoryType(notecard_name) == INVENTORY_NOTECARD)
|
|
{
|
|
Out(0, "Loading...");
|
|
notecard_query = llGetNotecardLine(notecard_name, notecard_line);
|
|
}
|
|
}
|
|
|
|
changed(integer change)
|
|
{
|
|
if (change & CHANGED_INVENTORY)
|
|
{
|
|
if (llGetInventoryKey(notecard_name) != notecard_key)
|
|
{
|
|
llResetScript();
|
|
}
|
|
}
|
|
}
|
|
|
|
dataserver(key query_id, string data)
|
|
{
|
|
if (query_id == notecard_query)
|
|
{
|
|
if (data == EOF)
|
|
{
|
|
commit_sequence_data();
|
|
state running;
|
|
}
|
|
else
|
|
{
|
|
list datalist = llParseString2List(data, [" "], []);
|
|
string command = llList2String(datalist, 0);
|
|
data = llStringTrim(llDumpList2String(llList2List(datalist, 1, 99999), " "), STRING_TRIM);
|
|
list commands = ["PLAY", "WAIT", "SAY", "WHISPER", "SOUND", "LOOP"];
|
|
if (command == "DEBUG")
|
|
{
|
|
DEBUG = (integer)data;
|
|
}
|
|
else if (command == "SEQUENCE")
|
|
{
|
|
if (CURRENT_SEQUENCE_NAME != "")
|
|
{
|
|
commit_sequence_data();
|
|
}
|
|
CURRENT_SEQUENCE_NAME = data;
|
|
CURRENT_SEQUENCE_ACTIONS = [];
|
|
CURRENT_SEQUENCE_DATAS = [];
|
|
}
|
|
else if (llListFindList(commands, [command]) != -1)
|
|
{
|
|
CURRENT_SEQUENCE_ACTIONS += command;
|
|
CURRENT_SEQUENCE_DATAS += data;
|
|
}
|
|
notecard_query = llGetNotecardLine(notecard_name, ++notecard_line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
state running
|
|
{
|
|
state_entry()
|
|
{
|
|
Out(0, (string)llGetListLength(SEQUENCE_DATA_NAMES) + " Sequences Ready, Mem=" + (string)(65536 - llGetUsedMemory()));
|
|
integer i;
|
|
for (i = 0; i < get_number_of_scripts(); i++)
|
|
{
|
|
SITTERS += NULL_KEY;
|
|
}
|
|
}
|
|
|
|
link_message(integer sender, integer num, string msg, key id)
|
|
{
|
|
if (sender == llGetLinkNumber())
|
|
{
|
|
if (num == 90065)
|
|
{
|
|
integer index = llListFindList(SITTERS, [id]);
|
|
if (index != -1)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], index, index);
|
|
}
|
|
stop_sequence(TRUE);
|
|
}
|
|
else if (num == 90030)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], (integer)msg, (integer)msg);
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], (integer)((string)id), (integer)((string)id));
|
|
stop_sequence(TRUE);
|
|
}
|
|
else if (num == 90070)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [id], (integer)msg, (integer)msg);
|
|
}
|
|
else if (num == 90000 || num == 90008)
|
|
{
|
|
stop_sequence(TRUE);
|
|
integer index = llListFindList(SEQUENCE_DATA_NAMES, [msg]);
|
|
if (index != -1)
|
|
{
|
|
start_sequence(index);
|
|
run_sequence();
|
|
}
|
|
}
|
|
else if (num == 90205)
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", id);
|
|
playsounds = !playsounds;
|
|
if (playsounds)
|
|
{
|
|
llSay(0, "Sounds ON");
|
|
}
|
|
else
|
|
{
|
|
llSay(0, "Sounds OFF");
|
|
llStopSound();
|
|
}
|
|
}
|
|
else if (num == SEQUENCE_LINKNUMBER)
|
|
{
|
|
stop_sequence(TRUE);
|
|
list data = llParseStringKeepNulls(id, ["|"], []);
|
|
CONTROLLER = (key)llList2String(data, 0);
|
|
CONTROLLED = (key)llList2String(data, -1);
|
|
integer index = llListFindList(SEQUENCE_DATA_NAMES, [msg]);
|
|
if (index != -1)
|
|
{
|
|
start_sequence(index);
|
|
if (llListFindList(CURRENT_SEQUENCE_ACTIONS, ["WAIT"]) != -1 && llListFindList(CURRENT_SEQUENCE_ACTIONS, ["PLAY"]) != -1)
|
|
{
|
|
sequence_control();
|
|
}
|
|
else
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", id);
|
|
}
|
|
run_sequence();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
listen(integer listen_channel, string name, key id, string msg)
|
|
{
|
|
if (msg == "▮▮")
|
|
{
|
|
sequence_running = FALSE;
|
|
llSetTimerEvent(0);
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Paused!");
|
|
}
|
|
else if (msg == "▶")
|
|
{
|
|
sequence_running = TRUE;
|
|
SEQUENCE_POINTER++;
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Resumed!");
|
|
run_sequence();
|
|
}
|
|
else if (msg == "▶▶")
|
|
{
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
else if (msg == "◀◀")
|
|
{
|
|
integer count_waits;
|
|
while (SEQUENCE_POINTER > -1 && count_waits < 2)
|
|
{
|
|
SEQUENCE_POINTER--;
|
|
if (llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER) == "WAIT")
|
|
{
|
|
count_waits++;
|
|
}
|
|
}
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
else if (msg == "[BACK]")
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", (string)id + "|" + (string)CONTROLLED);
|
|
return;
|
|
}
|
|
sequence_control();
|
|
}
|
|
|
|
timer()
|
|
{
|
|
llSetTimerEvent(0);
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
|
|
on_rez(integer start)
|
|
{
|
|
playsounds = TRUE;
|
|
}
|
|
|
|
changed(integer change)
|
|
{
|
|
/*
|
|
if (change & CHANGED_LINK)
|
|
{
|
|
}
|
|
*/
|
|
if (change & CHANGED_INVENTORY)
|
|
{
|
|
if (llGetInventoryKey(notecard_name) != notecard_key || get_number_of_scripts() != llGetListLength(SITTERS))
|
|
{
|
|
llResetScript();
|
|
}
|
|
}
|
|
}
|
|
}
|