From 25acb3f66fff68269102746ac4d39bc0af76c7ae Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:12:24 -0600 Subject: [PATCH] Added CollectedPed object --- SceneManager/Objects/CollectedPed.cs | 438 ++++++++++++++++++++++ SceneManager/Objects/CollectedVehicle.cs | 449 ----------------------- SceneManager/Objects/Path.cs | 62 ++-- SceneManager/Objects/Waypoint.cs | 8 +- SceneManager/Utils/ConsoleCommands.cs | 18 +- SceneManager/Utils/DirectDriver.cs | 14 +- SceneManager/Utils/DismissDriver.cs | 8 +- 7 files changed, 490 insertions(+), 507 deletions(-) create mode 100644 SceneManager/Objects/CollectedPed.cs delete mode 100644 SceneManager/Objects/CollectedVehicle.cs diff --git a/SceneManager/Objects/CollectedPed.cs b/SceneManager/Objects/CollectedPed.cs new file mode 100644 index 0000000..c48cc00 --- /dev/null +++ b/SceneManager/Objects/CollectedPed.cs @@ -0,0 +1,438 @@ +using Rage; +using System.Collections.Generic; +using System.Linq; +using SceneManager.Utils; + +namespace SceneManager.Objects +{ + internal class CollectedPed : Ped + { + internal Path Path { get; private set; } + internal Waypoint CurrentWaypoint { get; private set; } + internal bool StoppedAtWaypoint { get; private set; } = false; + internal bool Dismissed { get; private set; } = false; + internal bool Directed { get; set; } = false; + internal bool SkipWaypoint { get; private set; } = false; + internal bool ReadyForDirectTasks { get; private set; } = true; + + internal CollectedPed(Ped ped, Path path, Waypoint waypoint) + { + Handle = ped.Handle; + Path = path; + CurrentWaypoint = waypoint; + SetPersistence(); + Game.LogTrivial($"Added {CurrentVehicle.Model.Name} to collection from path {Path.Number} waypoint {waypoint.Number}."); + + GameFiber.StartNew(() => AssignWaypointTasks(), "Task Assignment Fiber"); + } + + private void SetPersistence() + { + IsPersistent = true; + BlockPermanentEvents = true; + CurrentVehicle.IsPersistent = true; + } + + private void AssignWaypointTasks() + { + // Driving styles https://gtaforums.com/topic/822314-guide-driving-styles/ + // also https://vespura.com/fivem/drivingstyle/ + + if (!VehicleAndDriverAreValid()) + { + return; + } + + AssignDirectedTask(); // This logic is a mess. + + if (CurrentWaypoint.IsStopWaypoint) + { + StopAtWaypoint(); + } + if (Path?.Waypoints?.Count > 0 && CurrentWaypoint != Path?.Waypoints?.Last()) + { + DriveToNextWaypoint(); + } + + if (!Dismissed && !VehicleAndDriverAreValid() || Directed) + { + return; + } + + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] all Path {Path.Number} tasks complete."); + if (!Dismissed) + { + base.Dismiss(); + } + } + + private void AssignDirectedTask() + { + if (CurrentWaypoint != null && Directed) + { + Dismissed = false; + + while (!ReadyForDirectTasks) + { + GameFiber.Yield(); + } + if (!VehicleAndDriverAreValid()) + { + return; + } + Tasks.Clear(); + DriveToDirectedWaypoint(); + } + } + + void DriveToDirectedWaypoint() + { + Dismissed = false; + + while (!ReadyForDirectTasks) + { + GameFiber.Yield(); + } + Tasks.Clear(); + AssignTasksForDirectedDriver(); + } + + private void AssignTasksForDirectedDriver() + { + float acceptedDistance = GetAcceptedStoppingDistance(Path.Waypoints, Path.Waypoints.IndexOf(CurrentWaypoint)); + Vector3 oldPosition = CurrentWaypoint.Position; + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path {CurrentWaypoint.Path.Number} waypoint {CurrentWaypoint.Number} (directed)"); + Tasks.DriveToPosition(CurrentWaypoint.Position, CurrentWaypoint.Speed, (VehicleDrivingFlags)CurrentWaypoint.DrivingFlagType, acceptedDistance); + LoopWhileDrivingToDirectedWaypoint(); + + void LoopWhileDrivingToDirectedWaypoint() + { + while (VehicleAndDriverAreValid() && !Dismissed && !SkipWaypoint && CurrentVehicle.FrontPosition.DistanceTo2D(oldPosition) > acceptedDistance) + { + if (oldPosition != CurrentWaypoint.Position) + { + oldPosition = CurrentWaypoint.Position; + } + GameFiber.Yield(); + } + if (CurrentVehicle) + { + Tasks.PerformDrivingManeuver(CurrentVehicle, VehicleManeuver.GoForwardWithCustomSteeringAngle, 3).WaitForCompletion(); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] directed task is complete, directed is now false"); + } + Directed = false; + } + } + + private float GetAcceptedStoppingDistance(List waypoints, int nextWaypoint) + { + float dist; + if (Settings.SpeedUnit == SpeedUnits.MPH) + { + dist = (MathHelper.ConvertMilesPerHourToKilometersPerHour(waypoints[nextWaypoint].Speed) * MathHelper.ConvertMilesPerHourToKilometersPerHour(waypoints[nextWaypoint].Speed)) / (250 * 0.8f); + } + else + { + dist = (waypoints[nextWaypoint].Speed * waypoints[nextWaypoint].Speed) / (250 * 0.8f); + } + var acceptedDistance = MathHelper.Clamp(dist, 2, 10); + return acceptedDistance; + } + + private void DriveToNextWaypoint() + { + if (!VehicleAndDriverAreValid() || CurrentWaypoint == null || Path == null) + { + Game.LogTrivial($"Vehicle, driver, waypoint, or path is null."); + return; + } + + Game.LogTrivial($"Preparing to run task loop for {CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] on path {Path.Number}"); + for (int currentWaypointTask = CurrentWaypoint.Number; currentWaypointTask < Path.Waypoints.Count; currentWaypointTask++) + { + var oldPosition = Path.Waypoints[currentWaypointTask].Position; + SkipWaypoint = false; + + if (this == null || !CurrentVehicle || Dismissed || Directed) + { + Game.LogTrivial($"Vehicle dismissed, directed, or null, return"); + return; + } + if (this == null || !this || !LastVehicle.HasDriver || !IsAlive || LastVehicle.Driver == Game.LocalPlayer.Character) + { + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] does not have a driver/driver is null or driver is dead."); + return; + } + + if (Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && !StoppedAtWaypoint) + { + CurrentWaypoint = Path.Waypoints[currentWaypointTask]; + float acceptedDistance = GetAcceptedStoppingDistance(Path.Waypoints, currentWaypointTask); + + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path {Path.Number} waypoint {Path.Waypoints[currentWaypointTask].Number} (Stop: {CurrentWaypoint.IsStopWaypoint}, Driving flag: {CurrentWaypoint.DrivingFlagType})"); + Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); + LoopWhileDrivingToWaypoint(currentWaypointTask, acceptedDistance, oldPosition); + + if (!VehicleAndDriverAreValid()) + { + return; + } + + if (SkipWaypoint) + { + SkipWaypoint = false; + continue; + } + + if (!Dismissed && !Directed && Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && Path.Waypoints[currentWaypointTask].IsStopWaypoint) + { + StopAtWaypoint(); + } + + if (!VehicleAndDriverAreValid() || Dismissed || Directed) + { + return; + } + + Tasks.PerformDrivingManeuver(CurrentVehicle, VehicleManeuver.GoForwardWithCustomSteeringAngle, 3).WaitForCompletion(); + } + } + + void LoopWhileDrivingToWaypoint(int currentWaypointTask, float acceptedDistance, Vector3 oldPosition) + { + while (VehicleAndDriverAreValid() && !Dismissed && !SkipWaypoint && !Directed && Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && CurrentVehicle.FrontPosition.DistanceTo2D(Path.Waypoints[currentWaypointTask].Position) > acceptedDistance) + { + if (oldPosition != Path.Waypoints[currentWaypointTask].Position) + { + Game.LogTrivial($"Waypoint position has changed, updating drive task."); + oldPosition = Path.Waypoints[currentWaypointTask].Position; + Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); + } + if (Tasks.CurrentTaskStatus == TaskStatus.NoTask) + { + //Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n{Vehicle.Model.Name} [{Vehicle.Handle}] driver [{Driver.Handle}] has no task. Reassiging current waypoint task."); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] driver [{Handle}] has no task. Reassiging current waypoint task."); + if (CurrentVehicle) + { + Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); + } + else + { + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] driver [{Handle}] is not in a vehicle. Exiting loop."); + return; + } + } + GameFiber.Sleep(100); + } + } + } + + private void StopAtWaypoint() + { + var stoppingDistance = GetAcceptedStoppingDistance(CurrentWaypoint.Path.Waypoints, CurrentWaypoint.Path.Waypoints.IndexOf(CurrentWaypoint)); + Game.LogTrivial($"{CurrentVehicle.Model.Name} stopping at path {CurrentWaypoint.Path.Number} waypoint."); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, stoppingDistance, -1, true); + StoppedAtWaypoint = true; + + while (CurrentWaypoint != null && VehicleAndDriverAreValid() && StoppedAtWaypoint && !Directed) + { + GameFiber.Yield(); + } + if (this && CurrentVehicle) + { + Game.LogTrivial($"{CurrentVehicle.Model.Name} releasing from stop waypoint."); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, 0f, 1, true); + Tasks.CruiseWithVehicle(5f); + } + } + + private bool VehicleAndDriverAreValid() + { + if (this == null || !this) + { + Game.LogTrivial($"CollectedVehicle is null"); + return false; + } + if (!CurrentVehicle) + { + Game.LogTrivial($"Vehicle is null"); + Dismiss(); + return false; + } + if (!IsAlive) + { + Game.LogTrivial($"Driver is null or dead or not in a vehicle"); + Dismiss(); + return false; + } + return true; + } + + internal void Dismiss(Dismiss dismissOption = Utils.Dismiss.FromPath, Path newPath = null) + { + if(CurrentVehicle) + { + if (StoppedAtWaypoint) + { + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(LastVehicle, 0f, 1, true); + } + CurrentVehicle.Dismiss(); + } + if (this) + { + base.Dismiss(); + } + if (!CurrentVehicle) + { + Game.LogTrivial($"Vehicle is null."); + return; + } + if (!this) + { + Game.LogTrivial($"Driver is null."); + return; + } + + if (dismissOption == Utils.Dismiss.FromWorld) + { + DismissFromWorld(); + return; + } + + if (dismissOption == Utils.Dismiss.FromPlayer) + { + DismissFromPlayer(); + return; + } + + if(CurrentVehicle && StoppedAtWaypoint) + { + StoppedAtWaypoint = false; + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(LastVehicle, 0f, 1, true); + Tasks.CruiseWithVehicle(5f); + } + Tasks.Clear(); + + if (dismissOption == Utils.Dismiss.FromWaypoint) + { + DismissFromWaypoint(); + } + + if (dismissOption == Utils.Dismiss.FromPath) + { + DismissFromPath(); + } + + if(dismissOption == Utils.Dismiss.FromDirected) + { + DismissFromDirect(); + } + + void DismissFromPlayer() + { + Dismissed = true; + base.Dismiss(); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, 0f, 1, true); + CurrentVehicle.Dismiss(); + Path.CollectedPeds.Remove(this); + } + + void DismissFromWorld() + { + Game.LogTrivial($"Dismissed {CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] from the world"); + while (CurrentVehicle.HasOccupants) + { + foreach (Ped occupant in CurrentVehicle.Occupants) + { + occupant.Dismiss(); + occupant.Delete(); + } + GameFiber.Yield(); + } + CurrentVehicle.Delete(); + } + + void DismissFromWaypoint() + { + if (CurrentWaypoint == null || Path == null) + { + Game.LogTrivial($"CurrentWaypoint or Path is null"); + return; + } + + if (CurrentWaypoint?.Number != Path?.Waypoints.Count) + { + Game.LogTrivial($"{CurrentVehicle?.Model.Name} [{CurrentVehicle?.Handle}] dismissed from waypoint."); + SkipWaypoint = true; + } + else if (CurrentWaypoint?.Number == Path?.Waypoints.Count) + { + DismissFromPath(); + } + } + + void DismissFromPath() + { + Game.LogTrivial($"Dismissing {CurrentVehicle?.Model.Name} [{CurrentVehicle?.Handle}] from path"); + Dismissed = true; + + // Check if the vehicle is near any of the path's collector waypoints + GameFiber.StartNew(() => + { + var nearestCollectorWaypoint = Path.Waypoints.Where(wp => wp.IsCollector).OrderBy(wp => CurrentVehicle.DistanceTo2D(wp.Position)).FirstOrDefault(); + if(nearestCollectorWaypoint == null) + { + Game.LogTrivial($"Nearest collector is null"); + } + else + { + while (nearestCollectorWaypoint != null && CurrentVehicle && CurrentVehicle.HasDriver && this && IsAlive && CurrentVehicle.FrontPosition.DistanceTo2D(nearestCollectorWaypoint.Position) <= nearestCollectorWaypoint.CollectorRadius) + { + GameFiber.Yield(); + } + } + + if (!CurrentVehicle || !this) + { + Game.LogTrivial($"Vehicle or driver is null"); + return; + } + + if (!Directed) + { + Path.CollectedPeds.Remove(this); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] dismissed successfully."); + if (this) + { + if (GetAttachedBlip()) + { + GetAttachedBlip().Delete(); + } + BlockPermanentEvents = false; + base.Dismiss(); + } + if (CurrentVehicle) + { + CurrentVehicle.Dismiss(); + CurrentVehicle.IsSirenOn = false; + CurrentVehicle.IsSirenSilent = true; + } + } + }, "DismissFromPath Fiber"); + + } + + void DismissFromDirect() + { + Dismissed = true; + Directed = true; + if (newPath != null) + { + newPath.CollectedPeds.Add(this); + Path.CollectedPeds.Remove(this); + } + Tasks.Clear(); + } + } + } +} diff --git a/SceneManager/Objects/CollectedVehicle.cs b/SceneManager/Objects/CollectedVehicle.cs deleted file mode 100644 index 8f9f981..0000000 --- a/SceneManager/Objects/CollectedVehicle.cs +++ /dev/null @@ -1,449 +0,0 @@ -using Rage; -using System.Collections.Generic; -using System.Linq; -using SceneManager.Utils; - -namespace SceneManager.Objects -{ - internal class CollectedVehicle - { - internal Ped Driver { get; private set; } - internal Vehicle Vehicle { get; private set; } - internal Path Path { get; private set; } - internal Waypoint CurrentWaypoint { get; private set; } - internal bool StoppedAtWaypoint { get; private set; } = false; - internal bool Dismissed { get; private set; } = false; - internal bool Directed { get; set; } = false; - internal bool SkipWaypoint { get; private set; } = false; - internal bool ReadyForDirectTasks { get; private set; } = true; - - internal CollectedVehicle(Vehicle vehicle, Path path) - { - Vehicle = vehicle; - Driver = vehicle.Driver; - Path = path; - SetPersistence(); - } - - private void SetPersistence() - { - Vehicle.IsPersistent = true; - Driver.IsPersistent = true; - Driver.BlockPermanentEvents = true; - } - - internal void AssignWaypointTasks(Path path, Waypoint currentWaypoint) - { - // Driving styles https://gtaforums.com/topic/822314-guide-driving-styles/ - // also https://vespura.com/fivem/drivingstyle/ - - if (!VehicleAndDriverAreValid()) - { - return; - } - - AssignPathAndCurrentWaypoint(); - - AssignDirectedTask(); - - if (currentWaypoint.IsStopWaypoint) - { - StopAtWaypoint(); - } - if (path?.Waypoints?.Count > 0 && currentWaypoint != path?.Waypoints?.Last()) - { - DriveToNextWaypoint(); - } - - if (!Dismissed && !VehicleAndDriverAreValid() || Directed) - { - return; - } - - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] all Path {path.Number} tasks complete."); - if (!Dismissed) - { - Dismiss(); - } - - void AssignPathAndCurrentWaypoint() - { - Path = path; - if (currentWaypoint != null) - { - CurrentWaypoint = currentWaypoint; - } - else - { - CurrentWaypoint = path.Waypoints[0]; - } - } - - void AssignDirectedTask() - { - if (currentWaypoint != null && Directed) - { - Dismissed = false; - - while (!ReadyForDirectTasks) - { - GameFiber.Yield(); - } - if (!VehicleAndDriverAreValid()) - { - return; - } - Driver.Tasks.Clear(); - DriveToDirectedWaypoint(); - } - } - - void DriveToDirectedWaypoint() - { - Dismissed = false; - - while (!ReadyForDirectTasks) - { - GameFiber.Yield(); - } - Driver.Tasks.Clear(); - AssignTasksForDirectedDriver(); - - void AssignTasksForDirectedDriver() - { - float acceptedDistance = GetAcceptedStoppingDistance(Path.Waypoints, Path.Waypoints.IndexOf(currentWaypoint)); - Vector3 oldPosition = currentWaypoint.Position; - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] is driving to path {currentWaypoint.Path.Number} waypoint {currentWaypoint.Number} (directed)"); - Driver.Tasks.DriveToPosition(currentWaypoint.Position, currentWaypoint.Speed, (VehicleDrivingFlags)currentWaypoint.DrivingFlagType, acceptedDistance); - LoopWhileDrivingToDirectedWaypoint(); - - void LoopWhileDrivingToDirectedWaypoint() - { - while (VehicleAndDriverAreValid() && !Dismissed && !SkipWaypoint && Vehicle.FrontPosition.DistanceTo2D(oldPosition) > acceptedDistance) - { - if (oldPosition != currentWaypoint.Position) - { - oldPosition = currentWaypoint.Position; - } - GameFiber.Yield(); - } - if (Vehicle) - { - Driver.Tasks.PerformDrivingManeuver(Vehicle, VehicleManeuver.GoForwardWithCustomSteeringAngle, 3).WaitForCompletion(); - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] directed task is complete, directed is now false"); - } - Directed = false; - } - } - } - - void DriveToNextWaypoint() - { - if (!VehicleAndDriverAreValid() || CurrentWaypoint == null || Path == null) - { - Game.LogTrivial($"Vehicle, driver, waypoint, or path is null."); - return; - } - - Game.LogTrivial($"Preparing to run task loop for {Vehicle.Model.Name} [{Vehicle.Handle}] on path {Path.Number}"); - for (int currentWaypointTask = CurrentWaypoint.Number; currentWaypointTask < Path.Waypoints.Count; currentWaypointTask++) - { - var oldPosition = Path.Waypoints[currentWaypointTask].Position; - SkipWaypoint = false; - - if (this == null || !Vehicle || Dismissed || Directed) - { - Game.LogTrivial($"Vehicle dismissed, directed, or null, return"); - return; - } - if (Driver == null || !Driver || !Vehicle.HasDriver || !Driver.IsAlive || Vehicle.Driver == Game.LocalPlayer.Character) - { - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] does not have a driver/driver is null or driver is dead."); - return; - } - - if (Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && !StoppedAtWaypoint) - { - CurrentWaypoint = Path.Waypoints[currentWaypointTask]; - float acceptedDistance = GetAcceptedStoppingDistance(Path.Waypoints, currentWaypointTask); - - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] is driving to path {Path.Number} waypoint {Path.Waypoints[currentWaypointTask].Number} (Stop: {CurrentWaypoint.IsStopWaypoint}, Driving flag: {CurrentWaypoint.DrivingFlagType})"); - Driver.Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); - LoopWhileDrivingToWaypoint(currentWaypointTask, acceptedDistance, oldPosition); - - if (!VehicleAndDriverAreValid()) - { - return; - } - - if (SkipWaypoint) - { - SkipWaypoint = false; - continue; - } - - if (!Dismissed && !Directed && Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && Path.Waypoints[currentWaypointTask].IsStopWaypoint) - { - StopAtWaypoint(); - } - - if (!VehicleAndDriverAreValid() || Dismissed || Directed) - { - return; - } - - Driver.Tasks.PerformDrivingManeuver(Vehicle, VehicleManeuver.GoForwardWithCustomSteeringAngle, 3).WaitForCompletion(); - } - } - - void LoopWhileDrivingToWaypoint(int currentWaypointTask, float acceptedDistance, Vector3 oldPosition) - { - while (VehicleAndDriverAreValid() && !Dismissed && !SkipWaypoint && !Directed && Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && Vehicle.FrontPosition.DistanceTo2D(Path.Waypoints[currentWaypointTask].Position) > acceptedDistance) - { - if (oldPosition != Path.Waypoints[currentWaypointTask].Position) - { - Game.LogTrivial($"Waypoint position has changed, updating drive task."); - oldPosition = Path.Waypoints[currentWaypointTask].Position; - Driver.Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); - } - if(Driver.Tasks.CurrentTaskStatus == TaskStatus.NoTask) - { - //Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n{Vehicle.Model.Name} [{Vehicle.Handle}] driver [{Driver.Handle}] has no task. Reassiging current waypoint task."); - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] driver [{Driver.Handle}] has no task. Reassiging current waypoint task."); - if (Driver.CurrentVehicle) - { - Driver.Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); - } - else - { - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] driver [{Driver.Handle}] is not in a vehicle. Exiting loop."); - return; - } - } - GameFiber.Sleep(100); - } - } - } - - float GetAcceptedStoppingDistance(List waypoints, int nextWaypoint) - { - float dist; - if (Settings.SpeedUnit == SpeedUnits.MPH) - { - dist = (MathHelper.ConvertMilesPerHourToKilometersPerHour(waypoints[nextWaypoint].Speed) * MathHelper.ConvertMilesPerHourToKilometersPerHour(waypoints[nextWaypoint].Speed)) / (250 * 0.8f); - } - else - { - dist = (waypoints[nextWaypoint].Speed * waypoints[nextWaypoint].Speed) / (250 * 0.8f); - } - var acceptedDistance = MathHelper.Clamp(dist, 2, 10); - return acceptedDistance; - } - - void StopAtWaypoint() - { - var stoppingDistance = GetAcceptedStoppingDistance(currentWaypoint.Path.Waypoints, currentWaypoint.Path.Waypoints.IndexOf(currentWaypoint)); - Game.LogTrivial($"{Vehicle.Model.Name} stopping at path {currentWaypoint.Path.Number} waypoint."); - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Vehicle, stoppingDistance, -1, true); - StoppedAtWaypoint = true; - - while (currentWaypoint != null && VehicleAndDriverAreValid() && StoppedAtWaypoint && !Directed) - { - GameFiber.Yield(); - } - if (Driver && Driver.CurrentVehicle) - { - Game.LogTrivial($"{Vehicle.Model.Name} releasing from stop waypoint."); - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Vehicle, 0f, 1, true); - Driver.Tasks.CruiseWithVehicle(5f); - } - } - - bool VehicleAndDriverAreValid() - { - if (this == null) - { - Game.LogTrivial($"CollectedVehicle is null"); - return false; - } - if (!Vehicle)// && !Dismissed) - { - Game.LogTrivial($"Vehicle is null"); - Dismiss(); - return false; - } - if (!Driver || !Driver.CurrentVehicle || !Driver.IsAlive) - { - Game.LogTrivial($"Driver is null or dead or not in a vehicle"); - Dismiss(); - return false; - } - return true; - } - } - - internal void Dismiss(Dismiss dismissOption = Utils.Dismiss.FromPath, Path newPath = null) - { - if(Vehicle) - { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Driver.LastVehicle, 0f, 1, true); - Vehicle.Dismiss(); - } - if (Driver) - { - Driver.Dismiss(); - } - if (!Vehicle) - { - Game.LogTrivial($"Vehicle is null."); - return; - } - if (!Driver) - { - Game.LogTrivial($"Driver is null."); - return; - } - - if (dismissOption == Utils.Dismiss.FromWorld) - { - DismissFromWorld(); - return; - } - - if (dismissOption == Utils.Dismiss.FromPlayer) - { - DismissFromPlayer(); - return; - } - - if(Driver.CurrentVehicle && StoppedAtWaypoint) - { - StoppedAtWaypoint = false; - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Driver.LastVehicle, 0f, 1, true); - Driver.Tasks.CruiseWithVehicle(5f); - } - Driver.Tasks.Clear(); - - if (dismissOption == Utils.Dismiss.FromWaypoint) - { - DismissFromWaypoint(); - } - - if (dismissOption == Utils.Dismiss.FromPath) - { - DismissFromPath(); - } - - if(dismissOption == Utils.Dismiss.FromDirected) - { - DismissFromDirect(); - } - - void DismissFromPlayer() - { - Dismissed = true; - Driver.Dismiss(); - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Vehicle, 0f, 1, true); - Vehicle.Dismiss(); - Path.CollectedVehicles.Remove(this); - } - - void DismissFromWorld() - { - Game.LogTrivial($"Dismissed {Vehicle.Model.Name} [{Vehicle.Handle}] from the world"); - while (Vehicle.HasOccupants) - { - foreach (Ped occupant in Vehicle.Occupants) - { - occupant.Dismiss(); - occupant.Delete(); - } - GameFiber.Yield(); - } - Vehicle.Delete(); - } - - void DismissFromWaypoint() - { - if (CurrentWaypoint == null || Path == null) - { - Game.LogTrivial($"CurrentWaypoint or Path is null"); - return; - } - - if (CurrentWaypoint?.Number != Path?.Waypoints.Count) - { - Game.LogTrivial($"{Vehicle?.Model.Name} [{Vehicle?.Handle}] dismissed from waypoint."); - SkipWaypoint = true; - } - else if (CurrentWaypoint?.Number == Path?.Waypoints.Count) - { - DismissFromPath(); - } - } - - void DismissFromPath() - { - Game.LogTrivial($"Dismissing {Vehicle?.Model.Name} [{Vehicle?.Handle}] from path"); - Dismissed = true; - - // Check if the vehicle is near any of the path's collector waypoints - GameFiber.StartNew(() => - { - var nearestCollectorWaypoint = Path.Waypoints.Where(wp => wp.IsCollector).OrderBy(wp => Vehicle.DistanceTo2D(wp.Position)).FirstOrDefault(); - if(nearestCollectorWaypoint == null) - { - Game.LogTrivial($"Nearest collector is null"); - } - else - { - while (nearestCollectorWaypoint != null && Vehicle && Vehicle.HasDriver && Driver && Driver.IsAlive && Vehicle.FrontPosition.DistanceTo2D(nearestCollectorWaypoint.Position) <= nearestCollectorWaypoint.CollectorRadius) - { - GameFiber.Yield(); - } - } - - if (!Vehicle || !Driver) - { - Game.LogTrivial($"Vehicle or driver is null"); - return; - } - - if (!Directed) - { - Path.CollectedVehicles.Remove(this); - Game.LogTrivial($"{Vehicle.Model.Name} [{Vehicle.Handle}] dismissed successfully."); - if (Driver) - { - if (Driver.GetAttachedBlip()) - { - Driver.GetAttachedBlip().Delete(); - } - Driver.BlockPermanentEvents = false; - Driver.Dismiss(); - } - if (Vehicle) - { - Vehicle.Dismiss(); - Vehicle.IsSirenOn = false; - Vehicle.IsSirenSilent = true; - } - } - }, "DismissFromPath Fiber"); - - } - - void DismissFromDirect() - { - Dismissed = true; - Directed = true; - if (newPath != null) - { - newPath.CollectedVehicles.Add(this); - Path.CollectedVehicles.Remove(this); - } - Driver.Tasks.Clear(); - } - } - } -} diff --git a/SceneManager/Objects/Path.cs b/SceneManager/Objects/Path.cs index ffac48a..de5bd08 100644 --- a/SceneManager/Objects/Path.cs +++ b/SceneManager/Objects/Path.cs @@ -21,7 +21,7 @@ namespace SceneManager.Objects [XmlArray("Waypoints")] [XmlArrayItem("Waypoint")] public List Waypoints { get; set; } = new List(); - internal List CollectedVehicles { get; } = new List(); + internal List CollectedPeds { get; } = new List(); private List BlacklistedVehicles { get; } = new List(); private Path() { } @@ -138,24 +138,23 @@ namespace SceneManager.Objects } GameFiber.Yield(); } - }); + }, "3D Waypoint Line Drawing Fiber"); } internal void LoopForVehiclesToBeDismissed() { while (PathManager.Paths.Contains(this)) { - //Logger.Log($"Dismissing unused vehicles for cleanup"); - foreach (CollectedVehicle cv in CollectedVehicles.Where(cv => cv.Vehicle && (!cv.Vehicle.IsDriveable || cv.Vehicle.IsUpsideDown || !cv.Vehicle.HasDriver))) + foreach (CollectedPed cp in CollectedPeds.Where(x => x && x.CurrentVehicle && (!x.CurrentVehicle.IsDriveable || x.CurrentVehicle.IsUpsideDown || !x.CurrentVehicle.HasDriver))) { - if (cv.Vehicle.HasDriver) + if (cp.CurrentVehicle.HasDriver) { - cv.Vehicle.Driver.Dismiss(); + cp.CurrentVehicle.Driver.Dismiss(); } - cv.Vehicle.Dismiss(); + cp.CurrentVehicle.Dismiss(); } - CollectedVehicles.RemoveAll(cv => !cv.Vehicle); + CollectedPeds.RemoveAll(cp => !cp || !cp.CurrentVehicle); BlacklistedVehicles.RemoveAll(v => !v); GameFiber.Sleep(60000); } @@ -174,13 +173,11 @@ namespace SceneManager.Objects { foreach (Waypoint waypoint in Waypoints.Where(x => x != null && x.IsCollector)) { - foreach (Vehicle v in World.GetAllVehicles()) + foreach (Vehicle vehicle in World.GetAllVehicles()) { - if (VehicleIsValidForCollection(v) && VehicleIsNearWaypoint(v, waypoint)) + if (VehicleIsValidForCollection(vehicle) && VehicleIsNearWaypoint(vehicle, waypoint)) { - CollectedVehicle newCollectedVehicle = AddVehicleToCollection(v); - GameFiber AssignTasksFiber = new GameFiber(() => newCollectedVehicle.AssignWaypointTasks(this, waypoint)); - AssignTasksFiber.Start(); + CollectedPeds.Add(new CollectedPed(vehicle.Driver, this, waypoint)); } checksDone++; // Increment the counter inside the vehicle loop @@ -200,14 +197,6 @@ namespace SceneManager.Objects lastProcessTime = Game.GameTime; } - CollectedVehicle AddVehicleToCollection(Vehicle vehicle) - { - var collectedVehicle = new CollectedVehicle(vehicle, this); - CollectedVehicles.Add(collectedVehicle); - Game.LogTrivial($"Added {vehicle.Model.Name} to collection from path {Number} waypoint {1}."); - return collectedVehicle; - } - bool VehicleIsNearWaypoint(Vehicle v, Waypoint wp) { return v.FrontPosition.DistanceTo2D(wp.Position) <= wp.CollectorRadius && Math.Abs(wp.Position.Z - v.Position.Z) < 3; @@ -215,9 +204,13 @@ namespace SceneManager.Objects bool VehicleIsValidForCollection(Vehicle v) { - if (v && v != Game.LocalPlayer.Character.LastVehicle && (v.IsCar || v.IsBike || v.IsBicycle || v.IsQuadBike) && !v.IsSirenOn && v.IsEngineOn && v.IsOnAllWheels && v.Speed > 1 && !CollectedVehicles.Any(cv => cv?.Vehicle == v) && !BlacklistedVehicles.Contains(v)) + if(!v) { - var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p.Number != Number && p.CollectedVehicles.Any(cv => cv.Vehicle == v)); + return false; + } + if (v != Game.LocalPlayer.Character.LastVehicle && (v.IsCar || v.IsBike || v.IsBicycle || v.IsQuadBike) && !v.IsSirenOn && v.IsEngineOn && v.IsOnAllWheels && v.Speed > 1 && !CollectedPeds.Any(cp => cp && cp.CurrentVehicle == v) && !BlacklistedVehicles.Contains(v)) + { + var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p.Number != Number && p.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == v)); if (vehicleCollectedOnAnotherPath) { return false; @@ -232,6 +225,7 @@ namespace SceneManager.Objects } if (v.IsPoliceVehicle && !v.Driver.IsAmbient()) { + Game.LogTrivial($"Vehicle's driver not ambient."); BlacklistedVehicles.Add(v); return false; } @@ -271,23 +265,23 @@ namespace SceneManager.Objects private void DismissCollectedDrivers() { - List pathVehicles = CollectedVehicles.ToList(); // Have to enumerate over a copied list because you can't delete from the same list you're enumerating through - foreach (CollectedVehicle collectedVehicle in pathVehicles.Where(x => x != null && x.Vehicle && x.Driver)) + List collectedPedsCopy = CollectedPeds.ToList(); // Have to enumerate over a copied list because you can't delete from the same list you're enumerating through + foreach (CollectedPed collectedPed in collectedPedsCopy.Where(x => x != null && x && x.CurrentVehicle)) { - if (collectedVehicle.StoppedAtWaypoint) + if (collectedPed.StoppedAtWaypoint) { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(collectedVehicle.Vehicle, 1f, 1, true); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(collectedPed.CurrentVehicle, 1f, 1, true); } - if (collectedVehicle.Driver.GetAttachedBlip()) + if (collectedPed.GetAttachedBlip()) { - collectedVehicle.Driver.GetAttachedBlip().Delete(); + collectedPed.GetAttachedBlip().Delete(); } - collectedVehicle.Driver.Dismiss(); - collectedVehicle.Vehicle.IsSirenOn = false; - collectedVehicle.Vehicle.IsSirenSilent = true; - collectedVehicle.Vehicle.Dismiss(); + collectedPed.Dismiss(); + collectedPed.CurrentVehicle.IsSirenOn = false; + collectedPed.CurrentVehicle.IsSirenSilent = true; + collectedPed.CurrentVehicle.Dismiss(); - CollectedVehicles.Remove(collectedVehicle); + CollectedPeds.Remove(collectedPed); } } diff --git a/SceneManager/Objects/Waypoint.cs b/SceneManager/Objects/Waypoint.cs index fd5c49f..e410b34 100644 --- a/SceneManager/Objects/Waypoint.cs +++ b/SceneManager/Objects/Waypoint.cs @@ -75,10 +75,10 @@ namespace SceneManager.Objects if (IsStopWaypoint && !stopWaypoint) { Blip.Color = Color.Green; - foreach(CollectedVehicle cv in Path.CollectedVehicles.Where(cv => cv.Vehicle && cv.Path == Path && cv.CurrentWaypoint == this && cv.StoppedAtWaypoint)) + foreach(CollectedPed cp in Path.CollectedPeds.Where(cp => cp.CurrentVehicle && cp.Path == Path && cp.CurrentWaypoint == this && cp.StoppedAtWaypoint)) { // Logger.Log($"Setting StoppedAtWaypoint to false for {cv.Vehicle.Model.Name}"); - cv.Dismiss(Dismiss.FromWaypoint); + cp.Dismiss(Dismiss.FromWaypoint); } } else if(stopWaypoint && !IsStopWaypoint) @@ -148,11 +148,11 @@ namespace SceneManager.Objects { if (Blip) { - Blip.Position = Game.LocalPlayer.Character.Position; + Blip.Position = newWaypointPosition; } if (CollectorRadiusBlip) { - CollectorRadiusBlip.Position = Game.LocalPlayer.Character.Position; + CollectorRadiusBlip.Position = newWaypointPosition; } } } diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index 2a8e988..7ce9e59 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -10,18 +10,18 @@ namespace SceneManager.Utils { internal static class ConsoleCommands { - [ConsoleCommand] + [ConsoleCommand("ShowCollectedVehicleInfo")] internal static void Command_ShowCollectedVehicleInfo([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterVehicle), Name = "ShowCollectedVehicleInfo")] Vehicle vehicle) { foreach(Path path in PathManager.Paths) { - var collectedVehicle = path.CollectedVehicles.Where(v => v.Vehicle == vehicle).FirstOrDefault(); + var collectedVehicle = path.CollectedPeds.Where(v => v.CurrentVehicle == vehicle).FirstOrDefault(); if(collectedVehicle != null) { - Game.LogTrivial($"Vehicle: {collectedVehicle.Vehicle.Model.Name} [{collectedVehicle.Vehicle.Handle}]"); - Rage.Native.NativeFunction.Natives.xA6E9C38DB51D7748(collectedVehicle.Vehicle, out uint script); + Game.LogTrivial($"Vehicle: {collectedVehicle.CurrentVehicle.Model.Name} [{collectedVehicle.CurrentVehicle.Handle}]"); + Rage.Native.NativeFunction.Natives.xA6E9C38DB51D7748(collectedVehicle.CurrentVehicle, out uint script); Game.LogTrivial($"Vehicle spawned by: {script}"); - Game.LogTrivial($"Driver handle: {collectedVehicle.Driver.Handle}"); + Game.LogTrivial($"Driver handle: {collectedVehicle.Handle}"); Game.LogTrivial($"Path: {collectedVehicle.Path.Number}"); Game.LogTrivial($"Current waypoint: {collectedVehicle.CurrentWaypoint.Number}"); Game.LogTrivial($"StoppedAtWaypoint: {collectedVehicle.StoppedAtWaypoint}"); @@ -29,18 +29,18 @@ namespace SceneManager.Utils Game.LogTrivial($"ReadyForDirectTasks: {collectedVehicle.ReadyForDirectTasks}"); Game.LogTrivial($"Directed: {collectedVehicle.Directed}"); Game.LogTrivial($"Dismissed: {collectedVehicle.Dismissed}"); - Game.LogTrivial($"Task status: {collectedVehicle.Driver.Tasks.CurrentTaskStatus}"); + Game.LogTrivial($"Task status: {collectedVehicle.Tasks.CurrentTaskStatus}"); return; } } Game.LogTrivial($"{vehicle.Model.Name} [{vehicle.Handle}] was not found collected by any path."); } - [ConsoleCommand] + [ConsoleCommand("GetPedsActiveTasks")] internal static void Command_GetPedsActiveTasks([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterPedAliveOnly), Name = "GetPedsActiveTasks")] Ped ped) { - var tasks = new List(); - foreach (PedTask task in (PedTask[])Enum.GetValues(typeof(PedTask))) + var tasks = (PedTask[])Enum.GetValues(typeof(PedTask)); + foreach (PedTask task in tasks) { if(Rage.Native.NativeFunction.Natives.GET_IS_TASK_ACTIVE(ped, (int)task)) { diff --git a/SceneManager/Utils/DirectDriver.cs b/SceneManager/Utils/DirectDriver.cs index b01824b..a024260 100644 --- a/SceneManager/Utils/DirectDriver.cs +++ b/SceneManager/Utils/DirectDriver.cs @@ -49,14 +49,14 @@ namespace SceneManager.Utils internal static void Direct(Vehicle nearbyVehicle, Path path, Waypoint targetWaypoint) { - var nearbyVehiclesPath = PathManager.Paths.FirstOrDefault(p => p.CollectedVehicles.Any(v => v.Vehicle == nearbyVehicle)); + var nearbyVehiclesPath = PathManager.Paths.FirstOrDefault(p => p.CollectedPeds.Any(v => v.CurrentVehicle == nearbyVehicle)); if(nearbyVehiclesPath == null) { Game.LogTrivial($"Nearby vehicle does not belong to any path."); } - var collectedVehicleOnThisPath = path.CollectedVehicles.FirstOrDefault(v => v.Vehicle == nearbyVehicle); - var nearbyCollectedVehicleOtherPath = nearbyVehiclesPath?.CollectedVehicles.FirstOrDefault(v => v.Vehicle == nearbyVehicle); + var collectedVehicleOnThisPath = path.CollectedPeds.FirstOrDefault(v => v.CurrentVehicle == nearbyVehicle); + var nearbyCollectedVehicleOtherPath = nearbyVehiclesPath?.CollectedPeds.FirstOrDefault(p => p.CurrentVehicle == nearbyVehicle); if (collectedVehicleOnThisPath == null) { Game.LogTrivial($"Nearby vehicle does not belong to this path."); @@ -66,12 +66,12 @@ namespace SceneManager.Utils nearbyCollectedVehicleOtherPath.Dismiss(Dismiss.FromDirected, path); } Game.LogTrivial($"[Direct Driver] Adding {nearbyVehicle.Model.Name} to directed path."); - path.CollectedVehicles.Add(collectedVehicleOnThisPath = new CollectedVehicle(nearbyVehicle, path)); - collectedVehicleOnThisPath.Directed = true; - collectedVehicleOnThisPath.Driver.Tasks.Clear(); + path.CollectedPeds.Add(collectedVehicleOnThisPath = new CollectedPed(nearbyVehicle.Driver, path, targetWaypoint) { Directed = true }); + //collectedVehicleOnThisPath.Directed = true; + collectedVehicleOnThisPath.Tasks.Clear(); } - GameFiber.StartNew(() => collectedVehicleOnThisPath.AssignWaypointTasks(path, targetWaypoint)); + //GameFiber.StartNew(() => collectedVehicleOnThisPath.AssignWaypointTasks(path, targetWaypoint)); } } } diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs index 32ad386..69ebadf 100644 --- a/SceneManager/Utils/DismissDriver.cs +++ b/SceneManager/Utils/DismissDriver.cs @@ -8,7 +8,7 @@ namespace SceneManager.Utils { internal static void Dismiss(int dismissIndex) { - var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).FirstOrDefault(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()); + var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).FirstOrDefault(v => v.VehicleAndDriverValid() && v != Game.LocalPlayer.Character.CurrentVehicle); if (!nearbyVehicle) { Game.LogTrivial($"Nearby vehicle is null."); @@ -32,10 +32,10 @@ namespace SceneManager.Utils } else { - CollectedVehicle collectedVehicle = PathManager.Paths.SelectMany(x => x.CollectedVehicles).FirstOrDefault(x => x.Vehicle == nearbyVehicle); - if(collectedVehicle != null) + CollectedPed collectedPed = PathManager.Paths.SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle == nearbyVehicle); + if(collectedPed != null) { - collectedVehicle.Dismiss((Dismiss)dismissIndex); + collectedPed.Dismiss((Dismiss)dismissIndex); } } }