datablock ParticleData(ScoutFlyerExplosionParticle)
{
   dragCoefficient      = 2;
   gravityCoefficient   = 0.2;
   inheritedVelFactor   = 0.2;
   constantAcceleration = 0.0;
   lifetimeMS           = 750;
   lifetimeVarianceMS   = 150;
   textureName          = "~/data/shapes/rifle/smokeParticle";
   colors[0]     = "0 0.2 1 1.0";
   colors[1]     = "0 0.2 1 0.0";
   sizes[0]      = 0.5;
   sizes[1]      = 1.0;
};

datablock ParticleEmitterData(ScoutFlyerExplosionEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles		= "ScoutFlyerExplosionParticle";
};

// TODOs from here
datablock ParticleEmitterData(VehicleLiftoffDustEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles		= "ScoutFlyerExplosionParticle";
};


datablock ExplosionData(ScoutFlyerExplosion)
{
   explosionShape = "~/data/shapes/vehicles/air_scout.dts";

   particleEmitter = ScoutFlyerExplosionEmitter;
   particleDensity = 50;
   particleRadius = 0.2;

   faceViewer     = true;
   explosionScale = "1 1 1";

   shakeCamera = true;
   camShakeFreq = "10.0 11.0 10.0";
   camShakeAmp = "1.0 1.0 1.0";
   camShakeDuration = 0.5;
   camShakeRadius = 10.0;
};

datablock ParticleEmitterData(ScoutFlyerEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles		= "ScoutFlyerExplosionParticle";
};



datablock ParticleEmitterData(ScoutFlyerContrailEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles		= "ScoutFlyerExplosionParticle";
};
datablock ParticleEmitterData(ScoutFlyerEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles		= "ScoutFlyerExplosionParticle";
};

//trailEmitter = ScoutFlyerContrailEmitter;
//forwardJetEmitter = ScoutFlyerEmitter;
//downJetEmitter = ScoutFlyerEmitter;
//
//jetSound = ScoutFlyerThrustSound;
//engineSound = ScoutFlyerEngineSound;
//softImpactSound = SoftImpactSound;
//hardImpactSound = HardImpactSound;
//wheelImpactSound = WheelImpactSound;
//exitingWater = VehicleExitWaterMediumSound;
//impactWaterEasy = VehicleImpactWaterSoftSound;
//impactWaterMedium = VehicleImpactWaterMediumSound;
//impactWaterHard = VehicleImpactWaterMediumSound;
//waterWakeSound = VehicleWakeMediumSplashSound;

//dustEmitter = VehicleLiftoffDustEmitter;
//damageEmitter[0] = ScoutFlyerEmitter;
//damageEmitter[1] = ScoutFlyerEmitter;
//damageEmitter[2] = ScoutFlyerEmitter;
//splashEmitter[0] = VehicleFoamDropletsEmitter;
//splashEmitter[1] = VehicleFoamEmitter;

//shieldImpact = VehicleShieldImpact;




datablock DebrisData(FlyingShapeDebris)
{
	explodeOnMaxBounce = false;

	elasticity = 0.15;
	friction = 0.5;

	lifetime = 4.0;
	lifetimeVariance = 0.0;

	minSpinSpeed = 40;
	maxSpinSpeed = 600;

	numBounces = 5;
	bounceVariance = 0;

	staticOnMaxBounce = true;
	gravModifier = 1.0;

	useRadiusMass = true;
	baseRadius = 1;

	velocity = 20.0;
	velocityVariance = 12.0;
};


