Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Vehicle: Mouselook banking oddness

Rhombur Volos
King of Scripture & Kebab
Join date: 6 Oct 2004
Posts: 102
05-23-2005 10:36
I've been playing around with alternate control methods for the Dolphin MkIV, and i've been trying to make a good mouselook banking control system for a few days now.

The major trouble is this:
The banking effect seems to decay no matter what i change in the vehicle script.
The pilot can enjoy about 30 seconds of it before the banking stops altogether.
Although the banking-effect seems to be reset every time a call is made to llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION....), having the script repeat this call periodically hardly seems like a good way to keep the vehicle working as it should.

I've tried making changes to the following parameters:

VEHICLE_LINEAR_FRICTION_TIMESCALE, VEHICLE_ANGULAR_FRICTION_TIMESCALE, VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, VEHICLE_BANKING_MIX, and VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE.

Nothing seems to work. I'm finding myself being dragged toward the half-solution of a periodic linear_motor_direction call.

Does anyone have any information that might help me?
Anything at all?
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
05-24-2005 15:31
Decay in motion is a hardcoded "feature" of LSL vehicle code. It might seem like a PITA for more advanced stuffs, and in ways that's by design - the vehicle engine itself was designed to make realistic physics easier at the expense of variation.

So you're left with two choices:
- Write your own vehicle code from scratch. (more powerful; more time consuming)
- Refresh the function every X seconds while the vehicle is active.

I would strongly suggest option number two, unless you have a better education in Physics than I do. ;)
_____________________
---
Stinky Queso
Second Life Resident
Join date: 29 Nov 2004
Posts: 53
05-25-2005 10:08
Writing your own vehicle isnt really that difficult. When I started my crusade into vehicles I just tore down andrew lindens flight script until it worked the way I wanted. Ill post it here in a new post.
lmho Impfondo
Registered User
Join date: 7 Apr 2005
Posts: 31
05-25-2005 10:11
you can see the parts of the old script that i havent deleted, some of the commentary and such. I made this to go along with a following turret as an experiment.

CODE

// Simple airplane script example

// THIS SCRIPT IS PUBLIC DOMAIN! Do not delete the credits at the top of this script!

// Nov 25, 2003 - created by Andrew Linden and posted in the Second Life scripting forum
// Jan 05, 2004 - Cubey Terra - minor changes: customized controls, added enable/disable physics events
// Feel free to copy, modify, and use this script.

// Always give credit to Andrew Linden and all people who modify it in a readme or in the object description.



// assumes that the root primitive is oriented such that its
// local x-axis points toward the nose of the plane, and its
// local z-axis points toward the top

// control flags that we set later

integer motor1 = FALSE;
integer gAngularControls = 0;
integer gLinearControls = 0;

// we keep track of angular history for more responsive turns
integer gOldAngularLevel = 0;

// the linear motor uses an accumulator model rather than keeping track
// of the linear control level history
vector gLinearMotor = <0, 0, 0>;

default
{
touch_start(integer total)
{
if(llDetectedKey(0) == llGetOwner())
{
//llResetScript();
}
}
on_rez(integer i)
{
llResetScript();

}
state_entry()
{
llRezObject("turret", llGetPos() + <0,0,7>, <0,0,0>, ZERO_ROTATION, 0);
llSleep(1);
llShout(909879001, "key:" + (string)llGetKey());
llSay(0, "startup done");



llMessageLinked(LINK_SET, 1, "", "");
llListen(0, "", llGetOwner(), "");
llSetSitText("Fly");
llCollisionSound("", 0.0);
llSetText("\n", <1,1,1>, 1);
// the sit and camera placement is very shape dependent
// so modify th0ese to suit your vehicle
llSitTarget(<0.0, 0.0, .1>, ZERO_ROTATION);
llSetCameraEyeOffset(<-10.0, 0.0, 3.0> );
llSetCameraAtOffset(<3.0, 0.0, 1.0> );

llSetVehicleType(VEHICLE_TYPE_AIRPLANE);

// weak angular deflection
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.75);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 1.0);

// strong linear deflection
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.2);

// somewhat responsive linear motor
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.5);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, .1);

// somewhat responsive angular motor, but with 3 second decay timescale
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.00001);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .00001);

// very weak friction
//llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000.0, 1000.0, 1000.0> ); // CUBEY - original line
//llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 200, 200> ); // CUBEY - increased friction
//llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <.1000, .1000, .1000> );

llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, .65); // almost wobbly - CUBEY - increased from .25 to improve stability
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1); // mediocre response

