Change font size
It is currently Tue Jul 17, 2018 11:38 pm

Forum rules


{L_IMAGE}



Post a new topicPost a reply Page 1 of 1   [ 10 posts ]
Author Message
 Post subject: Opensimulator Vehicle Scripting with LSL
PostPosted: Tue Feb 03, 2009 11:42 am 
Site Admin
User avatar

Joined: Sun Feb 03, 2008 9:10 am
Posts: 48
Location: Suburbia Americana in the Houston Texas area
Greetings!

As many of you may be aware, there are some limited vehicle scripting capabilities rumored to have been developed by one Owen Oyen (of OSGrid and Second Life), and myself.

I had promised some time ago to post my scripts here, in the clear, for my version of our work.

Unfortunately, time constraints have prevented my continuing work on the sailboats I so enjoy, so I have elected to take an earlier version of the script that implements a motorboat, and recode it as a primitive automobile motor prim.

Note that this is very crudely done, needs much more work to function properly and reliably as a vehicle, may or may not work the first time you try it, and will likely produce inconsistent and or unpredictable results.

Try at your own risk.
Use only as directed.
Your mileage may vary.
Failure to report as a standard deduction on your 1040EZ may result in prosecution by the IRS.

(Just kidding about that IRS part :twisted: )

Enough of my antics, here's the script:

{L_CODE}:
float gmass;
float up = 9.8 ;
float gleft;
float gright;
key g_owner;
float gvehiclespeed;

// llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

float XDRAGCOEFF=0.0025;
float YDRAGCOEFF=0.0025;
float ZDRAGCOEFF=1;

float gincrement;
integer g_leftrightflag;
integer gstart;
integer gchannel_num;
integer gtouch_toggle;
integer gtouchoff;
vector dragadjforces;
key g_agent;

applyFriction()
{
    vector rawforces = llGetForce();
    vector drag;
   
    llSay(0,"Raw Force: "+(string) rawforces);
   
    // calculate drag on all axis of motion
    drag.x = llFabs(XDRAGCOEFF * rawforces.x);
    drag.y = llFabs(YDRAGCOEFF * rawforces.y);
    drag.z = llFabs(ZDRAGCOEFF * rawforces.z);

    if(llFabs(rawforces.x) > llFabs(drag.x))
    {
        dragadjforces.x=rawforces.x + drag.x;
    }
    else
    {
        dragadjforces.x = 0;
    }

    if(llFabs(rawforces.y) > llFabs(drag.y))
    {
        dragadjforces.y=rawforces.y + drag.y;
    }
    else
    {
        dragadjforces.y = 0;
    }
   
    if(llFabs(rawforces.z) > llFabs(drag.z))
    {
        dragadjforces.z=rawforces.z + drag.z;
    }
    else
    {
        dragadjforces.z = 0;
    }
   
    llSay(0,"Drag Adj Force: "+(string) dragadjforces);
}

