Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

rotation on command, help plz!

ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-11-2006 14:07
HI! i am really NOOB to scripting and seems like noone could help me with it in game so was wondering if you guys could land a hand.

i got a script from someone that make an attachment rotate on root prim (making a tail wag, or wings flap etc), and the script is always running so tail is always wagin. but id like it to wag only for a certain amount of time after i used a /1wag command or something like this. tought this could be possible?

ill post the script here in hope this could help :)

thanks in advance :D

CODE
vector start;
tailwag()
{
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
}
default
{
state_entry()
{
start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));
llSetTimerEvent(10 + llFrand(10));
}
timer()
{
tailwag();
llSetTimerEvent(10 + llFrand(10));
}
}
Rodrick Harrington
Registered User
Join date: 9 Jul 2005
Posts: 150
02-11-2006 17:48
try this

CODE
 vector start;
integer ON = FALSE;
integer counter = 0;

tailwag()
{
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
}
default
{
state_entry()
{
start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));
llSetTimerEvent(10 + llFrand(10));
llListen(1, "", llGetOwner(), "");
}
timer()
{
if (on && counter < 10)//the 10 is arbitrary, set this to how long you want it to wag in "ticks"
{
tailwag();
counter ++;
}
llSetTimerEvent(10 + llFrand(10));
}

listen(integer channel, string name, key id, string message)
{
if (id == llGetOwner() && message == "wag") //redundant, but I always do it anyway
{
on = TRUE;
counter = 0;
}
}
}
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-11-2006 20:59
it returns error message there right before the && and says name isnt included within scope o_O this is so confusing ... eek!

CODE
if (on && counter < 10)//the 10 is arbitrary, set this to how long you want it to wag in "ticks"
Padraig Stygian
The thin mick
Join date: 15 Aug 2004
Posts: 111
02-11-2006 22:10
This actually works. I tested it. It only wags when you tell it to, and it wags max number of times, so you can change that variable to the number of wags you want.

CODE
integer max = 10; //how many wags?

vector start;
integer on = FALSE;
integer counter = 0;

tailwag()
{
integer x = 0;
for (x = 0; x < max; x++)
{
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
}
}
default
{
state_entry()
{
start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));
llListen(1, "", llGetOwner(), "");
}
listen(integer channel, string name, key id, string message)
{
if (id == llGetOwner() && message == "wag")
{
tailwag();
}
}
}
_____________________
(You): Aww! My pants won't rez! Does this texture look okay on me?

Incidental Radio :: Because nothing is by design
Now featuring Torley-tastic technomusic!
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-11-2006 22:24
wow thanks guys, you rock :)

edit: yes it works but i am having problems changing the rotation direction! seems like i can only make it rotate on the X acc, y and z wont work! :S

edit2: hmm wait i can edit accis, its just that i have to have the item with the rotation script inside of it, selected with my cursor to actually see that item rotate in world, no matter if worn or not. this is really strange and i wonder if it is just me or something.
Rodrick Harrington
Registered User
Join date: 9 Jul 2005
Posts: 150
02-12-2006 00:44
From: ReMzy Andrews
it returns error message there right before the && and says name isnt included within scope o_O this is so confusing ... eek!

CODE
if (on && counter < 10)//the 10 is arbitrary, set this to how long you want it to wag in "ticks"


oh yea consistant capitalization helps lol

CODE
 vector start;
integer ON = FALSE;
integer counter = 0;

tailwag()
{
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <-20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot 2Euler(llGetLocalRot()))+ <20, 0, 0>)));
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
}
default
{
state_entry()
{
start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));
llSetTimerEvent(10 + llFrand(10));
llListen(1, "", llGetOwner(), "");
}
timer()
{
if (ON && counter < 10)//the 10 is arbitrary, set this to how long you want it to wag in "ticks"
{
tailwag();
counter ++;
}
llSetTimerEvent(10 + llFrand(10));
}

listen(integer channel, string name, key id, string message)
{
if (id == llGetOwner() && message == "wag") //redundant, but I always do it anyway
{
ON = TRUE;
counter = 0;
}
}
}
Padraig Stygian
The thin mick
Join date: 15 Aug 2004
Posts: 111
02-12-2006 15:36
No, you're not crazy. rotating it on the Z axis seems to do exactly the same thing as rotating on the X axis. I have no idea why that's broken, but it's some inherent thing to do with the rotation of the root prim. It happens in the edit window, too, under certain circumstances.
_____________________
(You): Aww! My pants won't rez! Does this texture look okay on me?

