
//-------------------------------------- Ammo functions
function Ammo::onCollision(%data, %obj, %col)
{
   // %data = datablock of object; %obj = object number
   // %col = thing that collided with object (hopefully a player)

   if (%col.getDataBlock().className $= Armor)
   {
      %ammoName = %data.getName();
      %ammoStore = %col.inv[%ammoName];

      // if player has ammo pack, increase max amount of ammo
      if(%col.getMountedImage($BackpackSlot) != 0)
      {
         if(%col.getMountedImage($BackpackSlot).getName() $= "AmmoPackImage")
            %aMax = (%col.getDataBlock().max[%ammoName]) + AmmoPack.max[%ammoName];
         else
            %aMax = %col.getDataBlock().max[%ammoName];
      }
      else
         %aMax = %col.getDataBlock().max[%ammoName];

      if(%col.inv[%ammoName] < %aMax)
      {
         %col.incInventory(%ammoName, $AmmoIncrement[%ammoName]);
         serverPlay3D(ItemPickupSound, %col.getTransform());
         %obj.respawn();
         if (%col.client > 0)
            messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName);
      }
   }
}

function GrenadeThrown::onCollision(%data, %obj, %col)
{
   // nothing you can do now...
}

function HandInventory::onCollision(%data, %obj, %col)
{
   // %data = datablock of object; %obj = object number
   // %col = thing that collided with object (hopefully a player)
   if (%col.getDataBlock().className $= Armor)
   {
      if (%data.AlternateObject !$= "")
      {
         %ammoName = %data.AlternateObject.getName();
         %increment = 1;
         %Repack = false;
      } else {
         %ammoName = %data.getName();
         %increment = $AmmoIncrement[%ammoName];
         %Repack = true;
      }

      %ammoStore = %col.inv[%ammoName];

      // if player has ammo pack, increase max amount of ammo
      if(%col.getMountedImage($BackpackSlot) != 0)
      {
         if(%col.getMountedImage($BackpackSlot).getName() $= "AmmoPackImage")
            %aMax = (%col.getDataBlock().max[%ammoName]) + AmmoPack.max[%ammoName];
         else
            %aMax = %col.getDataBlock().max[%ammoName];
      }
      else
         %aMax = %col.getDataBlock().max[%ammoName];

      if(%data.isGrenade)
      {
         // it's a grenade -- see if it matches the type the player is carrying
         %pgType = "None";
         for(%x = 0; $InvGrenade[%x] !$= ""; %x++)
         {
            %gren = $NameToInv[$InvGrenade[%x]];
            if(%col.inv[%gren] > 0)
            {
               %pgType = %gren;
               break;
            }
         }
         if((%pgType $= "None") || (%pgType $= %ammoName))
         {
            // player either has no grenades or this type of grenades -- OK to pick up more
            %canPickup = true;
         } else {
            // player has a different kind of grenade -- don't pick this kind up
            %canPickup = false;
         }
      } else {
         if(%data.isMine)
         {
            // it's a Mine -- see if it matches the type the player is carrying
            %pgType = "None";
            for(%x = 0; $InvMine[%x] !$= ""; %x++)
            {
               %Mine = $NameToInv[$InvMine[%x]];
               if (%col.inv[%Mine] > 0)
               {
                  %pgType = %Mine;
                  break;
               }
            }
            if ((%pgType $= "None") || (%pgType $= %ammoName))
            {
               // player either has no mine or this type of mine -- OK to pick up more
               %canPickup = true;
            } else {
               // player has a different kind of mine -- don't pick this kind up
              %canPickup = false;
            }
         } else
            %canPickup = true;
      }

      if(%canPickup)
      {
         if(%col.inv[%ammoName] < %aMax)
         {
            %col.incInventory(%ammoName, %increment);
            serverPlay3D(ItemPickupSound, %col.getTransform());

            if (%Repack == true)
               %obj.respawn();
            else
               %obj.delete();

            if (%col.client > 0)
               messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName);
         }
      }
   }
}

//-------------------------------------- Specific turret functions

function SentryTurret::onAdd(%data, %obj)
{
   Parent::onAdd(%data, %obj);

   //error("error");
   %obj.mountImage(%data.barrel, 0, true);
}

function TurretDeployedCamera::onAdd(%this, %obj)
{
   Parent::onAdd(%this, %obj);   
   %obj.mountImage(DeployableCameraBarrel, 0, true);
	%obj.setRechargeRate(%this.rechargeRate);
}

