Jump to content

[Help] Channels between multiple transmittors and receivers


MSTRPLN
 Share

You are about to reply to a thread that has been inactive for 2087 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello. I;ve thought of a way to demo rez objects in world.

Concept: A vendor on the wall with a demo button under it.
When "Demo" is clicked it will rez a sized down demo in front of it which wil die
with a timer, so it only rezzes temporarily. (the demo object is in the content along with the transmittor script)

 

Problem: It works but if i have 2 or more of the same inworld System A will delete system B's rezzed
object before it's timer has ran out, this is because it's on the same channel. I've tried multiple options to
make the channels unique ie.

 

integer rChannel = 0x80000000 | (integer) ( "0x" + (string) llGetOwner() );


// and


integer rChannel = (integer)(llFrand(-999999999.0) - 10000000.0);

But now 2 problems occur: 1. I get an error saying "Cannot use llRegionSay(); on channel 0. 2. The receiver doesn't work anymore.

 

Below my codes.

Transmittor:

string object = "[V] Demo"; // Name of object in inventory
vector relativePosOffset = <2.0, 0.0, 0.0>; // "Forward" and a little "above" this prim
vector relativeVel = <1.0, 0.0, 0.0>; // Traveling in this prim's "forward" direction at 1m/s
rotation relativeRot = <0.0, 0.0, 1.0, 1.0>; // Rotated 90 degrees on the x-axis compared to this prim
integer startParam = 10;

// Channel
integer rChannel =-5001;
integer count;

default
{
     touch_start(integer tn)
    {
        // 1 minute
        llSetTimerEvent (60.0);
        llInstantMessage(llDetectedKey(0), "This is a demo! It will delete itself in 1 minute.");
        
        // Rezzes item
        vector myPos = llGetPos();
        rotation myRot = llGetRot();
 
        vector rezPos = myPos+relativePosOffset*myRot;
        vector rezVel = relativeVel*myRot;
        rotation rezRot = relativeRot*myRot;
 
        llRezAtRoot(object, rezPos, rezVel, rezRot, startParam);
    }
    on_rez(integer p) {
        llResetScript();   
    }

    timer ()
    {
        llOwnerSay("Sorry your demo is over.");
        llSetTimerEvent (0.0);
        llRegionSay(rChannel, "RezDemo");
    }
}

Receiver:

integer rChannel =-5001;
// Channel is the integer for reception (number mus the same as a transmission channel otherwise script will not work)

default
{
        state_entry()
        {
            llListen(rChannel, "", NULL_KEY, "");
        }
        
        listen(integer channel, string name, key id, string msg)
        {
                // Checks if same channel
            if (rChannel == channel) {  llDie();
            } else { llDie(); }
            llListenRemove(rChannel);//close listener
        }
}

What i would nee jhelp with exactly is:

 

- How to set a unique channel that the rezzer & rezzed object still listens to eachother but don't interfere with others.

- How to detect prim in it's inventory without the need to renaming to "[V] Demo".

- Send the message in the timer "Sorry your demo is over." to the person that started it so it doesn't spam the public channel. (if possible, cause llInstantMessage with DetectedKey(0) didn't work).

 

