/////////////////////////////////////////////////////////// // Plane Parameter float roll = 1; float pitch = 0.5; float yaw = 0.5; float accel = 0.2; float maxSpeed = 20.0; float uprate = 1.0; float stallspeed = 5.0; float enginepw = 2.0; /////////////////////////////////////////////////////////// // System Parameter float boundary_max = 245.0; float boundary_min = 10.0; float boundary_err = 10.0; float height_max = 50.0; float height_min = 0.0; float height_err = 5.0; float dfltdtime = 1.0; float dtime = 0.0; //// float avatarheight = 0.0; float speed = 0.0; float acceler = 0.0; float height = 0.0; float buoyancy = 0.0; ShowText(string str1, string str2, integer status) { vector col = <0.1, 1.0, 1.0>; if (status==1) col = <1.0, 0.1, 0.1>; else if (status==2) col = <1.0, 1.0, 0.1>; llSetText(str1 + " : " + str2 + "\n \n \n \n \n \n \n \n \n \n \n \n" , col, 2.0); } initParam() { llSetVehicleType(VEHICLE_TYPE_AIRPLANE); // 力を前方向へ直そうとする強さ llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1.0); llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.1); // 力のかかる方向に向こうとする強さ llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.0); // 0.0 llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 20.0); // 1.0 // 移動用モーターのタイムスケール llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 1.0); // 0.5 llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.2); // 20 // 方向転換用モーターのタイムスケール llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1); // 0.5 llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.1); // 3 // 安定性とそのタイムスケール llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.5); // almost wobbly 0.25 llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 0.5); // mediocre response 1.5 llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.4); // medium strength llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); // very responsive llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.95); // more banking when moving // very weak friction llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000.0, 1000.0, 1000.0> ); llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <1000.0, 1000.0, 1000.0> ); dtime = dfltdtime; vector pos = llGetPos(); avatarheight = pos.z - llGround(ZERO_VECTOR); llSetTimerEvent(dtime); uprate = height_max/maxSpeed; } normalizePos() { vector pos = llGetPos(); if (pos.xboundary_max) pos.x = boundary_max - 2; if (pos.yboundary_max) pos.y = boundary_max - 2; llSetPos(pos); } integer calc_velocity(integer level) { vector pos = llGetPos(); if (pos.xboundary_max || pos.xboundary_max) { llSay(0, "CRASHED!!!!"); llDie(); } integer status = 0; float obuoyancy = buoyancy; dtime = dfltdtime; speed = llVecMag(llGetVel()); height = pos.z - llGround(ZERO_VECTOR); if (pos.xboundary_max-boundary_err || pos.yboundary_max-boundary_err || height>height_max) { normalizePos(); status = 1; dtime = dfltdtime/10.; } else if (pos.xboundary_max-boundary_err*2 || pos.yboundary_max-boundary_err*2 || height>height_max -height_err) { status = 2; // 強制失速状態 dtime = dfltdtime/3.; } if (status!=0) { buoyancy = 0.0; if (obuoyancy!=buoyancy) llSetVehicleFloatParam(VEHICLE_BUOYANCY, buoyancy); if (status==1 || level==0) { vector motor = <0.0, 0.0, 0.0>; vector updwn = <0.0, 0.0, 0.0>; motor.y = pitch; updwn.z = - uprate*speed - (height - height_min); if (updwn.z>0.0) updwn.z = -uprate*speed; updwn.z *= enginepw; llApplyImpulse(updwn*llGetRot(), TRUE); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, motor*llGetRot()); if (speed>0.0 && status==1) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <-speed, 0.0, 0.0>); else if (speed>0.0 && status==2) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <-accel, 0.0, 0.0>); } } else { if (speed<=stallspeed) { buoyancy = 0.0; } else if (speed>stallspeed) { buoyancy = 1.00; } else { buoyancy = 0.0; } if (obuoyancy!=buoyancy) llSetVehicleFloatParam(VEHICLE_BUOYANCY, buoyancy); } ShowText((string)speed, (string)(height-avatarheight), status); return status; } control_handle(integer level, integer edge) { integer status = calc_velocity(level); vector motor = <0.0, 0.0, 0.0>; vector updwn = <0.0, 0.0, 0.0>; if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) { motor.x += roll; motor.y -= pitch/2; motor.z -= yaw; } if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT)) { motor.x -= roll; motor.y -= pitch/2; motor.z += yaw; } //if (level & CONTROL_UP) if (level & CONTROL_FWD) { motor.y -= pitch; } //if (level & CONTROL_DOWN) if (level & CONTROL_BACK) { motor.y += pitch; } if (status==0) { if (level & CONTROL_UP) //if (level & CONTROL_FWD) { updwn.z += uprate*speed - height; if (updwn.z<0.0) updwn.z = uprate*speed; updwn.z *= enginepw; if (speed < maxSpeed) acceler += accel; } //if (level & CONTROL_BACK) if (level & CONTROL_DOWN) { updwn.z -= (uprate*speed + (height - height_min))/5; if (updwn.z>0.0) updwn.z = -uprate*speed/5; acceler -= accel/5; if (acceler < 0) acceler = 0; } } else if (status==2) { //if (level & CONTROL_FWD) if (level & CONTROL_UP) { if (speed < stallspeed/2) acceler += accel/5; else { acceler -= accel/5; if (acceler < 0) acceler = 0; } } if (level & CONTROL_DOWN) //if (level & CONTROL_BACK) { acceler -= accel; //if (acceler < 0) acceler = 0; } } else if (status==1) { //if (level & CONTROL_FWD) if (level & CONTROL_UP) { if (speed < stallspeed/5) acceler += accel/10; else { acceler -= accel/20; if (acceler < 0) acceler = 0; } } if (level & CONTROL_DOWN) //if (level & CONTROL_BACK) { acceler -= speed; //if (acceler < 0) acceler = 0; } } // if (updwn.z!=0.0) llApplyImpulse(updwn*llGetRot(), TRUE); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, motor*llGetRot()); if (speed>0.0) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, ); } } default { state_entry() { llSetSitText("Ride"); llCollisionSound("", 0.0); llSitTarget(<0.9, 0.00, 0.20>, ZERO_ROTATION); } on_rez(integer param) { llResetScript(); } timer() { calc_velocity(0); } changed(integer change) { if (change & CHANGED_LINK) { key agent = llAvatarOnSitTarget(); if (agent!=NULL_KEY) { // clear linear motor on successful sit initParam(); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0.0, 0.0, 0.0>); llSetStatus(STATUS_PHYSICS, TRUE); llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1000.0); llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1000.0); llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); } else { // stop the motors llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0.0, 0.0, 0.0>); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0.0, 0.0, 0.0>); llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 0.0); llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 0.0); llApplyImpulse(-llGetVel()*llGetRot(), TRUE); // driver is getting up llReleaseControls(); llSetTimerEvent(0.0); llSetStatus(STATUS_PHYSICS, FALSE); llResetScript(); } } } run_time_permissions(integer perm) { if (perm!=0) { llSay(0, "All Go"); integer anglControls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_DOWN | CONTROL_UP; integer lineControls = CONTROL_FWD | CONTROL_BACK; llTakeControls(anglControls | lineControls, TRUE, FALSE); } } control(key id, integer level, integer edge) { llSetTimerEvent(0.0); control_handle(level, edge); llSetTimerEvent(dtime); } }