1
Fork 0
mirror of https://github.com/thegeneralist01/Scene-Manager-DevRepo synced 2026-01-11 15:40:29 +01:00

Mouse can now be used to fully navigate menus

This commit is contained in:
Rich Dunne 2020-10-23 06:22:19 -06:00
parent f81c7675c8
commit 9ff7aabd9f
8 changed files with 1476 additions and 607 deletions

View file

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
@ -21,6 +22,10 @@ namespace SceneManager
{
barrierMenu.ParentMenu = MainMenu.mainMenu;
MenuManager.menuPool.Add(barrierMenu);
barrierMenu.OnItemSelect += BarrierMenu_OnItemSelected;
barrierMenu.OnScrollerChange += BarrierMenu_OnScrollerChange;
barrierMenu.OnMenuOpen += BarrierMenu_OnMouseDown;
}
internal static void BuildBarrierMenu()
@ -37,23 +42,20 @@ namespace SceneManager
barrierMenu.AddItem(barrierList, 0);
barrierList.ForeColor = Color.Gold;
barrierMenu.OnItemSelect += BarrierMenu_OnItemSelected;
barrierMenu.OnScrollerChange += BarrierMenu_OnScrollerChange;
}
internal static void CreateShadowBarrier(UIMenu barrierMenu)
{
Hints.Display($"~o~Scene Manager ~y~[Hint]\n~y~ ~w~The shadow cone will disappear if you aim too far away.");
Hints.Display($"~o~Scene Manager ~y~[Hint]\n~w~The shadow cone will disappear if you aim too far away.");
if (shadowBarrier)
shadowBarrier.Delete();
shadowBarrier = new Rage.Object(Settings.barrierValues[barrierList.Index], TracePlayerView(Settings.BarrierPlacementDistance, TraceFlags.IntersectWorld).HitPosition, rotateBarrier.Value);
shadowBarrier = new Object(Settings.barrierValues[barrierList.Index], GetMousePositionInWorld(), rotateBarrier.Value);
if (!shadowBarrier)
{
barrierMenu.Close();
Game.DisplayNotification($"~o~Scene Manager ~red~[Error]\n~w~ Something went wrong creating the shadow barrier. Please try again.");
Game.DisplayNotification($"~o~Scene Manager ~r~[Error]\n~w~Something went wrong creating the shadow barrier. Please try again.");
return;
}
Rage.Native.NativeFunction.Natives.PLACE_OBJECT_ON_GROUND_PROPERLY(shadowBarrier);
@ -86,7 +88,7 @@ namespace SceneManager
void UpdateShadowBarrierPosition()
{
DisableBarrierMenuOptionsIfShadowConeTooFar();
shadowBarrier.SetPositionWithSnap(TracePlayerView(Settings.BarrierPlacementDistance, TraceFlags.IntersectWorld).HitPosition);
shadowBarrier.SetPositionWithSnap(GetMousePositionInWorld());
void DisableBarrierMenuOptionsIfShadowConeTooFar()
{
@ -108,37 +110,95 @@ namespace SceneManager
}
}
}
//------------ CREDIT PNWPARKS FOR THESE FUNCTIONS ------------\\
// Implement Parks's 'Get Point Player is Looking At' script for better placement in 3rd person https://bitbucket.org/snippets/gtaparks/MeBKxX
HitResult TracePlayerView(float maxTraceDistance = 30f, 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);
var barrierObjects = barriers.Where(b => b.Object).Select(b => b.Object).ToArray();
return World.TraceLine(start, end, flags, barrierObjects);
}
Vector3 GetPlayerLookingDirection(out Vector3 camPosition)
private static void SpawnBarrier()
{
if (Camera.RenderingCamera)
{
camPosition = Camera.RenderingCamera.Position;
return Camera.RenderingCamera.Direction;
}
else
{
float pitch = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_PITCH<float>();
float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING<float>();
var barrier = new Rage.Object(shadowBarrier.Model, shadowBarrier.Position, rotateBarrier.Value);
barrier.SetPositionWithSnap(shadowBarrier.Position);
Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(barrier, true);
barrier.IsPositionFrozen = false;
Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(barrier, true);
camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD<Vector3>();
return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized();
barriers.Add(new Barrier(barrier, barrier.Position, barrier.Heading));
removeBarrierOptions.Enabled = true;
resetBarriers.Enabled = true;
}
private static void SpawnFlare()
{
var flare = new Weapon("weapon_flare", shadowBarrier.Position, 1);
Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true);
GameFiber.StartNew(() =>
{
while (flare && flare.HeightAboveGround > 0.05f)
{
GameFiber.Yield();
}
//------------ CREDIT PNWPARKS FOR THESE FUNCTIONS ------------\\
GameFiber.Sleep(1000);
if (flare)
{
flare.IsPositionFrozen = true;
}
});
barriers.Add(new Barrier(flare, flare.Position, flare.Heading));
removeBarrierOptions.Enabled = true;
}
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()
{
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 = false;
Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(newBarrier, true);
barriers.Add(new Barrier(newBarrier, newBarrier.Position, newBarrier.Heading));
if (barrier.Object)
{
barrier.Object.Delete();
}
barriers.Remove(barrier);
}
currentBarriers.Clear();
}
private static void BarrierMenu_OnScrollerChange(UIMenu sender, UIMenuScrollerItem scrollerItem, int oldIndex, int newIndex)
@ -167,7 +227,7 @@ namespace SceneManager
private static void BarrierMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if (selectedItem == barrierList as UIMenuItem)
if (selectedItem == barrierList)
{
// Attach some invisible object to the cone which the AI try to drive around
// Barrier rotates with cone and becomes invisible similar to ASC when created
@ -182,99 +242,174 @@ namespace SceneManager
}
if (selectedItem == removeBarrierOptions as UIMenuItem)
if (selectedItem == removeBarrierOptions)
{
RemoveBarrier();
}
if (selectedItem == resetBarriers)
{
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 = false;
Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(newBarrier, true);
barriers.Add(new Barrier(newBarrier, newBarrier.Position, newBarrier.Heading));
if (barrier.Object)
{
barrier.Object.Delete();
ResetBarriers();
}
barriers.Remove(barrier);
}
currentBarriers.Clear();
}
void SpawnBarrier()
private static void BarrierMenu_OnMouseDown(UIMenu menu)
{
var barrier = new Rage.Object(shadowBarrier.Model, shadowBarrier.Position, rotateBarrier.Value);
barrier.SetPositionWithSnap(shadowBarrier.Position);
Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(barrier, true);
barrier.IsPositionFrozen = false;
Rage.Native.NativeFunction.Natives.SET_DISABLE_FRAG_DAMAGE(barrier, true);
barriers.Add(new Barrier(barrier, barrier.Position, barrier.Heading));
removeBarrierOptions.Enabled = true;
resetBarriers.Enabled = true;
}
void SpawnFlare()
{
var flare = new Weapon("weapon_flare", shadowBarrier.Position, 1);
Rage.Native.NativeFunction.Natives.SET_ENTITY_DYNAMIC(flare, true);
GameFiber.StartNew(() =>
{
while (flare && flare.HeightAboveGround > 0.05f)
while (menu.Visible)
{
GameFiber.Yield();
var selectedScroller = menu.MenuItems.Where(x => (x == barrierList || x == rotateBarrier || x == removeBarrierOptions) && x.Selected).FirstOrDefault();
if (selectedScroller != null)
{
HandleScrollerItemsWithMouseWheel(selectedScroller);
}
GameFiber.Sleep(1000);
if (flare)
// Add waypoint if menu item is selected and user left clicks
if (Game.IsKeyDown(Keys.LButton))
{
flare.IsPositionFrozen = true;
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
barriers.Add(new Barrier(flare, flare.Position, flare.Heading));
removeBarrierOptions.Enabled = true;
void OnMenuItemClicked()
{
if (barrierList.Selected)
{
if (barrierList.SelectedItem == "Flare")
{
SpawnFlare();
}
else
{
SpawnBarrier();
}
}
else if (removeBarrierOptions.Selected)
{
RemoveBarrier();
}
else if (resetBarriers.Selected)
{
ResetBarriers();
}
}
void RemoveBarrier()
void HandleScrollerItemsWithMouseWheel(UIMenuItem selectedScroller)
{
switch (removeBarrierOptions.Index)
var menuScrollingDisabled = false;
var menuItems = menu.MenuItems.Where(x => x != selectedScroller);
while (Game.IsShiftKeyDownRightNow)
{
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;
menu.ResetKey(Common.MenuControls.Up);
menu.ResetKey(Common.MenuControls.Down);
menuScrollingDisabled = true;
ScrollMenuItem();
GameFiber.Yield();
}
removeBarrierOptions.Enabled = barriers.Count == 0 ? false : true;
resetBarriers.Enabled = barriers.Count == 0 ? false : true;
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)
{
if (selectedScroller == barrierList)
{
barrierList.ScrollToNextOption();
CreateShadowBarrier(barrierMenu);
if (barrierList.SelectedItem == "Flare")
{
rotateBarrier.Enabled = false;
}
else
{
rotateBarrier.Enabled = true;
}
barrierMenu.Width = SetMenuWidth();
}
else if (selectedScroller == rotateBarrier)
{
rotateBarrier.ScrollToNextOption();
shadowBarrier.Heading = rotateBarrier.Value;
}
else if (selectedScroller == removeBarrierOptions)
{
removeBarrierOptions.ScrollToNextOption();
}
}
else if (Game.GetMouseWheelDelta() < 0)
{
if (selectedScroller == barrierList)
{
barrierList.ScrollToPreviousOption();
CreateShadowBarrier(barrierMenu);
if (barrierList.SelectedItem == "Flare")
{
rotateBarrier.Enabled = false;
}
else
{
rotateBarrier.Enabled = true;
}
barrierMenu.Width = SetMenuWidth();
}
else if (selectedScroller == rotateBarrier)
{
rotateBarrier.ScrollToPreviousOption();
shadowBarrier.Heading = rotateBarrier.Value;
}
else if(selectedScroller == removeBarrierOptions)
{
removeBarrierOptions.ScrollToPreviousOption();
}
}
}
}
}
private static Vector3 GetMousePositionInWorld()
{
HitResult TracePlayerView(float maxTraceDistance = 30f, 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>();
float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING<float>();
camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD<Vector3>();
return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized();
}
}
return TracePlayerView(Settings.BarrierPlacementDistance, TraceFlags.IntersectWorld).HitPosition;
}
private static float SetMenuWidth()

View file

@ -1,4 +1,6 @@
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
@ -15,6 +17,9 @@ namespace SceneManager
{
editPathMenu.ParentMenu = PathMainMenu.pathMainMenu;
MenuManager.menuPool.Add(editPathMenu);
editPathMenu.OnItemSelect += EditPath_OnItemSelected;
editPathMenu.OnCheckboxChange += EditPath_OnCheckboxChange;
editPathMenu.OnMenuOpen += EditPath_OnMouseDown;
}
internal static void BuildEditPathMenu()
@ -26,22 +31,44 @@ namespace SceneManager
deletePath.ForeColor = Color.Gold;
editPathMenu.RefreshIndex();
editPathMenu.OnItemSelect += EditPath_OnItemSelected;
editPathMenu.OnCheckboxChange += EditPath_OnCheckboxChange;
}
private static void EditPath_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
if (selectedItem == editPathWaypoints)
private static void EditPathWaypoints()
{
EditWaypointMenu.BuildEditWaypointMenu();
}
private static void DeletePath()
{
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
PathMainMenu.DeletePath(currentPath, PathMainMenu.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 EditPath_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if (selectedItem == editPathWaypoints)
{
EditPathWaypoints();
}
if (selectedItem == deletePath)
{
PathMainMenu.DeletePath(currentPath, PathMainMenu.Delete.Single);
DeletePath();
}
}
@ -49,16 +76,44 @@ namespace SceneManager
{
if (checkboxItem == disablePath)
{
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
if (disablePath.Checked)
{
currentPath.DisablePath();
Logger.Log($"Path {currentPath.Number} disabled.");
DisablePath();
}
else
}
private static void EditPath_OnMouseDown(UIMenu menu)
{
currentPath.EnablePath();
Logger.Log($"Path {currentPath.Number} enabled.");
GameFiber.StartNew(() =>
{
while (menu.Visible)
{
// Add waypoint if menu item is selected and user left clicks
if (Game.IsKeyDown(Keys.LButton))
{
OnCheckboxItemClicked();
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnCheckboxItemClicked()
{
if (disablePath.Selected && disablePath.Enabled)
{
disablePath.Checked = !disablePath.Checked;
DisablePath();
}
}
void OnMenuItemClicked()
{
if (editPathWaypoints.Selected)
{
EditPathWaypoints();
}
else if (deletePath.Selected)
{
DeletePath();
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
@ -16,26 +17,27 @@ namespace SceneManager
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<int> editWaypoint;
internal static UIMenuListScrollerItem<string> changeWaypointType = new UIMenuListScrollerItem<string>("Waypoint Type", "", waypointTypes);
private static UIMenuNumericScrollerItem<int> 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<int> changeCollectorRadius = new UIMenuNumericScrollerItem<int>("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1);
internal static UIMenuNumericScrollerItem<int> changeSpeedZoneRadius = new UIMenuNumericScrollerItem<int>("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 current position. You should turn this on if you're planning on adding this waypoint as a new waypoint.");
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 void InstantiateMenu()
{
editWaypointMenu.ParentMenu = EditPathMenu.editPathMenu;
MenuManager.menuPool.Add(editWaypointMenu);
editWaypointMenu.OnScrollerChange += EditWaypoint_OnScrollerChanged;
editWaypointMenu.OnCheckboxChange += EditWaypoint_OnCheckboxChanged;
editWaypointMenu.OnItemSelect += EditWaypoint_OnItemSelected;
editWaypointMenu.OnMenuOpen += EditWaypoint_OnMouseDown;
}
internal static void BuildEditWaypointMenu()
{
// Need to unsubscribe from these or else there will be duplicate firings if the user left the menu, then re-entered
ResetEventHandlerSubscriptions();
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Value-1];
//Logger.Log($"Current path: {currentPath.Number}");
@ -85,17 +87,116 @@ namespace SceneManager
editWaypointMenu.RefreshIndex();
editWaypointMenu.Visible = true;
}
}
void ResetEventHandlerSubscriptions()
private static void UpdateWaypoint(Path currentPath, Waypoint currentWaypoint, DrivingFlagType drivingFlag)
{
editWaypointMenu.OnItemSelect -= EditWaypoint_OnItemSelected;
editWaypointMenu.OnCheckboxChange -= EditWaypoint_OnCheckboxChanged;
editWaypointMenu.OnScrollerChange -= EditWaypoint_OnScrollerChanged;
if (currentPath.Waypoints.Count == 1)
{
currentWaypoint.UpdateWaypoint(currentWaypoint, GetMousePositionInWorld(), drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
}
else
{
currentWaypoint.UpdateWaypoint(currentWaypoint, GetMousePositionInWorld(), drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), collectorWaypoint.Checked, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
}
editWaypointMenu.OnScrollerChange += EditWaypoint_OnScrollerChanged;
editWaypointMenu.OnCheckboxChange += EditWaypoint_OnCheckboxChanged;
editWaypointMenu.OnItemSelect += EditWaypoint_OnItemSelected;
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\n~g~[Success]~w~ Waypoint {currentWaypoint.Number} updated.");
}
private static void RemoveWaypoint(Path currentPath, Waypoint currentWaypoint, DrivingFlagType drivingFlag)
{
if (currentPath.Waypoints.Count == 1)
{
Game.LogTrivial($"Deleting the last waypoint from the path.");
PathMainMenu.DeletePath(currentPath, PathMainMenu.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)
{
wp.Number = currentPath.Waypoints.IndexOf(wp) + 1;
//Logger.Log($"Waypoint at index {currentPath.Waypoints.IndexOf(wp)} is now waypoint #{wp.Number}");
}
editWaypointMenu.Clear();
BuildEditWaypointMenu();
if (currentPath.Waypoints.Count == 1)
{
Hints.Display($"~o~Scene Manager\n~y~[Hint]~w~ Your 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, GetMousePositionInWorld(), drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
collectorWaypoint.Checked = true;
changeCollectorRadius.Enabled = true;
changeSpeedZoneRadius.Enabled = true;
}
}
}
private static void AddAsNewWaypoint(Path currentPath, DrivingFlagType drivingFlag)
{
var pathIndex = PathMainMenu.paths.IndexOf(currentPath);
var newWaypointBlip = CreateNewWaypointBlip();
if (!currentPath.IsEnabled)
{
newWaypointBlip.Alpha = 0.5f;
}
if (collectorWaypoint.Checked)
{
currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, GetMousePositionInWorld(), SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip, true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value));
}
else
{
currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, GetMousePositionInWorld(), SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip));
}
editWaypointMenu.RemoveItemAt(0);
editWaypoint = new UIMenuNumericScrollerItem<int>("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(GetMousePositionInWorld())
{
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;
}
}
@ -106,8 +207,6 @@ namespace SceneManager
if (scrollerItem == editWaypoint)
{
//changeWaypointType.Index = Array.IndexOf(drivingFlags, currentWaypoint.DrivingFlag);
changeWaypointSpeed.Value = (int)MathHelper.ConvertMetersPerSecondToMilesPerHour(currentWaypoint.Speed);
stopWaypointType.Checked = currentWaypoint.IsStopWaypoint;
directWaypointBehavior.Checked = currentWaypoint.DrivingFlagType == DrivingFlagType.Direct ? true : false;
@ -156,117 +255,238 @@ namespace SceneManager
if (selectedItem == updateWaypoint)
{
if(currentPath.Waypoints.Count == 1)
{
currentWaypoint.UpdateWaypoint(currentWaypoint, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
}
else
{
currentWaypoint.UpdateWaypoint(currentWaypoint, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), collectorWaypoint.Checked, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
}
Logger.Log($"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\n~g~[Success]~w~ Waypoint {currentWaypoint.Number} updated.");
// Why am I rebuilding the menu??
//BuildEditWaypointMenu();
UpdateWaypoint(currentPath, currentWaypoint, drivingFlag);
}
if (selectedItem == addAsNewWaypoint)
{
var pathIndex = PathMainMenu.paths.IndexOf(currentPath);
var newWaypointBlip = CreateNewWaypointBlip();
if (!currentPath.IsEnabled)
{
newWaypointBlip.Alpha = 0.5f;
}
if (collectorWaypoint.Checked)
{
currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, Game.LocalPlayer.Character.Position, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip, true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value));
}
else
{
currentPath.Waypoints.Add(new Waypoint(currentPath, currentPath.Waypoints.Last().Number + 1, Game.LocalPlayer.Character.Position, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, newWaypointBlip));
}
editWaypointMenu.RemoveItemAt(0);
editWaypoint = new UIMenuNumericScrollerItem<int>("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;
Logger.Log($"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(Game.LocalPlayer.Character.Position)
{
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;
}
AddAsNewWaypoint(currentPath, drivingFlag);
}
if (selectedItem == removeWaypoint)
{
if (currentPath.Waypoints.Count == 1)
{
Logger.Log($"Deleting the last waypoint from the path.");
PathMainMenu.DeletePath(currentPath, PathMainMenu.Delete.Single);
RemoveWaypoint(currentPath, currentWaypoint, drivingFlag);
}
}
editWaypointMenu.Visible = false;
PathMainMenu.pathMainMenu.Visible = true;
private static void EditWaypoint_OnMouseDown(UIMenu menu)
{
GameFiber.StartNew(() =>
{
while (menu.Visible)
{
var selectedScroller = menu.MenuItems.Where(x => (x == editWaypoint || x == changeWaypointSpeed || x == changeCollectorRadius || x == changeSpeedZoneRadius) && x.Selected).FirstOrDefault();
if (selectedScroller != null)
{
HandleScrollerItemsWithMouseWheel(selectedScroller);
}
if (Game.IsKeyDown(Keys.LButton))
{
OnCheckboxItemClicked();
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnCheckboxItemClicked()
{
if (collectorWaypoint.Selected && collectorWaypoint.Enabled)
{
collectorWaypoint.Checked = !collectorWaypoint.Checked;
}
else if (stopWaypointType.Selected)
{
stopWaypointType.Checked = !stopWaypointType.Checked;
}
else if (directWaypointBehavior.Selected)
{
directWaypointBehavior.Checked = !directWaypointBehavior.Checked;
}
else if (updateWaypointPosition.Selected)
{
updateWaypointPosition.Checked = !updateWaypointPosition.Checked;
if (updateWaypointPosition.Checked)
{
DrawWaypointMarker(GetMousePositionInWorld());
}
}
}
void OnMenuItemClicked()
{
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
var currentWaypoint = currentPath.Waypoints[editWaypoint.Index];
DrivingFlagType drivingFlag = directWaypointBehavior.Checked ? DrivingFlagType.Direct : DrivingFlagType.Normal;
if (updateWaypoint.Selected)
{
UpdateWaypoint(currentPath, currentWaypoint, drivingFlag);
}
else if (removeWaypoint.Selected)
{
RemoveWaypoint(currentPath, currentWaypoint, drivingFlag);
}
else if (addAsNewWaypoint.Selected)
{
AddAsNewWaypoint(currentPath, drivingFlag);
}
}
void HandleScrollerItemsWithMouseWheel(UIMenuItem selectedScroller)
{
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();
CompareScrollerValues();
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)
{
if (selectedScroller == changeCollectorRadius)
{
changeCollectorRadius.ScrollToNextOption();
}
else if (selectedScroller == changeSpeedZoneRadius)
{
changeSpeedZoneRadius.ScrollToNextOption();
}
else if (selectedScroller == changeWaypointSpeed)
{
changeWaypointSpeed.ScrollToNextOption();
}
else if(selectedScroller == editWaypoint)
{
editWaypoint.ScrollToNextOption();
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
var currentWaypoint = currentPath.Waypoints[editWaypoint.Value - 1];
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;
}
}
else if (Game.GetMouseWheelDelta() < 0)
{
if (selectedScroller == changeCollectorRadius)
{
changeCollectorRadius.ScrollToPreviousOption();
}
else if (selectedScroller == changeSpeedZoneRadius)
{
changeSpeedZoneRadius.ScrollToPreviousOption();
}
else if (selectedScroller == changeWaypointSpeed)
{
changeWaypointSpeed.ScrollToPreviousOption();
}
else if (selectedScroller == editWaypoint)
{
editWaypoint.ScrollToPreviousOption();
var currentPath = PathMainMenu.paths[PathMainMenu.editPath.Index];
var currentWaypoint = currentPath.Waypoints[editWaypoint.Value - 1];
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;
}
}
}
void CompareScrollerValues()
{
if (selectedScroller == changeCollectorRadius && changeCollectorRadius.Value > changeSpeedZoneRadius.Value)
{
while (changeCollectorRadius.Value > changeSpeedZoneRadius.Value)
{
changeSpeedZoneRadius.ScrollToNextOption();
}
}
if (selectedScroller == changeSpeedZoneRadius && changeSpeedZoneRadius.Value < changeCollectorRadius.Value)
{
changeCollectorRadius.Value = changeSpeedZoneRadius.Value;
}
}
}
}
private static void DrawWaypointMarker(Vector3 waypointPosition)
{
if (SettingsMenu.threeDWaypoints.Checked && 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 (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
{
currentWaypoint.Remove();
currentPath.Waypoints.Remove(currentWaypoint);
Logger.Log($"[Path {currentPath.Number}] Waypoint {currentWaypoint.Number} ({currentWaypoint.DrivingFlagType}) removed");
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);
}
}
foreach (Waypoint wp in currentPath.Waypoints)
private static Vector3 GetMousePositionInWorld()
{
wp.Number = currentPath.Waypoints.IndexOf(wp) + 1;
//Logger.Log($"Waypoint at index {currentPath.Waypoints.IndexOf(wp)} is now waypoint #{wp.Number}");
}
HitResult TracePlayerView(float maxTraceDistance = 100f, TraceFlags flags = TraceFlags.IntersectWorld) => TracePlayerView2(out Vector3 v1, out Vector3 v2, maxTraceDistance, flags);
editWaypointMenu.Clear();
BuildEditWaypointMenu();
if (currentPath.Waypoints.Count == 1)
HitResult TracePlayerView2(out Vector3 start, out Vector3 end, float maxTraceDistance, TraceFlags flags)
{
Hints.Display($"~o~Scene Manager\n~y~[Hint]~w~ Your path's first waypoint ~b~must~w~ be a collector. If it's not, it will automatically be made into one.");
Logger.Log($"The path only has 1 waypoint left, this waypoint must be a collector.");
currentPath.Waypoints[0].UpdateWaypoint(currentWaypoint, drivingFlag, stopWaypointType.Checked, SetDriveSpeedForWaypoint(), true, changeCollectorRadius.Value, changeSpeedZoneRadius.Value, updateWaypointPosition.Checked);
collectorWaypoint.Checked = true;
changeCollectorRadius.Enabled = true;
changeSpeedZoneRadius.Enabled = true;
}
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>();
float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING<float>();
camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD<Vector3>();
return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized();
}
}
return TracePlayerView(100f, TraceFlags.IntersectWorld).HitPosition;
}
private static float SetDriveSpeedForWaypoint()

View file

@ -1,6 +1,9 @@
using RAGENativeUI;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace SceneManager
{
@ -29,6 +32,7 @@ namespace SceneManager
mainMenu.RefreshIndex();
mainMenu.OnItemSelect += MainMenu_OnItemSelected;
mainMenu.OnMenuOpen += MainMenu_OnMouseDown;
}
private static void MainMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
@ -38,5 +42,38 @@ namespace SceneManager
BarrierMenu.CreateShadowBarrier(BarrierMenu.barrierMenu);
}
}
private static void MainMenu_OnMouseDown(UIMenu menu)
{
GameFiber.StartNew(() =>
{
while (menu.Visible)
{
if (Game.IsKeyDown(Keys.LButton))
{
menu.Visible = false;
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnMenuItemClicked()
{
if (navigateToPathMenu.Selected)
{
PathMainMenu.pathMainMenu.Visible = true;
}
else if (navigateToBarrierMenu.Selected)
{
BarrierMenu.barrierMenu.Visible = true;
BarrierMenu.CreateShadowBarrier(BarrierMenu.barrierMenu);
}
else if (navigateToSettingsMenu.Selected)
{
SettingsMenu.settingsMenu.Visible = true;
}
}
}
}
}

View file

@ -34,7 +34,6 @@ namespace SceneManager
MainMenu.BuildMainMenu();
SettingsMenu.BuildSettingsMenu();
PathMainMenu.BuildPathMenu();
PathCreationMenu.BuildPathCreationMenu();
EditPathMenu.BuildEditPathMenu();
BarrierMenu.BuildBarrierMenu();
}

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
@ -10,22 +11,24 @@ namespace SceneManager
{
class PathCreationMenu
{
private static VehicleDrivingFlags[] drivingFlags = new VehicleDrivingFlags[] { VehicleDrivingFlags.Normal, VehicleDrivingFlags.IgnorePathFinding, VehicleDrivingFlags.StopAtDestination }; // Implement custom driving flag for normal
private static string[] waypointTypes = new string[] { "Drive To (Normal)", "Drive To (Direct)", "Stop" };
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 UIMenuListScrollerItem<string> waypointType = new UIMenuListScrollerItem<string>("Waypoint Type", $"~b~Drive To (Normal): ~w~AI obeys traffic as much as possible{Environment.NewLine}~b~Drive To (Direct): ~w~AI ignores pathfinding rules{Environment.NewLine}~b~Stop: ~w~AI stops at the waypoint until dismissed", waypointTypes);
private static UIMenuNumericScrollerItem<int> waypointSpeed;
internal static UIMenuNumericScrollerItem<int> 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<int> collectorRadius = new UIMenuNumericScrollerItem<int>("Collection Radius", "The distance from this waypoint (in meters) vehicles will be collected", 1, 50, 1);
internal static UIMenuNumericScrollerItem<int> speedZoneRadius = new UIMenuNumericScrollerItem<int>("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<UIMenuItem> menuItems = new List<UIMenuItem> {collectorWaypoint, collectorRadius, speedZoneRadius, stopWaypointType, directWaypointBehavior, waypointSpeed, trafficAddWaypoint, trafficRemoveWaypoint, trafficEndPath };
internal static void InstantiateMenu()
{
pathCreationMenu.ParentMenu = PathMainMenu.pathMainMenu;
MenuManager.menuPool.Add(pathCreationMenu);
pathCreationMenu.OnItemSelect += PathCreation_OnItemSelected;
pathCreationMenu.OnCheckboxChange += PathCreation_OnCheckboxChanged;
pathCreationMenu.OnScrollerChange += PathCreation_OnScrollerChanged;
pathCreationMenu.OnMenuOpen += PathCreation_OnMouseDown;
}
internal static void BuildPathCreationMenu()
@ -35,18 +38,20 @@ namespace SceneManager
collectorWaypoint.Checked = true;
pathCreationMenu.AddItem(collectorRadius);
collectorRadius.Index = 0;
collectorRadius.Index = Settings.CollectorRadius - 1;
collectorRadius.Enabled = true;
pathCreationMenu.AddItem(speedZoneRadius);
speedZoneRadius.Index = 0;
speedZoneRadius.Index = (Settings.SpeedZoneRadius / 5) - 1;
speedZoneRadius.Enabled = true;
pathCreationMenu.AddItem(stopWaypointType);
stopWaypointType.Checked = Settings.StopWaypoint;
pathCreationMenu.AddItem(directWaypointBehavior);
directWaypointBehavior.Checked = Settings.DirectDrivingBehavior;
pathCreationMenu.AddItem(waypointSpeed = new UIMenuNumericScrollerItem<int>("Waypoint Speed", $"How fast the AI will drive to this waypoint in ~b~{SettingsMenu.speedUnits.SelectedItem}", 5, 100, 5));
waypointSpeed.Index = 0;
waypointSpeed.Index = (Settings.WaypointSpeed / 5) - 1;
pathCreationMenu.AddItem(trafficAddWaypoint);
trafficAddWaypoint.ForeColor = Color.Gold;
@ -60,9 +65,6 @@ namespace SceneManager
trafficEndPath.Enabled = false;
pathCreationMenu.RefreshIndex();
pathCreationMenu.OnItemSelect += PathCreation_OnItemSelected;
pathCreationMenu.OnCheckboxChange += PathCreation_OnCheckboxChanged;
pathCreationMenu.OnScrollerChange += PathCreation_OnScrollerChanged;
}
private static void PathCreation_OnCheckboxChanged(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked)
@ -77,6 +79,176 @@ namespace SceneManager
private static void PathCreation_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if (selectedItem == trafficAddWaypoint)
{
AddNewWaypoint(GetMousePositionInWorld());
}
if (selectedItem == trafficRemoveWaypoint)
{
RemoveWaypoint();
}
if (selectedItem == trafficEndPath)
{
EndPath();
}
}
private static void PathCreation_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int first, int last)
{
if (scrollerItem == collectorRadius)
{
if (collectorRadius.Value > speedZoneRadius.Value)
{
while (collectorRadius.Value > speedZoneRadius.Value)
{
speedZoneRadius.ScrollToNextOption();
}
}
}
if (scrollerItem == speedZoneRadius)
{
if (speedZoneRadius.Value < collectorRadius.Value)
{
collectorRadius.Value = speedZoneRadius.Value;
}
}
}
private static void PathCreation_OnMouseDown(UIMenu menu)
{
GameFiber.StartNew(() =>
{
while (menu.Visible)
{
var selectedScroller = menu.MenuItems.Where(x => (x == collectorRadius || x == speedZoneRadius || x == waypointSpeed) && x.Selected).FirstOrDefault();
if (selectedScroller != null)
{
HandleScrollerItemsWithMouseWheel(selectedScroller);
}
// Draw marker at mouse position
DrawWaypointMarker(GetMousePositionInWorld());
// Add waypoint if menu item is selected and user left clicks
if (Game.IsKeyDown(Keys.LButton))
{
OnCheckboxItemClicked();
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnCheckboxItemClicked()
{
if (collectorWaypoint.Selected && collectorWaypoint.Enabled)
{
collectorWaypoint.Checked = !collectorWaypoint.Checked;
}
else if (stopWaypointType.Selected)
{
stopWaypointType.Checked = !stopWaypointType.Checked;
}
else if (directWaypointBehavior.Selected)
{
directWaypointBehavior.Checked = !directWaypointBehavior.Checked;
}
}
void OnMenuItemClicked()
{
if (trafficAddWaypoint.Selected)
{
AddNewWaypoint(GetMousePositionInWorld());
}
else if (trafficRemoveWaypoint.Selected)
{
RemoveWaypoint();
}
else if (trafficEndPath.Selected)
{
EndPath();
}
}
void HandleScrollerItemsWithMouseWheel(UIMenuItem selectedScroller)
{
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();
CompareScrollerValues();
DrawWaypointMarker(GetMousePositionInWorld());
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)
{
if (selectedScroller == collectorRadius)
{
collectorRadius.ScrollToNextOption();
}
else if (selectedScroller == speedZoneRadius)
{
speedZoneRadius.ScrollToNextOption();
}
else if (selectedScroller == waypointSpeed)
{
waypointSpeed.ScrollToNextOption();
}
}
else if (Game.GetMouseWheelDelta() < 0)
{
if (selectedScroller == collectorRadius)
{
collectorRadius.ScrollToPreviousOption();
}
else if (selectedScroller == speedZoneRadius)
{
speedZoneRadius.ScrollToPreviousOption();
}
else if (selectedScroller == waypointSpeed)
{
waypointSpeed.ScrollToPreviousOption();
}
}
}
void CompareScrollerValues()
{
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 AddNewWaypoint(Vector3 waypointPosition)
{
var anyPathsExist = PathMainMenu.paths.Count > 0;
@ -84,7 +256,7 @@ namespace SceneManager
{
AddNewPathToPathsCollection(PathMainMenu.paths, 0);
}
else if(anyPathsExist && !PathMainMenu.paths.Any(p => p != null && p.State == State.Creating))
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);
}
@ -97,13 +269,13 @@ namespace SceneManager
if (collectorWaypoint.Checked)
{
PathMainMenu.paths[pathIndex].Waypoints.Add(new Waypoint(firstNonNullPath, waypointNumber, Game.LocalPlayer.Character.Position, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, CreateWaypointBlip(), true, collectorRadius.Value, speedZoneRadius.Value));
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, Game.LocalPlayer.Character.Position, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, CreateWaypointBlip()));
PathMainMenu.paths[pathIndex].Waypoints.Add(new Waypoint(firstNonNullPath, waypointNumber, waypointPosition, SetDriveSpeedForWaypoint(), drivingFlag, stopWaypointType.Checked, CreateWaypointBlip()));
}
Logger.Log($"Path {pathNumber} Waypoint {waypointNumber} added [Driving style: {drivingFlag} | Stop waypoint: {stopWaypointType.Checked} | Speed: {waypointSpeed.Value} | Collector: {collectorWaypoint.Checked}]");
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;
@ -133,7 +305,7 @@ namespace SceneManager
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(Game.LocalPlayer.Character.Position)
var blip = new Blip(waypointPosition)
{
Scale = 0.5f,
Sprite = (BlipSprite)spriteNumericalEnum
@ -161,14 +333,13 @@ namespace SceneManager
}
}
if (selectedItem == trafficRemoveWaypoint)
private static void RemoveWaypoint()
{
// Loop through each path and find the first one which isn't finished, then delete the path's last waypoint and corresponding blip
for (int i = 0; i < PathMainMenu.paths.Count; i++)
{
if (PathMainMenu.paths.ElementAtOrDefault(i) != null && PathMainMenu.paths[i].State == State.Creating)
{
Logger.Log($"[Path {i + 1}] {PathMainMenu.paths[i].Waypoints.Last().DrivingFlagType} waypoint removed");
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();
@ -194,16 +365,15 @@ namespace SceneManager
}
}
if (selectedItem == trafficEndPath)
private static void EndPath()
{
// Loop through each path and find the first one which isn't finished
for (int i = 0; i < PathMainMenu.paths.Count; i++)
{
var currentPath = PathMainMenu.paths[i];
if (PathMainMenu.paths.ElementAtOrDefault(i) != null && currentPath.State == State.Creating)
{
Logger.Log($"[Path Creation] Path {currentPath.Number} finished with {currentPath.Waypoints.Count} waypoints.");
Game.DisplayNotification($"~o~Scene Manager\n~g~[Success]~w~ Path {i + 1} complete.");
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;
@ -212,57 +382,17 @@ namespace SceneManager
GameFiber.StartNew(() =>
{
currentPath.LoopWaypointCollection();
//foreach(Waypoint waypoint in PathMainMenu.paths[i].Waypoints)
//{
// GameFiber WaypointVehicleCollectorFiber = new GameFiber(() => waypoint.CollectVehicles(PathMainMenu.paths));
// WaypointVehicleCollectorFiber.Start();
// GameFiber.Sleep(1000);
//}
});
PathMainMenu.createNewPath.Text = "Create New Path";
PathMainMenu.BuildPathMenu();
PathMainMenu.pathMainMenu.RefreshIndex();
pathCreationMenu.RefreshIndex();
waypointSpeed.Index = 0;
collectorWaypoint.Enabled = false;
collectorWaypoint.Checked = true;
speedZoneRadius.Enabled = true;
speedZoneRadius.Index = 0;
collectorRadius.Enabled = true;
collectorRadius.Index = 0;
stopWaypointType.Checked = false;
directWaypointBehavior.Checked = false;
trafficEndPath.Enabled = false;
pathCreationMenu.Clear();
PathMainMenu.pathMainMenu.Visible = true;
break;
}
}
}
}
private static void PathCreation_OnScrollerChanged(UIMenu sender, UIMenuScrollerItem scrollerItem, int first, int last)
{
if (scrollerItem == collectorRadius)
{
if (collectorRadius.Value > speedZoneRadius.Value)
{
while(collectorRadius.Value > speedZoneRadius.Value)
{
speedZoneRadius.ScrollToNextOption();
}
}
}
if(scrollerItem == speedZoneRadius)
{
if(speedZoneRadius.Value < collectorRadius.Value)
{
collectorRadius.Value = speedZoneRadius.Value;
}
}
}
private static void ToggleTrafficEndPathMenuItem(int pathIndex)
{
@ -279,11 +409,59 @@ namespace SceneManager
internal static void AddNewPathToPathsCollection(List<Path> paths, int pathIndex)
{
var pathNum = pathIndex + 1;
Logger.Log($"Creating path {pathNum}");
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 DrawWaypointMarker(Vector3 waypointPosition)
{
if (SettingsMenu.threeDWaypoints.Checked && 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 (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);
}
}
private static Vector3 GetMousePositionInWorld()
{
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>();
float heading = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_RELATIVE_HEADING<float>();
camPosition = Rage.Native.NativeFunction.Natives.GET_GAMEPLAY_CAM_COORD<Vector3>();
return (Game.LocalPlayer.Character.Rotation + new Rotator(pitch, 0, heading)).ToVector().ToNormalized();
}
}
return TracePlayerView(100f, TraceFlags.IntersectWorld).HitPosition;
}
}
}

View file

@ -2,25 +2,20 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Rage;
using RAGENativeUI;
using RAGENativeUI.Elements;
namespace SceneManager
{
public enum DismissOption
{
FromPath = 0,
FromWaypoint = 1,
FromWorld = 2,
FromPlayer = 3,
FromDirected = 4
}
static class PathMainMenu
{
internal static List<Path> paths = new List<Path>() { };
private static List<string> dismissOptions = new List<string>() { "From path", "From waypoint", "From world" };
private static string[] dismissOptions = new string[] { "From path", "From waypoint", "From world" };
//private static List<string> dismissOptions = new List<string>() { "From path", "From waypoint", "From world" };
internal static UIMenu pathMainMenu = new UIMenu("Scene Manager", "~o~Path Manager Main Menu");
internal static UIMenuItem createNewPath;
@ -41,13 +36,13 @@ namespace SceneManager
{
pathMainMenu.ParentMenu = MainMenu.mainMenu;
MenuManager.menuPool.Add(pathMainMenu);
pathMainMenu.OnItemSelect += PathMenu_OnItemSelected;
pathMainMenu.OnCheckboxChange += PathMenu_OnCheckboxChange;
pathMainMenu.OnMenuOpen += PathMenu_OnMouseDown;
}
internal static void BuildPathMenu()
{
// Need to unsubscribe from events, else there will be duplicate firings if the user left the menu and re-entered
ResetEventHandlerSubscriptions();
MenuManager.menuPool.CloseAllMenus();
pathMainMenu.Clear();
@ -81,14 +76,6 @@ namespace SceneManager
}
MenuManager.menuPool.RefreshIndex();
void ResetEventHandlerSubscriptions()
{
pathMainMenu.OnItemSelect -= PathMenu_OnItemSelected;
pathMainMenu.OnCheckboxChange -= PathMenu_OnCheckboxChange;
pathMainMenu.OnItemSelect += PathMenu_OnItemSelected;
pathMainMenu.OnCheckboxChange += PathMenu_OnCheckboxChange;
}
}
private static bool VehicleAndDriverValid(this Vehicle v)
@ -103,6 +90,68 @@ namespace SceneManager
}
}
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;
//Draw3DWaypointOnPlayer();
// 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.LogTrivial($"Resuming path {paths[i].Number}");
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}");
@ -196,48 +245,7 @@ namespace SceneManager
}
}
private static void PathMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if (selectedItem == createNewPath)
{
pathMainMenu.Visible = false;
PathCreationMenu.pathCreationMenu.Visible = true;
Draw3DWaypointOnPlayer();
// 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.LogTrivial($"Resuming path {paths[i].Number}");
Game.DisplayNotification($"~o~Scene Manager\n~y~[Creating]~w~ Resuming path {paths[i].Number}");
break;
}
}
}
if (selectedItem == editPath)
{
pathMainMenu.Visible = false;
EditPathMenu.editPathMenu.Visible = true;
}
if (selectedItem == deleteAllPaths)
{
// Iterate through each item in paths and delete it
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.");
}
if (selectedItem == directDriver)
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];
@ -249,7 +257,7 @@ namespace SceneManager
if (nearbyVehicle)
{
var nearbyVehiclePath = paths.Where(p => p.CollectedVehicles.Any(v => v.Vehicle == nearbyVehicle)).FirstOrDefault();
if(nearbyVehiclePath != null)
if (nearbyVehiclePath != null)
{
var nearbyCollectedVehicle = nearbyVehiclePath.CollectedVehicles.Where(v => v.Vehicle == nearbyVehicle).FirstOrDefault();
if (nearbyCollectedVehicle != null)
@ -313,7 +321,7 @@ namespace SceneManager
}
}
if (selectedItem == dismissDriver)
private static void DismissDriver()
{
var nearbyVehicle = Game.LocalPlayer.Character.GetNearbyVehicles(16).Where(v => v != Game.LocalPlayer.Character.CurrentVehicle && v.VehicleAndDriverValid()).FirstOrDefault();
if (nearbyVehicle)
@ -336,7 +344,7 @@ namespace SceneManager
return;
}
foreach(Path path in paths)
foreach (Path path in paths)
{
var collectedVehicle = path.CollectedVehicles.Where(cv => cv.Vehicle == nearbyVehicle).FirstOrDefault();
if (collectedVehicle != null)
@ -364,60 +372,195 @@ namespace SceneManager
}
}
}
private static void PathMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if (selectedItem == createNewPath)
{
GoToPathCreationMenu();
}
if (selectedItem == editPath)
{
pathMainMenu.Visible = false;
EditPathMenu.editPathMenu.Visible = true;
}
if (selectedItem == deleteAllPaths)
{
DeleteAllPaths();
}
if (selectedItem == directDriver)
{
DirectDriver();
}
if (selectedItem == dismissDriver)
{
DismissDriver();
}
}
private static void PathMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked)
{
if (checkboxItem == 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.");
}
DisableAllPaths();
}
}
private static void Draw3DWaypointOnPlayer()
private static void PathMenu_OnMouseDown(UIMenu menu)
{
GameFiber.StartNew(() =>
{
while (SettingsMenu.threeDWaypoints.Checked)
while (menu.Visible)
{
if (PathCreationMenu.pathCreationMenu.Visible)
var selectedScroller = menu.MenuItems.Where(x => (x == directOptions || x == directDriver || x == dismissDriver || x == editPath) && x.Selected).FirstOrDefault();
if (selectedScroller != null)
{
if (PathCreationMenu.collectorWaypoint.Checked)
{
Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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);
HandleScrollerItemsWithMouseWheel(selectedScroller);
}
else if (PathCreationMenu.stopWaypointType.Checked)
// Add waypoint if menu item is selected and user left clicks
if (Game.IsKeyDown(Keys.LButton))
{
Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false);
}
}
else
{
break;
OnCheckboxItemClicked();
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnCheckboxItemClicked()
{
if (disableAllPaths.Selected && disableAllPaths.Enabled)
{
disableAllPaths.Checked = !disableAllPaths.Checked;
DisableAllPaths();
}
}
void OnMenuItemClicked()
{
if (createNewPath.Selected)
{
GoToPathCreationMenu();
}
else if (editPath.Selected)
{
menu.Visible = false;
EditPathMenu.editPathMenu.Visible = true;
}
else if (deleteAllPaths.Selected)
{
DeleteAllPaths();
}
else if (directDriver.Selected)
{
DirectDriver();
}
else if (dismissDriver.Selected)
{
DismissDriver();
}
}
void HandleScrollerItemsWithMouseWheel(UIMenuItem selectedScroller)
{
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();
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)
{
if (selectedScroller == editPath)
{
editPath.ScrollToNextOption();
}
else if (selectedScroller == directOptions)
{
directOptions.ScrollToNextOption();
}
else if (selectedScroller == directDriver)
{
directDriver.ScrollToNextOption();
}
else if (selectedScroller == dismissDriver)
{
dismissDriver.ScrollToNextOption();
}
}
else if (Game.GetMouseWheelDelta() < 0)
{
if (selectedScroller == editPath)
{
editPath.ScrollToPreviousOption();
}
else if (selectedScroller == directOptions)
{
directOptions.ScrollToPreviousOption();
}
else if (selectedScroller == directDriver)
{
directDriver.ScrollToPreviousOption();
}
else if (selectedScroller == dismissDriver)
{
dismissDriver.ScrollToPreviousOption();
}
}
}
}
}
//private static void Draw3DWaypointOnPlayer()
//{
// GameFiber.StartNew(() =>
// {
// while (SettingsMenu.threeDWaypoints.Checked)
// {
// if (PathCreationMenu.pathCreationMenu.Visible)
// {
// if (PathCreationMenu.collectorWaypoint.Checked)
// {
// Rage.Native.NativeFunction.Natives.DRAW_MARKER(1, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 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, Game.LocalPlayer.Character.Position.X, Game.LocalPlayer.Character.Position.Y, Game.LocalPlayer.Character.Position.Z - 1, 0, 0, 0, 0, 0, 0, 1f, 1f, 1f, 65, 255, 65, 80, false, false, 2, false, 0, 0, false);
// }
// }
// else
// {
// break;
// }
// GameFiber.Yield();
// }
// });
//}
}
}

