Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Driver animation with vehicles

Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
12-04-2006 09:02
My apologies, for I know this must have been asked already, but I can't seem to find an applicable thread for some reason.

I have a driver animation I want to use for my bicycle. The script for the animation works fine when I "play in world/locally" and works fine when my bicycle is moving (I used Aaron Perkin's realistic vehicle script in a transparent base for the bicycle).

The problem I have is I don't know how to get the script to work automatically when the driver clicks "drive" and starts moving.

I suppose I could make the seat a poseball, shove the script in that, but that seems rather inelegant. I really would prefer that it happen automatically, without the need to click twoice for the animation and to drive it.
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-04-2006 10:26
From: Virrginia Tombola
My apologies, for I know this must have been asked already, but I can't seem to find an applicable thread for some reason.

I have a driver animation I want to use for my bicycle. The script for the animation works fine when I "play in world/locally" and works fine when my bicycle is moving (I used Aaron Perkin's realistic vehicle script in a transparent base for the bicycle).

The problem I have is I don't know how to get the script to work automatically when the driver clicks "drive" and starts moving.

I suppose I could make the seat a poseball, shove the script in that, but that seems rather inelegant. I really would prefer that it happen automatically, without the need to click twoice for the animation and to drive it.


This is easy enough to do, you simply need to start the animation when the user sits same as you would for a pose ball. In fact You SHOULD be able to put the scripts from a pose ball into your root prim and have it all work.
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
Hmmm
12-04-2006 10:42
Thank you for the reply! Unfortuantely, I already tried that--put it in the root prim along with the vehicle script, that is. And it didn't do anything at all. Yet it does work when I play it by right clicking on it in inventory and selecting play.

Is there perhaps a command in the vehicle script I am missing? I am using the Perkins script, modified only for handling and sit target.
Kage Seraph
I Dig Giant Mecha
Join date: 3 Nov 2004
Posts: 513
12-04-2006 11:10
hi, Virrginia,

it sounds like you want to trigger the animation with the control events that start the "motor" on your bicycle.

Experiment with copying the start animation command from the run time animation section into the CONTROL_FWD block further down in the script. Doing it this way, you'll also need to add a stop animation command in a !level & edges CONTROL_FWD block so that you stop pedaling when you let go of the up arrow (or w).

Post your code and we'll hack away at it. =D
_____________________
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-04-2006 11:33
From: Virrginia Tombola
Thank you for the reply! Unfortuantely, I already tried that--put it in the root prim along with the vehicle script, that is. And it didn't do anything at all. Yet it does work when I play it by right clicking on it in inventory and selecting play.

Is there perhaps a command in the vehicle script I am missing? I am using the Perkins script, modified only for handling and sit target.


How did you trigger it? you woudl still need a script. kage's idea is sound and I'm sure a few others will chime in once we have some code to play with
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
Script
12-04-2006 15:14
Thank you again:)

I should clarify that the bicycle "animation" is really just a pose that puts the hands on the handle bars. A bicycling animation would be wonderful, but I am having enough trouble as it is :)

So, I want the animation to run from when the "Driver" clicks "drive" (here, I rewrote it to say "ride";), to when he or she clicks "stand up".

I didn't write the animation, and can't seem to open it up to look at it. But as I said, it runs when I command it to via opening it in inventory, so it seems to be working.

I'm guessing the command to start the animation needs to be in this block:
**********************************
else
{
//llTriggerSound("car_start",1);

llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DRIVING", NULL_KEY);
llSleep(.4);
llSetStatus(STATUS_PHYSICS, TRUE);
llSleep(.1);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);

llSetTimerEvent(0.1);
//llLoopSound("car_idle",1);
}
}
**********************************************************
And the command to stop it needs to be in this block:

************************************************
else
{
llSetTimerEvent(0);
//llStopSound();

llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(.1);
llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DEFAULT", NULL_KEY);
llSleep(.4);
llReleaseControls();

llResetScript();
}
*******************************************************

And for reference, here's the entire script. By the way, much of this is superfluous--I turned off the sound (I haven't got a good bicycle sound yet), I don't use a target seat prim (it didn't seem to work for me, so I just modified the sit target relative to the root prim), and I never could get the wheel animations to work either. *sigh* I am SO much the beginner here.

CODE

//**********************************************
//Title: Car
//Author: Aaron Perkins
//Date: 3/17/2004
//**********************************************