Optional/Additional: I would like to know (yes i've searched) if there is a way to detect when someone uses "Pay"
on right click > pay and play a sound or any other action.

Thanks in advance.
Sincerely, Chris.

Link to comment
Share on other sites

Let's just get the plumbing right first.

I'm assuming by "it only rezzes temporarily" you do not mean temp-on-rez but rather that your script is solely responsible for tidying up after your own "temporary" interval.

Don't mess with channels, but use llRegionSayTo() to direct chat to a specific object's key, identified in the rezzer's object_rez() event, or have the rezzed object only listen to its own rezzer, using OBJECT_REZZER_KEY from its own llGetObjectDetails, or both.

[Edit: For historical interest, in case you encounter older code, we used to do this by creating a random channel number in the rezzer and passing it to the rezzed object in the start_param of llRezAtRoot, so it can know which channel to listen on. That still works, too.]

For notifying the person who requested the demo, llInstantMessage should work, but of course you can't use llDetectedKey() except in the event where the demo was requested, so you'd need to save that in a global variable until time to notify them. Personally, though, I'd avoid llInstantMessage() because of its built-in delay, instead using llRegionSayTo() the avatar on channel 0.

Note, however, that the basic logic here is going to break if anybody touches the rezzer while an item is already rezzed. One way to avoid that is to put the rezzer into a state with no touch-related event handler.

I don't understand the question about detecting a prim in inventory. There's llGetInventoryName(INVENTORY_OBJECT, n) but not sure that's what you're asking about.

Link to comment
Share on other sites

You don't necessarily need to use different channels.  All you need is a way to address each rezzed instance uniquely.  You could do that in many ways, if you are imaginative.  One of my favorites is to pass a unique integer as the on_rez paramater when I rez a new object, and then use that integer as an identifier on any messages exchanged with the object.  So, if I have said:

integer Next_unique_integer = gLast_unique_integer +1;llRezAtRoot(My_object,llGetPos() + <0.0,0.0,0.5>,ZERO_VECTOR,ZERO_ROTATION,Next_unique_integer);gLast_unique_integer = Next_unique_integer;

that I can send any message to that particular instance in the form

llRegionSay(my_channel,(string)A_specific_integer + "~"+message);

and receive it with

listen (integer channel, string name,. key id, string message){    list temp = llParseString2List(message,["~"],[]);    if ((integer) llList2String(temp,0) == the_unique_integer_I_was_sent_on_rez)    {        // This message was meant for me    }    else    {        // This message was meant for a different rezzed instance    }}

I just need to keep track of what rezzed instances are out there and which one I want to send messages to.

There are loads of other ways to address this puzzle, though, so this is just one suggestion.

I'm not sure what the puzzle in your second question is.  After all, it's not all that hard to type the name of the object to be rezzed.  If your vendor will have more than one object in it, you don't have much other choice.

For your third puzzle, the solution is to save the targeted person's UUID and then send your message in the form

llRegionSayTo(UUID_goes_here,0,"Time's up, bozo.");

And for the last puzzle, your vendor must contain a money event, and that event is always triggered by someone clicking in a PAY box.  So, put your sound and thank you message in the money event.

 

 

 

Link to comment
Share on other sites

Thank you.  will look up and learn about what you both suggested.

With temporarily i meant that it will be rezzed for a limited time (for example 60 seconds) before the rezzed object destroys itself.

To make my 2nd question clear: The string "object" has to have a name that is the same as in the script.
I was wondering if i could use something like llGetInventory with a filter so it doesnt take the script but the object (just to be safe). This way i can just put a random object inside the sytsem and it won't give an debug error like "[V] Demo could not be found". 

Maybe that's possible with "llGetInventoryType" i'll have to look into that

I also need to create a safety feature so only 1 item cn be rezzed at the time which i forget & you mentioned.

 

Edit:

Im starting with one problem at a time, i tried the OBJECT_REZZER_KEY but i must be doing something wrong because A still removes B's rezzed object

// Script for texture changer receiverinteger rChannel =-5001;// Channel is the integer for reception (number mus the same as a transmission channel otherwise script will not work)integer Rezzer;default{        state_entry()        {            llListen(rChannel, "", NULL_KEY, "");            llScaleByFactor(0.3);            list Rezzer = llGetObjectDetails(llGetKey(), [OBJECT_REZZER_KEY]);        }                listen(integer channel, string name, key id, string msg)        {                // Checks if same channel            if (rChannel == channel) {                if (Rezzer = OBJECT_REZZER_KEY) {                    llDie();;                    } else {}                                } else { llDie(); }            llListenRemove(rChannel);//close listener        }}
Link to comment
Share on other sites

You're almost there.   Your problem is, I think, that llGetObjectDetails retuns a list, not a key, so you have to parse the list, using llList2Key,  to find out what the rezzer key is.   

That, of course, needs a new constant, kRezzer or something, and it needs reading in the on_rez event  since the object's uuid will change each time it's rezzed.   ETA  I would always sleep the script in the on_rez event for 0.25 seconds or so, before I do anything else, to give everything behind the scenes in the simulator time to catch up with itself, otherwise you risk not being able to read llGetObjectDetails(llGetKey(), [...]) properly, at least in my experience.

I don't really understand the logic of your listen event, which I think is over-complex for no good reason:

    listen(integer channel, string name, key id, string msg)    {        // Checks if same channel        if (rChannel == channel) {            if (id == kRezzer) { //if the message came from the rezzer
//note also id == kRezzer, not id = kRezzer -- we all do that until we get obsessive about checking it! llDie(); } else { //do something else if the message comes from an object other then rezzer //what, though, for heaven's sake? } } /* else { //it's never going to get this far, since you're listening only to rChannel llDie(); } */ //llListenRemove(rChannel);//close listener //I don't really understand what this is doing down here }

 

Link to comment
Share on other sites

Thank you, i've been experiencing with state so that once the item is rezzed it goes to state 2 and becomes unclickable to avoid multiple instaces and switched back to default state after the message to make the child die has been sent.

 

The logic well, I'm just trying to do my best to get it to work really, the reason behind the id = kRezzer instead of == is because == gave me an error and didnt with just one. Im going to try to understand all you said and try it out on a copy and see how far i get.

Link to comment
Share on other sites

The reason you didn't get a script error for if (rezzer = OBJECT_REZZER_KEY) is that, while it's pretty meaningless in context, it will compile because you're setting the value of an integer (rezzer, which you declared as an integer) to the value of an integer constant, OBJECT_REZZER_KEY (which is a more meaningful way of waying "32").

So I think you're saying the equivalent of if(32){ //do stuff}, which means that the script will always execute the instruction that folllows (in this case, llDie(), which is what you said it was doing), since if (integer) always evaluates as true, assuming the integer isn't 0.

ETA  You probably know this, but since you're experiementing with states, use the touch_end event to change states, not touch_start (otherwise you'll have difficulties with touch_start events in the state into which you move.   Also, don't forget that changing states closes all listeners, so they need opening again in state_entry of the new state if you want them to work in that state.

Link to comment
Share on other sites

Right thank you once again, i've read that the OBJECT_REZZER_KEY was equal to 32 on the wiki yes.

 

I'm familiar with the touch_end (saw it somewhere on the forum while searching) to switch states but i didn't know that listeners wouldnt work anymore, i'll keep that in mind

Link to comment
Share on other sites

Alright i've read about "llList2Key" Which didn't give much information on how to use it and more other things.
It just makes it look more complicated than it really is i guess.
Not sure if i would have to use "while" since most if not all examples i've seen using "llList2Key" were in the while parts.

I feel that i'm close but not quite there yet, something is wrong and i don't know what:

// Script for texture changer receiverinteger rChannel =-5001;integer Rezzer;integer kRezzer;// Channel is the integer for reception (number mus the same as a transmission channel otherwise script will not work)default{        state_entry()        {            llListen(rChannel, "", NULL_KEY, "");            integer i;            list Rezzer = llGetObjectDetails(llGetKey(), [OBJECT_REZZER_KEY]);            key kRezzer = llList2Key(Rezzer,i);        }                listen(integer channel, string name, key id, string msg)        {                // Checks if same channel            if (rChannel == channel) {                if (id == kRezzer) {                    //if the message came from the rezzer                     llDie();                }                else {                    // Not from the rezzer                    llWhisper(0, "Whut?");                }            }        }}

(20, 33) : ERROR : Type Mismatch That's right here there the red star is: if (id == kRezzer*) {
This is the script of the receiver (the prim getting rezzed)

Somehow i thought changing it to: key id = llList2Key(Rezzer,kRezzer) But that gave the same error, not sure if it works that way llList2Key(fromlist,tokey)


for the transmitting script:

//Rez an object on touch, with relative position, rotation, and velocity all described in the rezzing prim's coordinate system.string object = "[V] Demo"; // Name of object in inventoryvector relativePosOffset = <2.0, 0.0, 0.0>; // "Forward" and a little "above" this primvector relativeVel = <1.0, 0.0, 0.0>; // Traveling in this prim's "forward" direction at 1m/srotation relativeRot = <0.0, 0.0, 1.0, 1.0>; // Rotated 90 degrees on the x-axis compared to this priminteger startParam = 10;// Channelinteger rChannel =-5001;integer count;default{    state_entry()    {        llOwnerSay("Ready");    }    touch_end(integer total_number)    {        llInstantMessage(llDetectedKey(0), "This is a demo! It will delete itself in 10 seconds.");        state two;    }}state two{    state_entry()    {        // Rezzes item        vector myPos = llGetPos();        rotation myRot = llGetRot();         vector rezPos = myPos+relativePosOffset*myRot;        vector rezVel = relativeVel*myRot;        rotation rezRot = relativeRot*myRot;         llRezAtRoot(object, rezPos, rezVel, rezRot, startParam);                llSetTimerEvent (10.0);    }        timer ()    {        llWhisper(0, "Sorry your demo is over.");        llSetTimerEvent (0.0);        llRegionSay(rChannel, "RezDemo");        state default;    }}

I've got the states to work so it's unclickable during rezzing.

Link to comment
Share on other sites

That first script is a little muddy.  If you want to open a channel to listen to the rezzzer, all you need is

 

on_rez(integer startup){    llListen(startup,"","","");}listen(integer channel, string name, key id, string message){    if (message == "RezDemo")    {       lDie();    }}

 

Send a random channel number as the startParam in your rezzer script.

 

You could go through the business of using OBJECT_REZZER_KEY if you want, but you still have to open a channel.  It seems a lot easier to randomize the channel than to go through the trouble of using a constant channel and checking the rezzer's key, although this will work even if you don't randomize the channel.

Link to comment
Share on other sites

I don't understand the problem.  A unique channel is a unique channel.  In your rezzer....

gChan = -1 * (integer)llFrand(1000000.0) - 345;  // gChan is a global integerllRezAtRoot("object",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,gChan);

And you send the message in your timer event on that channel.  Only your rezzed object hears it.

 

 

 

Link to comment
Share on other sites

You need to know the uuid of the object that rezzed the item containing the script.

You get this from llGetObjectDetails(llGetKey(),[OBJECT_REZZER_KEY]);

The function llGetObjectDetails returns a list, depending on what kind of details, and how many,  about the object you've asked for.   If you look at the wiki article on llGetObjectDetails you'll see it can be used to obtain all sorts of information.   In this case, there's only one element in the list, the uuid of the rezzer.   So you extract it from the list thus:

kRezzer = llList2Key(llGetObjectDetails(llGetKey(),[OBJECT_REZZER_KEY]),0);

(that's assuming that you've already definded kRezzer somewhere).  

Once you've done that, you can check in the listen event if (id == kRezzer) -- that is, if the message is from the object that rezzed me.

 

Link to comment
Share on other sites

"Security" isn't really what you need here.  It isn;t as if someone is going to be hacking into your system to do something nasty.  All you are concerned about is being sure that the rezzer speaks to one and only one rezzed object.  You can do that by simply creating a unique throwaway channel that both of them know.  The extra bit of knowledge about the rezzer's UUID is nice, but doesn't really give you any more certainty than you need here.

"Hello, Bob!  I know it's you because nobody else calls me on this number.  Now, prove that you are really Bob."  Um ...... :smileywink:

Link to comment
Share on other sites

  • 2 weeks later...

All these channels and object keys and listeners seems a bit 'we love lag' sledgehammer vs peanut to me...

 

Have the vendor resz a demo object, inside the  demo object is a script with a timer and a die command... so on rez event, time starts... on timer event, poof self destructs.

 

Job done simple, no need to stop vendor a killing vendor b's demos, the demos SELF delete.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2087 days.

Please take a moment to consider if this thread is worth bumping.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...