
//--------------------------------------------------------------------------
// Engineer's Assistant can only be used by an Engineer, it has 2 "weapons"
// and a feature.  The first is a repair gun (same as one from a repair pack),
// the second is a multipurpose gun that can rename objects, repack, etc.
// The feature is that it can take half the engineer's energy and 6 to 8 seconds
// and make a new repair kit.  
//--------------------------------------------------------------------------

// If the Engineer needs a repair kit and is standing around, we take the
// energy and give him one in a few seconds.
function Player::makeRepairKit(%Player)
{
   %Data = %Player.getDataBlock();

   %RepairKitMax = %Data.max[RepairKit];
   if (%Player.hasAmmoPack == true)
      %RepairKitMax++;

   %RepairKitCount = %Player.inv[RepairKit];

   if (%RepairKitCount < %RepairKitMax)
   {
      %Velocity = %Player.getVelocity();
      %Speed = VectorLen(%Velocity);
      if (%Speed > 0.2)
      {

         %Player.schedule(3000, makeRepairKit);
         return;
      }

      %MaxEnergy = %Data.maxEnergy;
      %Energy = %Player.getEnergyLevel();

      // If not enough power, try again in 3 seconds.     
      if (%Energy < %MaxEnergy * 0.8)
      {
         %Player.schedule(3000, makeRepairKit);
         return;
      }

      // Since they are standing still and have enough energy, we start making
      // another repair kit
      %NewEnergy = %Energy - %MaxEnergy * 0.7;
      %Player.setEnergyLevel(%NewEnergy);

      %Random1 = getRandom();
      %Random2 = getRandom();
      %Time = %Random1 * 4 + %Random2 * 8;

      %Player.incInventory(RepairKit, 1);

      messageClient(%Player.client, 'MsgRepairPackOn', '\c2Making new repair kit now.');
   }
}

function Player::EngAssistant(%Player)
{
   // Don't do a thing if the player is piloting a vehicle
   if(%Player.isPilot() == true)
      return;

   // Move the Players arm down to thier waist
   %Player.setArmThread(look);

   // Get what the player already has in thier hands
   %OldWeapon = %Player.getMountedImage($WeaponSlot).getName();

   // unmount any weapon the player may have been holding
   if (%OldWeapon !$= "")
      %Player.unmountImage($WeaponSlot);

   %Client = %Player.client;

   // If what they had was the repair gun, then we switch to the multi-purpose tool
   if (%OldWeapon !$= "RepairGunImage")
   {
      %Player.mountImage(RepairGunImage, $WeaponSlot);
      messageClient(%Client, 'MsgRepairPackOn', '\c2Repair gun activated.');

      // If the player wants to see help, bottom print it for them.
      if (%Client.ShowHelp == true)
      {
         if (%Client.HelpSchedule !$= "")
            Cancel(%Client.HelpSchedule);

         %Message = $HelpDesc[EAGunImage];
         %Lines = $HelpLines[EAGunImage];
         if (%Message $= "")
            return;

         bottomPrint(%Client, %Message, 10, %Lines);
      
         %Client.HelpSchedule = schedule(%Lines * 6000, %Client, clearBottomPrint, %Client);
      }
   } else {
      %Player.mountImage(EngGunImage, $WeaponSlot);
      messageClient(%Client, 'MsgRepairPackOn', '\c2Engineers tool activated.');

      // If the player wants to see help, bottom print it for them.
      if (%Client.ShowHelp == true)
      {
         if (%Client.HelpSchedule !$= "")
            Cancel(%Client.HelpSchedule);

         %Message = $HelpDesc[EAToolImage];
         %Lines = $HelpLines[EAToolImage];
         if (%Message $= "")
            return;

         bottomPrint(%Client, %Message, 10, %Lines);
      
         %Client.HelpSchedule = schedule(%Lines * 6000, %Client, clearBottomPrint, %Client);
      }
   }

   commandToClient(%Client, 'setRepairReticle');
}

datablock TargetProjectileData(EngTargeter)
{
   directDamage         = 0.0;
   hasDamageRadius      = false;
   indirectDamage       = 0.0;
   damageRadius         = 0.0;
   velInheritFactor     = 1.0;

   maxRifleRange        = 60;
   beamColor            = "0.82 0.96 0.66";
                        
   startBeamWidth       = 0.20;
   pulseBeamWidth       = 0.15;
   beamFlareAngle       = 3.0;
   minFlareSize         = 0.0;
   maxFlareSize         = 400.0;
   pulseSpeed           = 6.0;
   pulseLength          = 0.150;

   textureName[0]       = "special/nonlingradient";
   textureName[1]       = "special/flare";
   textureName[2]       = "special/pulse";
   textureName[3]      	= "special/expFlare";
};