datablock FlyingVehicleData(AirScout)
{
   spawnOffset = "0 0 2";

   category = "Vehicles";
   shapeFile = "~/data/shapes/vehicles/ferrari/air_scout.dts";
   multipassenger = false;
   computeCRC = true;

   debrisShapeName = "~/data/shapes/vehicles/ferrari/air_scout_debris.dts";
   debris = FlyingShapeDebris;
   renderWhenDestroyed = false;

   drag = 0.15;
   density = 1.0;

   mountPose[0] = sitting;
   numMountPoints = 1;
   isProtectedMountPoint[0] = true;
   cameraMaxDist = 15;
   cameraOffset = 2.5;
   cameraLag = 0.9;
   explosion = ScoutFlyerExplosion;
   explosionDamage = 0.5;
   explosionRadius = 5.0;

   maxDamage = 90.00;
   destroyedLevel = 90.00;

   isShielded = true;
   energyPerDamagePoint = 160;
   maxEnergy = 280; // Afterburner and any energy weapon pool
   minDrag = 80; // Linear Drag (eventually slows you down when not thrusting...constant drag)
   rotationalDrag = 10; // Anguler Drag (dampens the drift after you stop moving the mouse...also tumble drag)
   rechargeRate = 0.0;

   maxAutoSpeed = 15; // Autostabilizer kicks in when less than this speed. (meters/second)
   autoAngularForce = 15; // Angular stabilizer force (this force levels you out when autostabilizer kicks in)
   autoLinearForce = 15; // Linear stabilzer force (this slows you down when autostabilizer kicks in)
   autoInputDamping = 0.95; // Dampen control input so you don't` whack out at very slow speeds
   // Maneuvering
   maxSteeringAngle = 5; // Max radiens you can rotate the wheel. Smaller number is more maneuverable.
   horizontalSurfaceForce = 10; // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning)
   verticalSurfaceForce = 100; // Vertical center "wing" (controls side slip. lower numbers make MORE slide.)
   maneuveringForce = 3000; // Horizontal jets (W,S,D,A key thrust)
   steeringForce = 500; // Steering jets (force applied when you move the mouse)
   steeringRollForce = 8; // Steering jets (how much you heel over when you turn)
   rollForce = 100; // Auto-roll (self-correction to right you after you roll/invert)
   hoverHeight = 5; // Height off the ground at rest
   createHoverHeight = 3; // Height off the ground when created

   //maxSteeringAngle = 5; // Max radiens you can rotate the wheel. Smaller number is more maneuverable.
   //horizontalSurfaceForce = 6; // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning)
   //verticalSurfaceForce = 4; // Vertical center "wing" (controls side slip. lower numbers make MORE slide.)
   //maneuveringForce = 2500; // Horizontal jets (W,S,D,A key thrust)
   //steeringForce = 1200; // Steering jets (force applied when you move the mouse)
   //steeringRollForce = 400; // Steering jets (how much you heel over when you turn)
   //rollForce = 4; // Auto-roll (self-correction to right you after you roll/invert)
   //hoverHeight = 5; // Height off the ground at rest
   //createHoverHeight = 3; // Height off the ground when created



   // Rigid body
   mass = 100; // Mass of the vehicle
   bodyFriction = 0; // Don't mess with this.
   bodyRestitution = 0.5; // When you hit the ground, how much you rebound. (between 0 and 1)
   minRollSpeed = 0; // Don't mess with this.
   minImpactSpeed = 1; // If hit ground at speed above this then it's an impact. Meters/second
   softImpactSpeed = 10; // Sound hooks. This is the soft hit.
   hardImpactSpeed = 25; // Sound hooks. This is the hard hit.
   speedDamageScale = 0.04;

   collDamageThresholdVel = 20.0;
   collDamageMultiplier = 0.02;

   //
   minTrailSpeed = 15; // The speed your contrail shows up at.

   trailEmitter = ScoutFlyerContrailEmitter;
   forwardJetEmitter = ScoutFlyerEmitter;
   downJetEmitter = ScoutFlyerEmitter;

   //
   //jetSound = ScoutFlyerThrustSound;
   //engineSound = ScoutFlyerEngineSound;
   //softImpactSound = SoftImpactSound;
   //hardImpactSound = HardImpactSound;
   //wheelImpactSound = WheelImpactSound;

   //
   softSplashSoundVelocity = 15.0;
   mediumSplashSoundVelocity = 30.0;
   hardSplashSoundVelocity = 60.0;
   exitSplashSoundVelocity = 20.0;

   //exitingWater = VehicleExitWaterMediumSound;
   //impactWaterEasy = VehicleImpactWaterSoftSound;
   //impactWaterMedium = VehicleImpactWaterMediumSound;
   //impactWaterHard = VehicleImpactWaterMediumSound;
   //waterWakeSound = VehicleWakeMediumSplashSound;

   dustEmitter = VehicleLiftoffDustEmitter;
   triggerDustHeight = 4.0;
   dustHeight = 1.0;

   damageEmitter[0] = ScoutFlyerEmitter;
   damageEmitter[1] = ScoutFlyerEmitter;
   damageEmitter[2] = ScoutFlyerEmitter;
   damageEmitterOffset[0] = "0.0 -3.0 0.0 ";
   damageLevelTolerance[0] = 0.3;
   damageLevelTolerance[1] = 0.7;
   numDmgEmitterAreas = 3;

   //
   max[chaingunAmmo] = 1000;

   minMountDist = 4;

   //splashEmitter[0] = VehicleFoamDropletsEmitter;
   //splashEmitter[1] = VehicleFoamEmitter;

   //shieldImpact = VehicleShieldImpact;

   checkRadius = 5.5;
   observeParameters = "1 10 10";
};



