Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Multimove hits version 3 !

Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
03-17-2006 02:49
This update has very little to do with the move to SL V1.9 ;)

As always, this set of scripts is designed to allow turning a big build composed of multiple objects (=multiple linksets) into a vehicle.

Alright, changes in this version:
- rotation of the main object now controls all the other objects' rotation. This means I can add fancy things like mouselook control in the near future
- simultaneous use of remote and control should be possible now
- movement has been smoothed out for finer control, the vehicle now accelerates and decelerates in finer steps

Control script (this one goes in the seat child prim of your main object, you will need to adapt the sit target and camera offset parameters in this script)
CODE

// MultiMove Controller Script
//
// Manages pilot seat and movement for the whole set

integer unichan = -79997; // this is the channel used by the controller and
// objects to sync and move

float deltat = 0.1; // interval between updates

integer controlstaken; // control keys taken by the script, initialised later

integer listener;
integer maxl = 4;

integer pressed;
integer change;

vector sitoffset = <0.2,0,-0.5>; // sitting position
vector camoffset = <-24,0,9>; // camera position
vector camtarget = <12,0,0>; // camera direction
float speed = 2.0; // distance to move within deltat
float vspeed = 1.0; // vertical distance to move within deltat
float rspeed = 0.3183; // angle in degrees to rotate left or right within deltat
float inertia = 0.8;
float moment = 0.5;

vector velocity;
float rotacity;

vector accel = <0.125, 0.125, 0.06125>;
float raccel = 0.06125;

rotation rtarget;

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

state_entry()
{
llMinEventDelay(deltat);
llSitTarget(sitoffset, ZERO_ROTATION);
llSetCameraAtOffset(camtarget);
llSetCameraEyeOffset(camoffset);
controlstaken = CONTROL_FWD|CONTROL_BACK|CONTROL_ROT_LEFT|CONTROL_ROT_RIGHT|CONTROL_LEFT|CONTROL_RIGHT|CONTROL_UP|CONTROL_DOWN;
}

changed(integer c)
{
if (c & CHANGED_LINK)
{
key id = llAvatarOnSitTarget();
if (id != NULL_KEY)
{
if (id == llGetOwner())
{
llRequestPermissions(id, PERMISSION_TAKE_CONTROLS);
} else llUnSit(id);
} else {
llReleaseControls();
llSetTimerEvent(0.0);
}
}
}

run_time_permissions(integer p)
{
if (p & PERMISSION_TAKE_CONTROLS)
{
integer n;
rtarget = llGetRootRotation();
velocity = ZERO_VECTOR;
rotacity = 0.0;
for (n=0; n<maxl; ++n)
llShout(unichan + n, (string)(llGetRootPosition() + llGetRegionCorner()) + "*" + (string)rtarget);

llSleep(1.0);
llTakeControls(controlstaken, TRUE, FALSE);
llSetTimerEvent(deltat);
} else {
llReleaseControls();
}
}

control(key id, integer level, integer edge)
{
pressed = level;
//change = edge;
}

timer()
{
vector target = llGetRootPosition() + llGetRegionCorner();
rotation rtarget = llGetRootRotation();

if (pressed)
{
if (pressed & CONTROL_ROT_RIGHT)
{
// turning left
rotacity -= raccel;
if (rotacity < -rspeed) rotacity = -rspeed;
} else if (pressed & CONTROL_ROT_LEFT)
{
// turning right
rotacity += raccel;
if (rotacity > rspeed) rotacity = rspeed;
} else rotacity *= moment;

if (pressed & CONTROL_FWD)
{
// going forward
velocity.x += accel.x;
if (velocity.x > speed) velocity.x = speed;
} else if (pressed & CONTROL_BACK)
{
// going backward
velocity.x -= accel.x;
if (velocity.x < -speed) velocity.x = -speed;
} else velocity.x *= inertia;

if (pressed & CONTROL_UP)
{
// going up
velocity.z += accel.z;
if (velocity.z > vspeed) velocity.z = vspeed;
} else if (pressed & CONTROL_DOWN)
{
// going down
velocity.z -= accel.z;
if (velocity.z < -vspeed) velocity.z = -vspeed;
} else velocity.z *= inertia;

if (pressed & CONTROL_LEFT)
{
// going up
velocity.y += accel.y;
if (velocity.y > speed) velocity.y = speed;
} else if (pressed & CONTROL_RIGHT)
{
// going down
velocity.y -= accel.y;
if (velocity.y < -speed) velocity.y = -speed;
} else velocity.y *= inertia;
} else {
velocity *= inertia;
rotacity *= moment;
}

rtarget *= llEuler2Rot(<0,0,rotacity>);
target += velocity * rtarget;

if ((velocity.x == 0.0) && (velocity.y == 0.0) && (velocity.z == 0.0) && (rotacity == 0.0))
return;

listener = (listener + 1) % maxl;
llShout(unichan + listener, (string)target + "*" + (string)rtarget);
}
}


