
function Player::Hologram(%Player)
{
   // If a hologram is active, toggle it off.
   if (%Player.Hologram !$= "")
   {
      %Message = "Turning off Hologram.";
      messageClient(%Player.client, '', %Message);

      cancel(%Player.HologramMonitor);
      %Player.HologramMonitor = "";

      %Player.Hologram.setCloaked(true);
      %Player.Hologram.schedule(850, Delete);
      %Player.Hologram = "";
      return;
   }

   // Get the Type of Hologram needed
   %HoloType = %Player.getDataBlock().getName();

   %Team = %Player.team;

   // Get the position of the Hologram
   %VectorX = (0.5 - getRandom()) * 3;
   %VectorY = (0.5 - getRandom()) * 3;
   %Vector = VectorNormalize(%VectorX @ " " @ %VectorY @ " 0");

   %Transform = %Player.getTransform();
   %Position = posFromTransform(%Transform);
   %Rotation = rotFromTransform(%Transform);

   %NewTransform = VectorAdd(%Position, %Vector) @ " " @ %Rotation;

   // Make the Hologram and Link it to the player
   %Hologram = new Player()
   {
      dataBlock = (%HoloType);
      source = %Player;
      scale = "0.01 0.01 0.01";
      team = %Team;
   };
   MissionCleanUp.Add(%Hologram);
   %Hologram.setTransform(%NewTransform);

   %Player.Hologram = %Hologram;
   %Hologram.MovementFactor = %Player.getDataBlock().mass * 0.75;
   %Hologram.setBoundingBox("0.01 0.01 0.01");
   %Hologram.invincible = true;

   %client = %Player.client;

   // Setup the Hologram to look like the Player
   %Hologram.target = createTarget(%Hologram, %client.name, $TeamSkin[%Team], %client.voiceTag, getTaggedString(%Client.name), %Team, 0);
   setTargetSensorGroup(%Hologram.getTarget(), %Team);

   setTargetDataBlock(%Hologram.target, %Hologram.getDatablock());
   setTargetSensorData(%Hologram.target, PlayerSensor);
   setTargetSensorGroup(%Hologram.target, %client.team);
   %client.setSensorGroup(%Hologram.team);
   
   // Put the same pack onto the hologram as the player
   %Pack = %Player.getMountedImage($BackpackSlot);
   if (%Pack !$= "")
      %Hologram.mountImage(%Pack, $BackpackSlot);

   // Put the same weapon in the Hologram's hand as the player
   %Weapon = %Player.getMountedImage($WeaponSlot);
   if (%Weapon !$= "")
      %Hologram.mountImage(%Weapon, $WeaponSlot);

   // Move the hologram in the general direction the player is moving (if they are).
   // and then begin to move them apart from each other.
   %Velocity = %Player.getVelocity();
   %Velocity = VectorAdd(%Velocity, VectorScale(%Vector, 0.4));
   %HologramVector = VectorScale(%Velocity, %Hologram.MovementFactor);
   %Hologram.ApplyImpulse(%Position, %HologramVector);

   // Start the Hologram Monitoring
   %Player.HologramMonitor = schedule(600, 0, MonitorHologram, %Hologram, %Player);
}

function MonitorHologram(%Hologram, %Player)
{
   // If neither player or hologram exist, just stop here.
   if (isObject(%Hologram) == false || isObject(%Player) == false)
      return;

   // If the player making the hologram is dead then fade it out and delete it.
   if (%Player.getState() $= "Dead")
   {
      %Hologram.setCloaked(true);
      %Hologram.schedule(850, Delete);
      return;
   }

   // If the Hologram is too far away from the player, then fade it out and delete it.
   %PlayerTransform = %Player.getTransform();
   %PlayerPosition = posFromTransform(%PlayerTransform);
   %PlayerRotation = rotFromTransform(%PlayerTransform);
   %HologramPosition = posFromTransform(%Hologram.getTransform());

   %VectorBetween = VectorSub(%PlayerPosition, %HologramPosition);
   %Distance = VectorLen(%VectorBetween);

   if (%Distance > 65)
   {
      %Player.Hologram = "";
      %Message = "The hologram is out of range, can not maintain it's stability.";
      messageclient(%Player.client, '', %Message);

      %Hologram.setCloaked(true);
      %Hologram.schedule(850, Delete);
      return;
   }

   // This becomes tedious, so we do it every 3rd time...
   if (%Hologram.HologramCheck > 2)
   {
      // Put the same pack onto the hologram as the player
      %Pack = %Player.getMountedImage($BackpackSlot);
      if (%Pack !$= "")
         %Hologram.mountImage(%Pack, $BackpackSlot);
      else
         %Hologram.unMountImage($BackpackSlot);

      // Put the same weapon in the Hologram's hand as the player
      %Weapon = %Player.getMountedImage($WeaponSlot);
      if (%Weapon !$= "")
         %Hologram.mountImage(%Weapon, $WeaponSlot);
      else
         %Hologram.unMountImage($WeaponSlot);

      %Hologram.HologramCheck = 0;
   } else {
      %Hologram.HologramCheck++;
   }
   
   // Move the hologram, if the player is moving
   %Velocity = getWords(%Player.getVelocity(), 0, 1) @ " " @ getWord(%Player.getVelocity(), 2) * 0.4;

   if (VectorLen(%Velocity) > 0.5)
   {
      %MovementVector = VectorScale(%Velocity, %Hologram.MovementFactor);
      %HologramVector = VectorAdd(%MovementVector, "0 0 " @ %Hologram.MovementFactor * 5);

      %Hologram.ApplyImpulse(%HologramPosition, %HologramVector);
   }

   // Turn the hologram if needed
   %Transform = %HologramPosition @ " " @ %PlayerRotation;
   %Hologram.setTransform(%Transform);

   // Reschedule the check
   %Player.HologramMonitor = schedule(400, 0, MonitorHologram, %Hologram, %Player);
}