function FlyingVehicleData::create(%block)
{
   %obj = new FlyingVehicle() {
      dataBlock = %block;
   };
   %obj.mountable = true;
   return(%obj);
}


// added for a weapon on the vehicle: - beffy 04/07/02
function FlyingVehicleData::onAdd(%this,%obj)
{
   %data = %obj.getDataBlock();
	%obj.setEnergyLevel(%data.maxEnergy);
        %obj.setImageAmmo(3,true);


      %obj.mountImage(carbowimage,0);
      %obj.mountImage(carbow2image,1);
      %obj.setImageAmmo(0,1);
      %obj.setImageAmmo(1,1);

}


function FlyingVehicleData::onCollision(%this,%obj,%col,%vec,%speed)
{
   // Collision with other objects, including items
   //echo("collision");
}   

function FlyingVehicleData::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
   %obj.applyDamage(%damage);
}

function FlyingVehicleData::onDamage(%this, %obj)
{
   //echo("damage");
   //Parent::onDamage(%this, %obj);

   %damage = %obj.getDamageLevel();
   if (%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         if(%obj.respawnTime !$= "")
            %obj.marker.schedule = %obj.marker.data.schedule(%obj.respawnTime, "respawn", %obj.marker); 
         %obj.setDamageState(Destroyed);
      }
   }
   else
   {
      if(%obj.getDamageState() !$= "Enabled")
         %obj.setDamageState(Enabled);
   }
}
function FlyingVehicleData::onDestroyed(%data, %obj, %prevState)
{
	radiusVehicleExplosion(%data, %obj);
   if(%obj.turretObject)
      if(%obj.turretObject.getControllingClient())
         %obj.turretObject.getDataBlock().playerDismount(%obj.turretObject);
   for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++)
   {
      if (%obj.getMountNodeObject(%i)) {
         %flingee = %obj.getMountNodeObject(%i);
         %flingee.getDataBlock().doDismount(%flingee, true);
         %xVel = 250.0 - (getRandom() * 500.0);
         %yVel = 250.0 - (getRandom() * 500.0);
         %zVel = (getRandom() * 100.0) + 50.0;
         %flingVel = %xVel @ " " @ %yVel @ " " @ %zVel;
         %flingee.applyImpulse(%flingee.getTransform(), %flingVel);
         %flingee.damage(0, %obj.getPosition(), 0.4, $DamageType::Explosion); 
      }
   }
   %obj.schedule(300, "delete");
}


function radiusVehicleExplosion(%data, %vehicle)
{
	// this is a modified version of RadiusExplosion() from projectiles.cs
	%position = %vehicle.getPosition();
   InitContainerRadiusSearch(%position, %data.explosionRadius, $TypeMasks::PlayerObjectType      |
                                                 $TypeMasks::VehicleObjectType     |
                                                 $TypeMasks::MoveableObjectType    |
                                                 $TypeMasks::StaticShapeObjectType |
                                                 $TypeMasks::ForceFieldObjectType  |
                                                 $TypeMasks::TurretObjectType      |
                                                 $TypeMasks::ItemObjectType);

   %numTargets = 0;
   while ((%targetObject = containerSearchNext()) != 0)
   {
		if(%targetObject == %vehicle)
			continue;

      %dist = containerSearchCurrRadDamageDist();

      if (%dist > %data.explosionRadius)
         continue;

      if (%targetObject.isMounted())
      {
         %mount = %targetObject.getObjectMount();
			if(%mount == %vehicle)
				continue;

         %found = -1;
         for (%i = 0; %i < %mount.getDataBlock().numMountPoints; %i++)
         {
            if (%mount.getMountNodeObject(%i) == %targetObject)
            {
               %found = %i;
               break;
            }
         }
      
         if (%found != -1)
         {
            if (%mount.getDataBlock().isProtectedMountPoint[%found] && (%mount != %vehicle))
               continue;
         }
      }

      %targets[%numTargets]     = %targetObject;
      %targetDists[%numTargets] = %dist;
      %numTargets++;
   }

   for (%i = 0; %i < %numTargets; %i++)
   {
      %targetObject = %targets[%i];
      %dist = %targetDists[%i];

      %coverage = calcExplosionCoverage(%position, %targetObject,
                                        ($TypeMasks::InteriorObjectType |
                                         $TypeMasks::TerrainObjectType |
                                         $TypeMasks::ForceFieldObjectType));
      if (%coverage == 0)
         continue;

      %amount = (1.0 - (%dist / %data.explosionRadius)) * %coverage * %data.explosionDamage;
      %targetData = %targetObject.getDataBlock();

      %momVec = "0 0 1";
      
      if(%amount > 0)
         %targetData.damageObject(%targetObject, %sourceObject, %position, %amount, $DamageType::Explosion, %momVec);
   }
}