llSetVehicleFlags(VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
//llRemoveVehicleFlags(VEHICLE_FLAG_CAMERA_DECOUPLED | VEHICLE_FLAG_MOUSELOOK_STEER);


llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.99); // medium strength
llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); // very responsive
llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.01); // more banking when moving

//llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE);

// hover can be better than sliding along the ground during takeoff and landing
// but it only works over the terrain (not objects)
//llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 1);
//llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.1);
//llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 5.0);
//llSetVehicleFlags(VEHICLE_FLAG_HOVER_UP_ONLY);

// non-zero buoyancy helps the airplane stay up
// set to zero if you don't want this crutch
llSetVehicleFloatParam(VEHICLE_BUOYANCY, .95);

// define these here for convenience later
// CUBEY - modified these as per Shadow's prefs


llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <500000000,500000000,500000000>);


// CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT |
gAngularControls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT;
gLinearControls = CONTROL_UP | CONTROL_DOWN | CONTROL_BACK | CONTROL_FWD;
llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - ensure that physics are disabled when plane is rezzed so it doesn't fly off
}

listen(integer channel, string name, key id, string message)
{
if(message == "/phant")
{
llVolumeDetect(TRUE);
}
if(message == "/phantoff")
{
llVolumeDetect(FALSE);
}
if(message == "h")
{
llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(1);
rotation rot = llGetRot();
vector rot1;
rot1 = RAD_TO_DEG * llRot2Euler(rot);
rot1.x = 0;
llSetRot(llEuler2Rot(DEG_TO_RAD * rot1));

llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.99);
llRemoveVehicleFlags(VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 1);
motor1 = TRUE;
llSetStatus(STATUS_PHYSICS, TRUE);
}
if(message == "i")
{
llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.01);
llSetVehicleFlags(VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .000001);
motor1 = FALSE;
}
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();

if (agent != llGetOwner())
{
// only the owner can use this vehicle
//llSay(0, "You aren't the owner -- only the owner can fly this plane.");
llUnSit(agent);
llPushObject(agent, <0,0,10>, ZERO_VECTOR, FALSE);
}
else if(agent == llGetOwner())
{
// clear linear motor on successful sit
gLinearMotor = <0, 0, 0>;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <500000000,500000000,500000000>);
//llSetStatus(STATUS_PHYSICS, TRUE);
llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 0.5);
llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 100000);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
llSetTimerEvent(1);
}
}
else
{
// stop the motors
gLinearMotor = <0, 0, 0>;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, gLinearMotor);

// use friction to stop the vehicle rather than pinning it in place
//llSetStatus(STATUS_PHYSICS, FALSE);
llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1.0);
llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1.0);

// driver is getting up
llReleaseControls();
//llStopAnimation("suitcase");
llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - turn off physics to make sure the parked plane can't be moved
llSetTimerEvent(0);
}


}

timer()
{
gLinearMotor = <.1, 0, 0>;
llMessageLinked(LINK_SET, 1, "", "");
//llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
//if(motor1)
//llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,0>);
}

run_time_permissions(integer perm)
{
if (perm)
{
//llStartAnimation("suitcase");
llTakeControls(gLinearControls | gAngularControls, TRUE, FALSE);
llSetStatus(STATUS_PHYSICS, TRUE); //CUBEY - enable physics when avatar sits
//llSensorRepeat("", llGetOwner(), AGENT, 96, PI, .1);
}
}



