Jump to content

Non-linked light on collision timer issue


Tattooshop
 Share

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

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

Recommended Posts

Hello! I make a couple of scripts - sender detector and listener lamp script. when you go through the phantom wall, a collision detector is triggered and a message is transmitted through the channel to turn on the light. The listener turns on the light and off it after a while. But if you go through the wall very fast for several times in a row, the timer adds up and the light glows for a longer time. Is it possible to make the detector not work if the light is already on? As timer i use llSleep().  Thanks!

Link to comment
Share on other sites

If you use llSleep() then nothing else can happen during that sleep period. A better approach is to use a timer and set it to perhaps 5 seconds.

For what you are asking, the fix is quite easy. In the script that gets the message, create a global integer called light. When you turn the light on, set it to 1, when you turn the light off, set it to 0.

 

The test to make when you get the message to turn the light on is to see if the value of this variable is 0, and if so, turn the light on, set the value to now be 1, and set a timer event to go in 5 seconds.

When the timer event occurs, set the timer event to 0.0. turn off the light, and set the variable to 0, so that the next message turns it back on.

integer lightOn = 0;

/// stuff here for state_entry and so on

if ( msg == "light on")
{
    if ( light == 0)
    {
    // turn light on
    lightOn = 1;
    llSetTimerEvent(5.0);
    }

}

timer()
{
    llSetTimerEvent(0.0)
    // turn light off
    lightOn = 0;

}

Warning, untested snippet,

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

Yes it's possible - but without seeing the actual code you've written, we can only guess at what the problem might be and how to correct it. If you are able, please post a sample of the code.

If I were to hazard a guess, it sounds like every time the trigger is sent to the lamp's listener, it basically resets the countdown and thus appears to extend the duration of the lamp's glow time. Depending on the application, using llSleep may or may not be ideal. llSleep forcibly suspends the script entirely for the duration, which can lead to queuing up events that occur while it's sleeping. This could be another reason why the light duration is extended: it gets the first signal and sleeps, but if more get queued up, they immediately get processed as soon as the initial sleep expires.

Generally speaking, I would suggest you use a timer event instead of llSleep. Additionally, make use of a global variable to track the state of the light. When triggered, first check if the light is already on and of so, do nothing. If on the other hand the light is currently off, then set it on, update the global variable and start a timer. When the timer pops, turn the light off, update the global variable, and stop the timer in the timer event.

Edit: ah, Profaitchikenz beat me to it. :)

Edited by Fenix Eldritch
  • Thanks 1
Link to comment
Share on other sites

1 minute ago, Fenix Eldritch said:

This could be another reason why the light duration is extended: it gets the first signal and sleeps, but if more get queued up, they immediately get processed as soon as the initial sleep expires.

This cropped up in another thread, I think it was decided that events arriving when a script was sleeping just got quietly dropped?

  • Thanks 1
Link to comment
Share on other sites

@Profaitchikenz Haiku@Fenix Eldritch Hello! Thank you very much! Here my codes:

 

// Detector script

default
{
    state_entry()
    {
        llVolumeDetect(TRUE); 
        /* If detect is TRUE, VolumeDetect is enabled, physical object and avatars can pass through the object. */
    }

    collision_start(integer num)
    {
        llSay(-1234567, "light_on"); /* And here you are telling anyone listening on channel -1234567 on command. */
    }
}
// Light script

vector LIGHT_COLOR = < 1.0, 1.0, 1.0 > ; // Light color lsl RGB
integer LIGHT_PRIM = 0; // Light prim number or LINK_THIS
integer LIGHT_FACE = ALL_SIDES; // Light face number or ALL_SIDES

default
{
    state_entry()
    {
        llListen(-1234567, "", "", ""); /* Listen to anybody saying anything on channel -1234567 */
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        if (msg == "light_on") /* That is, if the message was light_on */ 
        { 
        // On
        llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
            [PRIM_GLOW, LIGHT_FACE, 1,
                PRIM_POINT_LIGHT, TRUE,
                LIGHT_COLOR 
                , 1.0 
                , 10.0
                , 0.2 
            ]);
        llSleep(5); // Off Timer

        // Off
        llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
            [PRIM_GLOW, ALL_SIDES, FALSE, PRIM_POINT_LIGHT, FALSE,
                ZERO_VECTOR 
                , 0.0 
                , 0.0 
                , 0 
            ]);               
        }
    }
}

 