//Feel free to modify these basic parameters to suit your needs.
float forward_power = 15; //Power used to go forward (1 to 30)
float reverse_power = -10; //Power ued to go reverse (-1 to -30)
float turning_ratio = 2; //How sharply the vehicle turns. Less is more sharply. (.1 to 10)
string sit_message = "Ride!"; //Sit message
string not_owner_message = "Sorry, but you are not the owner of this vehicle ..."; //Not owner message

//Anything past this point should only be modfied if you know what you are doing
string last_wheel_direction;
string cur_wheel_direction;

default
{
state_entry()
{
llSetSitText(sit_message);
llCollisionSound("", 0.0);

llSitTarget(<0.2,0.1,2.15>, llEuler2Rot(<0,0.2,-.1> ));
llSetCameraEyeOffset(<-7.0, 0.0, 3.0> );
llSetCameraAtOffset(<10.0, 0.0, 2.0> );

//car
llSetVehicleType(VEHICLE_TYPE_CAR);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.2);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.80);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 1.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.1);
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000.0, 10.0, 1000.0> );
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <500.0, 500.0, 1000.0> );
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.50);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 0.50);
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if (agent)
{
if (agent != llGetOwner())
{
llSay(0, not_owner_message);
llUnSit(agent);
llPushObject(agent, <0,0,50>, ZERO_VECTOR, FALSE);
}
else
{
//llTriggerSound("car_start",1);

llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DRIVING", NULL_KEY);
llSleep(.4);
llSetStatus(STATUS_PHYSICS, TRUE);
llSleep(.1);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);

llSetTimerEvent(0.1);
//llLoopSound("car_idle",1);
}
}
else
{
llSetTimerEvent(0);
//llStopSound();

llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(.1);
llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DEFAULT", NULL_KEY);
llSleep(.4);
llReleaseControls();

llResetScript();
}
}

}

run_time_permissions(integer perm)
{
if (perm)
{
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
}
}

control(key id, integer level, integer edge)
{
integer reverse=1;
vector angular_motor;

//get current speed
vector vel = llGetVel();
float speed = llVecMag(vel);

//car controls
if(level & CONTROL_FWD)
{
cur_wheel_direction = "WHEEL_FORWARD";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <forward_power,0,0> );
reverse=1;
}
if(level & CONTROL_BACK)
{
cur_wheel_direction = "WHEEL_REVERSE";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <reverse_power,0,0> );
reverse = -1;
}

if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
cur_wheel_direction = "WHEEL_RIGHT";
angular_motor.z -= speed / turning_ratio * reverse;
}

if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
cur_wheel_direction = "WHEEL_LEFT";
angular_motor.z += speed / turning_ratio * reverse;
}

llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);

} //end control

timer()
{
if (cur_wheel_direction != last_wheel_direction)
{
llMessageLinked(LINK_ALL_CHILDREN , 0, cur_wheel_direction, NULL_KEY);
last_wheel_direction = cur_wheel_direction;
}
}

} //end default
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-04-2006 15:39
From: Virrginia Tombola
And for reference, here's the entire script. I'm not sure how to put the script in those little scroll down boxes such as you folks seem to do, so I'm afraid I'll just post the whole thing.



Every journey begins with a first step.

To post a script in the boxes use the PHP tags [ PHP ] and [ / PHP ] with out spaces

I've not really paid any attention to the mains cript but to get the animation to work try this

CODE

//**********************************************
//Title: Car
//Author: Aaron Perkins
//Date: 3/17/2004
//**********************************************

//Feel free to modify these basic parameters to suit your needs.
float forward_power = 15; //Power used to go forward (1 to 30)
float reverse_power = -10; //Power ued to go reverse (-1 to -30)
float turning_ratio = 2; //How sharply the vehicle turns. Less is more sharply. (.1 to 10)
string sit_message = "Ride!"; //Sit message
string not_owner_message = "Sorry, but you are not the owner of this vehicle ..."; //Not owner message

//Anything past this point should only be modfied if you know what you are doing
string last_wheel_direction;
string cur_wheel_direction;

string animation = "ride";
integer animationrunning = 0;

