lsl RLV Scripting

Noodles

Queen of Ramen
Sep 20, 2018
119
Illinois
SL Rez
2006
Joined SLU
04-28-2010
SLU Posts
6947
#1
So, I'm playing around with making an RLV script, it's pretty basic, it's just a folder changer. the result will basically be a HUD with some interface for "up and down" to cycle through a set of prebuilt folders, attaching and detaching whatever is in them.

I think I've managed to wrap my head around how RLV works with the @ commands, but I'm having trouble getting started. Basically, there doesn't seem to be any sort of response. I built a listerner HUD for testing if commands are passing through and when I touch an object with

llRegionSayTo(targetUUID, -1812221819, (string)targetUUID+",@getinvworn:Folder=2225");

I see the command come in. But I don't see any response on 2225, or any channel. i have RLV enabled on my viewer but I suspect maybe I need to do something to establish permissions to use RLV? I tried setting the relay to Auto accept and still didn't see any response.

On a second question, I didn't see anything here LSL Protocol/RestrainedLoveAPI - Second Life Wiki about how to scan for avatars with RLV enabled to target a particular person. The ultimate idea is that Person A can use the HUD on Person B. Also, maybe I'm going about this wrong but with a relay would person B need to wear anything else to capture the commands given from Person A?
 

Soen Eber

Vatican mole
VVO Supporter 🍦🎈👾❤
Sep 20, 2018
94
#2
The API left out something really basic that caught me as well. I forgot what it was, but try looking for some basic rlv scripts online and compare. I think the missing magic is in the call to the rlv channel, a missing component. The people on the builder's brewery group caught it right away, it's really simple.

Also, try posting your code, or a simplified version if possible.
 

Lori Claremont

Member
VVO Supporter 🍦🎈👾❤
Sep 20, 2018
33
San Bruno, CA
#3
So first of all, it you're wanting to send commands to the wearer of the HUD, then you want to use llOwnerSay("@getinvworn:Folder=2225").

If on the other hand, you want to be sending commands to other Avatars, they need to be wearing a Relay, and you need to follow the instructions here: LSL Protocol/Restrained Love Relay/Specification - Second Life Wiki
 

Noodles

Queen of Ramen
Sep 20, 2018
119
Illinois
SL Rez
2006
Joined SLU
04-28-2010
SLU Posts
6947
#4
So first of all, it you're wanting to send commands to the wearer of the HUD, then you want to use llOwnerSay("@getinvworn:Folder=2225").

If on the other hand, you want to be sending commands to other Avatars, they need to be wearing a Relay, and you need to follow the instructions here: LSL Protocol/Restrained Love Relay/Specification - Second Life Wiki
Ultimately it needs to send to another avatar. I was sending to myself as a test, using the ID of whomever touched the test prim.
 

Innula Zenovka

Nasty Brit
VVO Supporter 🍦🎈👾❤
Sep 20, 2018
349
SLU Posts
18459
#5
Ultimately it needs to send to another avatar. I was sending to myself as a test, using the ID of whomever touched the test prim.

RLV viewers will accept RLV commands only if they come in the form llOwnerSay("@getinvworn=2225") or whatever. So you want to send a command to anyone other than yourself, you need to send it to that person's RLV relay, in the format the Relay expects, using channel -1812221819 . Their relay will parse the command and if it understand it, and if you're allowed to using that person's relay, then it will relay the command to the HUD's wearer in the form an llOwnerSay() message.

You can test RLV commands on yourself by touching the prim and having it call llOwnerSay, but I'd do all the developing using a relay.
 

Noodles

Queen of Ramen
Sep 20, 2018
119
Illinois
SL Rez
2006
Joined SLU
04-28-2010
SLU Posts
6947
#6
RLV viewers will accept RLV commands only if they come in the form llOwnerSay("@getinvworn=2225") or whatever. So you want to send a command to anyone other than yourself, you need to send it to that person's RLV relay, in the format the Relay expects, using channel -1812221819 . Their relay will parse the command and if it understand it, and if you're allowed to using that person's relay, then it will relay the command to the HUD's wearer in the form an llOwnerSay() message.