Link to comment
Share on other sites

16 minutes ago, Tattooshop said:

 

// Light script

vector LIGHT_COLOR = < 1.0, 1.0, 1.0 > ; // Light color lsl RGB
integer LIGHT_PRIM = 0; // Light prim number or LINK_THIS
integer LIGHT_FACE = ALL_SIDES; // Light face number or ALL_SIDES

integer lightOn = 0;
  
default
{
    state_entry()
    {
        llListen(-1234567, "", "", ""); /* Listen to anybody saying anything on channel -1234567 */
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        if (msg == "light_on") /* That is, if the message was light_on */ 
        { 
            if( lightOn == 0)
            {
            // On
                llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
                [PRIM_GLOW, LIGHT_FACE, 1,
                    PRIM_POINT_LIGHT, TRUE,
                    LIGHT_COLOR 
                    , 1.0 
                    , 10.0
                    , 0.2 
                ]);
                lightOn = 1;
                // llSleep(5); // Off Timer
                llSetTimerEvent(5.0);
             }  
        }
    }
  timer()
  {
      llSetTimerEvent(0.0); // stop any repeating
        llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
            [PRIM_GLOW, ALL_SIDES, FALSE, PRIM_POINT_LIGHT, FALSE,
                ZERO_VECTOR 
                , 0.0 
                , 0.0 
                , 0 
            ]);    
       lightOn = 0;
    }
}

Try that, you might have to check brace-matching, I didn't get a chance to try it inworld

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Fenix Eldritch said:

llSleep forcibly suspends the script entirely for the duration, which can lead to queuing up events that occur while it's sleeping.

Now I've seen the OP's code, I can see no other reason for the extension of the light other than chat messages passed to a script that is sleeping DO get queued and the waking script then DOES get the events that occurred whilst it was supposedly unresponsive: I think this needs further testing. I'll bash a few prims together tomorrow and report back.

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

Huh... this is interesting. I slapped together a quick demo and tried a combination of chat commands and touches.

default
{
    touch_start(integer total_number)
    {
        llSay(-10, "test");
    }
}
default
{
    state_entry()
    {
        llListen(-10,"", "", "");
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        if (msg == "sleep")
        {
            llOwnerSay("sleep started");
            llSleep(10.0);
            llOwnerSay("sleep stopped");
        }
        
        if (msg == "test")
        {
            llOwnerSay("listen received ping");
        }
      
      	llOwnerSay("end of listen event");
    }

    touch_start(integer total_number)
    {
        llOwnerSay("Touched.");
    }
}

From my own avatar, I issued "/-10 sleep" which triggered the sleep routine on the listener. While that was sleeping, I did the following in this order:

  1. clicked the listener prim 1 time
  2. clicked the chat sender prim 3 times
  3. clicked the listener prim 1 time
  4. clicked the chat sender prim 3 times

The result was that after the sleep expired, the listener appeared to process all 6 queued up listen events, and then only one touch event. This was the output:

[16:10] Object: sleep started
[16:10] Object: sleep stopped
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: listen received ping
[16:10] Object: end of listen event
[16:10] Object: Touched.

Trying again with multiple additional touches on the listener prim but only one touch event ever seemed to queue up. So it seems that touch events are dropped after the first, but any chat that matches the listen handler filter will queue up even while the script sleeps.

Curious that the listen events seemed to take priority over the touch event when draining the queue...

Edited by Fenix Eldritch
  • Thanks 2
Link to comment
Share on other sites

Regarding listen events: http://wiki.secondlife.com/wiki/Talk:LlListen