control(key id, integer level, integer edge)
{
//llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.01);
//llRemoveVehicleFlags(VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
llMessageLinked(LINK_SET, 1, "", "");
// only change linear motor if one of the linear controls are pressed
vector motor;
integer motor_changed = level & gLinearControls;
gLinearMotor = <0,0,0>;
if (motor_changed)
{
if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
//if (gLinearMotor.y < 0)
{
// gLinearMotor.y = 0;
}
//else if (gLinearMotor.y < 9000)
{
//gLinearMotor.y -= 50;
llMoveToTarget(llGetPos() + <0,-10,0>, .2);
}
motor_changed = TRUE;
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
//if (gLinearMotor.y < 0)
{
// gLinearMotor.y = 0;
}
// else if (gLinearMotor.y < 9000)
{
//gLinearMotor.y += 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_UP) //CUBEY
{
//llMoveToTarget(llGetPos() + <0,0,1>, .1);
if (gLinearMotor.z < 0)
{
gLinearMotor.z = 0;
}
else if (gLinearMotor.z < 9000)
{
gLinearMotor.z += 50;
}
motor_changed = TRUE;
}

if(level & CONTROL_FWD) //CUBEY
{
if (gLinearMotor.x < 0)
{
gLinearMotor.x = 0;
}
else if (gLinearMotor.x < 9000)
{
gLinearMotor.x += 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_BACK) //CUBEY
{
//if (gLinearMotor.x > 0)
{
//gLinearMotor.x = 0;
}
//else if (gLinearMotor.x > -9000)
{
gLinearMotor.x -= 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_DOWN) //CUBEY
{
if (gLinearMotor.z > 0)
{
gLinearMotor.z = 0;
}
else if (gLinearMotor.z > -9000)
{
gLinearMotor.z -= 50;
}
motor_changed = TRUE;
}
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
}

// only change angular motor if the angular levels have changed
motor_changed = (edge & gOldAngularLevel) + (level & gAngularControls);
if(motor1)
{
//motor = <0,0,0>;
if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{


// add roll component ==> triggers banking behavior
motor.x += 10;
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{

motor.x -= 10;
}
if(motor1)
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, motor);

else if(!motor1)
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <10, 10, 10>);
}

// store the angular level history for the next control callback
gOldAngularLevel = level & gAngularControls;
}
}

lmho Impfondo
Registered User
Join date: 7 Apr 2005
Posts: 31
05-25-2005 10:12
Here is the turret script

CODE



string gBulletName = "Bullet";

float gBulletSpeed = 75.0;
integer gBulletDamage = 50;


vector gAimOffset = <0.0, 0.0, 0.0>;

integer keylock = FALSE;

key agent;

string accept = " ";

key TargetKey;
string end;
integer true = FALSE;
integer true1 = FALSE;


integer motor1 = FALSE;
integer gAngularControls = 0;
integer gLinearControls = 0;


integer gOldAngularLevel = 0;


vector gLinearMotor = <0, 0, 0>;

default
{
touch_start(integer total)
{
if(llDetectedKey(0) == llGetOwner())
{
//llResetScript();
}
}
on_rez(integer i)
{
llResetScript();
}
state_entry()
{
llSetStatus(STATUS_PHYSICS, TRUE);
llVolumeDetect(TRUE);
//llMessageLinked(LINK_SET, 1, "", "");
llListen(909879001, "", "", "");
llListen(0, "", llGetOwner(), "");
llSetSitText("Fly");
llCollisionSound("", 0.0);
llSetText("\n", <1,1,1>, 1);

llSitTarget(<0.0, 0.0, .1>, ZERO_ROTATION);
llSetCameraEyeOffset(<-10.0, 0.0, 3.0> );
llSetCameraAtOffset(<3.0, 0.0, 1.0> );

llSetVehicleType(VEHICLE_TYPE_AIRPLANE);

// weak angular deflection
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.75);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 1.0);

// strong linear deflection
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.2);

// somewhat responsive linear motor
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.5);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, .1);

// somewhat responsive angular motor, but with 3 second decay timescale
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.00001);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .00001);


llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, .25);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, .1);

llSetVehicleFlags(VEHICLE_FLAG_MOUSELOOK_STEER | VEHICLE_FLAG_CAMERA_DECOUPLED);
//llRemoveVehicleFlags(VEHICLE_FLAG_CAMERA_DECOUPLED | VEHICLE_FLAG_MOUSELOOK_STEER);


//llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.99); // medium strength
//llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); // very responsive
//llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.01); // more banking when moving

//llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE);

// hover can be better than sliding along the ground during takeoff and landing
// but it only works over the terrain (not objects)
//llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 1);
//llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.1);
//llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 5.0);
//llSetVehicleFlags(VEHICLE_FLAG_HOVER_UP_ONLY);

// non-zero buoyancy helps the airplane stay up
// set to zero if you don't want this crutch
llSetVehicleFloatParam(VEHICLE_BUOYANCY, .95);


llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <500000000,500000000,500000000>);


// CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT |
gAngularControls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT;
gLinearControls = CONTROL_UP | CONTROL_DOWN | CONTROL_BACK | CONTROL_FWD | CONTROL_ML_LBUTTON;
//llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - ensure that physics are disabled when plane is rezzed so it doesn't fly off
}

listen(integer channel, string name, key id, string message)
{
if(message == "/phant")
{
llVolumeDetect(TRUE);
}
if(message == "/phantoff")
{
llVolumeDetect(FALSE);
}


if(channel == 909879001 && llGetSubString(message, 0, 3) == "key:" && keylock != TRUE)
{
TargetKey = (key)llGetSubString(message, 4, -1);
llSensorRepeat("", TargetKey, SCRIPTED | ACTIVE | PASSIVE, 96, PI, .1);
keylock = TRUE;
}

if(llGetSubString(message, 0, 5) == "/admit")
{

llUnSit(agent);
accept = llGetSubString(message, 7, -1);
llWhisper(0, accept);
}


}