default
{
    state_entry()
    {
        rotation euler_sit_rot = llEuler2Rot (<0, 0, 0> * DEG_TO_RAD);
        llSetText("Owner\n Sit", <1.0, 1.0, 1.0>, 1.0);
        llSetSitText("Ride");   
        llSetAlpha(1,ALL_SIDES); 
        llSitTarget(<1.5, 0.0, 0.9>, euler_sit_rot);
        g_owner=llGetOwnerKey(llGetKey());
        llSetCameraEyeOffset(<-0.5,0.0,10.5>);
        llSetCameraAtOffset(<0.0,-0.0,0.0>);
       
        llSetStatus(STATUS_PHYSICS, FALSE);
       // llSetRot(<0,0,0,0>);
        llSetForce(<0,0,0>,TRUE);
        vector pos = llGetPos();
        float groundheight = llGround(pos);
        llSetPos(<pos.x, pos.y, groundheight+1>);

    }
   
    on_rez(integer numm)
    {
        llResetScript();
    }       
   
    touch_start(integer iii)
    {
        g_agent = llDetectedKey(0);
        llOwnerSay("touched" + (string)g_agent );
       
        if (g_agent == g_owner)
        {
            if (gtouch_toggle == 1)
            {
                llStopSound();
                gtouch_toggle = 0;
                gtouchoff = 1;
            }                           
            else
            {     
                gtouchoff = 0;
                if (llAvatarOnSitTarget()=="")
                {
                    llSay(0,"Resetting..");
                    llResetScript();
                }
                else
                {
                    llOwnerSay("agent= " + llKey2Name(g_agent));
                    gmass = llGetMass();
                    llRequestPermissions(g_agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
                    llSetTimerEvent(0.5);
                }
            }
        }
        else
        {
            llSay(0, "Sorry, you do not own this object.");
            llUnSit(g_agent);
            llResetScript();
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS)
        {
            llSetAlpha(0,ALL_SIDES);
            llStartAnimation("avatar_sit_generic-p2");
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
            llSetTimerEvent(0.5);
            llSetStatus(STATUS_PHYSICS, TRUE);
            // llSetBuoyancy(1);
         }
    }
   
    // ******* CHANGED *************   
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (llAvatarOnSitTarget()=="")
            {
                llSay(0,"Resetting..");
                llResetScript();
            }
        }
    }
     
    control(key id, integer held, integer changer)
    {
        if(held & CONTROL_FWD & changer)
        {
            gincrement+=2;
            if (gincrement > 10) gincrement = 10;
        }
       
        if(held & CONTROL_BACK & changer )
        {
            gincrement-=0.75;
            if (gincrement < -7) gincrement = -7;
        }
     
        if(held & (CONTROL_RIGHT|CONTROL_ROT_RIGHT) )
        {
            gright = -0.1; 
           
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);


            vector heading = pres_heading;

            heading.x = 0;  // tumble stop
            heading.y = 0;  // tumble stop
            heading.z += (gright);
            rot = llEuler2Rot(heading);

            llSetRot(rot);
        }

        if(held & (CONTROL_LEFT|CONTROL_ROT_LEFT) )
        {
            gleft = 0.1;
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);
            vector heading = pres_heading;
            heading.z += (gleft);
            rot = llEuler2Rot(heading);
            llSetRot(rot);
        }
       
        llSetStatus(STATUS_PHYSICS, TRUE);

        // Heading rotation
        llSetForce (gmass*<gincrement, 0, 0>, TRUE);
        llSetBuoyancy(1);
        // llOwnerSay("forwd inc ->"+(string)gincrement+" left/right  "+(string)(gleft) + " " + (string)gright);
    }
   
    timer()
    {
        llSetTimerEvent(0);
        llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

//        applyFriction();
//        llSetForce(dragadjforces,TRUE);float gmass;
float up = 9.8 ;
float gleft;
float gright;
key g_owner;
float gvehiclespeed;

// llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

float XDRAGCOEFF=0.0025;
float YDRAGCOEFF=0.0025;
float ZDRAGCOEFF=1;

float gincrement;
integer g_leftrightflag;
integer gstart;
integer gchannel_num;
integer gtouch_toggle;
integer gtouchoff;
vector dragadjforces;
key g_agent;

applyFriction()
{
    vector rawforces = llGetForce();
    vector drag;
   
    llSay(0,"Raw Force: "+(string) rawforces);
   
    // calculate drag on all axis of motion
    drag.x = llFabs(XDRAGCOEFF * rawforces.x);
    drag.y = llFabs(YDRAGCOEFF * rawforces.y);
    drag.z = llFabs(ZDRAGCOEFF * rawforces.z);

    if(llFabs(rawforces.x) > llFabs(drag.x))
    {
        dragadjforces.x=rawforces.x + drag.x;
    }
    else
    {
        dragadjforces.x = 0;
    }

    if(llFabs(rawforces.y) > llFabs(drag.y))
    {
        dragadjforces.y=rawforces.y + drag.y;
    }
    else
    {
        dragadjforces.y = 0;
    }
   
    if(llFabs(rawforces.z) > llFabs(drag.z))
    {
        dragadjforces.z=rawforces.z + drag.z;
    }
    else
    {
        dragadjforces.z = 0;
    }
   
    llSay(0,"Drag Adj Force: "+(string) dragadjforces);
}

default
{
    state_entry()
    {
        rotation euler_sit_rot = llEuler2Rot (<0, 0, 0> * DEG_TO_RAD);
        llSetText("Owner\n Sit", <1.0, 1.0, 1.0>, 1.0);
        llSetSitText("Ride");   
        llSetAlpha(1,ALL_SIDES); 
        llSitTarget(<1.5, 0.0, 0.9>, euler_sit_rot);
        g_owner=llGetOwnerKey(llGetKey());
        llSetCameraEyeOffset(<-0.5,0.0,10.5>);
        llSetCameraAtOffset(<0.0,-0.0,0.0>);
       
        llSetStatus(STATUS_PHYSICS, FALSE);
       // llSetRot(<0,0,0,0>);
        llSetForce(<0,0,0>,TRUE);
        vector pos = llGetPos();
        float groundheight = llGround(pos);
        llSetPos(<pos.x, pos.y, groundheight+1>);

    }
   
    on_rez(integer numm)
    {
        llResetScript();
    }       
   
    touch_start(integer iii)
    {
        g_agent = llDetectedKey(0);
        llOwnerSay("touched" + (string)g_agent );
       
        if (g_agent == g_owner)
        {
            if (gtouch_toggle == 1)
            {
                llStopSound();
                gtouch_toggle = 0;
                gtouchoff = 1;
            }                           
            else
            {     
                gtouchoff = 0;
                if (llAvatarOnSitTarget()=="")
                {
                    llSay(0,"Resetting..");
                    llResetScript();
                }
                else
                {
                    llOwnerSay("agent= " + llKey2Name(g_agent));
                    gmass = llGetMass();
                    llRequestPermissions(g_agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
                    llSetTimerEvent(0.5);
                }
            }
        }
        else
        {
            llSay(0, "Sorry, you do not own this object.");
            llUnSit(g_agent);
            llResetScript();
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS)
        {
            llSetAlpha(0,ALL_SIDES);
            llStartAnimation("avatar_sit_generic-p2");
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
            llSetTimerEvent(0.5);
            llSetStatus(STATUS_PHYSICS, TRUE);
            // llSetBuoyancy(1);
         }
    }
   
    // ******* CHANGED *************   
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (llAvatarOnSitTarget()=="")
            {
                llSay(0,"Resetting..");
                llResetScript();
            }
        }
    }
     
    control(key id, integer held, integer changer)
    {
        if(held & CONTROL_FWD & changer)
        {
            gincrement+=2;
            if (gincrement > 10) gincrement = 10;
        }
       
        if(held & CONTROL_BACK & changer )
        {
            gincrement-=0.75;
            if (gincrement < -7) gincrement = -7;
        }
     
        if(held & (CONTROL_RIGHT|CONTROL_ROT_RIGHT) )
        {
            gright = -0.1; 
           
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);


            vector heading = pres_heading;

            heading.x = 0;  // tumble stop
            heading.y = 0;  // tumble stop
            heading.z += (gright);
            rot = llEuler2Rot(heading);

            llSetRot(rot);
        }

        if(held & (CONTROL_LEFT|CONTROL_ROT_LEFT) )
        {
            gleft = 0.1;
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);
            vector heading = pres_heading;
            heading.z += (gleft);
            rot = llEuler2Rot(heading);
            llSetRot(rot);
        }
       
        llSetStatus(STATUS_PHYSICS, TRUE);

        // Heading rotation
        llSetForce (gmass*<gincrement, 0, 0>, TRUE);
        llSetBuoyancy(1);
        // llOwnerSay("forwd inc ->"+(string)gincrement+" left/right  "+(string)(gleft) + " " + (string)gright);
    }
   
    timer()
    {
        llSetTimerEvent(0);
        llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

//        applyFriction();
//        llSetForce(dragadjforces,TRUE);
        llSetTimerEvent(0.5);
    }
}


        llSetTimerEvent(0.5);
    }
}