You can test RLV commands on yourself by touching the prim and having it call llOwnerSay, but I'd do all the developing using a relay.
Ok, so maybe this is something I'm not right on. Does OpenCollar have a relay built in? Or maybe it doesn't? Or maybe it's a different protocol.
 

Noodles

Queen of Ramen
Sep 20, 2018
119
Illinois
SL Rez
2006
Joined SLU
04-28-2010
SLU Posts
6947
#8
Ok, so I found an free script in my inventory that just browsed and attached from the RLV folder. I played with it a bit and cut out a bunch of stuff and have a basic working script. Only the Owner can use it on themselves at the moment.

This isn't 100%, I need to add a few things before it's super usable, mostly, I need to parse through the number of folders available, since I want it to be open ended, and I need to parse if any folder is currently worn as a "starting point".

Step two after all that is done is to make it usable by someone else. Which means figuring out how to scan the area for available relays (targets) and choose a target, then make the commands work through a relay, which may be as easy as changign the llOwnerSay bits to llRegionSayTo(targetUUID, -1812221819, "whatever,"+(string)targetUUID+",RLVcommand|RLVcommand|...");

Anyway, here is the code I have right now. It will cycle up and down a list in the RLV folder "ShapeCycler" with sub folders numbered 1,2,3... etc It currently force wears the contents of folder 1, but I intend to change that. It will wear and detatch objects in theory, but the original idea was just for shapes which sort of just replace each other anyway. I haven't actually tested it with attachments yet.

Code:
integer channel;
key targetkey;
string targetname;
integer currentfolder=1;
integer maxfolder=10;


default
{
    on_rez(integer int)
    {
        llResetScript();
    }
    attach(key id)
    {
        llResetScript();
    }
    state_entry()
    {
        channel=-(integer)llFrand(100000)-1000000;
        llListen(channel,"",llGetOwner(),"");
        llListen(-channel,"",NULL_KEY,"");
    }   
    touch_start(integer total_number)
    {
        llOwnerSay("@getinvworn:ShapeCycler="+(string)(-channel));
    }



    listen(integer chan, string name, key id, string message)
    {
        //llOwnerSay(message); // For Debugging
        if(chan==(-channel)&&message!="")
        {
            llSay(0, message);
            //parse the message to find currentfolder if any
            // But for now just wear folder 1....
            if (currentfolder == 1) {  llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder)+"=force"); }
            
            if(currentfolder > 1 && currentfolder < maxfolder)
                    { llDialog(llGetOwner(),"Choose action",["NextShape","PrevShape"],channel); }
                else if(currentfolder == 1)
                    { llDialog(llGetOwner(),"Choose action",["NextShape"," - "],channel); }
                else if(currentfolder == maxfolder)
                    { llDialog(llGetOwner(),"Choose action",[" - ","PrevShape"],channel); }
                else
                    { llDialog(llGetOwner(),"Error",[" - "," - "],channel); }
        }

        else if(chan==channel)
        {
            if(message=="NextShape")
                {
                llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder+1)+"=force");
                llOwnerSay("@detach:ShapeCycler/"+(string)(currentfolder)+"=force");
                currentfolder=currentfolder+1;
                }
            else if(message=="PrevShape")
                {
                llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder-1)+"=force");
                llOwnerSay("@detach:ShapeCycler/"+(string)(currentfolder)+"=force");
                if (currentfolder > 1) { currentfolder=currentfolder-1; }
                }

        }
        else
        {
            // Do Nothing
        }
    }
}
 

Noodles

Queen of Ramen
Sep 20, 2018
119
Illinois
SL Rez
2006
Joined SLU
04-28-2010
SLU Posts
6947
#9
I figured it out. The base script was resetting after the button scripts, so it would change channels and the buttons were using the old channel. I've upsated the scripts below.

Folder Structure is

#RLV
|
---ShapeCycler
|
--- 1
|
--- 2
|
--- 3
|
--- 4
|
--- 5

It should, in theory go on indefinitely, but I have not tested any limit beyond 11. I will say it works with leading zeros, but it does some funky loop stuff for some reason, like it went down 04, 03, 02, 11, 10, 09, 08, in a loop. I may look into that, maybe.