Incidental Radio :: Because nothing is by design
Now featuring Torley-tastic technomusic!
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-12-2006 18:19
i really dont know how to fix that. i tryed to rotate the root prim aswell but it always goes back to its initiat position when i type /1wag. probably because of the (start) or something.

im running out of ideas and im starting to think it isnt possible to do atm.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
02-13-2006 06:44
ouch! my eyes! :)
I don't want to come across too teacher-y here, but I'm pretty sure it's gonna end up that way, so let me start by saying that I post this in the spirit of help and education, not to offend or hurt anyone. I'm looking at the code, not the coder. K? K.

K - here goes - First, the usage of start. Examine:
CODE
vector start;
...
start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));
...
llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));
What this translates to (over time) is:
CODE
llSetRot(llEuler2Rot(DEG_TO_RAD*(RAD_TO_DEG*llRot2Euler(llGetLocalRot()))));
or - "take our current rotation, convert it from a quaternion to Euler angles, convert them from radians to degrees, convert them back to radians, and then convert everything back to a quat". Not just any quat, but exactly the same one we started with.

Let's change start to a rotation instead of a vector so that the above three lines become
CODE
rotation start;
...
start = llGetLocalRot();
...
llSetRot(start);
Next, all those llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <-20, 0, 0>;))); are also doing way too much work that is just going to be undone, but taking much time to do so. These could all be replaced with something like llSetRot( llGetLocalRot() * llEuler2Rot(<-20, 0, 0>*DEG_TO_RAD) ); which could be optimised further to
CODE
rotation Nudge = llEuler2Rot(<-20, 0, 0>*DEG_TO_RAD);
rotation NudgeBack = - Nudge;
llSetRot( llGetLocalRot() * Nudge );
llSetRot( llGetLocalRot() * Nudge );
llSetRot( llGetLocalRot() * NudgeBack );
llSetRot( llGetLocalRot() * NudgeBack );
llSetRot( llGetLocalRot() * NudgeBack );
llSetRot( llGetLocalRot() * NudgeBack );
llSetRot( llGetLocalRot() * Nudge );
...
...
llSetRot( llGetLocalRot() * NudgeBack );
llSetRot( start );
(I can't get into SL at the moment, so my syntax may be out. I'll check tonight)
Incidentally, doing it this way should also get rid of the gimbal lock problem you are experiencing (rotation around the Z axis doing exactly the same as around the X axis)
Now those repeated calls to llGetLocalRot are not only (slightly) inefficient, but they allow rounding errors to accumulate during the wag. It is preferrable to always base repeated rotation on one known value. In this example, I'll set a base rotation on one side of the wag.
CODE
rotation Nudge = llEuler2Rot(<0.35, 0, 0>); // 0.35 is 20 degrees expressed in radians
rotation Base = Start * ( -2.0 * Nudge ); // base is two nudges back from center
llSetRot( Base );
llSetRot( Base * Nudge );
llSetRot( Base * (2.0*Nudge) );
llSetRot( Base * (3.0*Nudge) );
llSetRot( Base * (4.0*Nudge) );
llSetRot( Base * (3.0*Nudge) );
llSetRot( Base * (2.0*Nudge) );
llSetRot( Base * Nudge );
Now, while I'm tempted to write that using loops- it's a very small script, using verrrry little memory. We can trade some of that unused memory for a speed/lag improvement - but I'll illustrate the nice-to-have optimitsation after discussing what I think are larger issues.

- The timer runs continuously, even when wagging is off. We should rather switch the timer off when we don't want it. This is a biiig lag saving. (It also, incidentally, allows us to drop the variable ON which, being all capitalised, implies to most scripters that it's a constant - which it's not.)
- The comment in the listen event correctly identifies the owner check as redundant. Kill it. No questions asked - just kill it :).
- Also, the check for "wag" should be added to the listen filter.

Soooo..... putting this all together we get:
CODE
rotation Rotation1;
rotation Rotation2;
rotation Rotation3; // using discrete variables, because in this script memory is cheaper than cpu
rotation Rotation4;
rotation Rotation5;

integer Counter;

tailwag()
{
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
llSetRot(Rotation4);
llSetRot(Rotation5);
llSetRot(Rotation4);
llSetRot(Rotation3);
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
llSetRot(Rotation4);
llSetRot(Rotation5);
llSetRot(Rotation4);
llSetRot(Rotation3);
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
}

