User talk:Chibbchichi Resident

From Second Life Wiki
Jump to: navigation, search

llGetAgentInfo Example

I saw your recent contribution to llGetAgentInfo, but I felt it had some problems that needed addressing, so I took the liberty of moving it to here. Your attach event resets the script, forcing it back through state_entry. Within state_entry you assign the owner's key to the string 'id' (strictly should be a key variable). But then you attempt to test if the object is being detached by checking if id is NULL_KEY - but it can't be. That test needs to be done inside the attach() event. Stopping the timer from within state_entry is pointless, as no timer will be running first time nor on script reset. Within timer(), the information you gain from llGetAgentInfo() is not only about whether the agent is typing. It could for example include mouselook indication, or if they are flying. So testing this data for a change in typing status is not totally valid. You must isolate the AGENT_TYPING bit straightaway. I won't try and fix the whole script, but perhaps this would work for the timer code. The rest needs a bit of a rethink. Omei Qunhua 11:18, 26 December 2013 (PST)

<lsl> timer() {

   integer TypingNow = llGetAgentInfo( llGetOwner() ) & AGENT_TYPING;
   if (TypingNow != gLastAnimation)
   {
        if (TypingNow)
           doStuff();
        else
           stopStuff();
       gLastAnimation = TypingNow;
   }  

} </lsl>

[V3] <lsl> // A simple typing override example. // Modified the example-LSL of llGetAnimation to make it work with llGetAgentInfo. // Also included an easy way to hide and show the whole object depending on current typing state. // For example: Show a keyboard under avatars hands when avatar types.

key gOwner; // the wearer's key integer gWasTyping; // last state of typing seen

// User functions Initialize(key id){

   if (id == NULL_KEY) { // detaching
       llSetTimerEvent(0.0); // stop the timer
   }
   else { // attached, or reset while worn
       llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION);
       gOwner = id;
   }

}

// Event handlers default {

   state_entry() {
       // in case the script was reset while already attached
       if (llGetAttached() != 0) {
           Initialize(llGetOwner());
       }
   }

   attach(key id) {
       Initialize(id);
   }

   run_time_permissions(integer perm) {
       if (perm & PERMISSION_TRIGGER_ANIMATION) {
           llSetTimerEvent(0.25); // start polling
       }
   }

   timer() {
       integer typingNow = llGetAgentInfo(gOwner);

       if (gWasTyping != (typingNow & AGENT_TYPING)) { // any change?
           if(typingNow & AGENT_TYPING){ // set whole object visible when typing
               llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES);
               llStartAnimation("run");
           }
           else{ // set whole object invisible if not typing
               llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES);
               llStopAnimation("run");
           }
           gWasTyping = typingNow; // store away for  net time
       }
   }

} </lsl>

I agree with Omei here. The purpose of the examples in the wiki pages is to be educative about what the function does. This script is, at best, an example of how to put a bunch of functions and events together in order to make a typing overrider. Not really educative on what llGetAgentInfo does by itself. The individual functions are not the correct place for putting a script that requires mixing so many functions and events. The example that is already present there is enough, and serves as a good illustration of how an educational example looks like. --Pedro Oval 15:07, 29 December 2013 (PST)
I've already told Omei, wrote it as comment in the script and i will say it here again: This script is based on the example shown in LlGetAnimation. If my script is not an good example then the LlGetAnimation example is not good enough as well. I won't try anymore to get it as an example in llGetAgentInfo. The search box is gladly able to find it when someone searches for "typing override" so i hope it will make someone happy in the future. --Chibbchichi Resident 05:04, 30 December 2013 (PST)

Anyone finding this page as an example of a typing override should be aware of the following:-

1) It seems that the only reason for requesting animation permission, is a kack-handed way of deciding when to start the timer, as it's not actually doing any animating. Why not just start the timer any time the device gets attached?
2) The "typing" bit from llGetAgentInfo() is not being handled correctly. I refer you back to my suggested timer code. You should NOT be storing the full value returned from llGetAgentInfo() in your global variable. llGetAgentInfo() returns a whole plethera of bit-flags, whereas llGetAnimation() returns one single identity only. This code works by accident rather than by design.
3) The handling of the attach event via the the 'Initialise' user function is still flawed. When called from the attach() event, 'id' already tells you if the device is attached or not. Inside 'Initialise' the attached status is tested again, this time via llGetAttached(), but if that tells you it's not attached you don't stop the timer. In fact, the only place where the timer is stopped is when it has been proved that the device IS attached! But the confused logic means the timer will never be stopped. This processing differs significantly from the example in llGetAnimation.
4) A global variable called "gOwner" is declared and assigned but is never used.
5) And overall, this is more of an attempt at an application, rather than a demonstration of how llGetAgentInfo() works. It's really not suitable as an example of how to use that function.

Having taken a quick look at LlGetAnimation, I would say that only criticisms 4 and 5 apply to that example. The first 3 apply to yours, which is a significantly corrupted example. Omei Qunhua 05:43, 30 December 2013 (PST)

I offer the following for consideration:- <lsl> // A simple typing override example.

integer gWasTyping; // previous state of typing

default {

   state_entry()
   {
       if (llGetAttached() )
           llSetTimerEvent(0.25);
   }
   attach(key id)
   {
       if (id)
           llSetTimerEvent(0.25);
       else
       {
           llSetTimerEvent(0);
           llSetLinkAlpha (LINK_SET, 0, ALL_SIDES);
       }
   }
   timer()
   {
       integer typingNow = llGetAgentInfo(llGetOwner() ) & AGENT_TYPING;
       if (gWasTyping != typingNow)    
       {   // typing has started or stopped
           if (typingNow) // set whole object visible when typing
               llSetLinkAlpha(LINK_SET, 1, ALL_SIDES);
           else // set whole object invisible if not typing
               llSetLinkAlpha(LINK_SET, 0, ALL_SIDES);
           gWasTyping = typingNow;     // Remember for  next time
       }
   }

} </lsl> Omei Qunhua 06:31, 30 December 2013 (PST)