title Bedstraw Locomotive 202 notes user strick ip 75.144.20.97 vol 1 lock ******** /b Bedstraw Locomotive 202: /pre( // 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, ); 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, 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(); }