From f1554a4aea265f87263696c3048927f92850a5e5 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:35:21 -0700 Subject: [PATCH 001/112] Big refactor --- SceneManager/Menus/BarrierMenu.cs | 426 +++++----------------- SceneManager/Menus/EditPathMenu.cs | 119 +++---- SceneManager/Menus/EditWaypointMenu.cs | 360 +++++++------------ SceneManager/Menus/MainMenu.cs | 39 +- SceneManager/Menus/MenuManager.cs | 77 +++- SceneManager/Menus/PathCreationMenu.cs | 326 ++++------------- SceneManager/Menus/PathMainMenu.cs | 469 ++++++------------------- SceneManager/Menus/SettingsMenu.cs | 106 ++---- 8 files changed, 557 insertions(+), 1365 deletions(-) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index 1cc1539..111de48 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -7,428 +7,158 @@ using RAGENativeUI.Elements; using SceneManager.Objects; using SceneManager.Utils; -namespace SceneManager +namespace SceneManager.Menus { class BarrierMenu { - private static List trafficLightList = new List() { TrafficLight.Green, TrafficLight.Red, TrafficLight.Yellow, TrafficLight.None }; - internal static UIMenu barrierMenu = new UIMenu("Scene Manager", "~o~Barrier Management"); - internal static List barriers = new List(); - private static UIMenuListScrollerItem barrierList = new UIMenuListScrollerItem("Spawn Barrier", "", Settings.barriers.Keys); // Settings.barrierKeys - private static UIMenuNumericScrollerItem rotateBarrier = new UIMenuNumericScrollerItem("Rotate Barrier", "", 0, 350, 10); + private static List TrafficLightList { get; } = new List() { TrafficLight.Green, TrafficLight.Red, TrafficLight.Yellow, TrafficLight.None }; + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Barrier Management"); + internal static UIMenuListScrollerItem BarrierList { get; } = new UIMenuListScrollerItem("Spawn Barrier", "", Settings.Barriers.Keys); // Settings.barrierKeys + internal static UIMenuNumericScrollerItem RotateBarrier { get; } = new UIMenuNumericScrollerItem("Rotate Barrier", "", 0, 350, 10); // ADD CHECKBOX FOR BARRIER TO STOP TRAFFIC? ADD 3D MARKER TO SHOW WHERE TRAFFIC WILL STOP. ONLY NEED ONE CONE TO DO IT PER LANE - private static UIMenuCheckboxItem invincible = new UIMenuCheckboxItem("Indestructible", false); - private static UIMenuCheckboxItem immobile = new UIMenuCheckboxItem("Immobile", false); - private static UIMenuNumericScrollerItem barrierTexture = new UIMenuNumericScrollerItem("Change Texture", "", 0, 15, 1); - private static UIMenuCheckboxItem setBarrierLights = new UIMenuCheckboxItem("Enable Barrier Lights", Settings.EnableBarrierLightsDefaultOn); - private static UIMenuListScrollerItem setBarrierTrafficLight = new UIMenuListScrollerItem("Set Barrier Traffic Light", "", trafficLightList); - private static UIMenuListScrollerItem removeBarrierOptions = new UIMenuListScrollerItem("Remove Barrier", "", new[] { "Last Barrier", "Nearest Barrier", "All Barriers" }); - private static UIMenuItem resetBarriers = new UIMenuItem("Reset Barriers", "Reset all spawned barriers to their original position and rotation"); - internal static Object shadowBarrier; + internal static UIMenuCheckboxItem Invincible { get; } = new UIMenuCheckboxItem("Indestructible", false); + internal static UIMenuCheckboxItem Immobile { get; } = new UIMenuCheckboxItem("Immobile", false); + internal static UIMenuNumericScrollerItem BarrierTexture { get; } = new UIMenuNumericScrollerItem("Change Texture", "", 0, 15, 1); + internal static UIMenuCheckboxItem SetBarrierLights { get; } = new UIMenuCheckboxItem("Enable Barrier Lights", Settings.EnableBarrierLightsDefaultOn); + internal static UIMenuListScrollerItem SetBarrierTrafficLight { get; } = new UIMenuListScrollerItem("Set Barrier Traffic Light", "", TrafficLightList); + internal static UIMenuListScrollerItem RemoveBarrierOptions { get; } = new UIMenuListScrollerItem("Remove Barrier", "", new[] { "Last Barrier", "Nearest Barrier", "All Barriers" }); + internal static UIMenuItem ResetBarriers { get; } = new UIMenuItem("Reset Barriers", "Reset all spawned barriers to their original position and rotation"); - internal static void InstantiateMenu() + internal static void Initialize() { - barrierMenu.ParentMenu = MainMenu.mainMenu; - MenuManager.menuPool.Add(barrierMenu); + Menu.ParentMenu = MainMenu.Menu; + MenuManager.MenuPool.Add(Menu); - barrierMenu.OnItemSelect += BarrierMenu_OnItemSelected; - barrierMenu.OnScrollerChange += BarrierMenu_OnScrollerChanged; - barrierMenu.OnCheckboxChange += BarrierMenu_OnCheckboxChanged; - barrierMenu.OnMenuOpen += BarrierMenu_OnMenuOpen; + Menu.OnItemSelect += BarrierMenu_OnItemSelected; + Menu.OnScrollerChange += BarrierMenu_OnScrollerChanged; + Menu.OnCheckboxChange += BarrierMenu_OnCheckboxChanged; + Menu.OnMenuOpen += BarrierMenu_OnMenuOpen; } internal static void BuildBarrierMenu() { - barrierMenu.AddItem(barrierList); - barrierList.ForeColor = Color.Gold; + Menu.AddItem(BarrierList); + BarrierList.ForeColor = Color.Gold; - barrierMenu.AddItem(rotateBarrier); - - barrierMenu.AddItem(invincible); - - barrierMenu.AddItem(immobile); + Menu.AddItem(RotateBarrier); + Menu.AddItem(Invincible); + Menu.AddItem(Immobile); if (Settings.EnableAdvancedBarricadeOptions) { - barrierMenu.AddItem(barrierTexture); - barrierTexture.Index = 0; + Menu.AddItem(BarrierTexture); + BarrierTexture.Index = 0; - barrierMenu.AddItem(setBarrierLights); + Menu.AddItem(SetBarrierLights); //barrierMenu.AddItem(setBarrierTrafficLight); //setBarrierTrafficLight.Index = 3; } - barrierMenu.AddItem(removeBarrierOptions); - removeBarrierOptions.ForeColor = Color.Gold; - removeBarrierOptions.Enabled = false; + Menu.AddItem(RemoveBarrierOptions); + RemoveBarrierOptions.ForeColor = Color.Gold; + RemoveBarrierOptions.Enabled = false; - barrierMenu.AddItem(resetBarriers); - resetBarriers.ForeColor = Color.Gold; - resetBarriers.Enabled = false; + Menu.AddItem(ResetBarriers); + ResetBarriers.ForeColor = Color.Gold; + ResetBarriers.Enabled = false; } - internal static void CreateShadowBarrier() + internal static void ScrollBarrierList() { - if (shadowBarrier) + if (BarrierManager.PlaceholderBarrier) { - shadowBarrier.Delete(); + BarrierManager.PlaceholderBarrier.Delete(); } + BarrierTexture.Index = 0; - var barrierKey = Settings.barriers.Where(x => x.Key == barrierList.SelectedItem).FirstOrDefault().Key; - var barrierValue = Settings.barriers[barrierKey].Name; - shadowBarrier = new Object(barrierValue, MousePositionInWorld.GetPosition, rotateBarrier.Value); // Settings.barrierValues[barrierList.Index] - if (!shadowBarrier) + if (BarrierList.SelectedItem == "Flare") { - barrierMenu.Close(); - Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~Something went wrong creating the shadow barrier. Please try again."); - return; - } - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(shadowBarrier); - shadowBarrier.IsGravityDisabled = true; - shadowBarrier.IsCollisionEnabled = false; - shadowBarrier.Opacity = 0.7f; - - // Start with lights off for Parks's objects - if (Settings.EnableAdvancedBarricadeOptions) - { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(shadowBarrier, barrierTexture.Value); - SetBarrierLights(); - } - } - - private static void LoopToDisplayShadowBarrier() - { - while (barrierMenu.Visible) - { - if (barrierList.Selected || rotateBarrier.Selected || invincible.Selected || immobile.Selected || barrierTexture.Selected || setBarrierLights.Selected || setBarrierTrafficLight.Selected) - { - if (shadowBarrier) - { - UpdateShadowBarrierPosition(); - } - else if(MousePositionInWorld.GetPositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) - { - CreateShadowBarrier(); - } - } - else - { - if (shadowBarrier) - { - shadowBarrier.Delete(); - } - } - GameFiber.Yield(); - } - - if (shadowBarrier) - { - shadowBarrier.Delete(); - } - - void UpdateShadowBarrierPosition() - { - DisableBarrierMenuOptionsIfShadowConeTooFar(); - if (shadowBarrier) - { - // Delete and re-create for testing purposes.. Parks' stop light prop - //shadowBarrier.Delete(); - //CreateShadowBarrier(); - shadowBarrier.Heading = rotateBarrier.Value; - shadowBarrier.Position = MousePositionInWorld.GetPositionForBarrier; - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(shadowBarrier); - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); - } - - void DisableBarrierMenuOptionsIfShadowConeTooFar() - { - if (!shadowBarrier && MousePositionInWorld.GetPositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) - { - CreateShadowBarrier(); - - } - else if (shadowBarrier && shadowBarrier.Position.DistanceTo2D(Game.LocalPlayer.Character.Position) > Settings.BarrierPlacementDistance) - { - barrierList.Enabled = false; - rotateBarrier.Enabled = false; - shadowBarrier.Delete(); - } - else if (shadowBarrier && shadowBarrier.Position.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance && barrierList.SelectedItem == "Flare") - { - barrierList.Enabled = true; - rotateBarrier.Enabled = false; - } - else - { - barrierList.Enabled = true; - rotateBarrier.Enabled = true; - } - } - } - } - - private static void SpawnBarrier() - { - GameFiber.StartNew(() => - { - if (barrierList.SelectedItem == "Flare") - { - SpawnFlare(); - } - else - { - var barrier = new Object(shadowBarrier.Model, shadowBarrier.Position, rotateBarrier.Value); - barrier.SetPositionWithSnap(shadowBarrier.Position); - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(barrier, true); - if (invincible.Checked) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(barrier, true); - if (barrier.Model.Name != "prop_barrier_wat_03a") - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(barrier, true); - } - } - if (immobile.Checked) - { - barrier.IsPositionFrozen = true; - } - else - { - - barrier.IsPositionFrozen = false; - } - if (Settings.EnableAdvancedBarricadeOptions) - { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(barrier, barrierTexture.Value); - if (setBarrierLights.Checked) - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, false); - } - else - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, true); - } - - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); - barrier.IsPositionFrozen = true; - GameFiber.Sleep(50); - if (barrier && !immobile.Checked) - { - barrier.IsPositionFrozen = false; - } - } - barriers.Add(new Barrier(barrier, barrier.Position, barrier.Heading, invincible.Checked, immobile.Checked)); - //if (barriers.First().Object == barrier) - //{ - // barriers.First().GoAround(); - //} - removeBarrierOptions.Enabled = true; - resetBarriers.Enabled = true; - } - }, "Scene Manager Spawn Barrier Fiber"); - - - void SpawnFlare() - { - var flare = new Weapon("weapon_flare", shadowBarrier.Position, 1); - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true); - GameFiber.Sleep(1); - GameFiber.StartNew(() => - { - while (flare && flare.HeightAboveGround > 0.05f) - { - GameFiber.Yield(); - } - GameFiber.Sleep(1000); - if (flare) - { - flare.IsPositionFrozen = true; - } - }); - - barriers.Add(new Barrier(flare, flare.Position, flare.Heading, invincible.Checked, immobile.Checked)); - removeBarrierOptions.Enabled = true; - } - } - - internal static void RotateBarrier() - { - shadowBarrier.Heading = rotateBarrier.Value; - shadowBarrier.Position = MousePositionInWorld.GetPositionForBarrier; - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(shadowBarrier); - } - - private static void RemoveBarrier() - { - switch (removeBarrierOptions.Index) - { - case 0: - barriers[barriers.Count - 1].Object.Delete(); - barriers.RemoveAt(barriers.Count - 1); - break; - case 1: - var nearestBarrier = barriers.OrderBy(b => b.Object.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); - if (nearestBarrier != null) - { - nearestBarrier.Object.Delete(); - barriers.Remove(nearestBarrier); - } - break; - case 2: - foreach (Barrier b in barriers.Where(b => b.Object)) - { - b.Object.Delete(); - } - if (barriers.Count > 0) - { - barriers.Clear(); - } - break; - } - - removeBarrierOptions.Enabled = barriers.Count == 0 ? false : true; - resetBarriers.Enabled = barriers.Count == 0 ? false : true; - } - - private static void ResetBarriers() - { - GameFiber.StartNew(() => - { - var currentBarriers = barriers.Where(b => b.Model.Name != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash - foreach (Barrier barrier in currentBarriers) - { - var newBarrier = new Object(barrier.Model, barrier.Position, barrier.Rotation); - newBarrier.SetPositionWithSnap(barrier.Position); - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(newBarrier, true); - newBarrier.IsPositionFrozen = barrier.Immobile; - if (barrier.Invincible) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(newBarrier, true); - if (newBarrier.Model.Name != "prop_barrier_wat_03a") - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(newBarrier, true); - } - } - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(newBarrier, setBarrierTrafficLight.Index); - newBarrier.IsPositionFrozen = true; - GameFiber.Sleep(50); - if (newBarrier && !barrier.Immobile) - { - newBarrier.IsPositionFrozen = false; - } - barriers.Add(new Barrier(newBarrier, newBarrier.Position, newBarrier.Heading, barrier.Invincible, barrier.Immobile)); - - if (barrier.Object) - { - barrier.Object.Delete(); - } - barriers.Remove(barrier); - } - currentBarriers.Clear(); - }); - - } - - private static void SetBarrierLights() - { - if (setBarrierLights.Checked) - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(shadowBarrier, false); + RotateBarrier.Enabled = false; } else { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(shadowBarrier, true); + RotateBarrier.Enabled = true; } - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); + Menu.Width = SetMenuWidth(); } private static void BarrierMenu_OnCheckboxChanged(UIMenu sender, UIMenuCheckboxItem checkbox, bool @checked) { - if(checkbox == setBarrierLights) + if(checkbox == SetBarrierLights) { - SetBarrierLights(); + //SetBarrierLights(); + BarrierManager.SetBarrierLights(); } } private static void BarrierMenu_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int oldIndex, int newIndex) { - if (scrollerItem == barrierList) + if (scrollerItem == BarrierList) { - if (shadowBarrier) - { - shadowBarrier.Delete(); - } - barrierTexture.Index = 0; - - if(barrierList.SelectedItem == "Flare") - { - rotateBarrier.Enabled = false; - } - else - { - rotateBarrier.Enabled = true; - } - - barrierMenu.Width = SetMenuWidth(); + ScrollBarrierList(); } - if (scrollerItem == barrierTexture) + if (scrollerItem == BarrierTexture) { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(shadowBarrier, barrierTexture.Value); + Rage.Native.NativeFunction.Natives.x971DA0055324D033(BarrierManager.PlaceholderBarrier, BarrierTexture.Value); } - if (scrollerItem == setBarrierTrafficLight) + if (scrollerItem == SetBarrierTrafficLight) { - Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); + Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(BarrierManager.PlaceholderBarrier, SetBarrierTrafficLight.Index); } - if (scrollerItem == rotateBarrier) + if (scrollerItem == RotateBarrier) { - RotateBarrier(); + //RotateBarrier(); + BarrierManager.RotateBarrier(); } } private static void BarrierMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - if (selectedItem == barrierList) + if (selectedItem == BarrierList) { - SpawnBarrier(); + //SpawnBarrier(); + BarrierManager.SpawnBarrier(); } - if (selectedItem == removeBarrierOptions) + if (selectedItem == RemoveBarrierOptions) { - RemoveBarrier(); + //RemoveBarrier(); + BarrierManager.RemoveBarrier(RemoveBarrierOptions.Index); } - if (selectedItem == resetBarriers) + if (selectedItem == ResetBarriers) { - ResetBarriers(); + //ResetBarriers(); + BarrierManager.ResetBarriers(); } } private static void BarrierMenu_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { barrierList, barrierTexture, setBarrierTrafficLight, rotateBarrier, removeBarrierOptions }; + var scrollerItems = new List { BarrierList, BarrierTexture, SetBarrierTrafficLight, RotateBarrier, RemoveBarrierOptions }; - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~The shadow barrier will disappear if you aim too far away."); - CreateShadowBarrier(); + //CreatePlaceholderBarrier(); + BarrierManager.CreatePlaceholderBarrier(); - GameFiber ShadowConeLoopFiber = new GameFiber(() => LoopToDisplayShadowBarrier()); - ShadowConeLoopFiber.Start(); + //GameFiber PlaceholderBarrierRenderFiber = new GameFiber(() => LoopToDisplayShadowBarrier()); + GameFiber PlaceholderBarrierRenderFiber = new GameFiber(() => BarrierManager.LoopToRenderPlaceholderBarrier(), "Render Placeholder Barrier Loop Fiber"); + PlaceholderBarrierRenderFiber.Start(); - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } - internal static float SetMenuWidth() + private static float SetMenuWidth() { float defaultWidth = UIMenu.DefaultWidth; - barrierList.TextStyle.Apply(); + BarrierList.TextStyle.Apply(); Rage.Native.NativeFunction.Natives.x54CE8AC98E120CAB("STRING"); // _BEGIN_TEXT_COMMAND_GET_WIDTH - Rage.Native.NativeFunction.Natives.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(barrierList.SelectedItem); + Rage.Native.NativeFunction.Natives.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(BarrierList.SelectedItem); float textWidth = Rage.Native.NativeFunction.Natives.x85F061DA64ED2F67(true); // _END_TEXT_COMMAND_GET_WIDTH float padding = 0.00390625f * 2; // typical padding used in RNUI @@ -442,5 +172,17 @@ namespace SceneManager return selectedItemWidth * 1.6f; } } + + internal static void Cleanup() + { + foreach (Barrier barrier in BarrierManager.Barriers.Where(x => x.Object)) + { + barrier.Object.Delete(); + } + if (BarrierManager.PlaceholderBarrier) + { + BarrierManager.PlaceholderBarrier.Delete(); + } + } } } diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 01a672f..6367f2a 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -3,114 +3,89 @@ using System.Drawing; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; +using SceneManager.Menus; using SceneManager.Utils; namespace SceneManager { - class EditPathMenu + internal class EditPathMenu { - internal static UIMenu editPathMenu = new UIMenu("Scene Manager", "~o~Edit Path"); - private static UIMenuItem editPathWaypoints, deletePath, exportPath; - internal static UIMenuCheckboxItem disablePath; + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Edit Path"); + internal static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path", false); + private static UIMenuItem EditWaypoints { get; } = new UIMenuItem("Edit Waypoints"); + private static UIMenuItem deletePath { get; } = new UIMenuItem("Delete Path"); + private static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Path"); - internal static void InstantiateMenu() + internal static void Initialize() { - editPathMenu.ParentMenu = PathMainMenu.pathMainMenu; - MenuManager.menuPool.Add(editPathMenu); - editPathMenu.OnItemSelect += EditPath_OnItemSelected; - editPathMenu.OnCheckboxChange += EditPath_OnCheckboxChange; - editPathMenu.OnMenuOpen += EditPath_OnMenuOpen; + Menu.ParentMenu = PathMainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += EditPath_OnItemSelected; + Menu.OnCheckboxChange += EditPath_OnCheckboxChange; + Menu.OnMenuOpen += EditPath_OnMenuOpen; } internal static void BuildEditPathMenu() { - editPathMenu.AddItem(disablePath = new UIMenuCheckboxItem("Disable Path", false)); - editPathMenu.AddItem(editPathWaypoints = new UIMenuItem("Edit Waypoints")); - editPathWaypoints.ForeColor = Color.Gold; - editPathMenu.AddItem(deletePath = new UIMenuItem("Delete Path")); + Menu.AddItem(DisablePath); + Menu.AddItem(EditWaypoints); + EditWaypoints.ForeColor = Color.Gold; + Menu.AddItem(deletePath); deletePath.ForeColor = Color.Gold; - //editPathMenu.AddItem(exportPath = new UIMenuItem("Export Path")); - //exportPath.ForeColor = Color.Gold; - editPathMenu.RefreshIndex(); - } - - private static void EditPathWaypoints() - { - if (!SettingsMenu.threeDWaypoints.Checked) - { - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~You have 3D waypoints disabled in your settings. It's recommended to enable 3D waypoints while working with waypoints."); - } - EditWaypointMenu.BuildEditWaypointMenu(); - } - - private static void DeletePath() - { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - PathMainMenu.DeletePath(currentPath, Delete.Single); - } - - private static void DisablePath() - { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - if (disablePath.Checked) - { - currentPath.DisablePath(); - Game.LogTrivial($"Path {currentPath.Number} disabled."); - } - else - { - currentPath.EnablePath(); - Game.LogTrivial($"Path {currentPath.Number} enabled."); - } - } - - private static void ExportPath() - { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - // Reference PNWParks's UserInput class from LiveLights - var filename = PNWUserInput.GetUserInput("Type the name you would like to save your file as", "Enter a filename", 100) + ".xml"; - - // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) - if(string.IsNullOrWhiteSpace(filename)) - { - Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - return; - } - Game.LogTrivial($"Filename: {filename}"); - currentPath.Save(filename); + Menu.AddItem(ExportPath); + ExportPath.ForeColor = Color.Gold; + Menu.RefreshIndex(); } private static void EditPath_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - if (selectedItem == editPathWaypoints) + if (selectedItem == EditWaypoints) { - EditPathWaypoints(); + if (!SettingsMenu.ThreeDWaypoints.Checked) + { + Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~You have 3D waypoints disabled in your settings. It's recommended to enable 3D waypoints while working with waypoints."); + } + EditWaypointMenu.BuildEditWaypointMenu(); } if (selectedItem == deletePath) { - DeletePath(); + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + currentPath.Delete(); + PathManager.Paths.Remove(currentPath); + PathMainMenu.BuildPathMenu(); + PathMainMenu.Menu.Visible = true; } - if(selectedItem == exportPath) + if(selectedItem == ExportPath) { - ExportPath(); + PathManager.ExportPath(); } } private static void EditPath_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { - if (checkboxItem == disablePath) + if (checkboxItem == DisablePath) { - DisablePath(); + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + if (DisablePath.Checked) + { + currentPath.DisablePath(); + Game.LogTrivial($"Path {currentPath.Number} disabled."); + } + else + { + currentPath.EnablePath(); + Game.LogTrivial($"Path {currentPath.Number} enabled."); + } } } private static void EditPath_OnMenuOpen(UIMenu menu) { var scrollerItems = new List { }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } } } diff --git a/SceneManager/Menus/EditWaypointMenu.cs b/SceneManager/Menus/EditWaypointMenu.cs index 4413b08..19fffe3 100644 --- a/SceneManager/Menus/EditWaypointMenu.cs +++ b/SceneManager/Menus/EditWaypointMenu.cs @@ -7,308 +7,194 @@ using RAGENativeUI.Elements; using SceneManager.Objects; using SceneManager.Utils; -namespace SceneManager +namespace SceneManager.Menus { class EditWaypointMenu { - internal static UIMenu editWaypointMenu = new UIMenu("Scene Manager", "~o~Edit Waypoint"); - internal static UIMenuItem updateWaypoint = new UIMenuItem("Update Waypoint"); - internal static UIMenuItem removeWaypoint = new UIMenuItem("Remove Waypoint"); - internal static UIMenuItem addAsNewWaypoint = new UIMenuItem("Add as New Waypoint", "Adds a new waypoint to the end of the path with these settings"); - internal static UIMenuNumericScrollerItem editWaypoint; - private static UIMenuNumericScrollerItem changeWaypointSpeed; - internal static UIMenuCheckboxItem stopWaypointType; - internal static UIMenuCheckboxItem directWaypointBehavior = new UIMenuCheckboxItem("Drive directly to waypoint?", false, "If checked, vehicles will ignore traffic rules and drive directly to this waypoint."); - internal static UIMenuCheckboxItem collectorWaypoint; - internal static UIMenuNumericScrollerItem changeCollectorRadius = new UIMenuNumericScrollerItem("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1); - internal static UIMenuNumericScrollerItem changeSpeedZoneRadius = new UIMenuNumericScrollerItem("Speed Zone Radius", "The distance from this collector waypoint (in meters) non-collected vehicles will drive at this waypoint's speed", 5, 200, 5); - internal static UIMenuCheckboxItem updateWaypointPosition = new UIMenuCheckboxItem("Update Waypoint Position", false, "Updates the waypoint's position to the player's chosen position. You should turn this on if you're planning on adding this waypoint as a new waypoint."); + internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Edit Waypoint"); + internal static UIMenuItem UpdateWaypoint { get; } = new UIMenuItem("Update Waypoint"); + internal static UIMenuItem RemoveWaypoint { get; } = new UIMenuItem("Remove Waypoint"); + internal static UIMenuItem AddNewWaypoint { get; } = new UIMenuItem("Add as New Waypoint", "Adds a new waypoint to the end of the path with these settings"); + internal static UIMenuNumericScrollerItem EditWaypoint { get; set; } + internal static UIMenuNumericScrollerItem ChangeWaypointSpeed { get; private set; } + internal static UIMenuCheckboxItem StopWaypointType { get; private set; } + internal static UIMenuCheckboxItem DirectWaypointBehavior { get; } = new UIMenuCheckboxItem("Drive directly to waypoint?", false, "If checked, vehicles will ignore traffic rules and drive directly to this waypoint."); + internal static UIMenuCheckboxItem CollectorWaypoint { get; private set; } + internal static UIMenuNumericScrollerItem ChangeCollectorRadius { get; } = new UIMenuNumericScrollerItem("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1); + internal static UIMenuNumericScrollerItem ChangeSpeedZoneRadius { get; } = new UIMenuNumericScrollerItem("Speed Zone Radius", "The distance from this collector waypoint (in meters) non-collected vehicles will drive at this waypoint's speed", 5, 200, 5); + internal static UIMenuCheckboxItem UpdateWaypointPosition { get; } = new UIMenuCheckboxItem("Update Waypoint Position", false, "Updates the waypoint's position to the player's chosen position. You should turn this on if you're planning on adding this waypoint as a new waypoint."); - internal static void InstantiateMenu() + internal static void Initialize() { - editWaypointMenu.ParentMenu = EditPathMenu.editPathMenu; - MenuManager.menuPool.Add(editWaypointMenu); + Menu.ParentMenu = EditPathMenu.Menu; + MenuManager.MenuPool.Add(Menu); - editWaypointMenu.OnScrollerChange += EditWaypoint_OnScrollerChanged; - editWaypointMenu.OnCheckboxChange += EditWaypoint_OnCheckboxChanged; - editWaypointMenu.OnItemSelect += EditWaypoint_OnItemSelected; - editWaypointMenu.OnMenuOpen += EditWaypoint_OnMenuOpen; + Menu.OnScrollerChange += EditWaypoint_OnScrollerChanged; + Menu.OnCheckboxChange += EditWaypoint_OnCheckboxChanged; + Menu.OnItemSelect += EditWaypoint_OnItemSelected; + Menu.OnMenuOpen += EditWaypoint_OnMenuOpen; } internal static void BuildEditWaypointMenu() { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Value-1]; + Menu.MenuItems.Clear(); + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Value-1]; - editWaypoint = new UIMenuNumericScrollerItem("Edit Waypoint", "", currentPath.Waypoints.First().Number, currentPath.Waypoints.Last().Number, 1); - editWaypointMenu.Clear(); - editWaypointMenu.AddItem(editWaypoint); - editWaypoint.Index = 0; + Menu.AddItem(EditWaypoint = new UIMenuNumericScrollerItem("Edit Waypoint", "", currentPath.Waypoints.First().Number, currentPath.Waypoints.Last().Number, 1)); + EditWaypoint.Index = 0; - var currentWaypoint = currentPath.Waypoints.Where(wp => wp.Number == editWaypoint.Value).FirstOrDefault(); - if(currentWaypoint != null) + var currentWaypoint = currentPath.Waypoints.Where(wp => wp.Number == EditWaypoint.Value).FirstOrDefault(); + if(currentWaypoint == null) { - editWaypointMenu.AddItem(collectorWaypoint = new UIMenuCheckboxItem("Collector", currentWaypoint.IsCollector, "If this waypoint will collect vehicles to follow the path")); - - editWaypointMenu.AddItem(changeCollectorRadius); - changeCollectorRadius.Value = currentWaypoint.CollectorRadius != 0 - ? (int)currentWaypoint.CollectorRadius - : changeCollectorRadius.Minimum; - - editWaypointMenu.AddItem(changeSpeedZoneRadius); - changeSpeedZoneRadius.Value = currentWaypoint.CollectorRadius != 0 - ? (int)currentWaypoint.SpeedZoneRadius - : changeSpeedZoneRadius.Minimum; - - changeCollectorRadius.Enabled = collectorWaypoint.Checked ? true : false; - changeSpeedZoneRadius.Enabled = collectorWaypoint.Checked ? true : false; - - editWaypointMenu.AddItem(stopWaypointType = new UIMenuCheckboxItem("Is this a Stop waypoint?", currentWaypoint.IsStopWaypoint, "If checked, vehicles will drive to this waypoint, then stop.")); - editWaypointMenu.AddItem(directWaypointBehavior); - if(currentWaypoint.DrivingFlagType == DrivingFlagType.Direct) - { - directWaypointBehavior.Checked = true; - } - - editWaypointMenu.AddItem(changeWaypointSpeed = new UIMenuNumericScrollerItem("Waypoint Speed", $"How fast the AI will drive to the waypoint in ~b~{SettingsMenu.speedUnits.SelectedItem}", 5, 100, 5)); - changeWaypointSpeed.Value = (int)MathHelper.ConvertMetersPerSecondToMilesPerHour(currentWaypoint.Speed); - - editWaypointMenu.AddItem(updateWaypointPosition); - editWaypointMenu.AddItem(updateWaypoint); - updateWaypoint.ForeColor = Color.Gold; - editWaypointMenu.AddItem(removeWaypoint); - removeWaypoint.ForeColor = Color.Gold; - editWaypointMenu.AddItem(addAsNewWaypoint); - addAsNewWaypoint.ForeColor = Color.Gold; - - EditPathMenu.editPathMenu.Visible = false; - editWaypointMenu.RefreshIndex(); - editWaypointMenu.Visible = true; + Game.LogTrivial($"Current waypoint is null."); + return; } + + Menu.AddItem(CollectorWaypoint = new UIMenuCheckboxItem("Collector", currentWaypoint.IsCollector, "If this waypoint will collect vehicles to follow the path")); + + Menu.AddItem(ChangeCollectorRadius); + ChangeCollectorRadius.Value = currentWaypoint.CollectorRadius != 0 + ? (int)currentWaypoint.CollectorRadius + : ChangeCollectorRadius.Minimum; + + Menu.AddItem(ChangeSpeedZoneRadius); + ChangeSpeedZoneRadius.Value = currentWaypoint.CollectorRadius != 0 + ? (int)currentWaypoint.SpeedZoneRadius + : ChangeSpeedZoneRadius.Minimum; + + ChangeCollectorRadius.Enabled = CollectorWaypoint.Checked ? true : false; + ChangeSpeedZoneRadius.Enabled = CollectorWaypoint.Checked ? true : false; + + Menu.AddItem(StopWaypointType = new UIMenuCheckboxItem("Is this a Stop waypoint?", currentWaypoint.IsStopWaypoint, "If checked, vehicles will drive to this waypoint, then stop.")); + Menu.AddItem(DirectWaypointBehavior); + if(currentWaypoint.DrivingFlagType == DrivingFlagType.Direct) + { + DirectWaypointBehavior.Checked = true; + } + + Menu.AddItem(ChangeWaypointSpeed = new UIMenuNumericScrollerItem("Waypoint Speed", $"How fast the AI will drive to the waypoint in ~b~{SettingsMenu.SpeedUnits.SelectedItem}", 5, 100, 5)); + ChangeWaypointSpeed.Value = (int)MathHelper.ConvertMetersPerSecondToMilesPerHour(currentWaypoint.Speed); + + Menu.AddItem(UpdateWaypointPosition); + Menu.AddItem(UpdateWaypoint); + UpdateWaypoint.ForeColor = Color.Gold; + Menu.AddItem(RemoveWaypoint); + RemoveWaypoint.ForeColor = Color.Gold; + Menu.AddItem(AddNewWaypoint); + AddNewWaypoint.ForeColor = Color.Gold; + + EditPathMenu.Menu.Visible = false; + Menu.RefreshIndex(); + Menu.Visible = true; } - private static void UpdateCollectorMenuOptionsStatus() + private static void UpdateMenuSettings(Waypoint currentWaypoint) { - if (collectorWaypoint.Checked) - { - changeCollectorRadius.Enabled = true; - changeSpeedZoneRadius.Enabled = true; - } - else - { - changeCollectorRadius.Enabled = false; - changeSpeedZoneRadius.Enabled = false; - } + ChangeWaypointSpeed.Value = (int)MathHelper.ConvertMetersPerSecondToMilesPerHour(currentWaypoint.Speed); + StopWaypointType.Checked = currentWaypoint.IsStopWaypoint; + DirectWaypointBehavior.Checked = currentWaypoint.DrivingFlagType == DrivingFlagType.Direct ? true : false; + CollectorWaypoint.Checked = currentWaypoint.IsCollector; + ChangeCollectorRadius.Enabled = CollectorWaypoint.Checked ? true : false; + ChangeCollectorRadius.Value = (int)currentWaypoint.CollectorRadius; + ChangeSpeedZoneRadius.Enabled = CollectorWaypoint.Checked ? true : false; + ChangeSpeedZoneRadius.Value = (int)currentWaypoint.SpeedZoneRadius; + UpdateWaypointPosition.Checked = false; } - private static void UpdateWaypoint() + private static void ValidateCollectorRadiusSettings() { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - var currentWaypoint = currentPath.Waypoints[editWaypoint.Index]; - DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; - - if (currentPath.Waypoints.Count == 1) + if (ChangeCollectorRadius.Value > ChangeSpeedZoneRadius.Value) { - currentWaypoint.UpdateWaypoint(currentWaypoint, MousePositionInWorld.GetPosition, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked); - } - else - { - currentWaypoint.UpdateWaypoint(currentWaypoint, MousePositionInWorld.GetPosition, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), collectorWaypoint.Checked, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked); - } - - Game.LogTrivial($"Path {currentPath.Number} Waypoint {currentWaypoint.Number} updated [Driving style: {drivingFlag} | Stop waypoint: {stopWaypointType.Checked} | Speed: {changeWaypointSpeed.Value} | Collector: {currentWaypoint.IsCollector}]"); - - updateWaypointPosition.Checked = false; - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]~w~\nWaypoint {currentWaypoint.Number} updated."); - } - - private static void RemoveWaypoint() - { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - var currentWaypoint = currentPath.Waypoints[editWaypoint.Index]; - DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; - - if (currentPath.Waypoints.Count == 1) - { - Game.LogTrivial($"Deleting the last waypoint from the path."); - PathMainMenu.DeletePath(currentPath, Delete.Single); - - editWaypointMenu.Visible = false; - PathMainMenu.pathMainMenu.Visible = true; - } - else - { - currentWaypoint.Remove(); - currentPath.Waypoints.Remove(currentWaypoint); - Game.LogTrivial($"[Path {currentPath.Number}] Waypoint {currentWaypoint.Number} ({currentWaypoint.DrivingFlagType}) removed"); - - foreach (Waypoint wp in currentPath.Waypoints) + while (ChangeCollectorRadius.Value > ChangeSpeedZoneRadius.Value) { - wp.Number = currentPath.Waypoints.IndexOf(wp) + 1; - } - - editWaypointMenu.Clear(); - BuildEditWaypointMenu(); - - if (currentPath.Waypoints.Count == 1) - { - Hints.Display($"~o~Scene Manager ~y~[Hint]~w~\nYour path's first waypoint ~b~must~w~ be a collector. If it's not, it will automatically be made into one."); - Game.LogTrivial($"The path only has 1 waypoint left, this waypoint must be a collector."); - currentPath.Waypoints[0].UpdateWaypoint(currentWaypoint, MousePositionInWorld.GetPosition, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked); - collectorWaypoint.Checked = true; - changeCollectorRadius.Enabled = true; - changeSpeedZoneRadius.Enabled = true; + ChangeSpeedZoneRadius.ScrollToNextOption(); } } } - private static void AddAsNewWaypoint() + private static void ValidateSpeedZoneRadiusSettings() { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; - - var pathIndex = PathMainMenu.paths.IndexOf(currentPath); - var newWaypointBlip = CreateNewWaypointBlip(); - if (!currentPath.IsEnabled) + if (ChangeSpeedZoneRadius.Value < ChangeCollectorRadius.Value) { - newWaypointBlip.Alpha = 0.5f; - } - - if (collectorWaypoint.Checked) - { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, MousePositionInWorld.GetPosition, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip, true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value)); - } - else - { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, MousePositionInWorld.GetPosition, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip)); - } - - editWaypointMenu.RemoveItemAt(0); - editWaypoint = new UIMenuNumericScrollerItem("Edit Waypoint", "", currentPath.Waypoints.First().Number, currentPath.Waypoints.Last().Number, 1); - editWaypointMenu.AddItem(editWaypoint, 0); - editWaypoint.Index = editWaypoint.OptionCount - 1; - editWaypointMenu.RefreshIndex(); - updateWaypointPosition.Checked = false; - Game.LogTrivial($"New waypoint (#{currentPath.Waypoints.Last().Number}) added."); - - Blip CreateNewWaypointBlip() - { - var spriteNumericalEnum = pathIndex + 17; // 17 because the numerical value of these sprites are always 17 more than the path index - var blip = new Blip(MousePositionInWorld.GetPosition) - { - Scale = 0.5f, - Sprite = (BlipSprite)spriteNumericalEnum - }; - - if (collectorWaypoint.Checked) - { - blip.Color = Color.Blue; - } - else if (stopWaypointType.Checked) - { - blip.Color = Color.Red; - } - else - { - blip.Color = Color.Green; - } - - if (!SettingsMenu.mapBlips.Checked) - { - blip.Alpha = 0f; - } - - return blip; + ChangeCollectorRadius.Value = ChangeSpeedZoneRadius.Value; } } private static void EditWaypoint_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int first, int last) { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - var currentWaypoint = currentPath.Waypoints[editWaypoint.Value - 1]; + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + var currentWaypoint = currentPath.Waypoints[EditWaypoint.Value - 1]; - if (scrollerItem == editWaypoint) + if (scrollerItem == EditWaypoint) { - changeWaypointSpeed.Value = (int)MathHelper.ConvertMetersPerSecondToMilesPerHour(currentWaypoint.Speed); - stopWaypointType.Checked = currentWaypoint.IsStopWaypoint; - directWaypointBehavior.Checked = currentWaypoint.DrivingFlagType == DrivingFlagType.Direct ? true : false; - collectorWaypoint.Checked = currentWaypoint.IsCollector; - changeCollectorRadius.Enabled = collectorWaypoint.Checked ? true : false; - changeCollectorRadius.Value = (int)currentWaypoint.CollectorRadius; - changeSpeedZoneRadius.Enabled = collectorWaypoint.Checked ? true : false; - changeSpeedZoneRadius.Value = (int)currentWaypoint.SpeedZoneRadius; - updateWaypointPosition.Checked = false; + UpdateMenuSettings(currentWaypoint); } - if (scrollerItem == changeCollectorRadius) + if (scrollerItem == ChangeCollectorRadius) { - if (changeCollectorRadius.Value > changeSpeedZoneRadius.Value) - { - while(changeCollectorRadius.Value > changeSpeedZoneRadius.Value) - { - changeSpeedZoneRadius.ScrollToNextOption(); - } - } + ValidateCollectorRadiusSettings(); } - if (scrollerItem == changeSpeedZoneRadius) + if (scrollerItem == ChangeSpeedZoneRadius) { - if (changeSpeedZoneRadius.Value < changeCollectorRadius.Value) - { - changeCollectorRadius.Value = changeSpeedZoneRadius.Value; - } + ValidateSpeedZoneRadiusSettings(); } } private static void EditWaypoint_OnCheckboxChanged(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { - if (checkboxItem == collectorWaypoint) + if (checkboxItem == CollectorWaypoint) { - changeCollectorRadius.Enabled = collectorWaypoint.Checked ? true : false; - changeSpeedZoneRadius.Enabled = collectorWaypoint.Checked ? true : false; + ChangeCollectorRadius.Enabled = CollectorWaypoint.Checked ? true : false; + ChangeSpeedZoneRadius.Enabled = CollectorWaypoint.Checked ? true : false; } } private static void EditWaypoint_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index]; - var currentWaypoint = currentPath.Waypoints[editWaypoint.Index]; - DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; - if (selectedItem == updateWaypoint) + if (selectedItem == UpdateWaypoint) { - UpdateWaypoint(); + PathManager.UpdateWaypoint(); } - if (selectedItem == addAsNewWaypoint) + if (selectedItem == AddNewWaypoint) { - AddAsNewWaypoint(); + PathManager.AddNewEditWaypoint(currentPath); + + UpdateEditWaypointMenuItem(); } - if (selectedItem == removeWaypoint) + if (selectedItem == RemoveWaypoint) { - RemoveWaypoint(); + PathManager.RemoveEditWaypoint(currentPath); + if(PathManager.Paths.Count < 1) + { + return; + } + + BuildEditWaypointMenu(); + } + + void UpdateEditWaypointMenuItem() + { + // Need to close and re-open the menu so the mouse scroll works on the re-added menu item. + MenuManager.MenuPool.CloseAllMenus(); + Menu.RemoveItemAt(0); + EditWaypoint = new UIMenuNumericScrollerItem("Edit Waypoint", "", currentPath.Waypoints.First().Number, currentPath.Waypoints.Last().Number, 1); + Menu.AddItem(EditWaypoint, 0); + EditWaypoint.Index = EditWaypoint.OptionCount - 1; + Menu.RefreshIndex(); + UpdateWaypointPosition.Checked = false; + Menu.Visible = true; } } private static void EditWaypoint_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { editWaypoint, changeWaypointSpeed, changeCollectorRadius, changeSpeedZoneRadius }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); - } - - private static float SetDriveSpeedForWaypoint() - { - float convertedSpeed; - if (SettingsMenu.speedUnits.SelectedItem == SpeedUnits.MPH) - { - convertedSpeed = MathHelper.ConvertMilesPerHourToMetersPerSecond(changeWaypointSpeed.Value); - } - else - { - convertedSpeed = MathHelper.ConvertKilometersPerHourToMetersPerSecond(changeWaypointSpeed.Value); - } - - return convertedSpeed; + var scrollerItems = new List { EditWaypoint, ChangeWaypointSpeed, ChangeCollectorRadius, ChangeSpeedZoneRadius }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } } } diff --git a/SceneManager/Menus/MainMenu.cs b/SceneManager/Menus/MainMenu.cs index 229ce5f..40b0bda 100644 --- a/SceneManager/Menus/MainMenu.cs +++ b/SceneManager/Menus/MainMenu.cs @@ -3,42 +3,51 @@ using RAGENativeUI.Elements; using System.Collections.Generic; using System.Drawing; using SceneManager.Utils; +using Rage; -namespace SceneManager +namespace SceneManager.Menus { + // The only reason this class should change is to modify the main menu class MainMenu { - internal static UIMenu mainMenu { get; private set; } - private static UIMenuItem navigateToPathMenu, navigateToBarrierMenu, navigateToSettingsMenu; + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Main Menu"); - internal static void InstantiateMenu() + internal static void Initialize() { - mainMenu = new UIMenu("Scene Manager", "~o~Main Menu"); - MenuManager.menuPool.Add(mainMenu); + MenuManager.AddToMenuPool(Menu); + + Menu.OnMenuOpen += MainMenu_OnMenuOpen; } internal static void BuildMainMenu() { - mainMenu.AddItem(navigateToPathMenu = new UIMenuItem("Path Menu")); + var navigateToPathMenu = new UIMenuItem("Path Menu"); + Menu.AddItem(navigateToPathMenu); navigateToPathMenu.ForeColor = Color.Gold; - mainMenu.BindMenuToItem(PathMainMenu.pathMainMenu, navigateToPathMenu); + Menu.BindMenuToItem(PathMainMenu.Menu, navigateToPathMenu); - mainMenu.AddItem(navigateToBarrierMenu = new UIMenuItem("Barrier Menu")); + var navigateToBarrierMenu = new UIMenuItem("Barrier Menu"); + Menu.AddItem(navigateToBarrierMenu); navigateToBarrierMenu.ForeColor = Color.Gold; - mainMenu.BindMenuToItem(BarrierMenu.barrierMenu, navigateToBarrierMenu); + Menu.BindMenuToItem(BarrierMenu.Menu, navigateToBarrierMenu); - mainMenu.AddItem(navigateToSettingsMenu = new UIMenuItem("Settings")); + var navigateToSettingsMenu = new UIMenuItem("Settings Menu"); + Menu.AddItem(navigateToSettingsMenu); navigateToSettingsMenu.ForeColor = Color.Gold; - mainMenu.BindMenuToItem(SettingsMenu.settingsMenu, navigateToSettingsMenu); + Menu.BindMenuToItem(SettingsMenu.Menu, navigateToSettingsMenu); - mainMenu.RefreshIndex(); - mainMenu.OnMenuOpen += MainMenu_OnMenuOpen; + Menu.RefreshIndex(); } private static void MainMenu_OnMenuOpen(UIMenu menu) { var scrollerItems = new List { }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); + } + + internal static void DisplayMenu() + { + Menu.Visible = !Menu.Visible; } } } diff --git a/SceneManager/Menus/MenuManager.cs b/SceneManager/Menus/MenuManager.cs index 6b8edf1..be1202b 100644 --- a/SceneManager/Menus/MenuManager.cs +++ b/SceneManager/Menus/MenuManager.cs @@ -1,32 +1,36 @@ using RAGENativeUI; +using SceneManager.Menus; +using Rage; +using System.Linq; using RAGENativeUI.Elements; -using System.Collections.Generic; using System.Drawing; namespace SceneManager { + // The only reason this class should change is to modify how menus are are being handled internal static class MenuManager { - internal static MenuPool menuPool = new MenuPool(); - internal static Dictionary> menus = new Dictionary>(); + internal static MenuPool MenuPool { get; } = new MenuPool(); - internal static void InstantiateMenus() + internal static void InitializeMenus() { - MainMenu.InstantiateMenu(); - SettingsMenu.InstantiateMenu(); - PathMainMenu.InstantiateMenu(); - PathCreationMenu.InstantiateMenu(); - BarrierMenu.InstantiateMenu(); - EditPathMenu.InstantiateMenu(); - EditWaypointMenu.InstantiateMenu(); + MainMenu.Initialize(); + SettingsMenu.Initialize(); + PathMainMenu.Initialize(); + PathCreationMenu.Initialize(); + ImportPathMenu.Initialize(); + BarrierMenu.Initialize(); + EditPathMenu.Initialize(); + EditWaypointMenu.Initialize(); BuildMenus(); + ColorMenuItems(); DefineMenuMouseSettings(); } private static void DefineMenuMouseSettings() { - foreach (UIMenu menu in menuPool) + foreach (UIMenu menu in MenuPool) { menu.MouseControlsEnabled = false; menu.AllowCameraMovement = true; @@ -38,8 +42,57 @@ namespace SceneManager MainMenu.BuildMainMenu(); SettingsMenu.BuildSettingsMenu(); PathMainMenu.BuildPathMenu(); + ImportPathMenu.BuildImportMenu(); EditPathMenu.BuildEditPathMenu(); BarrierMenu.BuildBarrierMenu(); } + + private static void ColorMenuItems() + { + foreach(UIMenuItem menuItem in MenuPool.SelectMany(x => x.MenuItems)) + { + if (menuItem.Enabled && menuItem.ForeColor == Color.Gold) + { + menuItem.HighlightedBackColor = menuItem.ForeColor; + } + } + + } + + internal static bool AreMenusClosed() + { + if (!BarrierMenu.Menu.Visible && !PathMainMenu.Menu.Visible && !PathCreationMenu.Menu.Visible && !EditPathMenu.Menu.Visible && !EditWaypointMenu.Menu.Visible && !SettingsMenu.Menu.Visible) + { + return true; + } + else + { + return false; + } + } + + internal static void Update() + { + while (AnyMenuVisible()) + { + MenuPool.ProcessMenus(); + GameFiber.Yield(); + } + } + + private static bool AnyMenuVisible() + { + if(MenuPool.Any(x => x.Visible)) + { + return true; + } + + return false; + } + + internal static void AddToMenuPool(UIMenu menu) + { + MenuPool.Add(menu); + } } } diff --git a/SceneManager/Menus/PathCreationMenu.cs b/SceneManager/Menus/PathCreationMenu.cs index efea706..1e73f84 100644 --- a/SceneManager/Menus/PathCreationMenu.cs +++ b/SceneManager/Menus/PathCreationMenu.cs @@ -1,318 +1,148 @@ using System.Collections.Generic; using System.Drawing; -using System.Linq; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; using SceneManager.Utils; using SceneManager.Objects; -namespace SceneManager +namespace SceneManager.Menus { class PathCreationMenu { - internal static UIMenu pathCreationMenu = new UIMenu("Scene Manager", "~o~Path Creation Menu"); - private static UIMenuItem trafficAddWaypoint = new UIMenuItem("Add waypoint"), trafficRemoveWaypoint = new UIMenuItem("Remove last waypoint"), trafficEndPath = new UIMenuItem("End path creation"); - internal static UIMenuNumericScrollerItem waypointSpeed; - internal static UIMenuCheckboxItem stopWaypointType = new UIMenuCheckboxItem("Is this a Stop waypoint?", false, "If checked, vehicles will drive to this waypoint, then stop."); - internal static UIMenuCheckboxItem directWaypointBehavior = new UIMenuCheckboxItem("Drive directly to waypoint?", false, "If checked, vehicles will ignore traffic rules and drive directly to this waypoint."); - internal static UIMenuCheckboxItem collectorWaypoint = new UIMenuCheckboxItem("Collector", true, "If checked, this waypoint will collect vehicles to follow the path. Your path's first waypoint ~b~must~w~ be a collector."); - internal static UIMenuNumericScrollerItem collectorRadius = new UIMenuNumericScrollerItem("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1); - internal static UIMenuNumericScrollerItem speedZoneRadius = new UIMenuNumericScrollerItem("Speed Zone Radius", "The distance from this collector waypoint (in meters) non-collected vehicles will drive at this waypoint's speed", 5, 200, 5); - private static List menuItems = new List {collectorWaypoint, collectorRadius, speedZoneRadius, stopWaypointType, directWaypointBehavior, waypointSpeed, trafficAddWaypoint, trafficRemoveWaypoint, trafficEndPath }; + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Creation Menu"); + private static Path CurrentPath { get; set; } + private static UIMenuItem AddWaypoint { get; } = new UIMenuItem("Add waypoint"); + internal static UIMenuItem RemoveLastWaypoint { get; } = new UIMenuItem("Remove last waypoint"); + internal static UIMenuItem EndPathCreation { get; } = new UIMenuItem("End path creation"); + internal static UIMenuNumericScrollerItem WaypointSpeed { get; private set; } + internal static UIMenuCheckboxItem StopWaypoint { get; } = new UIMenuCheckboxItem("Is this a Stop waypoint?", false, "If checked, vehicles will drive to this waypoint, then stop."); + internal static UIMenuCheckboxItem DirectWaypoint { get; } = new UIMenuCheckboxItem("Drive directly to waypoint?", false, "If checked, vehicles will ignore traffic rules and drive directly to this waypoint."); + internal static UIMenuCheckboxItem CollectorWaypoint { get; } = new UIMenuCheckboxItem("Collector", true, "If checked, this waypoint will collect vehicles to follow the path. Your path's first waypoint ~b~must~w~ be a collector."); + internal static UIMenuNumericScrollerItem CollectorRadius { get; } = new UIMenuNumericScrollerItem("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1); + internal static UIMenuNumericScrollerItem SpeedZoneRadius { get; } = new UIMenuNumericScrollerItem("Speed Zone Radius", "The distance from this collector waypoint (in meters) non-collected vehicles will drive at this waypoint's speed", 5, 200, 5); + internal static State PathCreationState { get; set; } = State.Uninitialized; - internal static void InstantiateMenu() + internal static void Initialize() { - pathCreationMenu.ParentMenu = PathMainMenu.pathMainMenu; - MenuManager.menuPool.Add(pathCreationMenu); - pathCreationMenu.OnItemSelect += PathCreation_OnItemSelected; - pathCreationMenu.OnCheckboxChange += PathCreation_OnCheckboxChanged; - pathCreationMenu.OnScrollerChange += PathCreation_OnScrollerChanged; - pathCreationMenu.OnMenuOpen += PathCreation_OnMenuOpen; + Menu.ParentMenu = PathMainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += PathCreation_OnItemSelected; + Menu.OnCheckboxChange += PathCreation_OnCheckboxChanged; + Menu.OnScrollerChange += PathCreation_OnScrollerChanged; + Menu.OnMenuOpen += PathCreation_OnMenuOpen; } internal static void BuildPathCreationMenu() { - pathCreationMenu.AddItem(collectorWaypoint); - collectorWaypoint.Enabled = false; - collectorWaypoint.Checked = true; + Menu.MenuItems.Clear(); - pathCreationMenu.AddItem(collectorRadius); - collectorRadius.Index = Settings.CollectorRadius - 1; - collectorRadius.Enabled = true; + Menu.AddItem(CollectorWaypoint); + CollectorWaypoint.Enabled = false; + CollectorWaypoint.Checked = true; - pathCreationMenu.AddItem(speedZoneRadius); - speedZoneRadius.Index = (Settings.SpeedZoneRadius / 5) - 1; - speedZoneRadius.Enabled = true; + Menu.AddItem(CollectorRadius); + CollectorRadius.Index = Settings.CollectorRadius - 1; + CollectorRadius.Enabled = true; - pathCreationMenu.AddItem(stopWaypointType); - stopWaypointType.Checked = Settings.StopWaypoint; - pathCreationMenu.AddItem(directWaypointBehavior); - directWaypointBehavior.Checked = Settings.DirectDrivingBehavior; + Menu.AddItem(SpeedZoneRadius); + SpeedZoneRadius.Index = (Settings.SpeedZoneRadius / 5) - 1; + SpeedZoneRadius.Enabled = true; - pathCreationMenu.AddItem(waypointSpeed = new UIMenuNumericScrollerItem("Waypoint Speed", $"How fast the AI will drive to this waypoint in ~b~{SettingsMenu.speedUnits.SelectedItem}", 5, 100, 5)); - waypointSpeed.Index = (Settings.WaypointSpeed / 5) - 1; + Menu.AddItem(StopWaypoint); + StopWaypoint.Checked = Settings.StopWaypoint; + Menu.AddItem(DirectWaypoint); + DirectWaypoint.Checked = Settings.DirectDrivingBehavior; - pathCreationMenu.AddItem(trafficAddWaypoint); - trafficAddWaypoint.ForeColor = Color.Gold; + Menu.AddItem(WaypointSpeed = new UIMenuNumericScrollerItem("Waypoint Speed", $"How fast the AI will drive to this waypoint in ~b~{SettingsMenu.SpeedUnits.SelectedItem}", 5, 100, 5)); + WaypointSpeed.Index = (Settings.WaypointSpeed / 5) - 1; - pathCreationMenu.AddItem(trafficRemoveWaypoint); - trafficRemoveWaypoint.ForeColor = Color.Gold; - trafficRemoveWaypoint.Enabled = false; + Menu.AddItem(AddWaypoint); + AddWaypoint.ForeColor = Color.Gold; - pathCreationMenu.AddItem(trafficEndPath); - trafficEndPath.ForeColor = Color.Gold; - trafficEndPath.Enabled = false; + Menu.AddItem(RemoveLastWaypoint); + RemoveLastWaypoint.ForeColor = Color.Gold; + RemoveLastWaypoint.Enabled = false; - pathCreationMenu.RefreshIndex(); + Menu.AddItem(EndPathCreation); + EndPathCreation.ForeColor = Color.Gold; + EndPathCreation.Enabled = false; + + Menu.RefreshIndex(); } - private static void UpdateCollectorMenuOptionsStatus() + private static void ValidateCollectorRadiusSettings() { - if (collectorWaypoint.Checked) + if (CollectorRadius.Value > SpeedZoneRadius.Value) { - collectorRadius.Enabled = true; - speedZoneRadius.Enabled = true; - } - else - { - collectorRadius.Enabled = false; - speedZoneRadius.Enabled = false; - } - } - - private static void AddNewWaypoint() - { - var anyPathsExist = PathMainMenu.paths.Count > 0; - var waypointPosition = MousePositionInWorld.GetPosition; - - if (!anyPathsExist) - { - AddNewPathToPathsCollection(PathMainMenu.paths, 0); - } - else if (anyPathsExist && !PathMainMenu.paths.Any(p => p != null && p.State == State.Creating)) - { - AddNewPathToPathsCollection(PathMainMenu.paths, PathMainMenu.paths.IndexOf(PathMainMenu.paths.Where(p => p.State == State.Finished).Last()) + 1); - } - - var firstNonNullPath = PathMainMenu.paths.Where(p => p != null && p.State == State.Creating).First(); - var pathIndex = PathMainMenu.paths.IndexOf(firstNonNullPath); - var pathNumber = firstNonNullPath.Number; - var waypointNumber = PathMainMenu.paths[pathIndex].Waypoints.Count + 1; - DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; - - if (collectorWaypoint.Checked) - { - PathMainMenu.paths[pathIndex].Waypoints.Add(new Waypoint(firstNonNullPath, waypointNumber, waypointPosition, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, CreateWaypointBlip(), true, collectorRadius.Value, speedZoneRadius.Value)); - } - else - { - PathMainMenu.paths[pathIndex].Waypoints.Add(new Waypoint(firstNonNullPath, waypointNumber, waypointPosition, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, CreateWaypointBlip())); - } - Game.LogTrivial($"Path {pathNumber} Waypoint {waypointNumber} added [Driving style: {drivingFlag} | Stop waypoint: {stopWaypointType.Checked} | Speed: {waypointSpeed.Value} | Collector: {collectorWaypoint.Checked}]"); - - ToggleTrafficEndPathMenuItem(pathIndex); - collectorWaypoint.Enabled = true; - collectorWaypoint.Checked = false; - if (collectorWaypoint.Checked) - { - collectorRadius.Enabled = true; - speedZoneRadius.Enabled = true; - } - else - { - collectorRadius.Enabled = false; - speedZoneRadius.Enabled = false; - } - trafficRemoveWaypoint.Enabled = true; - PathMainMenu.createNewPath.Text = $"Continue Creating Path {pathNumber}"; - - float SetDriveSpeedForWaypoint() - { - float convertedSpeed; - if (SettingsMenu.speedUnits.SelectedItem == SpeedUnits.MPH) + while (CollectorRadius.Value > SpeedZoneRadius.Value) { - //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); - convertedSpeed = MathHelper.ConvertMilesPerHourToMetersPerSecond(waypointSpeed.Value); - //Logger.Log($"Converted speed: {convertedSpeed}m/s"); - } - else - { - //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); - convertedSpeed = MathHelper.ConvertKilometersPerHourToMetersPerSecond(waypointSpeed.Value); - //Logger.Log($"Converted speed: {convertedSpeed}m/s"); - } - - return convertedSpeed; - } - - Blip CreateWaypointBlip() - { - var spriteNumericalEnum = pathIndex + 17; // 17 because the numerical value of these sprites are always 17 more than the path index - var blip = new Blip(waypointPosition) - { - Scale = 0.5f, - Sprite = (BlipSprite)spriteNumericalEnum - }; - - if (collectorWaypoint.Checked) - { - blip.Color = Color.Blue; - } - else if (stopWaypointType.Checked) - { - blip.Color = Color.Red; - } - else - { - blip.Color = Color.Green; - } - - if (!SettingsMenu.mapBlips.Checked) - { - blip.Alpha = 0f; - } - - return blip; - } - } - - private static void RemoveWaypoint() - { - for (int i = 0; i < PathMainMenu.paths.Count; i++) - { - if (PathMainMenu.paths.ElementAtOrDefault(i) != null && PathMainMenu.paths[i].State == State.Creating) - { - Game.LogTrivial($"[Path {i + 1}] {PathMainMenu.paths[i].Waypoints.Last().DrivingFlagType} waypoint removed"); - PathMainMenu.paths[i].Waypoints.Last().Blip.Delete(); - PathMainMenu.paths[i].Waypoints.Last().RemoveSpeedZone(); - - if (PathMainMenu.paths[i].Waypoints.Last().CollectorRadiusBlip) - { - PathMainMenu.paths[i].Waypoints.Last().CollectorRadiusBlip.Delete(); - } - PathMainMenu.paths[i].Waypoints.RemoveAt(PathMainMenu.paths[i].Waypoints.IndexOf(PathMainMenu.paths[i].Waypoints.Last())); - - ToggleTrafficEndPathMenuItem(i); - - // If the path has no waypoints, disable the menu option to remove a waypoint - if (PathMainMenu.paths[i].Waypoints.Count == 0) - { - collectorWaypoint.Checked = true; - collectorWaypoint.Enabled = false; - speedZoneRadius.Enabled = true; - collectorRadius.Enabled = true; - trafficRemoveWaypoint.Enabled = false; - trafficEndPath.Enabled = false; - } + SpeedZoneRadius.ScrollToNextOption(); } } } - - private static void EndPath() + + private static void ValidateSpeedZoneRadiusSettings() { - for (int i = 0; i < PathMainMenu.paths.Count; i++) + if (SpeedZoneRadius.Value < CollectorRadius.Value) { - var currentPath = PathMainMenu.paths[i]; - if (PathMainMenu.paths.ElementAtOrDefault(i) != null && currentPath.State == State.Creating) - { - Game.LogTrivial($"[Path Creation] Path {currentPath.Number} finished with {currentPath.Waypoints.Count} waypoints."); - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path {i + 1} complete."); - currentPath.State = State.Finished; - currentPath.IsEnabled = true; - currentPath.Number = i + 1; - currentPath.LoopForVehiclesToBeDismissed(); - - GameFiber.StartNew(() => - { - currentPath.LoopWaypointCollection(); - }); - - PathMainMenu.createNewPath.Text = "Create New Path"; - PathMainMenu.BuildPathMenu(); - PathMainMenu.pathMainMenu.RefreshIndex(); - pathCreationMenu.Clear(); - PathMainMenu.pathMainMenu.Visible = true; - break; - } + CollectorRadius.Value = SpeedZoneRadius.Value; } } - private static void ToggleTrafficEndPathMenuItem(int pathIndex) - { - if (PathMainMenu.paths[pathIndex].Waypoints.Count > 0) - { - trafficEndPath.Enabled = true; - } - else - { - trafficEndPath.Enabled = false; - } - } - - private static void AddNewPathToPathsCollection(List paths, int pathIndex) - { - var pathNum = pathIndex + 1; - Game.LogTrivial($"Creating path {pathNum}"); - Game.DisplayNotification($"~o~Scene Manager\n~y~[Creating]~w~ Path {pathNum} started."); - paths.Insert(pathIndex, new Path(pathNum, State.Creating)); - trafficRemoveWaypoint.Enabled = false; - trafficEndPath.Enabled = false; - } - private static void PathCreation_OnCheckboxChanged(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { - if(checkboxItem == collectorWaypoint) + if(checkboxItem == CollectorWaypoint) { - collectorRadius.Enabled = collectorWaypoint.Checked ? true : false; - speedZoneRadius.Enabled = collectorWaypoint.Checked ? true : false; + CollectorRadius.Enabled = CollectorWaypoint.Checked ? true : false; + SpeedZoneRadius.Enabled = CollectorWaypoint.Checked ? true : false; } } private static void PathCreation_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - if (selectedItem == trafficAddWaypoint) + if (selectedItem == AddWaypoint) { - AddNewWaypoint(); + if (PathCreationState != State.Creating) + { + CurrentPath = PathManager.InitializeNewPath(); + } + + PathManager.AddWaypoint(CurrentPath); + PathManager.TogglePathCreationMenuItems(CurrentPath); } - if (selectedItem == trafficRemoveWaypoint) + if (selectedItem == RemoveLastWaypoint) { - RemoveWaypoint(); + PathManager.RemoveWaypoint(CurrentPath); + PathManager.TogglePathCreationMenuItems(CurrentPath); } - if (selectedItem == trafficEndPath) + if (selectedItem == EndPathCreation) { - EndPath(); + PathCreationState = State.Finished; + PathManager.EndPath(CurrentPath); } } private static void PathCreation_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int first, int last) { - if (scrollerItem == collectorRadius) + if (scrollerItem == CollectorRadius) { - if (collectorRadius.Value > speedZoneRadius.Value) - { - while (collectorRadius.Value > speedZoneRadius.Value) - { - speedZoneRadius.ScrollToNextOption(); - } - } + ValidateCollectorRadiusSettings(); } - if (scrollerItem == speedZoneRadius) + if (scrollerItem == SpeedZoneRadius) { - if (speedZoneRadius.Value < collectorRadius.Value) - { - collectorRadius.Value = speedZoneRadius.Value; - } + ValidateSpeedZoneRadiusSettings(); } } private static void PathCreation_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { collectorRadius, speedZoneRadius, waypointSpeed }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + var scrollerItems = new List { CollectorRadius, SpeedZoneRadius, WaypointSpeed }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } } } diff --git a/SceneManager/Menus/PathMainMenu.cs b/SceneManager/Menus/PathMainMenu.cs index 79b0c8a..817cdba 100644 --- a/SceneManager/Menus/PathMainMenu.cs +++ b/SceneManager/Menus/PathMainMenu.cs @@ -7,414 +7,157 @@ using RAGENativeUI.Elements; using SceneManager.Objects; using SceneManager.Utils; -namespace SceneManager +namespace SceneManager.Menus { internal static class PathMainMenu { - internal static List paths = new List(); - internal static List importedPaths = new List(); - private static string[] dismissOptions = new string[] { "From path", "From waypoint", "From world" }; - internal static UIMenu pathMainMenu = new UIMenu("Scene Manager", "~o~Path Manager Main Menu"); - internal static UIMenuItem createNewPath; - internal static UIMenuListScrollerItem importPath; - internal static UIMenuItem deleteAllPaths = new UIMenuItem("Delete All Paths"); - internal static UIMenuNumericScrollerItem editPath; - internal static UIMenuListScrollerItem directOptions = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); - internal static UIMenuNumericScrollerItem directDriver; - internal static UIMenuListScrollerItem dismissDriver = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~AI will be released from the path\n~b~From waypoint: ~w~AI will skip their current waypoint task\n~b~From world: ~w~AI will be removed from the world.", dismissOptions); - internal static UIMenuCheckboxItem disableAllPaths = new UIMenuCheckboxItem("Disable All Paths", false); + private static int MAX_PATH_LIMIT { get; } = 10; + internal static List ImportedPaths { get; } = new List(); + private static string[] DismissOptions { get; } = new string[] { "From path", "From waypoint", "From world" }; + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Manager Main Menu"); + internal static UIMenuItem CreateNewPath { get; } = new UIMenuItem("Create New Path"); + internal static UIMenuListScrollerItem ImportPath { get; } = new UIMenuListScrollerItem("Import Path", "Import a saved path", ImportedPaths); + internal static UIMenuItem DeleteAllPaths { get; } = new UIMenuItem("Delete All Paths"); + internal static UIMenuNumericScrollerItem EditPath { get; private set; } + internal static UIMenuListScrollerItem DirectOptions { get; } = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); + internal static UIMenuNumericScrollerItem DirectDriver { get; private set; } + internal static UIMenuListScrollerItem DismissDriver { get; } = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~AI will be released from the path\n~b~From waypoint: ~w~AI will skip their current waypoint task\n~b~From world: ~w~AI will be removed from the world.", DismissOptions); + internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Paths", false); - internal static void InstantiateMenu() + internal static void Initialize() { - pathMainMenu.ParentMenu = MainMenu.mainMenu; - MenuManager.menuPool.Add(pathMainMenu); - pathMainMenu.OnItemSelect += PathMenu_OnItemSelected; - pathMainMenu.OnCheckboxChange += PathMenu_OnCheckboxChange; - pathMainMenu.OnMenuOpen += PathMenu_OnMenuOpen; + Menu.ParentMenu = MainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += PathMenu_OnItemSelected; + Menu.OnCheckboxChange += PathMenu_OnCheckboxChange; + Menu.OnMenuOpen += PathMenu_OnMenuOpen; } internal static void BuildPathMenu() { - MenuManager.menuPool.CloseAllMenus(); - pathMainMenu.Clear(); + MenuManager.MenuPool.CloseAllMenus(); + Menu.Clear(); - pathMainMenu.AddItem(createNewPath = new UIMenuItem("Create New Path")); - createNewPath.ForeColor = Color.Gold; - //pathMainMenu.AddItem(importPath = new UIMenuListScrollerItem("Import Path", "Import a saved path", importedPaths)); - //importPath.ForeColor = Color.Gold; - pathMainMenu.AddItem(editPath = new UIMenuNumericScrollerItem("Edit Path", "", 1, paths.Count, 1)); - editPath.ForeColor = Color.Gold; - pathMainMenu.AddItem(disableAllPaths); - disableAllPaths.Enabled = true; - pathMainMenu.AddItem(deleteAllPaths); - deleteAllPaths.Enabled = true; - deleteAllPaths.ForeColor = Color.Gold; - pathMainMenu.AddItem(directOptions); - pathMainMenu.AddItem(directDriver = new UIMenuNumericScrollerItem("Direct nearest driver to path", "", 1, paths.Count, 1)); - directDriver.ForeColor = Color.Gold; - directDriver.Enabled = true; - pathMainMenu.AddItem(dismissDriver); - dismissDriver.ForeColor = Color.Gold; + Menu.AddItem(CreateNewPath); + CreateNewPath.ForeColor = Color.Gold; + Menu.AddItem(ImportPath); + ImportPath.ForeColor = Color.Gold; + ImportPath.Enabled = true; + Menu.AddItem(EditPath = new UIMenuNumericScrollerItem("Edit Path", "", 1, PathManager.Paths.Count, 1)); + EditPath.ForeColor = Color.Gold; + Menu.AddItem(DisableAllPaths); + DisableAllPaths.Enabled = true; + Menu.AddItem(DeleteAllPaths); + DeleteAllPaths.Enabled = true; + DeleteAllPaths.ForeColor = Color.Gold; + Menu.AddItem(DirectOptions); + Menu.AddItem(DirectDriver = new UIMenuNumericScrollerItem("Direct nearest driver to path", "", 1, PathManager.Paths.Count, 1)); // This must instantiate here because the Paths.Count value changes + DirectDriver.ForeColor = Color.Gold; + DirectDriver.Enabled = true; + Menu.AddItem(DismissDriver); + DismissDriver.ForeColor = Color.Gold; - if (paths.Count == 8) + if (PathManager.Paths.Count == MAX_PATH_LIMIT) { - createNewPath.Enabled = false; + CreateNewPath.Enabled = false; + ImportPath.Enabled = false; } - if (paths.Count == 0) + if (PathManager.Paths.Count == 0) { - editPath.Enabled = false; - deleteAllPaths.Enabled = false; - disableAllPaths.Enabled = false; - directDriver.Enabled = false; + EditPath.Enabled = false; + DeleteAllPaths.Enabled = false; + DisableAllPaths.Enabled = false; + DirectDriver.Enabled = false; + } + if(Settings.ImportedPaths.Count == 0) + { + ImportPath.Enabled = false; } - MenuManager.menuPool.RefreshIndex(); - } - - private static bool VehicleAndDriverValid(this Vehicle v) - { - if (v && v.HasDriver && v.Driver && v.Driver.IsAlive) - { - return true; - } - else - { - return false; - } - } - - private static void GoToEditPathMenu() - { - pathMainMenu.Visible = false; - EditPathMenu.editPathMenu.Visible = true; - } - - private static void GoToPathCreationMenu() - { - if (createNewPath.Text.Contains("Continue")) - { - pathMainMenu.Visible = false; - PathCreationMenu.pathCreationMenu.Visible = true; - } - else - { - PathCreationMenu.pathCreationMenu.Clear(); - PathCreationMenu.BuildPathCreationMenu(); - pathMainMenu.Visible = false; - PathCreationMenu.pathCreationMenu.Visible = true; - - // For each element in paths, determine if the element exists but is not finished yet, or if it doesn't exist, create it. - for (int i = 0; i <= paths.Count; i++) - { - if (paths.ElementAtOrDefault(i) != null && paths[i].State == State.Creating) - { - Game.DisplayNotification($"~o~Scene Manager~y~[Creating]\n~w~Resuming path {paths[i].Number}"); - break; - } - } - } - } - - private static void DisableAllPaths() - { - if (disableAllPaths.Checked) - { - foreach (Path path in paths) - { - path.DisablePath(); - } - Game.LogTrivial($"All paths disabled."); - } - else - { - foreach (Path path in paths) - { - path.EnablePath(); - } - Game.LogTrivial($"All paths enabled."); - } - } - - private static void DeleteAllPaths() - { - for (int i = 0; i < paths.Count; i++) - { - DeletePath(paths[i], Delete.All); - } - disableAllPaths.Checked = false; - paths.Clear(); - BuildPathMenu(); - pathMainMenu.Visible = true; - Game.LogTrivial($"All paths deleted"); - Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); - } - - internal static void DeletePath(Path path, Delete pathsToDelete) - { - //Game.LogTrivial($"Preparing to delete path {path.Number}"); - - RemoveVehiclesFromPath(); - RemoveBlipsAndYieldZones(); - - //Game.LogTrivial($"Clearing path waypoints"); - path.Waypoints.Clear(); - - // Manipulating the menu to reflect specific paths being deleted - if (pathsToDelete == Delete.Single) - { - paths.Remove(path); - UpdatePathNumbers(); - UpdatePathBlips(); - BuildPathMenu(); - pathMainMenu.Visible = true; - Game.LogTrivial($"Path {path.Number} deleted successfully."); - Game.DisplayNotification($"~o~Scene Manager\n~w~Path {path.Number} deleted."); - } - - EditPathMenu.editPathMenu.Reset(true, true); - EditPathMenu.disablePath.Enabled = true; - - void RemoveVehiclesFromPath() - { - //Game.LogTrivial($"Removing all vehicles on the path"); - var pathVehicles = path.CollectedVehicles.Where(cv => cv.Path.Number == path.Number).ToList(); - foreach (CollectedVehicle cv in pathVehicles.Where(cv => cv != null && cv.Vehicle && cv.Driver)) - { - if (cv.StoppedAtWaypoint) - { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(cv.Vehicle, 1f, 1, true); - } - //cv.StoppedAtWaypoint = false; - if (cv.Driver.GetAttachedBlip()) - { - cv.Driver.GetAttachedBlip().Delete(); - } - cv.Driver.Dismiss(); - cv.Vehicle.IsSirenOn = false; - cv.Vehicle.IsSirenSilent = true; - cv.Vehicle.Dismiss(); - - //Game.LogTrivial($"{cv.vehicle.Model.Name} cleared from path {cv.path}"); - path.CollectedVehicles.Remove(cv); - } - path.CollectedVehicles.Clear(); - } - - void RemoveBlipsAndYieldZones() - { - //Game.LogTrivial($"Removing waypoint blips and yield zones."); - foreach (Waypoint waypoint in path.Waypoints) - { - if (waypoint.SpeedZone != 0) - { - waypoint.RemoveSpeedZone(); - } - if (waypoint.Blip) - { - waypoint.Blip.Delete(); - } - if (waypoint.CollectorRadiusBlip) - { - waypoint.CollectorRadiusBlip.Delete(); - } - } - } - - void UpdatePathBlips() - { - foreach (Path p in paths) - { - foreach (Waypoint waypoint in p.Waypoints) - { - var blipColor = waypoint.Blip.Color; - waypoint.Blip.Sprite = (BlipSprite)paths.IndexOf(p) + 17; - waypoint.Blip.Color = blipColor; - } - } - } - - void UpdatePathNumbers() - { - for (int i = 0; i < paths.Count; i++) - { - paths[i].Number = i + 1; - } - } - } - - private static void DirectDriver() - { - var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).Where(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()).FirstOrDefault(); - var path = paths[directDriver.Index]; - var collectedVehicle = path.CollectedVehicles.Where(cv => cv.Vehicle == nearbyVehicle).FirstOrDefault(); - var waypoints = path.Waypoints; - var firstWaypoint = waypoints.First(); - var nearestWaypoint = waypoints.Where(wp => wp.Position.DistanceTo2D(nearbyVehicle.FrontPosition) < wp.Position.DistanceTo2D(nearbyVehicle.RearPosition)).OrderBy(wp => wp.Position.DistanceTo2D(nearbyVehicle)).FirstOrDefault(); - - if (nearbyVehicle) - { - var nearbyVehiclePath = paths.Where(p => p.CollectedVehicles.Any(v => v.Vehicle == nearbyVehicle)).FirstOrDefault(); - if (nearbyVehiclePath != null) - { - var nearbyCollectedVehicle = nearbyVehiclePath.CollectedVehicles.Where(v => v.Vehicle == nearbyVehicle).FirstOrDefault(); - if (nearbyCollectedVehicle != null) - { - nearbyCollectedVehicle.Dismiss(DismissOption.FromDirected, path); - if (directOptions.SelectedItem == "First waypoint") - { - GameFiber.StartNew(() => - { - nearbyCollectedVehicle.AssignWaypointTasks(path, firstWaypoint); - //AITasking.AssignWaypointTasks(nearbyCollectedVehicle, path, firstWaypoint); - }); - } - else - { - if (nearestWaypoint != null) - { - GameFiber.StartNew(() => - { - nearbyCollectedVehicle.AssignWaypointTasks(path, nearestWaypoint); - //AITasking.AssignWaypointTasks(nearbyCollectedVehicle, path, nearestWaypoint); - }); - } - } - return; - } - } - - // The vehicle should only be added to the collection when it's not null AND if the selected item is First Waypoint OR if the selected item is nearestWaypoint AND nearestWaypoint is not null - if (collectedVehicle == null && directOptions.SelectedItem == "First waypoint" || (directOptions.SelectedItem == "Nearest waypoint" && nearestWaypoint != null)) - { - Game.LogTrivial($"[Direct Driver] Adding {nearbyVehicle.Model.Name} to collection."); - path.CollectedVehicles.Add(new CollectedVehicle(nearbyVehicle, path)); - collectedVehicle = path.CollectedVehicles.Where(cv => cv.Vehicle == nearbyVehicle).FirstOrDefault(); - //Logger.Log($"Collected vehicle is {collectedVehicle.Vehicle.Model.Name}"); - } - - if (collectedVehicle == null) - { - return; - } - collectedVehicle.Directed = true; - collectedVehicle.Driver.Tasks.Clear(); - - //Logger.Log($"Collected vehicle properties: Dismissed [{collectedVehicle.Dismissed}], Directed [{collectedVehicle.Directed}], StopppedAtWaypoint [{collectedVehicle.StoppedAtWaypoint}]"); - if (directOptions.SelectedItem == "First waypoint") - { - GameFiber.StartNew(() => - { - collectedVehicle.AssignWaypointTasks(path, firstWaypoint); - //AITasking.AssignWaypointTasks(collectedVehicle, path, firstWaypoint); - }); - } - else - { - if (nearestWaypoint != null) - { - GameFiber.StartNew(() => - { - collectedVehicle.AssignWaypointTasks(path, nearestWaypoint); - //AITasking.AssignWaypointTasks(collectedVehicle, path, nearestWaypoint); - }); - } - } - } - } - - private static void DismissDriver() - { - var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).Where(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()).FirstOrDefault(); - if (nearbyVehicle) - { - if (!paths.Any() && dismissDriver.Index == (int)DismissOption.FromWorld) - { - Game.LogTrivial($"Dismissed {nearbyVehicle.Model.Name} from the world"); - while (nearbyVehicle && nearbyVehicle.HasOccupants) - { - foreach (Ped occupant in nearbyVehicle.Occupants) - { - occupant.Delete(); - } - GameFiber.Yield(); - } - if (nearbyVehicle) - { - nearbyVehicle.Delete(); - } - return; - } - - foreach (Path path in paths) - { - var collectedVehicle = path.CollectedVehicles.Where(cv => cv.Vehicle == nearbyVehicle).FirstOrDefault(); - if (collectedVehicle != null) - { - collectedVehicle.Dismiss((DismissOption)dismissDriver.Index); - break; - } - else if (dismissDriver.Index == (int)DismissOption.FromWorld) - { - Game.LogTrivial($"Dismissed {nearbyVehicle.Model.Name} from the world"); - while (nearbyVehicle && nearbyVehicle.HasOccupants) - { - foreach (Ped occupant in nearbyVehicle.Occupants) - { - occupant.Delete(); - } - GameFiber.Yield(); - } - if (nearbyVehicle) - { - nearbyVehicle.Delete(); - } - break; - } - } - } + MenuManager.MenuPool.RefreshIndex(); } private static void PathMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - if (selectedItem == createNewPath) + if (selectedItem == CreateNewPath) { GoToPathCreationMenu(); } - if (selectedItem == editPath) + if(selectedItem == ImportPath) { - pathMainMenu.Visible = false; - EditPathMenu.editPathMenu.Visible = true; + GoToImportMenu(); } - if (selectedItem == deleteAllPaths) + if (selectedItem == EditPath) { - DeleteAllPaths(); + GoToEditPathMenu(); } - if (selectedItem == directDriver) + if (selectedItem == DeleteAllPaths) { - DirectDriver(); + Utils.DeleteAllPaths.Delete(); + DisableAllPaths.Checked = false; + BuildPathMenu(); + Menu.Visible = true; } - if (selectedItem == dismissDriver) + if (selectedItem == DirectDriver) { - DismissDriver(); + if(Utils.DirectDriver.ValidateOptions(DirectOptions, PathManager.Paths[DirectDriver.Index], out Vehicle nearbyVehicle, out Waypoint targetWaypoint)) + { + Utils.DirectDriver.Direct(nearbyVehicle, PathManager.Paths[DirectDriver.Index], targetWaypoint); + } + } + + if (selectedItem == DismissDriver) + { + Utils.DismissDriver.Dismiss(DismissDriver.Index); } } private static void PathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { - if (checkboxItem == disableAllPaths) + if (checkboxItem == DisableAllPaths) { - DisableAllPaths(); + TogglePaths.Toggle(DisableAllPaths.Checked); } } private static void PathMenu_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { directOptions, directDriver, dismissDriver, editPath }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + var scrollerItems = new List { DirectOptions, DirectDriver, DismissDriver, EditPath }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); + } + + private static void GoToPathCreationMenu() + { + if (PathCreationMenu.PathCreationState == State.Creating) + { + Menu.Visible = false; + PathCreationMenu.Menu.Visible = true; + Path currentPath = PathManager.Paths.FirstOrDefault(x => x.State == State.Creating); + Game.DisplayNotification($"~o~Scene Manager~y~[Creating]\n~w~Resuming path {currentPath.Number}"); + } + else + { + PathCreationMenu.BuildPathCreationMenu(); + Menu.Visible = false; + PathCreationMenu.Menu.Visible = true; + } + } + + private static void GoToImportMenu() + { + Menu.Visible = false; + ImportPathMenu.Menu.Visible = true; + } + + private static void GoToEditPathMenu() + { + Menu.Visible = false; + EditPathMenu.Menu.Visible = true; } } } diff --git a/SceneManager/Menus/SettingsMenu.cs b/SceneManager/Menus/SettingsMenu.cs index 34cf754..3340514 100644 --- a/SceneManager/Menus/SettingsMenu.cs +++ b/SceneManager/Menus/SettingsMenu.cs @@ -3,113 +3,67 @@ using RAGENativeUI; using RAGENativeUI.Elements; using System; using System.Collections.Generic; -using SceneManager.Objects; using SceneManager.Utils; -namespace SceneManager +namespace SceneManager.Menus { class SettingsMenu { - internal static UIMenu settingsMenu = new UIMenu("Scene Manager", "~o~Plugin Settings"); - internal static UIMenuCheckboxItem threeDWaypoints = new UIMenuCheckboxItem("Enable 3D Waypoints", Settings.Enable3DWaypoints), - mapBlips = new UIMenuCheckboxItem("Enable Map Blips", Settings.EnableMapBlips), - hints = new UIMenuCheckboxItem("Enable Hints", Settings.EnableHints); - private static SpeedUnits[] speedArray = {SpeedUnits.MPH, SpeedUnits.KPH }; - internal static UIMenuListScrollerItem speedUnits = new UIMenuListScrollerItem("Speed Unit of Measure", "", new[] { SpeedUnits.MPH, SpeedUnits.KPH }); - internal static UIMenuItem saveSettings = new UIMenuItem("Save settings to .ini", "Updates the plugin's .ini file with the current settings so the next time the plugin is loaded, it will use these settings."); + internal static UIMenu Menu { get; set; } = new UIMenu("Scene Manager", "~o~Plugin Settings"); + internal static UIMenuCheckboxItem ThreeDWaypoints { get; } = new UIMenuCheckboxItem("Enable 3D Waypoints", Settings.Enable3DWaypoints); + internal static UIMenuCheckboxItem MapBlips { get; } = new UIMenuCheckboxItem("Enable Map Blips", Settings.EnableMapBlips); + internal static UIMenuCheckboxItem Hints { get; } = new UIMenuCheckboxItem("Enable Hints", Settings.EnableHints); + private static SpeedUnits[] SpeedUnitsArray { get; } = { Utils.SpeedUnits.MPH, Utils.SpeedUnits.KPH }; + internal static UIMenuListScrollerItem SpeedUnits { get; } = new UIMenuListScrollerItem("Speed Unit of Measure", "", new[] { Utils.SpeedUnits.MPH, Utils.SpeedUnits.KPH }); + internal static UIMenuItem SaveSettings { get; } = new UIMenuItem("Save settings to .ini", "Updates the plugin's .ini file with the current settings so the next time the plugin is loaded, it will use these settings."); - internal static void InstantiateMenu() + internal static void Initialize() { - settingsMenu.ParentMenu = MainMenu.mainMenu; - MenuManager.menuPool.Add(settingsMenu); - settingsMenu.OnCheckboxChange += SettingsMenu_OnCheckboxChange; - settingsMenu.OnScrollerChange += SettingsMenu_OnScrollerChange; - settingsMenu.OnItemSelect += SettingsMenu_OnItemSelected; - settingsMenu.OnMenuOpen += SettingsMenu_OnMenuOpen; + Menu.ParentMenu = MainMenu.Menu; + MenuManager.AddToMenuPool(Menu); + + Menu.OnCheckboxChange += SettingsMenu_OnCheckboxChange; + Menu.OnItemSelect += SettingsMenu_OnItemSelected; + Menu.OnMenuOpen += SettingsMenu_OnMenuOpen; } internal static void BuildSettingsMenu() { - settingsMenu.AddItem(threeDWaypoints); - settingsMenu.AddItem(mapBlips); - settingsMenu.AddItem(hints); - settingsMenu.AddItem(speedUnits); - speedUnits.Index = Array.IndexOf(speedArray, Settings.SpeedUnit); - settingsMenu.AddItem(saveSettings); - saveSettings.ForeColor = System.Drawing.Color.Gold; - } - - private static void ToggleMapBlips() - { - if (mapBlips.Checked) - { - foreach (Path path in PathMainMenu.paths) - { - foreach (Waypoint wp in path.Waypoints) - { - wp.EnableBlip(); - } - } - } - else - { - foreach (Path path in PathMainMenu.paths) - { - foreach (Waypoint wp in path.Waypoints) - { - wp.DisableBlip(); - } - } - } - } - - private static void ToggleHints() - { - Hints.Enabled = hints.Checked ? true : false; - } - - private static void ToggleSettings() - { - Settings.UpdateSettings(threeDWaypoints.Checked, mapBlips.Checked, hints.Checked, speedUnits.SelectedItem); - Game.DisplayHelp($"Scene Manager settings saved"); + Menu.AddItem(ThreeDWaypoints); + Menu.AddItem(MapBlips); + Menu.AddItem(Hints); + Menu.AddItem(SpeedUnits); + SpeedUnits.Index = Array.IndexOf(SpeedUnitsArray, Settings.SpeedUnit); + Menu.AddItem(SaveSettings); + SaveSettings.ForeColor = System.Drawing.Color.Gold; } private static void SettingsMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - if(selectedItem == saveSettings) + if(selectedItem == SaveSettings) { - Settings.UpdateSettings(threeDWaypoints.Checked, mapBlips.Checked, hints.Checked, speedUnits.SelectedItem); + Settings.UpdateSettings(ThreeDWaypoints.Checked, MapBlips.Checked, Hints.Checked, SpeedUnits.SelectedItem); Game.DisplayHelp($"Scene Manager settings saved"); } } private static void SettingsMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { - if (checkboxItem == mapBlips) + if (checkboxItem == MapBlips) { - ToggleMapBlips(); + PathManager.ToggleBlips(MapBlips.Checked); } - if (checkboxItem == hints) + if (checkboxItem == Hints) { - Hints.Enabled = hints.Checked ? true : false; - } - } - - private static void SettingsMenu_OnScrollerChange(UIMenu sender, UIMenuScrollerItem scrollerItem, int oldIndex, int newIndex) - { - if (scrollerItem == speedUnits) - { - // Clear the menu and rebuild it to reflect the menu item text change - PathCreationMenu.pathCreationMenu.Clear(); - PathCreationMenu.BuildPathCreationMenu(); + SceneManager.Hints.Enabled = Hints.Checked ? true : false; } } private static void SettingsMenu_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { speedUnits }; - RNUIMouseInputHandler.Initialize(menu, scrollerItems); + var scrollerItems = new List { SpeedUnits }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } } } \ No newline at end of file From 61141e9fb8f00c8ef376df4b2724e91081b2162a Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:35:57 -0700 Subject: [PATCH 002/112] Initial commit --- SceneManager/Menus/ImportPathMenu.cs | 61 ++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 SceneManager/Menus/ImportPathMenu.cs diff --git a/SceneManager/Menus/ImportPathMenu.cs b/SceneManager/Menus/ImportPathMenu.cs new file mode 100644 index 0000000..f4f3505 --- /dev/null +++ b/SceneManager/Menus/ImportPathMenu.cs @@ -0,0 +1,61 @@ +using RAGENativeUI; +using RAGENativeUI.Elements; +using System.Drawing; +using SceneManager.Objects; +using SceneManager.Utils; +using System.Collections.Generic; +using System.Linq; +using Rage; + +namespace SceneManager.Menus +{ + internal class ImportPathMenu + { + internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Import Path Menu"); + private static UIMenuItem menuItem; + + internal static void Initialize() + { + Menu.ParentMenu = PathMainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += ImportPathMenu_OnItemSelect; + Menu.OnMenuOpen += ImportPathMenu_OnMenuOpen; + } + + internal static void BuildImportMenu() + { + Menu.Clear(); + foreach(Path path in Settings.ImportedPaths) + { + Menu.AddItem(menuItem = new UIMenuItem(path.Name)); + menuItem.ForeColor = Color.Gold; + } + } + + private static void ImportPathMenu_OnMenuOpen(UIMenu menu) + { + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, new List()), "RNUI Mouse Input Fiber"); + + // Disable menu item if PathManager.Paths contains a path with a matching name + foreach (UIMenuItem menuItem in menu.MenuItems) + { + menuItem.Enabled = !PathManager.Paths.Any(x => x.Name == menuItem.Text); + } + } + + private static void ImportPathMenu_OnItemSelect(UIMenu sender, UIMenuItem selectedItem, int index) + { + // When the user clicks on a path, that path needs to be added from Settings.importedPaths to PathMainMenu.paths + Path importedPath = PathManager.ImportPath(Settings.ImportedPaths.FirstOrDefault(x => x.Name == selectedItem.Text)); + importedPath.Load(); + Game.LogTrivial($"{selectedItem.Text} added to paths collection as path #{importedPath.Number}. Paths count: {PathManager.Paths.Count}"); + selectedItem.Enabled = false; + + // Refresh path main menu + PathMainMenu.BuildPathMenu(); + PathMainMenu.Menu.RefreshIndex(); + Menu.Visible = true; + } + } +} From ad36c505464474edf77e6d15eb8f009045dddf53 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:36:13 -0700 Subject: [PATCH 003/112] Preparing for barrier import/export --- SceneManager/Objects/Barrier.cs | 68 ++++++--------------------------- 1 file changed, 11 insertions(+), 57 deletions(-) diff --git a/SceneManager/Objects/Barrier.cs b/SceneManager/Objects/Barrier.cs index 327c852..acddf5c 100644 --- a/SceneManager/Objects/Barrier.cs +++ b/SceneManager/Objects/Barrier.cs @@ -1,22 +1,19 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Rage; -using SceneManager.Utils; +using Rage; +using System.Xml.Serialization; namespace SceneManager.Objects { - class Barrier + [XmlRoot(ElementName = "Barrier", Namespace = "")] + public class Barrier // Change this and properties to Public for import/export { - internal Rage.Object Object { get; } - internal Model @Model{ get; } - internal Vector3 Position { get; } - internal float Rotation { get; } - internal bool Invincible { get; } + public Object Object { get; } + public Model @Model{ get; } + public Vector3 Position { get; } + public float Rotation { get; } + public bool Invincible { get; } + public bool Immobile { get; } - internal bool Immobile { get; } - - internal Barrier(Rage.Object barrier, Vector3 barrierPosition, float barrierRotation, bool invincible, bool immobile) + internal Barrier(Object barrier, Vector3 barrierPosition, float barrierRotation, bool invincible, bool immobile) { Object = barrier; @Model = barrier.Model; @@ -24,49 +21,6 @@ namespace SceneManager.Objects Rotation = barrierRotation; Invincible = invincible; Immobile = immobile; - //AddBlocker(); - } - - private void AddBlocker() - { - var blocker = new Rage.Object("prop_barier_conc_01a", Position, Rotation); - blocker.AttachTo(Object, 0, new Vector3(0, 0, 0), new Rotator()); - GameFiber.StartNew(() => - { - while (Object) - { - GameFiber.Yield(); - } - blocker.Delete(); - }); - } - - internal void GoAround() - { - GameFiber.StartNew(() => - { - var collected = new List(); - while (Object) - { - foreach (Vehicle v in World.GetAllVehicles()) - { - if(v && v.IsEngineOn) - { - if(v.HasDriver && v.Driver && v.Driver.IsAlive) - { - if (!collected.Contains(v)) - { - v.Driver.Tasks.Clear(); - v.Driver.Tasks.CruiseWithVehicle(5f, (VehicleDrivingFlags)17039872); - v.Driver.KeepTasks = true; - collected.Add(v); - } - } - } - } - GameFiber.Sleep(1000); - } - }); } } } From b7c9a5acf6180e245e716ed57a28172a18055386 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:36:52 -0700 Subject: [PATCH 004/112] Removed unused code. Fixed vehicles being stuck when the driver is removed at a stop waypoint --- SceneManager/Objects/CollectedVehicle.cs | 57 +++++++++++------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/SceneManager/Objects/CollectedVehicle.cs b/SceneManager/Objects/CollectedVehicle.cs index a43ca29..8f9f981 100644 --- a/SceneManager/Objects/CollectedVehicle.cs +++ b/SceneManager/Objects/CollectedVehicle.cs @@ -11,22 +11,12 @@ namespace SceneManager.Objects internal Vehicle Vehicle { get; private set; } internal Path Path { get; private set; } internal Waypoint CurrentWaypoint { get; private set; } - internal Waypoint NextWaypoint { 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, Waypoint currentWaypoint) - { - Vehicle = vehicle; - Driver = Vehicle.Driver; - Path = path; - CurrentWaypoint = currentWaypoint; - SetPersistence(); - } - internal CollectedVehicle(Vehicle vehicle, Path path) { Vehicle = vehicle; @@ -292,8 +282,17 @@ namespace SceneManager.Objects } } - internal void Dismiss(DismissOption dismissOption = DismissOption.FromPath, Path newPath = null) + 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."); @@ -305,25 +304,15 @@ namespace SceneManager.Objects return; } - if (dismissOption == DismissOption.FromWorld) + if (dismissOption == Utils.Dismiss.FromWorld) { DismissFromWorld(); return; } - if (dismissOption == DismissOption.FromPlayer) + if (dismissOption == Utils.Dismiss.FromPlayer) { - Dismissed = true; - //if (Driver) - //{ - Driver.Dismiss(); - //} - //if (Vehicle) - //{ - Vehicle.Dismiss(); - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Vehicle, 0f, 1, true); - //} - Path.CollectedVehicles.Remove(this); + DismissFromPlayer(); return; } @@ -331,28 +320,34 @@ namespace SceneManager.Objects { StoppedAtWaypoint = false; Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(Driver.LastVehicle, 0f, 1, true); - //if (Driver) - //{ - Driver.Tasks.CruiseWithVehicle(5f); - //} + Driver.Tasks.CruiseWithVehicle(5f); } Driver.Tasks.Clear(); - if (dismissOption == DismissOption.FromWaypoint) + if (dismissOption == Utils.Dismiss.FromWaypoint) { DismissFromWaypoint(); } - if (dismissOption == DismissOption.FromPath) + if (dismissOption == Utils.Dismiss.FromPath) { DismissFromPath(); } - if(dismissOption == DismissOption.FromDirected) + 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"); From f219bfd7f47d776f392a374ea69945bb2bd09d42 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:37:17 -0700 Subject: [PATCH 005/112] Refactored some methods and names --- SceneManager/Objects/Path.cs | 131 +++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 46 deletions(-) diff --git a/SceneManager/Objects/Path.cs b/SceneManager/Objects/Path.cs index ac59c7f..ffac48a 100644 --- a/SceneManager/Objects/Path.cs +++ b/SceneManager/Objects/Path.cs @@ -5,12 +5,15 @@ using System.Drawing; using System.Linq; using System.Xml.Serialization; using SceneManager.Utils; +using SceneManager.Menus; using System.IO; namespace SceneManager.Objects { - internal class Path // Change this to Public for import/export + [XmlRoot(ElementName = "Path", Namespace = "")] + public class Path // Change this to Public for import/export { + internal string Name { get; set; } internal int Number { get; set; } internal bool IsEnabled { get; set; } internal State State { get; set; } @@ -18,9 +21,8 @@ namespace SceneManager.Objects [XmlArray("Waypoints")] [XmlArrayItem("Waypoint")] public List Waypoints { get; set; } = new List(); - - internal List CollectedVehicles = new List(); - private List _blacklistedVehicles = new List(); + internal List CollectedVehicles { get; } = new List(); + private List BlacklistedVehicles { get; } = new List(); private Path() { } @@ -43,6 +45,18 @@ namespace SceneManager.Objects PathXMLManager.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + filename); } + internal void Load() + { + State = State.Finished; + EnablePath(); + foreach(Waypoint waypoint in Waypoints) + { + waypoint.LoadFromImport(this); + } + DrawLinesBetweenWaypoints(); + PathManager.EndPath(this); + } + private void LowerWaypointBlipsOpacity() { foreach (Waypoint wp in Waypoints) @@ -77,7 +91,7 @@ namespace SceneManager.Objects { wp.RemoveSpeedZone(); } - if (SettingsMenu.mapBlips.Checked) + if (SettingsMenu.MapBlips.Checked) { LowerWaypointBlipsOpacity(); } @@ -93,7 +107,7 @@ namespace SceneManager.Objects wp.AddSpeedZone(); } } - if (SettingsMenu.mapBlips.Checked) + if (SettingsMenu.MapBlips.Checked) { RestoreWaypointBlipsOpacity(); } @@ -105,7 +119,7 @@ namespace SceneManager.Objects { while(true) { - if (SettingsMenu.threeDWaypoints.Checked && (State == State.Finished && MenuManager.menuPool.IsAnyMenuOpen()) || (State == State.Creating && PathCreationMenu.pathCreationMenu.Visible)) + if (SettingsMenu.ThreeDWaypoints.Checked && (State == State.Finished && MenuManager.MenuPool.IsAnyMenuOpen()) || (State == State.Creating && PathCreationMenu.Menu.Visible)) { for (int i = 0; i < Waypoints.Count; i++) { @@ -129,67 +143,57 @@ namespace SceneManager.Objects internal void LoopForVehiclesToBeDismissed() { - GameFiber.StartNew(() => + while (PathManager.Paths.Contains(this)) { - while (PathMainMenu.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))) { - //Logger.Log($"Dismissing unused vehicles for cleanup"); - foreach (CollectedVehicle cv in CollectedVehicles.Where(cv => cv.Vehicle)) + if (cv.Vehicle.HasDriver) { - if (!cv.Vehicle.IsDriveable || cv.Vehicle.IsUpsideDown || !cv.Vehicle.HasDriver) - { - if (cv.Vehicle.HasDriver) - { - cv.Vehicle.Driver.Dismiss(); - } - cv.Vehicle.Dismiss(); - } + cv.Vehicle.Driver.Dismiss(); } - - CollectedVehicles.RemoveAll(cv => !cv.Vehicle); - _blacklistedVehicles.RemoveAll(v => !v); - GameFiber.Sleep(60000); + cv.Vehicle.Dismiss(); } - }); + + CollectedVehicles.RemoveAll(cv => !cv.Vehicle); + BlacklistedVehicles.RemoveAll(v => !v); + GameFiber.Sleep(60000); + } } internal void LoopWaypointCollection() { uint lastProcessTime = Game.GameTime; // Store the last time the full loop finished; this is a value in ms int yieldAfterChecks = 50; // How many calculations to do before yielding - while (PathMainMenu.paths.Contains(this)) + while (PathManager.Paths.Contains(this)) { if (IsEnabled) { int checksDone = 0; try { - foreach (Waypoint waypoint in Waypoints) + foreach (Waypoint waypoint in Waypoints.Where(x => x != null && x.IsCollector)) { - if (waypoint != null & waypoint.IsCollector) + foreach (Vehicle v in World.GetAllVehicles()) { - foreach (Vehicle v in World.GetAllVehicles()) + if (VehicleIsValidForCollection(v) && VehicleIsNearWaypoint(v, waypoint)) { - if (VehicleIsNearWaypoint(v, waypoint) && VehicleIsValidForCollection(v)) - { - CollectedVehicle newCollectedVehicle = AddVehicleToCollection(v); - GameFiber AssignTasksFiber = new GameFiber(() => newCollectedVehicle.AssignWaypointTasks(this, waypoint)); - //GameFiber AssignTasksFiber = new GameFiber(() => AITasking.AssignWaypointTasks(newCollectedVehicle, this, waypoint)); - AssignTasksFiber.Start(); - } + CollectedVehicle newCollectedVehicle = AddVehicleToCollection(v); + GameFiber AssignTasksFiber = new GameFiber(() => newCollectedVehicle.AssignWaypointTasks(this, waypoint)); + AssignTasksFiber.Start(); + } - checksDone++; // Increment the counter inside the vehicle loop - if (checksDone % yieldAfterChecks == 0) - { - GameFiber.Yield(); // Yield the game fiber after the specified number of vehicles have been checked - } + checksDone++; // Increment the counter inside the vehicle loop + if (checksDone % yieldAfterChecks == 0) + { + GameFiber.Yield(); // Yield the game fiber after the specified number of vehicles have been checked } } } } - catch + catch(Exception ex) { - //return; + Game.LogTrivial($"Vehicle collection error: {ex}"); } } GameFiber.Sleep((int)Math.Max(1, Game.GameTime - lastProcessTime)); // If the prior lines took more than a second to run, then you'll run again almost immediately, but if they ran fairly quickly, you can sleep the loop until the remainder of the time between checks has passed @@ -211,9 +215,9 @@ 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 && 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)) { - var vehicleCollectedOnAnotherPath = PathMainMenu.paths.Any(p => p.Number != Number && p.CollectedVehicles.Any(cv => cv.Vehicle == v)); + var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p.Number != Number && p.CollectedVehicles.Any(cv => cv.Vehicle == v)); if (vehicleCollectedOnAnotherPath) { return false; @@ -223,12 +227,12 @@ namespace SceneManager.Objects if(!v.Driver.IsAlive) { Game.LogTrivial($"Vehicle's driver is dead."); - _blacklistedVehicles.Add(v); + BlacklistedVehicles.Add(v); return false; } if (v.IsPoliceVehicle && !v.Driver.IsAmbient()) { - _blacklistedVehicles.Add(v); + BlacklistedVehicles.Add(v); return false; } } @@ -257,5 +261,40 @@ namespace SceneManager.Objects } } } + + internal void Delete() + { + DismissCollectedDrivers(); + RemoveWaypoints(); + Game.LogTrivial($"Path {Number} deleted."); + } + + 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)) + { + if (collectedVehicle.StoppedAtWaypoint) + { + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(collectedVehicle.Vehicle, 1f, 1, true); + } + if (collectedVehicle.Driver.GetAttachedBlip()) + { + collectedVehicle.Driver.GetAttachedBlip().Delete(); + } + collectedVehicle.Driver.Dismiss(); + collectedVehicle.Vehicle.IsSirenOn = false; + collectedVehicle.Vehicle.IsSirenSilent = true; + collectedVehicle.Vehicle.Dismiss(); + + CollectedVehicles.Remove(collectedVehicle); + } + } + + private void RemoveWaypoints() + { + Waypoints.ForEach(x => x.Delete()); + Waypoints.Clear(); + } } } From d22fb584a788c1a2488f7a0ee51640978ed87074 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:37:42 -0700 Subject: [PATCH 006/112] Refactored some methods and names --- SceneManager/Objects/Waypoint.cs | 140 +++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 36 deletions(-) diff --git a/SceneManager/Objects/Waypoint.cs b/SceneManager/Objects/Waypoint.cs index 1048df4..fd5c49f 100644 --- a/SceneManager/Objects/Waypoint.cs +++ b/SceneManager/Objects/Waypoint.cs @@ -2,10 +2,11 @@ using System.Drawing; using System.Linq; using SceneManager.Utils; +using SceneManager.Menus; namespace SceneManager.Objects { - internal class Waypoint // Change this to Public for import/export + public class Waypoint // Change this and select properties to Public for import/export { internal Path Path { get; set; } public int Number { get; set; } @@ -13,7 +14,7 @@ namespace SceneManager.Objects public float Speed { get; set; } public DrivingFlagType DrivingFlagType { get; set; } public bool IsStopWaypoint { get; set; } - internal Blip Blip { get; } + internal Blip Blip { get; private set; } public bool IsCollector { get; set; } public float CollectorRadius { get; set; } internal Blip CollectorRadiusBlip { get; set; } @@ -23,26 +24,26 @@ namespace SceneManager.Objects private Waypoint() { } - internal Waypoint(Path path, int waypointNum, Vector3 waypointPos, float speed, DrivingFlagType drivingFlag, bool stopWaypoint, Blip waypointBlip, bool collector = false, float collectorRadius = 1, float speedZoneRadius = 5) + internal Waypoint(Path path, int waypointNumber, Vector3 waypointPosition, float speed, DrivingFlagType drivingFlag, bool stopWaypoint, bool collector = false, float collectorRadius = 1, float speedZoneRadius = 5) { Path = path; - Number = waypointNum; - Position = waypointPos; + Number = waypointNumber; + Position = waypointPosition; Speed = speed; DrivingFlagType = drivingFlag; IsStopWaypoint = stopWaypoint; - Blip = waypointBlip; IsCollector = collector; CollectorRadius = collectorRadius; SpeedZoneRadius = speedZoneRadius; + CreateBlip(); if (collector) { AddSpeedZone(); - CollectorRadiusBlip = new Blip(waypointBlip.Position, collectorRadius) + CollectorRadiusBlip = new Blip(Blip.Position, collectorRadius) { - Color = waypointBlip.Color, + Color = Blip.Color, }; - if (SettingsMenu.mapBlips.Checked) + if (SettingsMenu.MapBlips.Checked) { CollectorRadiusBlip.Alpha = 0.5f; } @@ -51,6 +52,7 @@ namespace SceneManager.Objects CollectorRadiusBlip.Alpha = 0f; } } + DrawWaypointMarker(); } @@ -76,7 +78,7 @@ namespace SceneManager.Objects foreach(CollectedVehicle cv in Path.CollectedVehicles.Where(cv => cv.Vehicle && cv.Path == Path && cv.CurrentWaypoint == this && cv.StoppedAtWaypoint)) { // Logger.Log($"Setting StoppedAtWaypoint to false for {cv.Vehicle.Model.Name}"); - cv.Dismiss(DismissOption.FromWaypoint); + cv.Dismiss(Dismiss.FromWaypoint); } } else if(stopWaypoint && !IsStopWaypoint) @@ -155,19 +157,6 @@ namespace SceneManager.Objects } } - internal void Remove() - { - if (Blip) - { - Blip.Delete(); - } - if (CollectorRadiusBlip) - { - CollectorRadiusBlip.Delete(); - } - RemoveSpeedZone(); - } - internal void AddSpeedZone() { SpeedZone = World.AddSpeedZone(Position, SpeedZoneRadius, Speed); @@ -185,23 +174,23 @@ namespace SceneManager.Objects { while (true) { - if(SettingsMenu.threeDWaypoints.Checked && EnableWaypointMarker && Path.Waypoints.Contains(this)) + if(SettingsMenu.ThreeDWaypoints.Checked && EnableWaypointMarker && Path.Waypoints.Contains(this)) { - if (EditWaypointMenu.editWaypointMenu.Visible && PathMainMenu.editPath.Value == Path.Number && EditWaypointMenu.editWaypoint.Value == Number) + if (EditWaypointMenu.Menu.Visible && PathMainMenu.EditPath.Value == Path.Number && EditWaypointMenu.EditWaypoint.Value == Number) { - if (EditWaypointMenu.collectorWaypoint.Checked) + if (EditWaypointMenu.CollectorWaypoint.Checked) { - if (EditWaypointMenu.updateWaypointPosition.Checked) + if (EditWaypointMenu.UpdateWaypointPosition.Checked) { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.changeCollectorRadius.Value * 2, (float)EditWaypointMenu.changeCollectorRadius.Value * 2, 1f, 80, 130, 255, 100, false, false, 2, false, 0, 0, false); - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.changeSpeedZoneRadius.Value * 2, (float)EditWaypointMenu.changeSpeedZoneRadius.Value * 2, 1f, 255, 185, 80, 100, false, false, 2, false, 0, 0, false); + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.ChangeCollectorRadius.Value * 2, (float)EditWaypointMenu.ChangeCollectorRadius.Value * 2, 1f, 80, 130, 255, 100, false, false, 2, false, 0, 0, false); + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.ChangeSpeedZoneRadius.Value * 2, (float)EditWaypointMenu.ChangeSpeedZoneRadius.Value * 2, 1f, 255, 185, 80, 100, false, false, 2, false, 0, 0, false); } - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Position, 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.changeCollectorRadius.Value * 2, (float)EditWaypointMenu.changeCollectorRadius.Value * 2, 2f, 80, 130, 255, 100, false, false, 2, false, 0, 0, false); - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Position, 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.changeSpeedZoneRadius.Value * 2, (float)EditWaypointMenu.changeSpeedZoneRadius.Value * 2, 2f, 255, 185, 80, 100, false, false, 2, false, 0, 0, false); + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Position, 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.ChangeCollectorRadius.Value * 2, (float)EditWaypointMenu.ChangeCollectorRadius.Value * 2, 2f, 80, 130, 255, 100, false, false, 2, false, 0, 0, false); + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Position, 0, 0, 0, 0, 0, 0, (float)EditWaypointMenu.ChangeSpeedZoneRadius.Value * 2, (float)EditWaypointMenu.ChangeSpeedZoneRadius.Value * 2, 2f, 255, 185, 80, 100, false, false, 2, false, 0, 0, false); } - else if (EditWaypointMenu.stopWaypointType.Checked) + else if (EditWaypointMenu.StopWaypointType.Checked) { - if (EditWaypointMenu.updateWaypointPosition.Checked) + if (EditWaypointMenu.UpdateWaypointPosition.Checked) { Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 255, 65, 65, 100, false, false, 2, false, 0, 0, false); } @@ -209,17 +198,17 @@ namespace SceneManager.Objects } else { - if (EditWaypointMenu.updateWaypointPosition.Checked) + if (EditWaypointMenu.UpdateWaypointPosition.Checked) { Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, GetMousePositionInWorld(), 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 100, false, false, 2, false, 0, 0, false); } Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Position, 0, 0, 0, 0, 0, 0, 1f, 1f, 2f, 65, 255, 65, 100, false, false, 2, false, 0, 0, false); } } - else if ((Path.State == State.Finished && MenuManager.menuPool.IsAnyMenuOpen()) || (Path.State == State.Creating && PathCreationMenu.pathCreationMenu.Visible)) + else if ((Path.State == State.Finished && MenuManager.MenuPool.IsAnyMenuOpen()) || (Path.State == State.Creating && PathCreationMenu.Menu.Visible)) { float markerHeight = 1f; - if ((PathMainMenu.directDriver.Selected && PathMainMenu.directDriver.Value == Path.Number) || PathMainMenu.editPath.Selected && PathMainMenu.editPath.Value == Path.Number && (PathMainMenu.pathMainMenu.Visible || EditPathMenu.editPathMenu.Visible)) + if ((PathMainMenu.DirectDriver.Selected && PathMainMenu.DirectDriver.Value == Path.Number) || PathMainMenu.EditPath.Selected && PathMainMenu.EditPath.Value == Path.Number && (PathMainMenu.Menu.Visible || EditPathMenu.Menu.Visible)) { markerHeight = 2f; } @@ -283,6 +272,85 @@ namespace SceneManager.Objects } } + internal void Delete() + { + if (Blip) + { + Blip.Delete(); + } + if (CollectorRadiusBlip) + { + CollectorRadiusBlip.Delete(); + } + RemoveSpeedZone(); + } + + internal void LoadFromImport(Path path) + { + Path = path; + CreateBlip(); + Game.LogTrivial($"===== WAYPOINT DATA ====="); + Game.LogTrivial($"Path: {Path.Name}"); + Game.LogTrivial($"Number: {Number}"); + Game.LogTrivial($"Position: {Position}"); + Game.LogTrivial($"Speed: {Speed}"); + Game.LogTrivial($"DrivingFlag: {DrivingFlagType}"); + Game.LogTrivial($"Stop Waypoint: {IsStopWaypoint}"); + Game.LogTrivial($"Blip: {Blip}"); + Game.LogTrivial($"Collector: {IsCollector}"); + Game.LogTrivial($"Collector Radius: {CollectorRadius}"); + Game.LogTrivial($"SpeedZone Radius: {SpeedZoneRadius}"); + if (IsCollector) + { + CollectorRadiusBlip = new Blip(Position, CollectorRadius) + { + Color = Blip.Color, + }; + if (SettingsMenu.MapBlips.Checked) + { + CollectorRadiusBlip.Alpha = 0.5f; + } + else + { + CollectorRadiusBlip.Alpha = 0f; + } + } + DrawWaypointMarker(); + } + + private void CreateBlip() + { + var spriteNumericalEnum = Path.Number + 16; // 16 because the numerical value of these sprites are always 16 more than the path index + Blip = new Blip(Position) + { + Scale = 0.5f, + Sprite = (BlipSprite)spriteNumericalEnum + }; + + if (IsCollector) + { + Blip.Color = Color.Blue; + } + else if (IsStopWaypoint) + { + Blip.Color = Color.Red; + } + else + { + Blip.Color = Color.Green; + } + + if (!SettingsMenu.MapBlips.Checked) + { + Blip.Alpha = 0f; + } + + if (!Path.IsEnabled) + { + Blip.Alpha = 0.5f; + } + } + private static Vector3 GetMousePositionInWorld() { HitResult TracePlayerView(float maxTraceDistance = 100f, TraceFlags flags = TraceFlags.IntersectWorld) => TracePlayerView2(out Vector3 v1, out Vector3 v2, maxTraceDistance, flags); From 296206f5b901d16e35960370a422c7fc4aeac221 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:37:52 -0700 Subject: [PATCH 007/112] Updated version. --- SceneManager/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Properties/AssemblyInfo.cs b/SceneManager/Properties/AssemblyInfo.cs index 61eac82..b02b489 100644 --- a/SceneManager/Properties/AssemblyInfo.cs +++ b/SceneManager/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.0.0")] -[assembly: AssemblyFileVersion("2.2.0.0")] +[assembly: AssemblyVersion("2.2.2.2")] +[assembly: AssemblyFileVersion("2.2.2.2")] From fd12e1bea2372f5bfc48812d986a056634a3dbd3 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:38:17 -0700 Subject: [PATCH 008/112] Initial commit --- SceneManager/Utils/BarrierManager.cs | 286 ++++++++++++++++++++++++ SceneManager/Utils/DeleteAllPaths.cs | 15 ++ SceneManager/Utils/DependencyChecker.cs | 63 ++++++ SceneManager/Utils/DirectDriver.cs | 77 +++++++ SceneManager/Utils/DismissDriver.cs | 43 ++++ SceneManager/Utils/Hints.cs | 39 ++++ SceneManager/Utils/PathManager.cs | 258 +++++++++++++++++++++ SceneManager/Utils/TogglePaths.cs | 21 ++ SceneManager/Utils/UserInput.cs | 229 +++++++++++++++++++ 9 files changed, 1031 insertions(+) create mode 100644 SceneManager/Utils/BarrierManager.cs create mode 100644 SceneManager/Utils/DeleteAllPaths.cs create mode 100644 SceneManager/Utils/DependencyChecker.cs create mode 100644 SceneManager/Utils/DirectDriver.cs create mode 100644 SceneManager/Utils/DismissDriver.cs create mode 100644 SceneManager/Utils/Hints.cs create mode 100644 SceneManager/Utils/PathManager.cs create mode 100644 SceneManager/Utils/TogglePaths.cs create mode 100644 SceneManager/Utils/UserInput.cs diff --git a/SceneManager/Utils/BarrierManager.cs b/SceneManager/Utils/BarrierManager.cs new file mode 100644 index 0000000..06f430f --- /dev/null +++ b/SceneManager/Utils/BarrierManager.cs @@ -0,0 +1,286 @@ +using System.Collections.Generic; +using System.Linq; +using Rage; +using SceneManager.Menus; +using SceneManager.Objects; + +namespace SceneManager.Utils +{ + internal static class BarrierManager + { + internal static Object PlaceholderBarrier { get; private set; } + internal static List Barriers { get; } = new List(); + + internal static void CreatePlaceholderBarrier() + { + Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~The shadow barrier will disappear if you aim too far away."); + if (PlaceholderBarrier) + { + PlaceholderBarrier.Delete(); + } + + var barrierKey = Settings.Barriers.Where(x => x.Key == BarrierMenu.BarrierList.SelectedItem).FirstOrDefault().Key; + var barrierValue = Settings.Barriers[barrierKey].Name; + PlaceholderBarrier = new Rage.Object(barrierValue, UserInput.GetMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); + if (!PlaceholderBarrier) + { + BarrierMenu.Menu.Close(); + Game.LogTrivial($"Something went wrong creating the placeholder barrier. Mouse position: {UserInput.GetMousePositionForBarrier}"); + Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~Something went wrong creating the placeholder barrier. This is a rare problem that only happens in certain areas of the world. Please try again somewhere else."); + return; + } + + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); + PlaceholderBarrier.IsGravityDisabled = true; + PlaceholderBarrier.IsCollisionEnabled = false; + PlaceholderBarrier.Opacity = 0.7f; + + // Start with lights off for Parks's objects + if (Settings.EnableAdvancedBarricadeOptions) + { + Rage.Native.NativeFunction.Natives.x971DA0055324D033(PlaceholderBarrier, BarrierMenu.BarrierTexture.Value); + SetBarrierLights(); + } + } + + internal static void SetBarrierLights() + { + if (BarrierMenu.SetBarrierLights.Checked) + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(PlaceholderBarrier, false); + } + else + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(PlaceholderBarrier, true); + } + + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); + } + + internal static void UpdatePlaceholderBarrierPosition() + { + DisableBarrierMenuOptionsIfShadowConeTooFar(); + if (PlaceholderBarrier) + { + PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; + PlaceholderBarrier.Position = UserInput.GetMousePositionForBarrier; + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); + } + + void DisableBarrierMenuOptionsIfShadowConeTooFar() + { + if (!PlaceholderBarrier && UserInput.GetMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) + { + CreatePlaceholderBarrier(); + + } + else if (PlaceholderBarrier && PlaceholderBarrier.Position.DistanceTo2D(Game.LocalPlayer.Character.Position) > Settings.BarrierPlacementDistance) + { + BarrierMenu.BarrierList.Enabled = false; + BarrierMenu.RotateBarrier.Enabled = false; + PlaceholderBarrier.Delete(); + } + else if (PlaceholderBarrier && PlaceholderBarrier.Position.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance && BarrierMenu.BarrierList.SelectedItem == "Flare") + { + BarrierMenu.BarrierList.Enabled = true; + BarrierMenu.RotateBarrier.Enabled = false; + } + else + { + BarrierMenu.BarrierList.Enabled = true; + BarrierMenu.RotateBarrier.Enabled = true; + } + } + } + + internal static void LoopToRenderPlaceholderBarrier() + { + while (BarrierMenu.Menu.Visible) + { + if (BarrierMenu.BarrierList.Selected || BarrierMenu.RotateBarrier.Selected || BarrierMenu.Invincible.Selected || BarrierMenu.Immobile.Selected || BarrierMenu.BarrierTexture.Selected || BarrierMenu.SetBarrierLights.Selected || BarrierMenu.SetBarrierTrafficLight.Selected) + { + if (PlaceholderBarrier) + { + //UpdatePlaceholderBarrierPosition(); + UpdatePlaceholderBarrierPosition(); + } + else if (UserInput.GetMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) + { + //CreatePlaceholderBarrier(); + CreatePlaceholderBarrier(); + } + } + else + { + if (PlaceholderBarrier) + { + PlaceholderBarrier.Delete(); + } + } + GameFiber.Yield(); + } + + if (PlaceholderBarrier) + { + PlaceholderBarrier.Delete(); + } + } + + internal static void SpawnBarrier() + { + if (BarrierMenu.BarrierList.SelectedItem == "Flare") + { + SpawnFlare(); + } + else + { + var barrier = new Rage.Object(PlaceholderBarrier.Model, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value); + barrier.SetPositionWithSnap(PlaceholderBarrier.Position); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(barrier, true); + if (BarrierMenu.Invincible.Checked) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(barrier, true); + if (barrier.Model.Name != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(barrier, true); + } + } + if (BarrierMenu.Immobile.Checked) + { + barrier.IsPositionFrozen = true; + } + else + { + + barrier.IsPositionFrozen = false; + } + if (Settings.EnableAdvancedBarricadeOptions) + { + Rage.Native.NativeFunction.Natives.x971DA0055324D033(barrier, BarrierMenu.BarrierTexture.Value); + if (BarrierMenu.SetBarrierLights.Checked) + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, false); + } + else + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, true); + } + + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); + barrier.IsPositionFrozen = true; + GameFiber.Sleep(50); + if (barrier && !BarrierMenu.Immobile.Checked) + { + barrier.IsPositionFrozen = false; + } + } + Barriers.Add(new Barrier(barrier, barrier.Position, barrier.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked)); + + BarrierMenu.RemoveBarrierOptions.Enabled = true; + BarrierMenu.ResetBarriers.Enabled = true; + } + + void SpawnFlare() + { + var flare = new Weapon("weapon_flare", PlaceholderBarrier.Position, 1); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true); + GameFiber.Sleep(1); + GameFiber.StartNew(() => + { + while (flare && flare.HeightAboveGround > 0.05f) + { + GameFiber.Yield(); + } + GameFiber.Sleep(1000); + if (flare) + { + flare.IsPositionFrozen = true; + } + }, "Spawn Flare Fiber"); + + Barriers.Add(new Barrier(flare, flare.Position, flare.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked)); + BarrierMenu.RemoveBarrierOptions.Enabled = true; + } + } + + internal static void RemoveBarrier(int removeBarrierOptionsIndex) + { + switch (removeBarrierOptionsIndex) + { + case 0: + Barriers[Barriers.Count - 1].Object.Delete(); + Barriers.RemoveAt(Barriers.Count - 1); + break; + case 1: + var nearestBarrier = Barriers.OrderBy(b => b.Object.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); + if (nearestBarrier != null) + { + nearestBarrier.Object.Delete(); + Barriers.Remove(nearestBarrier); + } + break; + case 2: + foreach (Barrier b in Barriers.Where(b => b.Object)) + { + b.Object.Delete(); + } + if (Barriers.Count > 0) + { + Barriers.Clear(); + } + break; + } + + BarrierMenu.RemoveBarrierOptions.Enabled = Barriers.Count == 0 ? false : true; + BarrierMenu.ResetBarriers.Enabled = Barriers.Count == 0 ? false : true; + } + + internal static void ResetBarriers() + { + GameFiber.StartNew(() => + { + var currentBarriers = Barriers.Where(b => b.Model.Name != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash + foreach (Barrier barrier in currentBarriers) + { + var newBarrier = new Rage.Object(barrier.Model, barrier.Position, barrier.Rotation); + newBarrier.SetPositionWithSnap(barrier.Position); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(newBarrier, true); + newBarrier.IsPositionFrozen = barrier.Immobile; + if (barrier.Invincible) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(newBarrier, true); + if (newBarrier.Model.Name != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(newBarrier, true); + } + } + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(newBarrier, setBarrierTrafficLight.Index); + newBarrier.IsPositionFrozen = true; + GameFiber.Sleep(50); + if (newBarrier && !barrier.Immobile) + { + newBarrier.IsPositionFrozen = false; + } + Barriers.Add(new Barrier(newBarrier, newBarrier.Position, newBarrier.Heading, barrier.Invincible, barrier.Immobile)); + + if (barrier.Object) + { + barrier.Object.Delete(); + } + Barriers.Remove(barrier); + } + currentBarriers.Clear(); + }, "Barrier Reset Fiber"); + + } + + internal static void RotateBarrier() + { + PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; + PlaceholderBarrier.Position = UserInput.GetMousePositionForBarrier; + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); + } + } +} diff --git a/SceneManager/Utils/DeleteAllPaths.cs b/SceneManager/Utils/DeleteAllPaths.cs new file mode 100644 index 0000000..9835960 --- /dev/null +++ b/SceneManager/Utils/DeleteAllPaths.cs @@ -0,0 +1,15 @@ +using Rage; + +namespace SceneManager.Utils +{ + internal static class DeleteAllPaths + { + internal static void Delete() + { + PathManager.Paths.ForEach(x => x.Delete()); + PathManager.Paths.Clear(); + Game.LogTrivial($"All paths deleted"); + Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); + } + } +} diff --git a/SceneManager/Utils/DependencyChecker.cs b/SceneManager/Utils/DependencyChecker.cs new file mode 100644 index 0000000..7fffd9e --- /dev/null +++ b/SceneManager/Utils/DependencyChecker.cs @@ -0,0 +1,63 @@ +using Rage; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SceneManager.Utils +{ + internal class DependencyChecker + { + internal static bool DependenciesInstalled() + { + if (!InputManagerChecker() || !CheckRNUIVersion()) + { + return false; + } + + return true; + } + + private static bool CheckRNUIVersion() + { + var directory = Directory.GetCurrentDirectory(); + var exists = File.Exists(directory + @"\RAGENativeUI.dll"); + if (!exists) + { + Game.LogTrivial($"RNUI was not found in the user's GTA V directory."); + Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~RAGENativeUI.dll was not found in your GTA V directory. Please install RAGENativeUI and try again."); + return false; + } + + var userVersion = Assembly.LoadFrom(directory + @"\RAGENativeUI.dll").GetName().Version; + Version requiredMinimumVersion = new Version("1.7.0.0"); + if (userVersion >= requiredMinimumVersion) + { + Game.LogTrivial($"User's RNUI version: {userVersion}"); + return true; + } + else + { + Game.DisplayNotification($"~o~Scene Manager~r~[Error]\n~w~Your RAGENativeUI.dll version is below 1.7. Please update RAGENativeUI and try again."); + return false; + } + + } + + private static bool InputManagerChecker() + { + var directory = Directory.GetCurrentDirectory(); + var exists = File.Exists(directory + @"\InputManager.dll"); + if (!exists) + { + Game.LogTrivial($"InputManager was not found in the user's GTA V directory."); + Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~InputManager.dll was not found in your GTA V directory. Please install InputManager.dll and try again."); + return false; + } + return true; + } + } +} diff --git a/SceneManager/Utils/DirectDriver.cs b/SceneManager/Utils/DirectDriver.cs new file mode 100644 index 0000000..b01824b --- /dev/null +++ b/SceneManager/Utils/DirectDriver.cs @@ -0,0 +1,77 @@ +using Rage; +using RAGENativeUI.Elements; +using SceneManager.Objects; +using System.Linq; + +namespace SceneManager.Utils +{ + // The only reason this class should change is to modify how vehicles are directed to paths. + internal static class DirectDriver + { + internal static bool ValidateOptions(UIMenuListScrollerItem menuItem, Path path, out Vehicle vehicle, out Waypoint waypoint) + { + var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).FirstOrDefault(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()); + vehicle = nearbyVehicle; + waypoint = null; + if (!nearbyVehicle) + { + Game.LogTrivial($"Nearby vehicle is null."); + return false; + } + + var firstWaypoint = path.Waypoints.First(); + if (menuItem.SelectedItem == "First waypoint" && firstWaypoint == null) + { + Game.LogTrivial($"First waypoint is null."); + return false; + } + else if(menuItem.SelectedItem == "First waypoint" && firstWaypoint != null) + { + waypoint = firstWaypoint; + return true; + } + + var nearestWaypoint = path.Waypoints.Where(wp => wp.Position.DistanceTo2D(nearbyVehicle.FrontPosition) < wp.Position.DistanceTo2D(nearbyVehicle.RearPosition)).OrderBy(wp => wp.Position.DistanceTo2D(nearbyVehicle)).FirstOrDefault(); + if (menuItem.SelectedItem == "Nearest waypoint" && nearestWaypoint == null) + { + Game.LogTrivial($"Nearest waypoint is null."); + return false; + } + else if (menuItem.SelectedItem == "Nearest waypoint" && nearestWaypoint != null) + { + waypoint = nearestWaypoint; + return true; + } + + Game.LogTrivial($"What are we doing here?"); + return false; + } + + internal static void Direct(Vehicle nearbyVehicle, Path path, Waypoint targetWaypoint) + { + var nearbyVehiclesPath = PathManager.Paths.FirstOrDefault(p => p.CollectedVehicles.Any(v => v.Vehicle == 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); + if (collectedVehicleOnThisPath == null) + { + Game.LogTrivial($"Nearby vehicle does not belong to this path."); + if (nearbyCollectedVehicleOtherPath != null) + { + Game.LogTrivial($"Dismissing nearby vehicle from other path."); + 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(); + } + + GameFiber.StartNew(() => collectedVehicleOnThisPath.AssignWaypointTasks(path, targetWaypoint)); + } + } +} diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs new file mode 100644 index 0000000..32ad386 --- /dev/null +++ b/SceneManager/Utils/DismissDriver.cs @@ -0,0 +1,43 @@ +using Rage; +using SceneManager.Objects; +using System.Linq; + +namespace SceneManager.Utils +{ + internal static class DismissDriver + { + internal static void Dismiss(int dismissIndex) + { + var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).FirstOrDefault(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()); + if (!nearbyVehicle) + { + Game.LogTrivial($"Nearby vehicle is null."); + return; + } + + if(dismissIndex == (int)Utils.Dismiss.FromWorld) + { + // Have to loop because sometimes police peds don't get deleted properly + // The path should handle removing the deleted driver/vehicle from its list of collected vehicles + while (nearbyVehicle && nearbyVehicle.HasOccupants) + { + nearbyVehicle.Occupants.ToList().ForEach(x => x.Delete()); + GameFiber.Yield(); + } + if (nearbyVehicle) + { + nearbyVehicle.Delete(); + } + return; + } + else + { + CollectedVehicle collectedVehicle = PathManager.Paths.SelectMany(x => x.CollectedVehicles).FirstOrDefault(x => x.Vehicle == nearbyVehicle); + if(collectedVehicle != null) + { + collectedVehicle.Dismiss((Dismiss)dismissIndex); + } + } + } + } +} diff --git a/SceneManager/Utils/Hints.cs b/SceneManager/Utils/Hints.cs new file mode 100644 index 0000000..8405dbb --- /dev/null +++ b/SceneManager/Utils/Hints.cs @@ -0,0 +1,39 @@ +using Rage; +using System.Windows.Forms; +using SceneManager.Menus; + +namespace SceneManager +{ + class Hints + { + internal static bool Enabled { get; set; } = SettingsMenu.Hints.Checked; + + internal static void Display(string message) + { + if (Enabled) + { + Game.DisplayNotification($"{message}"); + } + } + + internal static void DisplayHintsToOpenMenu() + { + if (Settings.ModifierKey == Keys.None && Settings.ModifierButton == ControllerButtons.None) + { + Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ToggleKey} key ~w~or ~b~{Settings.ToggleButton} button"); + } + else if (Settings.ModifierKey == Keys.None) + { + Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ToggleKey} key ~w~or ~b~{Settings.ModifierButton} ~w~+ ~b~{Settings.ToggleButton} buttons"); + } + else if (Settings.ModifierButton == ControllerButtons.None) + { + Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press ~b~{Settings.ModifierKey} ~w~+ ~b~{Settings.ToggleKey} ~w~or the ~b~{Settings.ToggleButton} button"); + } + else + { + Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ModifierKey} ~w~+ ~b~{Settings.ToggleKey} keys ~w~or ~b~{Settings.ModifierButton} ~w~+ ~b~{Settings.ToggleButton} buttons"); + } + } + } +} diff --git a/SceneManager/Utils/PathManager.cs b/SceneManager/Utils/PathManager.cs new file mode 100644 index 0000000..7d27fe6 --- /dev/null +++ b/SceneManager/Utils/PathManager.cs @@ -0,0 +1,258 @@ +using Rage; +using RAGENativeUI.Elements; +using SceneManager.Menus; +using SceneManager.Objects; +using System.Collections.Generic; +using System.Linq; + +namespace SceneManager.Utils +{ + internal class PathManager + { + internal static List Paths { get; } = new List(10); + + internal static Path ImportPath(Path importedPath) + { + importedPath.State = State.Creating; + + var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State != State.Creating)) + 1; + if (firstVacantIndex < 0) + { + firstVacantIndex = 0; + } + var pathNumber = firstVacantIndex + 1; + + importedPath.Number = pathNumber; + Paths.Insert(firstVacantIndex, importedPath); + + Game.LogTrivial($"Importing path {importedPath.Number} at Paths index {firstVacantIndex}"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Path {importedPath.Number} import started."); + + return importedPath; + } + + internal static void ExportPath() + { + var currentPath = Paths[PathMainMenu.EditPath.Index]; + // Reference PNWParks's UserInput class from LiveLights + var filename = UserInput.GetFileName("Type the name you would like to save your file as", "Enter a filename", 100) + ".xml"; + + // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) + if (string.IsNullOrWhiteSpace(filename)) + { + Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + return; + } + Game.LogTrivial($"Filename: {filename}"); + currentPath.Save(filename); + currentPath.Name = filename.Remove(filename.Length - 4); + Game.LogTrivial($"Path name: {currentPath.Name}"); + Game.LogTrivial($"Exporting path {currentPath.Number}"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Exporting]\n~w~Path {currentPath.Number} exported."); + Settings.ImportPaths(); + PathMainMenu.ImportPath.Enabled = true; + ImportPathMenu.BuildImportMenu(); + } + + internal static Path InitializeNewPath() + { + PathCreationMenu.PathCreationState = State.Creating; + + var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State != State.Creating)) + 1; + if(firstVacantIndex < 0) + { + firstVacantIndex = 0; + } + var pathNumber = firstVacantIndex + 1; + + Path newPath = new Path(pathNumber, State.Creating); + Paths.Insert(firstVacantIndex, newPath); + + Game.LogTrivial($"Creating path {newPath.Number} at Paths index {firstVacantIndex}"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Creating]\n~w~Path {newPath.Number} started."); + + PathCreationMenu.RemoveLastWaypoint.Enabled = false; + PathCreationMenu.EndPathCreation.Enabled = false; + + return newPath; + } + + internal static void AddWaypoint(Path currentPath) + { + var waypointNumber = currentPath.Waypoints.Count + 1; + DrivingFlagType drivingFlag = PathCreationMenu.DirectWaypoint.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + Waypoint newWaypoint; + if (PathCreationMenu.CollectorWaypoint.Checked) + { + newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, PathCreationMenu.StopWaypoint.Checked, true, PathCreationMenu.CollectorRadius.Value, PathCreationMenu.SpeedZoneRadius.Value); + } + else + { + newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, PathCreationMenu.StopWaypoint.Checked); + } + currentPath.Waypoints.Add(newWaypoint); + Game.LogTrivial($"Path {currentPath.Number} Waypoint {waypointNumber} added [Driving style: {drivingFlag} | Stop waypoint: {newWaypoint.IsStopWaypoint} | Speed: {newWaypoint.Speed} | Collector: {newWaypoint.IsCollector}]"); + + if(currentPath.Waypoints.Count == 1) + { + PathMainMenu.CreateNewPath.Text = $"Continue Creating Path {currentPath.Number}"; + } + } + + internal static void AddNewEditWaypoint(Path currentPath) + { + DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + + if (EditWaypointMenu.CollectorWaypoint.Checked) + { + currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, EditWaypointMenu.StopWaypointType.Checked, true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value)); + } + else + { + currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, EditWaypointMenu.StopWaypointType.Checked)); + } + Game.LogTrivial($"New waypoint (#{currentPath.Waypoints.Last().Number}) added."); + } + + internal static void UpdateWaypoint() + { + var currentPath = Paths[PathMainMenu.EditPath.Index]; + var currentWaypoint = currentPath.Waypoints[EditWaypointMenu.EditWaypoint.Index]; + DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + + if (currentPath.Waypoints.Count == 1) + { + currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + } + else + { + currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), EditWaypointMenu.CollectorWaypoint.Checked, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + } + Game.LogTrivial($"Path {currentPath.Number} Waypoint {currentWaypoint.Number} updated [Driving style: {drivingFlag} | Stop waypoint: {EditWaypointMenu.StopWaypointType.Checked} | Speed: {EditWaypointMenu.ChangeWaypointSpeed.Value} | Collector: {currentWaypoint.IsCollector}]"); + + EditWaypointMenu.UpdateWaypointPosition.Checked = false; + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]~w~\nWaypoint {currentWaypoint.Number} updated."); + } + + private static float SetDriveSpeedForWaypoint() + { + float convertedSpeed; + if (SettingsMenu.SpeedUnits.SelectedItem == SpeedUnits.MPH) + { + //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); + convertedSpeed = MathHelper.ConvertMilesPerHourToMetersPerSecond(PathCreationMenu.WaypointSpeed.Value); + //Logger.Log($"Converted speed: {convertedSpeed}m/s"); + } + else + { + //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); + convertedSpeed = MathHelper.ConvertKilometersPerHourToMetersPerSecond(PathCreationMenu.WaypointSpeed.Value); + //Logger.Log($"Converted speed: {convertedSpeed}m/s"); + } + + return convertedSpeed; + } + + internal static void RemoveWaypoint(Path currentPath) + { + Waypoint lastWaypoint = currentPath.Waypoints.Last(); + lastWaypoint.Delete(); + currentPath.Waypoints.Remove(lastWaypoint); + } + + internal static void RemoveEditWaypoint(Path currentPath) + { + var currentWaypoint = currentPath.Waypoints[EditWaypointMenu.EditWaypoint.Index]; + if (currentPath.Waypoints.Count == 1) + { + Game.LogTrivial($"Deleting the last waypoint from the path."); + currentPath.Delete(); + Paths.Remove(currentPath); + PathMainMenu.BuildPathMenu(); + + EditWaypointMenu.Menu.Visible = false; + PathMainMenu.Menu.Visible = true; + return; + } + + currentWaypoint.Delete(); + currentPath.Waypoints.Remove(currentWaypoint); + Game.LogTrivial($"[Path {currentPath.Number}] Waypoint {currentWaypoint.Number} ({currentWaypoint.DrivingFlagType}) removed"); + currentPath.Waypoints.ForEach(x => x.Number = currentPath.Waypoints.IndexOf(x) + 1); + + DefaultWaypointToCollector(currentPath); + } + + private static void DefaultWaypointToCollector(Path currentPath) + { + if (currentPath.Waypoints.Count == 1) + { + DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + Hints.Display($"~o~Scene Manager ~y~[Hint]~w~\nYour path's first waypoint ~b~must~w~ be a collector. If it's not, it will automatically be made into one."); + Game.LogTrivial($"The path only has 1 waypoint left, this waypoint must be a collector."); + currentPath.Waypoints[0].UpdateWaypoint(currentPath.Waypoints.First(), UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + EditWaypointMenu.CollectorWaypoint.Checked = true; + EditWaypointMenu.ChangeCollectorRadius.Enabled = true; + EditWaypointMenu.ChangeSpeedZoneRadius.Enabled = true; + } + } + + internal static void EndPath(Path currentPath) + { + Game.LogTrivial($"[Path Creation] Path {currentPath.Number} finished with {currentPath.Waypoints.Count} waypoints."); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path {currentPath.Number} complete."); + currentPath.State = State.Finished; + currentPath.IsEnabled = true; + currentPath.Waypoints.ForEach(x => x.EnableBlip()); + GameFiber.StartNew(() => currentPath.LoopForVehiclesToBeDismissed(), "Vehicle Cleanup Loop Fiber"); + GameFiber.StartNew(() => currentPath.LoopWaypointCollection(), "Waypoint Collection Loop Fiber"); + + PathMainMenu.CreateNewPath.Text = "Create New Path"; + PathMainMenu.BuildPathMenu(); + PathMainMenu.Menu.Visible = true; + } + + internal static void TogglePathCreationMenuItems(Path currentPath) + { + if(currentPath.Waypoints.Count == 1) + { + PathCreationMenu.CollectorWaypoint.Enabled = true; + PathCreationMenu.CollectorWaypoint.Checked = false; + PathCreationMenu.RemoveLastWaypoint.Enabled = true; + PathCreationMenu.EndPathCreation.Enabled = true; + } + + if (currentPath.Waypoints.Count < 1) + { + PathCreationMenu.CollectorWaypoint.Enabled = false; + PathCreationMenu.CollectorWaypoint.Checked = true; + PathCreationMenu.RemoveLastWaypoint.Enabled = false; + PathCreationMenu.EndPathCreation.Enabled = false; + } + + if (PathCreationMenu.CollectorWaypoint.Checked) + { + PathCreationMenu.CollectorRadius.Enabled = true; + PathCreationMenu.SpeedZoneRadius.Enabled = true; + } + else + { + PathCreationMenu.CollectorRadius.Enabled = false; + PathCreationMenu.SpeedZoneRadius.Enabled = false; + } + } + + internal static void ToggleBlips(bool enabled) + { + if (enabled) + { + Paths.SelectMany(x => x.Waypoints).ToList().ForEach(x => x.EnableBlip()); + } + else + { + Paths.SelectMany(x => x.Waypoints).ToList().ForEach(x => x.DisableBlip()); + } + } + } +} diff --git a/SceneManager/Utils/TogglePaths.cs b/SceneManager/Utils/TogglePaths.cs new file mode 100644 index 0000000..f94f4d5 --- /dev/null +++ b/SceneManager/Utils/TogglePaths.cs @@ -0,0 +1,21 @@ +using Rage; + +namespace SceneManager.Utils +{ + internal static class TogglePaths + { + internal static void Toggle(bool disable) + { + if (disable) + { + PathManager.Paths.ForEach(x => x.DisablePath()); + Game.LogTrivial($"All paths disabled."); + } + else + { + PathManager.Paths.ForEach(x => x.EnablePath()); + Game.LogTrivial($"All paths enabled."); + } + } + } +} diff --git a/SceneManager/Utils/UserInput.cs b/SceneManager/Utils/UserInput.cs new file mode 100644 index 0000000..529e97f --- /dev/null +++ b/SceneManager/Utils/UserInput.cs @@ -0,0 +1,229 @@ +using InputManager; +using Rage; +using Rage.Native; +using RAGENativeUI; +using RAGENativeUI.Elements; +using SceneManager.Menus; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace SceneManager.Utils +{ + // The only reason this class should change is to modify how user input is handled + class UserInput + { + internal static void HandleKeyPress() + { + while (true) + { + bool isTextEntryOpen = (Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0); + if (!isTextEntryOpen && MenuKeysPressed()) + { + Menus.MainMenu.DisplayMenu(); + GameFiber.StartNew(() => MenuManager.Update(), "Menu Processing Fiber"); + } + +#if DEBUG + if (MenuManager.MenuPool.IsAnyMenuOpen()) + { + Game.DisplaySubtitle($"You are using a test build of Scene Manager. Please report any bugs/crashes in the Discord server."); + } +#endif + GameFiber.Yield(); + } + } + + private static bool MenuKeysPressed() + { + if (MenuKeysPressed()) + { + return true; + } + + return false; + + bool MenuKeysPressed() + { + if (MenuManager.AreMenusClosed() && + ((Settings.ModifierKey == Keys.None && Game.IsKeyDown(Settings.ToggleKey)) || + (Game.IsKeyDownRightNow(Settings.ModifierKey) && Game.IsKeyDown(Settings.ToggleKey)) || + (Settings.ModifierButton == ControllerButtons.None && Game.IsControllerButtonDown(Settings.ToggleButton)) || + (Game.IsControllerButtonDownRightNow(Settings.ModifierButton) && Game.IsControllerButtonDown(Settings.ToggleButton)))) + { + return true; + } + + return false; + } + } + + internal static Vector3 GetMousePosition { get { return GetMousePositionInWorld(); } } + + internal static Vector3 GetMousePositionForBarrier { get { return GetMousePositionInWorld(Settings.BarrierPlacementDistance); } } + + private static Vector3 GetMousePositionInWorld(float maxDistance = 100f) + { + HitResult TracePlayerView(float maxTraceDistance = 100f, TraceFlags flags = TraceFlags.IntersectWorld) => TracePlayerView2(out Vector3 v1, out Vector3 v2, maxTraceDistance, flags); + + HitResult TracePlayerView2(out Vector3 start, out Vector3 end, float maxTraceDistance, TraceFlags flags) + { + Vector3 direction = GetPlayerLookingDirection(out start); + end = start + (maxTraceDistance * direction); + return World.TraceLine(start, end, flags); + } + + Vector3 GetPlayerLookingDirection(out Vector3 camPosition) + { + if (Camera.RenderingCamera) + { + camPosition = Camera.RenderingCamera.Position; + return Camera.RenderingCamera.Direction; + } + else + { + float pitch = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_PITCH(); + float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING(); + + camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD(); + return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized(); + } + } + + return TracePlayerView(maxDistance, TraceFlags.IntersectWorld).HitPosition; + } + + internal static void InitializeMenuMouseControl(UIMenu menu, List scrollerItems) + { + while (menu.Visible) + { + var selectedScroller = menu.MenuItems.Where(x => scrollerItems.Contains(x) && x.Selected && x.Enabled).FirstOrDefault(); + if (selectedScroller != null) + { + OnWheelScroll(menu, selectedScroller, scrollerItems); + } + + if (Game.IsKeyDown(Keys.LButton) && Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() != 0) + { + Keyboard.KeyDown(Keys.Enter); + GameFiber.Wait(1); + Keyboard.KeyUp(Keys.Enter); + } + + if (menu.SubtitleText.Contains("Path Creation Menu")) + { + DrawWaypointMarker(); + } + GameFiber.Yield(); + } + } + + private static void OnWheelScroll(UIMenu menu, UIMenuItem selectedScroller, List scrollerItems) + { + var menuScrollingDisabled = false; + var menuItems = menu.MenuItems.Where(x => x != selectedScroller); + + while (Game.IsShiftKeyDownRightNow) + { + menu.ResetKey(Common.MenuControls.Up); + menu.ResetKey(Common.MenuControls.Down); + menuScrollingDisabled = true; + ScrollMenuItem(); + if (menu.SubtitleText.Contains("Path Creation Menu") || menu.SubtitleText.Contains("Edit Waypoint")) + { + CompareScrollerValues(); + } + if (menu.SubtitleText.Contains("Path Creation Menu")) + { + DrawWaypointMarker(); + } + GameFiber.Yield(); + } + + if (menuScrollingDisabled) + { + menuScrollingDisabled = false; + menu.SetKey(Common.MenuControls.Up, GameControl.CursorScrollUp); + menu.SetKey(Common.MenuControls.Up, GameControl.CellphoneUp); + menu.SetKey(Common.MenuControls.Down, GameControl.CursorScrollDown); + menu.SetKey(Common.MenuControls.Down, GameControl.CellphoneDown); + } + + void ScrollMenuItem() + { + if (Game.GetMouseWheelDelta() > 0) + { + Keyboard.KeyDown(Keys.Right); + GameFiber.Wait(1); + Keyboard.KeyUp(Keys.Right); + } + else if (Game.GetMouseWheelDelta() < 0) + { + Keyboard.KeyDown(Keys.Left); + GameFiber.Wait(1); + Keyboard.KeyUp(Keys.Left); + } + } + + void CompareScrollerValues() + { + var collectorRadius = (UIMenuNumericScrollerItem)scrollerItems.Where(x => x.Text == "Collection Radius").FirstOrDefault(); + var speedZoneRadius = (UIMenuNumericScrollerItem)scrollerItems.Where(x => x.Text == "Speed Zone Radius").FirstOrDefault(); + + if (selectedScroller.Text == "Collection Radius" || selectedScroller.Text == "Speed Zone Radius") + { + if (selectedScroller == collectorRadius && collectorRadius.Value > speedZoneRadius.Value) + { + while (collectorRadius.Value > speedZoneRadius.Value) + { + speedZoneRadius.ScrollToNextOption(); + } + } + if (selectedScroller == speedZoneRadius && speedZoneRadius.Value < collectorRadius.Value) + { + collectorRadius.Value = speedZoneRadius.Value; + } + } + } + } + + private static void DrawWaypointMarker() + { + var waypointPosition = GetMousePosition; + if (SettingsMenu.ThreeDWaypoints.Checked && PathCreationMenu.CollectorWaypoint.Checked) + { + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.CollectorRadius.Value * 2, (float)PathCreationMenu.CollectorRadius.Value * 2, 1f, 80, 130, 255, 80, false, false, 2, false, 0, 0, false); + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, 1f, 255, 185, 80, 80, false, false, 2, false, 0, 0, false); + } + else if (PathCreationMenu.StopWaypoint.Checked) + { + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 255, 65, 65, 80, false, false, 2, false, 0, 0, false); + } + else + { + Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false); + } + } + + internal static string GetFileName(string windowTitle, string defaultText, int maxLength) + { + NativeFunction.Natives.DISABLE_ALL_CONTROL_ACTIONS(2); + + NativeFunction.Natives.DISPLAY_ONSCREEN_KEYBOARD(true, windowTitle, 0, defaultText, 0, 0, 0, maxLength); + Game.DisplayHelp("Enter the filename you would like to save your path as\n~INPUT_FRONTEND_ACCEPT~ Export path\n~INPUT_FRONTEND_CANCEL~ Cancel", true); + Game.DisplaySubtitle(windowTitle, 100000); + + while (NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0) + { + GameFiber.Yield(); + } + + NativeFunction.Natives.ENABLE_ALL_CONTROL_ACTIONS(2); + Game.DisplaySubtitle("", 5); + Game.HideHelp(); + + return NativeFunction.Natives.GET_ONSCREEN_KEYBOARD_RESULT(); + } + + } +} From 1c46d4418f33977bebc9213c2469f8dc5f522f19 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:38:30 -0700 Subject: [PATCH 009/112] Deleted --- SceneManager/Hints.cs | 17 --- SceneManager/Utils/GetUserInput.cs | 75 ----------- SceneManager/Utils/MousePositionInWorld.cs | 42 ------- SceneManager/Utils/PNWUserInput.cs | 28 ----- SceneManager/Utils/RNUIMouseInputHandler.cs | 131 -------------------- 5 files changed, 293 deletions(-) delete mode 100644 SceneManager/Hints.cs delete mode 100644 SceneManager/Utils/GetUserInput.cs delete mode 100644 SceneManager/Utils/MousePositionInWorld.cs delete mode 100644 SceneManager/Utils/PNWUserInput.cs delete mode 100644 SceneManager/Utils/RNUIMouseInputHandler.cs diff --git a/SceneManager/Hints.cs b/SceneManager/Hints.cs deleted file mode 100644 index 6a52d42..0000000 --- a/SceneManager/Hints.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Rage; - -namespace SceneManager -{ - class Hints - { - internal static bool Enabled { get; set; } = SettingsMenu.hints.Checked; - - internal static void Display(string message) - { - if (Enabled) - { - Game.DisplayNotification($"{message}"); - } - } - } -} diff --git a/SceneManager/Utils/GetUserInput.cs b/SceneManager/Utils/GetUserInput.cs deleted file mode 100644 index b1277f1..0000000 --- a/SceneManager/Utils/GetUserInput.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Rage; - -namespace SceneManager.Utils -{ - class GetUserInput - { - internal static void LoopForUserInput() - { - while (true) - { - bool isTextEntryOpen = (Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0); - if (!isTextEntryOpen) - { - GetKeyboardInput(); - GetControllerInput(); - } - else - { - Game.LogTrivial($"A text menu is open."); - } - -#if DEBUG - if (MenuManager.menuPool.IsAnyMenuOpen()) - { - Game.DisplaySubtitle($"You are using a test build of Scene Manager. Please report any bugs/crashes in the Discord server."); - } -#endif - MenuManager.menuPool.ProcessMenus(); - GameFiber.Yield(); - } - } - - private static void GetControllerInput() - { - if (Settings.ModifierButton == ControllerButtons.None) - { - if (Game.IsControllerButtonDown(Settings.ToggleButton) && AreMenusClosed()) - { - MainMenu.mainMenu.Visible = !MainMenu.mainMenu.Visible; - } - } - else if (Game.IsControllerButtonDownRightNow(Settings.ModifierButton) && Game.IsControllerButtonDown(Settings.ToggleButton) && AreMenusClosed()) - { - MainMenu.mainMenu.Visible = !MainMenu.mainMenu.Visible; - } - } - - private static void GetKeyboardInput() - { - if (Settings.ModifierKey == System.Windows.Forms.Keys.None) - { - if (Game.IsKeyDown(Settings.ToggleKey) && AreMenusClosed()) - { - MainMenu.mainMenu.Visible = !MainMenu.mainMenu.Visible; - } - } - else if (Game.IsKeyDownRightNow(Settings.ModifierKey) && Game.IsKeyDown(Settings.ToggleKey) && AreMenusClosed()) - { - MainMenu.mainMenu.Visible = !MainMenu.mainMenu.Visible; - } - } - - private static bool AreMenusClosed() - { - if(!BarrierMenu.barrierMenu.Visible && !PathMainMenu.pathMainMenu.Visible && !PathCreationMenu.pathCreationMenu.Visible && !EditPathMenu.editPathMenu.Visible && !EditWaypointMenu.editWaypointMenu.Visible && !SettingsMenu.settingsMenu.Visible) - { - return true; - } - else - { - return false; - } - } - } -} diff --git a/SceneManager/Utils/MousePositionInWorld.cs b/SceneManager/Utils/MousePositionInWorld.cs deleted file mode 100644 index 4f17043..0000000 --- a/SceneManager/Utils/MousePositionInWorld.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Rage; - -namespace SceneManager.Utils -{ - internal static class MousePositionInWorld - { - internal static Vector3 GetPosition { get { return GetMousePositionInWorld(); } } - - internal static Vector3 GetPositionForBarrier { get { return GetMousePositionInWorld(Settings.BarrierPlacementDistance); } } - - private static Vector3 GetMousePositionInWorld(float maxDistance = 100f) - { - HitResult TracePlayerView(float maxTraceDistance = 100f, TraceFlags flags = TraceFlags.IntersectWorld) => TracePlayerView2(out Vector3 v1, out Vector3 v2, maxTraceDistance, flags); - - HitResult TracePlayerView2(out Vector3 start, out Vector3 end, float maxTraceDistance, TraceFlags flags) - { - Vector3 direction = GetPlayerLookingDirection(out start); - end = start + (maxTraceDistance * direction); - return World.TraceLine(start, end, flags); - } - - Vector3 GetPlayerLookingDirection(out Vector3 camPosition) - { - if (Camera.RenderingCamera) - { - camPosition = Camera.RenderingCamera.Position; - return Camera.RenderingCamera.Direction; - } - else - { - float pitch = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_PITCH(); - float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING(); - - camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD(); - return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized(); - } - } - - return TracePlayerView(maxDistance, TraceFlags.IntersectWorld).HitPosition; - } - } -} diff --git a/SceneManager/Utils/PNWUserInput.cs b/SceneManager/Utils/PNWUserInput.cs deleted file mode 100644 index 78e20e0..0000000 --- a/SceneManager/Utils/PNWUserInput.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Rage; -using Rage.Native; - -namespace SceneManager.Utils -{ - internal static class PNWUserInput - { - public static string GetUserInput(string windowTitle, string defaultText, int maxLength) - { - NativeFunction.Natives.DISABLE_ALL_CONTROL_ACTIONS(2); - - NativeFunction.Natives.DISPLAY_ONSCREEN_KEYBOARD(true, windowTitle, 0, defaultText, 0, 0, 0, maxLength); - Game.DisplayHelp("Enter the filename you would like to save your path as\n~INPUT_FRONTEND_ACCEPT~ Export path\n~INPUT_FRONTEND_CANCEL~ Cancel", true); - Game.DisplaySubtitle(windowTitle, 100000); - - while (NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0) - { - GameFiber.Yield(); - } - - NativeFunction.Natives.ENABLE_ALL_CONTROL_ACTIONS(2); - Game.DisplaySubtitle("", 5); - Game.HideHelp(); - - return NativeFunction.Natives.GET_ONSCREEN_KEYBOARD_RESULT(); - } - } -} \ No newline at end of file diff --git a/SceneManager/Utils/RNUIMouseInputHandler.cs b/SceneManager/Utils/RNUIMouseInputHandler.cs deleted file mode 100644 index 440f1f9..0000000 --- a/SceneManager/Utils/RNUIMouseInputHandler.cs +++ /dev/null @@ -1,131 +0,0 @@ -using InputManager; -using Rage; -using RAGENativeUI; -using RAGENativeUI.Elements; -using System.Collections.Generic; -using System.Linq; -using System.Windows.Forms; - - -namespace SceneManager.Utils -{ - internal class RNUIMouseInputHandler - { - internal delegate void Function(); - - internal static void Initialize(UIMenu menu, List scrollerItems) - { - GameFiber.StartNew(() => - { - while (menu.Visible) - { - var selectedScroller = menu.MenuItems.Where(x => scrollerItems.Contains(x) && x.Selected && x.Enabled).FirstOrDefault(); - if (selectedScroller != null) - { - OnWheelScroll(menu, selectedScroller, scrollerItems); - } - - if (Game.IsKeyDown(Keys.LButton) && Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() != 0) - { - Keyboard.KeyDown(Keys.Enter); - GameFiber.Wait(1); - Keyboard.KeyUp(Keys.Enter); - } - - if (menu.SubtitleText.Contains("Path Creation Menu")) - { - DrawWaypointMarker(); - } - GameFiber.Yield(); - } - }); - } - - internal static void OnWheelScroll(UIMenu menu, UIMenuItem selectedScroller, List scrollerItems) - { - var menuScrollingDisabled = false; - var menuItems = menu.MenuItems.Where(x => x != selectedScroller); - - while (Game.IsShiftKeyDownRightNow) - { - menu.ResetKey(Common.MenuControls.Up); - menu.ResetKey(Common.MenuControls.Down); - menuScrollingDisabled = true; - ScrollMenuItem(); - if (menu.SubtitleText.Contains("Path Creation Menu") || menu.SubtitleText.Contains("Edit Waypoint")) - { - CompareScrollerValues(); - } - if(menu.SubtitleText.Contains("Path Creation Menu")) - { - DrawWaypointMarker(); - } - GameFiber.Yield(); - } - - if (menuScrollingDisabled) - { - menuScrollingDisabled = false; - menu.SetKey(Common.MenuControls.Up, GameControl.CursorScrollUp); - menu.SetKey(Common.MenuControls.Up, GameControl.CellphoneUp); - menu.SetKey(Common.MenuControls.Down, GameControl.CursorScrollDown); - menu.SetKey(Common.MenuControls.Down, GameControl.CellphoneDown); - } - - void ScrollMenuItem() - { - if (Game.GetMouseWheelDelta() > 0) - { - Keyboard.KeyDown(Keys.Right); - GameFiber.Wait(1); - Keyboard.KeyUp(Keys.Right); - } - else if (Game.GetMouseWheelDelta() < 0) - { - Keyboard.KeyDown(Keys.Left); - GameFiber.Wait(1); - Keyboard.KeyUp(Keys.Left); - } - } - - void CompareScrollerValues() - { - var collectorRadius = (UIMenuNumericScrollerItem)scrollerItems.Where(x => x.Text == "Collection Radius").FirstOrDefault(); - var speedZoneRadius = (UIMenuNumericScrollerItem)scrollerItems.Where(x => x.Text == "Speed Zone Radius").FirstOrDefault(); - - if (selectedScroller.Text == "Collection Radius" || selectedScroller.Text == "Speed Zone Radius") - { - if (selectedScroller == collectorRadius && collectorRadius.Value > speedZoneRadius.Value) - { - while (collectorRadius.Value > speedZoneRadius.Value) - { - speedZoneRadius.ScrollToNextOption(); - } - } - if (selectedScroller == speedZoneRadius && speedZoneRadius.Value < collectorRadius.Value) - { - collectorRadius.Value = speedZoneRadius.Value; - } - } - } - } - - private static void DrawWaypointMarker() - { - var waypointPosition = MousePositionInWorld.GetPosition; - if (SettingsMenu.threeDWaypoints.Checked && PathCreationMenu.collectorWaypoint.Checked) - { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.collectorRadius.Value * 2, (float)PathCreationMenu.collectorRadius.Value * 2, 1f, 80, 130, 255, 80, false, false, 2, false, 0, 0, false); - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.speedZoneRadius.Value * 2, (float)PathCreationMenu.speedZoneRadius.Value * 2, 1f, 255, 185, 80, 80, false, false, 2, false, 0, 0, false); - } - else if (PathCreationMenu.stopWaypointType.Checked) - { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 255, 65, 65, 80, false, false, 2, false, 0, 0, false); - } - else - { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false); - } - } - } -} From 54c67efe2be2af5b2aaa27e978b95b77f8f561f3 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:39:30 -0700 Subject: [PATCH 010/112] Updated property reference due to refactor --- SceneManager/Utils/ConsoleCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index e812c52..2a8e988 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -13,7 +13,7 @@ namespace SceneManager.Utils [ConsoleCommand] internal static void Command_ShowCollectedVehicleInfo([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterVehicle), Name = "ShowCollectedVehicleInfo")] Vehicle vehicle) { - foreach(Path path in PathMainMenu.paths) + foreach(Path path in PathManager.Paths) { var collectedVehicle = path.CollectedVehicles.Where(v => v.Vehicle == vehicle).FirstOrDefault(); if(collectedVehicle != null) From 53f0e99b93f78005b6a1eec73a6ab6bcf13dbeb7 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:40:06 -0700 Subject: [PATCH 011/112] Renamed DissmissOption to Dismiss. DrivingFlagType is now a public enum for import/export --- SceneManager/Utils/Enums.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SceneManager/Utils/Enums.cs b/SceneManager/Utils/Enums.cs index 49faf18..d1399b6 100644 --- a/SceneManager/Utils/Enums.cs +++ b/SceneManager/Utils/Enums.cs @@ -455,13 +455,13 @@ KPH } - internal enum DrivingFlagType + public enum DrivingFlagType { Normal = 263075, Direct = 17040259 - } // Change this to Public for import/export? + } // Change this to Public for import/export - internal enum DismissOption + internal enum Dismiss { FromPath = 0, FromWaypoint = 1, From d6f5f8ebe3a42cfaf1626c38fb88cb266eb50082 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:40:18 -0700 Subject: [PATCH 012/112] Added extension VehicleAndDriverValid --- SceneManager/Utils/Extensions.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 2656499..9bb7861 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -96,5 +96,19 @@ namespace SceneManager.Utils Game.LogTrivial($"Nothing else has returned true by this point. (non-ambient)"); return false; } + + /// Determines if a vehicle and driver are valid. + /// + internal static bool VehicleAndDriverValid(this Vehicle vehicle) + { + if (vehicle && vehicle.HasDriver && vehicle.Driver && vehicle.Driver.IsAlive) + { + return true; + } + else + { + return false; + } + } } } From f494dd7a84d547ec3dbceae02b6ca5d9fad391b4 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:41:18 -0700 Subject: [PATCH 013/112] Modified param for new XmlSerializer. May need to modify later for barrier import/export --- SceneManager/Utils/PathXMLManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SceneManager/Utils/PathXMLManager.cs b/SceneManager/Utils/PathXMLManager.cs index 5f1b311..f6ac675 100644 --- a/SceneManager/Utils/PathXMLManager.cs +++ b/SceneManager/Utils/PathXMLManager.cs @@ -22,7 +22,8 @@ namespace SceneManager.Utils { Game.LogTrivialDebug("Adding " + typeof(T).Name + " to serializer cache"); Game.LogTrivialDebug("Overrides specified: " + (overrides != null)); - var s = new XmlSerializer(typeof(T), overrides); + var s = new XmlSerializer(typeof(T), new XmlRootAttribute("Path")); + //var s = new XmlSerializer(typeof(T), overrides); _serializerCache.Add(typeof(T), s); return s; } From b66a97fef836314ef9be3f3b65860e3a4878cd19 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:41:27 -0700 Subject: [PATCH 014/112] Initial commit --- SceneManager/SettingsValidator.cs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 SceneManager/SettingsValidator.cs diff --git a/SceneManager/SettingsValidator.cs b/SceneManager/SettingsValidator.cs new file mode 100644 index 0000000..d2cdd31 --- /dev/null +++ b/SceneManager/SettingsValidator.cs @@ -0,0 +1,54 @@ +using Rage; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SceneManager +{ + // The only reason this class should change is to modify how settings are validated + internal class SettingsValidator + { + internal static void ValidateWaypointSettings() + { + if (Settings.CollectorRadius > 50 || Settings.CollectorRadius < 1) + { + Settings.CollectorRadius = 1; + Game.LogTrivial($"Invalid value for CollectorRadius in user settings, resetting to default."); + } + if (Settings.SpeedZoneRadius > 200 || Settings.SpeedZoneRadius < 5) + { + Settings.SpeedZoneRadius = 5; + Game.LogTrivial($"Invalid value for SpeedZoneRadius in user settings, resetting to default."); + } + if (Settings.CollectorRadius > Settings.SpeedZoneRadius) + { + Settings.CollectorRadius = 1; + Settings.SpeedZoneRadius = 5; + Game.LogTrivial($"CollectorRadius is greater than SpeedZoneRadius in user settings, resetting to defaults."); + } + if (Settings.WaypointSpeed > 100 || Settings.WaypointSpeed < 5) + { + Settings.WaypointSpeed = 5; + Game.LogTrivial($"Invalid value for WaypointSpeed in user settings, resetting to default."); + } + } + + internal static void ValidateBarrierSettings(InitializationFile ini) + { + foreach (string displayName in ini.GetKeyNames("Barriers")) + { + var model = new Model(ini.ReadString("Barriers", displayName.Trim())); + if (model.IsValid) + { + Settings.Barriers.Add(displayName, model); + } + else + { + Game.LogTrivial($"{model.Name} is not valid."); + } + } + } + } +} From 6e2744a02c4c2cf5c323094632c2809b73d85da8 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:41:41 -0700 Subject: [PATCH 015/112] Big refactor --- SceneManager/Settings.cs | 132 +++++++++++++++------------------------ 1 file changed, 51 insertions(+), 81 deletions(-) diff --git a/SceneManager/Settings.cs b/SceneManager/Settings.cs index 915b472..2e998a2 100644 --- a/SceneManager/Settings.cs +++ b/SceneManager/Settings.cs @@ -6,36 +6,36 @@ using System.IO; namespace SceneManager { + // The only reason this class should change is to modify any plugin settings internal static class Settings { internal static readonly InitializationFile ini = new InitializationFile("Plugins/SceneManager.ini"); // Keybindings - internal static Keys ToggleKey = Keys.T; - internal static Keys ModifierKey = Keys.LShiftKey; - internal static ControllerButtons ToggleButton = ControllerButtons.Y; - internal static ControllerButtons ModifierButton = ControllerButtons.A; + internal static Keys ToggleKey { get; private set; } = Keys.T; + internal static Keys ModifierKey { get; private set; } = Keys.LShiftKey; + internal static ControllerButtons ToggleButton { get; private set; } = ControllerButtons.Y; + internal static ControllerButtons ModifierButton { get; private set; } = ControllerButtons.A; // Plugin Settings - internal static bool Enable3DWaypoints = true; - internal static bool EnableMapBlips = true; - internal static bool EnableHints = true; - internal static SpeedUnits SpeedUnit = SpeedUnits.MPH; - internal static float BarrierPlacementDistance = 30f; - internal static bool EnableAdvancedBarricadeOptions = false; - internal static bool EnableBarrierLightsDefaultOn = false; + internal static bool Enable3DWaypoints { get; private set; } = true; + internal static bool EnableMapBlips { get; private set; } = true; + internal static bool EnableHints { get; private set; } = true; + internal static SpeedUnits SpeedUnit { get; private set; } = SpeedUnits.MPH; + internal static float BarrierPlacementDistance { get; private set; } = 30f; + internal static bool EnableAdvancedBarricadeOptions { get; private set; } = false; + internal static bool EnableBarrierLightsDefaultOn { get; private set; } = false; // Default Waypoint Settings - internal static int CollectorRadius = 1; - internal static int SpeedZoneRadius = 5; - internal static bool StopWaypoint = false; - internal static bool DirectDrivingBehavior = false; - internal static int WaypointSpeed = 5; + internal static int CollectorRadius { get; set; } = 1; + internal static int SpeedZoneRadius { get; set; } = 5; + internal static bool StopWaypoint { get; set; } = false; + internal static bool DirectDrivingBehavior { get; set; } = false; + internal static int WaypointSpeed { get; set; } = 5; // Barriers - internal static Dictionary barriers = new Dictionary(); - //internal static List barrierKeys = new List(); - //internal static List barrierValues = new List(); + internal static Dictionary Barriers { get; private set; } = new Dictionary(); + internal static List ImportedPaths { get; private set; } = new List(); internal static void LoadSettings() { @@ -63,77 +63,47 @@ namespace SceneManager StopWaypoint = ini.ReadBoolean("Default Waypoint Settings", "StopWaypoint", false); DirectDrivingBehavior = ini.ReadBoolean("Default Waypoint Settings", "DirectDrivingBehavior", false); WaypointSpeed = ini.ReadInt32("Default Waypoint Settings", "WaypointSpeed", 5); - CheckForValidWaypointSettings(); - // Barriers - foreach(string displayName in ini.GetKeyNames("Barriers")) + SettingsValidator.ValidateWaypointSettings(); + SettingsValidator.ValidateBarrierSettings(ini); + ImportPaths(); + } + + // This will need to be moved to a different class + internal static void ImportPaths() + { + ImportedPaths.Clear(); + + // Check if Saved Paths directory exists + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; + if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) { - var model = new Model(ini.ReadString("Barriers", displayName.Trim())); - if (model.IsValid) - { - barriers.Add(displayName, model); - //barrierKeys.Add(key.Trim()); - //barrierValues.Add(model); - } - else - { - Game.LogTrivial($"{model.Name} is not valid."); - } + Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist. No paths available to import."); + return; } - //ImportPaths(); - - void CheckForValidWaypointSettings() + // Check if any XML files are available to import from Saved Paths + var savedPaths = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); + if (savedPaths.Length == 0) { - if(CollectorRadius > 50 || CollectorRadius < 1) - { - CollectorRadius = 1; - Game.LogTrivial($"Invalid value for CollectorRadius in user settings, resetting to default."); - } - if(SpeedZoneRadius > 200 || SpeedZoneRadius < 5) - { - SpeedZoneRadius = 5; - Game.LogTrivial($"Invalid value for SpeedZoneRadius in user settings, resetting to default."); - } - if (CollectorRadius > SpeedZoneRadius) - { - CollectorRadius = 1; - SpeedZoneRadius = 5; - Game.LogTrivial($"CollectorRadius is greater than SpeedZoneRadius in user settings, resetting to defaults."); - } - if (WaypointSpeed > 100 || WaypointSpeed < 5) - { - WaypointSpeed = 5; - Game.LogTrivial($"Invalid value for WaypointSpeed in user settings, resetting to default."); - } + Game.LogTrivial($"No saved paths found."); + return; + } + else + { + Game.LogTrivial($"{savedPaths.Length} path(s) available to import."); } - void ImportPaths() + // Import paths + foreach (string file in savedPaths) { - //read each file name in Saved Paths - var GAME_DIRECTORY = Directory.GetCurrentDirectory(); - var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; - if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) - { - Game.LogTrivial($"Directory '/plugins/SceneManager/Saved Paths' does not exist. No paths available to import."); - return; - } - - //add file name to PathMainMenu.importedPaths - var paths = Directory.GetFiles(SAVED_PATHS_DIRECTORY); - if (paths.Length == 0) - { - Game.LogTrivial($"No saved paths found."); - return; - } - - foreach (string path in paths) - { - Game.LogTrivial($"Path to import: {Path.GetFileName(path)}"); - - // Check if XML is valid before actually importing - } + Game.LogTrivial($"File: {Path.GetFileName(file)}"); + var importedPath = PathXMLManager.LoadItemFromXML(SAVED_PATHS_DIRECTORY + Path.GetFileName(file)); + importedPath.Name = Path.GetFileNameWithoutExtension(file); + ImportedPaths.Add(importedPath); } + Game.LogTrivial($"Successfully imported {ImportedPaths.Count} path(s)."); } internal static void UpdateSettings(bool threeDWaypointsEnabled, bool mapBlipsEnabled, bool hintsEnabled, SpeedUnits unit) From fabb34eba2a5e183c7d3934ac73f2185635ec379 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:41:51 -0700 Subject: [PATCH 016/112] Big refactor --- SceneManager/EntryPoint.cs | 96 ++++---------------------------------- 1 file changed, 9 insertions(+), 87 deletions(-) diff --git a/SceneManager/EntryPoint.cs b/SceneManager/EntryPoint.cs index 88f3812..f2bff6f 100644 --- a/SceneManager/EntryPoint.cs +++ b/SceneManager/EntryPoint.cs @@ -1,11 +1,8 @@ using System; -using System.IO; -using System.Linq; using System.Reflection; -using System.Windows.Forms; using Rage; -using SceneManager.Objects; using SceneManager.Utils; +using SceneManager.Menus; [assembly: Rage.Attributes.Plugin("Scene Manager", Author = "Rich", Description = "Control your scenes with custom AI pathing and traffic barrier management.", PrefersSingleInstance = true)] @@ -17,10 +14,9 @@ namespace SceneManager [Obfuscation(Exclude = false, Feature = "-rename")] internal static void Main() { - if(!InputManagerChecker() || !CheckRNUIVersion()) + if (!DependencyChecker.DependenciesInstalled()) { Game.UnloadActivePlugin(); - return; } while (Game.IsLoading) @@ -28,15 +24,13 @@ namespace SceneManager GameFiber.Yield(); } - AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler; + AppDomain.CurrentDomain.DomainUnload += TerminationHandler; Settings.LoadSettings(); GetAssemblyVersion(); - MenuManager.InstantiateMenus(); + MenuManager.InitializeMenus(); + Hints.DisplayHintsToOpenMenu(); - DisplayHintsToOpenMenu(); - - GameFiber UserInputFiber = new GameFiber(() => GetUserInput.LoopForUserInput()); - UserInputFiber.Start(); + GameFiber.StartNew(() => UserInput.HandleKeyPress(), "Handle User Input"); void GetAssemblyVersion() { @@ -45,82 +39,10 @@ namespace SceneManager } } - private static bool CheckRNUIVersion() + private static void TerminationHandler(object sender, EventArgs e) { - var directory = Directory.GetCurrentDirectory(); - var exists = File.Exists(directory + @"\RAGENativeUI.dll"); - if (!exists) - { - Game.LogTrivial($"RNUI was not found in the user's GTA V directory."); - Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~RAGENativeUI.dll was not found in your GTA V directory. Please install RAGENativeUI and try again."); - return false; - } - - var userVersion = Assembly.LoadFrom(directory + @"\RAGENativeUI.dll").GetName().Version; - Version requiredMinimumVersion = new Version("1.7.0.0"); - if(userVersion >= requiredMinimumVersion) - { - Game.LogTrivial($"User's RNUI version: {userVersion}"); - return true; - } - else - { - Game.DisplayNotification($"~o~Scene Manager~r~[Error]\n~w~Your RAGENativeUI.dll version is below 1.7. Please update RAGENativeUI and try again."); - return false; - } - - } - - private static bool InputManagerChecker() - { - var directory = Directory.GetCurrentDirectory(); - var exists = File.Exists(directory + @"\InputManager.dll"); - if (!exists) - { - Game.LogTrivial($"InputManager was not found in the user's GTA V directory."); - Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~InputManager.dll was not found in your GTA V directory. Please install InputManager.dll and try again."); - return false; - } - return true; - } - - private static void DisplayHintsToOpenMenu() - { - if (Settings.ModifierKey == Keys.None && Settings.ModifierButton == ControllerButtons.None) - { - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ToggleKey} key ~w~or ~b~{Settings.ToggleButton} button"); - } - else if (Settings.ModifierKey == Keys.None) - { - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ToggleKey} key ~w~or ~b~{Settings.ModifierButton} ~w~+ ~b~{Settings.ToggleButton} buttons"); - } - else if (Settings.ModifierButton == ControllerButtons.None) - { - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press ~b~{Settings.ModifierKey} ~w~+ ~b~{Settings.ToggleKey} ~w~or the ~b~{Settings.ToggleButton} button"); - } - else - { - Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~To open the menu, press the ~b~{Settings.ModifierKey} ~w~+ ~b~{Settings.ToggleKey} keys ~w~or ~b~{Settings.ModifierButton} ~w~+ ~b~{Settings.ToggleButton} buttons"); - } - } - - private static void MyTerminationHandler(object sender, EventArgs e) - { - // Clean up cones - foreach (Barrier barrier in BarrierMenu.barriers.Where(b => b.Object)) - { - barrier.Object.Delete(); - } - if (BarrierMenu.shadowBarrier) - { - BarrierMenu.shadowBarrier.Delete(); - } - - // Clean up paths - for (int i = 0; i < PathMainMenu.paths.Count; i++) - { - PathMainMenu.DeletePath(PathMainMenu.paths[i], Delete.All); - } + BarrierMenu.Cleanup(); + DeleteAllPaths.Delete(); Game.LogTrivial($"Plugin has shut down."); Game.DisplayNotification($"~o~Scene Manager ~r~[Terminated]\n~w~The plugin has shut down."); From 0e79fd8be84e5a5367b71793e8b42fb052761a75 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 10 Jan 2021 08:42:12 -0700 Subject: [PATCH 017/112] Added new classes, reorganized classes. --- SceneManager/SceneManager.csproj | 16 +++++++++++----- SceneManager/_ConfuserEx/c.crproj | 1 - 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/SceneManager/SceneManager.csproj b/SceneManager/SceneManager.csproj index 8181199..5c18d23 100644 --- a/SceneManager/SceneManager.csproj +++ b/SceneManager/SceneManager.csproj @@ -64,28 +64,34 @@ + + + + + + + - - + - + + + - - diff --git a/SceneManager/_ConfuserEx/c.crproj b/SceneManager/_ConfuserEx/c.crproj index 9a9f1f7..8b16c94 100644 --- a/SceneManager/_ConfuserEx/c.crproj +++ b/SceneManager/_ConfuserEx/c.crproj @@ -8,7 +8,6 @@ - From 93951b3e28b1d19ca99cd65cff0439b039907bbb Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:11:33 -0600 Subject: [PATCH 018/112] Added Barrier object --- SceneManager/Menus/BarrierMenu.cs | 4 +- SceneManager/Menus/MenuManager.cs | 1 - SceneManager/Objects/Barrier.cs | 67 +++++++++++++++++++---- SceneManager/Utils/BarrierManager.cs | 82 ++++------------------------ 4 files changed, 70 insertions(+), 84 deletions(-) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index 111de48..9d68ba3 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -175,9 +175,9 @@ namespace SceneManager.Menus internal static void Cleanup() { - foreach (Barrier barrier in BarrierManager.Barriers.Where(x => x.Object)) + foreach (Barrier barrier in BarrierManager.Barriers) { - barrier.Object.Delete(); + barrier.Delete(); } if (BarrierManager.PlaceholderBarrier) { diff --git a/SceneManager/Menus/MenuManager.cs b/SceneManager/Menus/MenuManager.cs index be1202b..97a174f 100644 --- a/SceneManager/Menus/MenuManager.cs +++ b/SceneManager/Menus/MenuManager.cs @@ -56,7 +56,6 @@ namespace SceneManager menuItem.HighlightedBackColor = menuItem.ForeColor; } } - } internal static bool AreMenusClosed() diff --git a/SceneManager/Objects/Barrier.cs b/SceneManager/Objects/Barrier.cs index acddf5c..702f4b4 100644 --- a/SceneManager/Objects/Barrier.cs +++ b/SceneManager/Objects/Barrier.cs @@ -1,26 +1,71 @@ using Rage; +using SceneManager.Menus; +using SceneManager.Utils; using System.Xml.Serialization; namespace SceneManager.Objects { [XmlRoot(ElementName = "Barrier", Namespace = "")] - public class Barrier // Change this and properties to Public for import/export + public class Barrier : Object // Change this and properties to Public for import/export { - public Object Object { get; } - public Model @Model{ get; } - public Vector3 Position { get; } - public float Rotation { get; } - public bool Invincible { get; } + public Vector3 SpawnPosition { get; } + public float SpawnHeading { get; } + new public bool Invincible { get; } public bool Immobile { get; } + public bool LightsEnabled { get; } + public int TextureVariation { get; } - internal Barrier(Object barrier, Vector3 barrierPosition, float barrierRotation, bool invincible, bool immobile) + internal Barrier(Object barrier, Vector3 barrierPosition, float barrierRotation, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) : base(barrier.Model, barrierPosition, barrierRotation) { - Object = barrier; - @Model = barrier.Model; - Position = barrierPosition; - Rotation = barrierRotation; + SpawnPosition = barrierPosition; + SpawnHeading = barrierRotation; Invincible = invincible; + IsInvincible = invincible; Immobile = immobile; + TextureVariation = textureVariation; + LightsEnabled = lightsEnabled; + + if(BarrierManager.PlaceholderBarrier) + { + SetPositionWithSnap(BarrierManager.PlaceholderBarrier.Position); + } + + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(this, true); + if (Invincible) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(this, true); + if (Model.Name != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(this, true); + } + } + IsPositionFrozen = Immobile; + + if (Settings.EnableAdvancedBarricadeOptions) + { + SetAdvancedOptions(); + } + } + + private void SetAdvancedOptions() + { + Rage.Native.NativeFunction.Natives.x971DA0055324D033(this, TextureVariation); + if (LightsEnabled) + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(this, false); + } + else + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(this, true); + } + + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); + IsPositionFrozen = true; + GameFiber.Sleep(50); + if (this && !Immobile) + { + IsPositionFrozen = false; + } } } } diff --git a/SceneManager/Utils/BarrierManager.cs b/SceneManager/Utils/BarrierManager.cs index 06f430f..860bb9f 100644 --- a/SceneManager/Utils/BarrierManager.cs +++ b/SceneManager/Utils/BarrierManager.cs @@ -21,7 +21,7 @@ namespace SceneManager.Utils var barrierKey = Settings.Barriers.Where(x => x.Key == BarrierMenu.BarrierList.SelectedItem).FirstOrDefault().Key; var barrierValue = Settings.Barriers[barrierKey].Name; - PlaceholderBarrier = new Rage.Object(barrierValue, UserInput.GetMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); + PlaceholderBarrier = new Object(barrierValue, UserInput.GetMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); if (!PlaceholderBarrier) { BarrierMenu.Menu.Close(); @@ -39,7 +39,7 @@ namespace SceneManager.Utils // Start with lights off for Parks's objects if (Settings.EnableAdvancedBarricadeOptions) { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(PlaceholderBarrier, BarrierMenu.BarrierTexture.Value); + Rage.Native.NativeFunction.Natives.x971DA0055324D033(PlaceholderBarrier, BarrierMenu.BarrierTexture.Value); // _SET_OBJECT_TEXTURE_VARIATION SetBarrierLights(); } } @@ -136,47 +136,8 @@ namespace SceneManager.Utils } else { - var barrier = new Rage.Object(PlaceholderBarrier.Model, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value); - barrier.SetPositionWithSnap(PlaceholderBarrier.Position); - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(barrier, true); - if (BarrierMenu.Invincible.Checked) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(barrier, true); - if (barrier.Model.Name != "prop_barrier_wat_03a") - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(barrier, true); - } - } - if (BarrierMenu.Immobile.Checked) - { - barrier.IsPositionFrozen = true; - } - else - { - - barrier.IsPositionFrozen = false; - } - if (Settings.EnableAdvancedBarricadeOptions) - { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(barrier, BarrierMenu.BarrierTexture.Value); - if (BarrierMenu.SetBarrierLights.Checked) - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, false); - } - else - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(barrier, true); - } - - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); - barrier.IsPositionFrozen = true; - GameFiber.Sleep(50); - if (barrier && !BarrierMenu.Immobile.Checked) - { - barrier.IsPositionFrozen = false; - } - } - Barriers.Add(new Barrier(barrier, barrier.Position, barrier.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked)); + var barrier = new Barrier(PlaceholderBarrier, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked, BarrierMenu.BarrierTexture.Value, BarrierMenu.SetBarrierLights.Checked); + Barriers.Add(barrier); BarrierMenu.RemoveBarrierOptions.Enabled = true; BarrierMenu.ResetBarriers.Enabled = true; @@ -210,21 +171,21 @@ namespace SceneManager.Utils switch (removeBarrierOptionsIndex) { case 0: - Barriers[Barriers.Count - 1].Object.Delete(); + Barriers[Barriers.Count - 1].Delete(); Barriers.RemoveAt(Barriers.Count - 1); break; case 1: - var nearestBarrier = Barriers.OrderBy(b => b.Object.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); + var nearestBarrier = Barriers.OrderBy(b => b.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); if (nearestBarrier != null) { - nearestBarrier.Object.Delete(); + nearestBarrier.Delete(); Barriers.Remove(nearestBarrier); } break; case 2: - foreach (Barrier b in Barriers.Where(b => b.Object)) + foreach (Barrier b in Barriers) { - b.Object.Delete(); + b.Delete(); } if (Barriers.Count > 0) { @@ -244,30 +205,11 @@ namespace SceneManager.Utils var currentBarriers = Barriers.Where(b => b.Model.Name != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash foreach (Barrier barrier in currentBarriers) { - var newBarrier = new Rage.Object(barrier.Model, barrier.Position, barrier.Rotation); - newBarrier.SetPositionWithSnap(barrier.Position); - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(newBarrier, true); - newBarrier.IsPositionFrozen = barrier.Immobile; - if (barrier.Invincible) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(newBarrier, true); - if (newBarrier.Model.Name != "prop_barrier_wat_03a") - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(newBarrier, true); - } - } - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(newBarrier, setBarrierTrafficLight.Index); - newBarrier.IsPositionFrozen = true; - GameFiber.Sleep(50); - if (newBarrier && !barrier.Immobile) - { - newBarrier.IsPositionFrozen = false; - } - Barriers.Add(new Barrier(newBarrier, newBarrier.Position, newBarrier.Heading, barrier.Invincible, barrier.Immobile)); + Barriers.Add(new Barrier(barrier, barrier.SpawnPosition, barrier.SpawnHeading, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled)); - if (barrier.Object) + if (barrier) { - barrier.Object.Delete(); + barrier.Delete(); } Barriers.Remove(barrier); } From 25acb3f66fff68269102746ac4d39bc0af76c7ae Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:12:24 -0600 Subject: [PATCH 019/112] 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); } } } From c87178267fcfb68be4378bcc2d3c70cb646e4f4d Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:12:31 -0600 Subject: [PATCH 020/112] Removed log spam --- SceneManager/Utils/Extensions.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 9bb7861..3258d46 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -44,25 +44,25 @@ namespace SceneManager.Utils // If ped relationship group does not contain "cop" then this extension doesn't apply if (pedType == PedType.Cop && !ped.RelationshipGroup.Name.ToLower().Contains("cop")) { - Game.LogTrivial($"Ped does not belong to a cop relationship group."); + //Game.LogTrivial($"Ped does not belong to a cop relationship group."); return false; } // Ped is in a vehicle if (taskInVehicleBasic) { - Game.LogTrivial($"Ped is in a vehicle."); + //Game.LogTrivial($"Ped is in a vehicle."); // Ped has a controlled driving task if (taskControlVehicle) { - Game.LogTrivial($"Ped has a controlled driving task. (non-ambient)"); + //Game.LogTrivial($"Ped has a controlled driving task. (non-ambient)"); return false; } // Ped has a wander driving task if (taskCarDriveWander) { - Game.LogTrivial($"Ped has a wander driving task. (ambient)"); + //Game.LogTrivial($"Ped has a wander driving task. (ambient)"); return true; } @@ -70,7 +70,7 @@ namespace SceneManager.Utils var driverHasWanderTask = Rage.Native.NativeFunction.Natives.GET_IS_TASK_ACTIVE(ped.CurrentVehicle.Driver, 151); if (driverHasWanderTask) { - Game.LogTrivial($"Ped is a passenger. Vehicle's driver has a wander driving task. (ambient)"); + //Game.LogTrivial($"Ped is a passenger. Vehicle's driver has a wander driving task. (ambient)"); return true; } } @@ -80,20 +80,20 @@ namespace SceneManager.Utils // UB unit on-foot, waiting for interaction if (ped.RelationshipGroup.Name == "UBCOP") { - Game.LogTrivial($"Cop is UB unit. (non-ambient)"); + //Game.LogTrivial($"Cop is UB unit. (non-ambient)"); return false; } // Cop ped walking around or standing still if ((taskComplexControlMovement && taskWanderingScenario) || (taskAmbientClips && taskUseScenario)) { - Game.LogTrivial($"Ped is wandering around or standing still. (ambient)"); + //Game.LogTrivial($"Ped is wandering around or standing still. (ambient)"); return true; } } // If nothing else returns true before now, then the ped is probably being controlled and doing something else - Game.LogTrivial($"Nothing else has returned true by this point. (non-ambient)"); + //Game.LogTrivial($"Nothing else has returned true by this point. (non-ambient)"); return false; } From 6b8d01dc01afa306bb0893f8f21f74ef9366646e Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:13:35 -0600 Subject: [PATCH 021/112] Added RPH nuget --- SceneManager/SceneManager.csproj | 7 +++---- SceneManager/packages.config | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SceneManager/SceneManager.csproj b/SceneManager/SceneManager.csproj index 5c18d23..5bcae53 100644 --- a/SceneManager/SceneManager.csproj +++ b/SceneManager/SceneManager.csproj @@ -40,9 +40,8 @@ D:\Program Files\Rockstar Games\Grand Theft Auto V\RAGENativeUI.dll False - - ..\..\Modding Resources\References\RagePluginHook.dll - False + + ..\packages\RagePluginHook.1.86.1\lib\net472\RagePluginHook.dll @@ -74,7 +73,7 @@ - + diff --git a/SceneManager/packages.config b/SceneManager/packages.config index 9eb48c7..2e38803 100644 --- a/SceneManager/packages.config +++ b/SceneManager/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file From bcaecb8788e390d44475970307cf657410f49030 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 1 May 2021 13:15:52 -0600 Subject: [PATCH 022/112] Remove unused code --- SceneManager/Utils/PathXMLManager.cs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/SceneManager/Utils/PathXMLManager.cs b/SceneManager/Utils/PathXMLManager.cs index f6ac675..906a747 100644 --- a/SceneManager/Utils/PathXMLManager.cs +++ b/SceneManager/Utils/PathXMLManager.cs @@ -130,25 +130,5 @@ namespace SceneManager.Utils { ModifyItemInXML>(path, t => t.Add(objectToAdd)); } - - ///// - ///// Creates folder in case it doesn't exist and checks file existance. - ///// - ///// - ///// false when a file does not exist. - //private static bool ValidatePath(string path) - //{ - // //TODO: implement - // // - check extension - // // - bool param: createDir - // string dir = Path.GetDirectoryName(path); - // if (!Directory.Exists(dir)) - // { - // Directory.CreateDirectory(dir); - // return false; - // } - - // return File.Exists(path); - //} } } From 1e50d1f53709f958de1b4b7db43c8978b70b099a Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:01:49 -0600 Subject: [PATCH 023/112] Moved to new namespace --- SceneManager/Barriers/Barrier.cs | 135 ++++++++++++++++++ .../CollectedPed.cs | 63 ++++---- .../{Utils => Managers}/BarrierManager.cs | 74 +++++++--- .../{Menus => Managers}/MenuManager.cs | 52 +++---- .../{Utils => Managers}/PathManager.cs | 82 +++++++---- SceneManager/Menus/PathCreationMenu.cs | 5 +- SceneManager/Objects/Barrier.cs | 71 --------- SceneManager/{Objects => Paths}/Path.cs | 128 ++++++----------- SceneManager/SceneManager.csproj | 20 +-- SceneManager/Utils/PathXMLManager.cs | 134 ----------------- SceneManager/Utils/TogglePaths.cs | 21 --- .../{Objects => Waypoints}/Waypoint.cs | 20 ++- 12 files changed, 366 insertions(+), 439 deletions(-) create mode 100644 SceneManager/Barriers/Barrier.cs rename SceneManager/{Objects => CollectedPeds}/CollectedPed.cs (89%) rename SceneManager/{Utils => Managers}/BarrierManager.cs (70%) rename SceneManager/{Menus => Managers}/MenuManager.cs (60%) rename SceneManager/{Utils => Managers}/PathManager.cs (74%) delete mode 100644 SceneManager/Objects/Barrier.cs rename SceneManager/{Objects => Paths}/Path.cs (67%) delete mode 100644 SceneManager/Utils/PathXMLManager.cs delete mode 100644 SceneManager/Utils/TogglePaths.cs rename SceneManager/{Objects => Waypoints}/Waypoint.cs (95%) diff --git a/SceneManager/Barriers/Barrier.cs b/SceneManager/Barriers/Barrier.cs new file mode 100644 index 0000000..c8a9a50 --- /dev/null +++ b/SceneManager/Barriers/Barrier.cs @@ -0,0 +1,135 @@ +using Rage; +using SceneManager.Managers; +using SceneManager.Utils; + +namespace SceneManager.Barriers +{ + public class Barrier : IDeletable, IHandleable, ISpatial + { + private Object _object { get; } + public string ModelName { get; set; } + public Vector3 Position { get; set; } + public float Heading { get; set; } + public bool Invincible { get; set; } + public bool Immobile { get; set; } + public bool LightsEnabled { get; set; } + public int TextureVariation { get; set; } + + public PoolHandle Handle => ((IHandleable)_object).Handle; + + private Barrier() { } + + internal Barrier(string modelName, Vector3 position, float heading, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) + { + ModelName = modelName; + Position = position; + Heading = heading; + Invincible = invincible; + Immobile = immobile; + TextureVariation = textureVariation; + LightsEnabled = lightsEnabled; + _object = new Object(ModelName, Position, Heading); + + if (BarrierManager.PlaceholderBarrier) + { + _object.SetPositionWithSnap(BarrierManager.PlaceholderBarrier.Position); + } + + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + if (Invincible) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); + if (ModelName != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); + } + } + _object.IsPositionFrozen = Immobile; + + if (Settings.EnableAdvancedBarricadeOptions) + { + SetAdvancedOptions(); + } + } + + private void SetAdvancedOptions() + { + Rage.Native.NativeFunction.Natives.x971DA0055324D033(_object, TextureVariation); + if (LightsEnabled) + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(_object, false); + } + else + { + Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(_object, true); + } + + //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); + _object.IsPositionFrozen = true; + GameFiber.Sleep(50); + if (_object && !Immobile) + { + _object.IsPositionFrozen = false; + } + } + + internal void LoadFromImport() + { + Game.LogTrivial($"===== BARRIER DATA ====="); + Game.LogTrivial($"Model: {ModelName}"); + Game.LogTrivial($"Position: {Position}"); + Game.LogTrivial($"Heading: {Heading}"); + Game.LogTrivial($"Invincible: {Invincible}"); + Game.LogTrivial($"Immobile: {Immobile}"); + Game.LogTrivial($"LightsEnabled: {LightsEnabled}"); + Game.LogTrivial($"Texture Variation: {TextureVariation}"); + var barrier = new Barrier(ModelName, Position, Heading, Invincible, Immobile, TextureVariation, LightsEnabled); + BarrierManager.Barriers.Add(barrier); + } + + public void Delete() + { + ((IDeletable)_object).Delete(); + } + + public bool IsValid() + { + return ((IHandleable)_object).IsValid(); + } + + public bool Equals(IHandleable other) + { + return ((System.IEquatable)_object).Equals(other); + } + + public float DistanceTo(Vector3 position) + { + return ((ISpatial)_object).DistanceTo(position); + } + + public float DistanceTo(ISpatial spatialObject) + { + return ((ISpatial)_object).DistanceTo(spatialObject); + } + + public float DistanceTo2D(Vector3 position) + { + return ((ISpatial)_object).DistanceTo2D(position); + } + + public float DistanceTo2D(ISpatial spatialObject) + { + return ((ISpatial)_object).DistanceTo2D(spatialObject); + } + + public float TravelDistanceTo(Vector3 position) + { + return ((ISpatial)_object).TravelDistanceTo(position); + } + + public float TravelDistanceTo(ISpatial spatialObject) + { + return ((ISpatial)_object).TravelDistanceTo(spatialObject); + } + } +} diff --git a/SceneManager/Objects/CollectedPed.cs b/SceneManager/CollectedPeds/CollectedPed.cs similarity index 89% rename from SceneManager/Objects/CollectedPed.cs rename to SceneManager/CollectedPeds/CollectedPed.cs index c48cc00..cb3b346 100644 --- a/SceneManager/Objects/CollectedPed.cs +++ b/SceneManager/CollectedPeds/CollectedPed.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Linq; using SceneManager.Utils; +using SceneManager.Waypoints; +using SceneManager.Paths; -namespace SceneManager.Objects +namespace SceneManager.CollectedPeds { internal class CollectedPed : Ped { @@ -54,7 +56,7 @@ namespace SceneManager.Objects DriveToNextWaypoint(); } - if (!Dismissed && !VehicleAndDriverAreValid() || Directed) + if (Path.State == State.Deleting || (!Dismissed && !VehicleAndDriverAreValid()) || Directed) { return; } @@ -62,7 +64,7 @@ namespace SceneManager.Objects Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] all Path {Path.Number} tasks complete."); if (!Dismissed) { - base.Dismiss(); + Dismiss(); } } @@ -85,7 +87,7 @@ namespace SceneManager.Objects } } - void DriveToDirectedWaypoint() + private void DriveToDirectedWaypoint() { Dismissed = false; @@ -115,6 +117,12 @@ namespace SceneManager.Objects } GameFiber.Yield(); } + + if(!VehicleAndDriverAreValid() || Path.State == State.Deleting) + { + return; + } + if (CurrentVehicle) { Tasks.PerformDrivingManeuver(CurrentVehicle, VehicleManeuver.GoForwardWithCustomSteeringAngle, 3).WaitForCompletion(); @@ -231,19 +239,26 @@ namespace SceneManager.Objects { 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); + var vehicleToStop = CurrentVehicle; + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(vehicleToStop, stoppingDistance, -1, true); StoppedAtWaypoint = true; - while (CurrentWaypoint != null && VehicleAndDriverAreValid() && StoppedAtWaypoint && !Directed) + while (CurrentWaypoint != null && VehicleAndDriverAreValid() && StoppedAtWaypoint && !Directed && IsInVehicle(CurrentVehicle, false)) { GameFiber.Yield(); } - if (this && CurrentVehicle) + if(vehicleToStop) { - Game.LogTrivial($"{CurrentVehicle.Model.Name} releasing from stop waypoint."); - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, 0f, 1, true); - Tasks.CruiseWithVehicle(5f); + Game.LogTrivial($"{vehicleToStop.Model.Name} releasing from stop waypoint."); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(vehicleToStop, 0f, 1, true); } + + //if (this && OriginalVehicle) + //{ + // Game.LogTrivial($"{OriginalVehicle.Model.Name} releasing from stop waypoint."); + // Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(OriginalVehicle, 0f, 1, true); + // Tasks.CruiseWithVehicle(5f); + //} } private bool VehicleAndDriverAreValid() @@ -274,7 +289,7 @@ namespace SceneManager.Objects { if (StoppedAtWaypoint) { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(LastVehicle, 0f, 1, true); + Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, 0f, 1, true); } CurrentVehicle.Dismiss(); } @@ -379,20 +394,20 @@ namespace SceneManager.Objects // 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(); - } - } + //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) + if (!this || !CurrentVehicle) { Game.LogTrivial($"Vehicle or driver is null"); return; diff --git a/SceneManager/Utils/BarrierManager.cs b/SceneManager/Managers/BarrierManager.cs similarity index 70% rename from SceneManager/Utils/BarrierManager.cs rename to SceneManager/Managers/BarrierManager.cs index 860bb9f..8dd6bbb 100644 --- a/SceneManager/Utils/BarrierManager.cs +++ b/SceneManager/Managers/BarrierManager.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; using System.Linq; using Rage; +using SceneManager.Barriers; using SceneManager.Menus; -using SceneManager.Objects; +using SceneManager.Paths; +using SceneManager.Utils; -namespace SceneManager.Utils +namespace SceneManager.Managers { internal static class BarrierManager { @@ -21,11 +23,11 @@ namespace SceneManager.Utils var barrierKey = Settings.Barriers.Where(x => x.Key == BarrierMenu.BarrierList.SelectedItem).FirstOrDefault().Key; var barrierValue = Settings.Barriers[barrierKey].Name; - PlaceholderBarrier = new Object(barrierValue, UserInput.GetMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); + PlaceholderBarrier = new Object(barrierValue, UserInput.PlayerMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); if (!PlaceholderBarrier) { BarrierMenu.Menu.Close(); - Game.LogTrivial($"Something went wrong creating the placeholder barrier. Mouse position: {UserInput.GetMousePositionForBarrier}"); + Game.LogTrivial($"Something went wrong creating the placeholder barrier. Mouse position: {UserInput.PlayerMousePositionForBarrier}"); Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~Something went wrong creating the placeholder barrier. This is a rare problem that only happens in certain areas of the world. Please try again somewhere else."); return; } @@ -64,14 +66,14 @@ namespace SceneManager.Utils if (PlaceholderBarrier) { PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; - PlaceholderBarrier.Position = UserInput.GetMousePositionForBarrier; + PlaceholderBarrier.Position = UserInput.PlayerMousePositionForBarrier; Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); } void DisableBarrierMenuOptionsIfShadowConeTooFar() { - if (!PlaceholderBarrier && UserInput.GetMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) + if (!PlaceholderBarrier && UserInput.PlayerMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) { CreatePlaceholderBarrier(); @@ -106,7 +108,7 @@ namespace SceneManager.Utils //UpdatePlaceholderBarrierPosition(); UpdatePlaceholderBarrierPosition(); } - else if (UserInput.GetMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) + else if (UserInput.PlayerMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) { //CreatePlaceholderBarrier(); CreatePlaceholderBarrier(); @@ -130,19 +132,31 @@ namespace SceneManager.Utils internal static void SpawnBarrier() { + Barrier barrier; + if (BarrierMenu.BarrierList.SelectedItem == "Flare") { SpawnFlare(); } else { - var barrier = new Barrier(PlaceholderBarrier, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked, BarrierMenu.BarrierTexture.Value, BarrierMenu.SetBarrierLights.Checked); + //var obj = new Object(PlaceholderBarrier.Model, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value); + barrier = new Barrier(PlaceholderBarrier.Model.Name, PlaceholderBarrier.Position, PlaceholderBarrier.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked, BarrierMenu.BarrierTexture.Value, BarrierMenu.SetBarrierLights.Checked); Barriers.Add(barrier); BarrierMenu.RemoveBarrierOptions.Enabled = true; BarrierMenu.ResetBarriers.Enabled = true; } + if (barrier != null && BarrierMenu.BelongsToPath.Checked) + { + var matchingPath = PathManager.Paths.FirstOrDefault(x => x.Name == BarrierMenu.AddToPath.OptionText); + if(matchingPath != null) + { + matchingPath.Barriers.Add(barrier); + } + } + void SpawnFlare() { var flare = new Weapon("weapon_flare", PlaceholderBarrier.Position, 1); @@ -161,31 +175,53 @@ namespace SceneManager.Utils } }, "Spawn Flare Fiber"); - Barriers.Add(new Barrier(flare, flare.Position, flare.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked)); + //var obj = new Object(flare.Model, flare.Position, flare.Heading); + barrier = new Barrier(flare.Model.Name, flare.Position, flare.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked); + Barriers.Add(barrier); BarrierMenu.RemoveBarrierOptions.Enabled = true; } } internal static void RemoveBarrier(int removeBarrierOptionsIndex) { + Path path; switch (removeBarrierOptionsIndex) { case 0: - Barriers[Barriers.Count - 1].Delete(); + var barrierToRemove = Barriers[Barriers.Count - 1]; + path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(barrierToRemove)); + if(path != null) + { + path.Barriers.Remove(barrierToRemove); + } + + barrierToRemove.Delete(); Barriers.RemoveAt(Barriers.Count - 1); break; case 1: var nearestBarrier = Barriers.OrderBy(b => b.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); if (nearestBarrier != null) { + path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(nearestBarrier)); + if (path != null) + { + path.Barriers.Remove(nearestBarrier); + } + nearestBarrier.Delete(); Barriers.Remove(nearestBarrier); } break; case 2: - foreach (Barrier b in Barriers) + foreach (Barrier barrier in Barriers) { - b.Delete(); + path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(barrier)); + if (path != null) + { + path.Barriers.Remove(barrier); + } + + barrier.Delete(); } if (Barriers.Count > 0) { @@ -194,20 +230,22 @@ namespace SceneManager.Utils break; } - BarrierMenu.RemoveBarrierOptions.Enabled = Barriers.Count == 0 ? false : true; - BarrierMenu.ResetBarriers.Enabled = Barriers.Count == 0 ? false : true; + BarrierMenu.RemoveBarrierOptions.Enabled = Barriers.Count != 0; + BarrierMenu.ResetBarriers.Enabled = Barriers.Count != 0; } internal static void ResetBarriers() { GameFiber.StartNew(() => { - var currentBarriers = Barriers.Where(b => b.Model.Name != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash + var currentBarriers = Barriers.Where(b => b.ModelName != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash foreach (Barrier barrier in currentBarriers) { - Barriers.Add(new Barrier(barrier, barrier.SpawnPosition, barrier.SpawnHeading, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled)); + //var obj = new Object(barrier.ModelName, barrier.Position, barrier.Heading); + var newBarrier = new Barrier(barrier.ModelName, barrier.Position, barrier.Heading, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled); + Barriers.Add(newBarrier); - if (barrier) + if (barrier.IsValid()) { barrier.Delete(); } @@ -221,7 +259,7 @@ namespace SceneManager.Utils internal static void RotateBarrier() { PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; - PlaceholderBarrier.Position = UserInput.GetMousePositionForBarrier; + PlaceholderBarrier.Position = UserInput.PlayerMousePositionForBarrier; Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); } } diff --git a/SceneManager/Menus/MenuManager.cs b/SceneManager/Managers/MenuManager.cs similarity index 60% rename from SceneManager/Menus/MenuManager.cs rename to SceneManager/Managers/MenuManager.cs index 97a174f..d6500be 100644 --- a/SceneManager/Menus/MenuManager.cs +++ b/SceneManager/Managers/MenuManager.cs @@ -5,7 +5,7 @@ using System.Linq; using RAGENativeUI.Elements; using System.Drawing; -namespace SceneManager +namespace SceneManager.Managers { // The only reason this class should change is to modify how menus are are being handled internal static class MenuManager @@ -19,6 +19,7 @@ namespace SceneManager PathMainMenu.Initialize(); PathCreationMenu.Initialize(); ImportPathMenu.Initialize(); + DriverMenu.Initialize(); BarrierMenu.Initialize(); EditPathMenu.Initialize(); EditWaypointMenu.Initialize(); @@ -37,61 +38,42 @@ namespace SceneManager } } - private static void BuildMenus() + internal static void BuildMenus() { MainMenu.BuildMainMenu(); SettingsMenu.BuildSettingsMenu(); - PathMainMenu.BuildPathMenu(); + DriverMenu.Build(); + PathMainMenu.Build(); + PathCreationMenu.BuildPathCreationMenu(); ImportPathMenu.BuildImportMenu(); EditPathMenu.BuildEditPathMenu(); - BarrierMenu.BuildBarrierMenu(); + BarrierMenu.BuildMenu(); } - private static void ColorMenuItems() + internal static void ColorMenuItems() { foreach(UIMenuItem menuItem in MenuPool.SelectMany(x => x.MenuItems)) { - if (menuItem.Enabled && menuItem.ForeColor == Color.Gold) + if (menuItem.Enabled) { menuItem.HighlightedBackColor = menuItem.ForeColor; } + if(!menuItem.Enabled) + { + menuItem.HighlightedBackColor = Color.DarkGray; + menuItem.DisabledForeColor = Color.Gray; + } } } - internal static bool AreMenusClosed() + internal static void ProcessMenus() { - if (!BarrierMenu.Menu.Visible && !PathMainMenu.Menu.Visible && !PathCreationMenu.Menu.Visible && !EditPathMenu.Menu.Visible && !EditWaypointMenu.Menu.Visible && !SettingsMenu.Menu.Visible) - { - return true; - } - else - { - return false; - } - } - - internal static void Update() - { - while (AnyMenuVisible()) + while (MenuPool.Any(x => x.Visible)) { MenuPool.ProcessMenus(); + ColorMenuItems(); GameFiber.Yield(); } } - - private static bool AnyMenuVisible() - { - if(MenuPool.Any(x => x.Visible)) - { - return true; - } - - return false; - } - - internal static void AddToMenuPool(UIMenu menu) - { - MenuPool.Add(menu); - } } } diff --git a/SceneManager/Utils/PathManager.cs b/SceneManager/Managers/PathManager.cs similarity index 74% rename from SceneManager/Utils/PathManager.cs rename to SceneManager/Managers/PathManager.cs index 7d27fe6..74a9ceb 100644 --- a/SceneManager/Utils/PathManager.cs +++ b/SceneManager/Managers/PathManager.cs @@ -1,11 +1,12 @@ using Rage; -using RAGENativeUI.Elements; using SceneManager.Menus; -using SceneManager.Objects; +using SceneManager.Paths; +using SceneManager.Utils; +using SceneManager.Waypoints; using System.Collections.Generic; using System.Linq; -namespace SceneManager.Utils +namespace SceneManager.Managers { internal class PathManager { @@ -15,7 +16,7 @@ namespace SceneManager.Utils { importedPath.State = State.Creating; - var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State != State.Creating)) + 1; + var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State == State.Uninitialized)) + 1; // != State.Creating if (firstVacantIndex < 0) { firstVacantIndex = 0; @@ -35,7 +36,7 @@ namespace SceneManager.Utils { var currentPath = Paths[PathMainMenu.EditPath.Index]; // Reference PNWParks's UserInput class from LiveLights - var filename = UserInput.GetFileName("Type the name you would like to save your file as", "Enter a filename", 100) + ".xml"; + var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100) + ".xml"; // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) if (string.IsNullOrWhiteSpace(filename)) @@ -53,6 +54,9 @@ namespace SceneManager.Utils Settings.ImportPaths(); PathMainMenu.ImportPath.Enabled = true; ImportPathMenu.BuildImportMenu(); + PathMainMenu.Build(); + + PathMainMenu.Menu.Visible = true; } internal static Path InitializeNewPath() @@ -85,11 +89,11 @@ namespace SceneManager.Utils Waypoint newWaypoint; if (PathCreationMenu.CollectorWaypoint.Checked) { - newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, PathCreationMenu.StopWaypoint.Checked, true, PathCreationMenu.CollectorRadius.Value, PathCreationMenu.SpeedZoneRadius.Value); + newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(PathCreationMenu.WaypointSpeed.Value), drivingFlag, PathCreationMenu.StopWaypoint.Checked, true, PathCreationMenu.CollectorRadius.Value, PathCreationMenu.SpeedZoneRadius.Value); } else { - newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, PathCreationMenu.StopWaypoint.Checked); + newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(PathCreationMenu.WaypointSpeed.Value), drivingFlag, PathCreationMenu.StopWaypoint.Checked); } currentPath.Waypoints.Add(newWaypoint); Game.LogTrivial($"Path {currentPath.Number} Waypoint {waypointNumber} added [Driving style: {drivingFlag} | Stop waypoint: {newWaypoint.IsStopWaypoint} | Speed: {newWaypoint.Speed} | Collector: {newWaypoint.IsCollector}]"); @@ -106,28 +110,29 @@ namespace SceneManager.Utils if (EditWaypointMenu.CollectorWaypoint.Checked) { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, EditWaypointMenu.StopWaypointType.Checked, true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value)); + currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked, true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value)); } else { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.GetMousePosition, SetDriveSpeedForWaypoint(), drivingFlag, EditWaypointMenu.StopWaypointType.Checked)); + currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked)); } Game.LogTrivial($"New waypoint (#{currentPath.Waypoints.Last().Number}) added."); } internal static void UpdateWaypoint() { - var currentPath = Paths[PathMainMenu.EditPath.Index]; + //var currentPath = Paths[PathMainMenu.EditPath.Index]; + var currentPath = Paths.FirstOrDefault(x => x.Name == PathMainMenu.EditPath.OptionText); var currentWaypoint = currentPath.Waypoints[EditWaypointMenu.EditWaypoint.Index]; DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; if (currentPath.Waypoints.Count == 1) { - currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.PlayerMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); } else { - currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), EditWaypointMenu.CollectorWaypoint.Checked, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + currentWaypoint.UpdateWaypoint(currentWaypoint, UserInput.PlayerMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), EditWaypointMenu.CollectorWaypoint.Checked, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); } Game.LogTrivial($"Path {currentPath.Number} Waypoint {currentWaypoint.Number} updated [Driving style: {drivingFlag} | Stop waypoint: {EditWaypointMenu.StopWaypointType.Checked} | Speed: {EditWaypointMenu.ChangeWaypointSpeed.Value} | Collector: {currentWaypoint.IsCollector}]"); @@ -135,22 +140,11 @@ namespace SceneManager.Utils Game.DisplayNotification($"~o~Scene Manager ~g~[Success]~w~\nWaypoint {currentWaypoint.Number} updated."); } - private static float SetDriveSpeedForWaypoint() + private static float ConvertDriveSpeedForWaypoint(float speed) { - float convertedSpeed; - if (SettingsMenu.SpeedUnits.SelectedItem == SpeedUnits.MPH) - { - //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); - convertedSpeed = MathHelper.ConvertMilesPerHourToMetersPerSecond(PathCreationMenu.WaypointSpeed.Value); - //Logger.Log($"Converted speed: {convertedSpeed}m/s"); - } - else - { - //Logger.Log($"Original speed: {waypointSpeeds[waypointSpeed.Index]}{SettingsMenu.speedUnits.SelectedItem}"); - convertedSpeed = MathHelper.ConvertKilometersPerHourToMetersPerSecond(PathCreationMenu.WaypointSpeed.Value); - //Logger.Log($"Converted speed: {convertedSpeed}m/s"); - } - + float convertedSpeed = SettingsMenu.SpeedUnits.SelectedItem == SpeedUnits.MPH + ? MathHelper.ConvertMilesPerHourToMetersPerSecond(speed) + : MathHelper.ConvertKilometersPerHourToMetersPerSecond(speed); return convertedSpeed; } @@ -169,7 +163,7 @@ namespace SceneManager.Utils Game.LogTrivial($"Deleting the last waypoint from the path."); currentPath.Delete(); Paths.Remove(currentPath); - PathMainMenu.BuildPathMenu(); + PathMainMenu.Build(); EditWaypointMenu.Menu.Visible = false; PathMainMenu.Menu.Visible = true; @@ -191,7 +185,7 @@ namespace SceneManager.Utils DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; Hints.Display($"~o~Scene Manager ~y~[Hint]~w~\nYour path's first waypoint ~b~must~w~ be a collector. If it's not, it will automatically be made into one."); Game.LogTrivial($"The path only has 1 waypoint left, this waypoint must be a collector."); - currentPath.Waypoints[0].UpdateWaypoint(currentPath.Waypoints.First(), UserInput.GetMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); + currentPath.Waypoints[0].UpdateWaypoint(currentPath.Waypoints.First(), UserInput.PlayerMousePosition, drivingFlag, EditWaypointMenu.StopWaypointType.Checked, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value, EditWaypointMenu.UpdateWaypointPosition.Checked); EditWaypointMenu.CollectorWaypoint.Checked = true; EditWaypointMenu.ChangeCollectorRadius.Enabled = true; EditWaypointMenu.ChangeSpeedZoneRadius.Enabled = true; @@ -209,8 +203,13 @@ namespace SceneManager.Utils GameFiber.StartNew(() => currentPath.LoopWaypointCollection(), "Waypoint Collection Loop Fiber"); PathMainMenu.CreateNewPath.Text = "Create New Path"; - PathMainMenu.BuildPathMenu(); + PathMainMenu.Build(); PathMainMenu.Menu.Visible = true; + + MainMenu.BuildMainMenu(); + DriverMenu.Build(); + PathCreationMenu.BuildPathCreationMenu(); + BarrierMenu.BuildMenu(); } internal static void TogglePathCreationMenuItems(Path currentPath) @@ -254,5 +253,28 @@ namespace SceneManager.Utils Paths.SelectMany(x => x.Waypoints).ToList().ForEach(x => x.DisableBlip()); } } + + internal static void ToggleAllPaths(bool disable) + { + if (disable) + { + Paths.ForEach(x => x.DisablePath()); + Game.LogTrivial($"All paths disabled."); + } + else + { + Paths.ForEach(x => x.EnablePath()); + Game.LogTrivial($"All paths enabled."); + } + } + + internal static void DeleteAllPaths() + { + Paths.ForEach(x => x.Delete()); + Paths.Clear(); + Game.LogTrivial($"All paths deleted"); + Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); + MainMenu.BuildMainMenu(); + } } } diff --git a/SceneManager/Menus/PathCreationMenu.cs b/SceneManager/Menus/PathCreationMenu.cs index 1e73f84..fa6cfb2 100644 --- a/SceneManager/Menus/PathCreationMenu.cs +++ b/SceneManager/Menus/PathCreationMenu.cs @@ -4,7 +4,8 @@ using Rage; using RAGENativeUI; using RAGENativeUI.Elements; using SceneManager.Utils; -using SceneManager.Objects; +using SceneManager.Managers; +using SceneManager.Paths; namespace SceneManager.Menus { @@ -36,7 +37,7 @@ namespace SceneManager.Menus internal static void BuildPathCreationMenu() { - Menu.MenuItems.Clear(); + Menu.Clear(); Menu.AddItem(CollectorWaypoint); CollectorWaypoint.Enabled = false; diff --git a/SceneManager/Objects/Barrier.cs b/SceneManager/Objects/Barrier.cs deleted file mode 100644 index 702f4b4..0000000 --- a/SceneManager/Objects/Barrier.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Rage; -using SceneManager.Menus; -using SceneManager.Utils; -using System.Xml.Serialization; - -namespace SceneManager.Objects -{ - [XmlRoot(ElementName = "Barrier", Namespace = "")] - public class Barrier : Object // Change this and properties to Public for import/export - { - public Vector3 SpawnPosition { get; } - public float SpawnHeading { get; } - new public bool Invincible { get; } - public bool Immobile { get; } - public bool LightsEnabled { get; } - public int TextureVariation { get; } - - internal Barrier(Object barrier, Vector3 barrierPosition, float barrierRotation, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) : base(barrier.Model, barrierPosition, barrierRotation) - { - SpawnPosition = barrierPosition; - SpawnHeading = barrierRotation; - Invincible = invincible; - IsInvincible = invincible; - Immobile = immobile; - TextureVariation = textureVariation; - LightsEnabled = lightsEnabled; - - if(BarrierManager.PlaceholderBarrier) - { - SetPositionWithSnap(BarrierManager.PlaceholderBarrier.Position); - } - - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(this, true); - if (Invincible) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(this, true); - if (Model.Name != "prop_barrier_wat_03a") - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(this, true); - } - } - IsPositionFrozen = Immobile; - - if (Settings.EnableAdvancedBarricadeOptions) - { - SetAdvancedOptions(); - } - } - - private void SetAdvancedOptions() - { - Rage.Native.NativeFunction.Natives.x971DA0055324D033(this, TextureVariation); - if (LightsEnabled) - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(this, false); - } - else - { - Rage.Native.NativeFunction.Natives.SET_ENTITY_LIGHTS(this, true); - } - - //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(barrier, setBarrierTrafficLight.Index); - IsPositionFrozen = true; - GameFiber.Sleep(50); - if (this && !Immobile) - { - IsPositionFrozen = false; - } - } - } -} diff --git a/SceneManager/Objects/Path.cs b/SceneManager/Paths/Path.cs similarity index 67% rename from SceneManager/Objects/Path.cs rename to SceneManager/Paths/Path.cs index de5bd08..20bb91c 100644 --- a/SceneManager/Objects/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -7,8 +7,12 @@ using System.Xml.Serialization; using SceneManager.Utils; using SceneManager.Menus; using System.IO; +using SceneManager.Managers; +using SceneManager.Barriers; +using SceneManager.Waypoints; +using SceneManager.CollectedPeds; -namespace SceneManager.Objects +namespace SceneManager.Paths { [XmlRoot(ElementName = "Path", Namespace = "")] public class Path // Change this to Public for import/export @@ -21,8 +25,11 @@ namespace SceneManager.Objects [XmlArray("Waypoints")] [XmlArrayItem("Waypoint")] public List Waypoints { get; set; } = new List(); + [XmlArray("Barriers")] + [XmlArrayItem("Barrier")] + public List Barriers { get; set; } = new List(); internal List CollectedPeds { get; } = new List(); - private List BlacklistedVehicles { get; } = new List(); + internal List BlacklistedVehicles { get; } = new List(); private Path() { } @@ -30,6 +37,7 @@ namespace SceneManager.Objects { Number = pathNum; State = pathState; + Name = Number.ToString(); DrawLinesBetweenWaypoints(); } @@ -42,7 +50,7 @@ namespace SceneManager.Objects Directory.CreateDirectory(SAVED_PATHS_DIRECTORY); Game.LogTrivial($"New directory created at '/plugins/SceneManager/Saved Paths'"); } - PathXMLManager.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + filename); + Serializer.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + filename); } internal void Load() @@ -53,6 +61,12 @@ namespace SceneManager.Objects { waypoint.LoadFromImport(this); } + + Game.LogTrivial($"This path has {Barriers.Count} barriers"); + foreach(Barrier barrier in Barriers) + { + barrier.LoadFromImport(); + } DrawLinesBetweenWaypoints(); PathManager.EndPath(this); } @@ -166,98 +180,48 @@ namespace SceneManager.Objects int yieldAfterChecks = 50; // How many calculations to do before yielding while (PathManager.Paths.Contains(this)) { - if (IsEnabled) + GameFiber.SleepUntil(() => IsEnabled, 0); + + if(State == State.Deleting) { - int checksDone = 0; - try - { - foreach (Waypoint waypoint in Waypoints.Where(x => x != null && x.IsCollector)) - { - foreach (Vehicle vehicle in World.GetAllVehicles()) - { - if (VehicleIsValidForCollection(vehicle) && VehicleIsNearWaypoint(vehicle, waypoint)) - { - CollectedPeds.Add(new CollectedPed(vehicle.Driver, this, waypoint)); - } + Game.LogTrivial($"Path deleted, ending waypoint collection."); + return; + } - checksDone++; // Increment the counter inside the vehicle loop - if (checksDone % yieldAfterChecks == 0) - { - GameFiber.Yield(); // Yield the game fiber after the specified number of vehicles have been checked - } + int checksDone = 0; + var collectorWaypoints = Waypoints.Where(x => x.IsCollector); + var vehiclesInWorld = World.GetAllVehicles().Where(x => x); + + foreach (Waypoint waypoint in collectorWaypoints) + { + foreach (Vehicle vehicle in vehiclesInWorld) + { + if (vehicle.IsNearCollectorWaypoint(waypoint) && vehicle.IsValidForPathCollection(this)) + { + CollectedPeds.Add(new CollectedPed(vehicle.Driver, this, waypoint)); + } + + checksDone++; // Increment the counter inside the vehicle loop + if (checksDone % yieldAfterChecks == 0) + { + GameFiber.Yield(); // Yield the game fiber after the specified number of vehicles have been checked + if(State == State.Deleting) + { + Game.LogTrivial($"Path deleted, ending waypoint collection."); + return; } } } - catch(Exception ex) - { - Game.LogTrivial($"Vehicle collection error: {ex}"); - } } + GameFiber.Sleep((int)Math.Max(1, Game.GameTime - lastProcessTime)); // If the prior lines took more than a second to run, then you'll run again almost immediately, but if they ran fairly quickly, you can sleep the loop until the remainder of the time between checks has passed lastProcessTime = Game.GameTime; } - - bool VehicleIsNearWaypoint(Vehicle v, Waypoint wp) - { - return v.FrontPosition.DistanceTo2D(wp.Position) <= wp.CollectorRadius && Math.Abs(wp.Position.Z - v.Position.Z) < 3; - } - - bool VehicleIsValidForCollection(Vehicle v) - { - if(!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; - } - if (v.HasDriver && v.Driver) - { - if(!v.Driver.IsAlive) - { - Game.LogTrivial($"Vehicle's driver is dead."); - BlacklistedVehicles.Add(v); - return false; - } - if (v.IsPoliceVehicle && !v.Driver.IsAmbient()) - { - Game.LogTrivial($"Vehicle's driver not ambient."); - BlacklistedVehicles.Add(v); - return false; - } - } - if (!v.HasDriver) - { - v.CreateRandomDriver(); - while (!v.HasDriver) - { - GameFiber.Yield(); - } - if (v && v.Driver) - { - v.Driver.IsPersistent = true; - v.Driver.BlockPermanentEvents = true; - } - else - { - return false; - } - } - return true; - } - else - { - return false; - } - } } internal void Delete() { + State = State.Deleting; DismissCollectedDrivers(); RemoveWaypoints(); Game.LogTrivial($"Path {Number} deleted."); diff --git a/SceneManager/SceneManager.csproj b/SceneManager/SceneManager.csproj index 5bcae53..2ef0ffc 100644 --- a/SceneManager/SceneManager.csproj +++ b/SceneManager/SceneManager.csproj @@ -63,41 +63,41 @@ + - + - - - - + + - + - - + + - + - + + diff --git a/SceneManager/Utils/PathXMLManager.cs b/SceneManager/Utils/PathXMLManager.cs deleted file mode 100644 index 906a747..0000000 --- a/SceneManager/Utils/PathXMLManager.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Rage; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using System.Xml.Serialization; - -namespace SceneManager.Utils -{ - internal static class PathXMLManager - { - private static Dictionary _serializerCache = new Dictionary(); - private static XmlSerializer _getOrCreateSerializer(XmlAttributeOverrides overrides = null) - { - if (_serializerCache.ContainsKey(typeof(T))) - { - Game.LogTrivialDebug("Serializer cache already contains " + typeof(T).Name); - return _serializerCache[typeof(T)]; - } - else - { - Game.LogTrivialDebug("Adding " + typeof(T).Name + " to serializer cache"); - Game.LogTrivialDebug("Overrides specified: " + (overrides != null)); - var s = new XmlSerializer(typeof(T), new XmlRootAttribute("Path")); - //var s = new XmlSerializer(typeof(T), overrides); - _serializerCache.Add(typeof(T), s); - return s; - } - } - - public static void SaveToNode(string file, string node, string value) - { - XmlNode n = SelectNodeFromXml(file, node); - - if (n == null) throw new KeyNotFoundException($"{nameof(SaveToNode)}: specified node does not exists!"); - - n.InnerText = value; - var doc = new XmlDocument(); - doc.Save(file); - } - - public static string ReadFromNode(string file, string node) - { - return SelectNodeFromXml(file, node).InnerText; - } - - private static XmlNode SelectNodeFromXml(string filePath, string node) - { - if (!File.Exists(filePath)) throw new FileNotFoundException($"{nameof(SelectNodeFromXml)}(): specified file does not exist: {filePath}"); - - using (TextReader reader = new StreamReader(filePath)) - { - var doc = new XmlDocument(); - doc.Load(reader); - return doc.SelectSingleNode(node); - } - } - - public static List LoadAllXML(string dirPath, SearchOption searchOption = SearchOption.AllDirectories) - { - if (!Directory.Exists(dirPath)) throw new DirectoryNotFoundException($"{nameof(LoadAllXML)}(): specified directory could not be found: {dirPath}"); - - string[] files = Directory.GetFiles(dirPath, "*.xml", searchOption); - - List result = new List(); - - Array.ForEach(files, f => result.AddRange(LoadFromXML(f))); - - return result; - } - - public static void SaveToXML(List list, string filePath) - { - SaveItemToXML(list, filePath); - } - - public static void SaveItemToXML(T item, string path, XmlAttributeOverrides overrides) - { - Encoding utf8NoBom = new UTF8Encoding(false); - using (TextWriter writer = new StreamWriter(path, false, utf8NoBom)) - { - XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); - ns.Add("", ""); - - // new XmlSerializer(typeof(T)).Serialize(writer, item); - _getOrCreateSerializer(overrides).Serialize(writer, item, ns); - } - } - - public static void SaveItemToXML(T item, string path) - { - SaveItemToXML(item, path, null); - } - - public static T LoadItemFromXML(string filePath, XmlAttributeOverrides overrides) - { - if (!File.Exists(filePath)) throw new FileNotFoundException($"{nameof(LoadItemFromXML)}(): specified file does not exist: {filePath}"); - - using (TextReader reader = new StreamReader(filePath)) - { - return (T)_getOrCreateSerializer(overrides).Deserialize(reader); - } - } - - public static T LoadItemFromXML(string filePath) - { - return (T)LoadItemFromXML(filePath, null); - } - - public static void ModifyItemInXML(string filePath, Action modification) - { - T item = LoadItemFromXML(filePath); - modification(item); - SaveItemToXML(item, filePath); - } - - public static T GetSelectedListElementFromXml(string file, Func, T> selector) - { - List deserialized = LoadItemFromXML>(file); - return selector(deserialized); - } - - public static List LoadFromXML(string filePath) - { - return LoadItemFromXML>(filePath); - } - - public static void AppendToXML(T objectToAdd, string path) - { - ModifyItemInXML>(path, t => t.Add(objectToAdd)); - } - } -} diff --git a/SceneManager/Utils/TogglePaths.cs b/SceneManager/Utils/TogglePaths.cs deleted file mode 100644 index f94f4d5..0000000 --- a/SceneManager/Utils/TogglePaths.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Rage; - -namespace SceneManager.Utils -{ - internal static class TogglePaths - { - internal static void Toggle(bool disable) - { - if (disable) - { - PathManager.Paths.ForEach(x => x.DisablePath()); - Game.LogTrivial($"All paths disabled."); - } - else - { - PathManager.Paths.ForEach(x => x.EnablePath()); - Game.LogTrivial($"All paths enabled."); - } - } - } -} diff --git a/SceneManager/Objects/Waypoint.cs b/SceneManager/Waypoints/Waypoint.cs similarity index 95% rename from SceneManager/Objects/Waypoint.cs rename to SceneManager/Waypoints/Waypoint.cs index e410b34..2e62513 100644 --- a/SceneManager/Objects/Waypoint.cs +++ b/SceneManager/Waypoints/Waypoint.cs @@ -3,8 +3,11 @@ using System.Drawing; using System.Linq; using SceneManager.Utils; using SceneManager.Menus; +using SceneManager.Managers; +using SceneManager.Paths; +using SceneManager.CollectedPeds; -namespace SceneManager.Objects +namespace SceneManager.Waypoints { public class Waypoint // Change this and select properties to Public for import/export { @@ -77,7 +80,6 @@ namespace SceneManager.Objects Blip.Color = Color.Green; 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}"); cp.Dismiss(Dismiss.FromWaypoint); } } @@ -157,15 +159,9 @@ namespace SceneManager.Objects } } - internal void AddSpeedZone() - { - SpeedZone = World.AddSpeedZone(Position, SpeedZoneRadius, Speed); - } + internal void AddSpeedZone() => SpeedZone = World.AddSpeedZone(Position, SpeedZoneRadius, Speed); - internal void RemoveSpeedZone() - { - World.RemoveSpeedZone(SpeedZone); - } + internal void RemoveSpeedZone() => World.RemoveSpeedZone(SpeedZone); internal void DrawWaypointMarker() { @@ -176,7 +172,7 @@ namespace SceneManager.Objects { if(SettingsMenu.ThreeDWaypoints.Checked && EnableWaypointMarker && Path.Waypoints.Contains(this)) { - if (EditWaypointMenu.Menu.Visible && PathMainMenu.EditPath.Value == Path.Number && EditWaypointMenu.EditWaypoint.Value == Number) + if (EditWaypointMenu.Menu.Visible && PathMainMenu.EditPath.OptionText == Path.Name && EditWaypointMenu.EditWaypoint.Value == Number) { if (EditWaypointMenu.CollectorWaypoint.Checked) { @@ -208,7 +204,7 @@ namespace SceneManager.Objects else if ((Path.State == State.Finished && MenuManager.MenuPool.IsAnyMenuOpen()) || (Path.State == State.Creating && PathCreationMenu.Menu.Visible)) { float markerHeight = 1f; - if ((PathMainMenu.DirectDriver.Selected && PathMainMenu.DirectDriver.Value == Path.Number) || PathMainMenu.EditPath.Selected && PathMainMenu.EditPath.Value == Path.Number && (PathMainMenu.Menu.Visible || EditPathMenu.Menu.Visible)) + if ((DriverMenu.DirectDriver.Selected && DriverMenu.DirectDriver.OptionText == Path.Name) || PathMainMenu.EditPath.Selected && PathMainMenu.EditPath.OptionText == Path.Name && (PathMainMenu.Menu.Visible || EditPathMenu.Menu.Visible)) { markerHeight = 2f; } From 5191899a1a87ee3d3b8490ac84c3f1467e3f071e Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:02:04 -0600 Subject: [PATCH 024/112] Refactored to different class --- SceneManager/Utils/DeleteAllPaths.cs | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 SceneManager/Utils/DeleteAllPaths.cs diff --git a/SceneManager/Utils/DeleteAllPaths.cs b/SceneManager/Utils/DeleteAllPaths.cs deleted file mode 100644 index 9835960..0000000 --- a/SceneManager/Utils/DeleteAllPaths.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Rage; - -namespace SceneManager.Utils -{ - internal static class DeleteAllPaths - { - internal static void Delete() - { - PathManager.Paths.ForEach(x => x.Delete()); - PathManager.Paths.Clear(); - Game.LogTrivial($"All paths deleted"); - Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); - } - } -} From f337f4b3d9e10f437732ad6e49bcdeb66a1ba0ed Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:02:50 -0600 Subject: [PATCH 025/112] Added ability to add barriers to paths --- SceneManager/Menus/BarrierMenu.cs | 33 +++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index 9d68ba3..cca1c5a 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -4,7 +4,8 @@ using System.Linq; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; -using SceneManager.Objects; +using SceneManager.Barriers; +using SceneManager.Managers; using SceneManager.Utils; namespace SceneManager.Menus @@ -16,10 +17,12 @@ namespace SceneManager.Menus internal static UIMenuListScrollerItem BarrierList { get; } = new UIMenuListScrollerItem("Spawn Barrier", "", Settings.Barriers.Keys); // Settings.barrierKeys internal static UIMenuNumericScrollerItem RotateBarrier { get; } = new UIMenuNumericScrollerItem("Rotate Barrier", "", 0, 350, 10); // ADD CHECKBOX FOR BARRIER TO STOP TRAFFIC? ADD 3D MARKER TO SHOW WHERE TRAFFIC WILL STOP. ONLY NEED ONE CONE TO DO IT PER LANE - internal static UIMenuCheckboxItem Invincible { get; } = new UIMenuCheckboxItem("Indestructible", false); - internal static UIMenuCheckboxItem Immobile { get; } = new UIMenuCheckboxItem("Immobile", false); - internal static UIMenuNumericScrollerItem BarrierTexture { get; } = new UIMenuNumericScrollerItem("Change Texture", "", 0, 15, 1); - internal static UIMenuCheckboxItem SetBarrierLights { get; } = new UIMenuCheckboxItem("Enable Barrier Lights", Settings.EnableBarrierLightsDefaultOn); + internal static UIMenuCheckboxItem Invincible { get; } = new UIMenuCheckboxItem("Indestructible", false, "If checked, the barrier will not break, or will be harder to break. The barrier will still able to be moved around."); + internal static UIMenuCheckboxItem Immobile { get; } = new UIMenuCheckboxItem("Immobile", false, "If checked, the barrier will be frozen in place."); + internal static UIMenuNumericScrollerItem BarrierTexture { get; } = new UIMenuNumericScrollerItem("Change Texture", "If the barrier has multiple textures, changing this value will apply them to the barrier.", 0, 15, 1); + internal static UIMenuCheckboxItem SetBarrierLights { get; } = new UIMenuCheckboxItem("Enable Barrier Lights", Settings.EnableBarrierLightsDefaultOn, "If the barrier has functional lights, checking this option will turn them on."); + internal static UIMenuCheckboxItem BelongsToPath { get; } = new UIMenuCheckboxItem("Belongs to Path", false, "If checked, the barrier will be saved with the path when the path is exported."); + internal static UIMenuListScrollerItem AddToPath { get; private set; } internal static UIMenuListScrollerItem SetBarrierTrafficLight { get; } = new UIMenuListScrollerItem("Set Barrier Traffic Light", "", TrafficLightList); internal static UIMenuListScrollerItem RemoveBarrierOptions { get; } = new UIMenuListScrollerItem("Remove Barrier", "", new[] { "Last Barrier", "Nearest Barrier", "All Barriers" }); internal static UIMenuItem ResetBarriers { get; } = new UIMenuItem("Reset Barriers", "Reset all spawned barriers to their original position and rotation"); @@ -35,8 +38,10 @@ namespace SceneManager.Menus Menu.OnMenuOpen += BarrierMenu_OnMenuOpen; } - internal static void BuildBarrierMenu() + internal static void BuildMenu() { + Menu.Clear(); + Menu.AddItem(BarrierList); BarrierList.ForeColor = Color.Gold; @@ -54,14 +59,21 @@ namespace SceneManager.Menus //barrierMenu.AddItem(setBarrierTrafficLight); //setBarrierTrafficLight.Index = 3; } + Menu.AddItem(BelongsToPath); + BelongsToPath.Enabled = PathManager.Paths.Count() > 0 ? true : false; + BelongsToPath.Checked = false; + + AddToPath = new UIMenuListScrollerItem("Path", "The path the barrier will be saved with when the path is exported.", PathManager.Paths.Select(x => x.Name)); + Menu.AddItem(AddToPath); + AddToPath.Enabled = BelongsToPath.Checked; Menu.AddItem(RemoveBarrierOptions); RemoveBarrierOptions.ForeColor = Color.Gold; - RemoveBarrierOptions.Enabled = false; + RemoveBarrierOptions.Enabled = BarrierManager.Barriers.Count() != 0; Menu.AddItem(ResetBarriers); ResetBarriers.ForeColor = Color.Gold; - ResetBarriers.Enabled = false; + ResetBarriers.Enabled = BarrierManager.Barriers.Count() != 0; } internal static void ScrollBarrierList() @@ -91,6 +103,11 @@ namespace SceneManager.Menus //SetBarrierLights(); BarrierManager.SetBarrierLights(); } + + if(checkbox == BelongsToPath) + { + AddToPath.Enabled = BelongsToPath.Checked; + } } private static void BarrierMenu_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int oldIndex, int newIndex) From 910c4bcc1616bdff8e5d58c4c0b28c7b41153b08 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:03:13 -0600 Subject: [PATCH 026/112] Added separate menu for managing drivers --- SceneManager/Menus/DriverMenu.cs | 74 ++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 SceneManager/Menus/DriverMenu.cs diff --git a/SceneManager/Menus/DriverMenu.cs b/SceneManager/Menus/DriverMenu.cs new file mode 100644 index 0000000..fda516c --- /dev/null +++ b/SceneManager/Menus/DriverMenu.cs @@ -0,0 +1,74 @@ +using Rage; +using RAGENativeUI; +using RAGENativeUI.Elements; +using SceneManager.CollectedPeds; +using SceneManager.Managers; +using SceneManager.Utils; +using SceneManager.Waypoints; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; + +namespace SceneManager.Menus +{ + internal class DriverMenu + { + internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Driver Menu"); + private static string[] DismissOptions { get; } = new string[] { "From path", "From waypoint", "From world" }; + internal static UIMenuListScrollerItem DirectOptions { get; } = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); + internal static UIMenuListScrollerItem DirectDriver { get; private set; } + internal static UIMenuListScrollerItem DismissDriver { get; } = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~Driver will be released from the path\n~b~From waypoint: ~w~Driver will skip their current waypoint task\n~b~From world: ~w~Driver will be removed from the world.", DismissOptions); + + internal static void Initialize() + { + Menu.ParentMenu = PathMainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += DriverMenu_OnItemSelected; + Menu.OnMenuOpen += DriverMenu_OnMenuOpen; + } + + internal static void Build() + { + Menu.Clear(); + + Menu.AddItem(DirectOptions); + DirectOptions.Enabled = true; + Menu.AddItem(DirectDriver = new UIMenuListScrollerItem("Direct nearest driver to path", "", PathManager.Paths.Select(x => x.Name))); // This must instantiate here because the Paths change + DirectDriver.ForeColor = Color.Gold; + DirectDriver.Enabled = true; + Menu.AddItem(DismissDriver); + DismissDriver.ForeColor = Color.Gold; + + if (PathManager.Paths.Count == 0) + { + DirectOptions.Enabled = false; + DirectDriver.Enabled = false; + } + + Menu.RefreshIndex(); + } + + private static void DriverMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) + { + if (selectedItem == DirectDriver) + { + if (Utils.DirectDriver.ValidateOptions(DirectOptions, PathManager.Paths[DirectDriver.Index], out Vehicle nearbyVehicle, out Waypoint targetWaypoint)) + { + Utils.DirectDriver.Direct(nearbyVehicle, PathManager.Paths[DirectDriver.Index], targetWaypoint); + } + } + + if (selectedItem == DismissDriver) + { + Utils.DismissDriver.Dismiss(DismissDriver.Index); + } + } + + private static void DriverMenu_OnMenuOpen(UIMenu menu) + { + var scrollerItems = new List { DirectOptions, DirectDriver, DismissDriver }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); + } + } +} From 7a5ffe331727107022a13010b54aeaa2fa5b0c78 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:03:48 -0600 Subject: [PATCH 027/112] Updated Export Path menu item description. --- SceneManager/Menus/EditPathMenu.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 6367f2a..40123dd 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.Drawing; +using System.Linq; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; +using SceneManager.Managers; using SceneManager.Menus; using SceneManager.Utils; @@ -14,7 +16,7 @@ namespace SceneManager internal static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path", false); private static UIMenuItem EditWaypoints { get; } = new UIMenuItem("Edit Waypoints"); private static UIMenuItem deletePath { get; } = new UIMenuItem("Delete Path"); - private static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Path"); + private static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Path", "Export path to ~b~plugins/SceneManager/Saved Paths"); internal static void Initialize() { @@ -28,13 +30,16 @@ namespace SceneManager internal static void BuildEditPathMenu() { + Menu.Clear(); + Menu.AddItem(DisablePath); Menu.AddItem(EditWaypoints); EditWaypoints.ForeColor = Color.Gold; - Menu.AddItem(deletePath); - deletePath.ForeColor = Color.Gold; Menu.AddItem(ExportPath); ExportPath.ForeColor = Color.Gold; + Menu.AddItem(deletePath); + deletePath.ForeColor = Color.Gold; + Menu.RefreshIndex(); } @@ -54,8 +59,9 @@ namespace SceneManager var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; currentPath.Delete(); PathManager.Paths.Remove(currentPath); - PathMainMenu.BuildPathMenu(); + PathMainMenu.Build(); PathMainMenu.Menu.Visible = true; + BarrierMenu.BuildMenu(); } if(selectedItem == ExportPath) From f415c2b69ee3d1b3715c06a5b330b4d8d57677cb Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:04:30 -0600 Subject: [PATCH 028/112] Fixed references from path name refactor --- SceneManager/Menus/EditWaypointMenu.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SceneManager/Menus/EditWaypointMenu.cs b/SceneManager/Menus/EditWaypointMenu.cs index 19fffe3..808b630 100644 --- a/SceneManager/Menus/EditWaypointMenu.cs +++ b/SceneManager/Menus/EditWaypointMenu.cs @@ -4,8 +4,9 @@ using System.Linq; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; -using SceneManager.Objects; +using SceneManager.Managers; using SceneManager.Utils; +using SceneManager.Waypoints; namespace SceneManager.Menus { @@ -38,7 +39,7 @@ namespace SceneManager.Menus internal static void BuildEditWaypointMenu() { Menu.MenuItems.Clear(); - var currentPath = PathManager.Paths[PathMainMenu.EditPath.Value-1]; + var currentPath = PathManager.Paths.FirstOrDefault(x => x.Name == PathMainMenu.EditPath.OptionText); Menu.AddItem(EditWaypoint = new UIMenuNumericScrollerItem("Edit Waypoint", "", currentPath.Waypoints.First().Number, currentPath.Waypoints.Last().Number, 1)); EditWaypoint.Index = 0; @@ -84,6 +85,7 @@ namespace SceneManager.Menus AddNewWaypoint.ForeColor = Color.Gold; EditPathMenu.Menu.Visible = false; + Menu.RefreshIndex(); Menu.Visible = true; } @@ -152,7 +154,8 @@ namespace SceneManager.Menus private static void EditWaypoint_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) { - var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + //var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + var currentPath = PathManager.Paths.FirstOrDefault(x => x.Name == PathMainMenu.EditPath.OptionText); if (selectedItem == UpdateWaypoint) { From 7fc1a4f8e6126e8bca06cc75fc95c0697f6fc6a0 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:04:47 -0600 Subject: [PATCH 029/112] Updated namespace references --- SceneManager/Menus/ImportPathMenu.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/SceneManager/Menus/ImportPathMenu.cs b/SceneManager/Menus/ImportPathMenu.cs index f4f3505..17f5bb9 100644 --- a/SceneManager/Menus/ImportPathMenu.cs +++ b/SceneManager/Menus/ImportPathMenu.cs @@ -1,11 +1,12 @@ using RAGENativeUI; using RAGENativeUI.Elements; using System.Drawing; -using SceneManager.Objects; using SceneManager.Utils; using System.Collections.Generic; using System.Linq; using Rage; +using SceneManager.Managers; +using SceneManager.Paths; namespace SceneManager.Menus { @@ -49,13 +50,11 @@ namespace SceneManager.Menus // When the user clicks on a path, that path needs to be added from Settings.importedPaths to PathMainMenu.paths Path importedPath = PathManager.ImportPath(Settings.ImportedPaths.FirstOrDefault(x => x.Name == selectedItem.Text)); importedPath.Load(); - Game.LogTrivial($"{selectedItem.Text} added to paths collection as path #{importedPath.Number}. Paths count: {PathManager.Paths.Count}"); + Game.LogTrivial($"{selectedItem.Text} added to paths collection. Paths count: {PathManager.Paths.Count}"); selectedItem.Enabled = false; - // Refresh path main menu - PathMainMenu.BuildPathMenu(); - PathMainMenu.Menu.RefreshIndex(); - Menu.Visible = true; + MenuManager.BuildMenus(); + PathMainMenu.Menu.Visible = true; } } } From 4e2fbe7afe186c7dc0376c5cca91a716dc1ab8f7 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:05:13 -0600 Subject: [PATCH 030/112] Added menu item for Driver Manager menu. Renamed menu items --- SceneManager/Menus/MainMenu.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/SceneManager/Menus/MainMenu.cs b/SceneManager/Menus/MainMenu.cs index 40b0bda..908dbc5 100644 --- a/SceneManager/Menus/MainMenu.cs +++ b/SceneManager/Menus/MainMenu.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Drawing; using SceneManager.Utils; using Rage; +using SceneManager.Managers; +using System.Linq; namespace SceneManager.Menus { @@ -14,24 +16,32 @@ namespace SceneManager.Menus internal static void Initialize() { - MenuManager.AddToMenuPool(Menu); + MenuManager.MenuPool.Add(Menu); Menu.OnMenuOpen += MainMenu_OnMenuOpen; } internal static void BuildMainMenu() { - var navigateToPathMenu = new UIMenuItem("Path Menu"); + Menu.Clear(); + + var navigateToPathMenu = new UIMenuItem("Manage Paths"); Menu.AddItem(navigateToPathMenu); navigateToPathMenu.ForeColor = Color.Gold; Menu.BindMenuToItem(PathMainMenu.Menu, navigateToPathMenu); - var navigateToBarrierMenu = new UIMenuItem("Barrier Menu"); + var navigateToDriverMenu = new UIMenuItem("Manage Drivers", "After you create a path, you will be able to direct drivers using this menu."); + Menu.AddItem(navigateToDriverMenu); + navigateToDriverMenu.ForeColor = Color.Gold; + Menu.BindMenuToItem(DriverMenu.Menu, navigateToDriverMenu); + navigateToDriverMenu.Enabled = PathManager.Paths.Count() > 0; + + var navigateToBarrierMenu = new UIMenuItem("Manage Barriers"); Menu.AddItem(navigateToBarrierMenu); navigateToBarrierMenu.ForeColor = Color.Gold; Menu.BindMenuToItem(BarrierMenu.Menu, navigateToBarrierMenu); - var navigateToSettingsMenu = new UIMenuItem("Settings Menu"); + var navigateToSettingsMenu = new UIMenuItem("Settings"); Menu.AddItem(navigateToSettingsMenu); navigateToSettingsMenu.ForeColor = Color.Gold; Menu.BindMenuToItem(SettingsMenu.Menu, navigateToSettingsMenu); From 1be5bea839604d0d7f614daa3ae74b30e5b291ac Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:05:35 -0600 Subject: [PATCH 031/112] Refactored driver options to separate menu --- SceneManager/Menus/PathMainMenu.cs | 72 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/SceneManager/Menus/PathMainMenu.cs b/SceneManager/Menus/PathMainMenu.cs index 817cdba..d7d8e59 100644 --- a/SceneManager/Menus/PathMainMenu.cs +++ b/SceneManager/Menus/PathMainMenu.cs @@ -4,8 +4,10 @@ using System.Linq; using Rage; using RAGENativeUI; using RAGENativeUI.Elements; -using SceneManager.Objects; +using SceneManager.Managers; +using SceneManager.Paths; using SceneManager.Utils; +using SceneManager.Waypoints; namespace SceneManager.Menus { @@ -14,14 +16,14 @@ namespace SceneManager.Menus private static int MAX_PATH_LIMIT { get; } = 10; internal static List ImportedPaths { get; } = new List(); private static string[] DismissOptions { get; } = new string[] { "From path", "From waypoint", "From world" }; - internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Manager Main Menu"); + internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Manager"); internal static UIMenuItem CreateNewPath { get; } = new UIMenuItem("Create New Path"); - internal static UIMenuListScrollerItem ImportPath { get; } = new UIMenuListScrollerItem("Import Path", "Import a saved path", ImportedPaths); + internal static UIMenuListScrollerItem ImportPath { get; } = new UIMenuListScrollerItem("Import Path", "Import a saved path from ~b~plugins/SceneManager/Saved Paths", ImportedPaths); internal static UIMenuItem DeleteAllPaths { get; } = new UIMenuItem("Delete All Paths"); - internal static UIMenuNumericScrollerItem EditPath { get; private set; } - internal static UIMenuListScrollerItem DirectOptions { get; } = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); - internal static UIMenuNumericScrollerItem DirectDriver { get; private set; } - internal static UIMenuListScrollerItem DismissDriver { get; } = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~AI will be released from the path\n~b~From waypoint: ~w~AI will skip their current waypoint task\n~b~From world: ~w~AI will be removed from the world.", DismissOptions); + internal static UIMenuListScrollerItem EditPath { get; private set; } + //internal static UIMenuListScrollerItem DirectOptions { get; } = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); + //internal static UIMenuListScrollerItem DirectDriver { get; private set; } + //internal static UIMenuListScrollerItem DismissDriver { get; } = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~Driver will be released from the path\n~b~From waypoint: ~w~Driver will skip their current waypoint task\n~b~From world: ~w~Driver will be removed from the world.", DismissOptions); internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Paths", false); internal static void Initialize() @@ -34,7 +36,7 @@ namespace SceneManager.Menus Menu.OnMenuOpen += PathMenu_OnMenuOpen; } - internal static void BuildPathMenu() + internal static void Build() { MenuManager.MenuPool.CloseAllMenus(); Menu.Clear(); @@ -43,20 +45,21 @@ namespace SceneManager.Menus CreateNewPath.ForeColor = Color.Gold; Menu.AddItem(ImportPath); ImportPath.ForeColor = Color.Gold; - ImportPath.Enabled = true; - Menu.AddItem(EditPath = new UIMenuNumericScrollerItem("Edit Path", "", 1, PathManager.Paths.Count, 1)); + ImportPath.Enabled = Settings.ImportedPaths.Count() > 0; + Menu.AddItem(EditPath = new UIMenuListScrollerItem("Edit Path", "Options to ~b~edit path waypoints~w~, ~b~disable the path~w~, ~b~export the path~w~, or ~b~delete the path~w~.", PathManager.Paths.Select(x => x.Name))); EditPath.ForeColor = Color.Gold; Menu.AddItem(DisableAllPaths); DisableAllPaths.Enabled = true; Menu.AddItem(DeleteAllPaths); DeleteAllPaths.Enabled = true; DeleteAllPaths.ForeColor = Color.Gold; - Menu.AddItem(DirectOptions); - Menu.AddItem(DirectDriver = new UIMenuNumericScrollerItem("Direct nearest driver to path", "", 1, PathManager.Paths.Count, 1)); // This must instantiate here because the Paths.Count value changes - DirectDriver.ForeColor = Color.Gold; - DirectDriver.Enabled = true; - Menu.AddItem(DismissDriver); - DismissDriver.ForeColor = Color.Gold; + //Menu.AddItem(DirectOptions); + //DirectOptions.Enabled = true; + //Menu.AddItem(DirectDriver = new UIMenuListScrollerItem("Direct nearest driver to path", "", PathManager.Paths.Select(x => x.Name))); // This must instantiate here because the Paths change + //DirectDriver.ForeColor = Color.Gold; + //DirectDriver.Enabled = true; + //Menu.AddItem(DismissDriver); + //DismissDriver.ForeColor = Color.Gold; if (PathManager.Paths.Count == MAX_PATH_LIMIT) { @@ -68,7 +71,8 @@ namespace SceneManager.Menus EditPath.Enabled = false; DeleteAllPaths.Enabled = false; DisableAllPaths.Enabled = false; - DirectDriver.Enabled = false; + //DirectOptions.Enabled = false; + //DirectDriver.Enabled = false; } if(Settings.ImportedPaths.Count == 0) { @@ -97,37 +101,39 @@ namespace SceneManager.Menus if (selectedItem == DeleteAllPaths) { - Utils.DeleteAllPaths.Delete(); + PathManager.DeleteAllPaths(); DisableAllPaths.Checked = false; - BuildPathMenu(); + Build(); Menu.Visible = true; + BarrierMenu.BuildMenu(); } - if (selectedItem == DirectDriver) - { - if(Utils.DirectDriver.ValidateOptions(DirectOptions, PathManager.Paths[DirectDriver.Index], out Vehicle nearbyVehicle, out Waypoint targetWaypoint)) - { - Utils.DirectDriver.Direct(nearbyVehicle, PathManager.Paths[DirectDriver.Index], targetWaypoint); - } - } + //if (selectedItem == DirectDriver) + //{ + // if(Utils.DirectDriver.ValidateOptions(DirectOptions, PathManager.Paths[DirectDriver.Index], out Vehicle nearbyVehicle, out Waypoint targetWaypoint)) + // { + // Utils.DirectDriver.Direct(nearbyVehicle, PathManager.Paths[DirectDriver.Index], targetWaypoint); + // } + //} - if (selectedItem == DismissDriver) - { - Utils.DismissDriver.Dismiss(DismissDriver.Index); - } + //if (selectedItem == DismissDriver) + //{ + // Utils.DismissDriver.Dismiss(DismissDriver.Index); + //} } private static void PathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) { if (checkboxItem == DisableAllPaths) { - TogglePaths.Toggle(DisableAllPaths.Checked); + PathManager.ToggleAllPaths(DisableAllPaths.Checked); } } private static void PathMenu_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { DirectOptions, DirectDriver, DismissDriver, EditPath }; + //var scrollerItems = new List { DirectOptions, DirectDriver, DismissDriver, EditPath }; + var scrollerItems = new List { EditPath }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } @@ -142,7 +148,7 @@ namespace SceneManager.Menus } else { - PathCreationMenu.BuildPathCreationMenu(); + //PathCreationMenu.BuildPathCreationMenu(); Menu.Visible = false; PathCreationMenu.Menu.Visible = true; } From 248c2ad30fdf3ef8cb46c8031913566fb24d2577 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:06:08 -0600 Subject: [PATCH 032/112] Updated menu item description --- SceneManager/Menus/SettingsMenu.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SceneManager/Menus/SettingsMenu.cs b/SceneManager/Menus/SettingsMenu.cs index 3340514..b205f22 100644 --- a/SceneManager/Menus/SettingsMenu.cs +++ b/SceneManager/Menus/SettingsMenu.cs @@ -4,6 +4,7 @@ using RAGENativeUI.Elements; using System; using System.Collections.Generic; using SceneManager.Utils; +using SceneManager.Managers; namespace SceneManager.Menus { @@ -15,12 +16,12 @@ namespace SceneManager.Menus internal static UIMenuCheckboxItem Hints { get; } = new UIMenuCheckboxItem("Enable Hints", Settings.EnableHints); private static SpeedUnits[] SpeedUnitsArray { get; } = { Utils.SpeedUnits.MPH, Utils.SpeedUnits.KPH }; internal static UIMenuListScrollerItem SpeedUnits { get; } = new UIMenuListScrollerItem("Speed Unit of Measure", "", new[] { Utils.SpeedUnits.MPH, Utils.SpeedUnits.KPH }); - internal static UIMenuItem SaveSettings { get; } = new UIMenuItem("Save settings to .ini", "Updates the plugin's .ini file with the current settings so the next time the plugin is loaded, it will use these settings."); + internal static UIMenuItem SaveSettings { get; } = new UIMenuItem("Save settings to .ini", "Updates the plugin's .ini file with the current settings. The next time the plugin is loaded, it will use these settings."); internal static void Initialize() { Menu.ParentMenu = MainMenu.Menu; - MenuManager.AddToMenuPool(Menu); + MenuManager.MenuPool.Add(Menu); Menu.OnCheckboxChange += SettingsMenu_OnCheckboxChange; Menu.OnItemSelect += SettingsMenu_OnItemSelected; From d552235d4bc35983f86395597f751618dc978e9f Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:06:21 -0600 Subject: [PATCH 033/112] Updated namespace references --- SceneManager/Utils/ConsoleCommands.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index 7ce9e59..8ae2301 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -2,9 +2,10 @@ using Rage.Attributes; using Rage.ConsoleCommands.AutoCompleters; using System.Linq; -using SceneManager.Objects; using System; using System.Collections.Generic; +using SceneManager.Managers; +using SceneManager.Paths; namespace SceneManager.Utils { From f66f348c63267ddcf758d08bd1a8fd9c926809ca Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:07:19 -0600 Subject: [PATCH 034/112] Updated namespace references --- SceneManager/EntryPoint.cs | 3 ++- SceneManager/Utils/DirectDriver.cs | 5 ++++- SceneManager/Utils/DismissDriver.cs | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/SceneManager/EntryPoint.cs b/SceneManager/EntryPoint.cs index f2bff6f..1ee02e6 100644 --- a/SceneManager/EntryPoint.cs +++ b/SceneManager/EntryPoint.cs @@ -3,6 +3,7 @@ using System.Reflection; using Rage; using SceneManager.Utils; using SceneManager.Menus; +using SceneManager.Managers; [assembly: Rage.Attributes.Plugin("Scene Manager", Author = "Rich", Description = "Control your scenes with custom AI pathing and traffic barrier management.", PrefersSingleInstance = true)] @@ -42,7 +43,7 @@ namespace SceneManager private static void TerminationHandler(object sender, EventArgs e) { BarrierMenu.Cleanup(); - DeleteAllPaths.Delete(); + PathManager.DeleteAllPaths(); Game.LogTrivial($"Plugin has shut down."); Game.DisplayNotification($"~o~Scene Manager ~r~[Terminated]\n~w~The plugin has shut down."); diff --git a/SceneManager/Utils/DirectDriver.cs b/SceneManager/Utils/DirectDriver.cs index a024260..03a0362 100644 --- a/SceneManager/Utils/DirectDriver.cs +++ b/SceneManager/Utils/DirectDriver.cs @@ -1,6 +1,9 @@ using Rage; using RAGENativeUI.Elements; -using SceneManager.Objects; +using SceneManager.CollectedPeds; +using SceneManager.Managers; +using SceneManager.Paths; +using SceneManager.Waypoints; using System.Linq; namespace SceneManager.Utils diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs index 69ebadf..6228119 100644 --- a/SceneManager/Utils/DismissDriver.cs +++ b/SceneManager/Utils/DismissDriver.cs @@ -1,5 +1,6 @@ using Rage; -using SceneManager.Objects; +using SceneManager.CollectedPeds; +using SceneManager.Managers; using System.Linq; namespace SceneManager.Utils From b2ce6f5598842513ac7aa943074afed135ad919e Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:07:34 -0600 Subject: [PATCH 035/112] Added Deleting state --- SceneManager/Utils/Enums.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SceneManager/Utils/Enums.cs b/SceneManager/Utils/Enums.cs index d1399b6..c604ac8 100644 --- a/SceneManager/Utils/Enums.cs +++ b/SceneManager/Utils/Enums.cs @@ -446,7 +446,8 @@ { Uninitialized, Creating, - Finished + Finished, + Deleting } internal enum SpeedUnits From 33bc15340d523d0efc3a76cfad263232bee6715c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:08:05 -0600 Subject: [PATCH 036/112] Added IsNearCollectorWaypoint and IsValidForPathCollection methods --- SceneManager/Utils/Extensions.cs | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 3258d46..6d7e889 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -1,4 +1,9 @@ using Rage; +using SceneManager.Managers; +using SceneManager.Paths; +using SceneManager.Waypoints; +using System; +using System.Linq; namespace SceneManager.Utils { @@ -110,5 +115,71 @@ namespace SceneManager.Utils return false; } } + + /// Determines if this vehicle is within the waypoint's collection range. + /// + internal static bool IsNearCollectorWaypoint(this Vehicle vehicle, Waypoint waypoint) + { + if(!waypoint.IsCollector) + { + return false; + } + + return vehicle.FrontPosition.DistanceTo2D(waypoint.Position) <= waypoint.CollectorRadius && Math.Abs(waypoint.Position.Z - vehicle.Position.Z) < 3; + } + + internal static bool IsValidForPathCollection(this Vehicle vehicle, Path path) + { + if (!vehicle) + { + return false; + } + + var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p.Number != path.Number && p.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle)); + if (vehicleCollectedOnAnotherPath) + { + return false; + } + + if (vehicle.Driver) + { + if (!vehicle.Driver.IsAlive) + { + Game.LogTrivial($"Vehicle's driver is dead."); + path.BlacklistedVehicles.Add(vehicle); + return false; + } + if (vehicle.IsPoliceVehicle && !vehicle.Driver.IsAmbient()) + { + Game.LogTrivial($"Vehicle is a non-ambient police vehicle."); + path.BlacklistedVehicles.Add(vehicle); + return false; + } + } + + if (vehicle != Game.LocalPlayer.Character.LastVehicle && (vehicle.IsCar || vehicle.IsBike || vehicle.IsBicycle || vehicle.IsQuadBike) && !vehicle.IsSirenOn && vehicle.IsEngineOn && vehicle.IsOnAllWheels && vehicle.Speed > 1 && !path.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle) && !path.BlacklistedVehicles.Contains(vehicle)) + { + if (!vehicle.HasDriver) + { + vehicle.CreateRandomDriver(); + while (!vehicle.HasDriver) + { + GameFiber.Yield(); + } + if(!vehicle || !vehicle.Driver) + { + return false; + } + + vehicle.Driver.IsPersistent = true; + vehicle.Driver.BlockPermanentEvents = true; + } + return true; + } + else + { + return false; + } + } } } From 7d1aa35f191a9f74338cf281c74812289f4cf15c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:08:18 -0600 Subject: [PATCH 037/112] Renamed PathXMLManager to Serializer --- SceneManager/Utils/Serializer.cs | 133 +++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 SceneManager/Utils/Serializer.cs diff --git a/SceneManager/Utils/Serializer.cs b/SceneManager/Utils/Serializer.cs new file mode 100644 index 0000000..da0bf3f --- /dev/null +++ b/SceneManager/Utils/Serializer.cs @@ -0,0 +1,133 @@ +using Rage; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Serialization; + +namespace SceneManager.Utils +{ + internal static class Serializer + { + private static Dictionary _serializerCache = new Dictionary(); + private static XmlSerializer _getOrCreateSerializer(XmlAttributeOverrides overrides = null) + { + if (_serializerCache.ContainsKey(typeof(T))) + { + Game.LogTrivialDebug("Serializer cache already contains " + typeof(T).Name); + return _serializerCache[typeof(T)]; + } + else + { + Game.LogTrivialDebug("Adding " + typeof(T).Name + " to serializer cache"); + Game.LogTrivialDebug("Overrides specified: " + (overrides != null)); + var s = new XmlSerializer(typeof(T), overrides); + _serializerCache.Add(typeof(T), s); + return s; + } + } + + public static void SaveToNode(string file, string node, string value) + { + XmlNode n = SelectNodeFromXml(file, node); + + if (n == null) throw new KeyNotFoundException($"{nameof(SaveToNode)}: specified node does not exists!"); + + n.InnerText = value; + var doc = new XmlDocument(); + doc.Save(file); + } + + public static string ReadFromNode(string file, string node) + { + return SelectNodeFromXml(file, node).InnerText; + } + + private static XmlNode SelectNodeFromXml(string filePath, string node) + { + if (!File.Exists(filePath)) throw new FileNotFoundException($"{nameof(SelectNodeFromXml)}(): specified file does not exist: {filePath}"); + + using (TextReader reader = new StreamReader(filePath)) + { + var doc = new XmlDocument(); + doc.Load(reader); + return doc.SelectSingleNode(node); + } + } + + public static List LoadAllXML(string dirPath, SearchOption searchOption = SearchOption.AllDirectories) + { + if (!Directory.Exists(dirPath)) throw new DirectoryNotFoundException($"{nameof(LoadAllXML)}(): specified directory could not be found: {dirPath}"); + + string[] files = Directory.GetFiles(dirPath, "*.xml", searchOption); + + List result = new List(); + + Array.ForEach(files, f => result.AddRange(LoadFromXML(f))); + + return result; + } + + public static void SaveToXML(List list, string filePath) + { + SaveItemToXML(list, filePath); + } + + public static void SaveItemToXML(T item, string path, XmlAttributeOverrides overrides) + { + Encoding utf8NoBom = new UTF8Encoding(false); + using (TextWriter writer = new StreamWriter(path, false, utf8NoBom)) + { + XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); + ns.Add("", ""); + + //new XmlSerializer(typeof(Objects.Path)).Serialize(writer, item); + _getOrCreateSerializer(overrides).Serialize(writer, item, ns); + } + } + + public static void SaveItemToXML(T item, string path) + { + SaveItemToXML(item, path, null); + } + + public static T LoadItemFromXML(string filePath, XmlAttributeOverrides overrides) + { + if (!File.Exists(filePath)) throw new FileNotFoundException($"{nameof(LoadItemFromXML)}(): specified file does not exist: {filePath}"); + + using (TextReader reader = new StreamReader(filePath)) + { + return (T)_getOrCreateSerializer(overrides).Deserialize(reader); + } + } + + public static T LoadItemFromXML(string filePath) + { + return LoadItemFromXML(filePath, null); + } + + public static void ModifyItemInXML(string filePath, Action modification) + { + T item = LoadItemFromXML(filePath); + modification(item); + SaveItemToXML(item, filePath); + } + + public static T GetSelectedListElementFromXml(string file, Func, T> selector) + { + List deserialized = LoadItemFromXML>(file); + return selector(deserialized); + } + + public static List LoadFromXML(string filePath) + { + return LoadItemFromXML>(filePath); + } + + public static void AppendToXML(T objectToAdd, string path) + { + ModifyItemInXML>(path, t => t.Add(objectToAdd)); + } + } +} From eb77107edf6ed2a3bc986c5abdad5cf4e09c88e1 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:09:21 -0600 Subject: [PATCH 038/112] Refactored user keypress logic, updated some method names to be more clear --- SceneManager/Utils/UserInput.cs | 77 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/SceneManager/Utils/UserInput.cs b/SceneManager/Utils/UserInput.cs index 529e97f..6ed9c56 100644 --- a/SceneManager/Utils/UserInput.cs +++ b/SceneManager/Utils/UserInput.cs @@ -3,6 +3,7 @@ using Rage; using Rage.Native; using RAGENativeUI; using RAGENativeUI.Elements; +using SceneManager.Managers; using SceneManager.Menus; using System.Collections.Generic; using System.Linq; @@ -13,55 +14,61 @@ namespace SceneManager.Utils // The only reason this class should change is to modify how user input is handled class UserInput { + private static bool _menuKeysPressed + { + get => (Settings.ModifierKey == Keys.None && Game.IsKeyDown(Settings.ToggleKey)) || + (Game.IsKeyDownRightNow(Settings.ModifierKey) && Game.IsKeyDown(Settings.ToggleKey)); + } + private static bool _menuControllerButtonsPressed + { + get => (Settings.ModifierButton == ControllerButtons.None && Game.IsControllerButtonDown(Settings.ToggleButton)) || + (Game.IsControllerButtonDownRightNow(Settings.ModifierButton) && Game.IsControllerButtonDown(Settings.ToggleButton)); + } + internal static Vector3 PlayerMousePosition { get => GetMousePositionInWorld(); } + internal static Vector3 PlayerMousePositionForBarrier { get => GetMousePositionInWorld(Settings.BarrierPlacementDistance); } + internal static void HandleKeyPress() - { + { while (true) { - bool isTextEntryOpen = (Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0); + GameFiber.Yield(); + + bool isTextEntryOpen = (NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() == 0); if (!isTextEntryOpen && MenuKeysPressed()) { + if (MenuManager.MenuPool.Any(x => x.Visible)) + { + foreach (UIMenu menu in MenuManager.MenuPool.Where(x => x.Visible)) + { + menu.Visible = !menu.Visible; + } + MenuManager.MenuPool.CloseAllMenus(); + continue; + } + Menus.MainMenu.DisplayMenu(); - GameFiber.StartNew(() => MenuManager.Update(), "Menu Processing Fiber"); + GameFiber.StartNew(() => MenuManager.ProcessMenus(), "Menu Processing Fiber"); } #if DEBUG if (MenuManager.MenuPool.IsAnyMenuOpen()) { - Game.DisplaySubtitle($"You are using a test build of Scene Manager. Please report any bugs/crashes in the Discord server."); + Game.DisplaySubtitle($"You are using a test build of ~y~Scene Manager~w~. Please report any ~r~bugs/crashes ~w~in the ~p~Discord ~w~server."); } #endif - GameFiber.Yield(); } } private static bool MenuKeysPressed() { - if (MenuKeysPressed()) + if (_menuKeysPressed || _menuControllerButtonsPressed) { return true; } return false; - - bool MenuKeysPressed() - { - if (MenuManager.AreMenusClosed() && - ((Settings.ModifierKey == Keys.None && Game.IsKeyDown(Settings.ToggleKey)) || - (Game.IsKeyDownRightNow(Settings.ModifierKey) && Game.IsKeyDown(Settings.ToggleKey)) || - (Settings.ModifierButton == ControllerButtons.None && Game.IsControllerButtonDown(Settings.ToggleButton)) || - (Game.IsControllerButtonDownRightNow(Settings.ModifierButton) && Game.IsControllerButtonDown(Settings.ToggleButton)))) - { - return true; - } - - return false; - } } - internal static Vector3 GetMousePosition { get { return GetMousePositionInWorld(); } } - - internal static Vector3 GetMousePositionForBarrier { get { return GetMousePositionInWorld(Settings.BarrierPlacementDistance); } } - private static Vector3 GetMousePositionInWorld(float maxDistance = 100f) { HitResult TracePlayerView(float maxTraceDistance = 100f, TraceFlags flags = TraceFlags.IntersectWorld) => TracePlayerView2(out Vector3 v1, out Vector3 v2, maxTraceDistance, flags); @@ -97,13 +104,13 @@ namespace SceneManager.Utils { while (menu.Visible) { - var selectedScroller = menu.MenuItems.Where(x => scrollerItems.Contains(x) && x.Selected && x.Enabled).FirstOrDefault(); + var selectedScroller = menu.MenuItems.FirstOrDefault(x => scrollerItems.Contains(x) && x.Selected && x.Enabled); if (selectedScroller != null) { OnWheelScroll(menu, selectedScroller, scrollerItems); } - if (Game.IsKeyDown(Keys.LButton) && Rage.Native.NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() != 0) + if (Game.IsKeyDown(Keys.LButton) && NativeFunction.Natives.UPDATE_ONSCREEN_KEYBOARD() != 0) { Keyboard.KeyDown(Keys.Enter); GameFiber.Wait(1); @@ -112,7 +119,7 @@ namespace SceneManager.Utils if (menu.SubtitleText.Contains("Path Creation Menu")) { - DrawWaypointMarker(); + DrawWaypointMarkerAtMousePosition(); } GameFiber.Yield(); } @@ -135,7 +142,7 @@ namespace SceneManager.Utils } if (menu.SubtitleText.Contains("Path Creation Menu")) { - DrawWaypointMarker(); + DrawWaypointMarkerAtMousePosition(); } GameFiber.Yield(); } @@ -187,25 +194,25 @@ namespace SceneManager.Utils } } - private static void DrawWaypointMarker() + private static void DrawWaypointMarkerAtMousePosition() { - var waypointPosition = GetMousePosition; + var waypointPosition = PlayerMousePosition; if (SettingsMenu.ThreeDWaypoints.Checked && PathCreationMenu.CollectorWaypoint.Checked) { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.CollectorRadius.Value * 2, (float)PathCreationMenu.CollectorRadius.Value * 2, 1f, 80, 130, 255, 80, false, false, 2, false, 0, 0, false); - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, 1f, 255, 185, 80, 80, false, false, 2, false, 0, 0, false); + NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.CollectorRadius.Value * 2, (float)PathCreationMenu.CollectorRadius.Value * 2, 1f, 80, 130, 255, 80, false, false, 2, false, 0, 0, false); + NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, (float)PathCreationMenu.SpeedZoneRadius.Value * 2, 1f, 255, 185, 80, 80, false, false, 2, false, 0, 0, false); } else if (PathCreationMenu.StopWaypoint.Checked) { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 255, 65, 65, 80, false, false, 2, false, 0, 0, false); + NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 255, 65, 65, 80, false, false, 2, false, 0, 0, false); } else { - Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false); + NativeFunction.Natives.DRAW_MARKER(1, waypointPosition, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false); } } - internal static string GetFileName(string windowTitle, string defaultText, int maxLength) + internal static string PromptPlayerForFileName(string windowTitle, string defaultText, int maxLength) { NativeFunction.Natives.DISABLE_ALL_CONTROL_ACTIONS(2); From ea3c3acff0f1ee1c4e0312720a8cda973f4ede01 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:09:35 -0600 Subject: [PATCH 039/112] Updated object reference --- SceneManager/Settings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Settings.cs b/SceneManager/Settings.cs index 2e998a2..9d68065 100644 --- a/SceneManager/Settings.cs +++ b/SceneManager/Settings.cs @@ -35,7 +35,7 @@ namespace SceneManager // Barriers internal static Dictionary Barriers { get; private set; } = new Dictionary(); - internal static List ImportedPaths { get; private set; } = new List(); + internal static List ImportedPaths { get; private set; } = new List(); internal static void LoadSettings() { @@ -99,7 +99,7 @@ namespace SceneManager foreach (string file in savedPaths) { Game.LogTrivial($"File: {Path.GetFileName(file)}"); - var importedPath = PathXMLManager.LoadItemFromXML(SAVED_PATHS_DIRECTORY + Path.GetFileName(file)); + var importedPath = Serializer.LoadItemFromXML(SAVED_PATHS_DIRECTORY + Path.GetFileName(file)); importedPath.Name = Path.GetFileNameWithoutExtension(file); ImportedPaths.Add(importedPath); } From 529f294e1a9e9baf84ef189affa1d629d41fe50e Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Fri, 7 May 2021 04:12:59 -0600 Subject: [PATCH 040/112] Added DeleteVehicle and DeletePed commands --- SceneManager/Utils/ConsoleCommands.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index 8ae2301..a5f5595 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -49,5 +49,23 @@ namespace SceneManager.Utils } } } + + [ConsoleCommand("DeleteVehicle")] + internal static void Command_DeleteVehicle([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterVehicle), Name = "Vehicle")] Vehicle vehicle) + { + if (vehicle) + { + vehicle.Delete(); + } + } + + [ConsoleCommand("DeletePed")] + internal static void Command_DeletePed([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterPed), Name = "Ped")] Ped ped) + { + if (ped && ped != Game.LocalPlayer.Character) + { + ped.Delete(); + } + } } } From 8d2ba32c2b47c3ae0273a6147f27cc9fbdcfd276 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 9 May 2021 11:56:46 -0600 Subject: [PATCH 041/112] Rename method for consistency --- SceneManager/Managers/BarrierManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Managers/BarrierManager.cs b/SceneManager/Managers/BarrierManager.cs index 8dd6bbb..634ce2f 100644 --- a/SceneManager/Managers/BarrierManager.cs +++ b/SceneManager/Managers/BarrierManager.cs @@ -62,7 +62,7 @@ namespace SceneManager.Managers internal static void UpdatePlaceholderBarrierPosition() { - DisableBarrierMenuOptionsIfShadowConeTooFar(); + DisableBarrierMenuOptionsIfPlaceholderTooFar(); if (PlaceholderBarrier) { PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; @@ -71,7 +71,7 @@ namespace SceneManager.Managers //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); } - void DisableBarrierMenuOptionsIfShadowConeTooFar() + void DisableBarrierMenuOptionsIfPlaceholderTooFar() { if (!PlaceholderBarrier && UserInput.PlayerMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) { From 6a933f82d33b90b08e30a474538132368c269eb0 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 9 May 2021 11:57:11 -0600 Subject: [PATCH 042/112] Removed unused code. Changed ImportPath to UIMenuItem --- SceneManager/Menus/PathMainMenu.cs | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/SceneManager/Menus/PathMainMenu.cs b/SceneManager/Menus/PathMainMenu.cs index d7d8e59..790668a 100644 --- a/SceneManager/Menus/PathMainMenu.cs +++ b/SceneManager/Menus/PathMainMenu.cs @@ -14,16 +14,11 @@ namespace SceneManager.Menus internal static class PathMainMenu { private static int MAX_PATH_LIMIT { get; } = 10; - internal static List ImportedPaths { get; } = new List(); - private static string[] DismissOptions { get; } = new string[] { "From path", "From waypoint", "From world" }; internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Manager"); internal static UIMenuItem CreateNewPath { get; } = new UIMenuItem("Create New Path"); - internal static UIMenuListScrollerItem ImportPath { get; } = new UIMenuListScrollerItem("Import Path", "Import a saved path from ~b~plugins/SceneManager/Saved Paths", ImportedPaths); + internal static UIMenuItem ImportPath { get; } = new UIMenuItem("Import Path", "Import a saved path from ~b~plugins/SceneManager/Saved Paths"); internal static UIMenuItem DeleteAllPaths { get; } = new UIMenuItem("Delete All Paths"); internal static UIMenuListScrollerItem EditPath { get; private set; } - //internal static UIMenuListScrollerItem DirectOptions { get; } = new UIMenuListScrollerItem("Direct driver to path's", "", new[] { "First waypoint", "Nearest waypoint" }); - //internal static UIMenuListScrollerItem DirectDriver { get; private set; } - //internal static UIMenuListScrollerItem DismissDriver { get; } = new UIMenuListScrollerItem("Dismiss nearest driver", $"~b~From path: ~w~Driver will be released from the path\n~b~From waypoint: ~w~Driver will skip their current waypoint task\n~b~From world: ~w~Driver will be removed from the world.", DismissOptions); internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Paths", false); internal static void Initialize() @@ -53,13 +48,6 @@ namespace SceneManager.Menus Menu.AddItem(DeleteAllPaths); DeleteAllPaths.Enabled = true; DeleteAllPaths.ForeColor = Color.Gold; - //Menu.AddItem(DirectOptions); - //DirectOptions.Enabled = true; - //Menu.AddItem(DirectDriver = new UIMenuListScrollerItem("Direct nearest driver to path", "", PathManager.Paths.Select(x => x.Name))); // This must instantiate here because the Paths change - //DirectDriver.ForeColor = Color.Gold; - //DirectDriver.Enabled = true; - //Menu.AddItem(DismissDriver); - //DismissDriver.ForeColor = Color.Gold; if (PathManager.Paths.Count == MAX_PATH_LIMIT) { @@ -71,8 +59,6 @@ namespace SceneManager.Menus EditPath.Enabled = false; DeleteAllPaths.Enabled = false; DisableAllPaths.Enabled = false; - //DirectOptions.Enabled = false; - //DirectDriver.Enabled = false; } if(Settings.ImportedPaths.Count == 0) { @@ -107,19 +93,6 @@ namespace SceneManager.Menus Menu.Visible = true; BarrierMenu.BuildMenu(); } - - //if (selectedItem == DirectDriver) - //{ - // if(Utils.DirectDriver.ValidateOptions(DirectOptions, PathManager.Paths[DirectDriver.Index], out Vehicle nearbyVehicle, out Waypoint targetWaypoint)) - // { - // Utils.DirectDriver.Direct(nearbyVehicle, PathManager.Paths[DirectDriver.Index], targetWaypoint); - // } - //} - - //if (selectedItem == DismissDriver) - //{ - // Utils.DismissDriver.Dismiss(DismissDriver.Index); - //} } private static void PathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked) @@ -132,7 +105,6 @@ namespace SceneManager.Menus private static void PathMenu_OnMenuOpen(UIMenu menu) { - //var scrollerItems = new List { DirectOptions, DirectDriver, DismissDriver, EditPath }; var scrollerItems = new List { EditPath }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); } From 277a03edf416978e04632171478440c842440640 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 9 May 2021 11:57:17 -0600 Subject: [PATCH 043/112] Updated version --- SceneManager/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Properties/AssemblyInfo.cs b/SceneManager/Properties/AssemblyInfo.cs index b02b489..3e03168 100644 --- a/SceneManager/Properties/AssemblyInfo.cs +++ b/SceneManager/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.2.2")] -[assembly: AssemblyFileVersion("2.2.2.2")] +[assembly: AssemblyVersion("2.2.2.3")] +[assembly: AssemblyFileVersion("2.2.2.3")] From ff302d998db2582a664d293f941ef05f8d2f7f39 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 9 May 2021 11:57:45 -0600 Subject: [PATCH 044/112] Added null check for vehicle being checked for collection --- SceneManager/Utils/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 6d7e889..bc6e61f 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -162,7 +162,7 @@ namespace SceneManager.Utils if (!vehicle.HasDriver) { vehicle.CreateRandomDriver(); - while (!vehicle.HasDriver) + while (vehicle && !vehicle.HasDriver) { GameFiber.Yield(); } From 91aaf9b7f2f422fc5a2e1df94a0d88711d21349c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 9 May 2021 11:59:25 -0600 Subject: [PATCH 045/112] Added method to delete barriers when path is deleted. --- SceneManager/Paths/Path.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index 20bb91c..e851e00 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -224,6 +224,7 @@ namespace SceneManager.Paths State = State.Deleting; DismissCollectedDrivers(); RemoveWaypoints(); + RemoveBarriers(); Game.LogTrivial($"Path {Number} deleted."); } @@ -254,5 +255,13 @@ namespace SceneManager.Paths Waypoints.ForEach(x => x.Delete()); Waypoints.Clear(); } + + private void RemoveBarriers() + { + foreach(Barrier barrier in Barriers.Where(x => x.IsValid())) + { + barrier.Delete(); + } + } } } From 14b94fe19f05840660358c55d077e3320f2662ea Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:36:45 -0600 Subject: [PATCH 046/112] Added Path property. Removed Rage.Object inheritance --- SceneManager/Barriers/Barrier.cs | 66 +++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/SceneManager/Barriers/Barrier.cs b/SceneManager/Barriers/Barrier.cs index c8a9a50..dfd26c1 100644 --- a/SceneManager/Barriers/Barrier.cs +++ b/SceneManager/Barriers/Barrier.cs @@ -1,5 +1,6 @@ using Rage; using SceneManager.Managers; +using SceneManager.Paths; using SceneManager.Utils; namespace SceneManager.Barriers @@ -14,26 +15,66 @@ namespace SceneManager.Barriers public bool Immobile { get; set; } public bool LightsEnabled { get; set; } public int TextureVariation { get; set; } + internal Path Path { get; set; } public PoolHandle Handle => ((IHandleable)_object).Handle; private Barrier() { } - internal Barrier(string modelName, Vector3 position, float heading, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) + internal Barrier(Barrier obj, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) { - ModelName = modelName; - Position = position; - Heading = heading; + ModelName = obj.ModelName; + Position = obj.Position; + Heading = obj.Heading; Invincible = invincible; Immobile = immobile; TextureVariation = textureVariation; LightsEnabled = lightsEnabled; + if (obj.IsValid()) + { + obj.Delete(); + } + _object = new Object(ModelName, Position, Heading); - if (BarrierManager.PlaceholderBarrier) + _object.SetPositionWithSnap(Position); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); + + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + if (Invincible) { - _object.SetPositionWithSnap(BarrierManager.PlaceholderBarrier.Position); + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); + if (ModelName != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); + } } + _object.IsPositionFrozen = Immobile; + + if (Settings.EnableAdvancedBarricadeOptions) + { + SetAdvancedOptions(); + } + } + + internal Barrier(Object obj, bool invincible, bool immobile, int textureVariation = 0, bool lightsEnabled = false) + { + ModelName = obj.Model.Name; + Position = obj.Position; + Heading = obj.Heading; + Invincible = invincible; + Immobile = immobile; + TextureVariation = textureVariation; + LightsEnabled = lightsEnabled; + if(BarrierManager.PlaceholderBarrier) + { + BarrierManager.PlaceholderBarrier.Delete(); + } + + _object = new Object(ModelName, Position, Heading); + + _object.SetPositionWithSnap(Position); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); if (Invincible) @@ -73,8 +114,9 @@ namespace SceneManager.Barriers } } - internal void LoadFromImport() + internal void LoadFromImport(Path path) { + Path = path; Game.LogTrivial($"===== BARRIER DATA ====="); Game.LogTrivial($"Model: {ModelName}"); Game.LogTrivial($"Position: {Position}"); @@ -83,18 +125,22 @@ namespace SceneManager.Barriers Game.LogTrivial($"Immobile: {Immobile}"); Game.LogTrivial($"LightsEnabled: {LightsEnabled}"); Game.LogTrivial($"Texture Variation: {TextureVariation}"); - var barrier = new Barrier(ModelName, Position, Heading, Invincible, Immobile, TextureVariation, LightsEnabled); + var barrier = new Barrier(this, Invincible, Immobile, TextureVariation, LightsEnabled); + Path.Barriers.Add(barrier); BarrierManager.Barriers.Add(barrier); } public void Delete() { - ((IDeletable)_object).Delete(); + if (_object) + { + ((IDeletable)_object).Delete(); + } } public bool IsValid() { - return ((IHandleable)_object).IsValid(); + return _object != null; } public bool Equals(IHandleable other) From 98dba8d6050ec4d72a4a84374f3cb7ca7cc2890d Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:37:02 -0600 Subject: [PATCH 047/112] Updated log message --- SceneManager/CollectedPeds/CollectedPed.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/CollectedPeds/CollectedPed.cs b/SceneManager/CollectedPeds/CollectedPed.cs index cb3b346..84ca437 100644 --- a/SceneManager/CollectedPeds/CollectedPed.cs +++ b/SceneManager/CollectedPeds/CollectedPed.cs @@ -23,7 +23,7 @@ namespace SceneManager.CollectedPeds Path = path; CurrentWaypoint = waypoint; SetPersistence(); - Game.LogTrivial($"Added {CurrentVehicle.Model.Name} to collection from path {Path.Number} waypoint {waypoint.Number}."); + Game.LogTrivial($"Added {CurrentVehicle.Model.Name} to collection from path {Path.Number} waypoint {CurrentWaypoint.Number}."); GameFiber.StartNew(() => AssignWaypointTasks(), "Task Assignment Fiber"); } @@ -103,7 +103,7 @@ namespace SceneManager.CollectedPeds { 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)"); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path {Path.Number} waypoint {CurrentWaypoint.Number} (directed)"); Tasks.DriveToPosition(CurrentWaypoint.Position, CurrentWaypoint.Speed, (VehicleDrivingFlags)CurrentWaypoint.DrivingFlagType, acceptedDistance); LoopWhileDrivingToDirectedWaypoint(); From 1889bf83ca77cd434e70ca0db3de70cc2375fd44 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:38:39 -0600 Subject: [PATCH 048/112] Added ability to add unassigned barriers to a designated path --- SceneManager/Managers/BarrierManager.cs | 49 ++++++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/SceneManager/Managers/BarrierManager.cs b/SceneManager/Managers/BarrierManager.cs index 634ce2f..7b27719 100644 --- a/SceneManager/Managers/BarrierManager.cs +++ b/SceneManager/Managers/BarrierManager.cs @@ -21,8 +21,8 @@ namespace SceneManager.Managers PlaceholderBarrier.Delete(); } - var barrierKey = Settings.Barriers.Where(x => x.Key == BarrierMenu.BarrierList.SelectedItem).FirstOrDefault().Key; - var barrierValue = Settings.Barriers[barrierKey].Name; + var barrierKey = Settings.BarrierModels.Where(x => x.Key == BarrierMenu.BarrierList.SelectedItem).FirstOrDefault().Key; + var barrierValue = Settings.BarrierModels[barrierKey].Name; PlaceholderBarrier = new Object(barrierValue, UserInput.PlayerMousePositionForBarrier, BarrierMenu.RotateBarrier.Value); if (!PlaceholderBarrier) { @@ -67,7 +67,7 @@ namespace SceneManager.Managers { PlaceholderBarrier.Heading = BarrierMenu.RotateBarrier.Value; PlaceholderBarrier.Position = UserInput.PlayerMousePositionForBarrier; - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); //Rage.Native.NativeFunction.Natives.SET_ENTITY_TRAFFICLIGHT_OVERRIDE(shadowBarrier, setBarrierTrafficLight.Index); } @@ -105,12 +105,10 @@ namespace SceneManager.Managers { if (PlaceholderBarrier) { - //UpdatePlaceholderBarrierPosition(); UpdatePlaceholderBarrierPosition(); } else if (UserInput.PlayerMousePositionForBarrier.DistanceTo2D(Game.LocalPlayer.Character.Position) <= Settings.BarrierPlacementDistance) { - //CreatePlaceholderBarrier(); CreatePlaceholderBarrier(); } } @@ -140,10 +138,10 @@ namespace SceneManager.Managers } else { - //var obj = new Object(PlaceholderBarrier.Model, PlaceholderBarrier.Position, BarrierMenu.RotateBarrier.Value); - barrier = new Barrier(PlaceholderBarrier.Model.Name, PlaceholderBarrier.Position, PlaceholderBarrier.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked, BarrierMenu.BarrierTexture.Value, BarrierMenu.SetBarrierLights.Checked); + barrier = new Barrier(PlaceholderBarrier, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked, BarrierMenu.BarrierTexture.Value, BarrierMenu.SetBarrierLights.Checked); Barriers.Add(barrier); + BarrierMenu.AddUnassignedToPath.Enabled = true; BarrierMenu.RemoveBarrierOptions.Enabled = true; BarrierMenu.ResetBarriers.Enabled = true; } @@ -175,10 +173,12 @@ namespace SceneManager.Managers } }, "Spawn Flare Fiber"); - //var obj = new Object(flare.Model, flare.Position, flare.Heading); - barrier = new Barrier(flare.Model.Name, flare.Position, flare.Heading, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked); + barrier = new Barrier(flare, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked); Barriers.Add(barrier); + + BarrierMenu.AddUnassignedToPath.Enabled = true; BarrierMenu.RemoveBarrierOptions.Enabled = true; + BarrierMenu.ResetBarriers.Enabled = true; } } @@ -189,7 +189,7 @@ namespace SceneManager.Managers { case 0: var barrierToRemove = Barriers[Barriers.Count - 1]; - path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(barrierToRemove)); + path = PathManager.Paths.FirstOrDefault(x => x != null && x.Barriers.Contains(barrierToRemove)); if(path != null) { path.Barriers.Remove(barrierToRemove); @@ -202,7 +202,7 @@ namespace SceneManager.Managers var nearestBarrier = Barriers.OrderBy(b => b.DistanceTo2D(Game.LocalPlayer.Character)).FirstOrDefault(); if (nearestBarrier != null) { - path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(nearestBarrier)); + path = PathManager.Paths.FirstOrDefault(x => x != null && x.Barriers.Contains(nearestBarrier)); if (path != null) { path.Barriers.Remove(nearestBarrier); @@ -215,7 +215,7 @@ namespace SceneManager.Managers case 2: foreach (Barrier barrier in Barriers) { - path = PathManager.Paths.FirstOrDefault(x => x.Barriers.Contains(barrier)); + path = PathManager.Paths.FirstOrDefault(x => x != null && x.Barriers.Contains(barrier)); if (path != null) { path.Barriers.Remove(barrier); @@ -230,6 +230,7 @@ namespace SceneManager.Managers break; } + BarrierMenu.AddUnassignedToPath.Enabled = Barriers.Any(x => x.Path == null); BarrierMenu.RemoveBarrierOptions.Enabled = Barriers.Count != 0; BarrierMenu.ResetBarriers.Enabled = Barriers.Count != 0; } @@ -241,8 +242,7 @@ namespace SceneManager.Managers var currentBarriers = Barriers.Where(b => b.ModelName != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash foreach (Barrier barrier in currentBarriers) { - //var obj = new Object(barrier.ModelName, barrier.Position, barrier.Heading); - var newBarrier = new Barrier(barrier.ModelName, barrier.Position, barrier.Heading, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled); + var newBarrier = new Barrier(barrier, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled); Barriers.Add(newBarrier); if (barrier.IsValid()) @@ -262,5 +262,26 @@ namespace SceneManager.Managers PlaceholderBarrier.Position = UserInput.PlayerMousePositionForBarrier; Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(PlaceholderBarrier); } + + internal static void AddBarrierToPath() + { + var unassignedBarriers = Barriers.Where(x => x.Path == null); + if(unassignedBarriers.Count() == 0) + { + Game.LogTrivial($"There are no unassigned barriers."); + return; + } + + var pathToAssignTo = PathManager.Paths.First(x => x.Name == BarrierMenu.AddUnassignedToPath.OptionText); + foreach (Barrier barrier in unassignedBarriers) + { + pathToAssignTo.Barriers.Add(barrier); + } + + Game.LogTrivial($"Added {unassignedBarriers.Count()} unassigned barrier to {pathToAssignTo.Name}"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Barriers]\n~w~Assigned ~b~{unassignedBarriers.Count()} ~w~barrier(s) to ~b~{pathToAssignTo.Name}~w~."); + + BarrierMenu.AddUnassignedToPath.Enabled = false; + } } } From 2603752cfeff3eebc9be72c8888a48f7abdec0e5 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:39:20 -0600 Subject: [PATCH 049/112] Reordered menu build order. Added Import and Export path menu build methods. --- SceneManager/Managers/MenuManager.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/SceneManager/Managers/MenuManager.cs b/SceneManager/Managers/MenuManager.cs index d6500be..e14454d 100644 --- a/SceneManager/Managers/MenuManager.cs +++ b/SceneManager/Managers/MenuManager.cs @@ -16,9 +16,10 @@ namespace SceneManager.Managers { MainMenu.Initialize(); SettingsMenu.Initialize(); + ImportPathMenu.Initialize(); PathMainMenu.Initialize(); PathCreationMenu.Initialize(); - ImportPathMenu.Initialize(); + ExportPathMenu.Initialize(); DriverMenu.Initialize(); BarrierMenu.Initialize(); EditPathMenu.Initialize(); @@ -40,14 +41,15 @@ namespace SceneManager.Managers internal static void BuildMenus() { - MainMenu.BuildMainMenu(); - SettingsMenu.BuildSettingsMenu(); + MainMenu.Build(); + SettingsMenu.Build(); + ImportPathMenu.Build(); + ExportPathMenu.Build(); DriverMenu.Build(); PathMainMenu.Build(); - PathCreationMenu.BuildPathCreationMenu(); - ImportPathMenu.BuildImportMenu(); - EditPathMenu.BuildEditPathMenu(); - BarrierMenu.BuildMenu(); + PathCreationMenu.Build(); + EditPathMenu.Build(); + BarrierMenu.Build(); } internal static void ColorMenuItems() From 13a448c855a01bba0ce846c2ad0db8f72916eb75 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:40:25 -0600 Subject: [PATCH 050/112] Added import/export functionality. --- SceneManager/Managers/PathManager.cs | 217 +++++++++++++++------------ 1 file changed, 120 insertions(+), 97 deletions(-) diff --git a/SceneManager/Managers/PathManager.cs b/SceneManager/Managers/PathManager.cs index 74a9ceb..280f196 100644 --- a/SceneManager/Managers/PathManager.cs +++ b/SceneManager/Managers/PathManager.cs @@ -1,22 +1,24 @@ using Rage; using SceneManager.Menus; -using SceneManager.Paths; using SceneManager.Utils; using SceneManager.Waypoints; +using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Xml.Serialization; namespace SceneManager.Managers { internal class PathManager { - internal static List Paths { get; } = new List(10); + internal static Paths.Path[] Paths { get; } = new Paths.Path[10]; + internal static Dictionary> ImportedPaths { get; } = new Dictionary>(); - internal static Path ImportPath(Path importedPath) + internal static Paths.Path ImportPath(Paths.Path importedPath) { importedPath.State = State.Creating; - - var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State == State.Uninitialized)) + 1; // != State.Creating + var firstVacantIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); if (firstVacantIndex < 0) { firstVacantIndex = 0; @@ -24,10 +26,10 @@ namespace SceneManager.Managers var pathNumber = firstVacantIndex + 1; importedPath.Number = pathNumber; - Paths.Insert(firstVacantIndex, importedPath); + Paths[firstVacantIndex] = importedPath; - Game.LogTrivial($"Importing path {importedPath.Number} at Paths index {firstVacantIndex}"); - Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Path {importedPath.Number} import started."); + Game.LogTrivial($"Importing {importedPath.Name} at Paths index {firstVacantIndex}"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Importing path: ~b~{importedPath.Name} ~w~."); return importedPath; } @@ -35,46 +37,52 @@ namespace SceneManager.Managers internal static void ExportPath() { var currentPath = Paths[PathMainMenu.EditPath.Index]; - // Reference PNWParks's UserInput class from LiveLights - var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100) + ".xml"; - // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) - if (string.IsNullOrWhiteSpace(filename)) + // If the path is in the import menu, autosave with the same name. + if(ImportPathMenu.Menu.MenuItems.Any(x=> x.Text == currentPath.Name)) { - Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - return; + Game.LogTrivial($"Autosaving {currentPath.Name}"); + currentPath.Save(); } - Game.LogTrivial($"Filename: {filename}"); - currentPath.Save(filename); - currentPath.Name = filename.Remove(filename.Length - 4); - Game.LogTrivial($"Path name: {currentPath.Name}"); - Game.LogTrivial($"Exporting path {currentPath.Number}"); - Game.DisplayNotification($"~o~Scene Manager ~y~[Exporting]\n~w~Path {currentPath.Number} exported."); - Settings.ImportPaths(); + else + { + // Reference PNWParks's UserInput class from LiveLights + var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + + // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) + if (string.IsNullOrWhiteSpace(filename)) + { + Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + return; + } + + Game.LogTrivial($"Filename: {filename}"); + currentPath.Name = filename; + currentPath.Save(); + } + PathMainMenu.ImportPath.Enabled = true; - ImportPathMenu.BuildImportMenu(); + ImportPathMenu.Build(); PathMainMenu.Build(); + BarrierMenu.Build(); PathMainMenu.Menu.Visible = true; } - internal static Path InitializeNewPath() + internal static Paths.Path InitializeNewPath() { PathCreationMenu.PathCreationState = State.Creating; - var firstVacantIndex = Paths.IndexOf(Paths.FirstOrDefault(x => x.State != State.Creating)) + 1; - if(firstVacantIndex < 0) - { - firstVacantIndex = 0; - } - var pathNumber = firstVacantIndex + 1; + Paths.Path newPath = new Paths.Path(); + var firstEmptyIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); + Game.LogTrivial($"First empty index: {firstEmptyIndex}"); + Paths[firstEmptyIndex] = newPath; + newPath.Name = newPath.Number.ToString(); - Path newPath = new Path(pathNumber, State.Creating); - Paths.Insert(firstVacantIndex, newPath); - - Game.LogTrivial($"Creating path {newPath.Number} at Paths index {firstVacantIndex}"); - Game.DisplayNotification($"~o~Scene Manager ~y~[Creating]\n~w~Path {newPath.Number} started."); + PathMainMenu.CreateNewPath.Text = $"Continue Creating Path {newPath.Name}"; + Game.LogTrivial($"Creating path {newPath.Name} at Paths[{firstEmptyIndex}]"); + Game.DisplayNotification($"~o~Scene Manager ~y~[Creating]\n~w~Path ~b~{newPath.Name} ~w~started."); PathCreationMenu.RemoveLastWaypoint.Enabled = false; PathCreationMenu.EndPathCreation.Enabled = false; @@ -82,46 +90,23 @@ namespace SceneManager.Managers return newPath; } - internal static void AddWaypoint(Path currentPath) - { - var waypointNumber = currentPath.Waypoints.Count + 1; - DrivingFlagType drivingFlag = PathCreationMenu.DirectWaypoint.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; - Waypoint newWaypoint; - if (PathCreationMenu.CollectorWaypoint.Checked) - { - newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(PathCreationMenu.WaypointSpeed.Value), drivingFlag, PathCreationMenu.StopWaypoint.Checked, true, PathCreationMenu.CollectorRadius.Value, PathCreationMenu.SpeedZoneRadius.Value); - } - else - { - newWaypoint = new Waypoint(currentPath, waypointNumber, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(PathCreationMenu.WaypointSpeed.Value), drivingFlag, PathCreationMenu.StopWaypoint.Checked); - } - currentPath.Waypoints.Add(newWaypoint); - Game.LogTrivial($"Path {currentPath.Number} Waypoint {waypointNumber} added [Driving style: {drivingFlag} | Stop waypoint: {newWaypoint.IsStopWaypoint} | Speed: {newWaypoint.Speed} | Collector: {newWaypoint.IsCollector}]"); - - if(currentPath.Waypoints.Count == 1) - { - PathMainMenu.CreateNewPath.Text = $"Continue Creating Path {currentPath.Number}"; - } - } - - internal static void AddNewEditWaypoint(Path currentPath) + internal static void AddNewEditWaypoint(Paths.Path currentPath) { DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; if (EditWaypointMenu.CollectorWaypoint.Checked) { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked, true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value)); + currentPath.Waypoints.Add(new Waypoint(currentPath, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked, true, EditWaypointMenu.ChangeCollectorRadius.Value, EditWaypointMenu.ChangeSpeedZoneRadius.Value)); } else { - currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked)); + currentPath.Waypoints.Add(new Waypoint(currentPath, UserInput.PlayerMousePosition, ConvertDriveSpeedForWaypoint(EditWaypointMenu.ChangeWaypointSpeed.Value), drivingFlag, EditWaypointMenu.StopWaypointType.Checked)); } Game.LogTrivial($"New waypoint (#{currentPath.Waypoints.Last().Number}) added."); } internal static void UpdateWaypoint() { - //var currentPath = Paths[PathMainMenu.EditPath.Index]; var currentPath = Paths.FirstOrDefault(x => x.Name == PathMainMenu.EditPath.OptionText); var currentWaypoint = currentPath.Waypoints[EditWaypointMenu.EditWaypoint.Index]; DrivingFlagType drivingFlag = EditWaypointMenu.DirectWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; @@ -148,21 +133,14 @@ namespace SceneManager.Managers return convertedSpeed; } - internal static void RemoveWaypoint(Path currentPath) - { - Waypoint lastWaypoint = currentPath.Waypoints.Last(); - lastWaypoint.Delete(); - currentPath.Waypoints.Remove(lastWaypoint); - } - - internal static void RemoveEditWaypoint(Path currentPath) + internal static void RemoveEditWaypoint(Paths.Path currentPath) { var currentWaypoint = currentPath.Waypoints[EditWaypointMenu.EditWaypoint.Index]; if (currentPath.Waypoints.Count == 1) { Game.LogTrivial($"Deleting the last waypoint from the path."); currentPath.Delete(); - Paths.Remove(currentPath); + Paths[Array.IndexOf(Paths, currentPath)] = null; PathMainMenu.Build(); EditWaypointMenu.Menu.Visible = false; @@ -178,7 +156,7 @@ namespace SceneManager.Managers DefaultWaypointToCollector(currentPath); } - private static void DefaultWaypointToCollector(Path currentPath) + private static void DefaultWaypointToCollector(Paths.Path currentPath) { if (currentPath.Waypoints.Count == 1) { @@ -192,27 +170,7 @@ namespace SceneManager.Managers } } - internal static void EndPath(Path currentPath) - { - Game.LogTrivial($"[Path Creation] Path {currentPath.Number} finished with {currentPath.Waypoints.Count} waypoints."); - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path {currentPath.Number} complete."); - currentPath.State = State.Finished; - currentPath.IsEnabled = true; - currentPath.Waypoints.ForEach(x => x.EnableBlip()); - GameFiber.StartNew(() => currentPath.LoopForVehiclesToBeDismissed(), "Vehicle Cleanup Loop Fiber"); - GameFiber.StartNew(() => currentPath.LoopWaypointCollection(), "Waypoint Collection Loop Fiber"); - - PathMainMenu.CreateNewPath.Text = "Create New Path"; - PathMainMenu.Build(); - PathMainMenu.Menu.Visible = true; - - MainMenu.BuildMainMenu(); - DriverMenu.Build(); - PathCreationMenu.BuildPathCreationMenu(); - BarrierMenu.BuildMenu(); - } - - internal static void TogglePathCreationMenuItems(Path currentPath) + internal static void TogglePathCreationMenuItems(Paths.Path currentPath) { if(currentPath.Waypoints.Count == 1) { @@ -228,6 +186,15 @@ namespace SceneManager.Managers PathCreationMenu.CollectorWaypoint.Checked = true; PathCreationMenu.RemoveLastWaypoint.Enabled = false; PathCreationMenu.EndPathCreation.Enabled = false; + PathCreationMenu.PathName.Enabled = false; + PathCreationMenu.PathName.Description = "Add your first waypoint to enable this option."; + currentPath.Delete(); + + PathCreationMenu.PathCreationState = State.Uninitialized; + PathMainMenu.CreateNewPath.Text = "Create New Path"; + PathMainMenu.Build(); + GameFiber.Yield(); + PathCreationMenu.Menu.Visible = true; } if (PathCreationMenu.CollectorWaypoint.Checked) @@ -256,25 +223,81 @@ namespace SceneManager.Managers internal static void ToggleAllPaths(bool disable) { + var nonNullPaths = Paths.Where(x => x != null).ToList(); if (disable) { - Paths.ForEach(x => x.DisablePath()); + nonNullPaths.ForEach(x => x.Disable()); Game.LogTrivial($"All paths disabled."); } else { - Paths.ForEach(x => x.EnablePath()); + nonNullPaths.ForEach(x => x.Enable()); Game.LogTrivial($"All paths enabled."); } } internal static void DeleteAllPaths() { - Paths.ForEach(x => x.Delete()); - Paths.Clear(); + for(int i = 0; i < Paths.Length; i++) + { + if(Paths[i] != null) + { + Paths[i].Delete(); + } + } + Array.Clear(Paths, 0, Paths.Length); + //Paths.Clear(); Game.LogTrivial($"All paths deleted"); Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); - MainMenu.BuildMainMenu(); + MainMenu.Build(); + } + + internal static void ImportPaths() + { + ImportedPaths.Clear(); + + // Check if Saved Paths directory exists + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; + if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) + { + Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist. No paths available to import."); + return; + } + + // Check if any XML files are available to import from Saved Paths + var savedPathNames = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); + if (savedPathNames.Length == 0) + { + Game.LogTrivial($"No saved paths found."); + return; + } + else + { + Game.LogTrivial($"{savedPathNames.Length} path(s) available to import."); + } + + // Import paths + foreach (string pathName in savedPathNames) + { + var fileName = Path.GetFileNameWithoutExtension(pathName); + Game.LogTrivial($"File: {fileName}"); + + var overrides = DefineOverridesForCombinedPath(); + var paths = Serializer.LoadItemFromXML>(SAVED_PATHS_DIRECTORY + Path.GetFileName(pathName), overrides); + ImportedPaths.Add(fileName, paths); + } + Game.LogTrivial($"Successfully imported {ImportedPaths.Count} file(s)."); + } + + private static XmlAttributeOverrides DefineOverridesForCombinedPath() + { + XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + XmlAttributes attr = new XmlAttributes(); + attr.XmlRoot = new XmlRootAttribute("Paths"); + overrides.Add(typeof(List), attr); + + return overrides; } } } From 5b872b7c87b512c024db0cf57b8bf69f5e22326a Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:40:54 -0600 Subject: [PATCH 051/112] Added option to add unassigned barriers to a designated path --- SceneManager/Menus/BarrierMenu.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index cca1c5a..6c96eb0 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -14,15 +14,15 @@ namespace SceneManager.Menus { private static List TrafficLightList { get; } = new List() { TrafficLight.Green, TrafficLight.Red, TrafficLight.Yellow, TrafficLight.None }; internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Barrier Management"); - internal static UIMenuListScrollerItem BarrierList { get; } = new UIMenuListScrollerItem("Spawn Barrier", "", Settings.Barriers.Keys); // Settings.barrierKeys + internal static UIMenuListScrollerItem BarrierList { get; } = new UIMenuListScrollerItem("Spawn Barrier", "", Settings.BarrierModels.Keys); // Settings.barrierKeys internal static UIMenuNumericScrollerItem RotateBarrier { get; } = new UIMenuNumericScrollerItem("Rotate Barrier", "", 0, 350, 10); - // ADD CHECKBOX FOR BARRIER TO STOP TRAFFIC? ADD 3D MARKER TO SHOW WHERE TRAFFIC WILL STOP. ONLY NEED ONE CONE TO DO IT PER LANE internal static UIMenuCheckboxItem Invincible { get; } = new UIMenuCheckboxItem("Indestructible", false, "If checked, the barrier will not break, or will be harder to break. The barrier will still able to be moved around."); internal static UIMenuCheckboxItem Immobile { get; } = new UIMenuCheckboxItem("Immobile", false, "If checked, the barrier will be frozen in place."); internal static UIMenuNumericScrollerItem BarrierTexture { get; } = new UIMenuNumericScrollerItem("Change Texture", "If the barrier has multiple textures, changing this value will apply them to the barrier.", 0, 15, 1); internal static UIMenuCheckboxItem SetBarrierLights { get; } = new UIMenuCheckboxItem("Enable Barrier Lights", Settings.EnableBarrierLightsDefaultOn, "If the barrier has functional lights, checking this option will turn them on."); internal static UIMenuCheckboxItem BelongsToPath { get; } = new UIMenuCheckboxItem("Belongs to Path", false, "If checked, the barrier will be saved with the path when the path is exported."); internal static UIMenuListScrollerItem AddToPath { get; private set; } + internal static UIMenuListScrollerItem AddUnassignedToPath { get; private set; } internal static UIMenuListScrollerItem SetBarrierTrafficLight { get; } = new UIMenuListScrollerItem("Set Barrier Traffic Light", "", TrafficLightList); internal static UIMenuListScrollerItem RemoveBarrierOptions { get; } = new UIMenuListScrollerItem("Remove Barrier", "", new[] { "Last Barrier", "Nearest Barrier", "All Barriers" }); internal static UIMenuItem ResetBarriers { get; } = new UIMenuItem("Reset Barriers", "Reset all spawned barriers to their original position and rotation"); @@ -38,7 +38,7 @@ namespace SceneManager.Menus Menu.OnMenuOpen += BarrierMenu_OnMenuOpen; } - internal static void BuildMenu() + internal static void Build() { Menu.Clear(); @@ -63,10 +63,15 @@ namespace SceneManager.Menus BelongsToPath.Enabled = PathManager.Paths.Count() > 0 ? true : false; BelongsToPath.Checked = false; - AddToPath = new UIMenuListScrollerItem("Path", "The path the barrier will be saved with when the path is exported.", PathManager.Paths.Select(x => x.Name)); + AddToPath = new UIMenuListScrollerItem("Path", "The path the barrier will be saved with when the path is exported.", PathManager.Paths.Where(x => x != null).Select(x => x.Name)); Menu.AddItem(AddToPath); AddToPath.Enabled = BelongsToPath.Checked; + AddUnassignedToPath = new UIMenuListScrollerItem("Add Unassigned Barriers to Path", "The path to add all unassigned barriers to.", PathManager.Paths.Where(x => x != null).Select(x => x.Name)); + Menu.AddItem(AddUnassignedToPath); + AddUnassignedToPath.ForeColor = Color.Gold; + AddUnassignedToPath.Enabled = BarrierManager.Barriers.Any(x => x.Path == null); + Menu.AddItem(RemoveBarrierOptions); RemoveBarrierOptions.ForeColor = Color.Gold; RemoveBarrierOptions.Enabled = BarrierManager.Barriers.Count() != 0; @@ -138,19 +143,21 @@ namespace SceneManager.Menus { if (selectedItem == BarrierList) { - //SpawnBarrier(); BarrierManager.SpawnBarrier(); } + if (selectedItem == AddUnassignedToPath) + { + BarrierManager.AddBarrierToPath(); + } + if (selectedItem == RemoveBarrierOptions) { - //RemoveBarrier(); BarrierManager.RemoveBarrier(RemoveBarrierOptions.Index); } if (selectedItem == ResetBarriers) { - //ResetBarriers(); BarrierManager.ResetBarriers(); } } From 97c21fbc938a82c6096287efa845a3eaa6c17a63 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:41:41 -0600 Subject: [PATCH 052/112] Updated Paths property due to data structure change --- SceneManager/Menus/DriverMenu.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Menus/DriverMenu.cs b/SceneManager/Menus/DriverMenu.cs index fda516c..de6d937 100644 --- a/SceneManager/Menus/DriverMenu.cs +++ b/SceneManager/Menus/DriverMenu.cs @@ -34,13 +34,13 @@ namespace SceneManager.Menus Menu.AddItem(DirectOptions); DirectOptions.Enabled = true; - Menu.AddItem(DirectDriver = new UIMenuListScrollerItem("Direct nearest driver to path", "", PathManager.Paths.Select(x => x.Name))); // This must instantiate here because the Paths change + Menu.AddItem(DirectDriver = new UIMenuListScrollerItem("Direct nearest driver to path", "", PathManager.Paths.Where(x => x != null).Select(x => x.Name))); // This must instantiate here because the Paths change DirectDriver.ForeColor = Color.Gold; DirectDriver.Enabled = true; Menu.AddItem(DismissDriver); DismissDriver.ForeColor = Color.Gold; - if (PathManager.Paths.Count == 0) + if (PathManager.Paths.Length == 0) { DirectOptions.Enabled = false; DirectDriver.Enabled = false; From b02f2278444fdfc61ac9c862ea0407efe47781f1 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:42:14 -0600 Subject: [PATCH 053/112] Replaced Export option with ChangePathName. --- SceneManager/Menus/EditPathMenu.cs | 49 ++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 40123dd..1f49bba 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Drawing; using System.Linq; using Rage; @@ -6,6 +7,7 @@ using RAGENativeUI; using RAGENativeUI.Elements; using SceneManager.Managers; using SceneManager.Menus; +using SceneManager.Paths; using SceneManager.Utils; namespace SceneManager @@ -13,10 +15,11 @@ namespace SceneManager internal class EditPathMenu { internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Edit Path"); - internal static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path", false); + private static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path", false); private static UIMenuItem EditWaypoints { get; } = new UIMenuItem("Edit Waypoints"); - private static UIMenuItem deletePath { get; } = new UIMenuItem("Delete Path"); - private static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Path", "Export path to ~b~plugins/SceneManager/Saved Paths"); + private static UIMenuItem DeletePath { get; } = new UIMenuItem("Delete Path"); + private static UIMenuItem ChangePathName { get; } = new UIMenuItem("Change Path Name"); + internal static Path CurrentPath { get; set; } internal static void Initialize() { @@ -28,17 +31,17 @@ namespace SceneManager Menu.OnMenuOpen += EditPath_OnMenuOpen; } - internal static void BuildEditPathMenu() + internal static void Build() { Menu.Clear(); Menu.AddItem(DisablePath); Menu.AddItem(EditWaypoints); EditWaypoints.ForeColor = Color.Gold; - Menu.AddItem(ExportPath); - ExportPath.ForeColor = Color.Gold; - Menu.AddItem(deletePath); - deletePath.ForeColor = Color.Gold; + Menu.AddItem(ChangePathName); + ChangePathName.ForeColor = Color.Gold; + Menu.AddItem(DeletePath); + DeletePath.ForeColor = Color.Gold; Menu.RefreshIndex(); } @@ -54,19 +57,21 @@ namespace SceneManager EditWaypointMenu.BuildEditWaypointMenu(); } - if (selectedItem == deletePath) + if (selectedItem == DeletePath) { var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; currentPath.Delete(); - PathManager.Paths.Remove(currentPath); PathMainMenu.Build(); PathMainMenu.Menu.Visible = true; - BarrierMenu.BuildMenu(); + BarrierMenu.Build(); } - if(selectedItem == ExportPath) + if(selectedItem == ChangePathName) { - PathManager.ExportPath(); + var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + currentPath.ChangeName(); + MenuManager.BuildMenus(); + Menu.Visible = true; } } @@ -74,16 +79,20 @@ namespace SceneManager { if (checkboxItem == DisablePath) { - var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + //var currentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + var currentPath = PathManager.Paths.FirstOrDefault(x => x.Name == PathMainMenu.EditPath.OptionText); + if(currentPath == null) + { + return; + } + if (DisablePath.Checked) { - currentPath.DisablePath(); - Game.LogTrivial($"Path {currentPath.Number} disabled."); + currentPath.Disable(); } else { - currentPath.EnablePath(); - Game.LogTrivial($"Path {currentPath.Number} enabled."); + currentPath.Enable(); } } } @@ -92,6 +101,8 @@ namespace SceneManager { var scrollerItems = new List { }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); + //CurrentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + ChangePathName.Description = $"Change the path name from ~b~{CurrentPath.Name} ~w~to something else."; } } } From ed48504d0300a7d23cbc7d0f1cfc1727e4d8abce Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:43:45 -0600 Subject: [PATCH 054/112] Updated Paths property due to data structure change --- SceneManager/Menus/EditWaypointMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Menus/EditWaypointMenu.cs b/SceneManager/Menus/EditWaypointMenu.cs index 808b630..8dd229d 100644 --- a/SceneManager/Menus/EditWaypointMenu.cs +++ b/SceneManager/Menus/EditWaypointMenu.cs @@ -172,7 +172,7 @@ namespace SceneManager.Menus if (selectedItem == RemoveWaypoint) { PathManager.RemoveEditWaypoint(currentPath); - if(PathManager.Paths.Count < 1) + if(PathManager.Paths.Length < 1) { return; } From 38b9b04d74d376a3a4a9f6abc0b7e02d9734bf90 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:45:44 -0600 Subject: [PATCH 055/112] Initial commit --- SceneManager/Menus/ExportPathMenu.cs | 205 +++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 SceneManager/Menus/ExportPathMenu.cs diff --git a/SceneManager/Menus/ExportPathMenu.cs b/SceneManager/Menus/ExportPathMenu.cs new file mode 100644 index 0000000..ded3451 --- /dev/null +++ b/SceneManager/Menus/ExportPathMenu.cs @@ -0,0 +1,205 @@ +using RAGENativeUI; +using RAGENativeUI.Elements; +using System.Drawing; +using SceneManager.Utils; +using System.Collections.Generic; +using System.Linq; +using Rage; +using SceneManager.Managers; +using System.IO; +using System.Xml.Serialization; + +namespace SceneManager.Menus +{ + internal static class ExportPathMenu + { + public static List ExportPaths { get; } = new List(); + + internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Export Path Menu"); + internal static UIMenuListScrollerItem ExportOptions = new UIMenuListScrollerItem("Export As", "Choose whether you want the paths exported as individual files, or all within the same file.", new string[] { "Individual file(s)", "Combined file" }); + internal static UIMenuItem Export = new UIMenuItem("Export", "Export the selected path(s)"); + + internal static void Initialize() + { + Menu.ParentMenu = PathMainMenu.Menu; + MenuManager.MenuPool.Add(Menu); + + Menu.OnItemSelect += ExportPathMenu_OnItemSelect; + Menu.OnCheckboxChange += ExportPathMenu_OnCheckboxChange; + Menu.OnMenuOpen += ExportPathMenu_OnMenuOpen; + } + + internal static void Build() + { + Menu.Clear(); + foreach(Paths.Path path in PathManager.Paths.Where(x => x != null)) + { + Menu.AddItem(new UIMenuCheckboxItem(path.Name, false)); + } + + Menu.AddItem(ExportOptions); + ExportOptions.Enabled = false; + Menu.AddItem(Export); + Export.ForeColor = Color.Gold; + Export.Enabled = false; + + Menu.RefreshIndex(); + } + + private static void ExportPathMenu_OnMenuOpen(UIMenu menu) + { + var scrollerItems = new List { ExportOptions }; + GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); + } + + private static void ExportPathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool Checked) + { + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)); + int checkedItems = 0; + foreach (UIMenuCheckboxItem menuItem in checkboxItems) + { + if (menuItem.Checked) + { + checkedItems++; + } + } + + Export.Enabled = checkedItems > 0; + + if(checkedItems > 1) + { + ExportOptions.Enabled = true; + } + else + { + if(!ExportOptions.OptionText.Contains("Individual")) + { + ExportOptions.ScrollToNextOption(); + } + ExportOptions.Enabled = false; + } + } + + private static void ExportPathMenu_OnItemSelect(UIMenu sender, UIMenuItem selectedItem, int index) + { + if(selectedItem == Export) + { + ExportPaths.Clear(); + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)).Select(x => (UIMenuCheckboxItem)x); + var checkedItems = checkboxItems.Where(x => x.Checked); + foreach(UIMenuCheckboxItem checkedItem in checkedItems) + { + var pathToExport = PathManager.Paths.First(x => x.Name == checkedItem.Text); + ExportPaths.Add(pathToExport); + } + + if (ExportOptions.OptionText.Contains("Individual")) + { + foreach (UIMenuCheckboxItem menuItem in checkedItems) + { + var pathToExport = PathManager.Paths.First(x => x.Name == menuItem.Text); + ExportAsIndividualFile(pathToExport); + } + } + else + { + ExportAsCombinedFile(checkboxItems); + } + + MenuManager.BuildMenus(); + Menu.Visible = true; + } + } + + private static void ExportAsIndividualFile(Paths.Path pathToExport) + { + if (CanQuickSavePath(pathToExport)) + { + pathToExport.Save(); + return; + } + + var fileName = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + if (string.IsNullOrWhiteSpace(fileName)) + { + Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to ~b~\"{pathToExport.Name}\""); + Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to \"{pathToExport.Name}\""); + fileName = pathToExport.Name; + } + + Game.LogTrivial($"Filename: {fileName}"); + pathToExport.Name = fileName; + + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; + var overrides = DefineOverridesForCombinedPath(); + Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + fileName + ".xml", overrides); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path exported as ~b~{fileName}.xml~w~."); + } + + private static void ExportAsCombinedFile(IEnumerable checkedItems) + { + // If any file contains all (and only) path names from checkedItems, it can be quicksaved + string existingFile = GetNameForExistingCombinedPathsFile(checkedItems); + if(existingFile == "") + { + existingFile = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + + if (string.IsNullOrWhiteSpace(existingFile)) + { + Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to ~b~\"{checkedItems.First().Text}\""); + Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to \"{checkedItems.First().Text}\""); + existingFile = checkedItems.First().Text; + } + } + + Game.LogTrivial($"Filename: {existingFile}"); + + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; + var overrides = DefineOverridesForCombinedPath(); + Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + existingFile + ".xml", overrides); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Paths exported as ~b~{existingFile}.xml~w~."); + } + + private static bool CanQuickSavePath(Paths.Path pathToExport) + { + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; + if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) + { + Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist."); + return false; + } + + var savedPathNames = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); + return savedPathNames.Any(x => Path.GetFileNameWithoutExtension(x) == pathToExport.Name); + } + + private static string GetNameForExistingCombinedPathsFile(IEnumerable checkedItems) + { + var checkedItemsText = checkedItems.Select(x => x.Text); + foreach (KeyValuePair> kvp in PathManager.ImportedPaths) + { + var pathNames = kvp.Value.Select(x => x.Name); + if (checkedItemsText.Count() == pathNames.Count() && checkedItemsText.All(x => pathNames.Contains(x))) + { + Game.LogTrivial($"File \"{kvp.Key}\" contains all paths to be exported. Quicksave."); + return kvp.Key; + } + } + + return ""; + } + + private static XmlAttributeOverrides DefineOverridesForCombinedPath() + { + XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + XmlAttributes attr = new XmlAttributes(); + attr.XmlRoot = new XmlRootAttribute("Paths"); + overrides.Add(typeof(List), attr); + + return overrides; + } + } +} From 48d4b2bc71a1577467a02cdbf63745a2bd4acda6 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:46:51 -0600 Subject: [PATCH 056/112] Added simultaneous file importation --- SceneManager/Menus/ImportPathMenu.cs | 92 ++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/SceneManager/Menus/ImportPathMenu.cs b/SceneManager/Menus/ImportPathMenu.cs index 17f5bb9..a19fbc9 100644 --- a/SceneManager/Menus/ImportPathMenu.cs +++ b/SceneManager/Menus/ImportPathMenu.cs @@ -7,13 +7,15 @@ using System.Linq; using Rage; using SceneManager.Managers; using SceneManager.Paths; +using System; +using System.Windows.Forms; namespace SceneManager.Menus { internal class ImportPathMenu { internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Import Path Menu"); - private static UIMenuItem menuItem; + internal static UIMenuItem Import { get; } = new UIMenuItem("Import", "Import the selected paths."); internal static void Initialize() { @@ -22,39 +24,93 @@ namespace SceneManager.Menus Menu.OnItemSelect += ImportPathMenu_OnItemSelect; Menu.OnMenuOpen += ImportPathMenu_OnMenuOpen; + Menu.OnCheckboxChange += ImportPathMenu_OnCheckboxChange; } - internal static void BuildImportMenu() + internal static void Build() { Menu.Clear(); - foreach(Path path in Settings.ImportedPaths) + PathManager.ImportPaths(); + foreach(KeyValuePair> kvp in PathManager.ImportedPaths) { - Menu.AddItem(menuItem = new UIMenuItem(path.Name)); - menuItem.ForeColor = Color.Gold; + Menu.AddItem(new UIMenuCheckboxItem(kvp.Key, false)); } + + Menu.AddItem(Import); + Import.ForeColor = Color.Gold; + Import.Enabled = false; } private static void ImportPathMenu_OnMenuOpen(UIMenu menu) { GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, new List()), "RNUI Mouse Input Fiber"); - - // Disable menu item if PathManager.Paths contains a path with a matching name - foreach (UIMenuItem menuItem in menu.MenuItems) - { - menuItem.Enabled = !PathManager.Paths.Any(x => x.Name == menuItem.Text); - } } private static void ImportPathMenu_OnItemSelect(UIMenu sender, UIMenuItem selectedItem, int index) { - // When the user clicks on a path, that path needs to be added from Settings.importedPaths to PathMainMenu.paths - Path importedPath = PathManager.ImportPath(Settings.ImportedPaths.FirstOrDefault(x => x.Name == selectedItem.Text)); - importedPath.Load(); - Game.LogTrivial($"{selectedItem.Text} added to paths collection. Paths count: {PathManager.Paths.Count}"); - selectedItem.Enabled = false; + if(selectedItem == Import) + { + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)); + foreach(UIMenuCheckboxItem menuItem in checkboxItems) + { + if(menuItem.Checked) + { + var pathsFromFile = PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Value; + foreach(Path path in pathsFromFile) + { + if(PathManager.Paths.Any(x => x != null && x.Name == path.Name)) + { + Game.DisplayHelp($"A path with the name ~b~{path.Name} ~w~already exists. Do you want to replace it? ~{Keys.Y.GetInstructionalId()}~ or ~{Keys.N.GetInstructionalId()}~"); + GameFiber.Sleep(100); + GameFiber.SleepUntil(() => Game.IsKeyDown(Keys.Y) || Game.IsKeyDown(Keys.N), 8300); - MenuManager.BuildMenus(); - PathMainMenu.Menu.Visible = true; + if(Game.IsKeyDown(Keys.Y)) + { + var pathToReplace = PathManager.Paths.First(x => x.Name == path.Name); + var pathToReplaceIndex = Array.IndexOf(PathManager.Paths, pathToReplace); + pathToReplace.Delete(); + PathManager.Paths[pathToReplaceIndex] = path; + path.Load(); + Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); + continue; + } + else + { + Game.DisplayNotification($"~o~Scene Manager ~y~[Import]\n~w~Path ~b~{path.Name} ~w~was not imported."); + Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); + continue; + } + } + + var firstNullPathIndex = Array.IndexOf(PathManager.Paths, PathManager.Paths.First(x => x == null)); + PathManager.Paths[firstNullPathIndex] = path; + path.Load(); + } + + var numberOfNonNullPaths = PathManager.Paths.Where(x => x != null).Count(); + Game.LogTrivial($"{menuItem.Text} added to paths collection. Paths count: {numberOfNonNullPaths}"); + Menu.RefreshIndex(); + } + } + + MenuManager.BuildMenus(); + Menu.Visible = true; + } + } + + private static void ImportPathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool Checked) + { + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)); + int checkedItems = 0; + foreach (UIMenuCheckboxItem menuItem in checkboxItems) + { + if (menuItem.Checked) + { + checkedItems++; + } + } + + Import.Enabled = checkedItems > 0; } } } From 521f204e56dbb942cdce8b96f015d205b4d3798c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:47:22 -0600 Subject: [PATCH 057/112] Renamed BuildMainMenu method to Build --- SceneManager/Menus/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Menus/MainMenu.cs b/SceneManager/Menus/MainMenu.cs index 908dbc5..64aaa12 100644 --- a/SceneManager/Menus/MainMenu.cs +++ b/SceneManager/Menus/MainMenu.cs @@ -21,7 +21,7 @@ namespace SceneManager.Menus Menu.OnMenuOpen += MainMenu_OnMenuOpen; } - internal static void BuildMainMenu() + internal static void Build() { Menu.Clear(); From 817b7cb6855887b6c3818a72bc1d8267aee5b473 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:49:29 -0600 Subject: [PATCH 058/112] Added option to change path name --- SceneManager/Menus/PathCreationMenu.cs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/SceneManager/Menus/PathCreationMenu.cs b/SceneManager/Menus/PathCreationMenu.cs index fa6cfb2..8b19352 100644 --- a/SceneManager/Menus/PathCreationMenu.cs +++ b/SceneManager/Menus/PathCreationMenu.cs @@ -22,6 +22,7 @@ namespace SceneManager.Menus internal static UIMenuCheckboxItem CollectorWaypoint { get; } = new UIMenuCheckboxItem("Collector", true, "If checked, this waypoint will collect vehicles to follow the path. Your path's first waypoint ~b~must~w~ be a collector."); internal static UIMenuNumericScrollerItem CollectorRadius { get; } = new UIMenuNumericScrollerItem("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1); internal static UIMenuNumericScrollerItem SpeedZoneRadius { get; } = new UIMenuNumericScrollerItem("Speed Zone Radius", "The distance from this collector waypoint (in meters) non-collected vehicles will drive at this waypoint's speed", 5, 200, 5); + internal static UIMenuItem PathName { get; private set; } = new UIMenuItem("Change Path Name", $"Add your first waypoint to enable this option."); internal static State PathCreationState { get; set; } = State.Uninitialized; internal static void Initialize() @@ -35,7 +36,7 @@ namespace SceneManager.Menus Menu.OnMenuOpen += PathCreation_OnMenuOpen; } - internal static void BuildPathCreationMenu() + internal static void Build() { Menu.Clear(); @@ -59,6 +60,10 @@ namespace SceneManager.Menus Menu.AddItem(WaypointSpeed = new UIMenuNumericScrollerItem("Waypoint Speed", $"How fast the AI will drive to this waypoint in ~b~{SettingsMenu.SpeedUnits.SelectedItem}", 5, 100, 5)); WaypointSpeed.Index = (Settings.WaypointSpeed / 5) - 1; + Menu.AddItem(PathName); + PathName.ForeColor = Color.Gold; + PathName.Enabled = false; + Menu.AddItem(AddWaypoint); AddWaypoint.ForeColor = Color.Gold; @@ -108,22 +113,31 @@ namespace SceneManager.Menus if (PathCreationState != State.Creating) { CurrentPath = PathManager.InitializeNewPath(); + PathName.Description = $"Current path name is ~b~{CurrentPath.Name}"; + PathName.Enabled = true; } - PathManager.AddWaypoint(CurrentPath); + CurrentPath.AddWaypoint(); PathManager.TogglePathCreationMenuItems(CurrentPath); } if (selectedItem == RemoveLastWaypoint) { - PathManager.RemoveWaypoint(CurrentPath); + CurrentPath.RemoveWaypoint(); PathManager.TogglePathCreationMenuItems(CurrentPath); } if (selectedItem == EndPathCreation) { - PathCreationState = State.Finished; - PathManager.EndPath(CurrentPath); + CurrentPath.Finish(); + PathCreationState = State.Uninitialized; + PathName.Description = $"Add your first waypoint to enable this option."; + } + + if(selectedItem == PathName) + { + CurrentPath.ChangeName(); + PathName.Description = $"Current path name is ~b~{CurrentPath.Name}"; } } From bbc0ea6354caaca5a74a92e1cfd2822294546fb2 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:49:47 -0600 Subject: [PATCH 059/112] Added ExportPath option --- SceneManager/Menus/PathMainMenu.cs | 37 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/SceneManager/Menus/PathMainMenu.cs b/SceneManager/Menus/PathMainMenu.cs index 790668a..065e215 100644 --- a/SceneManager/Menus/PathMainMenu.cs +++ b/SceneManager/Menus/PathMainMenu.cs @@ -7,16 +7,15 @@ using RAGENativeUI.Elements; using SceneManager.Managers; using SceneManager.Paths; using SceneManager.Utils; -using SceneManager.Waypoints; namespace SceneManager.Menus { internal static class PathMainMenu { - private static int MAX_PATH_LIMIT { get; } = 10; internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Path Manager"); internal static UIMenuItem CreateNewPath { get; } = new UIMenuItem("Create New Path"); - internal static UIMenuItem ImportPath { get; } = new UIMenuItem("Import Path", "Import a saved path from ~b~plugins/SceneManager/Saved Paths"); + internal static UIMenuItem ImportPath { get; } = new UIMenuItem("Import Paths", "Import saved paths from ~b~plugins/SceneManager/Saved Paths"); + internal static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Paths", "Export selected paths to ~b~plugins/SceneManager/Saved Paths"); internal static UIMenuItem DeleteAllPaths { get; } = new UIMenuItem("Delete All Paths"); internal static UIMenuListScrollerItem EditPath { get; private set; } internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Paths", false); @@ -40,8 +39,11 @@ namespace SceneManager.Menus CreateNewPath.ForeColor = Color.Gold; Menu.AddItem(ImportPath); ImportPath.ForeColor = Color.Gold; - ImportPath.Enabled = Settings.ImportedPaths.Count() > 0; - Menu.AddItem(EditPath = new UIMenuListScrollerItem("Edit Path", "Options to ~b~edit path waypoints~w~, ~b~disable the path~w~, ~b~export the path~w~, or ~b~delete the path~w~.", PathManager.Paths.Select(x => x.Name))); + ImportPath.Enabled = PathManager.ImportedPaths.Count > 0; + Menu.AddItem(ExportPath); + ExportPath.ForeColor = Color.Gold; + ExportPath.Enabled = PathManager.Paths.Any(x => x != null); + Menu.AddItem(EditPath = new UIMenuListScrollerItem("Edit Path", "Options to ~b~edit path waypoints~w~, ~b~disable the path~w~, ~b~change path name~w~, or ~b~delete the path~w~.", PathManager.Paths.Where(x => x != null).Select(x => x.Name))); EditPath.ForeColor = Color.Gold; Menu.AddItem(DisableAllPaths); DisableAllPaths.Enabled = true; @@ -49,18 +51,18 @@ namespace SceneManager.Menus DeleteAllPaths.Enabled = true; DeleteAllPaths.ForeColor = Color.Gold; - if (PathManager.Paths.Count == MAX_PATH_LIMIT) + if (PathManager.Paths.All(x => x != null)) { CreateNewPath.Enabled = false; ImportPath.Enabled = false; } - if (PathManager.Paths.Count == 0) + if (PathManager.Paths.All(x => x == null)) { EditPath.Enabled = false; DeleteAllPaths.Enabled = false; DisableAllPaths.Enabled = false; } - if(Settings.ImportedPaths.Count == 0) + if(PathManager.ImportedPaths.Count == 0) { ImportPath.Enabled = false; } @@ -80,6 +82,11 @@ namespace SceneManager.Menus GoToImportMenu(); } + if(selectedItem == ExportPath) + { + GoToExportMenu(); + } + if (selectedItem == EditPath) { GoToEditPathMenu(); @@ -91,7 +98,7 @@ namespace SceneManager.Menus DisableAllPaths.Checked = false; Build(); Menu.Visible = true; - BarrierMenu.BuildMenu(); + BarrierMenu.Build(); } } @@ -115,12 +122,11 @@ namespace SceneManager.Menus { Menu.Visible = false; PathCreationMenu.Menu.Visible = true; - Path currentPath = PathManager.Paths.FirstOrDefault(x => x.State == State.Creating); - Game.DisplayNotification($"~o~Scene Manager~y~[Creating]\n~w~Resuming path {currentPath.Number}"); + Path currentPath = PathManager.Paths.FirstOrDefault(x => x != null && x.State == State.Creating); + Game.DisplayNotification($"~o~Scene Manager~y~[Creating]\n~w~Resuming path ~b~{currentPath.Name}~w~."); } else { - //PathCreationMenu.BuildPathCreationMenu(); Menu.Visible = false; PathCreationMenu.Menu.Visible = true; } @@ -132,9 +138,16 @@ namespace SceneManager.Menus ImportPathMenu.Menu.Visible = true; } + private static void GoToExportMenu() + { + Menu.Visible = false; + ExportPathMenu.Menu.Visible = true; + } + private static void GoToEditPathMenu() { Menu.Visible = false; + EditPathMenu.CurrentPath = PathManager.Paths[EditPath.Index]; EditPathMenu.Menu.Visible = true; } } From cdd81438b691fadfc1e5208077b497e2e15488ec Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:50:08 -0600 Subject: [PATCH 060/112] Updated BuildSettingsMenu method name to Build --- SceneManager/Menus/SettingsMenu.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SceneManager/Menus/SettingsMenu.cs b/SceneManager/Menus/SettingsMenu.cs index b205f22..96cb83a 100644 --- a/SceneManager/Menus/SettingsMenu.cs +++ b/SceneManager/Menus/SettingsMenu.cs @@ -28,8 +28,10 @@ namespace SceneManager.Menus Menu.OnMenuOpen += SettingsMenu_OnMenuOpen; } - internal static void BuildSettingsMenu() + internal static void Build() { + Menu.Clear(); + Menu.AddItem(ThreeDWaypoints); Menu.AddItem(MapBlips); Menu.AddItem(Hints); From 7461f049211dd29d3b10f56862b76eafbb775dba Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:51:26 -0600 Subject: [PATCH 061/112] Added AddWaypoint, RemoveWaypoint, Finish, and ChangeName methods --- SceneManager/Paths/Path.cs | 129 ++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 25 deletions(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index e851e00..40967da 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -14,11 +14,10 @@ using SceneManager.CollectedPeds; namespace SceneManager.Paths { - [XmlRoot(ElementName = "Path", Namespace = "")] public class Path // Change this to Public for import/export { - internal string Name { get; set; } - internal int Number { get; set; } + public string Name { get; set; } + internal int Number { get => Array.IndexOf(PathManager.Paths, this) + 1; set { } } internal bool IsEnabled { get; set; } internal State State { get; set; } @@ -31,17 +30,13 @@ namespace SceneManager.Paths internal List CollectedPeds { get; } = new List(); internal List BlacklistedVehicles { get; } = new List(); - private Path() { } - - internal Path(int pathNum, State pathState) + internal Path() { - Number = pathNum; - State = pathState; - Name = Number.ToString(); + State = State.Creating; DrawLinesBetweenWaypoints(); } - internal void Save(string filename) + internal void Save() { var GAME_DIRECTORY = Directory.GetCurrentDirectory(); var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; @@ -50,28 +45,78 @@ namespace SceneManager.Paths Directory.CreateDirectory(SAVED_PATHS_DIRECTORY); Game.LogTrivial($"New directory created at '/plugins/SceneManager/Saved Paths'"); } - Serializer.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + filename); + + var overrides = DefineOverridesForCombinedPath(); + Serializer.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + Name + ".xml", overrides); + Game.LogTrivial($"Saved {Name}.xml"); + + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path ~b~{Name} ~w~exported."); } internal void Load() { - State = State.Finished; - EnablePath(); foreach(Waypoint waypoint in Waypoints) { waypoint.LoadFromImport(this); } Game.LogTrivial($"This path has {Barriers.Count} barriers"); - foreach(Barrier barrier in Barriers) + for(int i = 0; i < Barriers.Count(); i++) { - barrier.LoadFromImport(); + var barrier = new Barrier(Barriers[i], Barriers[i].Invincible, Barriers[i].Immobile, Barriers[i].TextureVariation, Barriers[i].LightsEnabled); + barrier.Path = this; + Barriers[i] = barrier; + BarrierManager.Barriers.Add(barrier); } + DrawLinesBetweenWaypoints(); - PathManager.EndPath(this); + Finish(); } - private void LowerWaypointBlipsOpacity() + internal void AddWaypoint() + { + DrivingFlagType drivingFlag = PathCreationMenu.DirectWaypoint.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal; + float speed = HelperMethods.ConvertDriveSpeedForWaypoint(PathCreationMenu.WaypointSpeed.Value); + + if (PathCreationMenu.CollectorWaypoint.Checked) + { + new Waypoint(this, UserInput.PlayerMousePosition, speed, drivingFlag, PathCreationMenu.StopWaypoint.Checked, true, PathCreationMenu.CollectorRadius.Value, PathCreationMenu.SpeedZoneRadius.Value); + } + else + { + new Waypoint(this, UserInput.PlayerMousePosition, speed, drivingFlag, PathCreationMenu.StopWaypoint.Checked); + } + } + + internal void RemoveWaypoint() + { + Waypoint lastWaypoint = Waypoints.Last(); + lastWaypoint.Delete(); + Waypoints.Remove(lastWaypoint); + } + + internal void Finish() + { + Game.LogTrivial($"[Path Creation] Path {Name} finished with {Waypoints.Count} waypoints."); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path ~b~{Name} ~w~complete."); + State = State.Finished; + IsEnabled = true; + Waypoints.ForEach(x => x.EnableBlip()); + GameFiber.StartNew(() => LoopForVehiclesToBeDismissed(), "Vehicle Cleanup Loop Fiber"); + GameFiber.StartNew(() => LoopWaypointCollection(), "Waypoint Collection Loop Fiber"); + + PathMainMenu.CreateNewPath.Text = "Create New Path"; + PathMainMenu.Build(); + PathMainMenu.Menu.Visible = true; + + MainMenu.Build(); + DriverMenu.Build(); + PathCreationMenu.Build(); + ExportPathMenu.Build(); + BarrierMenu.Build(); + } + + internal void LowerWaypointBlipsOpacity() { foreach (Waypoint wp in Waypoints) { @@ -98,7 +143,7 @@ namespace SceneManager.Paths } } - internal void DisablePath() + internal void Disable() { IsEnabled = false; foreach(Waypoint wp in Waypoints) @@ -109,9 +154,10 @@ namespace SceneManager.Paths { LowerWaypointBlipsOpacity(); } + Game.LogTrivial($"Path {Name} disabled."); } - internal void EnablePath() + internal void Enable() { IsEnabled = true; foreach (Waypoint wp in Waypoints) @@ -125,6 +171,7 @@ namespace SceneManager.Paths { RestoreWaypointBlipsOpacity(); } + Game.LogTrivial($"Path {Name} enabled."); } internal void DrawLinesBetweenWaypoints() @@ -221,11 +268,13 @@ namespace SceneManager.Paths internal void Delete() { + var pathIndex = Array.IndexOf(PathManager.Paths, this); State = State.Deleting; + RemoveAllBarriers(); DismissCollectedDrivers(); - RemoveWaypoints(); - RemoveBarriers(); - Game.LogTrivial($"Path {Number} deleted."); + RemoveAllWaypoints(); + PathManager.Paths[pathIndex] = null; + Game.LogTrivial($"Path {Name} deleted."); } private void DismissCollectedDrivers() @@ -250,18 +299,48 @@ namespace SceneManager.Paths } } - private void RemoveWaypoints() + private void RemoveAllWaypoints() { Waypoints.ForEach(x => x.Delete()); Waypoints.Clear(); } - private void RemoveBarriers() + private void RemoveAllBarriers() { - foreach(Barrier barrier in Barriers.Where(x => x.IsValid())) + Game.LogTrivial($"Deleting barriers."); + foreach(Barrier barrier in Barriers) { barrier.Delete(); } } + + internal void ChangeName() + { + var pathName = UserInput.PromptPlayerForFileName("Type the name you would like for your path", "Enter a path name", 100); + if (string.IsNullOrWhiteSpace(pathName)) + { + Game.DisplayHelp($"Invalid path name given. Name cannot be null, empty, or consist of just white spaces. Defaulting to ~b~\"{Name}\""); + Game.LogTrivial($"Invalid path name given. Name cannot be null, empty, or consist of just white spaces. Defaulting to \"{Name}\""); + return; + } + if (PathManager.Paths.Any(x => x != null && x.Name == pathName)) + { + Game.DisplayHelp($"Invalid path name given. A path with that name already exists. Defaulting to ~b~\"{Name}\""); + Game.LogTrivial($"Invalid path name given. A path with that name already exists. Defaulting to \"{Name}\""); + return; + } + + Name = pathName; + } + + private static XmlAttributeOverrides DefineOverridesForCombinedPath() + { + XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + XmlAttributes attr = new XmlAttributes(); + attr.XmlRoot = new XmlRootAttribute("Paths"); + overrides.Add(typeof(List), attr); + + return overrides; + } } } From 762bd6941160edc29a7602a1cd4fd562ddd745a4 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:51:36 -0600 Subject: [PATCH 062/112] Updated command method names --- SceneManager/Utils/ConsoleCommands.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index a5f5595..9acea7d 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -51,7 +51,7 @@ namespace SceneManager.Utils } [ConsoleCommand("DeleteVehicle")] - internal static void Command_DeleteVehicle([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterVehicle), Name = "Vehicle")] Vehicle vehicle) + internal static void Command_DeleteVehicleSM([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterVehicle), Name = "Vehicle")] Vehicle vehicle) { if (vehicle) { @@ -60,7 +60,7 @@ namespace SceneManager.Utils } [ConsoleCommand("DeletePed")] - internal static void Command_DeletePed([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterPed), Name = "Ped")] Ped ped) + internal static void Command_DeletePedSM([ConsoleCommandParameter(AutoCompleterType = typeof(ConsoleCommandAutoCompleterPed), Name = "Ped")] Ped ped) { if (ped && ped != Game.LocalPlayer.Character) { From 9a4c2d983eb2df56a06c42d9dd5b68856e317446 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:51:48 -0600 Subject: [PATCH 063/112] Removed unused Delete enum --- SceneManager/Utils/Enums.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/SceneManager/Utils/Enums.cs b/SceneManager/Utils/Enums.cs index c604ac8..8b2e166 100644 --- a/SceneManager/Utils/Enums.cs +++ b/SceneManager/Utils/Enums.cs @@ -1,11 +1,5 @@ namespace SceneManager.Utils { - internal enum Delete - { - Single, - All - } - internal enum PedTask { CTaskHandsUp = 0, From f2729a41b46c000fc0cf2610a7f6ce9dc72ff397 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:52:15 -0600 Subject: [PATCH 064/112] Added null check for path --- SceneManager/Utils/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index bc6e61f..1f20538 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -135,7 +135,7 @@ namespace SceneManager.Utils return false; } - var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p.Number != path.Number && p.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle)); + var vehicleCollectedOnAnotherPath = PathManager.Paths.Any(p => p != null && p.Number != path.Number && p.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle)); if (vehicleCollectedOnAnotherPath) { return false; From 990c745d6d89ab456f95bd215bda6d049464666b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:52:28 -0600 Subject: [PATCH 065/112] Initial commit --- SceneManager/Utils/HelperMethods.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 SceneManager/Utils/HelperMethods.cs diff --git a/SceneManager/Utils/HelperMethods.cs b/SceneManager/Utils/HelperMethods.cs new file mode 100644 index 0000000..21d8fd2 --- /dev/null +++ b/SceneManager/Utils/HelperMethods.cs @@ -0,0 +1,16 @@ +using Rage; +using SceneManager.Menus; + +namespace SceneManager.Utils +{ + internal class HelperMethods + { + internal static float ConvertDriveSpeedForWaypoint(float speed) + { + float convertedSpeed = SettingsMenu.SpeedUnits.SelectedItem == SpeedUnits.MPH + ? MathHelper.ConvertMilesPerHourToMetersPerSecond(speed) + : MathHelper.ConvertKilometersPerHourToMetersPerSecond(speed); + return convertedSpeed; + } + } +} From 267e6dd0caabcaaea8f820625439552cff1c801f Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:53:01 -0600 Subject: [PATCH 066/112] Removed duplicate methods --- SceneManager/Utils/Serializer.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/SceneManager/Utils/Serializer.cs b/SceneManager/Utils/Serializer.cs index da0bf3f..52e7eaf 100644 --- a/SceneManager/Utils/Serializer.cs +++ b/SceneManager/Utils/Serializer.cs @@ -11,6 +11,7 @@ namespace SceneManager.Utils internal static class Serializer { private static Dictionary _serializerCache = new Dictionary(); + private static XmlSerializer _getOrCreateSerializer(XmlAttributeOverrides overrides = null) { if (_serializerCache.ContainsKey(typeof(T))) @@ -74,7 +75,7 @@ namespace SceneManager.Utils SaveItemToXML(list, filePath); } - public static void SaveItemToXML(T item, string path, XmlAttributeOverrides overrides) + public static void SaveItemToXML(T item, string path, XmlAttributeOverrides overrides = null) { Encoding utf8NoBom = new UTF8Encoding(false); using (TextWriter writer = new StreamWriter(path, false, utf8NoBom)) @@ -82,17 +83,16 @@ namespace SceneManager.Utils XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); - //new XmlSerializer(typeof(Objects.Path)).Serialize(writer, item); - _getOrCreateSerializer(overrides).Serialize(writer, item, ns); + _getOrCreateSerializer(overrides).Serialize(writer, item, ns); } } - public static void SaveItemToXML(T item, string path) - { - SaveItemToXML(item, path, null); - } + //public static void SaveItemToXML(T item, string path) + //{ + // SaveItemToXML(item, path, null); + //} - public static T LoadItemFromXML(string filePath, XmlAttributeOverrides overrides) + public static T LoadItemFromXML(string filePath, XmlAttributeOverrides overrides = null) { if (!File.Exists(filePath)) throw new FileNotFoundException($"{nameof(LoadItemFromXML)}(): specified file does not exist: {filePath}"); @@ -102,10 +102,10 @@ namespace SceneManager.Utils } } - public static T LoadItemFromXML(string filePath) - { - return LoadItemFromXML(filePath, null); - } + //public static T LoadItemFromXML(string filePath) + //{ + // return LoadItemFromXML(filePath, null); + //} public static void ModifyItemInXML(string filePath, Action modification) { From 07bb1a577be5cbc7a1830a776f18cae200ab855f Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:54:36 -0600 Subject: [PATCH 067/112] Changed Number property to internal, added getter method --- SceneManager/Waypoints/Waypoint.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/SceneManager/Waypoints/Waypoint.cs b/SceneManager/Waypoints/Waypoint.cs index 2e62513..62d6de0 100644 --- a/SceneManager/Waypoints/Waypoint.cs +++ b/SceneManager/Waypoints/Waypoint.cs @@ -12,7 +12,7 @@ namespace SceneManager.Waypoints public class Waypoint // Change this and select properties to Public for import/export { internal Path Path { get; set; } - public int Number { get; set; } + internal int Number { get => Path.Waypoints.IndexOf(this) + 1; set { } } public Vector3 Position { get; set; } public float Speed { get; set; } public DrivingFlagType DrivingFlagType { get; set; } @@ -27,10 +27,9 @@ namespace SceneManager.Waypoints private Waypoint() { } - internal Waypoint(Path path, int waypointNumber, Vector3 waypointPosition, float speed, DrivingFlagType drivingFlag, bool stopWaypoint, bool collector = false, float collectorRadius = 1, float speedZoneRadius = 5) + internal Waypoint(Path path, Vector3 waypointPosition, float speed, DrivingFlagType drivingFlag, bool stopWaypoint, bool collector = false, float collectorRadius = 1, float speedZoneRadius = 5) { Path = path; - Number = waypointNumber; Position = waypointPosition; Speed = speed; DrivingFlagType = drivingFlag; @@ -56,6 +55,8 @@ namespace SceneManager.Waypoints } } + Path.Waypoints.Add(this); + Game.LogTrivial($"Path {Path.Name} Waypoint {Number} added [Driving style: {DrivingFlagType} | Stop waypoint: {IsStopWaypoint} | Speed: {Speed} | Collector: {IsCollector}]"); DrawWaypointMarker(); } From 03586cd49f1214a457fb52ef9deba76df67bc49b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:54:54 -0600 Subject: [PATCH 068/112] Added ExportPathMenu and HelperMethods classes --- SceneManager/SceneManager.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SceneManager/SceneManager.csproj b/SceneManager/SceneManager.csproj index 2ef0ffc..9a38cb2 100644 --- a/SceneManager/SceneManager.csproj +++ b/SceneManager/SceneManager.csproj @@ -64,6 +64,7 @@ + @@ -74,6 +75,7 @@ + From cce3c6bf217ff3f7cdb86c0a21293398a17d5465 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:55:12 -0600 Subject: [PATCH 069/112] Removed path import code --- SceneManager/Settings.cs | 45 +++++----------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/SceneManager/Settings.cs b/SceneManager/Settings.cs index 9d68065..1f61e4b 100644 --- a/SceneManager/Settings.cs +++ b/SceneManager/Settings.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Windows.Forms; using SceneManager.Utils; using System.IO; +using System.Xml.Linq; +using System.Linq; +using System.Xml.Serialization; +using SceneManager.Managers; namespace SceneManager { @@ -34,8 +38,7 @@ namespace SceneManager internal static int WaypointSpeed { get; set; } = 5; // Barriers - internal static Dictionary Barriers { get; private set; } = new Dictionary(); - internal static List ImportedPaths { get; private set; } = new List(); + internal static Dictionary BarrierModels { get; private set; } = new Dictionary(); internal static void LoadSettings() { @@ -66,44 +69,6 @@ namespace SceneManager SettingsValidator.ValidateWaypointSettings(); SettingsValidator.ValidateBarrierSettings(ini); - ImportPaths(); - } - - // This will need to be moved to a different class - internal static void ImportPaths() - { - ImportedPaths.Clear(); - - // Check if Saved Paths directory exists - var GAME_DIRECTORY = Directory.GetCurrentDirectory(); - var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; - if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) - { - Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist. No paths available to import."); - return; - } - - // Check if any XML files are available to import from Saved Paths - var savedPaths = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); - if (savedPaths.Length == 0) - { - Game.LogTrivial($"No saved paths found."); - return; - } - else - { - Game.LogTrivial($"{savedPaths.Length} path(s) available to import."); - } - - // Import paths - foreach (string file in savedPaths) - { - Game.LogTrivial($"File: {Path.GetFileName(file)}"); - var importedPath = Serializer.LoadItemFromXML(SAVED_PATHS_DIRECTORY + Path.GetFileName(file)); - importedPath.Name = Path.GetFileNameWithoutExtension(file); - ImportedPaths.Add(importedPath); - } - Game.LogTrivial($"Successfully imported {ImportedPaths.Count} path(s)."); } internal static void UpdateSettings(bool threeDWaypointsEnabled, bool mapBlipsEnabled, bool hintsEnabled, SpeedUnits unit) From b8207b14adc82b9042a4eae1eefa1412bd6c6557 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sat, 15 May 2021 09:55:23 -0600 Subject: [PATCH 070/112] Updated property name --- SceneManager/SettingsValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/SettingsValidator.cs b/SceneManager/SettingsValidator.cs index d2cdd31..2f42b73 100644 --- a/SceneManager/SettingsValidator.cs +++ b/SceneManager/SettingsValidator.cs @@ -42,7 +42,7 @@ namespace SceneManager var model = new Model(ini.ReadString("Barriers", displayName.Trim())); if (model.IsValid) { - Settings.Barriers.Add(displayName, model); + Settings.BarrierModels.Add(displayName, model); } else { From 3565b326cee559bd9e35a2b0461bee237a834a2d Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:21:39 -0600 Subject: [PATCH 071/112] Updated version --- SceneManager/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Properties/AssemblyInfo.cs b/SceneManager/Properties/AssemblyInfo.cs index 3e03168..17564d7 100644 --- a/SceneManager/Properties/AssemblyInfo.cs +++ b/SceneManager/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.2.3")] -[assembly: AssemblyFileVersion("2.2.2.3")] +[assembly: AssemblyVersion("2.2.2.4")] +[assembly: AssemblyFileVersion("2.2.2.4")] From aad8521479a2963092fb64cbaa4134e66ef86508 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:22:01 -0600 Subject: [PATCH 072/112] Fixed potential crash with IsAmbient check --- SceneManager/Utils/Extensions.cs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 1f20538..34c472b 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -54,15 +54,15 @@ namespace SceneManager.Utils } // Ped is in a vehicle - if (taskInVehicleBasic) + if (ped.CurrentVehicle) { //Game.LogTrivial($"Ped is in a vehicle."); // Ped has a controlled driving task - if (taskControlVehicle) - { - //Game.LogTrivial($"Ped has a controlled driving task. (non-ambient)"); - return false; - } + //if (taskControlVehicle) + //{ + // //Game.LogTrivial($"Ped has a controlled driving task. (non-ambient)"); + // return false; + //} // Ped has a wander driving task if (taskCarDriveWander) @@ -72,23 +72,19 @@ namespace SceneManager.Utils } // If the ped is in a vehicle but doesn't have a driving task, then it's a passenger. Check if the vehicle's driver has a driving wander task - var driverHasWanderTask = Rage.Native.NativeFunction.Natives.GET_IS_TASK_ACTIVE(ped.CurrentVehicle.Driver, 151); - if (driverHasWanderTask) + if (ped.CurrentVehicle.Driver && ped.CurrentVehicle.Driver != ped) { - //Game.LogTrivial($"Ped is a passenger. Vehicle's driver has a wander driving task. (ambient)"); - return true; + var driverHasWanderTask = Rage.Native.NativeFunction.Natives.GET_IS_TASK_ACTIVE(ped.CurrentVehicle.Driver, 151); + if (driverHasWanderTask) + { + //Game.LogTrivial($"Ped is a passenger. Vehicle's driver has a wander driving task. (ambient)"); + return true; + } } } if (ped.IsOnFoot) { - // UB unit on-foot, waiting for interaction - if (ped.RelationshipGroup.Name == "UBCOP") - { - //Game.LogTrivial($"Cop is UB unit. (non-ambient)"); - return false; - } - // Cop ped walking around or standing still if ((taskComplexControlMovement && taskWanderingScenario) || (taskAmbientClips && taskUseScenario)) { From cc80401c55f18fd70349432a5d58aad931696113 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:22:34 -0600 Subject: [PATCH 073/112] Path ChangeName dialog default text changed to path's current name --- SceneManager/Paths/Path.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index 40967da..14019fd 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -316,7 +316,7 @@ namespace SceneManager.Paths internal void ChangeName() { - var pathName = UserInput.PromptPlayerForFileName("Type the name you would like for your path", "Enter a path name", 100); + var pathName = UserInput.PromptPlayerForFileName("Type the name you would like for your path", $"{Name}", 100); if (string.IsNullOrWhiteSpace(pathName)) { Game.DisplayHelp($"Invalid path name given. Name cannot be null, empty, or consist of just white spaces. Defaulting to ~b~\"{Name}\""); From 4bae2d713e287beba7fa40a780739918c930366b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:41:33 -0600 Subject: [PATCH 074/112] Add validity check to CollectedPed on waypoint task --- SceneManager/CollectedPeds/CollectedPed.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/CollectedPeds/CollectedPed.cs b/SceneManager/CollectedPeds/CollectedPed.cs index 84ca437..dff8c94 100644 --- a/SceneManager/CollectedPeds/CollectedPed.cs +++ b/SceneManager/CollectedPeds/CollectedPed.cs @@ -161,7 +161,7 @@ namespace SceneManager.CollectedPeds var oldPosition = Path.Waypoints[currentWaypointTask].Position; SkipWaypoint = false; - if (this == null || !CurrentVehicle || Dismissed || Directed) + if (this == null || !this || !CurrentVehicle || Dismissed || Directed) { Game.LogTrivial($"Vehicle dismissed, directed, or null, return"); return; From 8e5821006b9a5ec0ba13a880032e622d675d4170 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:41:49 -0600 Subject: [PATCH 075/112] Increased menu max items property --- SceneManager/Menus/BarrierMenu.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index 6c96eb0..ff69003 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -41,6 +41,7 @@ namespace SceneManager.Menus internal static void Build() { Menu.Clear(); + Menu.MaxItemsOnScreen = 11; Menu.AddItem(BarrierList); BarrierList.ForeColor = Color.Gold; From 84223508cbef34b39595835fcc7f6a055b1c5eb5 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:42:04 -0600 Subject: [PATCH 076/112] Menu description now shows path currently being edited --- SceneManager/Menus/EditPathMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 1f49bba..587f548 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -101,7 +101,7 @@ namespace SceneManager { var scrollerItems = new List { }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); - //CurrentPath = PathManager.Paths[PathMainMenu.EditPath.Index]; + Menu.SubtitleText = $"Currently editing path {CurrentPath.Name}"; ChangePathName.Description = $"Change the path name from ~b~{CurrentPath.Name} ~w~to something else."; } } From 4ee9d1e3dabc4bb777d02507724b95d8dddcc8b9 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:42:33 -0600 Subject: [PATCH 077/112] Attempted to fix modified collection crash in waypoint collection loop --- SceneManager/Paths/Path.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index 14019fd..75fe11d 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -239,9 +239,9 @@ namespace SceneManager.Paths var collectorWaypoints = Waypoints.Where(x => x.IsCollector); var vehiclesInWorld = World.GetAllVehicles().Where(x => x); - foreach (Waypoint waypoint in collectorWaypoints) + foreach (Waypoint waypoint in collectorWaypoints.ToList()) { - foreach (Vehicle vehicle in vehiclesInWorld) + foreach (Vehicle vehicle in vehiclesInWorld.ToList()) { if (vehicle.IsNearCollectorWaypoint(waypoint) && vehicle.IsValidForPathCollection(this)) { From bc2979de8c606f97ef37ff1f9ddbd5c2e348580f Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 06:43:28 -0600 Subject: [PATCH 078/112] Fixed null crash --- SceneManager/Utils/DismissDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs index 6228119..3c505f6 100644 --- a/SceneManager/Utils/DismissDriver.cs +++ b/SceneManager/Utils/DismissDriver.cs @@ -33,7 +33,7 @@ namespace SceneManager.Utils } else { - CollectedPed collectedPed = PathManager.Paths.SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle == nearbyVehicle); + CollectedPed collectedPed = PathManager.Paths.Where(x => x != null).SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle == nearbyVehicle); if(collectedPed != null) { collectedPed.Dismiss((Dismiss)dismissIndex); From 7bc6303eb7a51b01941344f251514490ee69da4c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 07:05:47 -0600 Subject: [PATCH 079/112] Removed ToList from vehiclesInWorld loop --- SceneManager/Paths/Path.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index 75fe11d..b5fae34 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -241,7 +241,7 @@ namespace SceneManager.Paths foreach (Waypoint waypoint in collectorWaypoints.ToList()) { - foreach (Vehicle vehicle in vehiclesInWorld.ToList()) + foreach (Vehicle vehicle in vehiclesInWorld) { if (vehicle.IsNearCollectorWaypoint(waypoint) && vehicle.IsValidForPathCollection(this)) { From 7e7bf6fae52d8c9e8ff8d0dc6c221cd021d3d7d1 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 07:06:03 -0600 Subject: [PATCH 080/112] Fixed invalid CurrentVehicle crash --- SceneManager/Utils/DismissDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs index 3c505f6..23d5935 100644 --- a/SceneManager/Utils/DismissDriver.cs +++ b/SceneManager/Utils/DismissDriver.cs @@ -33,7 +33,7 @@ namespace SceneManager.Utils } else { - CollectedPed collectedPed = PathManager.Paths.Where(x => x != null).SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle == nearbyVehicle); + CollectedPed collectedPed = PathManager.Paths.Where(x => x != null).SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle && x.CurrentVehicle == nearbyVehicle); if(collectedPed != null) { collectedPed.Dismiss((Dismiss)dismissIndex); From e7be1dc8202ca3c466515ba7a33dd19ff9e1d53c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 07:11:31 -0600 Subject: [PATCH 081/112] Fixed invalid CollectedPed crash --- SceneManager/Utils/DismissDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/DismissDriver.cs b/SceneManager/Utils/DismissDriver.cs index 23d5935..a2ec3d2 100644 --- a/SceneManager/Utils/DismissDriver.cs +++ b/SceneManager/Utils/DismissDriver.cs @@ -33,7 +33,7 @@ namespace SceneManager.Utils } else { - CollectedPed collectedPed = PathManager.Paths.Where(x => x != null).SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x.CurrentVehicle && x.CurrentVehicle == nearbyVehicle); + CollectedPed collectedPed = PathManager.Paths.Where(x => x != null).SelectMany(x => x.CollectedPeds).FirstOrDefault(x => x != null && x.CurrentVehicle == nearbyVehicle); if(collectedPed != null) { collectedPed.Dismiss((Dismiss)dismissIndex); From 132b89dd25a87012acbc27dffd87c7b7792b9fcd Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:28:16 -0600 Subject: [PATCH 082/112] Added null check to barrier creation --- SceneManager/Barriers/Barrier.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SceneManager/Barriers/Barrier.cs b/SceneManager/Barriers/Barrier.cs index dfd26c1..14dca5f 100644 --- a/SceneManager/Barriers/Barrier.cs +++ b/SceneManager/Barriers/Barrier.cs @@ -36,6 +36,11 @@ namespace SceneManager.Barriers } _object = new Object(ModelName, Position, Heading); + if(!_object) + { + Game.LogTrivial($"New barrier object is invalid."); + return; + } _object.SetPositionWithSnap(Position); Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); From 20f6cf0df57df84784487b83f34294b375be504b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:28:57 -0600 Subject: [PATCH 083/112] Added null check to CollectedPed creaetion. Replaced 100ms Sleep in DrivingToWaypoint loop with Yield --- SceneManager/CollectedPeds/CollectedPed.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SceneManager/CollectedPeds/CollectedPed.cs b/SceneManager/CollectedPeds/CollectedPed.cs index dff8c94..9ac98f3 100644 --- a/SceneManager/CollectedPeds/CollectedPed.cs +++ b/SceneManager/CollectedPeds/CollectedPed.cs @@ -19,6 +19,10 @@ namespace SceneManager.CollectedPeds internal CollectedPed(Ped ped, Path path, Waypoint waypoint) { + if(!ped) + { + Game.LogTrivial($"Ped is invalid."); + } Handle = ped.Handle; Path = path; CurrentWaypoint = waypoint; @@ -223,6 +227,7 @@ namespace SceneManager.CollectedPeds if (CurrentVehicle) { Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] driver [{Handle}] should have a task now."); } else { @@ -230,7 +235,8 @@ namespace SceneManager.CollectedPeds return; } } - GameFiber.Sleep(100); + //GameFiber.Sleep(100); + GameFiber.Yield(); } } } From 58dd8afa223719e915e214f987029b9060a0cf18 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:29:45 -0600 Subject: [PATCH 084/112] Fixed remove all barriers sometimes spawning barriers. Fixed replace barriers sometimes duplicating barriers. --- SceneManager/Managers/BarrierManager.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/SceneManager/Managers/BarrierManager.cs b/SceneManager/Managers/BarrierManager.cs index 7b27719..c4c9333 100644 --- a/SceneManager/Managers/BarrierManager.cs +++ b/SceneManager/Managers/BarrierManager.cs @@ -215,10 +215,9 @@ namespace SceneManager.Managers case 2: foreach (Barrier barrier in Barriers) { - path = PathManager.Paths.FirstOrDefault(x => x != null && x.Barriers.Contains(barrier)); - if (path != null) + if(barrier.Path != null) { - path.Barriers.Remove(barrier); + barrier.Path.Barriers.Remove(barrier); } barrier.Delete(); @@ -237,22 +236,19 @@ namespace SceneManager.Managers internal static void ResetBarriers() { - GameFiber.StartNew(() => - { + //GameFiber.StartNew(() => + //{ var currentBarriers = Barriers.Where(b => b.ModelName != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash foreach (Barrier barrier in currentBarriers) { var newBarrier = new Barrier(barrier, barrier.Invincible, barrier.Immobile, barrier.TextureVariation, barrier.LightsEnabled); Barriers.Add(newBarrier); - if (barrier.IsValid()) - { - barrier.Delete(); - } + //barrier.Delete(); Barriers.Remove(barrier); } currentBarriers.Clear(); - }, "Barrier Reset Fiber"); + //}, "Barrier Reset Fiber"); } From c9e40a49d98a57a6eea353c1815cf2e48efc282a Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:29:58 -0600 Subject: [PATCH 085/112] Commented out unused code --- SceneManager/Managers/PathManager.cs | 90 ++++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/SceneManager/Managers/PathManager.cs b/SceneManager/Managers/PathManager.cs index 280f196..3a17df3 100644 --- a/SceneManager/Managers/PathManager.cs +++ b/SceneManager/Managers/PathManager.cs @@ -15,60 +15,60 @@ namespace SceneManager.Managers internal static Paths.Path[] Paths { get; } = new Paths.Path[10]; internal static Dictionary> ImportedPaths { get; } = new Dictionary>(); - internal static Paths.Path ImportPath(Paths.Path importedPath) - { - importedPath.State = State.Creating; - var firstVacantIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); - if (firstVacantIndex < 0) - { - firstVacantIndex = 0; - } - var pathNumber = firstVacantIndex + 1; + //internal static Paths.Path ImportPath(Paths.Path importedPath) + //{ + // importedPath.State = State.Creating; + // var firstVacantIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); + // if (firstVacantIndex < 0) + // { + // firstVacantIndex = 0; + // } + // var pathNumber = firstVacantIndex + 1; - importedPath.Number = pathNumber; - Paths[firstVacantIndex] = importedPath; + // importedPath.Number = pathNumber; + // Paths[firstVacantIndex] = importedPath; - Game.LogTrivial($"Importing {importedPath.Name} at Paths index {firstVacantIndex}"); - Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Importing path: ~b~{importedPath.Name} ~w~."); + // Game.LogTrivial($"Importing {importedPath.Name} at Paths index {firstVacantIndex}"); + // Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Importing path: ~b~{importedPath.Name} ~w~."); - return importedPath; - } + // return importedPath; + //} - internal static void ExportPath() - { - var currentPath = Paths[PathMainMenu.EditPath.Index]; + //internal static void ExportPath() + //{ + // var currentPath = Paths[PathMainMenu.EditPath.Index]; - // If the path is in the import menu, autosave with the same name. - if(ImportPathMenu.Menu.MenuItems.Any(x=> x.Text == currentPath.Name)) - { - Game.LogTrivial($"Autosaving {currentPath.Name}"); - currentPath.Save(); - } - else - { - // Reference PNWParks's UserInput class from LiveLights - var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + // // If the path is in the import menu, autosave with the same name. + // if(ImportPathMenu.Menu.MenuItems.Any(x=> x.Text == currentPath.Name)) + // { + // Game.LogTrivial($"Autosaving {currentPath.Name}"); + // currentPath.Save(); + // } + // else + // { + // // Reference PNWParks's UserInput class from LiveLights + // var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); - // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) - if (string.IsNullOrWhiteSpace(filename)) - { - Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - return; - } + // // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) + // if (string.IsNullOrWhiteSpace(filename)) + // { + // Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + // Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); + // return; + // } - Game.LogTrivial($"Filename: {filename}"); - currentPath.Name = filename; - currentPath.Save(); - } + // Game.LogTrivial($"Filename: {filename}"); + // currentPath.Name = filename; + // currentPath.Save(); + // } - PathMainMenu.ImportPath.Enabled = true; - ImportPathMenu.Build(); - PathMainMenu.Build(); - BarrierMenu.Build(); + // PathMainMenu.ImportPath.Enabled = true; + // ImportPathMenu.Build(); + // PathMainMenu.Build(); + // BarrierMenu.Build(); - PathMainMenu.Menu.Visible = true; - } + // PathMainMenu.Menu.Visible = true; + //} internal static Paths.Path InitializeNewPath() { From 8386a47a9007cec9e1050048fad40026eb50ebd0 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:30:12 -0600 Subject: [PATCH 086/112] Updated menu subtitle text --- SceneManager/Menus/EditPathMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 587f548..3a753ea 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -101,7 +101,7 @@ namespace SceneManager { var scrollerItems = new List { }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); - Menu.SubtitleText = $"Currently editing path {CurrentPath.Name}"; + Menu.SubtitleText = $"~o~Currently editing: ~b~{CurrentPath.Name}"; ChangePathName.Description = $"Change the path name from ~b~{CurrentPath.Name} ~w~to something else."; } } From f19f2bc79dd25e2c04c483f1b80c2f0ec0fdf3a8 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:30:43 -0600 Subject: [PATCH 087/112] Added menu item badges to show which files have been imported --- SceneManager/Menus/ImportPathMenu.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/SceneManager/Menus/ImportPathMenu.cs b/SceneManager/Menus/ImportPathMenu.cs index a19fbc9..026636a 100644 --- a/SceneManager/Menus/ImportPathMenu.cs +++ b/SceneManager/Menus/ImportPathMenu.cs @@ -17,6 +17,8 @@ namespace SceneManager.Menus internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Import Path Menu"); internal static UIMenuItem Import { get; } = new UIMenuItem("Import", "Import the selected paths."); + private static List _HasBeenImported = new List(); + internal static void Initialize() { Menu.ParentMenu = PathMainMenu.Menu; @@ -33,7 +35,12 @@ namespace SceneManager.Menus PathManager.ImportPaths(); foreach(KeyValuePair> kvp in PathManager.ImportedPaths) { - Menu.AddItem(new UIMenuCheckboxItem(kvp.Key, false)); + var menuItem = new UIMenuCheckboxItem(kvp.Key, false); + if(!_HasBeenImported.Contains(kvp.Key)) + { + menuItem.LeftBadge = UIMenuItem.BadgeStyle.Star; + } + Menu.AddItem(menuItem); } Menu.AddItem(Import); @@ -72,6 +79,7 @@ namespace SceneManager.Menus PathManager.Paths[pathToReplaceIndex] = path; path.Load(); Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); + _HasBeenImported.Add(PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Key); continue; } else @@ -85,6 +93,7 @@ namespace SceneManager.Menus var firstNullPathIndex = Array.IndexOf(PathManager.Paths, PathManager.Paths.First(x => x == null)); PathManager.Paths[firstNullPathIndex] = path; path.Load(); + _HasBeenImported.Add(PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Key); } var numberOfNonNullPaths = PathManager.Paths.Where(x => x != null).Count(); From c3e401193b1d08370c4202a462de8c9083721523 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:32:51 -0600 Subject: [PATCH 088/112] Added check for vehicle's driver before creating new CollectedPed --- SceneManager/Paths/Path.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index b5fae34..42a2615 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -237,14 +237,25 @@ namespace SceneManager.Paths int checksDone = 0; var collectorWaypoints = Waypoints.Where(x => x.IsCollector); - var vehiclesInWorld = World.GetAllVehicles().Where(x => x); foreach (Waypoint waypoint in collectorWaypoints.ToList()) { - foreach (Vehicle vehicle in vehiclesInWorld) + foreach (Vehicle vehicle in World.GetAllVehicles().Where(x => x)) { if (vehicle.IsNearCollectorWaypoint(waypoint) && vehicle.IsValidForPathCollection(this)) { + while(!vehicle.Driver) + { + GameFiber.Yield(); + if (!vehicle) + { + break; + } + } + if (!vehicle) + { + continue; + } CollectedPeds.Add(new CollectedPed(vehicle.Driver, this, waypoint)); } From 97c6fd91c6a8704b5504deb4a7dcca99b2e57fb0 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Sun, 23 May 2021 08:33:23 -0600 Subject: [PATCH 089/112] Added more guard clauses to IsValidForPathCollection --- SceneManager/Utils/Extensions.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 34c472b..6fc2453 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -116,11 +116,6 @@ namespace SceneManager.Utils /// internal static bool IsNearCollectorWaypoint(this Vehicle vehicle, Waypoint waypoint) { - if(!waypoint.IsCollector) - { - return false; - } - return vehicle.FrontPosition.DistanceTo2D(waypoint.Position) <= waypoint.CollectorRadius && Math.Abs(waypoint.Position.Z - vehicle.Position.Z) < 3; } @@ -137,6 +132,16 @@ namespace SceneManager.Utils return false; } + if(path.BlacklistedVehicles.Contains(vehicle)) + { + return false; + } + + if(vehicle == Game.LocalPlayer.Character.LastVehicle) + { + return false; + } + if (vehicle.Driver) { if (!vehicle.Driver.IsAlive) @@ -153,7 +158,7 @@ namespace SceneManager.Utils } } - if (vehicle != Game.LocalPlayer.Character.LastVehicle && (vehicle.IsCar || vehicle.IsBike || vehicle.IsBicycle || vehicle.IsQuadBike) && !vehicle.IsSirenOn && vehicle.IsEngineOn && vehicle.IsOnAllWheels && vehicle.Speed > 1 && !path.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle) && !path.BlacklistedVehicles.Contains(vehicle)) + if ((vehicle.IsCar || vehicle.IsBike || vehicle.IsBicycle || vehicle.IsQuadBike) && !vehicle.IsSirenOn && vehicle.IsEngineOn && vehicle.IsOnAllWheels && vehicle.Speed > 1 && !path.CollectedPeds.Any(cp => cp && cp.CurrentVehicle == vehicle)) { if (!vehicle.HasDriver) { @@ -166,7 +171,7 @@ namespace SceneManager.Utils { return false; } - + Game.LogTrivial($"Vehicle has a new driver"); vehicle.Driver.IsPersistent = true; vehicle.Driver.BlockPermanentEvents = true; } From e563612ab059530d613f2239932c84d5656e5d9d Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:19:16 -0600 Subject: [PATCH 090/112] Fixed flare spawn --- SceneManager/Barriers/Barrier.cs | 91 ++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/SceneManager/Barriers/Barrier.cs b/SceneManager/Barriers/Barrier.cs index 14dca5f..0e0cac4 100644 --- a/SceneManager/Barriers/Barrier.cs +++ b/SceneManager/Barriers/Barrier.cs @@ -35,30 +35,40 @@ namespace SceneManager.Barriers obj.Delete(); } - _object = new Object(ModelName, Position, Heading); - if(!_object) + if (ModelName == "0xa2c44e80") // Flare { - Game.LogTrivial($"New barrier object is invalid."); - return; - } + var flare = new Weapon("weapon_flare", Position, 1); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true); + _object = flare; - _object.SetPositionWithSnap(Position); - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); - - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); - if (Invincible) - { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); - if (ModelName != "prop_barrier_wat_03a") + GameFiber.StartNew(() => { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); - } + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + GameFiber.Sleep(1000); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, false); + }, "Spawn Flare Fiber"); } - _object.IsPositionFrozen = Immobile; - - if (Settings.EnableAdvancedBarricadeOptions) + else // Any other barrier object { - SetAdvancedOptions(); + _object = new Object(ModelName, Position, Heading); + _object.SetPositionWithSnap(Position); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + + if (Invincible) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); + if (ModelName != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); + } + } + _object.IsPositionFrozen = Immobile; + + if (Settings.EnableAdvancedBarricadeOptions) + { + SetAdvancedOptions(); + } } } @@ -76,25 +86,38 @@ namespace SceneManager.Barriers BarrierManager.PlaceholderBarrier.Delete(); } - _object = new Object(ModelName, Position, Heading); - - _object.SetPositionWithSnap(Position); - Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); - - Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); - if (Invincible) + if (ModelName == "0xa2c44e80") // Flare { - Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); - if (ModelName != "prop_barrier_wat_03a") + _object = obj; + + GameFiber.StartNew(() => { - Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); - } + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + GameFiber.Sleep(1000); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, false); + }, "Spawn Flare Fiber"); } - _object.IsPositionFrozen = Immobile; - - if (Settings.EnableAdvancedBarricadeOptions) + else // Any other barrier object { - SetAdvancedOptions(); + _object = new Object(ModelName, Position, Heading); + _object.SetPositionWithSnap(Position); + Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(_object); + Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(_object, true); + + if (Invincible) + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(_object, true); + if (ModelName != "prop_barrier_wat_03a") + { + Rage.Native.NativeFunction.Natives.SET_DISABLE_BREAKING(_object, true); + } + } + _object.IsPositionFrozen = Immobile; + + if (Settings.EnableAdvancedBarricadeOptions) + { + SetAdvancedOptions(); + } } } From eb5fbfa1bc07cd923aea70386e1e15d4fa518823 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:19:49 -0600 Subject: [PATCH 091/112] Fixed duplicate ped creation --- SceneManager/CollectedPeds/CollectedPed.cs | 191 ++++++++++----------- 1 file changed, 94 insertions(+), 97 deletions(-) diff --git a/SceneManager/CollectedPeds/CollectedPed.cs b/SceneManager/CollectedPeds/CollectedPed.cs index 9ac98f3..a73d0a7 100644 --- a/SceneManager/CollectedPeds/CollectedPed.cs +++ b/SceneManager/CollectedPeds/CollectedPed.cs @@ -9,26 +9,22 @@ namespace SceneManager.CollectedPeds { internal class CollectedPed : Ped { - internal Path Path { get; private set; } - internal Waypoint CurrentWaypoint { get; private set; } + internal Path Path { get; set; } + internal Waypoint CurrentWaypoint { get; 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) + internal CollectedPed(Ped basePed, Path path, Waypoint waypoint) : base(basePed.Handle) { - if(!ped) - { - Game.LogTrivial($"Ped is invalid."); - } - Handle = ped.Handle; + Handle = basePed.Handle; Path = path; CurrentWaypoint = waypoint; SetPersistence(); - Game.LogTrivial($"Added {CurrentVehicle.Model.Name} to collection from path {Path.Number} waypoint {CurrentWaypoint.Number}."); - + Game.LogTrivial($"Added {CurrentVehicle.Model.Name} to collection from path \"{Path.Name}\" waypoint {CurrentWaypoint.Number}."); + GameFiber.StartNew(() => AssignWaypointTasks(), "Task Assignment Fiber"); } @@ -60,16 +56,19 @@ namespace SceneManager.CollectedPeds DriveToNextWaypoint(); } - if (Path.State == State.Deleting || (!Dismissed && !VehicleAndDriverAreValid()) || Directed) + if (Path.State == State.Deleting || !VehicleAndDriverAreValid()) { + Dismiss(); return; } - Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] all Path {Path.Number} tasks complete."); - if (!Dismissed) + if(Directed) { - Dismiss(); + Dismiss(Utils.Dismiss.FromDirected); } + + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] all path \"{Path.Name}\" tasks complete."); + Dismiss(); } private void AssignDirectedTask() @@ -107,7 +106,7 @@ namespace SceneManager.CollectedPeds { float acceptedDistance = GetAcceptedStoppingDistance(Path.Waypoints, Path.Waypoints.IndexOf(CurrentWaypoint)); Vector3 oldPosition = CurrentWaypoint.Position; - Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path {Path.Number} waypoint {CurrentWaypoint.Number} (directed)"); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path \"{Path.Name}\" waypoint {CurrentWaypoint.Number} (directed)"); Tasks.DriveToPosition(CurrentWaypoint.Position, CurrentWaypoint.Speed, (VehicleDrivingFlags)CurrentWaypoint.DrivingFlagType, acceptedDistance); LoopWhileDrivingToDirectedWaypoint(); @@ -159,7 +158,7 @@ namespace SceneManager.CollectedPeds return; } - Game.LogTrivial($"Preparing to run task loop for {CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] on path {Path.Number}"); + Game.LogTrivial($"Preparing to run task loop for {CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] on path \"{Path.Name}\""); for (int currentWaypointTask = CurrentWaypoint.Number; currentWaypointTask < Path.Waypoints.Count; currentWaypointTask++) { var oldPosition = Path.Waypoints[currentWaypointTask].Position; @@ -181,7 +180,7 @@ namespace SceneManager.CollectedPeds 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})"); + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] is driving to path \"{Path.Name}\" 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); @@ -212,6 +211,7 @@ namespace SceneManager.CollectedPeds void LoopWhileDrivingToWaypoint(int currentWaypointTask, float acceptedDistance, Vector3 oldPosition) { + int lostTasks = 0; while (VehicleAndDriverAreValid() && !Dismissed && !SkipWaypoint && !Directed && Path.Waypoints.ElementAtOrDefault(currentWaypointTask) != null && CurrentVehicle.FrontPosition.DistanceTo2D(Path.Waypoints[currentWaypointTask].Position) > acceptedDistance) { if (oldPosition != Path.Waypoints[currentWaypointTask].Position) @@ -224,9 +224,16 @@ namespace SceneManager.CollectedPeds { //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(lostTasks == 3) + { + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] driver [{Handle}] lost their task too many times. Dismissing from world to prevent problems."); + Dismiss(Utils.Dismiss.FromWorld); + return; + } if (CurrentVehicle) { Tasks.DriveToPosition(Path.Waypoints[currentWaypointTask].Position, Path.Waypoints[currentWaypointTask].Speed, (VehicleDrivingFlags)Path.Waypoints[currentWaypointTask].DrivingFlagType, acceptedDistance); + lostTasks++; Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] driver [{Handle}] should have a task now."); } else @@ -235,8 +242,7 @@ namespace SceneManager.CollectedPeds return; } } - //GameFiber.Sleep(100); - GameFiber.Yield(); + GameFiber.Sleep(100); } } } @@ -244,7 +250,7 @@ namespace SceneManager.CollectedPeds 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."); + Game.LogTrivial($"{CurrentVehicle.Model.Name} stopping at path \"{CurrentWaypoint.Path.Name}\" waypoint."); var vehicleToStop = CurrentVehicle; Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(vehicleToStop, stoppingDistance, -1, true); StoppedAtWaypoint = true; @@ -258,32 +264,23 @@ namespace SceneManager.CollectedPeds Game.LogTrivial($"{vehicleToStop.Model.Name} releasing from stop waypoint."); Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(vehicleToStop, 0f, 1, true); } - - //if (this && OriginalVehicle) - //{ - // Game.LogTrivial($"{OriginalVehicle.Model.Name} releasing from stop waypoint."); - // Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(OriginalVehicle, 0f, 1, true); - // Tasks.CruiseWithVehicle(5f); - //} } private bool VehicleAndDriverAreValid() { - if (this == null || !this) + if (!this) { - Game.LogTrivial($"CollectedVehicle is null"); + Game.LogTrivial($"CollectedPed 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; @@ -291,26 +288,15 @@ namespace SceneManager.CollectedPeds internal void Dismiss(Dismiss dismissOption = Utils.Dismiss.FromPath, Path newPath = null) { - if(CurrentVehicle) + if(!this) { - if (StoppedAtWaypoint) - { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(CurrentVehicle, 0f, 1, true); - } - CurrentVehicle.Dismiss(); - } - if (this) - { - base.Dismiss(); - } - if (!CurrentVehicle) - { - Game.LogTrivial($"Vehicle is null."); + Game.LogTrivial($"CollectedPed is not valid in Dismiss."); + Path.CollectedPeds.Remove(this); return; } - if (!this) + if(Dismissed) { - Game.LogTrivial($"Driver is null."); + Game.LogTrivial($"CollectedPed is already dismissed."); return; } @@ -320,13 +306,7 @@ namespace SceneManager.CollectedPeds return; } - if (dismissOption == Utils.Dismiss.FromPlayer) - { - DismissFromPlayer(); - return; - } - - if(CurrentVehicle && StoppedAtWaypoint) + if (CurrentVehicle && StoppedAtWaypoint) { StoppedAtWaypoint = false; Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(LastVehicle, 0f, 1, true); @@ -344,40 +324,49 @@ namespace SceneManager.CollectedPeds DismissFromPath(); } - if(dismissOption == Utils.Dismiss.FromDirected) + 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) + if (GetAttachedBlip()) + { + GetAttachedBlip().Delete(); + } + while (this && CurrentVehicle && CurrentVehicle.HasOccupants) { foreach (Ped occupant in CurrentVehicle.Occupants) { - occupant.Dismiss(); occupant.Delete(); } GameFiber.Yield(); } - CurrentVehicle.Delete(); + if(!this) + { + Path.CollectedPeds.Remove(this); + return; + } + if (CurrentVehicle) + { + CurrentVehicle.Delete(); + } + Path.CollectedPeds.Remove(this); } void DismissFromWaypoint() { - if (CurrentWaypoint == null || Path == null) + if (Path == null) { - Game.LogTrivial($"CurrentWaypoint or Path is null"); + Game.LogTrivial($"Path is null"); + return; + } + + if(CurrentWaypoint == null) + { + Game.LogTrivial($"CurrentWaypoint is null"); return; } @@ -394,18 +383,27 @@ namespace SceneManager.CollectedPeds void DismissFromPath() { + if(!this) + { + Game.LogTrivial($"CollectedPed is not valid in DismissFromPath."); + Path.CollectedPeds.Remove(this); + return; + } + + if(Dismissed) + { + Game.LogTrivial($"CollectedPed is already dismissed."); + return; + } + 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(() => - { + //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 + //if (nearestCollectorWaypoint != null) //{ // while (nearestCollectorWaypoint != null && CurrentVehicle && CurrentVehicle.HasDriver && this && IsAlive && CurrentVehicle.FrontPosition.DistanceTo2D(nearestCollectorWaypoint.Position) <= nearestCollectorWaypoint.CollectorRadius) // { @@ -413,34 +411,33 @@ namespace SceneManager.CollectedPeds // } //} - if (!this || !CurrentVehicle) + if (!Directed) + { + if (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()) { - if (GetAttachedBlip()) - { - GetAttachedBlip().Delete(); - } - BlockPermanentEvents = false; - base.Dismiss(); + GetAttachedBlip().Delete(); } + BlockPermanentEvents = false; + IsPersistent = false; + base.Dismiss(); + } + + if (CurrentVehicle) + { + Game.LogTrivial($"{CurrentVehicle.Model.Name} [{CurrentVehicle.Handle}] dismissed successfully."); + LastVehicle.Dismiss(); + if (CurrentVehicle) { - CurrentVehicle.Dismiss(); - CurrentVehicle.IsSirenOn = false; - CurrentVehicle.IsSirenSilent = true; + LastVehicle.IsSirenOn = false; + LastVehicle.IsSirenSilent = true; } } - }, "DismissFromPath Fiber"); - + Path.CollectedPeds.Remove(this); + } + //}, "DismissFromPath Fiber"); } void DismissFromDirect() From 36fdf258997e3ba35c690582acd07fa5487f32fe Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:20:15 -0600 Subject: [PATCH 092/112] Added help message when resetting barriers --- SceneManager/Managers/BarrierManager.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/SceneManager/Managers/BarrierManager.cs b/SceneManager/Managers/BarrierManager.cs index c4c9333..211ccb9 100644 --- a/SceneManager/Managers/BarrierManager.cs +++ b/SceneManager/Managers/BarrierManager.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Rage; +using RAGENativeUI; using SceneManager.Barriers; using SceneManager.Menus; using SceneManager.Paths; @@ -159,19 +160,6 @@ namespace SceneManager.Managers { var flare = new Weapon("weapon_flare", PlaceholderBarrier.Position, 1); Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true); - GameFiber.Sleep(1); - GameFiber.StartNew(() => - { - while (flare && flare.HeightAboveGround > 0.05f) - { - GameFiber.Yield(); - } - GameFiber.Sleep(1000); - if (flare) - { - flare.IsPositionFrozen = true; - } - }, "Spawn Flare Fiber"); barrier = new Barrier(flare, BarrierMenu.Invincible.Checked, BarrierMenu.Immobile.Checked); Barriers.Add(barrier); @@ -238,6 +226,7 @@ namespace SceneManager.Managers { //GameFiber.StartNew(() => //{ + Game.DisplayHelp($"~{InstructionalKey.SymbolBusySpinner.GetId()}~ Resetting barriers..."); var currentBarriers = Barriers.Where(b => b.ModelName != "0xa2c44e80").ToList(); // 0xa2c44e80 is the flare weapon hash foreach (Barrier barrier in currentBarriers) { From 5130a42c7dc9e1af832f45b53782f83f33145e96 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:20:45 -0600 Subject: [PATCH 093/112] Added SetMenuWidth method --- SceneManager/Managers/MenuManager.cs | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/SceneManager/Managers/MenuManager.cs b/SceneManager/Managers/MenuManager.cs index e14454d..26adf0d 100644 --- a/SceneManager/Managers/MenuManager.cs +++ b/SceneManager/Managers/MenuManager.cs @@ -1,5 +1,6 @@ using RAGENativeUI; using SceneManager.Menus; +using SceneManager.Utils; using Rage; using System.Linq; using RAGENativeUI.Elements; @@ -50,6 +51,11 @@ namespace SceneManager.Managers PathCreationMenu.Build(); EditPathMenu.Build(); BarrierMenu.Build(); + foreach(UIMenu menu in MenuPool) + { + //Game.LogTrivial($"Setting with of {menu.SubtitleText} menu."); + SetMenuWidth(menu); + } } internal static void ColorMenuItems() @@ -77,5 +83,52 @@ namespace SceneManager.Managers GameFiber.Yield(); } } + + internal static void SetMenuWidth(UIMenu menu) + { + float MINIMUM_WIDTH = 0.25f; + //float PADDING = 0.00390625f * 2; // typical padding used in RNUI + float widthToAssign = MINIMUM_WIDTH; + //float scrollerItemWidth = 0; + //float totalWidth = 0; + + //Game.LogTrivial($"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + foreach(UIMenuItem menuItem in menu.MenuItems) + { + //Game.LogTrivial($"========== Menu Item: {menuItem.Text}"); + float textWidth = menuItem.GetTextWidth(); + //Game.LogTrivial($"Menu Item Text Width: {textWidth}"); + + float newWidth = textWidth; + if (menuItem.GetType() == typeof(UIMenuListScrollerItem)) + { + var scrollerItem = menuItem as UIMenuListScrollerItem; + float selectedItemTextWidth = scrollerItem.GetSelectedItemTextWidth(); + //Game.LogTrivial($"Menu Item Scroller Text Width: {selectedItemTextWidth}"); + + //totalWidth = textWidth + selectedItemTextWidth; + //Game.LogTrivial($"Total Width: {totalWidth}"); + + newWidth += selectedItemTextWidth * 1.3f; + //Game.LogTrivial($"========== New Width from Longer Selected Item Text: {newWidth}"); + } + + if (menuItem.LeftBadge != UIMenuItem.BadgeStyle.None) + { + newWidth += 0.02f; + } + + if(newWidth > 0.25f && menuItem.LeftBadge != UIMenuItem.BadgeStyle.None) + { + newWidth += 0.02f; + } + + if (newWidth > widthToAssign) + { + widthToAssign = newWidth; + } + } + menu.Width = widthToAssign; + } } } From 17cd498e5e07b0de642f81a8f481ea57d440344b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:21:13 -0600 Subject: [PATCH 094/112] Removed unused code, fixed serializer --- SceneManager/Managers/PathManager.cs | 139 ++++++++++----------------- 1 file changed, 52 insertions(+), 87 deletions(-) diff --git a/SceneManager/Managers/PathManager.cs b/SceneManager/Managers/PathManager.cs index 3a17df3..1cc9f2f 100644 --- a/SceneManager/Managers/PathManager.cs +++ b/SceneManager/Managers/PathManager.cs @@ -1,4 +1,5 @@ using Rage; +using RAGENativeUI; using SceneManager.Menus; using SceneManager.Utils; using SceneManager.Waypoints; @@ -6,7 +7,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Xml.Serialization; +using System.Windows.Forms; namespace SceneManager.Managers { @@ -14,61 +15,7 @@ namespace SceneManager.Managers { internal static Paths.Path[] Paths { get; } = new Paths.Path[10]; internal static Dictionary> ImportedPaths { get; } = new Dictionary>(); - - //internal static Paths.Path ImportPath(Paths.Path importedPath) - //{ - // importedPath.State = State.Creating; - // var firstVacantIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); - // if (firstVacantIndex < 0) - // { - // firstVacantIndex = 0; - // } - // var pathNumber = firstVacantIndex + 1; - - // importedPath.Number = pathNumber; - // Paths[firstVacantIndex] = importedPath; - - // Game.LogTrivial($"Importing {importedPath.Name} at Paths index {firstVacantIndex}"); - // Game.DisplayNotification($"~o~Scene Manager ~y~[Importing]\n~w~Importing path: ~b~{importedPath.Name} ~w~."); - - // return importedPath; - //} - - //internal static void ExportPath() - //{ - // var currentPath = Paths[PathMainMenu.EditPath.Index]; - - // // If the path is in the import menu, autosave with the same name. - // if(ImportPathMenu.Menu.MenuItems.Any(x=> x.Text == currentPath.Name)) - // { - // Game.LogTrivial($"Autosaving {currentPath.Name}"); - // currentPath.Save(); - // } - // else - // { - // // Reference PNWParks's UserInput class from LiveLights - // var filename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); - - // // If filename != null or empty, check if export directory exists (GTA V/Plugins/SceneManager/Saved Paths) - // if (string.IsNullOrWhiteSpace(filename)) - // { - // Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - // Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces."); - // return; - // } - - // Game.LogTrivial($"Filename: {filename}"); - // currentPath.Name = filename; - // currentPath.Save(); - // } - - // PathMainMenu.ImportPath.Enabled = true; - // ImportPathMenu.Build(); - // PathMainMenu.Build(); - // BarrierMenu.Build(); - - // PathMainMenu.Menu.Visible = true; - //} + internal static List LoadedFiles { get; } = new List(); internal static Paths.Path InitializeNewPath() { @@ -246,58 +193,76 @@ namespace SceneManager.Managers } } Array.Clear(Paths, 0, Paths.Length); - //Paths.Clear(); Game.LogTrivial($"All paths deleted"); Game.DisplayNotification($"~o~Scene Manager\n~w~All paths deleted."); - MainMenu.Build(); + Menus.MainMenu.Build(); } - internal static void ImportPaths() + internal static List ImportPathsFromFile(string file) { - ImportedPaths.Clear(); - - // Check if Saved Paths directory exists + List importedPaths; var GAME_DIRECTORY = Directory.GetCurrentDirectory(); var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) { Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist. No paths available to import."); - return; + return null; } - // Check if any XML files are available to import from Saved Paths - var savedPathNames = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); - if (savedPathNames.Length == 0) + var overrides = Serializer.DefineOverrides(); + try { - Game.LogTrivial($"No saved paths found."); - return; + importedPaths = Serializer.LoadItemFromXML>(SAVED_PATHS_DIRECTORY + Path.GetFileName(file) + ".xml", overrides); + ImportedPaths.Add(file, importedPaths); + } - else + catch (Exception ex) { - Game.LogTrivial($"{savedPathNames.Length} path(s) available to import."); + Game.DisplayNotification($"~y~Scene Manager ~w~[~r~ERROR~w~]: There was a problem importing file ~b~{file}~w~. This is likely due to an XML error. Double check any changes you've made to this file."); + Game.LogTrivial($"Error: {ex.Message}"); + return null; } - // Import paths - foreach (string pathName in savedPathNames) - { - var fileName = Path.GetFileNameWithoutExtension(pathName); - Game.LogTrivial($"File: {fileName}"); - - var overrides = DefineOverridesForCombinedPath(); - var paths = Serializer.LoadItemFromXML>(SAVED_PATHS_DIRECTORY + Path.GetFileName(pathName), overrides); - ImportedPaths.Add(fileName, paths); - } - Game.LogTrivial($"Successfully imported {ImportedPaths.Count} file(s)."); + return importedPaths; } - private static XmlAttributeOverrides DefineOverridesForCombinedPath() + internal static void LoadImportedPaths(List paths, string file) { - XmlAttributeOverrides overrides = new XmlAttributeOverrides(); - XmlAttributes attr = new XmlAttributes(); - attr.XmlRoot = new XmlRootAttribute("Paths"); - overrides.Add(typeof(List), attr); + foreach (Paths.Path path in paths) + { + if (Paths.Any(x => x != null && x.Name == path.Name)) + { + Game.DisplayHelp($"~y~Scene Manager ~w~[~o~WARNING~w~]:\nA path with the name ~b~{path.Name} ~w~already exists. Do you want to replace it? ~{Keys.Y.GetInstructionalId()}~ or ~{Keys.N.GetInstructionalId()}~"); + GameFiber.Sleep(100); + GameFiber.SleepUntil(() => Game.IsKeyDown(Keys.Y) || Game.IsKeyDown(Keys.N), 8300); - return overrides; + if (Game.IsKeyDown(Keys.Y)) + { + var pathToReplace = Paths.First(x => x.Name == path.Name); + var pathToReplaceIndex = Array.IndexOf(Paths, pathToReplace); + pathToReplace.Delete(); + Paths[pathToReplaceIndex] = path; + path.Load(); + Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); + LoadedFiles.Add(file); + continue; + } + else + { + Game.DisplayNotification($"~o~Scene Manager ~y~[Import]\n~w~Path ~b~{path.Name} ~w~was not imported."); + Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); + continue; + } + } + + var firstNullPathIndex = Array.IndexOf(Paths, Paths.First(x => x == null)); + Paths[firstNullPathIndex] = path; + path.Load(); + LoadedFiles.Add(file); + + var numberOfNonNullPaths = Paths.Where(x => x != null).Count(); + Game.LogTrivial($"{path.Name} added to paths collection. Paths count: {numberOfNonNullPaths}"); + } } } } From 0a5eb760482433a451b312f4771a159187e2de1d Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:21:37 -0600 Subject: [PATCH 095/112] Added dynamic menu width --- SceneManager/Menus/BarrierMenu.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/SceneManager/Menus/BarrierMenu.cs b/SceneManager/Menus/BarrierMenu.cs index ff69003..7335a68 100644 --- a/SceneManager/Menus/BarrierMenu.cs +++ b/SceneManager/Menus/BarrierMenu.cs @@ -31,6 +31,7 @@ namespace SceneManager.Menus { Menu.ParentMenu = MainMenu.Menu; MenuManager.MenuPool.Add(Menu); + Menu.MaxItemsOnScreen = 11; Menu.OnItemSelect += BarrierMenu_OnItemSelected; Menu.OnScrollerChange += BarrierMenu_OnScrollerChanged; @@ -41,7 +42,6 @@ namespace SceneManager.Menus internal static void Build() { Menu.Clear(); - Menu.MaxItemsOnScreen = 11; Menu.AddItem(BarrierList); BarrierList.ForeColor = Color.Gold; @@ -93,13 +93,19 @@ namespace SceneManager.Menus if (BarrierList.SelectedItem == "Flare") { RotateBarrier.Enabled = false; + Invincible.Enabled = false; + Immobile.Enabled = false; + BarrierTexture.Enabled = false; + SetBarrierLights.Enabled = false; } else { RotateBarrier.Enabled = true; + Invincible.Enabled = true; + Immobile.Enabled = true; + BarrierTexture.Enabled = true; + SetBarrierLights.Enabled = true; } - - Menu.Width = SetMenuWidth(); } private static void BarrierMenu_OnCheckboxChanged(UIMenu sender, UIMenuCheckboxItem checkbox, bool @checked) @@ -135,9 +141,10 @@ namespace SceneManager.Menus if (scrollerItem == RotateBarrier) { - //RotateBarrier(); BarrierManager.RotateBarrier(); } + + MenuManager.SetMenuWidth(Menu); } private static void BarrierMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index) @@ -165,7 +172,7 @@ namespace SceneManager.Menus private static void BarrierMenu_OnMenuOpen(UIMenu menu) { - var scrollerItems = new List { BarrierList, BarrierTexture, SetBarrierTrafficLight, RotateBarrier, RemoveBarrierOptions }; + var scrollerItems = new List { BarrierList, BarrierTexture, SetBarrierTrafficLight, RotateBarrier, AddToPath, AddUnassignedToPath, RemoveBarrierOptions }; //CreatePlaceholderBarrier(); BarrierManager.CreatePlaceholderBarrier(); From ac89da6cc814a0b4c9b0eae7b82c9fe29f40b957 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:22:12 -0600 Subject: [PATCH 096/112] Disabled option to dismiss driver if there are no paths --- SceneManager/Menus/DriverMenu.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SceneManager/Menus/DriverMenu.cs b/SceneManager/Menus/DriverMenu.cs index de6d937..dfad9db 100644 --- a/SceneManager/Menus/DriverMenu.cs +++ b/SceneManager/Menus/DriverMenu.cs @@ -39,11 +39,13 @@ namespace SceneManager.Menus DirectDriver.Enabled = true; Menu.AddItem(DismissDriver); DismissDriver.ForeColor = Color.Gold; + DismissDriver.Enabled = true; - if (PathManager.Paths.Length == 0) + if (PathManager.Paths.All(x => x == null)) { DirectOptions.Enabled = false; DirectDriver.Enabled = false; + DismissDriver.Enabled = false; } Menu.RefreshIndex(); From 5aba36f8298c1b6d210f786bcd5a4950f12b4bf9 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:23:13 -0600 Subject: [PATCH 097/112] Added error checking for current path name --- SceneManager/Menus/EditPathMenu.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/SceneManager/Menus/EditPathMenu.cs b/SceneManager/Menus/EditPathMenu.cs index 3a753ea..98d18d3 100644 --- a/SceneManager/Menus/EditPathMenu.cs +++ b/SceneManager/Menus/EditPathMenu.cs @@ -15,7 +15,7 @@ namespace SceneManager internal class EditPathMenu { internal static UIMenu Menu { get; } = new UIMenu("Scene Manager", "~o~Edit Path"); - private static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path", false); + private static UIMenuCheckboxItem DisablePath { get; } = new UIMenuCheckboxItem("Disable Path Collection", false); private static UIMenuItem EditWaypoints { get; } = new UIMenuItem("Edit Waypoints"); private static UIMenuItem DeletePath { get; } = new UIMenuItem("Delete Path"); private static UIMenuItem ChangePathName { get; } = new UIMenuItem("Change Path Name"); @@ -101,8 +101,16 @@ namespace SceneManager { var scrollerItems = new List { }; GameFiber.StartNew(() => UserInput.InitializeMenuMouseControl(menu, scrollerItems), "RNUI Mouse Input Fiber"); - Menu.SubtitleText = $"~o~Currently editing: ~b~{CurrentPath.Name}"; - ChangePathName.Description = $"Change the path name from ~b~{CurrentPath.Name} ~w~to something else."; + if (CurrentPath == null) + { + Menu.SubtitleText = $"~o~Currently editing: ~r~[ERROR GETTING CURRENT PATH]"; + ChangePathName.Description = $"Change the path name from ~r~[ERROR] ~w~to something else."; + } + else + { + Menu.SubtitleText = $"~o~Currently editing: ~b~{CurrentPath.Name}"; + ChangePathName.Description = $"Change the path name from ~b~{CurrentPath.Name} ~w~to something else."; + } } } } From aae797c0c48fbf4f12d43bdbe98b15d23171f2f7 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:23:46 -0600 Subject: [PATCH 098/112] Set MaxItemsOnScreen for menu --- SceneManager/Menus/EditWaypointMenu.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/SceneManager/Menus/EditWaypointMenu.cs b/SceneManager/Menus/EditWaypointMenu.cs index 8dd229d..355d00e 100644 --- a/SceneManager/Menus/EditWaypointMenu.cs +++ b/SceneManager/Menus/EditWaypointMenu.cs @@ -29,6 +29,7 @@ namespace SceneManager.Menus { Menu.ParentMenu = EditPathMenu.Menu; MenuManager.MenuPool.Add(Menu); + Menu.MaxItemsOnScreen = 11; Menu.OnScrollerChange += EditWaypoint_OnScrollerChanged; Menu.OnCheckboxChange += EditWaypoint_OnCheckboxChanged; From e73e75c1df3da6c8ceaf80a3b5fd9dac1baf4bc4 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:24:07 -0600 Subject: [PATCH 099/112] Added combined file exportation --- SceneManager/Menus/ExportPathMenu.cs | 64 +++++++++++++++++----------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/SceneManager/Menus/ExportPathMenu.cs b/SceneManager/Menus/ExportPathMenu.cs index ded3451..16e7e12 100644 --- a/SceneManager/Menus/ExportPathMenu.cs +++ b/SceneManager/Menus/ExportPathMenu.cs @@ -132,34 +132,56 @@ namespace SceneManager.Menus var GAME_DIRECTORY = Directory.GetCurrentDirectory(); var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; - var overrides = DefineOverridesForCombinedPath(); + var overrides = Serializer.DefineOverrides(); Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + fileName + ".xml", overrides); Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path exported as ~b~{fileName}.xml~w~."); } - private static void ExportAsCombinedFile(IEnumerable checkedItems) + private static void ExportAsCombinedFile(IEnumerable checkedItems, bool autosave = false) { - // If any file contains all (and only) path names from checkedItems, it can be quicksaved - string existingFile = GetNameForExistingCombinedPathsFile(checkedItems); - if(existingFile == "") - { - existingFile = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; + var overrides = Serializer.DefineOverrides(); - if (string.IsNullOrWhiteSpace(existingFile)) + if (autosave) + { + Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + "autosave.xml", overrides); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Paths exported as ~b~autosave.xml~w~."); + return; + } + + // If any file contains all (and only) path names from checkedItems, it can be quicksaved + string existingFile = GetNameForExistingCombinedPathsFile(checkedItems); + string exportFilename = existingFile; + + if (exportFilename == "") + { + exportFilename = UserInput.PromptPlayerForFileName("Type the name you would like to save your file as", "Enter a filename", 100); + + if (string.IsNullOrWhiteSpace(exportFilename)) { Game.DisplayHelp($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to ~b~\"{checkedItems.First().Text}\""); Game.LogTrivial($"Invalid filename given. Filename cannot be null, empty, or consist of just white spaces. Defaulting to \"{checkedItems.First().Text}\""); - existingFile = checkedItems.First().Text; + exportFilename = checkedItems.First().Text; } } - - Game.LogTrivial($"Filename: {existingFile}"); + Game.LogTrivial($"Filename: {exportFilename}"); - var GAME_DIRECTORY = Directory.GetCurrentDirectory(); - var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "/plugins/SceneManager/Saved Paths/"; - var overrides = DefineOverridesForCombinedPath(); - Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + existingFile + ".xml", overrides); - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Paths exported as ~b~{existingFile}.xml~w~."); + Serializer.SaveItemToXML(ExportPaths, SAVED_PATHS_DIRECTORY + exportFilename + ".xml", overrides); + Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Paths exported as ~b~{exportFilename}.xml~w~."); + } + + internal static void ExportOnUnload() + { + ExportPaths.Clear(); + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)).Select(x => (UIMenuCheckboxItem)x); + foreach (UIMenuCheckboxItem checkboxItem in checkboxItems) + { + var pathToExport = PathManager.Paths.First(x => x != null && x.Name == checkboxItem.Text); + ExportPaths.Add(pathToExport); + } + + ExportAsCombinedFile(checkboxItems, true); } private static bool CanQuickSavePath(Paths.Path pathToExport) @@ -191,15 +213,5 @@ namespace SceneManager.Menus return ""; } - - private static XmlAttributeOverrides DefineOverridesForCombinedPath() - { - XmlAttributeOverrides overrides = new XmlAttributeOverrides(); - XmlAttributes attr = new XmlAttributes(); - attr.XmlRoot = new XmlRootAttribute("Paths"); - overrides.Add(typeof(List), attr); - - return overrides; - } } } From aac76cb79d93e3e7a01665427563f26353bfde4c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:25:27 -0600 Subject: [PATCH 100/112] Paths are no longer fully imported on plugin load --- SceneManager/Menus/ImportPathMenu.cs | 99 ++++++++++++++-------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/SceneManager/Menus/ImportPathMenu.cs b/SceneManager/Menus/ImportPathMenu.cs index 026636a..c66ff39 100644 --- a/SceneManager/Menus/ImportPathMenu.cs +++ b/SceneManager/Menus/ImportPathMenu.cs @@ -6,9 +6,7 @@ using System.Collections.Generic; using System.Linq; using Rage; using SceneManager.Managers; -using SceneManager.Paths; -using System; -using System.Windows.Forms; +using System.IO; namespace SceneManager.Menus { @@ -16,8 +14,7 @@ namespace SceneManager.Menus { internal static UIMenu Menu = new UIMenu("Scene Manager", "~o~Import Path Menu"); internal static UIMenuItem Import { get; } = new UIMenuItem("Import", "Import the selected paths."); - - private static List _HasBeenImported = new List(); + internal static List ImportedFileNames { get; } = new List(); internal static void Initialize() { @@ -32,11 +29,12 @@ namespace SceneManager.Menus internal static void Build() { Menu.Clear(); - PathManager.ImportPaths(); - foreach(KeyValuePair> kvp in PathManager.ImportedPaths) + + GetFileNamesForPathsToImport(); + foreach(string fileName in ImportedFileNames) { - var menuItem = new UIMenuCheckboxItem(kvp.Key, false); - if(!_HasBeenImported.Contains(kvp.Key)) + var menuItem = new UIMenuCheckboxItem(fileName, false); + if (!PathManager.LoadedFiles.Contains(fileName)) { menuItem.LeftBadge = UIMenuItem.BadgeStyle.Star; } @@ -57,56 +55,59 @@ namespace SceneManager.Menus { if(selectedItem == Import) { - var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)); - foreach(UIMenuCheckboxItem menuItem in checkboxItems) + var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)).Cast(); + var checkedItems = checkboxItems.Where(x => x.Checked); + + foreach(var menuItem in checkedItems) { - if(menuItem.Checked) + var importedPaths = PathManager.ImportPathsFromFile(menuItem.Text); + if (importedPaths != null) { - var pathsFromFile = PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Value; - foreach(Path path in pathsFromFile) - { - if(PathManager.Paths.Any(x => x != null && x.Name == path.Name)) - { - Game.DisplayHelp($"A path with the name ~b~{path.Name} ~w~already exists. Do you want to replace it? ~{Keys.Y.GetInstructionalId()}~ or ~{Keys.N.GetInstructionalId()}~"); - GameFiber.Sleep(100); - GameFiber.SleepUntil(() => Game.IsKeyDown(Keys.Y) || Game.IsKeyDown(Keys.N), 8300); - - if(Game.IsKeyDown(Keys.Y)) - { - var pathToReplace = PathManager.Paths.First(x => x.Name == path.Name); - var pathToReplaceIndex = Array.IndexOf(PathManager.Paths, pathToReplace); - pathToReplace.Delete(); - PathManager.Paths[pathToReplaceIndex] = path; - path.Load(); - Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); - _HasBeenImported.Add(PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Key); - continue; - } - else - { - Game.DisplayNotification($"~o~Scene Manager ~y~[Import]\n~w~Path ~b~{path.Name} ~w~was not imported."); - Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); - continue; - } - } - - var firstNullPathIndex = Array.IndexOf(PathManager.Paths, PathManager.Paths.First(x => x == null)); - PathManager.Paths[firstNullPathIndex] = path; - path.Load(); - _HasBeenImported.Add(PathManager.ImportedPaths.FirstOrDefault(x => x.Key == menuItem.Text).Key); - } - - var numberOfNonNullPaths = PathManager.Paths.Where(x => x != null).Count(); - Game.LogTrivial($"{menuItem.Text} added to paths collection. Paths count: {numberOfNonNullPaths}"); - Menu.RefreshIndex(); + PathManager.LoadImportedPaths(importedPaths, menuItem.Text); } } + Menu.RefreshIndex(); MenuManager.BuildMenus(); Menu.Visible = true; } } + private static void GetFileNamesForPathsToImport() + { + ImportedFileNames.Clear(); + + // Check if Saved Paths directory exists + var GAME_DIRECTORY = Directory.GetCurrentDirectory(); + var SAVED_PATHS_DIRECTORY = GAME_DIRECTORY + "\\plugins\\SceneManager\\Saved Paths\\"; + if (!Directory.Exists(SAVED_PATHS_DIRECTORY)) + { + Game.LogTrivial($"Directory '\\plugins\\SceneManager\\Saved Paths' does not exist. No paths available to import."); + return; + } + + // Check if any XML files are available to import from Saved Paths + var savedPathFiles = Directory.GetFiles(SAVED_PATHS_DIRECTORY, "*.xml"); + if (savedPathFiles.Length == 0) + { + Game.LogTrivial($"No saved paths found."); + return; + } + else + { + Game.LogTrivial($"{savedPathFiles.Length} path(s) available to import."); + } + + // Import file names + foreach (string file in savedPathFiles) + { + string fileName = System.IO.Path.GetFileNameWithoutExtension(file); + Game.LogTrivial($"File: {fileName}"); + ImportedFileNames.Add(fileName); + } + Game.LogTrivial($"Successfully populated menu with {ImportedFileNames.Count} file(s)."); + } + private static void ImportPathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool Checked) { var checkboxItems = Menu.MenuItems.Where(x => x.GetType() == typeof(UIMenuCheckboxItem)); From 802fe37a5ff907bebaa1a510f58f351ac863da9c Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:26:24 -0600 Subject: [PATCH 101/112] ImportPath option enabled based on if there are any paths to import --- SceneManager/Menus/PathMainMenu.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/SceneManager/Menus/PathMainMenu.cs b/SceneManager/Menus/PathMainMenu.cs index 065e215..50e96cc 100644 --- a/SceneManager/Menus/PathMainMenu.cs +++ b/SceneManager/Menus/PathMainMenu.cs @@ -18,7 +18,7 @@ namespace SceneManager.Menus internal static UIMenuItem ExportPath { get; } = new UIMenuItem("Export Paths", "Export selected paths to ~b~plugins/SceneManager/Saved Paths"); internal static UIMenuItem DeleteAllPaths { get; } = new UIMenuItem("Delete All Paths"); internal static UIMenuListScrollerItem EditPath { get; private set; } - internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Paths", false); + internal static UIMenuCheckboxItem DisableAllPaths { get; } = new UIMenuCheckboxItem("Disable All Path Collection", false); internal static void Initialize() { @@ -39,7 +39,7 @@ namespace SceneManager.Menus CreateNewPath.ForeColor = Color.Gold; Menu.AddItem(ImportPath); ImportPath.ForeColor = Color.Gold; - ImportPath.Enabled = PathManager.ImportedPaths.Count > 0; + ImportPath.Enabled = ImportPathMenu.ImportedFileNames.Count > 0; Menu.AddItem(ExportPath); ExportPath.ForeColor = Color.Gold; ExportPath.Enabled = PathManager.Paths.Any(x => x != null); @@ -62,7 +62,7 @@ namespace SceneManager.Menus DeleteAllPaths.Enabled = false; DisableAllPaths.Enabled = false; } - if(PathManager.ImportedPaths.Count == 0) + if(ImportPathMenu.ImportedFileNames.Count == 0) { ImportPath.Enabled = false; } @@ -95,10 +95,9 @@ namespace SceneManager.Menus if (selectedItem == DeleteAllPaths) { PathManager.DeleteAllPaths(); - DisableAllPaths.Checked = false; - Build(); + PathManager.LoadedFiles.Clear(); + MenuManager.BuildMenus(); Menu.Visible = true; - BarrierMenu.Build(); } } From a23ea86decd2bab5d4f9404555d851741bd9bb31 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:27:25 -0600 Subject: [PATCH 102/112] Added help message on path load, modified logging and messages, fixed sleep timer bug on path disable --- SceneManager/Paths/Path.cs | 121 ++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/SceneManager/Paths/Path.cs b/SceneManager/Paths/Path.cs index 42a2615..b2a0005 100644 --- a/SceneManager/Paths/Path.cs +++ b/SceneManager/Paths/Path.cs @@ -11,6 +11,7 @@ using SceneManager.Managers; using SceneManager.Barriers; using SceneManager.Waypoints; using SceneManager.CollectedPeds; +using RAGENativeUI; namespace SceneManager.Paths { @@ -46,16 +47,17 @@ namespace SceneManager.Paths Game.LogTrivial($"New directory created at '/plugins/SceneManager/Saved Paths'"); } - var overrides = DefineOverridesForCombinedPath(); - Serializer.SaveItemToXML(this, SAVED_PATHS_DIRECTORY + Name + ".xml", overrides); + var overrides = Serializer.DefineOverrides(); + Serializer.SaveItemToXML(new List { this }, SAVED_PATHS_DIRECTORY + Name + ".xml", overrides); Game.LogTrivial($"Saved {Name}.xml"); - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path ~b~{Name} ~w~exported."); + Game.DisplayNotification($"~o~Scene Manager ~w~[~g~Success~w~]\n~w~Path ~b~{Name} ~w~exported."); } internal void Load() { - foreach(Waypoint waypoint in Waypoints) + Game.DisplayHelp($"~{InstructionalKey.SymbolBusySpinner.GetId()}~ Loading ~b~{Name}~w~..."); + foreach (Waypoint waypoint in Waypoints) { waypoint.LoadFromImport(this); } @@ -68,7 +70,7 @@ namespace SceneManager.Paths Barriers[i] = barrier; BarrierManager.Barriers.Add(barrier); } - + Rage.Native.NativeFunction.Natives.CLEAR_ALL_HELP_MESSAGES(); DrawLinesBetweenWaypoints(); Finish(); } @@ -97,12 +99,12 @@ namespace SceneManager.Paths internal void Finish() { - Game.LogTrivial($"[Path Creation] Path {Name} finished with {Waypoints.Count} waypoints."); - Game.DisplayNotification($"~o~Scene Manager ~g~[Success]\n~w~Path ~b~{Name} ~w~complete."); + Game.LogTrivial($"[Path Creation] Path \"{Name}\" finished with {Waypoints.Count} waypoints."); + Game.DisplayNotification($"~o~Scene Manager ~w~[~g~Success~w~]\n~w~Path ~b~{Name} ~w~complete."); State = State.Finished; IsEnabled = true; Waypoints.ForEach(x => x.EnableBlip()); - GameFiber.StartNew(() => LoopForVehiclesToBeDismissed(), "Vehicle Cleanup Loop Fiber"); + //GameFiber.StartNew(() => LoopForVehiclesToBeDismissed(), "Vehicle Cleanup Loop Fiber"); GameFiber.StartNew(() => LoopWaypointCollection(), "Waypoint Collection Loop Fiber"); PathMainMenu.CreateNewPath.Text = "Create New Path"; @@ -154,7 +156,7 @@ namespace SceneManager.Paths { LowerWaypointBlipsOpacity(); } - Game.LogTrivial($"Path {Name} disabled."); + Game.LogTrivial($"Path \"{Name}\" disabled."); } internal void Enable() @@ -171,7 +173,7 @@ namespace SceneManager.Paths { RestoreWaypointBlipsOpacity(); } - Game.LogTrivial($"Path {Name} enabled."); + Game.LogTrivial($"Path \"{Name}\" enabled."); } internal void DrawLinesBetweenWaypoints() @@ -202,23 +204,40 @@ namespace SceneManager.Paths }, "3D Waypoint Line Drawing Fiber"); } - internal void LoopForVehiclesToBeDismissed() - { - while (PathManager.Paths.Contains(this)) - { - foreach (CollectedPed cp in CollectedPeds.Where(x => x && x.CurrentVehicle && (!x.CurrentVehicle.IsDriveable || x.CurrentVehicle.IsUpsideDown || !x.CurrentVehicle.HasDriver))) - { - if (cp.CurrentVehicle.HasDriver) - { - cp.CurrentVehicle.Driver.Dismiss(); - } - cp.CurrentVehicle.Dismiss(); - } + //internal void LoopForVehiclesToBeDismissed() + //{ + // while (PathManager.Paths.Contains(this)) + // { + // foreach (CollectedPed cp in CollectedPeds.Where(x => x && x.CurrentVehicle && (!x.CurrentVehicle.IsDriveable || x.CurrentVehicle.IsUpsideDown || !x.CurrentVehicle.HasDriver))) + // { + // if (cp.CurrentVehicle.HasDriver) + // { + // cp.CurrentVehicle.Driver.Dismiss(); + // } + // cp.CurrentVehicle.Dismiss(); + // } - CollectedPeds.RemoveAll(cp => !cp || !cp.CurrentVehicle); - BlacklistedVehicles.RemoveAll(v => !v); - GameFiber.Sleep(60000); + // CollectedPeds.RemoveAll(cp => !cp || !cp.CurrentVehicle); + // BlacklistedVehicles.RemoveAll(v => !v); + // GameFiber.Sleep(60000); + // } + //} + + internal void CleanupInvalidPedsAndVehicles() + { + var pedsToDismiss = CollectedPeds.Where(x => x && x.CurrentVehicle && (!x.CurrentVehicle.IsDriveable || x.CurrentVehicle.IsUpsideDown || !x.CurrentVehicle.HasDriver)).ToList(); + foreach (CollectedPed cp in pedsToDismiss) + { + //if (cp.CurrentVehicle.HasDriver) + //{ + // cp.CurrentVehicle.Driver.Dismiss(); + //} + //cp.CurrentVehicle.Dismiss(); + cp.Dismiss(); } + + CollectedPeds.RemoveAll(cp => !cp || !cp.CurrentVehicle); + BlacklistedVehicles.RemoveAll(v => !v); } internal void LoopWaypointCollection() @@ -227,11 +246,19 @@ namespace SceneManager.Paths int yieldAfterChecks = 50; // How many calculations to do before yielding while (PathManager.Paths.Contains(this)) { - GameFiber.SleepUntil(() => IsEnabled, 0); - - if(State == State.Deleting) + //Game.DisplaySubtitle($"CollectedPeds: ~b~{CollectedPeds.Count} ~w~| Persistent Peds: ~b~{World.GetAllPeds().Count(p => p.IsPersistent)}"); + + //Game.LogTrivial($"Looping for waypoint collection"); + //GameFiber.SleepUntil(() => IsEnabled, 0); + if(!IsEnabled) + { + lastProcessTime = Game.GameTime; + GameFiber.Yield(); + continue; + } + + if (State == State.Deleting) { - Game.LogTrivial($"Path deleted, ending waypoint collection."); return; } @@ -240,11 +267,17 @@ namespace SceneManager.Paths foreach (Waypoint waypoint in collectorWaypoints.ToList()) { - foreach (Vehicle vehicle in World.GetAllVehicles().Where(x => x)) + foreach (Vehicle vehicle in World.GetAllVehicles()) { + if(!vehicle) + { + lastProcessTime = Game.GameTime; + continue; + } + if (vehicle.IsNearCollectorWaypoint(waypoint) && vehicle.IsValidForPathCollection(this)) { - while(!vehicle.Driver) + while (!vehicle.Driver) { GameFiber.Yield(); if (!vehicle) @@ -254,6 +287,7 @@ namespace SceneManager.Paths } if (!vehicle) { + lastProcessTime = Game.GameTime; continue; } CollectedPeds.Add(new CollectedPed(vehicle.Driver, this, waypoint)); @@ -268,6 +302,7 @@ namespace SceneManager.Paths Game.LogTrivial($"Path deleted, ending waypoint collection."); return; } + CleanupInvalidPedsAndVehicles(); } } } @@ -285,7 +320,7 @@ namespace SceneManager.Paths DismissCollectedDrivers(); RemoveAllWaypoints(); PathManager.Paths[pathIndex] = null; - Game.LogTrivial($"Path {Name} deleted."); + Game.LogTrivial($"Path \"{Name}\" deleted."); } private void DismissCollectedDrivers() @@ -293,19 +328,7 @@ namespace SceneManager.Paths 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 (collectedPed.StoppedAtWaypoint) - { - Rage.Native.NativeFunction.Natives.x260BE8F09E326A20(collectedPed.CurrentVehicle, 1f, 1, true); - } - if (collectedPed.GetAttachedBlip()) - { - collectedPed.GetAttachedBlip().Delete(); - } collectedPed.Dismiss(); - collectedPed.CurrentVehicle.IsSirenOn = false; - collectedPed.CurrentVehicle.IsSirenSilent = true; - collectedPed.CurrentVehicle.Dismiss(); - CollectedPeds.Remove(collectedPed); } } @@ -343,15 +366,5 @@ namespace SceneManager.Paths Name = pathName; } - - private static XmlAttributeOverrides DefineOverridesForCombinedPath() - { - XmlAttributeOverrides overrides = new XmlAttributeOverrides(); - XmlAttributes attr = new XmlAttributes(); - attr.XmlRoot = new XmlRootAttribute("Paths"); - overrides.Add(typeof(List), attr); - - return overrides; - } } } From 54128653ef9e422fdfdc81fedffa0e393a59a513 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:27:33 -0600 Subject: [PATCH 103/112] Updated version --- SceneManager/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SceneManager/Properties/AssemblyInfo.cs b/SceneManager/Properties/AssemblyInfo.cs index 17564d7..bcbdcf0 100644 --- a/SceneManager/Properties/AssemblyInfo.cs +++ b/SceneManager/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.2.4")] -[assembly: AssemblyFileVersion("2.2.2.4")] +[assembly: AssemblyVersion("2.3.0.0")] +[assembly: AssemblyFileVersion("2.3.0.0")] From 17135760b479d892947dd1622ddb09e16bf0e57a Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:27:53 -0600 Subject: [PATCH 104/112] Added commaned GetNumberOfVehiclesOnPath --- SceneManager/Utils/ConsoleCommands.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/SceneManager/Utils/ConsoleCommands.cs b/SceneManager/Utils/ConsoleCommands.cs index 9acea7d..a82555d 100644 --- a/SceneManager/Utils/ConsoleCommands.cs +++ b/SceneManager/Utils/ConsoleCommands.cs @@ -3,7 +3,6 @@ using Rage.Attributes; using Rage.ConsoleCommands.AutoCompleters; using System.Linq; using System; -using System.Collections.Generic; using SceneManager.Managers; using SceneManager.Paths; @@ -67,5 +66,14 @@ namespace SceneManager.Utils ped.Delete(); } } + + [ConsoleCommand("GetNumberOfVehiclesOnPath")] + internal static void Command_GetNumberOfVehiclesOnPath() + { + foreach(Path path in PathManager.Paths.Where(x => x != null)) + { + Game.LogTrivial($"Path \"{path.Name}\" has {path.CollectedPeds.Count} collected peds."); + } + } } } From 7c009e0f5bdb493a10e345737c66ad26b5ee4fb4 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:28:21 -0600 Subject: [PATCH 105/112] Modified driver collection --- SceneManager/Utils/DirectDriver.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/SceneManager/Utils/DirectDriver.cs b/SceneManager/Utils/DirectDriver.cs index 03a0362..ecb55ea 100644 --- a/SceneManager/Utils/DirectDriver.cs +++ b/SceneManager/Utils/DirectDriver.cs @@ -69,12 +69,10 @@ namespace SceneManager.Utils nearbyCollectedVehicleOtherPath.Dismiss(Dismiss.FromDirected, path); } Game.LogTrivial($"[Direct Driver] Adding {nearbyVehicle.Model.Name} to directed path."); - path.CollectedPeds.Add(collectedVehicleOnThisPath = new CollectedPed(nearbyVehicle.Driver, path, targetWaypoint) { Directed = true }); - //collectedVehicleOnThisPath.Directed = true; - collectedVehicleOnThisPath.Tasks.Clear(); + var newCollectedPed = new CollectedPed(nearbyVehicle.Driver, path, targetWaypoint) { Directed = true }; + path.CollectedPeds.Add(newCollectedPed); + //collectedVehicleOnThisPath.Tasks.Clear(); } - - //GameFiber.StartNew(() => collectedVehicleOnThisPath.AssignWaypointTasks(path, targetWaypoint)); } } } From 1fe9a61d0ee5dd49cf0b9dce281473de2c148864 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:28:34 -0600 Subject: [PATCH 106/112] Changed FromPlayer to ByPlayer --- SceneManager/Utils/Enums.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SceneManager/Utils/Enums.cs b/SceneManager/Utils/Enums.cs index 8b2e166..2eaa328 100644 --- a/SceneManager/Utils/Enums.cs +++ b/SceneManager/Utils/Enums.cs @@ -461,7 +461,7 @@ FromPath = 0, FromWaypoint = 1, FromWorld = 2, - FromPlayer = 3, + ByPlayer = 3, FromDirected = 4 } From bed387ae9abc39377b3452e1dc7d4b67607f72e7 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:28:58 -0600 Subject: [PATCH 107/112] Added GetTextWidth and GetSelectedItemTextWidth methods --- SceneManager/Utils/Extensions.cs | 44 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/SceneManager/Utils/Extensions.cs b/SceneManager/Utils/Extensions.cs index 6fc2453..f53fb63 100644 --- a/SceneManager/Utils/Extensions.cs +++ b/SceneManager/Utils/Extensions.cs @@ -1,4 +1,5 @@ using Rage; +using RAGENativeUI.Elements; using SceneManager.Managers; using SceneManager.Paths; using SceneManager.Waypoints; @@ -163,16 +164,24 @@ namespace SceneManager.Utils if (!vehicle.HasDriver) { vehicle.CreateRandomDriver(); - while (vehicle && !vehicle.HasDriver) - { - GameFiber.Yield(); - } - if(!vehicle || !vehicle.Driver) + GameFiber.Yield(); + //while (vehicle && !vehicle.HasDriver) + //{ + // Game.LogTrivial($"Trying to create new driver"); + // GameFiber.Yield(); + //} + if(!vehicle) { return false; } + if(!vehicle.Driver) + { + Game.LogTrivial($"Unable to create a new driver"); + vehicle.Delete(); + return false; + } Game.LogTrivial($"Vehicle has a new driver"); - vehicle.Driver.IsPersistent = true; + //vehicle.Driver.IsPersistent = true; vehicle.Driver.BlockPermanentEvents = true; } return true; @@ -182,5 +191,28 @@ namespace SceneManager.Utils return false; } } + + internal static float GetTextWidth(this UIMenuItem menuItem) + { + menuItem.TextStyle.Apply(); + Rage.Native.NativeFunction.Natives.x54CE8AC98E120CAB("STRING"); // _BEGIN_TEXT_COMMAND_GET_WIDTH + Rage.Native.NativeFunction.Natives.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(menuItem.Text); + return Rage.Native.NativeFunction.Natives.x85F061DA64ED2F67(true); // _END_TEXT_COMMAND_GET_WIDTH + } + + internal static float GetSelectedItemTextWidth(this UIMenuListScrollerItem scrollerItem) + { + if (scrollerItem.OptionCount == 0) + { + return 0; + } + scrollerItem.GetTextWidth(); + scrollerItem.TextStyle.Apply(); + + Rage.Native.NativeFunction.Natives.x54CE8AC98E120CAB("STRING"); // _BEGIN_TEXT_COMMAND_GET_WIDTH + Rage.Native.NativeFunction.Natives.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(scrollerItem.SelectedItem); + + return Rage.Native.NativeFunction.Natives.x85F061DA64ED2F67(true); // _END_TEXT_COMMAND_GET_WIDTH + } } } From 03aa96090e9dd5f0fb54a1f54b781233dfde8602 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:29:09 -0600 Subject: [PATCH 108/112] Added DefineOverrides method --- SceneManager/Utils/Serializer.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SceneManager/Utils/Serializer.cs b/SceneManager/Utils/Serializer.cs index 52e7eaf..16e62ea 100644 --- a/SceneManager/Utils/Serializer.cs +++ b/SceneManager/Utils/Serializer.cs @@ -129,5 +129,15 @@ namespace SceneManager.Utils { ModifyItemInXML>(path, t => t.Add(objectToAdd)); } + + internal static XmlAttributeOverrides DefineOverrides() + { + XmlAttributeOverrides overrides = new XmlAttributeOverrides(); + XmlAttributes attr = new XmlAttributes(); + attr.XmlRoot = new XmlRootAttribute("Paths"); + overrides.Add(typeof(List), attr); + + return overrides; + } } } From fff7e146012a1f9d9861f0b9988217f3d1ac11d7 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:29:50 -0600 Subject: [PATCH 109/112] Updated for RPH and RNUI nugets --- SceneManager/_ConfuserEx/c.crproj | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/SceneManager/_ConfuserEx/c.crproj b/SceneManager/_ConfuserEx/c.crproj index 8b16c94..79b73cc 100644 --- a/SceneManager/_ConfuserEx/c.crproj +++ b/SceneManager/_ConfuserEx/c.crproj @@ -10,17 +10,11 @@ - - - - - - ..\..\..\packages\InputManager.1.0.0\lib -D:\Program Files\Rockstar Games\Grand Theft Auto V -C:\Users\Rich\Desktop\Mod Stuff\Mod Development\Modding Resources\References +..\..\..\packages\RagePluginHook.1.86.1\lib\net472 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\Facades +..\..\..\packages\RAGENativeUI.1.8.0\lib\net472 From b73b8d0987ebb3ead57ee7c808557a9819a9539b Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:30:06 -0600 Subject: [PATCH 110/112] Added try/catch for autosave --- SceneManager/EntryPoint.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/SceneManager/EntryPoint.cs b/SceneManager/EntryPoint.cs index 1ee02e6..8899c6e 100644 --- a/SceneManager/EntryPoint.cs +++ b/SceneManager/EntryPoint.cs @@ -42,11 +42,20 @@ namespace SceneManager private static void TerminationHandler(object sender, EventArgs e) { + try + { + ExportPathMenu.ExportOnUnload(); + } + catch(Exception ex) + { + Game.LogTrivial($"Autosave error: {ex.Message}"); + Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~There was a problem autosaving the paths."); + } BarrierMenu.Cleanup(); PathManager.DeleteAllPaths(); Game.LogTrivial($"Plugin has shut down."); - Game.DisplayNotification($"~o~Scene Manager ~r~[Terminated]\n~w~The plugin has shut down."); + //Game.DisplayNotification($"~o~Scene Manager ~r~[Terminated]\n~w~The plugin has shut down."); } } } From ce6b59265b03b289cf9099c0b803a5864e78bedb Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:30:23 -0600 Subject: [PATCH 111/112] Added RNUI 1.8 nuget --- SceneManager/packages.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SceneManager/packages.config b/SceneManager/packages.config index 2e38803..d85b8f7 100644 --- a/SceneManager/packages.config +++ b/SceneManager/packages.config @@ -1,5 +1,7 @@  + + \ No newline at end of file From 4726efb26e2723c544ee9b82cf491a313d5ae213 Mon Sep 17 00:00:00 2001 From: Rich Dunne Date: Wed, 7 Jul 2021 07:30:34 -0600 Subject: [PATCH 112/112] Added RNUI 1.8 nuget --- SceneManager/SceneManager.csproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SceneManager/SceneManager.csproj b/SceneManager/SceneManager.csproj index 9a38cb2..53b73f6 100644 --- a/SceneManager/SceneManager.csproj +++ b/SceneManager/SceneManager.csproj @@ -36,9 +36,8 @@ ..\packages\InputManager.1.0.0\lib\InputManager.dll - - D:\Program Files\Rockstar Games\Grand Theft Auto V\RAGENativeUI.dll - False + + ..\packages\RAGENativeUI.1.8.0\lib\net472\RAGENativeUI.dll ..\packages\RagePluginHook.1.86.1\lib\net472\RagePluginHook.dll