Initial Upload

This commit is contained in:
2025-09-27 10:48:07 +01:00
commit 48d171ca34
11 changed files with 1281 additions and 0 deletions

297
Throne/MenuGen.lsl Normal file
View File

@ -0,0 +1,297 @@
// ********************************************************************
//
// Menu Display Script
//
// Menu command format
// string = menuidentifier | display navigate? TRUE/FALSE | menuMaintitle~subtitle1~subtitle2~subtitle3 | button1~button2~button3 {| fixedbutton1~fixedbutton2~fixedbutton3 optional}
// key = menuuser key
//
// Return is in the format
// "menuidentifier | item"
//
// menusDescription [menuchannel, key, menu & parent, return link, nav?, titles, buttons, fixed buttons]
// menusActive [menuchannel, menuhandle, time, page]
//
// by SimonT Quinnell
//
// CHANGES
// 2010/10/14 - Timeout message now gets sent to the prim that called the menu, not LINK_THIS. Also includes menuidentifier
// 2010/11/29 - Fixed Bug in RemoveUser function. Thanks for Virtouse Lilienthal for pointing it out.
// 2010/11/29 - Tidied up a little and removed functions NewMenu and RemoveUser that are only called once
// 2014/04/28 - Clarified licence
//
// NOTE: This script is licenced using the Creative Commons Attribution-Share Alike 3.0 license
//
// ********************************************************************
// ********************************************************************
// CONSTANTS
// ********************************************************************
// Link Commands
integer LINK_MENU_DISPLAY = 300;
integer LINK_MENU_CLOSE = 310;
integer LINK_MENU_RETURN = 320;
integer LINK_MENU_TIMEOUT = 330;
// Main Menu Details
string BACK = "<<";
string FOWARD = ">>";
list MENU_NAVIGATE_BUTTONS = [ " ", "Back", "Exit"];
float MENU_TIMEOUT_CHECK = 10.0;
integer MENU_TIMEOUT = 120000000;
integer MAX_TEXT = 510;
integer STRIDE_DESCRIPTION = 8;
integer STRIDE_ACTIVE = 4;
integer DEBUG = FALSE;
// ********************************************************************
// Variables
// ********************************************************************
list menusDescription;
list menusActive;
// ********************************************************************
// Functions - General
// ********************************************************************
debug(string debug)
{
if (DEBUG) llSay(DEBUG_CHANNEL,"DEBUG:"+llGetScriptName()+":"+debug+" : Free("+(string)llGetFreeMemory()+")");
}
integer string2Bool (string test)
{
if (test == "TRUE") return TRUE;
else return FALSE;
}
// ********************************************************************
// Functions - Menu Helpers
// ********************************************************************
integer NewChannel()
{ // generates unique channel number
integer channel;
do channel = -(llRound(llFrand(999999)) + 99999);
while (~llListFindList(menusDescription, [channel]));
return channel;
}
string CheckTitleLength(string title)
{
if (llStringLength(title) > MAX_TEXT) title = llGetSubString(title, 0, MAX_TEXT-1);
return title;
}
list FillMenu(list buttons)
{ //adds empty buttons until the list length is multiple of 3, to max of 12
integer i;
list listButtons;
for(i=0;i<llGetListLength(buttons);i++)
{
string name = llList2String(buttons,i);
if (llStringLength(name) > 24) name = llGetSubString(name, 0, 23);
listButtons = listButtons + [name];
}
while (llGetListLength(listButtons) != 3 && llGetListLength(listButtons) != 6 && llGetListLength(listButtons) != 9 && llGetListLength(listButtons) < 12)
{
listButtons = listButtons + [" "];
}
buttons = llList2List(listButtons, 9, 11);
buttons = buttons + llList2List(listButtons, 6, 8);
buttons = buttons + llList2List(listButtons, 3, 5);
buttons = buttons + llList2List(listButtons, 0, 2);
return buttons;
}
RemoveMenu(integer channel, integer echo)
{
integer index = llListFindList(menusDescription, [channel]);
if (index != -1)
{
key menuId = llList2Key(menusDescription, index+1);
string menuDetails = llList2String(menusDescription, index+2);
integer menuLink = llList2Integer(menusDescription, index+3);
menusDescription = llDeleteSubList(menusDescription, index, index + STRIDE_DESCRIPTION - 1);
RemoveListen(channel);
if (echo) llMessageLinked(menuLink, LINK_MENU_TIMEOUT, menuDetails, menuId);
}
}
RemoveListen(integer channel)
{
integer index = llListFindList(menusActive, [channel]);
if (index != -1)
{
llListenRemove(llList2Integer(menusActive, index + 1));
menusActive = llDeleteSubList(menusActive, index, index + STRIDE_ACTIVE - 1);
}
}
// ********************************************************************
// Functions - Menu Main
// ********************************************************************
DisplayMenu(key id, integer channel, integer page)
{
string menuTitle;
list menuSubTitles;
list menuButtonsAll;
list menuButtons;
list menuNavigateButtons;
list menuFixedButtons;
integer max = 12;
// Populate values
integer index = llListFindList(menusDescription, [channel]);
menuButtonsAll = llParseString2List(llList2String(menusDescription, index+6), ["~"], []);
if (llList2String(menusDescription, index+7) != "") menuFixedButtons = llParseString2List(llList2String(menusDescription, index+7), ["~"], []);
// Set up the menu buttons
if (llList2Integer(menusDescription, index+4)) menuNavigateButtons= MENU_NAVIGATE_BUTTONS;
else if (llGetListLength(menuButtonsAll) > (max-llGetListLength(menuFixedButtons))) menuNavigateButtons = [" ", " ", " "];
// FIXME: add sanity check for menu page
max = max - llGetListLength(menuFixedButtons) - llGetListLength(menuNavigateButtons);
integer start = page*max;
integer stop = (page+1)*max - 1;
menuButtons = FillMenu(menuFixedButtons + llList2List(menuButtonsAll, start, stop));
// Generate the title
list tempTitle = llParseString2List(llList2String(menusDescription, index+5), ["~"], []);
menuTitle = llList2String(tempTitle,0);
if (llGetListLength(tempTitle) > 1) menuSubTitles = llList2List(tempTitle, 1, -1);
if (llGetListLength(menuSubTitles) > 0)
{
integer i;
for(i=start;i<(stop+1);++i)
{
if (llList2String(menuSubTitles, i) != "") menuTitle += "\n"+llList2String(menuSubTitles, i);
}
}
menuTitle = CheckTitleLength(menuTitle);
// Add navigate buttons if necessary
if (page > 0) menuNavigateButtons = llListReplaceList(menuNavigateButtons, [BACK], 0, 0);
if (llGetListLength(menuButtonsAll) > (page+1)*max) menuNavigateButtons = llListReplaceList(menuNavigateButtons, [FOWARD], 2, 2);
// Set up listen and add the row details
integer menuHandle = llListen(channel, "", id, "");
menusActive = [channel, menuHandle, llGetUnixTime(), page] + menusActive;
//llSetTimerEvent(MENU_TIMEOUT_CHECK);
// Display menu
llDialog(id, menuTitle, menuNavigateButtons + menuButtons, channel);
}
// ********************************************************************
// Event Handlers
// ********************************************************************
default
{
listen(integer channel, string name, key id, string message)
{
if (message == BACK)
{
integer index = llListFindList(menusActive, [channel]);
integer page = llList2Integer(menusActive, index+3)-1;
RemoveListen(channel);
DisplayMenu(id, channel, page);
}
else if (message == FOWARD)
{
integer index = llListFindList(menusActive, [channel]);
integer page = llList2Integer(menusActive, index+3)+1;
RemoveListen(channel);
DisplayMenu(id, channel, page);
}
else if (message == " ")
{
integer index = llListFindList(menusActive, [channel]);
integer page = llList2Integer(menusActive, index+3);
RemoveListen(channel);
DisplayMenu(id, channel, page);
}
else
{
integer index = llListFindList(menusDescription, [channel]);
llMessageLinked(llList2Integer(menusDescription, index+3), LINK_MENU_RETURN, llList2String(menusDescription, index+2)+"|"+message, id);
RemoveMenu(channel, FALSE);
}
}
link_message(integer senderNum, integer num, string message, key id)
{
if (num == LINK_MENU_DISPLAY)
{ // Setup New Menu
list temp = llParseString2List(message, ["|"], []);
integer channel = NewChannel();
if (llGetListLength(temp) > 2)
{
menusDescription = [channel, id, llList2String(temp, 0), senderNum, string2Bool(llList2String(temp, 1)), llList2String(temp, 2), llList2String(temp, 3), llList2String(temp, 4)] + menusDescription;
DisplayMenu(id, channel, 0);
}
else llSay (DEBUG_CHANNEL, "ERROR in "+llGetScriptName()+": Dialog Script. Incorrect menu format");
}
else if (num == LINK_MENU_CLOSE)
{ // Will remove all menus that have the user id.
integer index_id = llListFindList(menusDescription, [id]);
while (~index_id)
{
integer channel = llList2Integer(menusDescription, index_id-1);
RemoveMenu(channel, FALSE);
// Check for another menu by same user
index_id = llListFindList(menusDescription, [id]);
}
}
}
timer()
{ // Check through timers and close if necessary
integer i;
list toRemove;
integer currentTime = llGetUnixTime();
integer length = llGetListLength(menusActive);
for(i=0;i<length;i+=STRIDE_ACTIVE)
{
if (currentTime - llList2Integer(menusActive, i+2) > MENU_TIMEOUT) toRemove = [llList2Integer(menusActive, i)] + toRemove;
}
length = llGetListLength(toRemove);
if (length > 0)
{
for(i=0;i<length;i++)
{
RemoveMenu(llList2Integer(toRemove, i), TRUE);
}
}
}
}