default
{
state_entry()
{
llSetSitText(sit_message);
llCollisionSound("", 0.0);

llSitTarget(<0.2,0.1,2.15>, llEuler2Rot(<0,0.2,-.1> ));
llSetCameraEyeOffset(<-7.0, 0.0, 3.0> );
llSetCameraAtOffset(<10.0, 0.0, 2.0> );

//car
llSetVehicleType(VEHICLE_TYPE_CAR);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_ EFFICIENCY, 0.2);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_E FFICIENCY, 0.80);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_ TIMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_T IMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESC ALE, 1.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_ TIMESCALE, 0.1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMES CALE, 0.1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY _TIMESCALE, 0.1);
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TI MESCALE, <1000.0, 10.0, 1000.0> );
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_T IMESCALE, <500.0, 500.0, 1000.0> );
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION _EFFICIENCY, 0.50);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION _TIMESCALE, 0.50);
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if (agent)
{
if (agent != llGetOwner())
{
llSay(0, not_owner_message);
llUnSit(agent);
llPushObject(agent, <0,0,50>, ZERO_VECTOR, FALSE);
}
else
{
//llTriggerSound("car_start",1);

llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DRIVING", NULL_KEY);
llSleep(.4);
llSetStatus(STATUS_PHYSICS, TRUE);
llSleep(.1);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);

llSetTimerEvent(0.1);
//llLoopSound("car_idle",1);
}
}
else
{
llSetTimerEvent(0);
//llStopSound();

llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(.1);
llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DEFAULT", NULL_KEY);
llSleep(.4);
llReleaseControls();
if(animationrunning)
{
llStopAnimation(animation);
animationrunning = 0;
}
llResetScript();
}
}
}

run_time_permissions(integer perm)
{
if( (perm & PERMISSION_TAKE_CONTROLS) == PERMISSION_TAKE_CONTROLS)
{
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
}
if( (perms & PERMISSION_TRIGGER_ANIMATION) == PERMISSION_TRIGGER_ANIMATION)
{
llStopAnimation("sit");
llStartAnimation(animation);
animationrunning = 1;
}
}

control(key id, integer level, integer edge)
{
integer reverse=1;
vector angular_motor;

//get current speed
vector vel = llGetVel();
float speed = llVecMag(vel);

//car controls
if(level & CONTROL_FWD)
{
cur_wheel_direction = "WHEEL_FORWARD";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIREC TION, <forward_power,0,0> );
reverse=1;
}
if(level & CONTROL_BACK)
{
cur_wheel_direction = "WHEEL_REVERSE";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIREC TION, <reverse_power,0,0> );
reverse = -1;
}

if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
cur_wheel_direction = "WHEEL_RIGHT";
angular_motor.z -= speed / turning_ratio * reverse;
}

if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
cur_wheel_direction = "WHEEL_LEFT";
angular_motor.z += speed / turning_ratio * reverse;
}

llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRE CTION, angular_motor);

} //end control

timer()
{
if (cur_wheel_direction != last_wheel_direction)
{
llMessageLinked(LINK_ALL_CHILDREN , 0, cur_wheel_direction, NULL_KEY);
last_wheel_direction = cur_wheel_direction;
}
}

} //end default
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
12-04-2006 16:49
Hurrah! That worked--or at least I am getting an animation. Oddly enough though, unlike when I simply "played in world" before when the avatar was on the bicycle, now the rider is appearing a good distance about the original sit target with her legs crossed (AO is off). Hmmmm....not sure how I can fix this without being able to look at the animation proper.

I might have to talk to the animator who created the rider animation.
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-05-2006 01:38
From: Virrginia Tombola
Hurrah! That worked--or at least I am getting an animation. Oddly enough though, unlike when I simply "played in world" before when the avatar was on the bicycle, now the rider is appearing a good distance about the original sit target with her legs crossed (AO is off). Hmmmm....not sure how I can fix this without being able to look at the animation proper.

I might have to talk to the animator who created the rider animation.


When you play an animation in world there is no sit target offset. The sit target offset in the script puts it 2.15m above the prim. Alter this line:
CODE
llSitTarget(<0.2,0.1,2.15>, llEuler2Rot(<0,0.2,-.1> )); 


Also I have no idea what the name of your animation is so I called it "ride".
It can be automatically obtained using the following line of code as long as it is the only animation in the object. inside state_entry add the following line

CODE
animation = llGetInventoryName(INVENTORY_ANIMATION,0);
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
12-06-2006 17:04
From: Newgate Ludd
When you play an animation in world there is no sit target offset. The sit target offset in the script puts it 2.15m above the prim. Alter this line:
CODE
llSitTarget(<0.2,0.1,2.15>, llEuler2Rot(<0,0.2,-.1> )); 