Quote
  1. Chat that is said gets added to a history.
  2. A script that is running and has a listen event will ask the history for a chat message during its slice of run time.
  3. When the script asks the history for a chat message the checks are done in this order:
    1. channel
    2. self chat (objects can't hear themselves)
    3. distance/RegionSay
    4. key
    5. name
    6. message
  4. If a message is found then a listen event is added to the event queue.

This means that no matter for how long the script is sleeping or the event queue stays full, the script will always receive all messages in the order they were received by the sim.

Edited by Wulfie Reanimator
  • Thanks 2
Link to comment
Share on other sites

Thanks both Fenix and Wlfie, and I have a feeling Rider's work on event-ordering last year might have some bearing on this?

Just thinking, touch can have also a touch_start and touch_end, would it distinguish those as well?

Edited by Profaitchikenz Haiku
spoiling errors
  • Thanks 1
Link to comment
Share on other sites

26 minutes ago, Profaitchikenz Haiku said:

Thanks both Fenix and Wlfie, and I have a feeling Rider's work on event-ordering last year might have some bearing on this?

Just thinking, touch can have also a touch_start and touch_end, would it distinguish those as well?

Listens and sensors had their priority handling changed at the end of last year.

touch_start() > touch() > touch_end() should still queue as they always have.

Edited by Lucia Nightfire
  • Thanks 2
Link to comment
Share on other sites

1 hour ago, Lucia Nightfire said:

touch_start() > touch() > touch_end() should still queue as they always have.

Confirmed.

 

I created a cube and had a 10-second sleep in State_entry, then added touch_start, touch and touch_end blocks, within each of those I chatted out the face that had been touched. Reset the script and touched a sequence of three faces. The resulting chat showed that

Touch_start chatted back the first face I had touched

Touch_end chatted back the last face I had touched

Touch also chatted back the last face.

 

I tried different sequences of faces just in case the face number dictated the ordering, but the results above were consistent.

Edited by Profaitchikenz Haiku
  • Thanks 2
Link to comment
Share on other sites

I just repeated the test but now using collision events, and only the last detected position I was at was chatted out, so collisions store none or one, and it's always the last one.

 

I've realised that the sequence of the touch events being stored can be quite useful. Imagine you have a number pad and you tap away at the numeric keys, then realise this thing isn't responding, and you tap a cancel key. When it does come back to life, it will record the first of many keys, but also the last, which you can test for, and if it's cancel, take appropriate action, but it does mean shifting the touch processing out into a function instead of within the event.

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

10 minutes ago, Profaitchikenz Haiku said:

I just repeated the test but now using collision events, and only the last detected position I was t as chatted out, so collisions store none or one, and it's always the last one.

 

I've realised that the sequence of the touch events being stored can be quite useful. Imagine you have a number pad and you tap away at the numeric keys, then realise this thing isn't responding, and you tap a cancel key. When it does come back to life, it will record the first of many keys, but also the last, which you can test for, and if it's cancel, take appropriate action, but it does mean shifting the touch processing out into a function instead of within the event.

Thank you very much! Your method works for me and i even managed to make this version for linked detector and light.

/* Light with detector V.2 - For linked detector and light */

vector LIGHT_COLOR = < 1.0, 1.0, 1.0 > ; // Light color lsl RGB
integer LIGHT_PRIM = 2; // Light prim number or LINK_THIS
integer LIGHT_FACE = ALL_SIDES; // Light face number or ALL_SIDES

integer lightOn = 0;

default
{
    state_entry()
    {
        llVolumeDetect(TRUE); // Starts llVolumeDetect

        /* If detect is TRUE, VolumeDetect is enabled, physical object and avatars can pass through the object. */

    }

    collision_start(integer num)
    {
        if (lightOn == 0)
        {
            // On
            llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
                [PRIM_GLOW, LIGHT_FACE, 1,
                    PRIM_POINT_LIGHT, TRUE,
                    LIGHT_COLOR 
                    , 1.0 
                    , 10.0 
                    , 0.2 
                ]);
            lightOn = 1;
            llSetTimerEvent(5.0);
        }
    }

    timer()
    {
        llSetTimerEvent(0.0); // stop any repeating
        llSetLinkPrimitiveParamsFast(LIGHT_PRIM,
            [PRIM_GLOW, ALL_SIDES, FALSE, PRIM_POINT_LIGHT, FALSE,
                ZERO_VECTOR, 0.0, 0.0, 0
            ]);
        lightOn = 0;
    }
}

 

  • Like 1
Link to comment
Share on other sites

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

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

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...