function VehicleData::onRemove(%this, %obj)
{
   // if there are passengers/driver, kick them out
   //%this.deleteAllMounted(%obj);
   //for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++)
   //  if (%obj.getMountNodeObject(%i)) {
   //      %passenger = %obj.getMountNodeObject(%i);
   //      %passenger.unmount();
   //   }
   //vehicleListRemove(%obj.getDataBlock(), %obj);
   //if(%obj.lastPilot.lastVehicle == %obj)
   //   %obj.lastPilot.lastVehicle = "";      

   //Parent::onRemove(%this, %obj);
}

function FlyingVehicleData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec)
{
   // check for team damage
   %sourceClient = %sourceObject ? %sourceObject.getOwnerClient() : 0;
   %targetTeam = getTargetSensorGroup(%targetObject.getTarget());

   if(%sourceClient)
      %sourceTeam = %sourceClient.getSensorGroup();
   else if(isObject(%sourceObject) && %sourceObject.getClassName() $= "Turret")
      %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget());
   else
      %sourceTeam = %sourceObject ? getTargetSensorGroup(%sourceObject.getTarget()) : -1;

   if(!$teamDamage && (%targetTeam == %sourceTeam))
      return;

   // Scale damage type & include shield calculations...
   if (%data.isShielded)
      %amount = %data.checkShields(%targetObject, %position, %amount, %damageType);
   
   %damageScale = %data.damageScale[%damageType];
   if(%damageScale !$= "")
      %amount *= %damageScale;
      
   if(%amount != 0)
      %targetObject.applyDamage(%amount);
      
   if(%targetObject.getDamageState() $= "Destroyed" && %momVec !$= "")
      %targetObject.setMomentumVector(%momVec);
}

function FlyingVehicleData::onImpact(%data, %vehicleObject, %collidedObject, %vec, %vecLen)
{
   //echo("impact");
   if(%vecLen > %data.minImpactSpeed)
      %data.damageObject(%vehicleObject, 0, VectorAdd(%vec, %vehicleObject.getPosition()), 
                         %vecLen * %data.speedDamageScale, $DamageType::Ground);

   // associated "crash" sounds
   if(%vecLen > %vDataBlock.hardImpactSpeed)
      %vehicleObject.playAudio(0, %vDataBlock.hardImpactSound);
   else if(%vecLen > %vDataBlock.softImpactSpeed)
      %vehicleObject.playAudio(0, %vDataBlock.softImpactSound);
}   

function FlyingVehicleData::onTrigger(%data, %obj, %trigger, %state)
{
   // data = datablock
   // obj = object number
   // trigger = 0 for "fire", 1 for "jump", 3 for "thrust"
   // state = 1 for firing, 0 for not firing
   if(%trigger == 0)
   {
      switch (%state) {
         case 0:
            %obj.fireWeapon = false;
            %obj.setImageTrigger(0, false);
            %obj.setImageTrigger(1, false);
         case 1:
            %obj.fireWeapon = true;
            if(%obj.nextWeaponFire == 0) {
               %obj.setImageTrigger(0, true);
               %obj.setImageTrigger(1, false);
            }
            else {
               %obj.setImageTrigger(0, false);
               %obj.setImageTrigger(1, true);
            }
      }
   }
}

function CarbowImage::onFire(%data,%obj,%slot)
{
   Parent::onFire(%data,%obj,%slot);
   %obj.nextWeaponFire = 1;
   schedule(%data.fireTimeout, 0, "fireNextGun", %obj);   
}