function TurretDeployedCamera::onDestroyed(%this, %obj, %prevState)
{
   Parent::onDestroyed(%this, %obj, %prevState);
   $TeamDeployedCount[%obj.team, DeployedCamera]--;
   // doesn't seem to delete itself, so...
   %obj.schedule(500, "delete");
}

function ScoutFlyer::playerDismounted(%data, %obj, %player)
{
   %obj.fireWeapon = false;
   %obj.setImageTrigger(2, false);
   %obj.setImageTrigger(3, false);
   setTargetSensorGroup(%obj.getTarget(), %obj.team);
}

function ScoutChaingunImage::onFire(%data,%obj,%slot)
{
   // obj = ScoutFlyer object number
   // slot = 2

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

function ScoutChaingunPairImage::onFire(%data,%obj,%slot)
{
   // obj = ScoutFlyer object number
   // slot = 3

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

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

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

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

function ScoutChaingunImage::onMount(%this, %obj, %slot)
{
//   %obj.setImageAmmo(%slot,true);
}

function ScoutChaingunPairImage::onMount(%this, %obj, %slot)
{
//   %obj.setImageAmmo(%slot,true);
}

function ScoutChaingunImage::onUnmount(%this,%obj,%slot)
{
}

function ScoutChaingunPairImage::onUnmount(%this,%obj,%slot)
{
}


function BomberTurret::onDamage(%data, %obj)
{
   %newDamageVal = %obj.getDamageLevel();
   if(%obj.lastDamageVal !$= "")
      if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal)   
         %obj.getObjectMount().setDamageLevel(%newDamageVal);
   %obj.lastDamageVal = %newDamageVal;
}

function BomberTurret::damageObject(%this, %damageObj, %projectile, %amount, %damageType)
{
   //If vehicle turret is hit then apply damage to the vehicle
   %vehicle = %damageObj.getObjectMount();
   %vehicle.getDataBlock().damageObject(%vehicle, %projectile, %amount, %damageType);
}

function VehicleTurret::onEndSequence(%data, %obj, %thread)
{
   if($DeployThread == %thread)
      %obj.stopThread($DeployThread);
}

function BomberTurret::onTrigger(%data, %obj, %trigger, %state)
{
   //error("onTrigger: trigger = " @ %trigger @ ", state = " @ %state);
   //error("obj = " @ %obj @ ", class " @ %obj.getClassName());
   switch (%trigger)
   {
      case 0:
         %obj.fireTrigger = %state;
         if(%obj.selectedWeapon == 1)
         {
            %obj.setImageTrigger(4, false);
            if(%obj.getImageTrigger(6))
            {
               %obj.setImageTrigger(6, false);
               ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj);
            }
            if(%state)
               %obj.setImageTrigger(2, true);
            else
               %obj.setImageTrigger(2, false);
         }
         else if(%obj.selectedWeapon == 2)
         {
            %obj.setImageTrigger(2, false);
            if(%obj.getImageTrigger(6))
            {
               %obj.setImageTrigger(6, false);
               ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj);
            }
            if(%state)
            {
               %Player = %obj.getControllingClient().player;

               DropBomb(%Player, %obj);
            } else
               %obj.setImageTrigger(4, false);
         } 
         else
         {
            %obj.setImageTrigger(2, false);

            if(%state)
               %obj.setImageTrigger(6, true);
            else
            {
               %obj.setImageTrigger(6, false);
               BomberTargetingImage::deconstruct(%obj.getMountedImage(6), %obj);
            }                   
         }

      case 2:
         if(%state)
         {
            %obj.getDataBlock().playerDismount(%obj);
         }
   }
}

function BomberTurret::playerDismount(%data, %obj)
{
   //Passenger Exiting
   %obj.fireTrigger = 0;
   %obj.setImageTrigger(2, false);
   %obj.setImageTrigger(4, false);
   if(%obj.getImageTrigger(6))
   {
      %obj.setImageTrigger(6, false);
      ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj);
   }
   %client = %obj.getControllingClient();
   commandToClient(%client, 'endBomberSight');
//   %client.player.setControlObject(%client.player);
   %client.player.mountVehicle = false;
//   %client.player.getDataBlock().doDismount(%client.player);
   if(%client.player.getState() !$= "Dead")
      %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot);
   setTargetSensorGroup(%obj.getTarget(), 0);
   setTargetNeverVisMask(%obj.getTarget(), 0xffffffff);
}

//function BomberTurret::getHudNum(%data, %num)
//{
//   if(%num == 1)
//      return 0;
//   else
//      return 4;
//}

function AIAimingTurretBarrel::onFire(%this,%obj,%slot)
{
}

function BomberBombPairImage::onUnmount(%this,%obj,%slot)
{
}

function BomberTurretBarrel::onTriggerDown(%this, %obj, %slot)
{
   %obj.turretBarrelSchedule = %obj.schedule(300, "setImageTrigger", 3, true);
}

function BomberTurretBarrel::onTriggerUp(%this, %obj, %slot)
{
   cancel(%obj.turretBarrelSchedule);
   %obj.setImageTrigger( 3, false);
}

function BomberTurretBarrelPair::onMount(%this, %obj, %slot)
{
//   %obj.setImageAmmo(%slot,true);
}

function BomberTurretBarrel::onMount(%this, %obj, %slot)
{
//   %obj.setImageAmmo(%slot,true);
}

function BomberBombPairImage::onMount(%this, %obj, %slot)
{
//   %obj.setImageAmmo(%slot,true);
}

function BomberBombPairImage::onUnmount(%this,%obj,%slot)
{
}

function MobileTurretBase::onAdd(%this, %obj)
{
   Parent::onAdd(%this, %obj);
   setTargetSensorGroup(%obj.target, %obj.team);
   setTargetNeverVisMask(%obj.target, 0xffffffff);
}

function MobileTurretBase::onDamage(%data, %obj)
{
   %newDamageVal = %obj.getDamageLevel();
   if(%obj.lastDamageVal !$= "")
      if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal)   
         %obj.getObjectMount().setDamageLevel(%newDamageVal);
   %obj.lastDamageVal = %newDamageVal;
}

function MobileTurretBase::damageObject(%this, %targetObject, %sourceObject, %position, %amount, %damageType)
{
   //If vehicle turret is hit then apply damage to the vehicle
   %vehicle = %targetObject.getObjectMount();
   if(%vehicle)
      %vehicle.getDataBlock().damageObject(%vehicle, %sourceObject, %position, %amount, %damageType);
}

function MobileTurretBase::onEndSequence(%data, %obj, %thread)
{
   //Used so that the parent wont be called..
}

function AssaultTurret::onDamage(%data, %Turret)
{
   %NewDamageValue = %Turret.getDamageLevel();

   if(%Turret.lastDamageVal !$= "")
      if(isObject(%Turret.getObjectMount()) && %Turret.lastDamageVal > %NewDamageValue)   
         %Turret.getObjectMount().setDamageLevel(%NewDamageValue);
   %Turret.lastDamageVal = %NewDamageValue;
}

function AssaultTurret::damageObject(%this, %Turret, %Projectile, %Amount, %DamageType)
{                                           
   //If vehicle turret is hit then apply damage to the vehicle
   %Vehicle = %Turret.getObjectMount();
   %Vehicle.getDataBlock().damageObject(%Vehicle, %Projectile, %Amount, %DamageType);
}

function AssaultTurret::onTrigger(%data, %Vehicle, %Trigger, %State)
{
   switch (%Trigger) {
      // Fire weapon
      case 0:
         %Vehicle.fireTrigger = %State;
         if(%Vehicle.selectedWeapon == 1)
         {
            %Vehicle.setImageTrigger(4, false);
            if(%State)
               %Vehicle.setImageTrigger(2, true);
            else
               %Vehicle.setImageTrigger(2, false);
         }                       
         else
         {
            %Vehicle.setImageTrigger(2, false);
            if(%State)
               %Vehicle.setImageTrigger(4, true);
            else           
               %Vehicle.setImageTrigger(4, false);
         }

      // Jump out 
      case 2:
         if(%State) 
         {
            %Vehicle.getDataBlock().playerDismount(%Vehicle);
         }
   }
}

function AssaultTurret::playerDismount(%data, %Vehicle)
{
   //Passenger Exiting
   %Vehicle.fireTrigger = 0;
   %Vehicle.setImageTrigger(2, false);
   %Vehicle.setImageTrigger(4, false);

   %Player = %Vehicle.getControllingClient().player;
   %Player.mountImage(%Player.lastWeapon, $WeaponSlot);
   %Player.mountVehicle = false;

   setTargetSensorGroup(%Vehicle.getTarget(), 0);
   setTargetNeverVisMask(%Vehicle.getTarget(), 0xffffffff);
//   %client.player.getDataBlock().doDismount(%client.player);
}

// The on trigger checks which weapon you wish to fire
function ScoutFlyer::onTrigger(%data, %obj, %trigger, %state)
{
   // data = ScoutFlyer datablock
   // obj = ScoutFlyer object number
   // trigger = 0 for "fire", 1 for "jump", 3 for "thrust"
   // state = 1 for firing, 0 for not firing
   if(%trigger == 0)
   {
      if (%state == 0)
      {
         // No longer firing
         %obj.fireWeapon = false;
         %obj.setImageTrigger(2, false);
         %obj.setImageTrigger(3, false);
         %obj.setImageTrigger(4, false);
         if(%obj.getImageTrigger(5))
         {
            %obj.setImageTrigger(5, false);
            ShapeBaseImageData::deconstruct(%obj.getMountedImage(5), %obj);
         }

      } else {
         // Firing
         %obj.fireWeapon = true;
         switch (%obj.selectedWeapon)
         {
            case 1 :
               // Firing Chaingun
               if (%obj.nextWeaponFire == 2) {
                  %obj.setImageTrigger(2, true);
                  %obj.setImageTrigger(3, false);
               } else {
                  %obj.setImageTrigger(2, false);
                  %obj.setImageTrigger(3, true);
               }
               %obj.setImageTrigger(4, false);
               if(%obj.getImageTrigger(5))
               {
                  %obj.setImageTrigger(5, false);
                  ShapeBaseImageData::deconstruct(%obj.getMountedImage(5), %obj);
               }

            case 2 :
               // Firing Missile
               %obj.setImageTrigger(2, false);
               %obj.setImageTrigger(3, false);
               %obj.setImageTrigger(4, true);
               if(%obj.getImageTrigger(5))
               {
                  %obj.setImageTrigger(5, false);
                  ShapeBaseImageData::deconstruct(%obj.getMountedImage(5), %obj);
               }

            case 3 :
               %obj.setImageTrigger(2, false);
               %obj.setImageTrigger(3, false);
               %obj.setImageTrigger(4, false);
               %obj.setImageTrigger(5, true);
         }
      }
   }
}


// ------------------------------------------
// camera functions
// ------------------------------------------

$CameraDeployTime = 1000;
$CameraDeployCheckMax = 6;
$CameraMinVelocity = 0.1;

function CameraGrenadeThrown::onThrow(%this, %gren)
{
   // schedule a check to see if the camera is at rest but not deployed
   %gren.checkCount = 0;
   %gren.velocCheck = %this.schedule($CameraDeployTime, "checkCameraDeploy", %gren);
}

function CameraGrenadeThrown::onStickyCollision(%data, %obj)
{
   cancel(%obj.velocCheck);
   %pos = %obj.getLastStickyPos();
   %norm = %obj.getLastStickyNormal();
   
   %intAngle = getTerrainAngle(%norm);  // staticShape.cs
   %rotAxis = vectorNormalize(vectorCross(%norm, "0 0 1"));
   if (getWord(%norm, 2) == 1 || getWord(%norm, 2) == -1)
      %rotAxis = vectorNormalize(vectorCross(%norm, "0 1 0"));

   %rotation = %rotAxis @ " " @ %intAngle;
   %dcSucc = activateCamera(%pos, %rotation, %obj.sourceObject, %obj.sourceObject.team);
   if(%dcSucc == 0)
      messageClient(%obj.sourceObject.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav');
   %obj.schedule(50,"delete");
}

function CameraGrenadeThrown::checkCameraDeploy(%this, %gren)
{
   %gren.checkCount++;
   if(VectorLen(%gren.getVelocity()) < $CameraMinVelocity)
   {
      // camera has come to rest but not deployed -- probably on a staticshape (station, gen, etc)
      // no resolution, so get rid of it
      %gren.schedule(450, "delete");
   }
   else if(%gren.checkCount >= $CameraDeployCheckMax)
   {
      // camera's still moving but it's been check several times -- it was thrown from too great
      // a height or off the edge of the world -- delete it
      %gren.schedule(450, "delete");
   }
   else
   {
      // check back in a little while
      %gren.velocCheck = %this.schedule($CameraDeployTime, "checkCameraDeploy", %gren);
   }
}

function activateCamera(%position, %rotation, %sourceObj, %team)
{
   if($TeamDeployedCount[%team, DeployedCamera] >= $TeamDeployableMax[DeployedCamera])
   {
      // team has too many cameras deployed already, don't deploy this one
      return 0;
   }

   %Data = "TurretDeployedCamera";
   %dCam = new Turret()
   {
      dataBlock = %Data;
      team = %team;
      needsNoPower = true;
      owner = %sourceObj.client;
      ownerHandle = %sourceObj.client.handle;
      position = %position;
      rotation = %rotation;
      scale = %Data.scale;
   };
   addToDeployGroup(%dCam);

   if(%dCam.getTarget() != -1)
      setTargetSensorGroup(%dCam.getTarget(), %team);

   %dCam.playAudio($DeploySound, CameraGrenadeAttachSound);
   %dCam.deploy();
   %dCam.playThread($AmbientThread, "ambient");

   // increment team's deployed count for cameras
   $TeamDeployedCount[%team, DeployedCamera]++;
   return 1;
}

function FlareGrenade::onUse(%this, %obj)
{
   // a stripped-down version of HandInventory::onUse from weapons.cs
   if(Game.handInvOnUse(%data, %obj)) {
      %obj.decInventory(%this, 1);
      %p = new FlareProjectile() {
         dataBlock        = FlareGrenadeProj;
         initialDirection = %obj.getEyeVector();
         initialPosition  = getBoxCenter(%obj.getWorldBox());
         sourceObject     = %obj;
         sourceSlot       = 0;
         team = %obj.team;
      };
      FlareSet.add(%p);
      MissionCleanup.add(%p);
      serverPlay3D(GrenadeThrowSound, getBoxCenter(%obj.getWorldBox()));
      %p.schedule(7500, "delete");

      // miscellaneous grenade-throwing cleanup stuff
      %obj.lastThrowTime[%data] = getSimTime();
      %obj.throwStrength = 0;
   }
}

// uncomment when explosion type can be set from script (dont want underwater explosion here)
//function grenadeOnEnterLiquid(%data, %obj, %coverage, %type, %flash)
//{
//   // 4: Lava 
//   // 5: Hot Lava
//   // 6: Crusty Lava
//   if(%type >=4 && %type <= 6)
//   {
//      if(%obj.getDamageState() !$= "Destroyed")
//      {
//         cancel(%obj.detThread);
//         if(%flash)
//            detonateFlashGrenade(%obj);
//         else
//            detonateGrenade(%obj);
//         return(true);
//      }
//   }
//   
//   // flash grenades do not ignore quicksand
//   if((%type == 7) && !%flash)
//      return(true);
//
//   return(false);
//}

function GrenadeThrown::onThrow(%this, %gren)
{
   AIGrenadeThrown(%gren);
   %gren.detThread = schedule(1500, %gren, "detonateGrenade", %gren);
}

//function GrenadeThrown::onEnterLiquid(%data, %obj, %coverage, %type)
//{
//   if(!grenadeOnEnterLiquid(%data, %obj, %coverage, %type, false))
//      Parent::onEnterLiquid(%data, %obj, %coverage, %type);
//}

function ConcussionGrenadeThrown::onThrow(%this, %gren)
{
   AIGrenadeThrown(%gren);
   %gren.detThread = schedule(2000, %gren, "detonateGrenade", %gren);
}

//function ConcussionGrenadeThrown::onEnterLiquid(%data, %obj, %coverage, %type)
//{
//   if(!grenadeOnEnterLiquid(%data, %obj, %coverage, %type, false))
//      Parent::onEnterLiquid(%data, %obj, %coverage, %type);
//}

// This code will detonate any object (generally grenades)
function detonateGrenade(%Object)
{
   %Data = %Object.getDataBlock();
   %Transform = %Object.getTransform();
   %Position = posFromTransform(%Transform);

   %Object.setDamageState(Destroyed);

   if (%Data.hasDamageRadius == true)
   {
      %Radius = %Data.damageRadius;
      %Damage = %Data.indirectDamage;
      %KickBack = %Data.kickBackStrength;
      %Owner = %Object.sourceObject;
      %DamageType = %Data.radiusDamageType;

      RadiusExplosion(%Object, %Position, %Radius, %Damage, %KickBack, %Owner, %DamageType);
   }

   %Object.schedule(750,"delete");
}