Note that I do not provide support for this script, you are pretty much on your own with it, though if I have time I might answer easy questions about it, and if you have a really interesting hard question I might take a swing at it too.

Just please dont be offended if I tell you I dont have time for it right now.

Also, if you see Owen Oyen, tell him thanks for working on this technology.


Cheers
Hiro

_________________
http://opensimulator.org http://osgrid.org http://simhost.com
---------------------------------------------------------------------------------------------------------------------------
The wind
scours the earth for prayers
The night obscures them


Last edited by Nebadon Izumi on Tue Feb 03, 2009 7:44 pm, edited 1 time in total.
fixed the code portion so its easiuer to select now.


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Sun Feb 08, 2009 4:42 pm 

Joined: Sun Feb 08, 2009 4:39 pm
Posts: 2
Hi Hiro,

Thanks for publishing this.

But I think the code is a bit mucked up. It looks like half way through the code starts again. There are two default states for instance.

Any chance you could give it the once over and make sure its all there?

Many thanks and apologies if I've got the wrong end of the stick.

Cat


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Sun Feb 08, 2009 8:30 pm 

Joined: Wed Feb 04, 2009 6:37 am
Posts: 6
Looks like a copy/pasta error. I cleaned up the extra lines and it works great; thanks for the code Hiro!