function Carbow2Image::onFire(%data,%obj,%slot)
{
   Parent::onFire(%data,%obj,%slot);
   %obj.nextWeaponFire = 0;
   schedule(%data.fireTimeout, 0, "fireNextGun", %obj);
}

function CarbowImage::onTriggerDown(%this, %obj, %slot)
{
}

function CarbowImage::onTriggerUp(%this, %obj, %slot)
{
}

function fireNextGun(%obj)
{
   if(%obj.fireWeapon)
   {
      if(%obj.nextWeaponFire == 0)
      {
         %obj.setImageTrigger(0, true);
         %obj.setImageTrigger(1, false);
      }
      else
      {
         %obj.setImageTrigger(0, false);
         %obj.setImageTrigger(1, true);
      }
   }
   else
   {
      %obj.setImageTrigger(0, false);
      %obj.setImageTrigger(1, false);
   }
}

function ShapeBaseImageData::onFire(%data, %obj, %slot)
{
	%projectile = %data.projectile;
	
	%muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));
   
   %vehicle = 0;
   
       %p = new (%data.projectileType)() {
         dataBlock        = %data.projectile;
         initialVelocity  = %muzzleVelocity;
         initialDirection = %obj.getMuzzleVector(%slot);
         initialPosition  = %obj.getMuzzlePoint(%slot);
         sourceObject     = %obj;
         sourceSlot       = %slot;
         vehicleObject    = %vehicle;
      };
 
   if (isObject(%obj.lastProjectile) && %obj.deleteLastProjectile)
      %obj.lastProjectile.delete();

   %obj.lastProjectile = %p;
   %obj.deleteLastProjectile = %data.deleteLastProjectile;
   
   MissionCleanup.add(%p);
 
   return %p;
}

datablock ShapeBaseImageData(CarbowImage)
{
   // Basic Item properties
   shapeFile = "~/data/shapes/vehicles/ferrari/carbow.dts";
   emap = true;

   // Specify mount point & offset for 3rd person, and eye offset
   // for first person rendering.
   mountPoint = 0;
   offset = "0 0 0";
   correctMuzzleVector = false;
   className = "WeaponImage";

   projectile = CrossbowProjectile;
   projectileType = Projectile;
	fireTimeout = 300;

   // Initial start up state
   stateName[0]                     = "Preactivate";
   stateTransitionOnLoaded[0]       = "Activate";
   stateTransitionOnNoAmmo[0]       = "Activate";

   // Activating the gun.  Called when the weapon is first
   // mounted and there is ammo.
   stateName[1]                     = "Activate";
   stateTransitionOnTimeout[1]      = "Ready";
   stateTimeoutValue[1]             = 0.6;
   stateSequence[1]                 = "Activate";

   // Ready to fire, just waiting for the trigger
   stateName[2]                     = "Ready";
   stateTransitionOnNoAmmo[2]       = "Activate";
   stateTransitionOnTriggerDown[2]  = "Fire";

   // Fire the weapon. Calls the fire script which does 
   // the actual work.
   stateName[3]                     = "Fire";
   stateTransitionOnTimeout[3]      = "Reload";
   stateTimeoutValue[3]             = 0.2;
   stateFire[3]                     = true;
   stateRecoil[3]                   = LightRecoil;
   stateAllowImageChange[3]         = false;
   stateSequence[3]                 = "Fire";
   stateScript[3]                   = "onFire";

   // Play the relead animation, and transition into
   stateName[4]                     = "Reload";
   stateTransitionOnNoAmmo[4]       = "Activate";
   stateTransitionOnTimeout[4]      = "Ready";
   stateTimeoutValue[4]             = 0.8;
   stateAllowImageChange[4]         = false;
   stateSequence[4]                 = "Reload";
   stateEjectShell[4]               = true;

   // No ammo in the weapon, just idle until something
   // shows up. Play the dry fire sound if the trigger is
   // pulled.
   stateName[5]                     = "Activate";
   stateTransitionOnAmmo[5]         = "Reload";
   stateSequence[5]                 = "Activate";
   stateTransitionOnTriggerDown[5]  = "DryFire";

   // No ammo dry fire
   stateName[6]                     = "DryFire";
   stateTimeoutValue[6]             = 1.0;
   stateTransitionOnTimeout[6]      = "Activate";
};

//datablock ShapeBaseImageData(Carbow2Image : CarbowImage)
//{
//   mountPoint = 1;
//};



