Jump to content

Detect if avatar is walking or standing and hide or show linked prims when state changes


Ozmodius Elswit
 Share

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

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

Recommended Posts

so .. this is what I have so far.... any pointers on what i'm doing wrong?

 

agentState = llGetAgentInfo(llDetectedKey(0));

integer topper = 2
integer floater = 3
default
{
Switch (agentState)
case AGENT_FLYING:
llSetLinkAlpha(topper, 0.0, ALL_SIDES);
llSetLinkAlpha(floater, 100.0, ALL_SIDES);
Break;
case AGENT_ALWAYS_RUN:
llSetLinkAlpha(topper, 0.0, ALL_SIDES);
llSetLinkAlpha(floater, 100.0, ALL_SIDES);
Break;
case AGENT_AUTOPILOT:
llSetLinkAlpha(topper, 0.0, ALL_SIDES);
llSetLinkAlpha(floater, 100.0, ALL_SIDES);
Break;
case AGENT_WALKING:
llSetLinkAlpha(topper, 0.0, ALL_SIDES);
llSetLinkAlpha(floater, 100.0, ALL_SIDES);
Break;
case AGENT_IN_AIR:
llSetLinkAlpha(topper, 0.0, ALL_SIDES);
llSetLinkAlpha(floater, 100.0, ALL_SIDES);
Break;
case else:
llSetLinkAlpha(topper, 100.0, ALL_SIDES);
llSetLinkAlpha(floater, 0.0, ALL_SIDES);

}

Link to comment
Share on other sites

Ok.. another stab at it...  I'm now getting a null reference exeption and anyone identify it?

integer floater = 2;integer topper = 3;integer myState = 0;float poll = 0.2;key owner = llGetOwner;integer buf; default{           state_entry()    {       llSetTimerEvent(poll);    }   timer()    {        buf = llGetAgentInfo(owner);          if (buf == AGENT_FLYING) {           myState = 1;            return;        }         if (buf == AGENT_ALWAYS_RUN) {           myState = 1;            return;        }         if (buf == AGENT_AUTOPILOT) {           myState = 1;            return;        }         if (buf ==  AGENT_WALKING) {           myState = 1;            return;        }         if (buf == AGENT_IN_AIR) {          myState = 1;            return;        }        if (myState == 0) {            llSetLinkAlpha(topper, 100.0, ALL_SIDES);            llSetLinkAlpha(floater, 0.0, ALL_SIDES);             return;        }        if (myState ==1) {            llSetLinkAlpha(topper, 0.0, ALL_SIDES);            llSetLinkAlpha(floater, 100.0, ALL_SIDES);            return;        }    }}

 

Link to comment
Share on other sites

The issue is your attempted assignment of owner = llGetOwner() in the variables section.

llGetOwner() is a function, it must be executed, you're trying to assign a variable to another variable, llGetOwner isn't a function, llGetOwner() is a function.

So, quick and dirty, you could put the owner = llGetOwner() inside your state_entry function along with llSetTimer().

I say quick and dirty because that's fine but it will only resolve the owner at the time that state_entry executes and that's when the script is compiled or reset, so if you gave this to someone else, the owner variable would still be assigned with the avatar key of the person who gave the item.

How can you fix this?

There are a number of ways, take your pick.