View file

@ -2,6 +2,8 @@
using RAGENativeUI;
using RAGENativeUI.Elements;
using System;
using System.Linq;
using System.Windows.Forms;
namespace SceneManager
{
@ -19,6 +21,10 @@ namespace SceneManager
{
settingsMenu.ParentMenu = MainMenu.mainMenu;
MenuManager.menuPool.Add(settingsMenu);
settingsMenu.OnCheckboxChange += SettingsMenu_OnCheckboxChange;
settingsMenu.OnScrollerChange += SettingsMenu_OnScrollerChange;
settingsMenu.OnItemSelect += SettingsMenu_OnItemSelected;
settingsMenu.OnMenuOpen += SettingsMenu_OnMouseDown;
}
internal static void BuildSettingsMenu()
@ -30,30 +36,15 @@ namespace SceneManager
speedUnits.Index = Array.IndexOf(speedArray, Settings.SpeedUnit);
settingsMenu.AddItem(saveSettings);
saveSettings.ForeColor = System.Drawing.Color.Gold;
settingsMenu.OnCheckboxChange += SettingsMenu_OnCheckboxChange;
settingsMenu.OnScrollerChange += SettingsMenu_OnScrollerChange;
settingsMenu.OnItemSelect += SettingsMenu_OnItemSelected;
}
private static void SettingsMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if(selectedItem == saveSettings)
{
Settings.UpdateSettings(threeDWaypoints.Checked, mapBlips.Checked, hints.Checked, speedUnits.SelectedItem);
Game.DisplayHelp($"Settings saved");
}
}
private static void SettingsMenu_OnCheckboxChange(UIMenu sender, UIMenuCheckboxItem checkboxItem, bool @checked)
{
if (checkboxItem == mapBlips)
internal static void ToggleMapBlips()
{
if (mapBlips.Checked)
{
foreach(Path path in PathMainMenu.paths)
foreach (Path path in PathMainMenu.paths)
{
foreach(Waypoint wp in path.Waypoints)
foreach (Waypoint wp in path.Waypoints)
{
wp.EnableBlip();
}
@ -71,6 +62,22 @@ namespace SceneManager
}
}
private static void SettingsMenu_OnItemSelected(UIMenu sender, UIMenuItem selectedItem, int index)
{
if(selectedItem == saveSettings)
{
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)
{
ToggleMapBlips();
}
if (checkboxItem == hints)
{
Hints.Enabled = hints.Checked ? true : false;
@ -86,5 +93,100 @@ namespace SceneManager
PathCreationMenu.BuildPathCreationMenu();
}
}
private static void SettingsMenu_OnMouseDown(UIMenu menu)
{
GameFiber.StartNew(() =>
{
while (menu.Visible)
{
var selectedScroller = menu.MenuItems.Where(x => x == speedUnits && x.Selected).FirstOrDefault();
if (selectedScroller != null)
{
HandleScrollerItemsWithMouseWheel(selectedScroller);
}
// Add waypoint if menu item is selected and user left clicks
if (Game.IsKeyDown(Keys.LButton))
{
OnCheckboxItemClicked();
OnMenuItemClicked();
}
GameFiber.Yield();
}
});
void OnCheckboxItemClicked()
{
if (threeDWaypoints.Selected && threeDWaypoints.Enabled)
{
threeDWaypoints.Checked = !threeDWaypoints.Checked;
}
else if (mapBlips.Selected)
{
mapBlips.Checked = !mapBlips.Checked;
ToggleMapBlips();
}
else if (hints.Selected)
{
hints.Checked = !hints.Checked;
Hints.Enabled = hints.Checked ? true : false;
}
}
void OnMenuItemClicked()
{
if (saveSettings.Selected)
{
Settings.UpdateSettings(threeDWaypoints.Checked, mapBlips.Checked, hints.Checked, speedUnits.SelectedItem);
Game.DisplayHelp($"Scene Manager settings saved");
}
}
void HandleScrollerItemsWithMouseWheel(UIMenuItem selectedScroller)
{
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();
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)
{
if (selectedScroller == speedUnits)
{
speedUnits.ScrollToNextOption();
PathCreationMenu.pathCreationMenu.Clear();
PathCreationMenu.BuildPathCreationMenu();
}
}
else if (Game.GetMouseWheelDelta() < 0)
{
if (selectedScroller == speedUnits)
{
speedUnits.ScrollToPreviousOption();
PathCreationMenu.pathCreationMenu.Clear();
PathCreationMenu.BuildPathCreationMenu();
}
}
}
}
}
}
}