Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Moving avi in relation to sit target

Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
07-27-2008 15:05
OK, I admit I am over my head here. I keep promising to write the code to adjust a sitting avatar. I have done the basic work. I can get the avatar to move along the 3 axes with the following code. However, it only works if the prim I am sitting on has all 3 rotations set to zero, which is obviously not very useful. How do I make adjustments to allow for rotated prims and a rotated avatar?

Note that the initial llSitTarget is set in a diffferent script in the prim

CODE

//Avatar Ahimation Adjustment Script
//By Cheree Bury

vector animation_offset;
float pressed_adjustment_amount = 0.01;
float held_adjustment_amount = 0.03;

default
{
changed(integer change)
{
if (change & CHANGED_LINK)
{ // it was a link change
key av = llAvatarOnSitTarget();
if (av == NULL_KEY)
{
if (llGetPermissions() & PERMISSION_TAKE_CONTROLS)
{
llReleaseControls();
}
}
else
{
llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TAKE_CONTROLS);
}
}
}

run_time_permissions(integer perm)
{
// Take control of the control keys
integer desired_controls =
CONTROL_FWD | CONTROL_BACK |
CONTROL_LEFT | CONTROL_RIGHT |
CONTROL_UP | CONTROL_DOWN;

if (perm & PERMISSION_TAKE_CONTROLS)
{
llTakeControls(desired_controls, TRUE, FALSE);
}
}

control(key id, integer down, integer new)
{
integer pressed = down & new;
integer held = down & ~new;
integer released = ~down & new;

//Get the avi position and rotation
list a = llGetObjectDetails(llAvatarOnSitTarget(), ([OBJECT_POS, OBJECT_ROT]));
vector AviPos = llList2Vector(a,0);
rotation AviRot = llList2Rot(a,1);
//llWhisper(0, "Avi Position: " + (string)AviPos);
//llWhisper(0, "Avatar Position: " + llList2String(a,0) +
// "\nAvatar Rotation: " + llList2String(a,1));

//Get the position and rotation of the prim the avi is sitting on (the primt this cript is in)
list b = llGetObjectDetails(llGetLinkKey(llGetObjectPrimCount(llGetKey())), ([OBJECT_POS, OBJECT_ROT]));;
vector PrimPos =llList2Vector(b,0);
rotation PrimRot = llList2Rot(b, 1);
//llWhisper(0, "Prim Position: " + (string)PrimPos);
//llWhisper(0, "Prim Position: " + llList2String(b,0) +
// "\nPrim Rotation: " + llList2String(b,1));

//The offset is the difference between then avi's position and the prim's position
animation_offset = AviPos - PrimPos;

//Now adjust the offset amount by whatever control key is pressed
if (held & CONTROL_FWD) animation_offset.x += held_adjustment_amount;
if (held & CONTROL_BACK) animation_offset.x -= held_adjustment_amount;

if (pressed & CONTROL_FWD) animation_offset.x += pressed_adjustment_amount;
if (pressed & CONTROL_BACK) animation_offset.x -= pressed_adjustment_amount;

if (held & CONTROL_LEFT) animation_offset.y += held_adjustment_amount;
if (held & CONTROL_RIGHT) animation_offset.y -= held_adjustment_amount;

if (pressed & CONTROL_LEFT) animation_offset.y += pressed_adjustment_amount;
if (pressed & CONTROL_RIGHT) animation_offset.y -= pressed_adjustment_amount;

if (held & CONTROL_UP) animation_offset.z += held_adjustment_amount;
if (held & CONTROL_DOWN) animation_offset.z -= held_adjustment_amount;

if (pressed & CONTROL_UP) animation_offset.z += pressed_adjustment_amount;
if (pressed & CONTROL_DOWN) animation_offset.z -= pressed_adjustment_amount;

//llOwnerSay((string)animation_offset);

//Move the avatar by the calculated amount
llSetLinkPrimitiveParams(llGetObjectPrimCount(llGetKey()) + 1, [PRIM_POSITION, animation_offset] );

//The sit target is slightly different. It's z axis is 0.365 less than the offset
//Remove this section if you do not want the sit target changed
vector SitVector = animation_offset;
SitVector.z -= 0.365;
llSitTarget(SitVector, AviRot);

}

}
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
07-27-2008 18:39
From: Cheree Bury
How do I make adjustments to allow for rotated prims and a rotated avatar?
Here's the error:

CODE
        //The offset is the difference between then avi's position and the prim's position
animation_offset = AviPos - PrimPos;
That's the offset in world-space. You want the offset in prim-space, taking the prim's rotation into account, because llSetLinkPrimitiveParams deals in prim-space coordinates:

CODE
        animation_offset = ( AviPos - PrimPos ) / PrimRot;
That will get the av moving correctly, at least in relation to the prim.

As far as accounting for the Av's rotation, your system of adding or subtracting set values to/from the existing offset vector's components based on which direction key was pressed/held is inherently prim-space locked. You'll instead need to generate a second offset vector which is how much you're moving the av:
CODE
        vector new_offset;

if (held & CONTROL_FWD) new_offset.x += held_adjustment_amount;
if (held & CONTROL_BACK) new_offset.x -= held_adjustment_amount;