no_sensor()
{
llDie();
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
agent = llAvatarOnSitTarget();
if(agent != NULL_KEY)
{
if (accept != llKey2Name(agent))
{
// only the owner can use this vehicle
//llSay(0, "You aren't the owner -- only the owner can fly this plane.");
llUnSit(agent);
llPushObject(agent, <0,0,10>, ZERO_VECTOR, FALSE);
}
else if(accept == llKey2Name(agent))
{
// clear linear motor on successful sit
gLinearMotor = <0, 0, 0>;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <500000000,500000000,500000000>);
//llSetStatus(STATUS_PHYSICS, TRUE);
llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 0.5);
llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 100000);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
llSetTimerEvent(1);
}
}
}
else
{
// stop the motors
gLinearMotor = <0, 0, 0>;
//llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
//llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, gLinearMotor);

// use friction to stop the vehicle rather than pinning it in place
//llSetStatus(STATUS_PHYSICS, FALSE);
//llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1.0);
//llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1.0);

// driver is getting up
llReleaseControls();
//llStopAnimation("suitcase");
//llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - turn off physics to make sure the parked plane can't be moved
llSetTimerEvent(0);
}


}



timer()
{
gLinearMotor = <.1, 0, 0>;
llMessageLinked(LINK_SET, 1, "", "");
//llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
//if(motor1)
//llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,0>);
}

run_time_permissions(integer perm)
{
if (perm)
{
//llStartAnimation("suitcase");
llTakeControls(gLinearControls | gAngularControls, TRUE, FALSE);
llSetStatus(STATUS_PHYSICS, TRUE); //CUBEY - enable physics when avatar sits
//llSensorRepeat("", llGetOwner(), AGENT, 96, PI, .1);
//llSensorRepeat("Cyrus Therian", "", AGENT, 96, PI, .1);
}
}

sensor(integer total)
{
llMoveToTarget(llDetectedPos(0) + <0,0,5>, .1);
}

control(key id, integer level, integer edge)
{
//llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.01);
//llRemoveVehicleFlags(VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
llMessageLinked(LINK_SET, 1, "", "");
// only change linear motor if one of the linear controls are pressed
vector motor;
integer motor_changed = level & gLinearControls;
gLinearMotor = <0,0,0>;
if (motor_changed)
{
if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
//if (gLinearMotor.y < 0)
{
// gLinearMotor.y = 0;
}
//else if (gLinearMotor.y < 9000)
{
//gLinearMotor.y -= 50;
//llMoveToTarget(llGetPos() + <0,-10,0>, .2);
}
motor_changed = TRUE;
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
//if (gLinearMotor.y < 0)
{
// gLinearMotor.y = 0;
}
// else if (gLinearMotor.y < 9000)
{
//gLinearMotor.y += 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_UP) //CUBEY
{
//llMoveToTarget(llGetPos() + <0,0,1>, .1);
if (gLinearMotor.z < 0)
{
gLinearMotor.z = 0;
}
else if (gLinearMotor.z < 9000)
{
gLinearMotor.z += 50;
}
motor_changed = TRUE;
}

if(level & CONTROL_FWD) //CUBEY
{
if (gLinearMotor.x < 0)
{
gLinearMotor.x = 0;
}
else if (gLinearMotor.x < 9000)
{
gLinearMotor.x += 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_BACK) //CUBEY
{
//if (gLinearMotor.x > 0)
{
//gLinearMotor.x = 0;
}
//else if (gLinearMotor.x > -9000)
{
gLinearMotor.x -= 50;
}
motor_changed = TRUE;
}
if(level & CONTROL_DOWN) //CUBEY
{
if (gLinearMotor.z > 0)
{
gLinearMotor.z = 0;
}
else if (gLinearMotor.z > -9000)
{
gLinearMotor.z -= 50;
}
motor_changed = TRUE;
}
//llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor);
}

// only change angular motor if the angular levels have changed

llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <10, 10, 10>);

if (!(level & CONTROL_ML_LBUTTON) && (edge & CONTROL_ML_LBUTTON))
{

rotation rot = llGetRot();
vector aim = llRot2Fwd(rot);
vector pos = llGetPos() + gAimOffset + (aim * 1.0);
llRezObject(gBulletName, pos, aim * gBulletSpeed, rot, gBulletDamage);
}

// store the angular level history for the next control callback
gOldAngularLevel = level & gAngularControls;
}
}