Remote script (put this one in any child prim of your main build, IM me for the RemoteHUD object or indications on how to make one)
CODE

// Multimove Autopilot
//
// For navigating big space cruisers

integer unichan = -79997;
integer listener;
integer maxl = 4;
float rate = 0.1;
integer my_chan = 128;
integer handle;
string opt;
list buttons;

integer vel;
integer vvel;
integer lvel;
integer rvel;

float speed = 2.0;
float vspeed = 1.0;
float lspeed = 1.0;
float rspeed = 0.3183;
float inertia = 0.8;
float moment = 0.5;

vector velocity;
float rotacity;

vector accel = <0.125, 0.125, 0.06125>;
float raccel = 0.06125;

rotation rtarget;

default
{
on_rez(integer p)
{
llSleep(2.0);
llResetScript();
}

state_entry()
{
llSetTimerEvent(0.0);
velocity = ZERO_VECTOR;
rotacity = 0.0;
rtarget = llGetRootRotation();
vel = 0;
vvel = 0;
lvel = 0;
rvel = 0;
opt = "";
buttons = [];
for (listener = 0; listener < maxl; listener = listener + 1)
llShout(unichan + listener, (string)(llGetRootPosition() + llGetRegionCorner()) + "*" + (string)rtarget);
handle = llListen(my_chan, "", "", "");
}

listen(integer chan, string name, key id, string msg)
{
if ((llGetOwner() != id) && (llGetOwnerKey(id) != llGetOwner())) return;

string t = llGetSubString(msg, 0, 0);

if (t == "m") { vel = (integer)llDeleteSubString(msg, 0, 0); llSetTimerEvent(rate); } else
if (t == "v") { vvel = (integer)llDeleteSubString(msg, 0, 0); llSetTimerEvent(rate); } else
if (t == "l") { lvel = (integer)llDeleteSubString(msg, 0, 0); llSetTimerEvent(rate); } else
if (t == "r") { rvel = (integer)llDeleteSubString(msg, 0, 0); llSetTimerEvent(rate); } else
if (t == "k") { llSetTimerEvent(0.0); llShout(unichan, "k"); }
}

timer()
{
vector pos = llGetRootPosition() + llGetRegionCorner();
listener = (listener + 1) % maxl;

if (rvel != 0)
{
rotacity += rvel * raccel;
if (rotacity > rspeed) rotacity = rspeed;
if (rotacity < -rspeed) rotacity = -rspeed;
} else rotacity *= moment;

if (vel != 0)
{
velocity.x += vel * accel.x;
if (velocity.x > speed) velocity.x = speed;
if (velocity.x < -speed) velocity.x = -speed;
} else velocity.x *= inertia;

if (vvel != 0)
{
velocity.z += vvel * accel.z;
if (velocity.z > vspeed) velocity.z = vspeed;
if (velocity.z < -vspeed) velocity.z = -vspeed;
} else velocity.z *= inertia;

if (lvel != 0)
{
velocity.y += lvel * accel.y;
if (velocity.y > lspeed) velocity.y = lspeed;
if (velocity.y < -lspeed) velocity.y = -lspeed;
} else velocity.y *= inertia;

if (rotacity != 0.0)
{
rtarget = llGetRootRotation() * llEuler2Rot(<0,0,rotacity>);
} else {
if ((velocity.x == 0.0) && (velocity.y == 0.0) && (velocity.z == 0.0)) llSetTimerEvent(0.0);
}
llShout(unichan + listener, (string)(pos + velocity * rtarget) + "*" + (string)rtarget);
}
}