if (pressed & CONTROL_FWD) new_offset.x += pressed_adjustment_amount;
if (pressed & CONTROL_BACK) new_offset.x -= pressed_adjustment_amount;

if (held & CONTROL_LEFT) new_offset.y += held_adjustment_amount;
if (held & CONTROL_RIGHT) new_offset.y -= held_adjustment_amount;

if (pressed & CONTROL_LEFT) new_offset.y += pressed_adjustment_amount;
if (pressed & CONTROL_RIGHT) new_offset.y -= pressed_adjustment_amount;

if (held & CONTROL_UP) new_offset.z += held_adjustment_amount;
if (held & CONTROL_DOWN) new_offset.z -= held_adjustment_amount;

if (pressed & CONTROL_UP) new_offset.z += pressed_adjustment_amount;
if (pressed & CONTROL_DOWN) new_offset.z -= pressed_adjustment_amount;

Then add that new_offset, multiplied by AviRot divided by PrimRot (which is the av's rotation in prim-space), which gives you the new_offset in prim-space, to animation_offset:
CODE
        animation_offset += new_offset * ( AviRot / PrimRot );
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
My contribution for eliminating pose balls from furniture
07-29-2008 18:35
I believe this script is finished. I need lots of people to test it out please. Let me know if it works corrrectly for you.

Also let me know if you have suggestions for improvements.

Place this script in the prim in your furniture that contains your llSitTarget script.

When the avi sits on the furinture, she can say "adjust start" on channel 1 to take control of the control keys. e.g. /1adjust start

Then use the up, down, shift left, shift right, page up, and page down keys to reposition the sitting avatar.

Say "adjust stop" on channel 1 after the adjustments are complete.


CODE

//Avatar Animation Adjustment Script
//This script will allow the sitting avatar to adjust their position along the 3 axes in order to better align their avi

//By Cheree Bury
//Rotation code submitted by Deanna Trollop

float pressed_adjustment_amount = 0.01; //Movement amount when key is initally pressed (for fine tuning)
float held_adjustment_amount = 0.03; //Movement amount when key is held down (for faster movement)
vector SitTargetOffset = <0.0, 0.0, -0.365>; //The difference between the location of the avatar as a prim and the sit target
integer ListenChannel = 1;
string StartCommand = "adjust start";
string StopCommand = "adjust stop";
float TimerLength = 20.0; //Timer just in case user forgets to turn off the adjuster

vector animation_offset;
integer ListenHandle;

default
{
changed(integer change)
{
if (change & CHANGED_LINK)
{ // it was a link change
key av = llAvatarOnSitTarget();
if (av == NULL_KEY)
{
llListenRemove(ListenHandle);
llSetTimerEvent(0.0);
}
else
{
ListenHandle = llListen( ListenChannel, "", av, "" );
}
}
}

listen( integer channel, string name, key id, string message )
{
if (channel == ListenChannel)
{
if (id == llAvatarOnSitTarget())
{
if (llToLower(message) == llToLower(StartCommand))
{
llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TAKE_CONTROLS);
llSetTimerEvent(TimerLength);
}
else if (llToLower(message) == llToLower(StopCommand))
{
if (llGetPermissions() & PERMISSION_TAKE_CONTROLS)
{
llReleaseControls();
llSetTimerEvent(0.0);
llListenRemove(ListenHandle);
}
}
}
}
}

timer()
{
llSetTimerEvent(0.0);
llReleaseControls();
}

run_time_permissions(integer perm)
{
// Take control of the control keys
integer desired_controls =
CONTROL_FWD | CONTROL_BACK |
CONTROL_LEFT | CONTROL_RIGHT |
CONTROL_UP | CONTROL_DOWN;

if (perm & PERMISSION_TAKE_CONTROLS)
{
llTakeControls(desired_controls, TRUE, FALSE);
}
}

control(key id, integer down, integer new)
{
integer pressed = down & new;
integer held = down & ~new;

//Get the avi position and rotation
list a = llGetObjectDetails(llAvatarOnSitTarget(), ([OBJECT_POS, OBJECT_ROT]));
vector AviPos = llList2Vector(a,0);
rotation AviRot = llList2Rot(a,1);

//Get the position and rotation of the prim the avi is sitting on (the primt this cript is in)
list b = llGetObjectDetails(llGetLinkKey(llGetObjectPrimCount(llGetKey())), ([OBJECT_POS, OBJECT_ROT]));;
vector PrimPos =llList2Vector(b,0);
rotation PrimRot = llList2Rot(b, 1);

//The offset is the difference between the avi's position and the prim's position and then adjusted for rotations
animation_offset = ( AviPos - PrimPos ) / PrimRot;

//Now adjust the offset amount by whatever control key is pressed
if (held & CONTROL_FWD) animation_offset.x += held_adjustment_amount;
if (held & CONTROL_BACK) animation_offset.x -= held_adjustment_amount;

if (pressed & CONTROL_FWD) animation_offset.x += pressed_adjustment_amount;
if (pressed & CONTROL_BACK) animation_offset.x -= pressed_adjustment_amount;

if (held & CONTROL_LEFT) animation_offset.y += held_adjustment_amount;
if (held & CONTROL_RIGHT) animation_offset.y -= held_adjustment_amount;

if (pressed & CONTROL_LEFT) animation_offset.y += pressed_adjustment_amount;
if (pressed & CONTROL_RIGHT) animation_offset.y -= pressed_adjustment_amount;

if (held & CONTROL_UP) animation_offset.z += held_adjustment_amount;
if (held & CONTROL_DOWN) animation_offset.z -= held_adjustment_amount;

if (pressed & CONTROL_UP) animation_offset.z += pressed_adjustment_amount;
if (pressed & CONTROL_DOWN) animation_offset.z -= pressed_adjustment_amount;

animation_offset = ( AviPos - PrimPos ) / PrimRot;

//Now adjust for the rotation of the avi
vector new_offset;

if (held & CONTROL_FWD) new_offset.x += held_adjustment_amount;
if (held & CONTROL_BACK) new_offset.x -= held_adjustment_amount;

if (pressed & CONTROL_FWD) new_offset.x += pressed_adjustment_amount;
if (pressed & CONTROL_BACK) new_offset.x -= pressed_adjustment_amount;

if (held & CONTROL_LEFT) new_offset.y += held_adjustment_amount;
if (held & CONTROL_RIGHT) new_offset.y -= held_adjustment_amount;

if (pressed & CONTROL_LEFT) new_offset.y += pressed_adjustment_amount;
if (pressed & CONTROL_RIGHT) new_offset.y -= pressed_adjustment_amount;

if (held & CONTROL_UP) new_offset.z += held_adjustment_amount;
if (held & CONTROL_DOWN) new_offset.z -= held_adjustment_amount;

if (pressed & CONTROL_UP) new_offset.z += pressed_adjustment_amount;
if (pressed & CONTROL_DOWN) new_offset.z -= pressed_adjustment_amount;

animation_offset += new_offset * ( AviRot / PrimRot );

//Move the avatar by the calculated amount
llSetLinkPrimitiveParams(llGetObjectPrimCount(llGetKey()) + 1, [PRIM_POSITION, animation_offset] );

//The sit target is slightly different. It's z axis is 0.365 less than the offset
//Remove this section if you do not want the sit target changed
vector SitVector = animation_offset;;
SitVector += SitTargetOffset * AviRot;
llSitTarget(SitVector, AviRot / PrimRot);

//Reset the timer with each keystroke
llSetTimerEvent(TimerLength);
}

}
]/PHP]
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
08-04-2008 05:20
So far I have had great results with people using this script in a single object with only one sit target.