188
Throne/ThroneDefault.lsl Normal file
View File

@ -0,0 +1,188 @@
string current_sitting_anim = "throneSitChilled";
vector current_sitting_offset = <-0.055, 0.2, 0.125>;
vector init_pos;
rotation default_rot = <0.000000, 0.000000, -0.707107, 0.707107>;
integer can_ex = 1;
float ex_timer = 20;
float ex_frequency = 0.3; // Frequency % of EX to add RNG
// Link Commands
integer LINK_MENU_DISPLAY = 300;
integer LINK_MENU_RETURN = 320;
integer LINK_MENU_TIMEOUT = 330;
DisplayMenu(key id) {
string menuDescripter = "thronesitmenu";
string menuNavigate = "FALSE";
string menuText = "Select a sitting animation";
string menuButtons = "Sit~Chilled~Crossed~Slumped~Sleepy~Cozy"; // The buttons, each button separated by a '~'.
llMessageLinked(LINK_THIS, LINK_MENU_DISPLAY, menuDescripter+"|"+menuNavigate+"|"+menuText+"|"+ menuButtons, id);
}
//Sets / Updates the sit target moving the avatar on it if necessary.
UpdateSitTarget(vector pos, rotation rot)
{//Using this while the object is moving may give unpredictable results.
llSitTarget(pos, rot);//Set the sit target
key user = llAvatarOnSitTarget();
if(user)//true if there is a user seated on the sittarget, if so update their position
{
vector size = llGetAgentSize(user);
if(size)//This tests to make sure the user really exists.
{
//We need to make the position and rotation local to the current prim
rotation localrot = ZERO_ROTATION;
vector localpos = ZERO_VECTOR;
if(llGetLinkNumber() > 1)//only need the local rot if it's not the root.
{
localrot = llGetLocalRot();
localpos = llGetLocalPos();
}
integer linkNum = llGetNumberOfPrims();
do
{
if(user == llGetLinkKey( linkNum ))//just checking to make sure the index is valid.
{
//<0.008906, -0.049831, 0.088967> are the coefficients for a parabolic curve that best fits real avatars. It is not a perfect fit.
float fAdjust = ((((0.008906 * size.z) + -0.049831) * size.z) + 0.088967) * size.z;
llSetLinkPrimitiveParamsFast(linkNum,
[PRIM_POS_LOCAL, (pos + <0.0, 0.0, 0.4> - (llRot2Up(rot) * fAdjust)) * localrot + localpos,
PRIM_ROT_LOCAL, rot * localrot]);
jump end;//cheaper but a tad slower then return
}
}while( --linkNum );
}
else
{//It is rare that the sit target will bork but it does happen, this can help to fix it.
llUnSit(user);
}
}
@end;
}//Written by Strife Onizuka, size adjustment and improvements provided by Talarus Luan
default
{
state_entry()
{
llSitTarget(ZERO_VECTOR,ZERO_ROTATION);
vector default_seat = llGetGeometricCenter() - current_sitting_offset;
init_pos = llGetGeometricCenter();
llSitTarget(default_seat, default_rot);
}
on_rez(integer start_param) {
llResetScript();
//llOwnerSay("Reset"); // for debugging
}
changed(integer change) {
//llOwnerSay("Changes"); // for debugging
if (change & CHANGED_LINK) {
//llOwnerSay("Sat"); // for debugging
key av = llAvatarOnSitTarget();
integer perm = llGetPermissions();
if (av) {
if(PERMISSION_TRIGGER_ANIMATION & perm) {
llStopAnimation("sit");
llStartAnimation(current_sitting_anim);
llSetTimerEvent(ex_timer);
} else {
llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
}
DisplayMenu(av);
} else {
if(PERMISSION_TRIGGER_ANIMATION & perm) {
llStopAnimation(current_sitting_anim);
}
llResetScript();
}
}
}
run_time_permissions(integer perm) {
key av = llAvatarOnSitTarget();
if (av) {
if(PERMISSION_TRIGGER_ANIMATION & perm) {
llStopAnimation("sit");
llStartAnimation(current_sitting_anim);
llSetTimerEvent(ex_timer);
}
}
}
timer() {
key av = llAvatarOnSitTarget();
if (av) {
integer perm = llGetPermissions();
if(PERMISSION_TRIGGER_ANIMATION & perm) {
if (can_ex == 1) {
float roll_dem_bones = llFrand(1.0);
if (roll_dem_bones <= ex_frequency) {
llStartAnimation(current_sitting_anim + "Ex");
}
}
}
}
}
link_message(integer intSenderNum, integer num, string message, key id) {
if (num == LINK_MENU_RETURN) {
list returnMenu = llParseString2List(message, ["|"], []);
string menuDescriptor = llList2String(returnMenu,0);
if (menuDescriptor == "thronesitmenu") {
key av = llAvatarOnSitTarget();
if (av) {
string item = llList2String(returnMenu,1);
//llOwnerSay(item); // for debugging
string actual_current_sitting_anim = current_sitting_anim;
if (item == "Sit") {
current_sitting_anim = "sit";
current_sitting_offset = <0.05, 0.65, -0.15>;
can_ex = 0;
} else if (item == "Chilled") {
current_sitting_anim = "throneSitChilled";
current_sitting_offset = <-0.055, 0.2, 0.125>;
can_ex = 1;
} else if (item == "Crossed") {
current_sitting_anim = "throneSitCrossed";
current_sitting_offset = <0.01, 0.12, 0.125>;
can_ex = 1;
} else if (item == "Slumped") {
current_sitting_anim = "throneSitSlumped";
current_sitting_offset = <0.01, 0.12, 0.125>;
can_ex = 1;
} else if (item == "Sleepy") {
current_sitting_anim = "throneSitSleepy";
current_sitting_offset = <0.01, 0.12, 0.125>;
can_ex = 1;
} else if (item == "Cozy") {
current_sitting_anim = "throneSitCozy";
current_sitting_offset = <0.01, 0.12, 0.125>;
can_ex = 1;
}
integer perm = llGetPermissions();
if(PERMISSION_TRIGGER_ANIMATION & perm) {
llStopAnimation(actual_current_sitting_anim);
vector default_seat = init_pos - current_sitting_offset;
UpdateSitTarget(default_seat, default_rot);
//llSetLinkPrimitiveParamsFast(llGetNumberOfPrims(),[PRIM_POS_LOCAL,default_seat]);
llStartAnimation(current_sitting_anim);
}
DisplayMenu(av);
}
}
} else if (num == LINK_MENU_TIMEOUT) {
if (message == "thronesitmenu") {
key av = llAvatarOnSitTarget();
if (av) {
DisplayMenu(av);
}
}
}
}
}