You can include a change event which in this simple case could detect the change of owner of the script and just reset the script (not always what you want to do as resetting will clear other variables but it's fine for this simple version).

change (integer changed){  if (changed == CHANGED_OWNER)  {    llResetScript();  }}

 Another way would be to use the attach event since that will pass the key of the avatar to whom the item is attached at the time its attached.

attach(key id){  if (id)  {    owner = id;  }}

 If id == NULL_KEY then the item is being detached.

You can also condense a lot of your "if's", for example:-

if (buf == AGENT_FLYING || AGENT_ALWAYS_RUN || AGENT_AUTOPILOT)...etc.

 Be careful with the difference between | and ||

The first is a bitwise comparison, the second is a logical comparison and using the wrong one will bite you one day.

Well done for having a go, we all learn somewhere.

 

  • Like 1
Link to comment
Share on other sites

Ok.. not sure why this is happening. But none of my if statements are True at anytime.. I'm not sure how this is. I have llSay in everyone in the timer. I know the timer is running because I've put an llSay before the first if and it spams happily. Any thoughts?

integer floater = 2;integer topper = 3;integer myState = 0;float poll = 0.2;key owner;integer buf; default{    attach(key id){  if (id)  {    owner = id;    buf = llGetAgentInfo(owner);    llSetTimerEvent(poll);  }}       state_entry()    {          }   timer()    {                  if (buf == AGENT_FLYING || AGENT_ALWAYS_RUN || AGENT_AUTOPILOT || AGENT_WALKING || AGENT_IN_AIR){        myState = 1;        llSay(0,"setting State to 1");
} if (myState == 0) { llSetLinkAlpha(topper, 100.0, ALL_SIDES); llSetLinkAlpha(floater, 0.0, ALL_SIDES); llSay(0, "0"); return; } if (myState == 1) { llSetLinkAlpha(topper, 0.0, ALL_SIDES); llSetLinkAlpha(floater, 100.0, ALL_SIDES); llSay(0,"1"); return; } }}

 

Link to comment
Share on other sites

Your sequence is a little wrong.

You get the locomotion state with llGetInfo only once, then you start a timer and every 0.2s see what it says but you never check again.

Within the timer() event, you need to call llGetInfo there instead so just move the buf=llGetInfo(owner) out of the attach event and into the timer event before your "if" test for the locomotion states of interest.

Link to comment
Share on other sites

A number of things could be improved on that script.

The first if gate with all that ||, if I'm reading that right, the first check would be either true or false, but then all the subesquent checks are merely a single non-zero integer, so they will all return true, meaning that that net if statement isn't going to work out right.

What you seem to be angling at is:

if (buf == AGENT_FLYING || buf == AGENT_ALWAYS_RUN || buff == AGENT_AUTOPILOT || buf == AGENT_WALKING || buff == AGENT_IN_AIR)

 However, that still isn't going to produce what you want.  Agent info returns a bitfield, which is a variety of yes/no states which comes together to form a single integer.  To properly check against those statues you'd do this:

if (buf & (AGENT_FLYING | AGENT_ALWAYS_RUN | AGENT_AUTOPILOT | AGENT WALKING | AGENT_IN_AIR))

 That creates a composit state of the various things you want to check for, and tests it against the agent state.

Also, set link alpha works on a number from 0 to 1, with 1 being 100% visible, 0 being fully transparent.  Do NOT go to 100.0, you are overshooting the maximum by a factor of 100.

However, a huge problem with this code is buf is only reporting the state of the agent at the code bootup.  You want to reset it every run of the code.  Sooooooo... here's a completely rewritten version of your code because I've naught better to do.

integer FLOATER_PRIM = 2;integer TOP_PRIM = 3;float TICK_LENGTH = 0.2;key OWNER;integer TRIGGER_STATES;default {       state_entry() {         OWNER = llGetOwner();        TRIGGER_STATES = (AGENT_FLYING | AGENT_ALWAYS_RUN | AGENT_AUTOPILOT | AGENT_WALKING | AGENT_IN_AIR);        if (llGetAttached()) llSetTimerEvent(TICK_LENGTH);    }        changed(integer change) {         if (change & CHANGED_OWNER) llResetScript();    }        attach(key wearer) {        if (wearer) {            llSetTimerEvent(TICK_LENGTH);        } else {            llSetTimerEvent(0);        }    }    timer() {        integer status = llGetAgentInfo(OWNER);          if (status & TRIGGER_STATES) {            llSetLinkAlpha(TOP_PRIM, 1.0, ALL_SIDES);            llSetLinkAlpha(FLOATER_PRIM, 0.0, ALL_SIDES);             llOwnerSay("Avatar is in motion");        } else {            llSetLinkAlpha(TOP_PRIM, 0.0, ALL_SIDES);            llSetLinkAlpha(FLOATER_PRIM, 1.0, ALL_SIDES);            llOwnerSay("Avatar is stationary");                 }         }}

 

 I've done a few things here on top of reorganizing it. 

First off I renamed a few variables for my own convenience.  I tend to ALL_CAPS immuteables, stuff I set once and leave.  I set up the core initialization stuff in state_entry, i added a check for changed owners, with the script resetting if it sees that so OWNER will never be incorrect.  An attach event toggles the timer on and off as needed.

I took all the states you needed to check for and slammed them all together into something known as TRIGGER_STATES.

Now if you draw your attention to the timer event, you'll see I dump the agent info into a local integer; status.  Then I can test status against the TRIGGER_STATES I built in the state_entry event.  If it triggers then execute the code, else execute the other code.  No return statements needed since the if/else design means I'm only testing once.

Hope that helps.

  • Like 1
Link to comment
Share on other sites

Wow, I love all the different ways to accomplish the same tasks.. I solved it before you all solved it better.. here was my solution. I'm going to go with the last example .. simply because it's much cleaner. Thanks to everyone!

integer floater = 2;integer topper = 3;integer myState = 0;float poll = 0.2;key owner;string ani;default{state_entry(){           }attach(key id){  if (id){    owner = id;    myState = 0;    llSay(0, "Attachment Action");    llSetTimerEvent(poll);  } }timer()    {            ani = llGetAnimation(owner);        if(ani == "Walking"){              myState = 1;        }         if(ani == "Flying"){              myState = 1;        }         if(ani == "FlyingSlow"){              myState = 1;        }         if(ani == "Falling Down"){              myState = 1;        }         if(ani == "Jumping"){              myState = 1;        }         if(ani == "PreJumping"){              myState = 1;        }         if(ani == "Taking Off"){              myState = 1;        }         if(ani == "Walking"){              myState = 1;        }         if(ani == "Falling Down"){              myState = 1;        }         if(ani == "CrouchWalking"){              myState = 1;        }         if(ani == "Crouching"){              myState = 0;        }         if(ani == "Standing"){              myState = 0;        }         if(ani == "Sitting"){              myState = 0;        }         if(ani == "Sitting on Ground"){              myState = 0;        }        if (myState == 0) {            llSetLinkAlpha(topper, 100.0, ALL_SIDES);            llSetLinkAlpha(floater, 0.0, ALL_SIDES);             return;        }        if (myState == 1) {            llSetLinkAlpha(topper, 0.0, ALL_SIDES);            llSetLinkAlpha(floater, 100.0, ALL_SIDES);            return;        }                 }}

 

Link to comment
Share on other sites

Glad it helped, little general pointer with a big old ladder of if statments:  use if/else

Kind of like this:

        if(ani == "Walking"){              myState = 1;        }        else if(ani == "Flying"){              myState = 1;        }        else if(ani == "FlyingSlow"){              myState = 1;        }        else if(ani == "Falling Down"){              myState = 1;        }        else if(ani == "Jumping"){              myState = 1;        }

 If one of the if statements checks out TRUE on your little ladder there, it will still test against all those other words in that code.  By adding an else to all those ifs it won't check it if one checks true, makes it duck out of the whole chain.

This sort of efficiency is good when you got code that's being executed over and over, like what you got on a timer event.  it's better to work through llGetAgentInfo though like what I did because the animations can be changed via llSetAnimationOverride, you can figure out what you should be checking for with llGetAnimationOverride but that adds an extra step in the process, besides, it's faster to test an integer over a string.

Hopefully I haven't overwhelmed you with information, and good luck.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3455 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...