I had already used that to position the rider on the seat (the coordinates there are the seat relative to the root prim, which is the transparent base). I tested it by having the rider click "ride", and then playing the pose animation in world.

Once I had that all set and adjusted, I added the code to start the animation automatically. That's when I got the rider suddenly floating even higher above the seat with her legs crossed (as opposed to the animation, which had the legs in a "bicycle" position). Any idea why that happened?

From: someone
Also I have no idea what the name of your animation is so I called it "ride".
It can be automatically obtained using the following line of code as long as it is the only animation in the object. inside state_entry add the following line

CODE
animation = llGetInventoryName(INVENTORY_ANIMATION,0);


I actually figured that one out myself, albeit not before a few syntax errors :)

A customer of mine just sent me a "fix it" script the other day. When placed in the root prim along with the vehicle script and the animation script, it runs the animation perfectly. She graciously is allowing me to share it, although I'll be honest and say I can't quite figure out exactly HOW it works. (I'm still slogging my way along on the LSL learning curve). I'll post it here when I get a chance.
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
"Riding"
12-06-2006 17:11
Here's the script. Credit goes to Reysa Sanders for this one :)

Edit: "Bicycle 2" is the name of the animation.

CODE

// Set the sit animation
// Reysa Sanders, Nov 06

default {

state_entry() {
}

changed(integer change) {
if (change & CHANGED_LINK) {
if (llAvatarOnSitTarget() != NULL_KEY) {
llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TRIGGER_ANIMATION);
}
}
}

run_time_permissions(integer perm) {
if (perm & PERMISSION_TRIGGER_ANIMATION) {
llStartAnimation("Bicycle 2");
}
}
}
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-07-2006 01:23
From: Virrginia Tombola
Once I had that all set and adjusted, I added the code to start the animation automatically. That's when I got the rider suddenly floating even higher above the seat with her legs crossed (as opposed to the animation, which had the legs in a "bicycle" position). Any idea why that happened?


I'd guess that it was your standard sit being triggered. The offset is from the hip joints (I think) so it was then placing you at the 'correct' distance as far as it was concerned

From: Virrginia Tombola
A customer of mine just sent me a "fix it" script the other day. When placed in the root prim along with the vehicle script and the animation script, it runs the animation perfectly. She graciously is allowing me to share it, although I'll be honest and say I can't quite figure out exactly HOW it works. (I'm still slogging my way along on the LSL learning curve). I'll post it here when I get a chance.


If you look closely at the new 'fix it' script its just the bare bones of what we had already crafted.

The changed event is triggered when you sit down and casues a request to allow animations.
This in turn triggers a run time permissions event which is starting the animation
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
12-07-2006 14:09
From: Newgate Ludd
I'd guess that it was your standard sit being triggered. The offset is from the hip joints (I think) so it was then placing you at the 'correct' distance as far as it was concerned



If you look closely at the new 'fix it' script its just the bare bones of what we had already crafted.

The changed event is triggered when you sit down and casues a request to allow animations.
This in turn triggers a run time permissions event which is starting the animation


A-ha! Still unclear on why it would work this way and not the first way, though (that is, without that sit postion glitch)

Very dumb newbie scripeter question here--what is the difference between putting the above code in a script and adding the additional script to a prim, as opposed to integrating the code into one script? Is it the same as pasting the code onto the end of a single script?

(if this is off topic, I can move the question elsewhere)
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
12-07-2006 16:46
From: Virrginia Tombola
A-ha! Still unclear on why it would work this way and not the first way, though (that is, without that sit postion glitch)

Very dumb newbie scripeter question here--what is the difference between putting the above code in a script and adding the additional script to a prim, as opposed to integrating the code into one script? Is it the same as pasting the code onto the end of a single script?

(if this is off topic, I can move the question elsewhere)


Its only dumb if you dont ask questiosn you need answering.
There is no difference, I think the difference in behaviour is just due to the sit target. For what ever reason I think the sit target originally calculated was wrong since the 'fix it' script doesnt set the sit target (which wilL give an offset of 0,0,0) and that works.
Virrginia Tombola
Equestrienne
Join date: 10 Nov 2006
Posts: 938
12-09-2006 10:15
Thank you so much for all your help!