
//--------------------------------------------------------------------------
// Satchel Charge pack
// can be used by any armor type
// when activated, throws the pack -- when activated again (before
// picking up another pack), detonates with a BIG explosion.


//-------------------------------------------------------------------------
// shapebase datablocks
datablock ShapeBaseImageData(SatchelChargeImage)
{
   shapeFile = "pack_upgrade_satchel.dts";
   item = SatchelCharge;
   mountPoint = 1;
   mass = 2.5;
   offset = "0 0 0";
   emap = true;
};

datablock ItemData(SatchelCharge)
{
   className = Pack;
   catagory = "Packs";
   image = SatchelChargeImage;
   shapeFile = "pack_upgrade_satchel.dts";
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
   rotate = true;
   pickUpName = "a satchel charge pack";

   computeCRC = true;
};

datablock ItemData(SatchelChargeThrown)
{
   shapeFile = "pack_upgrade_satchel.dts";

   mass = 1.2;
   elasticity = 1.0;
   friction = 1.0;

   sticky = true;

   rotate = false;
   pickupRadius = 0;

   noTimeout = true;

   armDelay = 3000;
   maxDamage = 0.6;

   explosion = SatchelMainExplosion;
   underwaterExplosion = UnderwaterSatchelMainExplosion;

   indirectDamage      = 1.2;
   damageRadius        = 22.0;
   radiusDamageType    = $DamageType::Explosion;
   kickBackStrength    = 4000;

   computeCRC = true;
};

datablock ItemData(SatchelChargePremature)
{
   shapeFile = "pack_upgrade_satchel.dts";

   mass = 1.2;
   elasticity = 1.0;
   friction = 1.0;

   sticky = true;

   rotate = false;
   pickupRadius = 0;

   noTimeout = true;

   armDelay = 3000;
   maxDamage = 0.6;

   explosion = SatchelMainExplosion;
   underwaterExplosion = UnderwaterSatchelMainExplosion;

   indirectDamage      = 0.68;
   damageRadius        = 14.0;
   radiusDamageType    = $DamageType::Explosion;
   kickBackStrength    = 2600;

   computeCRC = true;
};

datablock ItemData(SatchelChargeTwart)
{
   shapeFile = "pack_upgrade_satchel.dts";

   mass = 1.2;
   elasticity = 1.0;
   friction = 1.0;
   sticky = true;

   rotate = false;
   pickupRadius = 0;

   noTimeout = true;

   armDelay = 3000;
   maxDamage = 0.6;

   explosion = HandGrenadeExplosion;
   underwaterExplosion = UnderwaterHandGrenadeExplosion;

   indirectDamage      = 0.3;
   damageRadius        = 8.0;
   radiusDamageType    = $DamageType::Explosion;
   kickBackStrength    = 1000;

   computeCRC = true;
};

//--------------------------------------------------------------------------

function SatchelCharge::onUse(%this, %Player)
{
   %Item = new Item() {
      dataBlock = SatchelChargeThrown;
      rotation = "0 0 1 " @ (getRandom() * 6.2831852);  // 2 * PI
   };
   MissionCleanup.add(%Item);

   // take pack out of inventory and unmount image
   %Player.decInventory(SatchelCharge, 1);
   %Player.throwObject(%Item, 60);
   %Player.thrownChargeId = %Item;

   %Item.armed = false;
   %Item.damaged = 0.0;
   %Item.sourceObject = %Player;

   // arm itself 3 seconds after being thrown
   schedule(%Item.getDatablock().armDelay, %Item, "initArmSatchelCharge", %Item);
   messageClient(%Player.client, 'MsgSatchelChargePlaced', "\c2Satchel charge deployed.");
}

function initArmSatchelCharge(%Charge)
{
   // "deet deet deet" sound
   %Charge.playAudio(1, SatchelChargeActivateSound);

   // also need to play "antenna extending" animation
   %Charge.playThread(0, "deploy");
   %Charge.playThread(1, "activate");

   // delay the actual arming until after sound is done playing
   schedule(2200, 0, "armSatchelCharge", %Charge);
}

function armSatchelCharge(%Charge)
{
   %Charge.armed = true;
}

function Player::detonateSatchelCharge(%Player)
{
   %Charge = %Player.thrownChargeId;

   echo("Satchel Charge: " @ %Charge);

   // can't detonate the satchel charge if it isn't armed
   if(%Charge.armed != true)
      return;

   if(%Charge.getDamageState() !$= Destroyed)
      %Charge.setDamageState(Destroyed);

   %Player.thrownChargeId = "";
}