My next concern is making a separate controller HUD that just issues commands, but I need to set up some menu based handshaking (Scan for targets, get responses, ask who to target, prompt user for permission, etc, pass the private channel back).

Also I may look into adding a few other features, locking or a timer based auto change.


Ok, so, I feel like this should be straight forward.

I have a decent working basic script, better than the last one, which I may delete just for the sake of less confusion.

Here is the basic script (below). It detects if the user is wearing something already and starts there, if not, it starts in slot 1. It wears the new folder and detatches the previous folder, leaving anything else alone. Put it in a prim and when you touch it, you get a menu to pick the next shape or the previous shape, except when at the min/max.

I want to turn this into a HUD, because menus are kind of ugly. Maybe it could be both. Whatever the case, the script drops the random channel into its description. I created two child prims, linked them all up and they will pull the proper channel from the root prim. It will llOwnerSay the correct channel both on rez and touch so I know that part is working. The buttons are SUPPOSED to say on the proper channel, "NextShape" and "PrevShape" which are the two commands to toggle. Except nothing happens. I suspect there is some sort of UUID issue here, maybe, like it sees the commands but it's not seeing a proper UUID on the listener. Except It's all still Owner touching Owned object, so I don't know what the issue would be.

I've put the script for the buttons below as well.


Code:
integer channel;
key targetkey;
string targetname;
integer currentfolder=1;
integer maxfolder=10;



default
{
    on_rez(integer int)
    {
        llResetScript();
    }
    attach(key id)
    {
        llResetScript();
    }
    state_entry()
    {
        channel=-(integer)llFrand(100000)-1000000;
        llListen(channel,"",llGetOwner(),"");
        llListen(-channel,"",NULL_KEY,"");
        llSetObjectDesc((string)channel);
    }  
    touch_start(integer total_number)
    {
        llOwnerSay("@getinvworn:ShapeCycler="+(string)(-channel));
    }



    listen(integer chan, string name, key id, string message)
    {
        //llOwnerSay(message); // For Debugging
        if(chan==(-channel)&&message!="")
        {
           
            //llSay(0, message);
            list folderlist = llParseString2List(message,[","],[""]);
            maxfolder = llGetListLength(folderlist) - 1;
           
            // See what if anything is work currently
            integer i;
            do {
                string tmp = llList2String(folderlist, i);
                if (llGetSubString(tmp, -2, -1) == "30")
                    {currentfolder = (integer) llGetSubString(tmp, 0, -4); }
                }
            while(++i <= maxfolder);
           
            //parse the message to find currentfolder if any
            // But for now just wear folder 1....
            if (currentfolder == 1) {  llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder)+"=force"); }
           
            if(currentfolder > 1 && currentfolder < maxfolder)
                    { llDialog(llGetOwner(),"Choose action",["NextShape","PrevShape"],channel); }
                else if(currentfolder == 1)
                    { llDialog(llGetOwner(),"Choose action",["NextShape"," - "],channel); }
                else if(currentfolder == maxfolder)
                    { llDialog(llGetOwner(),"Choose action",[" - ","PrevShape"],channel); }
                else
                    { llDialog(llGetOwner(),"Error",[" - "," - "],channel); }
        }

        else if(chan==channel)
        {
            if(message=="NextShape" && currentfolder < maxfolder)
                {
                llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder+1)+"=force");
                llOwnerSay("@detach:ShapeCycler/"+(string)(currentfolder)+"=force");
                currentfolder=currentfolder+1;
                }
            else if(message=="PrevShape" && currentfolder > 1)
                {
                    llOwnerSay("@attach:ShapeCycler/"+(string)(currentfolder-1)+"=force");
                    llOwnerSay("@detach:ShapeCycler/"+(string)(currentfolder)+"=force");
                    currentfolder=currentfolder-1;
                }

        }
        else
        {
            // Do Nothing
        }
    }
}
Button Code

Code:
integer channel=0;

default
{
    state_entry()
    {

    }

    touch_start(integer total_number)
    {
        channel=(integer)llList2String(llGetLinkPrimitiveParams(LINK_ROOT, [ PRIM_DESC ]), 0);
        llSay(channel,"NextShape");
    }
}
 
Last edited: