
// This function rewrites the use of the beacon and allows the interception
// of that code.  The original code was copied to TargetingBeacon.cs and
// can still function.

function Beacon::onUse(%data, %Player)
{
   switch$ (%Player.Special)
   {
      case "" :
         return(0);

      case "Adren" :
         %Player.Adrenaline();

      case "CodeBreaker" :
         // Do nothing, trigger code will handle it
         %Client = %Player.client;
         echo("CodeBreaker Help");
         if (%Client.ShowHelp == true)
         {
            if (%Client.HelpSchedule !$= "")
               Cancel(%Client.HelpSchedule);

            %Message = $HelpDesc[CodeBreakerImage];
            %Lines = $HelpLines[CodeBreakerImage];

            echo("CodeBreaker Help Message: " @ %Message);

            if (%Message $= "")
               return;

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

      case "EngAssistant" :
         // Initiate Inertial Dampner
         %Player.EngAssistant();

      case "GrapplingHook" :
         // Initiate Grappling Hook
         %Player.GrapplingHook();

      case "Hologram" :
         // Initiate Hologram Projector
         %Player.Hologram();

      case "InertialDampner" :
         // Initiate Inertial Dampner
         %Player.InertialDampen();

      case "LightShield" :
         // Start Light Shields 
         %Player.LightShield();

      case "SpeedBooster" :
         // Boost the player
         %Player.SpeedBoost();

      case "WCS" :
         // Cycle the Current Weapon's Projectile Type Forward
         %Player.WCS(1);

      default :
         // Pass the info through if they actually have a targeting beacon, assume targeting beacon
         TargetingBeacon::onUse(%data, %Player);
   }
}

// This puts the physical representation of the Special onto the player model in
// the Auxillary Slot
function Player::MountSpecial(%this)
{
   %Armor = %this.getDataBlock().getName();
   switch$ (%Armor)
   {
      case "" :
         return;

      case "LightMaleBiodermArmor" :
         %Item = "LMB";

      case "MediumMaleBiodermArmor" :
         %Item = "MMB";

      case "EngineerMaleBiodermArmor" :
         return;

      case "HeavyMaleBiodermArmor" :
         %Item = "HMB";

      case "LightMaleHumanArmor" :
         %Item = "LMH";

      case "MediumMaleHumanArmor" :
         %Item = "MMH";

      case "EngineerMaleHumanArmor" :
         return;

      case "HeavyMaleHumanArmor" :
         %Item = "HMH";

      case "LightFemaleHumanArmor" :
         %Item = "LFH";

      case "MediumFemaleHumanArmor" :
         %Item = "MFH";

      case "EngineerFemaleHumanArmor" :
         return;

      case "HeavyFemaleHumanArmor" :
         %Item = "HFH";
   }

   switch$ (%this.Special)
   {
      case "" :
         return;

      case "CodeBreaker" :
         %Item = %Item @ "CB";

      case "EngAssistant" :
         // Initiate Inertial Dampner
         %Item = %Item @ "EA";

      case "GrapplingHook" :
         %Item = %Item @ "GH";

      case "InertialDampner" :
         %Item = %Item @ "ID";

      case "LightShield" :
         %Item = %Item @ "LS";

      case "SpeedBooster" :
         %Item = %Item @ "SB";

      default :
         %Item = %Item @ "TB";
   }

   %this.mountImage(%Item, $AuxiliarySlot);
}

function TargetingBeacon::onUse(%data, %obj)
{
   // look for 3 meters along player's viewpoint for interior or terrain
   %searchRange = 3.0;
   %mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType;
   // get the eye vector and eye transform of the player
   %eyeVec = %obj.getEyeVector();
   %eyeTrans = %obj.getEyeTransform();
   // extract the position of the player's camera from the eye transform (first 3 words)
   %eyePos = posFromTransform(%eyeTrans);
   // normalize the eye vector
   %nEyeVec = VectorNormalize(%eyeVec);
   // scale (lengthen) the normalized eye vector according to the search range
   %scEyeVec = VectorScale(%nEyeVec, %searchRange);
   // add the scaled & normalized eye vector to the position of the camera
   %eyeEnd = VectorAdd(%eyePos, %scEyeVec);
   // see if anything gets hit
   %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0);
   if(!%searchResult )
   {
      // no terrain/interior collision within search range
      if(%obj.inv[%data.getName()] > 0)
         messageClient(%obj.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Too far from surface.');
      return 0;
   }
   else
   {
      %searchObj = GetWord(%searchResult, 0);
      if(%searchObj.getType() & $TypeMasks::StaticShapeObjectType)
      {
         // if there's already a beacon where player is aiming, switch its type
         // otherwise, player can't deploy a beacon there
         if(%searchObj.getDataBlock().getName() $= DeployedBeacon)
            switchBeaconType(%searchObj);
         else
            messageClient(%obj.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Not a valid surface.');
         return 0;
      }
      else if(%obj.inv[%data.getName()] <= 0) 
         return 0;   
   }
   // newly deployed beacons default to "target" type
   if($TeamDeployedCount[%obj.team, TargetBeacon] >= $TeamDeployableMax[TargetBeacon])
   {
      messageClient(%obj.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav');
      return 0;
   }
   %terrPt = posFromRaycast(%searchResult);
   %terrNrm = normalFromRaycast(%searchResult);

   %intAngle = getTerrainAngle(%terrNrm);  // getTerrainAngle() function found in staticShape.cs
   %rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 0 1"));
   if (getWord(%terrNrm, 2) == 1 || getWord(%terrNrm, 2) == -1)
      %rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 1 0"));
   %rotation = %rotAxis @ " " @ %intAngle;

   %obj.decInventory(%data, 1);
   %depBeac = new ScopeAlwaysShape() {
      dataBlock = "DeployedBeacon";
      position = VectorAdd(%terrPt, VectorScale(%terrNrm, 0.05));
      rotation = %rotation;
   };
   $TeamDeployedCount[%obj.team, TargetBeacon]++;
   
   %depBeac.playThread($AmbientThread, "ambient");
   %depBeac.team = %obj.team;
   %depBeac.sourceObject = %obj;

   // give it a team target
   %depBeac.setTarget(%depBeac.team);
   MissionCleanup.add(%depBeac);
}