{L_CODE}:
float gmass;
float up = 9.8 ;
float gleft;
float gright;
key g_owner;
float gvehiclespeed;

// llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

float XDRAGCOEFF=0.0025;
float YDRAGCOEFF=0.0025;
float ZDRAGCOEFF=1;

float gincrement;
integer g_leftrightflag;
integer gstart;
integer gchannel_num;
integer gtouch_toggle;
integer gtouchoff;
vector dragadjforces;
key g_agent;

applyFriction()
{
    vector rawforces = llGetForce();
    vector drag;
   
    llSay(0,"Raw Force: "+(string) rawforces);
   
    // calculate drag on all axis of motion
    drag.x = llFabs(XDRAGCOEFF * rawforces.x);
    drag.y = llFabs(YDRAGCOEFF * rawforces.y);
    drag.z = llFabs(ZDRAGCOEFF * rawforces.z);

    if(llFabs(rawforces.x) > llFabs(drag.x))
    {
        dragadjforces.x=rawforces.x + drag.x;
    }
    else
    {
        dragadjforces.x = 0;
    }

    if(llFabs(rawforces.y) > llFabs(drag.y))
    {
        dragadjforces.y=rawforces.y + drag.y;
    }
    else
    {
        dragadjforces.y = 0;
    }
   
    if(llFabs(rawforces.z) > llFabs(drag.z))
    {
        dragadjforces.z=rawforces.z + drag.z;
    }
    else
    {
        dragadjforces.z = 0;
    }
   
    llSay(0,"Drag Adj Force: "+(string) dragadjforces);
}

default
{
    state_entry()
    {
        rotation euler_sit_rot = llEuler2Rot (<0, 0, 0> * DEG_TO_RAD);
        llSetText("Owner\n Sit", <1.0, 1.0, 1.0>, 1.0);
        llSetSitText("Ride");   
        llSetAlpha(1,ALL_SIDES);
        llSitTarget(<1.5, 0.0, 0.9>, euler_sit_rot);
        g_owner=llGetOwnerKey(llGetKey());
        llSetCameraEyeOffset(<-0.5,0.0,10.5>);
        llSetCameraAtOffset(<0.0,-0.0,0.0>);
       
        llSetStatus(STATUS_PHYSICS, FALSE);
       // llSetRot(<0,0,0,0>);
        llSetForce(<0,0,0>,TRUE);
        vector pos = llGetPos();
        float groundheight = llGround(pos);
        llSetPos(<pos.x, pos.y, groundheight+2.0>);

    }
   
    on_rez(integer numm)
    {
        llResetScript();
    }       
   
    touch_start(integer iii)
    {
        g_agent = llDetectedKey(0);
        llOwnerSay("touched" + (string)g_agent );
       
        if (g_agent == g_owner)
        {
            if (gtouch_toggle == 1)
            {
                llStopSound();
                gtouch_toggle = 0;
                gtouchoff = 1;
            }                           
            else
            {     
                gtouchoff = 0;
                if (llAvatarOnSitTarget()=="")
                {
                    llSay(0,"Resetting..");
                    llResetScript();
                }
                else
                {
                    llOwnerSay("agent= " + llKey2Name(g_agent));
                    gmass = llGetMass();
                    llRequestPermissions(g_agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
                    llSetTimerEvent(0.5);
                }
            }
        }
        else
        {
            llSay(0, "Sorry, you do not own this object.");
            llUnSit(g_agent);
            llResetScript();
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS)
        {
            llSetAlpha(0,ALL_SIDES);
            llStartAnimation("avatar_sit_generic-p2");
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
            llSetTimerEvent(0.5);
            llSetStatus(STATUS_PHYSICS, TRUE);
            // llSetBuoyancy(1);
         }
    }
   
    // ******* CHANGED *************   
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (llAvatarOnSitTarget()=="")
            {
                llSay(0,"Resetting..");
                llResetScript();
            }
        }
    }
     
    control(key id, integer held, integer changer)
    {
        if(held & CONTROL_FWD & changer)
        {
            gincrement+=2;
            if (gincrement > 10) gincrement = 10;
        }
       
        if(held & CONTROL_BACK & changer )
        {
            gincrement-=0.75;
            if (gincrement < -7) gincrement = -7;
        }
     
        if(held & (CONTROL_RIGHT|CONTROL_ROT_RIGHT) )
        {
            gright = -0.1;
           
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);


            vector heading = pres_heading;

            heading.x = 0;  // tumble stop
            heading.y = 0;  // tumble stop
            heading.z += (gright);
            rot = llEuler2Rot(heading);

            llSetRot(rot);
        }

        if(held & (CONTROL_LEFT|CONTROL_ROT_LEFT) )
        {
            gleft = 0.1;
            rotation rot = llGetRot();
            vector pres_heading = llRot2Euler(rot);
            vector heading = pres_heading;
            heading.z += (gleft);
            rot = llEuler2Rot(heading);
            llSetRot(rot);
        }
       
        llSetStatus(STATUS_PHYSICS, TRUE);

        // Heading rotation
        llSetForce (gmass*<gincrement, 0, 0>, TRUE);
        llSetBuoyancy(1);
        // llOwnerSay("forwd inc ->"+(string)gincrement+" left/right  "+(string)(gleft) + " " + (string)gright);
    }
     
    timer()
    {
        llSetTimerEvent(0);
        llApplyImpulse(gmass*<(0.001 * -gvehiclespeed), 0, 0>, TRUE); // 1st order friction

//        applyFriction();
//        llSetForce(dragadjforces,TRUE);
        llSetTimerEvent(0.5);
    }
}


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Sun Feb 08, 2009 8:35 pm 

