The new versioning scheme uses a letter instead of the dash. The letter is a p for a work-in-progress/pre-release version, or an r for a release version. For example: 2.2p04 - work in progress for version 2.2r04 2.2r04 - release version (2.2-04 with the previous scheme) The two digit number will be increasing even for minor changes. The last minor changes indicator is dropped.
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)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|