However, it is not working with an object that has multiple sit targets. Its behavior is erratic when moving the avi.

I will be working on it later tonight if I have time. But I would appreciate any help in pointing me to the error in my ways.
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
08-04-2008 10:50
I have the feeling your problem might be in misconstruing what an avatar sits on. An avatar sits on the OBJECT, not a PRIM. If the avatar happens to sit on a sit target defined relative to a PRIM, so be it, but the avatar's position and rotation as far as llSetPrimitiveParams() goes should be (just like any other actual prim in the linkset) relative to the ROOT prim.
Imnotgoing Sideways
Can't outlaw cute! =^-^=
Join date: 17 Nov 2007
Posts: 4,694
08-04-2008 11:31
I think I had that worked out once... Using a sit target helper I got from Aley. Cheree, ain't you seen my black chair I use in the blitz builds? I gotta look again... It may have my multi-sit experiment in it. (^_^)y
_____________________
Somewhere in this world; there is someone having some good clean fun doing the one thing you hate the most. (^_^)y


http://slurl.com/secondlife/Ferguson/54/237/94
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
08-04-2008 11:36
From: Hewee Zetkin
I have the feeling your problem might be in misconstruing what an avatar sits on. An avatar sits on the OBJECT, not a PRIM. If the avatar happens to sit on a sit target defined relative to a PRIM, so be it, but the avatar's position and rotation as far as llSetPrimitiveParams() goes should be (just like any other actual prim in the linkset) relative to the ROOT prim.


This makes sense now that I think about how it is acting. Gives me a good place to start. Tnx Hewee
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
08-04-2008 11:40
From: Imnotgoing Sideways
I think I had that worked out once... Using a sit target helper I got from Aley. Cheree, ain't you seen my black chair I use in the blitz builds? I gotta look again... It may have my multi-sit experiment in it. (^_^)y


Immy, I have seen your black chair, but had no idea it was special. I need all the help I can get here, so please have a look.

I might even vote for you one Sunday night. :-)
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
08-07-2008 07:32
From: Cheree Bury
This makes sense now that I think about how it is acting. Gives me a good place to start. Tnx Hewee


**Bump**

I'm still struggling with this one. Things that I try seem to work, then when I rotate them, they do not work correctly. Obviously I just do not understand enough about it.

Any more suggestions?

My intent was that this would be freely available for all to use, but I am spending too much time on it and getting frustrated by my lack of knowledge. I hate it when I don't know something, but I just don't seem to be able to get my mind around this one.