1. Rainer Hilmer
  2. Havoc!

Source

Havoc! / Havoc! / Havoc! / HijackerHandling.cs

using GTA;

namespace Havoc
{
   internal class HijackerHandling : Script
   {
      private readonly Core _core;
      private Vehicle _currentVehicle;
      private Ped _driver;
      private bool _hijackerIsRouting;
      private Vector3 _waypointTarget;

      public HijackerHandling()
      {
      }

      internal HijackerHandling(Core core)
      {
         _core = core;
      }

      internal bool HijackerActivated { get; set; }

      internal void BailOut()
      {
         if (!HijackerActivated)
            return;
         if (_hijackerIsRouting)
         {
            _hijackerIsRouting = false;
            if (CommonFunctions.PedExists(_driver))
            {
               _driver.Task.ClearAllImmediately();
               _driver.Delete();
            }
            HijackerActivated = false;
            Player.Character.WarpIntoVehicle(_currentVehicle, VehicleSeat.Driver);
            return;
         }
         DriverStopVehicleAndLeave();
      }

      /// <summary>
      /// Hijacker stops and leaves when Player leaves.
      /// </summary>
      internal void StopHijackerIfPlayerLeftVehicle()
      {
         if (Player.Character.isInVehicle() || !HijackerActivated)
            return;
         if (_currentVehicle == null)
         {
            CommonFunctions.DisplayText("currentVehicle is null.", 3000);
            return;
         }
         DriverStopVehicleAndLeave();
      }

      internal void StopHijackerIfTargetReached()
      {
         if (!_hijackerIsRouting || !CommonFunctions.VehicleExists(_currentVehicle))
            return;
         if (_currentVehicle.Position.NewDistanceTo2D(_waypointTarget) < 10.0f)
            DriverStopVehicleAndLeave();
      }

      internal void TriggerHijacker()
      {
         if (!Player.Character.isSittingInVehicle()
             || !_core.Configuration.Hijacker
             || Player.Character.CurrentVehicle.PassengerSeats == 0
             || HijackerActivated)
            return;
         Game.LoadAllPathNodes = true;
         _currentVehicle = Player.Character.CurrentVehicle;
         _currentVehicle.MakeProofTo(false, false, false, false, true);
         var freeSeat = _currentVehicle.GetFreePassengerSeat();
         Player.Character.WarpIntoVehicle(_currentVehicle, freeSeat);
         _driver = _currentVehicle.CreatePedOnSeat(VehicleSeat.Driver);
         if (!CommonFunctions.PedExists(_driver))
         {
            Player.Character.WarpIntoVehicle(_currentVehicle, VehicleSeat.Driver);
            Game.DisplayText("Failed to create hijacker!", 5000);
            return;
         }
         _driver.isRequiredForMission = true;
         if (Game.GetWaypoint() != null)
         {
            _waypointTarget = World.GetNextPositionOnStreet(Game.GetWaypoint().Position);
            _hijackerIsRouting = true;
            HijackerDriveToWaypoint();
         }
         else
         {
            _hijackerIsRouting = false;
            _driver.Task.CruiseWithVehicle(
               _currentVehicle,
               CommonFunctions.CorrectedSpeed(_core.Configuration.MadDriversSpeed),
               _core.Configuration.MadDriversObeyTrafficLaws);
         }
         HijackerActivated = true;
      }

      internal void UpdateTarget()
      {
         var waypoint = Game.GetWaypoint();
         if (waypoint == null)
            return;
         var tempTarget = waypoint.Position;
         if (_waypointTarget == default(Vector3))
            _waypointTarget = tempTarget;
         if(_waypointTarget != tempTarget)
            _waypointTarget = tempTarget;
         if (!CommonFunctions.PedExists(_driver))
            return;
         _driver.Task.ClearAll();
         HijackerDriveToWaypoint();
      }

      private void DriverStopVehicleAndLeave()
      {
         if (!CommonFunctions.PedExists(_driver))
            return;
         _driver.Task.CruiseWithVehicle(
            _currentVehicle, 0.0f, ObeyTrafficLaws: true);
         WaitForVehicleToStop();
         _driver.Task.AlwaysKeepTask = false;
         _driver.LeaveVehicle();
         _driver.NoLongerNeeded();
         _driver.isRequiredForMission = false;
         _hijackerIsRouting = false;
         Game.LoadAllPathNodes = false;
         HijackerActivated = false;
         WarpPlayerBackToDriverSeatOnceFree();
      }

      private void HijackerDriveToWaypoint()
      {
         _hijackerIsRouting = true;
         _driver.Task.DriveTo(_waypointTarget,
            CommonFunctions.CorrectedSpeed(_core.Configuration.MadDriversSpeed),
            _core.Configuration.MadDriversObeyTrafficLaws);
      }

      private void WaitForVehicleToStop()
      {
         while (_currentVehicle.Speed > 1)
            Wait(Interval);
      }

      private void WarpPlayerBackToDriverSeatOnceFree()
      {
         if (!CommonFunctions.VehicleExists(_currentVehicle)
             || !CommonFunctions.PedExists(Player.Character))
            return;
         while (!_currentVehicle.isSeatFree(VehicleSeat.Driver))
            Wait(Interval);
         Player.Character.WarpIntoVehicle(_currentVehicle, VehicleSeat.Driver);
      }
   }
}