Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

I am scripting impared :(

Chem Cosmo
Registered User
Join date: 22 Apr 2005
Posts: 104
10-11-2005 11:36
Ok, I am trying to make a simple script for a rocking chair. Eloise Pasteur was kind enough to give me the movement part (ty again Eloise:). I want to make it so that the chair is still until it is touched and the avie sits on it. Then it rocks. When the stand, the chair stops. I can't even get past the touch_start part. lol. Here it is. If anyone can help, I would greatly appreciate it.

default
{
state_entry()
{
llSay(0,"Hello! Have a seat!";);
}

touch_start(integer total_number)
{
llSay(0,"Touched.";);
}
}

state_entry()
{
rotation Inverse(rotation r)

r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}
rotation GetParentRot()
{
return Inverse(llGetLocalRot())*llGetRot();
}
SetLocalRot(rotation x)
{
llSetRot(x*Inverse(GetParentRot()));
}


vector normal = <1.5, 0.0, -1.75>;

default
{
state_entry()
{
@a;
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + 0.35>;));
SetLocalRot(llEuler2Rot(normal));
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z - 0.10>;));
SetLocalRot(llEuler2Rot(normal));
jump a;
}

}
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
10-11-2005 12:24
You can't do it the way Eloise told you (at least not exactly), because that makes the chair rock infinitely. You'll need to have the rocking motion work off a timer, and each time the timer fires you check a variable to see if you still need to be rocking.

This is untested, so it might have bugs.

CODE

integer rocking;
integer tick;

rotation Inverse(rotation r)
{
r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}
rotation GetParentRot()
{
return Inverse(llGetLocalRot())*llGetRot();
}
SetLocalRot(rotation x)
{
llSetRot(x*Inverse(GetParentRot()));
}

// Adjust this to change the axis around which the chair rocks (I think... ask Eloise)
vector normal = <1.5, 0.0, -1.75>;

default
{
on_rez(integer param)
{
llResetScript();
}

state_entry()
{
rocking = FALSE;
llSetTimerEvent(0);
// Adjust this for the size of your chair
llSitTarget(<0, 0, 0.1>, ZERO_ROTATION);
}

changed(integer change)
{
if ((change & CHANGED_LINK) == CHANGED_LINK)
{
if (llAvatarOnSitTarget() != NULL_KEY)
{
rocking = TRUE;
tick = 0;
// Adjust this to change the chair's speed
llSetTimerEvent(1);
}
else
{
rocking = FALSE;
tick = 0;
llSetTimerEvent(0);
SetLocalRot(llEuler2Rot(normal));
}
}
}

timer()
{
// Check for race condition
if (rocking == FALSE)
{
return;
}

integer step = tick % 4;

if (step == 0)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + 1>));
}
else if (step == 1)
{
SetLocalRot(llEuler2Rot(normal));
}
else if (step == 2)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z - 1>));
}
else if (step == 3)
{
SetLocalRot(llEuler2Rot(normal));
}

tick ++;
}
}


Edited to remove an incorrect comment
Chem Cosmo
Registered User
Join date: 22 Apr 2005
Posts: 104
10-11-2005 12:54
Thank you very much for your help ziggy. I appreciate it. I will let you know how it works.

Chem
Online Doesburg
absurd hero
Join date: 6 Jul 2005
Posts: 53
10-11-2005 17:40
I haven't tried it, but there is at least one problem I can see without testing it:
CODE
 
...

tick++;

...
...at the end of of the timer handle will eventually cause an 'overflow', i.e. the value of tick will become so large it can no longer be represented by an integer. I'm not sure when this would happen, but it will happen eventually, so you should better avoid it. You could easily replace it with a simple if then rule:
CODE

//tick++
if (tick==4) {
tick=1;
}
else {
tick++;
}


I'm also not sure if the if (rocking == false) condition should span the entire rest of the timer event (and be changed to: rocking=='true').
_____________________
"The evil that is in the world almost always comes of ignorance, and good intentions may do as much harm as malevolence if they lack understanding." - Albert Camus
Quince Farber
Registered User
Join date: 14 Jan 2005
Posts: 9
10-11-2005 18:19
From: someone
CODE

if (tick==4) {
tick=1;
}
else {
tick++;
}


you can cut that down to
CODE

if (tick++ == 4) { tick=0;}
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
10-11-2005 18:53
From: someone
...at the end of of the timer handle will eventually cause an 'overflow', i.e. the value of tick will become so large it can no longer be represented by an integer.