function SatchelChargeThrown::onEnterLiquid(%data, %Charge, %Coverage, %Type)
{
   // lava types
   if(%Type >=4 && %type <= 6)
   {
      if(%Charge.getDamageState() !$= "Destroyed")
      {
         %Charge.armed = true;
         %Charge.sourceObject.detonateSatchelCharge();
      }
      return;   
   }
      
   Parent::onEnterLiquid(%data, %Charge, %Coverage, %Type);
}

function SatchelChargeImage::onMount(%data, %obj, %node)
{
   %obj.thrownChargeId = 0;
}

function SatchelChargeImage::onUnmount(%data, %obj, %node)
{
   // Created to reduce console spam
}

function SatchelChargeThrown::onCollision(%data, %Charge, %Player)
{
   if (%Charge.kaboom == true)
      return;

   %Charge.setVelocity("0 0 0");

   if (%Charge.team == %Player.team)
      return;

   %Armor = %Player.getArmorSize();
   if (%Armor !$= "Engineer")
      return;

   %Charge.kaboom = true;
   %Charge.sourceObject.thrownChargeId = "";

   %Random = getRandom();
   echo("Random Value: " @ %Random);
   if (%Random > 0.985)
   {
      %Charge.playAudio(1, SatchelChargePreExplosionSound);
      schedule(2250, 0, detonateGrenade, %Charge);

      messageClient(%Player.client, 'msgSatchelChargeDetonate', "\c2Oops, wrong wire...");
      messageClient(%Charge.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge detonated!");
   } else {

      %Charge.schedule(500, delete);

      messageClient(%Player.client, 'msgSatchelChargeDetonate', "\c2Satchel charge disarmed!");
      messageClient(%Charge.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Lost contact with Satchel Charge.");
   }
}

// When it is blown, do this code.
function SatchelChargeThrown::onDestroyed(%this, %Charge, %lastState)
{
   if (%Charge.kaboom == true)
      return;

   %Charge.sourceObject.thrownChargeId = "";

   messageClient(%Charge.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge detonated!");

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

   %Data = %Charge.getDataBlock();
   %Radius = %Data.damageRadius;
   %DamageAmount = %Data.indirectDamage;
   %KickBack = %Data.kickBackStrength;
   %DamageType = %Data.radiusDamageType;

   RadiusExplosion(%Charge, %Position, %Radius, %DamageAmount, %KickBack, %Charge.sourceObject, %DamageType);

   %Charge.schedule(400, "delete");
}

// When it is damaged, do this.  If it is destroyed, then we replace it with a smaller
// explosive and detonate that to show it was not destroyed by detonating it.
function SatchelChargeThrown::damageObject(%data, %Charge, %SourceObject, %Position, %Amount, %DamageType)
{
   if (%Charge.kaboom == true)
      return;

   %Charge.damaged += %Amount;

   if(%Charge.damaged < %Charge.getDataBlock().maxDamage)
      return;

   // Replace the real satchel with one that looks like it and has a smaller explosion
   %Charge.thwart = true;
   %Charge.kaboom = true;

   messageClient(%Charge.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Lost contact with Satchel Charge.");

   %Transform = %Charge.getTransform();

   %Item = new Item()
   {
      datablock = SatchelChargeTwart;
      sourceObject = %Projectile.sourceObject;
   };
   MissionGroup.add(%Item);

   %Item.setTransform(%Transform);

   %Charge.schedule(350, delete);
   schedule(375, 0, detonateGrenade, %Item);
}

function SatchelCharge::onPickup(%this, %obj, %shape, %amount)
{
   // created to prevent console errors
}

function Player::PrematureSatchel(%Player)
{
   %Player.unMountImage($BackPackSlot);
   %Player.inv[SatchelCharge] = 0;

   %BackPackPosition = %Player.getMuzzlePoint($BackPackSlot);
   %Velocity = %Player.getVelocity();

   %Item = new Item()
   {
      dataBlock = SatchelChargePremature;
      position = %BackPackPosition;
      sourceObject = %Player;
   };
   MissionCleanUp.add(%Item);

   %Item.ApplyImpulse(%BackPackPosition, "0 0 5");
   schedule(650, 0, detonateGrenade, %Item);
}