Non physical vehicle scripts
|
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
|
08-30-2005 00:43
Here is a set of scripts I am using to make non physical flying vehicles that move relatively smoothly. They all go into the root prim of your object. Control script (manages controls): // Non-Physical Flying Vehicle // A.K.A: How to exploit tricks in LSL to get your way // // (your way being: up to 254 prims on a vehicle, in this case) // Author: Jesrad Seraph // Modify and redistribute freely, as long as your permit free modification and redistribution
float max_fwd_vel = 8.0; // how fast this vehicle can go horizontally, per step float max_vert_vel = 4.0; // how fast this vehicle can go vertically, per step float max_rot_vel = 12.0; // how fast this vehicle can turn, per step float fwd_increment = 4.0; // by how much it will accelerate at each step until reaching max_fwd_vel float vert_increment = 2.0; // by how much it will accelerate at each step until reaching max_vert_vel float rot_increment = 4.0; // by how much it will accelerate at each step until reaching max_rot_vel
integer active; vector velocity;
integer down; integer change;
default { state_entry() { active = FALSE; velocity = ZERO_VECTOR; llSetObjectDesc("<0,0,0>"); llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); }
touch_start(integer c) { if (llDetectedKey(0) != llGetOwner()) return; if (active) { llReleaseControls(); llSetTimerEvent(0.0); active = FALSE; llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); } else { llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS); } }
run_time_permissions(integer p) { if (p) { llTakeControls(CONTROL_FWD|CONTROL_BACK|CONTROL_ROT_LEFT|CONTROL_ROT_RIGHT|CONTROL_LEFT|CONTROL_RIGHT|CONTROL_UP|CONTROL_DOWN, TRUE, FALSE); llSetTimerEvent(0.1); active = TRUE; llSetScriptState("move", TRUE); llSetScriptState("turn", TRUE); } else { llReleaseControls(); llSetTimerEvent(0.0); active = FALSE; llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); } }
control(key id, integer pressed, integer switched) { down = pressed; change = switched; }
timer() { if (down & CONTROL_FWD) { if (velocity.x < max_fwd_vel) { velocity.x += fwd_increment; } } else if (down & CONTROL_BACK) { if (velocity.x > -max_fwd_vel) { velocity.x -= fwd_increment; } } else { if (velocity.x < 0) { velocity.x += fwd_increment; } else if (velocity.x > 0) { velocity.x -= fwd_increment; } } if (down & CONTROL_UP) { if (velocity.z < max_vert_vel) { velocity.z += vert_increment; } } else if (down & CONTROL_DOWN) { if (velocity.z > -max_vert_vel) { velocity.z -= vert_increment; } } else { if (velocity.z < 0) { velocity.z += vert_increment; } else if (velocity.z > 0) { velocity.z -= vert_increment; } }
if (down & (CONTROL_LEFT|CONTROL_ROT_LEFT)) { if (velocity.y < max_rot_vel) { velocity.y += rot_increment; } } else if (down & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) { if (velocity.y > -max_rot_vel) { velocity.y -= rot_increment; } } else { if (velocity.y > 0) { velocity.y -= rot_increment; } else if (velocity.y < 0) { velocity.y += rot_increment; } }
llSetObjectDesc((string)(velocity)); } }
Movement script (reads the position offset in the object's description, running a perpetual loop): default { state_entry() { vector t; llSleep(0.2); // this is to let the control script stop it from running while(TRUE) { t = (vector)llGetObjectDesc(); t.y = 0.0; llSetPos(llGetPos() + t * llGetRot()); t = (vector)llGetObjectDesc(); t.y = 0.0; llSetPos(llGetPos() + t * llGetRot()); t = (vector)llGetObjectDesc(); t.y = 0.0; llSetPos(llGetPos() + t * llGetRot()); t = (vector)llGetObjectDesc(); t.y = 0.0; llSetPos(llGetPos() + t * llGetRot()); t = (vector)llGetObjectDesc(); t.y = 0.0; llSetPos(llGetPos() + t * llGetRot()); } } }
Turning script (reads the rotation speed from object's description, running a perpetual loop): default { state_entry() { vector t; llSleep(0.2); // this is to let the control script stop it from running while(TRUE) { t = (vector)llGetObjectDesc(); llSetRot(llGetRot() * llEuler2Rot(<0,0,DEG_TO_RAD * t.y>)); t = (vector)llGetObjectDesc(); llSetRot(llGetRot() * llEuler2Rot(<0,0,DEG_TO_RAD * t.y>)); t = (vector)llGetObjectDesc(); llSetRot(llGetRot() * llEuler2Rot(<0,0,DEG_TO_RAD * t.y>)); t = (vector)llGetObjectDesc(); llSetRot(llGetRot() * llEuler2Rot(<0,0,DEG_TO_RAD * t.y>)); t = (vector)llGetObjectDesc(); llSetRot(llGetRot() * llEuler2Rot(<0,0,DEG_TO_RAD * t.y>)); } } }
Originally the control script would be starting and stopping the other two scripts, but this caused the vehicle to stop operating partly after crossing a sim border  I have put this back but only when the controls are taken or released instead. That should save a bit of lag when you are not using the vehicle. I discovered that the object's description is the only truely versatile property that all scripts can set and get... I wanted to use llSetForce and llSetTorque to send over the offset and rotation speed, but they don't even get set on non-physical objects (I thought they would even if they'd not do anything)  Another method is to use the color of a hidden internal face of the root prim and scale it back in the movement and turning scripts. Your mileage may vary. Other thing to try: using more perpetually-looping scripts to refine the movement a bit. Duplicate the two scripts and change their "llSleep(0.2);" call with "llSleep(0.3);". Another note: don't set max_vert_vel and max_fwd_vel to values over 10 ! A non-physical object can only move 10m per call to llSetPos, so when moving forward and up/down at the same time you're moving Sqrt(max_fwd_vel**2 + max_vert_vel**2), which WILL be more than 10m if you increase any of these settings and your object's speed will then be clamped down to 10m per step.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
|
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
|
08-31-2005 05:30
Well, I just went and incorporated the changes I suggested in the previous post. The end result was tested in Balance yesterday and works great  You may have to change the hidden_face parameter to be the number of an hidden (but not unused, this face must exist on the root prim or the script will throw an error) face. I suggest hollowing out your root prim and using this internal face. The difference with the previous scripts is that the maximum speed is now set in the "move" and "turn" scripts. NOTE: now we're using doubled scripts: "move" and "move2" for position, "turn" and "turn2" for rotation. Usage: drop all these in your vehicle, take the vehicle to your inventory, then rez a copy whenever you feel like using it. Control script: // Non-Physical Flying Vehicle // A.K.A: How to exploit tricks in LSL to get your way // // (your way being: up to 254 prims on a vehicle, in this case) // Author: Jesrad Seraph // Modify and redistribute freely, as long as your permit free modification and redistribution
float fwd_increment = 0.25; // fraction of the max horizontal velocity added when accelerating float vert_increment = 0.1; // fraction of the max vertical velocity added when accelerating float rot_increment = 0.25; // fraction of the max rotational velocity added when accelerating
float max_fwd_vel = 1.0; // max forward speed is 100% of the max_vel parameter set in move float max_vert_vel = 0.7; // max vertical speed is 70% of the max_vel parameter set in move
integer active; vector velocity;
float rotacity; integer down; integer change;
default { on_rez(integer p) { active = FALSE; velocity = <0.5, 0.5, 0.5>; rotacity = 0.5; llSetPrimitiveParams([PRIM_COLOR, hidden_face, velocity, rotacity]); llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); }
touch_start(integer c) { if (llDetectedKey(0) != llGetOwner()) return; if (active) { llReleaseControls(); llSetTimerEvent(0.0); active = FALSE; llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); } else { llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS); } }
run_time_permissions(integer p) { if (p) { llTakeControls(CONTROL_FWD|CONTROL_BACK|CONTROL_ROT_LEFT|CONTROL_ROT_RIGHT|CONTROL_LEFT|CONTROL_RIGHT|CONTROL_UP|CONTROL_DOWN, TRUE, FALSE); llSetTimerEvent(0.1); active = TRUE; velocity = <0.5, 0.5, 0.5>; rotacity = 0.5; llSetColor(velocity, hidden_face); llSetAlpha(rotacity, hidden_face); llSetScriptState("move", TRUE); llSetScriptState("turn", TRUE); } else { llReleaseControls(); llSetTimerEvent(0.0); active = FALSE; llSetScriptState("move", FALSE); llSetScriptState("turn", FALSE); } }
control(key id, integer pressed, integer switched) { down = pressed; change = switched; }
timer() { if (down & CONTROL_FWD) { if (velocity.x < max_fwd_vel) { velocity.x += fwd_increment; } } else if (down & CONTROL_BACK) { if (velocity.x > (1.0 - max_fwd_vel)) { velocity.x -= fwd_increment; } } else { if (velocity.x < 0.5) { velocity.x += fwd_increment; } else if (velocity.x > 0.5) { velocity.x -= fwd_increment; } } if (down & CONTROL_UP) { if (velocity.z < max_vert_vel) { velocity.z += vert_increment; } } else if (down & CONTROL_DOWN) { if (velocity.z > (1.0 - max_vert_vel)) { velocity.z -= vert_increment; } } else { if (velocity.z < 0.5) { velocity.z += vert_increment; } else if (velocity.z > 0.5) { velocity.z -= vert_increment; } }
if (down & (CONTROL_LEFT|CONTROL_ROT_LEFT)) { if (velocity.y < 1.0) { velocity.y += rot_increment; } } else if (down & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) { if (velocity.y > 0.0) { velocity.y -= rot_increment; } } else { if (velocity.y > 0.5) { velocity.y -= rot_increment; } else if (velocity.y < 0.5) { velocity.y += rot_increment; } }
llSetColor(velocity, hidden_face); llSetAlpha(rotacity, hidden_face); } }
move: float max_vel = 5.0; integer hidden_face = 1;
default { on_rez(integer p) { llSleep(0.2); // this is to let the control script stop it from running while(TRUE) { llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) + llGetPos()); } } }
move2 is the same as move but with llSleep(0.3); turn: integer hidden_face = 1; float max_vel = 0.6;
default { on_rez(integer p) { llSleep(0.2); // this is to let the control script stop it from running while(TRUE) { llSetRot(llGetRot() * llEuler2Rot(<0,0,max_vel * (llGetAlpha(hidden_face) - 0.5)>) ); llSetRot(llGetRot() * llEuler2Rot(<0,0,max_vel * (llGetAlpha(hidden_face) - 0.5)>) ); llSetRot(llGetRot() * llEuler2Rot(<0,0,max_vel * (llGetAlpha(hidden_face) - 0.5)>) ); llSetRot(llGetRot() * llEuler2Rot(<0,0,max_vel * (llGetAlpha(hidden_face) - 0.5)>) ); llSetRot(llGetRot() * llEuler2Rot(<0,0,max_vel * (llGetAlpha(hidden_face) - 0.5)>) ); } } }
turn2 is the same as turn but with llSleep(0.3);
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
09-06-2005 15:43
Trying to understand how this works, and I have a couple of questions.
1. I assume the 5 steps in each loop is to get around the built-in loop sleep/delay? How long is that delay? Visually, how much does this smoothen the movement compared to doing just one step per loop iteration? Just trying to get a rough feel for how long that delay is compared to the 0.2s hit per SetPos/SetRot call.
2. The while loops in the movement and turning scripts - those will continue executing even if the vehicle is standing still, right? Or did I misunderstand how this works. The scripts are started/stopped only when permissions change, so as soon as permissions are granted, the scripts will start running. Let's say the vehicle is moving forward and the user lets off the up arrow key. The timer in the control script will decrement the velocity down to 0, and then the velocity will stay at 0. The two movement scripts will still keep processing that, and will effectively call llSetPos(llGetPos()) over and over again. Same for the two rotation scripts. Is that right, or have I completely misunderstood how this is working?
I've been thinking about this recently, how to make non-physics movement stop. A while loop produces the (visually) smoothest movement I've seen, but the problem is, there's no way to stop it unless you know the movement/rotation target ahead of time. Changing while (TRUE) to while (Moving) doesn't help, because no one will update the Moving variable once you enter the while loop. The only thing that I can think of which will work is to move on a timer event. A 0.2s timer will probably back up the queue because it'll take more than 0.2s to do the math and make the SetPos/SetRot call. So maybe a 0.21s timer, or 0.25 for safety. And then you can handle other events, and set the Moving variable, or do whatever else it takes to decide that the vehicle isn't moving any more. If anyone knows of a different way to do this, I'd love to learn it.
|
Ursula Madison
Chewbacca is my co-pilot
Join date: 31 Jul 2004
Posts: 713
|
09-12-2005 01:44
I was playing around some with these scripts...
Everything seems to work just peachy, except instead of actually turning left and right, the vehicle strafes left and right, always pointing east no matter what. Is that the intended behavior?
_____________________
"Huh... did everything just taste purple for a second?" -- Philip J. Fry
|
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
|
09-12-2005 02:11
Sorry Ursula, I forgot an important piece of code in the move script  Here's the fixed one: float max_vel = 5.0; integer hidden_face = 1;
default { on_rez(integer p) { llSleep(0.2); // this is to let the control script stop it from running while(TRUE) { llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) * llGetRot() + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) * llGetRot() + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) * llGetRot() + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) * llGetRot() + llGetPos()); llSetPos(max_vel * (llGetColor(hidden_face) - <0.5, 0.5, 0.5>) * llGetRot() + llGetPos()); } } }
Same for Move2, with llSleep(0.3); Ziggy, this script does not need to tell in advance the speed to the looping llSetPos of the move scripts, instead it continually updates the speed by using a simple trick: the speed is read at each move from the color of a hidden face in the root prim  This way I can change the offset that is continually applied by the parallelly-run loops in both move scripts. You are right that once set to zero the speed keeps getting added continually every 0.1 second in average to the vehicle... I have set the scripts to stop running when the pilot stands up to avoid this to go on all the time. Fortunately if an object's position is updated to the exact same position, no client update is sent. But it still does provide a bit of lag, true. There is a way around it, it is to simply put the timer() code into the control() event, apply a fixed speed with each control key, and stop the scripts whenever all keys are off. But then there is no acceleration/deceleration simulation possible.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
09-12-2005 08:18
Thanks.
|
Stuna213 Absolute
Member
Join date: 8 Jun 2005
Posts: 99
|
09-19-2005 16:52
i cant get it to work! i touch it, and give it permission to act on my control inputs... but all it does is change color on one side... what am i doing wrong?
|
Stuna213 Absolute
Member
Join date: 8 Jun 2005
Posts: 99
|
09-19-2005 16:55
it says it couldnt find script move and turn, but there inside it spelled correctly with correct capitolization.
|
Harke Hartnell
Registered User
Join date: 10 Nov 2005
Posts: 32
|
11-15-2005 17:22
Yes, I'm having trouble with this as well, the colors of the faces change, but I get no move ment on a single cube. Also, the main script doesn't have integer hidden_face; defined, had to put it in myself.
|
Robin Peel
Registered User
Join date: 8 Feb 2005
Posts: 163
|
11-16-2005 01:43
From: Harke Hartnell Yes, I'm having trouble with this as well, the colors of the faces change, but I get no move ment on a single cube. Also, the main script doesn't have integer hidden_face; defined, had to put it in myself. I had to give it a shot. I got it to move by renaming the move2 script to turn. But it wouldn't turn, the page up and page down made it go forward and reverse, the direction keys was up, down, move left and move right. i have to turn at all. lol
|
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
|
11-16-2005 11:21
As they are, these scripts suppose your root prim is a zero-rotated, hollowed sphere  IM me and I'll send you a working copy when I get back.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
|