Bedstraw Locomotive 202:
// Train 201. (C) Strick Unknown. Bedstraw(128,128).
integer Physical;
integer gAngularControls;
integer gLinearControls;
integer Speed;
integer TTL;
integer WasSatOn;
integer UnixTimeLinked;
vector Corner;
vector Bedstraw;
vector Prev;
float Meters;
float VERTICAL_PRESSURE = -0.2;
integer TICK = 2;
integer MAX_IDLE = 900; // 15 min
Init() {
llSetVehicleType(VEHICLE_TYPE_CAR);
llSetVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP );
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <0,1,1>);
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <3,1,1>);
llSitTarget( <-1.8,0,1.5>, ZERO_ROTATION );
llSetSitText("Ride");
llSetCameraEyeOffset(<-3, 0, 3>);
llSetCameraAtOffset(<2.5, 0, 1>);
Phys(FALSE);
// define these here for convenience later
gAngularControls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT ;
gLinearControls = CONTROL_UP | CONTROL_DOWN | CONTROL_BACK | CONTROL_FWD;
Bedstraw = <1011,1023,0>;
}
Phys(integer how) {llSetStatus(STATUS_PHYSICS, how); Physical= how;}
UnPhys(integer verbose) {
if (Physical) {
ReSpeed(0);
Phys(FALSE);
if (verbose) llWhisper(0,
"Physics OFF. (Hit PAGE DOWN to restore.)");
}
}
RePhys(integer verbose) {
if (!Physical) {
Phys(TRUE);
ReSpeed(0);
llWhisper(0,
"Physics ON. (Hit SHIFT LEFT or SHIFT RIGHT to side out & freeze.)");
}
}
ReSpeed(integer s) {
llSetVehicleVectorParam(
VEHICLE_LINEAR_MOTOR_DIRECTION, <s, 0, VERTICAL_PRESSURE>);
if (Speed != s) {
llWhisper(0, HowFar() + "Speed: "+(string)s);
Speed = s;
}
}
RotImp(integer k) {
llApplyRotationalImpulse(<0, 0, k>, TRUE);
}
SideOutLeft(float y) {
llSetPos(llGetPos() + y*llRot2Left(llGetRot()));
}
SideOutFwd(float x) {
llSetPos(llGetPos() + x*llRot2Fwd(llGetRot()));
}
string HowFar() {
integer ut = llGetUnixTime();
integer im = (integer)Meters;
return "{"+ (string)im+"m "+(string)(ut-UnixTimeLinked)+"s} ... ";
}
default {
on_rez(integer a) {
TTL = -1;
}
state_entry() {
Init();
if (TTL >= 0) TTL = 0;
Corner = llGetRegionCorner();
Prev = Corner + llGetPos();
llSetTimerEvent(TICK);
}
changed(integer change) {
if (change & CHANGED_LINK) {
key agent = llAvatarOnSitTarget();
llOwnerSay("llAvatarOnSitTarget() " + (string)agent);
if (agent) {
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
TTL = 300;
WasSatOn = TRUE;
UnixTimeLinked = llGetUnixTime();
Corner = llGetRegionCorner();
Prev = Corner + llGetPos();
llSetTimerEvent(2);
} else if (WasSatOn) {
// driver is getting up
llReleaseControls();
llStopAnimation("sit");
llSleep( 1.0 );
Phys(FALSE);
WasSatOn = FALSE;
state limbo;
} else {
llSay(0, "Stray UNLINK Event!");
}
}
}
run_time_permissions(integer perm)
{
if (perm)
{
llStartAnimation("sit");
llTakeControls(gAngularControls | gLinearControls, TRUE, FALSE);
RePhys(0);
llWhisper(0, "###### Important Hints:");
llWhisper(0, "###### Use PAGE UP to move to nearest rails.");
llWhisper(0, "###### Use PAGE DOWN to reverse direction (180 degrees).");
llWhisper(0, "###### SHIFT LEFT, SHIFT RIGHT to side out & stop Physics.");
llWhisper(0, "###### FWD, BACK, LEFT, RIGHT drive as normal.");
}
}
control(key id, integer level, integer edge)
{
TTL = 0;
if (level & edge & CONTROL_FWD ) {
if (Physical) ReSpeed(Speed + 2); else SideOutFwd(4);
} else if (level & edge & CONTROL_BACK ) {
if (Physical) ReSpeed(Speed - 2); else SideOutFwd(-4);
} else if (level & CONTROL_ROT_LEFT ) {
if (Physical) RotImp(100); else SideOutLeft(4);
} else if (level & CONTROL_ROT_RIGHT ) {
if (Physical) RotImp(-100); else SideOutLeft(-4);
} else if (level & CONTROL_LEFT ) {
UnPhys(1);
SideOutLeft(4);
} else if (level & CONTROL_RIGHT ) {
UnPhys(1);
SideOutLeft(-4);
} else if (level & edge & CONTROL_UP ) {
llSensor("Guide", NULL_KEY, PASSIVE, 96, PI);
} else if (level & edge & CONTROL_DOWN ) {
if (Physical) {
UnPhys(0);
llSetRot(llEuler2Rot(<0,0,PI> + llRot2Euler(llGetRot())));
RePhys(0);
} else {
RePhys(1);
// llWhisper(0,"## Hit PAGE DOWN again to flip 180 degrees.");
}
}
}
timer() {
if (TTL >= 0) {
TTL += TICK;
if (TTL > MAX_IDLE) llDie();
if (Physical) {
vector c = llGetRegionCorner();
vector here = c + llGetPos();
Meters += llVecDist(Prev, here);
if (c != Corner) {
integer dx = (integer)(c.x/256 - Bedstraw.x);
integer dy = (integer)(c.y/256 - Bedstraw.y);
string s = HowFar() + "Bedstraw + ("+(string)dx+", "+(string)dy;
s += ") == \"" + llGetRegionName() + "\"";
llWhisper(0, s);
Corner = c;
}
Prev = here;
}
}
}
sensor(integer n) {
integer i;
vector pos = llDetectedPos(0);
rotation rot = llDetectedRot(0);
llWhisper(0, "Detected track: "+ (string)pos);
// Mark places with footballs
/*for (i=0; i<n; ++i) {
vector p = llDetectedPos(i);
integer xxx = (integer)p.x;
integer yyy = (integer)p.y;
integer zzz = (integer)p.z;
integer param = ((i*10+1)<<24) | ((xxx&255)<<16) |
((yyy&255)<<8) | (zzz&255);
llRezObject("Football Place Marker (temp)",
llGetPos()+<0,0,9>, ZERO_VECTOR, ZERO_ROTATION, param);
}*/
Speed = 0;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0,0,-0.1>);
Phys(FALSE);
rotation myRot = llGetRot();
vector myFwd = llRot2Fwd(myRot);
vector left = llRot2Left(rot);
vector cross = myFwd % left;
if (cross.z < 0) {
rot = rot * llEuler2Rot(<0,0,PI>);
}
llSetRot(rot);
for (i=0; i<12; ++i) {
llSetPos(pos + <0,0,1>);
}
RePhys(1);
}
}
state limbo {
state_entry() {
llSetTimerEvent(3);
}
touch_start(integer i) {
state default;
}
timer() {
llDie();
}
}
(unless otherwise marked) Copyright 2002-2014 YakPeople. All rights reserved.