
datablock ExplosionData(ArtillerySubExplosion)
{
   debris = SatchelDebris;
   debrisThetaMin = 10;
   debrisThetaMax = 170;
   debrisNum = 16;
   debrisVelocity = 60.0;
   debrisVelocityVariance = 15.0;

   lifetimeMS = 2000;
   delayMS = 100;

   emitter[0] = SatchelExplosionSmokeEmitter;
   emitter[1] = SatchelSparksEmitter;

   offset = 9.0;

   sizes[0] = "1.0 1.0 1.0";
   sizes[1] = "1.0 1.0 1.0";
   times[0] = 0.0;
   times[1] = 1.0;
};

datablock ExplosionData(ArtilleryExplosion)
{
   soundProfile = SatchelChargePreExplosionSound;
   
   subExplosion[0] = ArtillerySubExplosion;
   subExplosion[1] = ArtillerySubExplosion;
};

datablock LinearProjectileData(LinearArtilleryShot)
{
   projectileShapeName = "grenade_projectile.dts";
   scale     = "3.0 3.0 3.0";

   directDamage        = 0.0;
   hasDamageRadius     = true;
   indirectDamage      = 1.50;
   damageRadius        = 24;
   radiusDamageType    = $DamageType::Explosive;
   kickBackStrength    = 4500;

   explosion           = ArtilleryExplosion;
   velInheritFactor    = 0;

   dryVelocity         = 250;
   fizzleTimeMS        = 4000;
   lifetimeMS          = 5000;
   explodeOnDeath      = false;

   sound               = MortarProjectileSound;
};

datablock GrenadeProjectileData(ArtilleryShot)
{
   projectileShapeName = "grenade_projectile.dts";
   scale     = "3.0 3.0 3.0";

   directDamage        = 0.0;
   hasDamageRadius     = true;
   indirectDamage      = 1.50;
   damageRadius        = 24;
   radiusDamageType    = $DamageType::Explosive;
   kickBackStrength    = 4500;

   explosion           = ArtilleryExplosion;
   velInheritFactor    = 0;

   grenadeElasticity   = 0.0;
   grenadeFriction     = 1.0;
   armingDelayMS       = 250;
   muzzleVelocity      = 250;
   drag                = 0.0;

   sound               = MortarProjectileSound;
};

datablock ItemData(ArtilleryBarrelSmoke)
{
   className = Other;
   shapeFile = "turret_muzzlepoint.dts";

   mass = 10.0;

   sticky = true;

   elasticity = 0.0;
   friction = 1.0;

   maxDamage = 100;

   explosion = HandGrenadeExplosion;

   indirectDamage   = 0.4;
   damageRadius     = 10.0;
   radiusDamageType = $DamageType::Explosion;
   kickBackStrength = 2000;
};

datablock ItemData(ArtilleryDischargeSmoke)
{
   className = Other;
   shapeFile = "turret_muzzlepoint.dts";

   mass = 0.1;

   sticky = true;

   elasticity = 0.0;
   friction = 1.0;

   maxDamage = 100;

   explosion = DeployablesExplosion;

   indirectDamage   = 0.1;
   damageRadius     = 2.0;
   radiusDamageType = $DamageType::Explosion;
   kickBackStrength = 800;
};

datablock AudioDescription(LouderAudioClose3d)
{
   volume   = 3.0;
   isLooping= false;

   is3D     = true;
   minDistance= 10.0;
   MaxDistance= 90.0;
   type     = $EffectAudioType;
};

datablock AudioDescription(LoudAudioClosest3d)
{
   volume   = 1.6;
   isLooping= false;

   is3D     = true;
   minDistance= 5.0;
   MaxDistance= 20.0;
   type     = $EffectAudioType;
};

datablock AudioProfile(ArtilleryFireSound)
{
   filename    = "fx/weapons/mortar_explode.wav";
   description = LouderAudioClose3d;
   preload = true;
};

datablock AudioProfile(ArtilleryReloadSound)
{
   filename    = "fx/weapons/mortar_reload.wav";
   description = LoudAudioClosest3d;
   preload = true;
};


datablock ItemData(ArtilleryShell)
{
   shapeFile = "grenade_projectile.dts";
   scale     = "3.0 3.0 3.0";

   mass = 1.0;
   elasticity = 0.0;
   friction = 1;
   drag = 0.1;

   sticky = true;

   hasDamageRadius     = true;
   indirectDamage      = 1.5;
   damageRadius        = 26;
   radiusDamageType    = $DamageType::Explosion;
   kickBackStrength    = 3250;

   explosion           = "VehicleBombExplosion";

   sound                = BomberBombProjectileSound;

   emap = true;
};