Unless LSL works differently from C in this, it shouldn't overflow, it should wrap around. So it should go to a very large positive number, wrap around to a very large negative number, then climb back up to 0, and repeat. The modulo-4 operation should still give you 0-1-2-3 each time.

But, I'm not 100% sure this is what will happen, so your way is probably safer.

From: someone
I'm also not sure if the if (rocking == false) condition should span the entire rest of the timer event (and be changed to: rocking=='true').


That check is there for the rare case when a timer event has already fired and is in the queue and hasn't been handled yet, and then the person gets off, the timer is stopped and rocking is set to FALSE, but the queued up timer event comes and hits you. For normal use, rocking should always be TRUE when you get the timer event.

So unless I misunderstood you, that's a style thing. Some people hate returns in the middle of a function with a passion, and will put large blocks of code indented inside if() checks to avoid that. I prefer to check for error cases when entering a function, and return if I know I don't have anything to do. Makes the code more readable, IMO. I don't think the functionality or performance matters too much either way.

Edit: P.S. And the largest value for an integer is 2147483647. Since this counts in seconds and the counter resets when the person gets up, someone would need to sit on that chair for about 68 years straight to even hit that limit.

;) Just kidding. If it does overflow and not wrap, then my solution isn't the best design, even if it takes 68 years for it to break.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
10-12-2005 05:33
From: Quince Farber

you can cut that down to
CODE

if (tick++ == 4) { tick=0;}
yes you can - but you shouldn't.

primarily because the legibility suffers so much. so many bugs are created out of a misunderstanding (even by the original author) of illegible code.

almost as a side note, though - why would you want to? I guess that efficiency was the intention. but you have turned the increment into a non-conditional, possibly followed by an assignment that invalidates it.

to illustrate, the original code would either compare, assign, jump or compare, jump, increment. yours will either compare, post-increment, jump or compare, post-increment, assign. no improvement either way.

some of the rules:
  1. "efficient" does not mean "few lines of code"
  2. bytecode size is only roughly proportional to source-code line-count
  3. readable and maintainable always trumps unneccesary optimisation
  4. don't be clever
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
10-12-2005 05:53
First off you don't need step at all. Below is a clean nad clever free solution.

Replace...
CODE

timer()
{
// Check for race condition
if (rocking == FALSE)
{
return;
}

integer step = tick % 4;

if (step == 0)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + 1>));
}
else if (step == 1)
{
SetLocalRot(llEuler2Rot(normal));
}
else if (step == 2)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z - 1>));
}
else if (step == 3)
{
SetLocalRot(llEuler2Rot(normal));
}

tick ++;
}


with...
CODE

timer()
{
// Check for race condition
if (rocking == FALSE)
{
llSetTimerEvent(0.0); //just to make sure
return;
}

if (tick == 0)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + 1>));
}
else if (tick == 2)
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z - 1>));
}
else
{
SetLocalRot(llEuler2Rot(normal));
}

tick = (tick + 1) % 4;
}


course if you want clever...
CODE

timer()
{
// Check for race condition
if (rocking == FALSE)
{
llSetTimerEvent(0.0); //just to make sure
return;
}

SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + ((1 - (tick & 2)) * (++tick & 1))>));

}
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
10-12-2005 07:24
From: Strife Onizuka
CODE

timer()
{
// Check for race condition
if (rocking == FALSE)
{
llSetTimerEvent(0.0); //just to make sure
return;
}

SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + ((1 - (tick & 2)) * (++tick & 1))>));

}

yeah? well I see your clever, and raise you cleverer :p
CODE

timer()
{
if (rocking) SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + ((1 - (tick & 2)) * (++tick & 1))>)) else llSetTimerEvent(0.0);
}
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
10-12-2005 10:11
hehe

I just wanted to leave it semi readable :p
and you forgot your ";"

it's a good thing expanding the math in llEuler2Rot is so complex or you would get a taste of that.

CODE

timer()
{
if (rocking) SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + ((1 - (tick & 2)) * (++tick & 1))>)); else llSetTimerEvent(0.0);
}
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
10-12-2005 10:43
From: Strife Onizuka
and you forgot your ";"
No I didn't!
I was, ummmm, just, errrrr, testing you! Yeah! That's what I was doing - testing.
:D