Joined: Wed Feb 04, 2009 6:37 am
Posts: 6
Gah, forgot to revert the float height back to what Mr. Protagonist had.

llSetPos(<pos.x, pos.y, groundheight+2.0>);

should be:
llSetPos(<pos.x, pos.y, groundheight+1.0>);

Sorry about that.


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Mon Feb 09, 2009 5:58 pm 

Joined: Sun Feb 08, 2009 4:39 pm
Posts: 2
A couple of points to note if you're having problems with the above script:

Initially I just rolled around when trying to move. Removing the line
{L_CODE}:
llSetAlpha(1,ALL_SIDES);
fixed this
Havn't got a clue why the transparancy should effect the physics engine

The ApplyFriction() function is not called unless you uncomment the appropriate line in the timer event.


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Fri May 01, 2009 11:27 pm 

Joined: Mon Apr 27, 2009 1:52 am
Posts: 6
Hey all, I have been trying for some time now to get any kind of vehicle script working for my sim. I took this code, making the changes you all outline above but it's just not driveable. Are their currently any alternatives? Are they planning on adding more vehicle functionality with later versions of OpenSIm?


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Mon May 04, 2009 6:42 am 
OSG Elite
User avatar

Joined: Thu Jul 31, 2008 2:48 am
Posts: 394
Constantine {L_WROTE}:
Are their currently any alternatives?

Not that I'm aware @ present.
However, a completed working version of the script in the OP can be seen in the
Sail Boat obtainable from a vendor Prim on the North side of Sailor's Vista.

Constantine {L_WROTE}:
Are they planning on adding more vehicle functionality with later versions of OpenSIm?

Yes, LSL like vehicle functions are in the dev queue. For now we will just have to do what we can with work-arounds
and other hacks.

Personally I don't get the fascination with vehicles when avatars can fly unassisted. But that's just me :P

PocoLoco

_________________
PocoLoco
Avatar@Large


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Mon May 04, 2009 1:25 pm 
Site Admin
User avatar

Joined: Sat Feb 02, 2008 5:27 pm
Posts: 843
you may find this following video interesting



I filmed this on OSGrid, i have not made the script available widespread yet, as it will likely break several times in the near future and need complete overhaul.

Neb


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Tue May 05, 2009 2:41 am 
OSG Elite
User avatar

Joined: Thu Jul 31, 2008 2:48 am
Posts: 394
nebs and his blocks and balls.
always showing off the ODE engine ;)

PocoLoco
driving avatars crazy
for nearly a year now...

_________________
PocoLoco
Avatar@Large


Top
 Profile  
 
 Post subject: Re: Opensimulator Vehicle Scripting with LSL
PostPosted: Tue May 05, 2009 2:57 pm 

Joined: Tue May 05, 2009 2:19 pm
Posts: 2
PocoLoco {L_WROTE}:
Personally I don't get the fascination with vehicles when avatars can fly unassisted. But that's just me :P


Yes, it is easier to just take off and "Superman it" around but some enjoy the shared experience of 2 or more people getting into the same vehicle & "flying" from one place to another. Not to mention the Star Trek RP enthusiasts that want their shuttlecraft! :)

Chrys


Top
 Profile  
 
Display posts from previous:  Sort by  
Post a new topicPost a reply Page 1 of 1   [ 10 posts ]


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
610nm Style by Daniel St. Jules of Gamexe.net