// Let it explode if it hits an object.
function ArtilleryShell::onCollision(%Data, %Shell, %ColidingObject)
{
   %Shell.setDamageState(Destroyed);
}

// Let it explode if it hits the ground or some other non-object.
function ArtilleryShell::onStickyCollision(%Data, %Shell)
{
   %Shell.setDamageState(Destroyed);
}

// Let it explode if it goes into the water.
function ArtilleryShell::onEnterLiquid(%Data, %Shell, %Coverage, %Type)
{
   %Shell.setDamageState(Destroyed);
}

function ArtilleryShell::onDestroyed(%Data, %Shell, %prevState)
{
   // If it already exploded somehow, ignore the second attempt
   if (%Shell.detonated == true)
      return;

   %Position = posFromTransform(%Shell.getTransform());

   %Radius = %Data.damageRadius;
   %Damage = %Data.indirectDamage;
   %KickBack = %Data.kickBackStrength;
   %DamageType = %Data.radiusDamageType;

   // Explosion Damage
   RadiusExplosion(%Shell, %Position, %Radius, %Damage, %KickBack, 0, %DamageType);

   %Shell.detonated = true;
   %Shell.schedule(500,"delete");
}

function OffMapArtillery(%Position, %Spread, %Frequency, %Duration, %Delay)
{
   if (%Position $= "")
   {
      logEcho("Unable to start Artillery, center position is not defined.");
      Echo("Unable to start Artillery, center position is not defined.");
      return;
   }

   if (%Spread $= "")
   {
      logEcho("Unable to start Artillery, spread from center position is not defined.");
      Echo("Unable to start Artillery, spread from center position is not defined.");
      return;
   }

   if (%Spread < 25)
   {
      logEcho("Unable to start Artillery, spread from center position is too small.  Can not bombard area less than 50 meters in diameter.");
      Echo("Unable to start Artillery, spread from center position is too small.");
      echo("Can not bombard area less than 50 meters in diameter.");
      return;
   }

   if (%Frequency $= "")
   {
      logEcho("Unable to start Artillery, frequency of artillery barrage not defined.");
      Echo("Unable to start Artillery, frequency of artillery barrage not defined.");
      return;
   }

   if (%Frequency < 5)
   {
      logEcho("Unable to start Artillery, frequency of artillery barrage is too low.  Can not bombard map more often then once every 5 seconds.");
      Echo("Unable to start Artillery, frequency of artillery barrage is too low.");
      echo("Can not bombard map more often then once every 5 seconds.");
      return;
   }

   // If Duration is not passed, we do this up to 16.67 hours
   if (%Duration $= "")
      %Duration = 60000;

   // If this is not passed or set to 0, warn the server owner but continue anyways.
   if (%Delay $= "" || %Delay == 0)
   {
      logEcho("Starting bombardment right away, if there are errors try setting this to at least 10.");
      Echo("Starting bombardment right away, if there are errors try setting this to at least 10.");
   }

   // Strip the Z factor and start the artillery falling from 2000 feet up
   %PositionXY = getWords(%Position, 0, 1);
   %Position = %PositionXY @ " 2000";

   schedule(%Delay * 1000, 0, BombardPosition, %Position, %Spread, %Frequency, %Duration, %Position);
}

function BombardPosition(%Position, %Spread, %Frequency, %Duration, %AbsolutePosition)
{
   // Create a new shell and throw it towards the ground
   %ArtilleryShell = new Item()
   {
      dataBlock = ArtilleryShell;
      position = %Position;
      scale = ArtilleryShell.Scale;
   };
   MissionCleanUp.Add(%ArtilleryShell);

   %ArtilleryShell.ApplyImpulse(%Position, "0 0 -100");

   %PositionX = getWord(%Position, 0);
   %PositionY = getWord(%Position, 1);

   %PositionFound = false;   

   // Attempt to pick a new random location based on where the last one landed
   // Compare the location to the absolute one passed and if within the spread
   // accept it and prepare for the next firing.
   while (%PositionFound == false)
   {
      %PositionOffsetX = (getRandom() * %Spread * 0.85) - (%Spread * 0.45);
      %PositionOffsetY = (getRandom() * %Spread * 0.85) - (%Spread * 0.45);

      %TestPosition = %PositionX + %PositionOffsetX @ " " @ %PositionY + %PositionOffsetY @ " 2000";

      %DistanceFromCenter = VectorLen(VectorSub(%AbsolutePosition, %TestPosition));

      if (%DistanceFromCenter <= %Spread)
         %PositionFound = true;
   }   

   // Reduce the Time left
   %Duration -= %Frequency;

   // If there is still time left, we fire again
   if (%Duration > 0)
      schedule(%Frequency * 1000, 0, BombardPosition, %TestPosition, %Spread, %Frequency, %Duration, %AbsolutePosition);
}