From 689c5da8ece8fa808376c87e291ba293eded12fc Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Tue, 25 Aug 2020 17:10:33 -0600 Subject: [PATCH] Refactored TrafficPathing class into VehicleCollector and AITasking classes --- SceneManager/AITasking.cs | 96 +++++++++ ...{TrafficPathing.cs => VehicleCollector.cs} | 190 +++++------------- 2 files changed, 147 insertions(+), 139 deletions(-) create mode 100644 SceneManager/AITasking.cs rename SceneManager/{TrafficPathing.cs => VehicleCollector.cs} (56%) diff --git a/SceneManager/AITasking.cs b/SceneManager/AITasking.cs new file mode 100644 index 0000000..63f6b6e --- /dev/null +++ b/SceneManager/AITasking.cs @@ -0,0 +1,96 @@ +using Rage; +using System.Collections.Generic; +using System.Linq; + +namespace SceneManager +{ + class AITasking + { + public static void AssignWaypointTasks(CollectedVehicle collectedVehicle, List waypoints, Waypoint currentWaypoint) + { + if (currentWaypoint != null && currentWaypoint.DrivingFlag == VehicleDrivingFlags.StopAtDestination) + { + StopVehicleAtWaypoint(collectedVehicle); + } + + DriveVehicleToNextWaypoint(collectedVehicle, waypoints, currentWaypoint); + + Game.LogTrivial($"{collectedVehicle.Vehicle.Model.Name} all tasks complete."); + DismissDriver(collectedVehicle); + } + + private static void DriveVehicleToNextWaypoint(CollectedVehicle collectedVehicle, List waypoints, Waypoint currentWaypoint) + { + var vehicle = collectedVehicle.Vehicle; + var driver = vehicle.Driver; + + for (int nextWaypoint = currentWaypoint.Number; nextWaypoint < waypoints.Count; nextWaypoint++) + { + if (waypoints.ElementAtOrDefault(nextWaypoint) == null) + { + Game.LogTrivial($"Waypoint is null"); + return; + } + if (!vehicle) + { + Game.LogTrivial($"Vehicle is null"); + return; + } + if (!driver) + { + Game.LogTrivial($"Driver is null"); + return; + } + + Game.LogTrivial($"{vehicle.Model.Name} is driving to waypoint {waypoints[nextWaypoint].Number}"); + if (waypoints.ElementAtOrDefault(nextWaypoint) != null && !collectedVehicle.StoppedAtWaypoint) + { + collectedVehicle.Vehicle.Driver.Tasks.DriveToPosition(waypoints[nextWaypoint].Position, waypoints[nextWaypoint].Speed, (VehicleDrivingFlags)263043, 2f).WaitForCompletion(); + } + + if (waypoints.ElementAtOrDefault(nextWaypoint) != null && waypoints[nextWaypoint].DrivingFlag == VehicleDrivingFlags.StopAtDestination) + { + Game.LogTrivial($"{collectedVehicle.Vehicle.Model.Name} stopping at waypoint."); + collectedVehicle.Vehicle.Driver.Tasks.PerformDrivingManeuver(VehicleManeuver.GoForwardStraightBraking); + collectedVehicle.SetStoppedAtWaypoint(true); + } + } + } + + private static void StopVehicleAtWaypoint(CollectedVehicle collectedVehicle) + { + Game.LogTrivial($"{collectedVehicle.Vehicle.Model.Name} stopping at waypoint."); + collectedVehicle.Vehicle.Driver.Tasks.PerformDrivingManeuver(VehicleManeuver.GoForwardStraightBraking); + collectedVehicle.SetStoppedAtWaypoint(true); + } + + public static void DismissDriver(CollectedVehicle cv) + { + if (!cv.Vehicle) + { + Game.LogTrivial($"Vehicle is not valid after tasks completed."); + return; + } + if (!cv.Vehicle.Driver) + { + Game.LogTrivial($"Driver is not valid after tasks completed."); + return; + } + + cv.SetDismissNow(true); + cv.SetStoppedAtWaypoint(false); + if (cv.Vehicle && cv.Vehicle.Driver) + { + cv.Vehicle.Driver.Dismiss(); + cv.Vehicle.Driver.Tasks.Clear(); + cv.Vehicle.Driver.BlockPermanentEvents = false; + cv.Vehicle.Driver.IsPersistent = false; + + cv.Vehicle.Dismiss(); + cv.Vehicle.IsPersistent = false; + + Game.LogTrivial($"{cv.Vehicle.Model.Name} dismissed successfully."); + } + } + } +} diff --git a/SceneManager/TrafficPathing.cs b/SceneManager/VehicleCollector.cs similarity index 56% rename from SceneManager/TrafficPathing.cs rename to SceneManager/VehicleCollector.cs index f641970..e12ac83 100644 --- a/SceneManager/TrafficPathing.cs +++ b/SceneManager/VehicleCollector.cs @@ -5,8 +5,30 @@ using Rage; namespace SceneManager { - public static class TrafficPathing + public static class VehicleCollector { + // Driving styles https://gtaforums.com/topic/822314-guide-driving-styles/ + // also https://vespura.com/fivem/drivingstyle/ + [Flags] + private enum EDrivingFlags + { + None = 0, + StopForVehicles = 1, + StopForPeds = 2, + AvoidEmptyVehicles = 8, + AvoidPeds = 16, + AvoidObjects = 32, + StopForTrafficLights = 128, + UseBlinkers = 256, + AllowWrongWay = 512, + TakeShortestPath = 262144, + IgnoreRoads = 4194304, + IgnorePathfinding = 16777216, + AvoidHighways = 536870912, + Normal = StopForVehicles | StopForPeds | AvoidEmptyVehicles | StopForTrafficLights | UseBlinkers | AllowWrongWay | IgnoreRoads, + TotalControl = AllowWrongWay | AvoidObjects | AvoidPeds | TakeShortestPath | StopForTrafficLights | IgnorePathfinding | StopForVehicles + } + public static Dictionary collectedVehicles = new Dictionary(); public static void StartCollectingAtWaypoint(List paths, Path path, Waypoint waypoint) @@ -34,10 +56,8 @@ namespace SceneManager SetVehicleAndDriverPersistence(vehicle); CollectedVehicle newCollectedVehicle = AddVehicleToCollection(path, waypoint, vehicle); Game.LogTrivial($"[WaypointVehicleCollector] Added {vehicle.Model.Name} to collection."); - //GameFiber DismissCheckFiber = new GameFiber(() => VehicleDismissed(collectedVehicle, path.Waypoints)); - //DismissCheckFiber.Start(); - GameFiber AssignTasksFiber = new GameFiber(() => AssignWaypointTasks(newCollectedVehicle, path.Waypoints, waypoint)); + GameFiber AssignTasksFiber = new GameFiber(() => AITasking.AssignWaypointTasks(newCollectedVehicle, path.Waypoints, waypoint)); AssignTasksFiber.Start(); } // If the vehicle is in the collection, but has no tasks @@ -46,12 +66,38 @@ namespace SceneManager Game.LogTrivial($"[WaypointVehicleCollector] {vehicle.Model.Name} already in collection, but with no tasks. Assigning tasks."); collectedVehicles[vehicle.LicensePlate].SetTasksAssigned(true); - GameFiber AssignTasksFiber = new GameFiber(() => AssignWaypointTasks(collectedVehicles[vehicle.LicensePlate], path.Waypoints, waypoint)); + GameFiber AssignTasksFiber = new GameFiber(() => AITasking.AssignWaypointTasks(collectedVehicles[vehicle.LicensePlate], path.Waypoints, waypoint)); AssignTasksFiber.Start(); } } } + private static Vehicle[] GetNearbyVehicles(Vector3 OriginPosition, float radius) + { + return (from x in World.GetAllVehicles() where !x.IsTrailer && x.DistanceTo(OriginPosition) < radius select x).ToArray(); + } + + private static void AssignStopForVehiclesFlag(List paths, Path path, Waypoint waypointData) + { + while (paths.Contains(path) && path.Waypoints.Contains(waypointData)) + { + if (path.IsEnabled) + { + foreach (Vehicle v in GetNearbyVehicles(waypointData.Position, 50f).Where(v => v && v.HasDriver && v.Driver)) + { + SetDriveTaskDrivingFlags(v.Driver, EDrivingFlags.StopForVehicles); + } + } + GameFiber.Sleep(500); + } + } + + private static void SetDriveTaskDrivingFlags(this Ped ped, EDrivingFlags flags) + { + ulong SetDriveTaskDrivingFlagsHash = 0xDACE1BE37D88AF67; + Rage.Native.NativeFunction.CallByHash(SetDriveTaskDrivingFlagsHash, ped, (int)flags); + } + private static CollectedVehicle AddVehicleToCollection(Path path, Waypoint waypoint, Vehicle v) { var collectedVehicle = new CollectedVehicle(v, v.LicensePlate, path.PathNum, path.Waypoints.Count, waypoint.Number, true, false, false); @@ -80,107 +126,6 @@ namespace SceneManager } } - // TODO: Refactor, extract methods - public static void AssignWaypointTasks(CollectedVehicle collectedVehicle, List waypoints, Waypoint currentWaypoint) - { - var vehicle = collectedVehicle.Vehicle; - var driver = vehicle.Driver; - - if (currentWaypoint != null && currentWaypoint.DrivingFlag == VehicleDrivingFlags.StopAtDestination) - { - Game.LogTrivial($"{collectedVehicle.Vehicle.Model.Name} stopping at waypoint."); - collectedVehicle.Vehicle.Driver.Tasks.PerformDrivingManeuver(VehicleManeuver.GoForwardStraightBraking); - collectedVehicle.SetStoppedAtWaypoint(true); - } - - for (int nextWaypoint = currentWaypoint.Number; nextWaypoint < waypoints.Count; nextWaypoint++) - { - if (waypoints.ElementAtOrDefault(nextWaypoint) == null) - { - Game.LogTrivial($"Waypoint is null"); - break; - } - - Game.LogTrivial($"{vehicle.Model.Name} is driving to waypoint {waypoints[nextWaypoint].Number}"); - if (waypoints.ElementAtOrDefault(nextWaypoint) != null && !collectedVehicle.StoppedAtWaypoint) - { - collectedVehicle.Vehicle.Driver.Tasks.DriveToPosition(waypoints[nextWaypoint].Position, waypoints[nextWaypoint].Speed, (VehicleDrivingFlags)263043, 2f).WaitForCompletion(); - } - - if (waypoints.ElementAtOrDefault(nextWaypoint) != null && waypoints[nextWaypoint].DrivingFlag == VehicleDrivingFlags.StopAtDestination) - { - Game.LogTrivial($"{collectedVehicle.Vehicle.Model.Name} stopping at waypoint."); - collectedVehicle.Vehicle.Driver.Tasks.PerformDrivingManeuver(VehicleManeuver.GoForwardStraightBraking); - collectedVehicle.SetStoppedAtWaypoint(true); - } - } - Game.LogTrivial($"{vehicle.Model.Name} all tasks complete."); - DismissDriver(collectedVehicle); - } - - public static void DismissDriver(CollectedVehicle cv) - { - cv.SetDismissNow(true); - cv.SetStoppedAtWaypoint(false); - if (cv.Vehicle && cv.Vehicle.Driver)// && !cv.Redirected) - { - cv.Vehicle.Driver.Dismiss(); - cv.Vehicle.Driver.Tasks.Clear(); - cv.Vehicle.Driver.BlockPermanentEvents = false; - cv.Vehicle.Driver.IsPersistent = false; - - cv.Vehicle.Dismiss(); - cv.Vehicle.IsPersistent = false; - - Game.LogTrivial($"{cv.Vehicle.Model.Name} dismissed successfully."); - } - else if (!cv.Vehicle) - { - Game.LogTrivial($"{cv.Vehicle.Model.Name} is not valid after tasks completed."); - } - else if (!cv.Vehicle.Driver) - { - Game.LogTrivial($"{cv.Vehicle.Model.Name} driver is not valid after tasks completed."); - } - } - - public static void AssignStopForVehiclesFlag(List paths, Path path, Waypoint waypointData) - { - while (paths.Contains(path) && path.Waypoints.Contains(waypointData)) - { - if (path.IsEnabled) - { - foreach (Vehicle v in GetNearbyVehicles(waypointData.Position, 50f).Where(v => v && v.HasDriver && v.Driver)) - { - SetDriveTaskDrivingFlags(v.Driver, EDrivingFlags.StopForVehicles); - } - } - GameFiber.Sleep(500); - } - } - - //public static void DirectTask(CollectedVehicle collectedVehicle, List waypoints) - //{ - // // Set persistence - - // // Assign tasks similar to joining from collection waypoint - // //GameFiber AssignTasksFiber = new GameFiber(() => AssignWaypointTasks(collectedVehicle, waypoints, waypoint)); - // //AssignTasksFiber.Start(); - - // // Give vehicle task to initial waypoint of desired path, then run a loop to keep giving the task until they're close enough in case they try to wander away too early - // // Need to figure out how to only get waypoints which are in front of or within 90 degrees of either side of the vehicle - // var nearestWaypoint = waypoints.OrderBy(wp => wp.Position).Take(1) as Waypoint; - - // collectedVehicle.Vehicle.Driver.Tasks.DriveToPosition(nearestWaypoint.Position, nearestWaypoint.Speed, (VehicleDrivingFlags)262539, 1f); // waypointData[0].WaypointPos - // while (nearestWaypoint != null && collectedVehicle.Vehicle && collectedVehicle.Vehicle.Driver && collectedVehicle.Vehicle.DistanceTo(waypoints[0].Position) > 3f && !collectedVehicle.DismissNow) - // { - // collectedVehicle.Vehicle.Driver.Tasks.DriveToPosition(nearestWaypoint.Position, nearestWaypoint.Speed, (VehicleDrivingFlags)262539, 1f); - // GameFiber.Sleep(500); - // } - // collectedVehicle.SetRedirected(false); - // Game.LogTrivial($"DirectTask loop over"); - //} - private static void VehicleDismissed(CollectedVehicle cv, List waypointData) { while (!cv.DismissNow) @@ -210,38 +155,5 @@ namespace SceneManager GameFiber.Sleep(1000); } } - - private static Vehicle[] GetNearbyVehicles(Vector3 OriginPosition, float radius) - { - return (from x in World.GetAllVehicles() where !x.IsTrailer && x.DistanceTo(OriginPosition) < radius select x).ToArray(); - } - - // Driving styles https://gtaforums.com/topic/822314-guide-driving-styles/ - // also https://vespura.com/fivem/drivingstyle/ - [Flags] - public enum EDrivingFlags - { - None = 0, - StopForVehicles = 1, - StopForPeds = 2, - AvoidEmptyVehicles = 8, - AvoidPeds = 16, - AvoidObjects = 32, - StopForTrafficLights = 128, - UseBlinkers = 256, - AllowWrongWay = 512, - TakeShortestPath = 262144, - IgnoreRoads = 4194304, - IgnorePathfinding = 16777216, - AvoidHighways = 536870912, - Normal = StopForVehicles | StopForPeds | AvoidEmptyVehicles | StopForTrafficLights | UseBlinkers | AllowWrongWay | IgnoreRoads, - TotalControl = AllowWrongWay | AvoidObjects | AvoidPeds | TakeShortestPath | StopForTrafficLights | IgnorePathfinding | StopForVehicles - } - - public static void SetDriveTaskDrivingFlags(this Ped ped, EDrivingFlags flags) - { - ulong SetDriveTaskDrivingFlagsHash = 0xDACE1BE37D88AF67; - Rage.Native.NativeFunction.CallByHash(SetDriveTaskDrivingFlagsHash, ped, (int)flags); - } } }