Move (copy this script four times, called move 0, move 1, move 2, move 3; put all four copies in EACH linkset's root prim)
CODE

// Move
//
// Multimove follower

integer unichan = -79997; // this is the channel used by the controller and
// objects to sync

integer handle; // handle for the listen function

vector my_offset; // original offset, set at first activation
rotation my_orientation; // original rotation, set at first activation
integer my_num; // position in the chain of redundancy
float azimut;

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

state_entry()
{
my_num = (integer)llGetSubString(llGetScriptName(), -1, -1);
handle = llListen(unichan + my_num, "", "", "");
}

listen(integer chan, string name, key id, string mesg)
{
if (mesg == "k") llDie();
if (mesg == "s") return;

integer index = llSubStringIndex(mesg, "*");

my_offset = llGetPos() + llGetRegionCorner() - (vector)llGetSubString(mesg, 0, index - 1);
my_orientation = llGetRot() / (rotation)(llDeleteSubString(mesg, 0, index));
my_offset = my_offset / llGetRot();
state running;
}

state_exit()
{
llListenRemove(handle);
}
}

state running
{
on_rez(integer p)
{
state default;
}

state_entry()
{
handle = llListen(unichan + my_num, "", "", "");
}

listen(integer chan, string name, key id, string mesg)
{
if (mesg == "k")
{
llDie();
} else if (mesg == "s")
{
state default;
} else {
list info = llParseString2List(mesg, ["*"], []);
rotation rtarget = my_orientation * (rotation)llList2String(info, 1);
vector target = my_offset * rtarget + (vector)llList2String(info, 0) - llGetRegionCorner();
llSetPrimitiveParams([PRIM_POSITION, target, PRIM_ROTATION, rtarget]);
}
}

state_exit()
{
llListenRemove(handle);
}
}
_____________________
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
03-17-2006 13:50
[Edit]There, fixed :)
_____________________
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.
Brookston Holiday
Registered User
Join date: 29 May 2005
Posts: 58
04-12-2006 10:54
HEllo-

I'm trying out these scripts and was wondering if you could tell me why, when i go into mouslook view, suddenly the left right controls slew the craft left and right, but outside of mouselook, they rotate it.

thanks
Tre Giles
Registered User
Join date: 16 Dec 2005
Posts: 294
04-12-2006 11:18
HEY again Jesrad, the problem I have with the multimove is only one, sim border crossing. Unless there was an update before this, the multimove couldn't cross sims and always froze my giant crafts in midspace ( >.< ), Can this one cross sim boundries?
scubadiver Albert
Registered User
Join date: 8 Oct 2006
Posts: 24
10-11-2006 09:07
does this system still allow things like turrets to move on its own but stay on the same spot of a ship?

if it does it is wkd because then i can build a ship with a turret (albeit the lack of a turret script).
scubadiver Albert
Registered User
Join date: 8 Oct 2006
Posts: 24
10-15-2006 02:27
i did what you said but it doesn't work can you please explain in a bit more depth please because its saying wrong bound error.
ScriptScavenger Lei
Registered User
Join date: 3 Sep 2006
Posts: 14
buffer issue
11-05-2006 18:42
From: Tre Giles
HEY again Jesrad, the problem I have with the multimove is only one, sim border crossing. Unless there was an update before this, the multimove couldn't cross sims and always froze my giant crafts in midspace ( >.< ), Can this one cross sim boundries?

i dont recall where ive seen it but...
theres a 10 m buffer between sims if the object attempting to pass through this buffer larger than 10 m tends to fly appart
apperently now it also stops u dead perhaps there attempting to correct the problem and the fix isnt implemented or functioning correctly