default
{
state_entry()
{
// we can pre-calculate EVERYTHING :)
Rotation3 = llGetLocalRot();
rotation Nudge = llEuler2Rot(<0.35, 0, 0>);
Rotation1 = Rotation3 * ( -2 * Nudge );
Rotation2 = Rotation3 * ( -Nudge );
Rotation4 = Rotation3 * ( Nudge );
Rotation5 = Rotation3 * ( 2 * Nudge );
llListen(1, "", llGetOwner(), "wag");
}

timer()
{
if (Counter < 10) // the 10 is arbitrary, set this to how long you want it to wag in "ticks"
{
tailwag();
++counter; // a good habit to get into: --x and ++y rather than x-- and y++, where appropriate
llSetTimerEvent(10 + llFrand(10));
}
else
llSetTimerEvent(0.0);
}

listen(integer channel, string name, key id, string message)
{
Counter = 0;
tailwag(); // do one immediately
llSetTimerEvent(10 + llFrand(10));
}
}
Once again, keep in mind that this is untested until I get home tonight - but it should illustrate the point until then.

While I believe in avoiding "you should do it this way" discussions when they are based solely on personal coding style, I think this code had enough unneccesary inefficiency in it to warrant some correction, and I welcome any thoughts or critisicm of the code I have offered, as well as the way in which I have offered it.

Above all else - have fun :)
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
02-13-2006 06:46
From: ReMzy Andrews
i really dont know how to fix that. i tryed to rotate the root prim aswell but it always goes back to its initiat position when i type /1wag. probably because of the (start) or something.
Yes, it is because of start being initialised in state_entry. With most scripts like this, you just need to rest the script after manually rotating the object. That way the script learns the new position.
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-13-2006 17:16
hot dayumn! okay thanks ill look what i can make out with this! thanks mister bacon ;)
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-14-2006 20:57
okay Ben i just tryed it and im getting type mismatch error message and it put my cursor right after the first Nudge. no clue what thats for.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
02-15-2006 13:42
From: ReMzy Andrews
okay Ben i just tryed it and im getting type mismatch error message and it put my cursor right after the first Nudge. no clue what thats for.
heheh - that's for me being stupid and trying to apply operators I use in my C++ libraries in LSL.

Here is the new code (and this time it's checked:))
CODE
 rotation Rotation1;
rotation Rotation2;
rotation Rotation3; // using discrete variables, because in this script memory is cheaper than cpu
rotation Rotation4;
rotation Rotation5;

integer Counter;

tailwag()
{
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
llSetRot(Rotation4);
llSetRot(Rotation5);
llSetRot(Rotation4);
llSetRot(Rotation3);
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
llSetRot(Rotation4);
llSetRot(Rotation5);
llSetRot(Rotation4);
llSetRot(Rotation3);
llSetRot(Rotation2);
llSetRot(Rotation1);
llSetRot(Rotation2);
llSetRot(Rotation3);
}

default
{
state_entry()
{
// we can pre-calculate EVERYTHING :)
Rotation3 = llGetLocalRot();
rotation Nudge = llEuler2Rot(<0.35, 0, 0>);
rotation NudgeBack = Nudge; NudgeBack.s = -NudgeBack.s;
Rotation1 = Rotation3 * NudgeBack * NudgeBack;
Rotation2 = Rotation3 * NudgeBack;
Rotation4 = Rotation3 * Nudge;
Rotation5 = Rotation3 * Nudge * Nudge;
llListen(1, "", llGetOwner(), "wag");
}

timer()
{
if (Counter < 10) // the 10 is arbitrary, set this to how long you want it to wag in "ticks"
{
tailwag();
++Counter; // a good habit to get into: --x and ++y rather than x-- and y++, where appropriate
llSetTimerEvent(10 + llFrand(10));
}
else
llSetTimerEvent(0.0);
}

listen(integer channel, string name, key id, string message)
{
Counter = 0;
tailwag(); // do one immediately
llSetTimerEvent(10 + llFrand(10));
}
}
ReMzy Andrews
Registered User
Join date: 8 Jul 2005
Posts: 61
02-15-2006 15:14
sorry but nope.. it works and all when its on the ground but as soon as i wear it, it stops rotating on command unless it is selected with the cursor, just like all the other rotating scripts in this thread. :(