Bird Flight Script 8f1
//
// Bird Flight Script
//
// Move the bird high enough that it won't hit anything right away and then click on it.
// It will fly around the location vector set at the top of "timer". It will stay on about a quarter sim.
// The z omponent of this vector is the maximum height.
// (If it won't let you change the script, find a copy with full permissions.)
// It attempts to resume flying after various problems, but if it stops or gets stuck,
// move it where there is space to fly and click again once or twice. If that fails, reset the script.
// (It may fail to climb if you launch it more than about 50 m below the set hight.)
//
//
// There are no "if" statements controling the normal flight! The whole thing is done by simulating aerodynamics.
// That is, by coupled differectial equations (approximated by difference equations), simulating a free flight model airplane.
// It uses the SL physical vehicle type, and much additional dynamics and tuning is done by the script.
// The bird (or airplane) is not forced to stay on the sim, it is steared, as a bird would stay above a food area.
// Vertically, it stays off the ground by simulating a stable free flight model,
// such as a Guillows rise off ground rubber powered model from a toy store or Langley's pioneering steam powered models.
// To make long flights more interesting, the parametres are gradually varried with hight,
// so that a stall is assured by the time it reaches the hight set in the top of "timer", below.
// Mathematically the motion is deterministic at low altitude, in the strong sense of
// the coupled differential equations being uniformly integrable. But the motion is chaotic at high altitude.
// That is, the recovery from a stall can be arbitrarily sensetive to the exact motion at the point of stall.
// The numerical solution captures some of the chaotic nature of a real world stalling airplane.
//
//
// Based on:
// Li'l Stinker Flight Script, by Fritz t. Cat (Fritz Kakapo)
//
// Since the version I started with was public domain, with free software intentions expressed,
// I, Fritz t. Cat, hereby publish my modified version, below, under the GNU General Public License,
// on 2009 July 14 and subsequent versions as available. This means that it is a copyright violation to set
// no-copy, no-modify, no-transfer or turn off "allow anyone to copy" on this script,
// the Li'l Stinker Airplane for which it was written, or anything derived from either of them.
// And also that a GNU Licence statement and credits, according to the current version of the license,
// must accompany anything derived from this script or airplane. I have reproduced the public domain script,
// in a note card, for use in proprietary products.
// The aerodynamics and algorithms used are not copyrightable and may be used as a guide to other scripts.
// Please refer to some source, such as Wikipedia, for the exact license terms.
//
// I have kept some of the earlier comments here:
//"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
// Simple airplane script example
// THIS SCRIPT IS PUBLIC DOMAIN! Do not delete the credits at the top of this script!
// Nov 25, 2003 - created by Andrew Linden and posted in the Second Life scripting forum
// Jan 05, 2004 - Cubey Terra - minor changes: customized controls, added enable/disable physics events
// Feel free to copy, modify, and use this script.
// Always give credit to Andrew Linden and all people who modify it in a read me or in the object description.
//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
//
// The script assumes that the root primitive is oriented such that its:
// local x-axis points toward the nose of the plane, and its
// local z-axis points toward the top.
//
// This bird script is tuned for a flight weight of 0.194306 virtual kilegrams, as of 2009.12.19.
//
//=============================================================================================================
//
// Particle System This is not bird-like but can be used to see the flight path more clearly.
//
//float rate = 0.1; // Adujusted in timer.
//
StartSteam()
{
// MASK FLAGS: set to "TRUE" to enable
integer glow = TRUE; // Makes the particles glow
integer bounce = FALSE; // Make particles bounce on Z plane of objects
integer interpColor = TRUE; // Color - from start value to end value
integer interpSize = TRUE; // Size - from start value to end value
integer wind = FALSE; // Particles effected by wind
integer followSource = FALSE; // Particles follow the source
integer followVel = TRUE; // Particles turn to velocity direction
// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_EXPLODE;
// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner
// and "self" will target this object
// or put the key of an object for particles to go to
// Particle paramaters
float age = 255.; // Life of each particle
float maxSpeed = 0.03; // Max speed each particle is spit out at
float minSpeed = 0.0; // Min speed each particle is spit out at
string texture = "cloud for smoke"; // Texture used for particles, default used if blank
float startAlpha = .8; // Start alpha (transparency) value
float endAlpha = 0.05; // End alpha (transparency) value
vector startColor = <0.99, 0.99, 0.99 >; // Start color of particles
vector endColor = <0.2, 0.7, 0.2 >; // End color of particles (if interpColor == TRUE)
vector startSize = <0.2, 0.2, 0>; // Start size of particles
vector endSize = ><2., 2., 0 >; // End size of particles (if interpSize == TRUE)
vector push = ><0., 0., 0. >; // Force pushed on particles
// System paramaters
float rate = 0.15; // How fast (rate) to emit particles
float radius = 0.1; // Radius to emit particles for BURST pattern
integer count = 1; // How many particles to emit per BURST
float outerAngle = 0.; // Outer angle for all ANGLE patterns
float innerAngle = 0.; // Inner angle for all ANGLE patterns
vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source
float life = 0; // Life in seconds for the system to make particles
// Script variables
integer flags;
flags = 0;
if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
if (wind) flags = flags | PSYS_PART_WIND_MASK;
if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
llParticleSystem();
}
//
StopSteam()
{
llParticleSystem( );
}
//
//=====================================================================================================
//
// The thrust is saved and restored as it decays, to continue cruising.
vector gLinearMotor = 0><0, 0, 0>;
//
// Used to handle exceptions:
float last_time; // previously stored time of day
vector last_pos_1a = <-7,-7,-7>;
vector last_pos_1b = ><-7,-7,-7>;
vector last_pos_2a = ><-7,-7,-7>;
vector last_pos_2b = ><-7,-7,-7>;
integer kownt_1 = 0;
integer kownt_2 = 0;
float leap = 10.;
integer flying = FALSE; // Keeps track of whether flying or pearched.
integer pause = 1;
//
// Base values of dynamically varied parameters:
float ANGULAR_DEFLECTION_TIMESCALE_0 = 8.; // Can be used to decrease stability with altitude.
//
float LINEAR_DEFLECTION_TIMESCALE_0 = 27.; // fuselage lift
//
float ANGULAR_MOTOR_TIMESCALE_0 = 1.0; // This is shortened in timer, to increase control effectiveness with speed.
//
vector ANGULAR_FRICTION_TIMESCALE_0 = ><0.10, 0.08, 0.58 >; // Along with angular motor time scale,
//
//
vector steady_torque = ><0, 0, 0. >; // Aerodynamic torque, to add trim and dynamics.
//
integer new_collision = 5; // Decremented in timer.
vector global_pos; // position relative to launch point, counting 246 m for each sim
vector Center_0;
//
//--------------------------------------------------------------------------------------------------------
init()
{
llSetStatus( STATUS_PHYSICS, FALSE ); // Stop if already flying.
//
//
// Set initial values of vehicle parameters.
//
llSetVehicleType( VEHICLE_TYPE_AIRPLANE ); // Sets default airplane-like parameters.
//
// action of the fin and stabilizer: Points toward velocity.
// The front turns toward the current velocity.
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 1. );
// "behave much like the deflection time scales"
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, ANGULAR_DEFLECTION_TIMESCALE_0 / 2. );
//
// fuselage lift.
// Wing lift is handled with VEHICLE_LINEAR_FRICTION_TIMESCALE below.
// The velocity turns toward the front. (Exact formula unknown.)
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1. );
// "behave much like the deflection time scales"
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, LINEAR_DEFLECTION_TIMESCALE_0 );
//
// propeller thrust strength
// Shorter time scale makes it more stable. Longer makes a wider speed range.
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_TIMESCALE, 2.0 ); // 1/strength
// "it cannot be set longer than 120 seconds"
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 15.);
// Throttle gradually closes with time, but defeated: Refreshed below in timer.
//
// This controls the strength of the torques set in timer.
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, ANGULAR_MOTOR_TIMESCALE_0 ); // 1/strength
//
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 1.5 );
// Control returns to neutral when released. But it is reset in timer, so this ony matters when there is lag.
//
//--------------------- linear friction ------------------------------------------------
// The x component is parasite drag (along with VEHICLE_LINEAR_MOTOR_TIMESCALE).
// The y component contributes to fuselage transverse lift and to drag due to yaw.
// The effect of dyhedral depends on side slip.
// The z component might seem to be just a vertical damping, but when pitch changes by a small amount,
// most of the motion in the direction that was previously forward, becomes motion in the new forward direction,
// with initially only a small transverse (up or down) component. With a short decay time scale
// in the z direction, that component is lost quickly, so the motion continues to follow the pitch angle, with little loss.
// The larger the z time constant is, the more "induced drag" there is. That is VEHICLE_LINEAR_FRICTION_TIMESCALE.z
// greater than zero causes a drag that increases with lift, similarly to induced drag of a physical airplane.
//
// The z component gives the wing lift. Decreasing it allows the airplane to fly more slowly,
// without loss of speed or altitude. But it seems to be near the limit, to fly slower one may need buoyancy.
llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, ><14., 2.0, 0.008 > );
//
// This is damping of rotation. Physically it would increase with the length and wing span.
// The z component is neccesary for the dihedral and sweepback to be effective.
llSetVehicleVectorParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, ANGULAR_FRICTION_TIMESCALE_0 );
// Along with angular motor time scale, this damps the rotational motion.
//
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1000 ); // CG below center of lift, pendulum period.
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0 ); // damping, 0–1: 1. is fully damped.
// This needs to be weak for a stunt airplane, that should fly nearly the same upside down as right side up.
// It is desirable especially in free flight models, such as paper gliders. See the dynamic coupling in timer.
//
// This drives yaw in the direction of roll, imitating use of rudder by the pilot.
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 0 ); // Is there a difference between time scale
llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 1000 ); // and efficiency?
llSetVehicleFloatParam( VEHICLE_BANKING_MIX, 0 ); // more yaw control when moving, 0 = none at rest.
// Since this imitates a manual control, any convenient value set is physical (assuming a rotating tail wheel).
// The Wright brothers found that mechanical coupling of the rudder and ailerons was not sufficient,
// because of the delays involved.
// It is not used here, because it was not intended for attitudes far from right side up.
//
// "hover can be better than sliding along the ground during takeoff and landing
// but it only works over the terrain (not objects)"
//llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 3.0);
//llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.5);
//llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 2.0);
//llSetVehicleFlags(VEHICLE_FLAG_HOVER_UP_ONLY);
//
// "non-zero buoyancy helps the airplane stay up
// set to zero if you don't want this crutch"
// This was useful in the initial stages of tuning. I think it simply reduces the gravitational
// contribution to downward acceleration. It, here, is supposed to allow a longer timer setting.
llSetVehicleFloatParam( VEHICLE_BUOYANCY, 0. );
//
// Start with only vehicle torques. This is set in timer.
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,0> );
//
//-------------------------------------------------------------------------------------------------------
flying = FALSE; // Keep track of not flying.
llSetTimerEvent( 0. ); // Stop timer.
//StopSteam(); // Stop particles.
llStopSound();
//llSetSoundQueueing( TRUE ); // This is supposed to make sounds wait for eachother, but it doesn't work.
// So llSleep is used below to force wait.
//
//llSay(0, (string)llGetMass()+" virtual kilograms." );
llSay(0, "Cogito ergo sum."); // (quote from 1952 Galaxy science fiction story)
llSay(0, "Touch to set center and start."); //
//
} // End init().
//
//-------------------------------------------------------------------------------------------------------------------
default
{
state_entry()
{
init();
}
//
on_rez(integer start_param)
{
init();
}
//
//----------------------------------------------------------------------------------------------------------------
touch_start(integer total_number)
{
if ( llDetectedOwner( 0 ) != llGetOwner() )
{
// only the owner can use this vehicle
llSay(0, "Please take a copy of this airplane or bird and fly your own copy.
(If it is not set \"Free to copy\" or \"For sale l$ 0\", contact the owner or the creator.)
You aren't the owner -- only the owner can fly this plane.");
}
else
{
//
if ( ! flying )
{
Center_0 = llGetPos();
global_pos = Center_0; // location relative to launch point
llPlaySound( "parrot2", 1.0 );
//
//StartSteam(); // Start paricle tracer smoke trail.
//
gLinearMotor = <11., 0, 0. >; // Set thrust.
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor );
//
llSetStatus( STATUS_PHYSICS, TRUE ); // Enable physics.
//
llApplyImpulse( ><0.3, 0, 0.05 >, TRUE ); // Except for humbingbirds, birds run or push off with their feet.
//
flying = TRUE;
llSay(0, "Started.");
last_time = llGetTimeOfDay(); // to test for lag
llSetTimerEvent( 0.5 ); // seconds Timer controls flight.
//
llSleep( 2. );
llLoopSound( "parrot1", 0.25 );
//
}
else
{
llSetStatus( STATUS_PHYSICS, FALSE );
llSay(0, "Stopped manually.");
llSetTimerEvent( 0. ); // Stop timer.
flying = FALSE;
llStopSound();
//StopSteam();
//
}
//
} // End owner.
}
//
//======================================================================================================
timer()
{
//----------------------------------- Set parcel center. -------------------------------------------
//
// This vector should be changed to match the location available for flight. ><--------------------<<<<
//
//vector Center = < 128., 128., 30.+20.+llFabs(llGround(<0,0,0>)-20.) >; // Use constant east, north.
//vector Center = Center_0 + ><0., 0., 30. >; // Use starting hight as flat ground level.
Center_0.z = 0.;
vector Center = Center_0 + ><0., 0., 30.+20.+llFabs(llGround(<0,0,0>)-20.) >; // higher over water
//vector Center = Center_0 + ><0., 0., 30.+10.+llGround(<0,0,0>) >; // lower over water
//
// This is the locaiton that it flies around. The z component is about the top of the flight pattern
// and should be high enough to keep it off the ground most of the time.
// The bird will stear to stay near the horizontal part and below the vertical value.
//
//---------------------------- Update position + 256 * sim count. ------------------------------------
//
vector pos = llGetPos();
//
vector delta_pos = pos-global_pos;
//
if ( delta_pos.x ><-128. ) delta_pos.x = delta_pos.x + 256.;
else if ( delta_pos.x > 128. ) delta_pos.x = delta_pos.x - 256.;
//
if ( delta_pos.y ><-128. ) delta_pos.y = delta_pos.y + 256.;
else if ( delta_pos.y > 128. ) delta_pos.y = delta_pos.y - 256.;
//
global_pos += delta_pos;
//
//----------------------------- Get some flight data used below. ------------------------------------
rotation rot = llGetRot();
vector glob_dorsal = <0,0,1> * rot; // dorsal direction in global coordinates
float horizontal = glob_dorsal * 0><0,0,1>;
//
vector v = llGetVel();
//
float speed = llSqrt( v * v );
//
//llShout( 0, (string) speed ); // debug and tuning
//
//-------------------------------- Refresh motor settings. -----------------------------------------
//
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor );
// This is to defeat VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE.
//
//---------------- Include speed increase of contol surface effectiveness. ----------------------------------
//
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, LINEAR_DEFLECTION_TIMESCALE_0
/ ( 0.5 + 0.5 * speed / 8. ) ); // fuselage lift
//
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, ANGULAR_MOTOR_TIMESCALE_0
/ ( 0.15 + 0.85 * llSqrt( speed*speed ) / 8. ) ); // 1/strength of controls
//
//
//--------------------------------------------- Dynamics ------------------------------------------------------
//
//
steady_torque = <0., 0, 0. >;
//
// >>>>>>-------------------------> Stear toward parcel center. ><--------------------------------------<<<<<<
// (It can be allowed to wander by removing this section.)
//
vector toCenter = Center - global_pos; // global vector to center of parcel
//
if ( toCenter.z < 0. ) { jump skip_dynamics; } // None of this dynamics makes any sense if we are above ceiling!
//
// Roll and yaw to the port of center, moving inward and to starboard when moving away from center.
// This moves it toward center, when circling right.
vector h_toCenter = toCenter;
h_toCenter.z = 0; // No vertical here.
vector loc_h_toCenter = h_toCenter / rot; // global to local coordinate transformation;
vector left = -loc_h_toCenter;
left.y = 0;
left.z = -2. * left.x; // Roll component goes to roll and yaw.
steady_torque += left * 0.0016 * speed; // Roll to left of center, to right away.
//
// Turn toward center. This tends to move it to center when not circeling.
vector turn_toCenter = < 1, 0, 0 > % loc_h_toCenter;
// Forward x redius = torque toward center.
steady_torque += turn_toCenter * 0.0030 * speed; // Adjust strength. Add to torque.
//
//
// This replaces the code above, to move cross country:
//steady_torque += ><-1, 1, 0 > / llSqrt(2.) * 1.2 / llGetRot(); // Turn to east.
// This line directs the average direction approximatly East. Rotate for other directions.
// That is, the version tested goes around 135 degrees to the right of the above constant vector.
//
//
//-------------------------------------- Reduce stability at high altitude. --------------------------------
float stability = toCenter.z / 30.;
stability = llFabs( stability ) + 0.001; // There have been run time math errors.
float sqr_stab = llSqrt( stability );
float fourR_stab = llSqrt( sqr_stab ) ;
float eightR_stab = llSqrt( fourR_stab ) ;
//
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, ANGULAR_DEFLECTION_TIMESCALE_0
/ ( 0.6 + 0.4*speed/8. ) * ( 0.1 + 0.9*stability ) ); // fin and stabalizer
// Too much fin and stabalizer reduces dynamic stability, at maximum height.
//
llSetVehicleVectorParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, ANGULAR_FRICTION_TIMESCALE_0
/ ( sqr_stab ) );
// Along with angular motor time scale,
// Less angular friction reduces static (angle only) stability damping.
//
//
//--------------------------- Dynamic Coupling and Trim Tuneing -----------------------------------------------
//
vector local_vel = v / rot; // global to local coordines
//
// Spiral right to help stay in sim (and stabalize phugoid).
float right = 0.;
right += 0.04 * local_vel.x * fourR_stab;
right += 0.024 * local_vel.x * local_vel.x * fourR_stab;
right += 0.002 * local_vel.x * local_vel.x * local_vel.x;
steady_torque.x += right;
steady_torque.z -= 1.5 * right;
//
// Dihedral: Wing tip on the downward side lifts when moving sideways.
// If VEHICLE_ANGULAR_FRICTION_TIMESCALE.z holds the nose back from the turn
// and VEHICLE_LINEAR_FRICTION_TIMESCALE.y lets it slip slip sideways,
// then the dihedral lifts the inside wing in a turn.
//
steady_torque.x += 4. * local_vel.y; //
steady_torque.x += 0.5 * local_vel.y * speed * fourR_stab; //
steady_torque.x += 0.06 * local_vel.y * speed * speed * fourR_stab; //
//
// Wing sweep-back --- similar to dyhedral but only works when lifting
// The wing that is yawed forward and the body is sideslipping toward has more lift.
steady_torque.x -= 0.5 *( local_vel.y * local_vel.z * local_vel.x );
steady_torque.x -= 0.5 *( local_vel.y * local_vel.z * local_vel.x * local_vel.x );
//
// Turn upward: This is the trim incidence of the stabalizer.
steady_torque.y -= 0.10 * speed;
// Low powers of speed control the climb angle.
steady_torque.y -= 0.30 * local_vel.x * speed * speed;
// The high powers of speed make it recover quickly from steep dives.
steady_torque.y -= 0.03 * speed * speed * speed * speed / fourR_stab;
//
// Turn downward: Like the paper clip on the nose of a paper airplane.
steady_torque.y += 1.; // A steep slope of this torque with speed
steady_torque.y += 1.3 * horizontal // makes the phugoid unstable.
* sqr_stab; // Fades out to make it stall.
//
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, steady_torque ); // Apply the torque.
//
@skip_dynamics;
//----------------------------------- Handle Exceptions --------------------------------------------
//
// Lag
float time = llGetTimeOfDay();
//
if ( time > last_time + 5. ) // Usually when crossing sim boundaries.
{
llSetStatus( STATUS_PHYSICS, FALSE ); // Turn off physics.
llSay( 0, "Flight suspended, for timer timeout." );
pause = -20;
}
last_time = time;
//
// Recovers from trying to enter restricted space.
if ( !llGetStatus(STATUS_PHYSICS) && flying && pause>0 )
{
llSetRot( llGetRot() * llAxisAngle2Rot( <0,0,1>, PI*2./3. ) );
pause = -10;
}
//
// Low "energy"
float e = llGetEnergy();
//
if ( e <0.95 )
{
llSay( 0, (string) e );
//
if ( e < 0.5 )
{
llSetStatus( STATUS_PHYSICS, FALSE ); // Pause physics.
llSay( 0, "Flight suspended, to catch his breath." );
pause = -30;
}
}
//
// Continue after timed pause.
pause += 1;
if ( pause == 0 && flying )
{
llPlaySound( "parrot2", 1.0 );
llSetStatus( STATUS_PHYSICS, TRUE );
llSleep( 2. );
llLoopSound( "parrot1", 0.25 );
}
//
//-------------------------------------------------------------------------------------------------------------
//
// Break away if stuck.
if ( llGetStatus( STATUS_PHYSICS ) )
{
if ( kownt_1 == 40 )
{
vector diff_a = pos - last_pos_1a;
vector diff_b = pos - last_pos_1b;
if ( diff_a*diff_a + diff_b*diff_b < 2. )
{
llPlaySound( "parrot2", 1.0 );
llSay( 0, "Stuck!" );
llSetStatus(STATUS_PHYSICS, FALSE);
pos.z += leap; // Attempt to jump over obsticle.
if ( pos.z > Center.z )
{ pos.z = Center.z; } // But not above set ceiling.
llSetPos( pos );
llSetStatus(STATUS_PHYSICS, TRUE);
leap += 10.;
llSleep( 2. );
llLoopSound( "parrot1", 0.25 );
}
last_pos_1b = last_pos_1a;
last_pos_1a = pos;
kownt_1 = 0;
}
//
if ( kownt_2 == 400 )
{
vector diff_a = pos - last_pos_2a;
vector diff_b = pos - last_pos_2b;
if ( diff_a*diff_a + diff_b*diff_b ><6. )
{
llPlaySound( "parrot2", 1.0 );
llSay( 0, "Stuck!" );
llSetStatus(STATUS_PHYSICS, FALSE);
pos.z += leap; // Attempt to jump over obsticle.
if ( pos.z > Center.z )
{ pos.z = Center.z; } // But not above set ceiling.
llSetPos( pos );
llSetStatus(STATUS_PHYSICS, TRUE);
leap += 10.;
llSleep( 2. );
llLoopSound( "parrot1", 0.25 );
}
last_pos_2b = last_pos_2a;
last_pos_2a = pos;
kownt_2 = 0;
}
kownt_1 += 1;
kownt_2 += 1;
} // End STATUS_PHYSICS.
//
new_collision -= 1;
//
//
} // End timer. -------------------------------------------------------------------------------------------
//
land_collision( vector pos ) // It tends to get stuck on its back like a turtle.
{
if ( flying )
{
if ( new_collision ><= 0 )
{
llStopSound(); // ?
llPlaySound( "parrot2", 1.0 );
//
llSetStatus( STATUS_PHYSICS, FALSE ); // Must be non-physical to set pos and rot.
//
llSetPos( llGetPos() + < 0, 0, 7. > );
//
rotation rot = llGetRot();
vector forward = llRot2Fwd( rot );
forward.z = 0.; // Keep only the rotation around the vertical axis.
rot = llAxes2Rot( forward, <0,0,1.>%forward, 0><0,0,1.> );
rot = llAxisAngle2Rot( 0><0, -1. ,0>, 30.*PI/180. ) * rot;
rot = llAxisAngle2Rot( 0><0,0, -1. >, 45.*PI/180. ) * rot;
rot = llAxisAngle2Rot( <1., 0,0>, 10.*PI/180. ) * rot;
llSetRot( rot );
//
llSetStatus( STATUS_PHYSICS, TRUE );
//
//llSay(0, "Ouch!" );
//
llApplyImpulse( ><0.05, 0, 0.002 >, TRUE ); // Except for humbingbirds, birds run or push off with there feet.
//
last_time = llGetTimeOfDay(); // Don't time out for the time it took to do this.
//llSleep( 2. ); This was for the sound, but I think the script engine is not multi-threaded.
llStopSound(); // ? Otherwise it loops the wrong sound !?
llLoopSound( "parrot1", 0.25 );
new_collision = 10;
}
}
else
{
llSetStatus( STATUS_PHYSICS, FALSE );
}
} // End land_collision.
//
collision( integer n ) // It tends to get stuck on its back like a turtle.
{
if ( flying )
{
if ( new_collision ><= 0 )
{
llStopSound(); // ?
llPlaySound( "parrot2", 0.1 );
//
llSetStatus( STATUS_PHYSICS, FALSE ); // Must be non-physical to set pos and rot.
//
rotation rot = llGetRot();
vector forward = llRot2Fwd( rot );
forward.z = 0.; // Keep only the rotation around the vertical axis.
rot = llAxes2Rot( forward, <0,0,1.>%forward, <0,0,1.> );
rot = llAxisAngle2Rot( 0><0, -1. ,0>, 30.*PI/180. ) * rot;
rot = llAxisAngle2Rot( 0><0,0, -1. >, 45.*PI/180. ) * rot;
rot = llAxisAngle2Rot( <1., 0,0>, 10.*PI/180. ) * rot;
llSetRot( rot );
//
llSetPos( llGetPos() + ><0, 0, 2. > );
llSetStatus( STATUS_PHYSICS, TRUE );
//
//llSay(0, "Ouch!" );
//
llApplyImpulse( ><0.1, 0, 0.07 >, TRUE ); // Except for humbingbirds, birds run or push off with there feet.
//
last_time = llGetTimeOfDay(); // Don't time out for the time it took to do this.
//llSleep( 2. ); This was for the sound, but I think the script engine is not multi-threaded.
llStopSound(); // ? Otherwise it loops the wrong sound !?
llLoopSound( "parrot1", 0.05 );
new_collision = 10;
}
}
else
{
llSetStatus( STATUS_PHYSICS, FALSE );
}
} // End collision.
} // End default.
//
//=============================================================================================================================
//
//=============================================================================================================================
//>0>>0>>0>>0>>0>>0>>>>