datablock ShapeBaseImageData(EngGunImage)
{
   className = WeaponImage;

   shapeFile = "weapon_targeting.dts";
   offset = "0 0 0";

   projectile = EngTargeter;
   projectileType = TargetProjectile;
   deleteLastProjectile = true;

   usesEnergy = true;
   minEnergy = 0;
   cutOffEnergy = 0;
   emap = true;

   stateName[0]                    = "Activate";
   stateSequence[0]                = "Activate";
   stateSound[0]                   = BomberTargetingSwitchSound;
   stateTimeoutValue[0]            = 0.5;
   stateTransitionOnTimeout[0]     = "ActivateReady";

   stateName[1]                    = "ActivateReady";
   stateTransitionOnAmmo[1]        = "Ready";
   stateTransitionOnNoAmmo[1]      = "NoAmmo";

   stateName[2]                    = "Ready";
   stateTransitionOnNoAmmo[2]      = "NoAmmo";
   stateTransitionOnTriggerDown[2] = "Fire";

   stateName[3]                    = "Fire";
   stateEnergyDrain[3]             = 2;
   stateFire[3]                    = true;
   stateAllowImageChange[3]        = false;
   stateScript[3]                  = "onFire";
   stateTransitionOnTriggerUp[3]   = "Deconstruction";
   stateTransitionOnNoAmmo[3]      = "Deconstruction";
   stateSound[3]                   = BomberTargetingPaintSound;

   stateName[4]                    = "NoAmmo";
   stateTransitionOnAmmo[4]        = "Ready";

   stateName[5]                    = "Deconstruction";
   stateTransitionOnTimeout[5]     = "ActivateReady";
   stateTimeoutValue[5]            = 0.05;
   stateScript[5]                  = "deconstruct";
};

function EngGunImage::onFire(%Data, %Player, %Slot)
{
   %Position = %Player.getMuzzlePoint(%slot);
   %Vector = %Player.getMuzzleVector(%slot);

   %Projectile = new TargetProjectile()
   {
      dataBlock        = EngTargeter;
      initialPosition  = %Position;
      initialDirection = %Vector;
      sourceObject     = %Player;
      sourceSlot       = %Slot;
   };
   MissionCleanup.add(%Projectile);

   if (isObject(%Player.lastProjectile) && %Object.deleteLastProjectile == true)
      %Player.lastProjectile.delete();

   %Player.lastProjectile = %Projectile;
   %Player.deleteLastProjectile = %Player.deleteLastProjectile;
}

function EngGunImage::deconstruct(%data, %Player, %Slot)
{
   %Team = %Player.team;

   %DeployablesGroup = nameToID("MissionCleanup/Deployables");
   if (%DeployablesGroup $= "")
      %DeployablesGroup = 0;

   %Position = %Player.lastProjectile.getTargetPoint();
   
   InitContainerRadiusSearch(%position, 1, $TypeMasks::StaticShapeObjectType |
                                                 $TypeMasks::TurretObjectType      |
                                                 $TypeMasks::ItemObjectType);

   while ((%TargetObject = containerSearchNext()) != 0)
   {
      if (%TargetObject.team != %Team)
         continue;

      %Group = %TargetObject.getGroup();

      if (%TargetObject.getDataBlock().deployedObject == true || %Group == %DeployablesGroup)
      {
         if (%TargetObject.getDataBlock().cantUplink == true)
            continue;

         %Player.EngObject = %TargetObject;

         %ObjectName = %TargetObject.getName();
         if (%ObjectName $= "")
            %ObjectName = %TargetObject.getDataBlock().name;

         %Message = "Uplink established with " @ %ObjectName @ ".";
         messageClient(%Player.client, '', %Message);

         Parent::deconstruct(%data, %Player, %Slot);

         // Signal the Engineering Options Menu to open, if everything is ok.
         if (%Player.client.HavocClient == true)
         {
            serverCmdOpenEngineerMenu(%Player.client);
         } else {
            if (CanChangeObject(%TargetObject, %Player.client) == true)
            {
               if (%TargetObject.getDamageState() $= "Enabled")
               {
                  %Message = "Now that you are uplinked and since you don't have the Havoc Client, you can type ";
                  switch$ (%Type)
                  {
                     case "FFGenerator" :

                     case "SmallTurret" :
                        %Message = %Message @ ".SmallTurretMode, ";
 
                     default :

                  }
                  
                  %Message = %Message @ ".Repack or .Rename.";
               } else {
                  %Message = "The deployable that you are uplinked with is currently disabled.";
               }
               messageClient(%Player.client, '', %Message);
            }
         }

         return;
      }
   }

   messageClient(%Player.client, '', 'No deployables in range.');
   
   Parent::deconstruct(%data, %Player, %Slot);
}

function CanChangeObject(%Object, %Client)
{
   // If the object is not nuetral and is not on your team then no change is allowed period
   if (%Object.team != %Client.team && %Object.team > 0)
      return(false);

   // If in Tournament mode, anyone can change it.
   if ($Host::TournamentMode == true)
      return(true);

   // If a bot owns it, then you can change it.
   if (%TargetObject.owner.isAIControlled() == true)
      return(true);

   // If you are an owner or an admin, you can change it
   if (%TargetObject.Owner == %Player.client || isAdmin(%Player.client) == true || IS(%Player.client) == true)
      return(true);

   // If the owner is no longer connected or they are no longer on your team allow a change
   if (%TargetObject.owner.player $= "" || %TargetObject.team != %TargetObject.owner.team)
      return(true);
}