Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Suggestion] Customizable Vehicle Spawn Time Limiter #462

Open
ryanb9038 opened this issue Dec 4, 2024 · 8 comments
Open

[Suggestion] Customizable Vehicle Spawn Time Limiter #462

ryanb9038 opened this issue Dec 4, 2024 · 8 comments

Comments

@ryanb9038
Copy link

I have been trying to do this myself and failed miserably. I would like to see a configurable entity spawn rate limiter specific to vehicles, built in to vMenu. If you play RSM Freeroam and spawn a vehicle, you will see they managed to do it with their custom vMenu.

@Ecliptedkillz
Copy link

Ecliptedkillz commented Dec 19, 2024

@ryanb9038 ive gotten it to work (for vehicles) but idk if ther are any bugs or if its the best wat to do it

and use this as the convar
setr vmenu_vehicle_spawn_cooldown 5

In Common Funtions after line 26 where the Variables are add
private static DateTime lastSpawnTime = DateTime.MinValue;

In Common Funtions around 1200 the Main Spawn Vehicle Functions replace

public static async Task<int> SpawnVehicle(uint vehicleHash, bool spawnInside, bool replacePrevious, bool skipLoad, VehicleInfo vehicleInfo, string saveName = null, float x = 0f, float y = 0f, float z = 0f, float heading = -1f)
{
    // Get the cooldown time from ConVar (default to 10 seconds if not set)
    int spawnCooldown = int.Parse(GetConvar("vehicle_spawn_cooldown", "10"));

    // Check cooldown before spawning the vehicle
    if ((DateTime.UtcNow - lastSpawnTime).TotalSeconds < spawnCooldown)
    {
        Notify.Alert($"Please wait {spawnCooldown} seconds before spawning another vehicle.");
        return 0;
    }

    var speed = 0f;
    var rpm = 0f;
    if (Game.PlayerPed.IsInVehicle())
    {
        var tmpOldVehicle = GetVehicle();
        speed = GetEntitySpeedVector(tmpOldVehicle.Handle, true).Y; // get forward/backward speed only
        rpm = tmpOldVehicle.CurrentRPM;
    }

    var modelClass = GetVehicleClassFromName(vehicleHash);
    if (!VehicleSpawner.allowedCategories[modelClass])
    {
        Notify.Alert("You are not allowed to spawn this vehicle, because it belongs to a category which is restricted by the server owner.");
        return 0;
    }

    if (!skipLoad)
    {
        var successFull = await LoadModel(vehicleHash);
        if (!successFull || !IsModelAVehicle(vehicleHash))
        {
            Notify.Error(CommonErrors.InvalidModel);
            return 0;
        }
    }

    Log("Spawning of vehicle is NOT cancelled, if this model is invalid then there's something wrong.");

    // Get the heading & position for where the vehicle should be spawned.
    var pos = new Vector3(x, y, z);
    if (pos.IsZero)
    {
        pos = spawnInside ? GetEntityCoords(Game.PlayerPed.Handle, true) : GetOffsetFromEntityInWorldCoords(Game.PlayerPed.Handle, 0f, 8f, 0f);
        pos += new Vector3(0f, 0f, 1f);
    }

    heading = heading == -1 ? GetEntityHeading(Game.PlayerPed.Handle) + (spawnInside ? 0f : 90f) : heading;

    // Update the last spawn time
    lastSpawnTime = DateTime.UtcNow;

@ryanb9038
Copy link
Author

ryanb9038 commented Dec 19, 2024

So far, this is working incredibly well. Thank you for taking the time to share this. I will publicly test this in my server and share any issues I may stumble across. I don't want to close this quite yet anyways though because I still want this to be a suggestion for this to be a feature included with vMenu. It will help many communities, particularly public ones, with trolls and spammers.

Edit: To add to this suggestion, a better way to handle this would be to figure out how we can lock the buttons during the cooldown. When I go down my vehicle list really fast spamming my spawn button with a 3 second delay, fairly often it will still spawn about 3-4 cars all in a very quick succession due to the cars needing to cache in still. That is not really that big of a deal, but just another suggestion for anyone who may want to tackle the issue further. Thank you again @Ecliptedkillz for sharing this, well done!

@Ecliptedkillz
Copy link

Ecliptedkillz commented Dec 19, 2024

ok i didnt test addon vehicles when making that but i think i also fixed that issue for non cached vehicles @ryanb9038 lmk if this works for you

In VehicleSpawners.cs after line 21 where the Variables are add

public static DateTime lastSpawnTime = DateTime.MinValue;

and at #region addon cars menu repalce it all with line 48

        #region addon cars menu
        // Vehicle Addons List
        var addonCarsMenu = new Menu("Addon Vehicles", "Spawn An Addon Vehicle");
        var addonCarsBtn = new MenuItem("Addon Vehicles", "A list of addon vehicles available on this server.") { Label = "→→→" };

        menu.AddMenuItem(addonCarsBtn);

        if (IsAllowed(Permission.VSAddon))
        {
            if (AddonVehicles != null)
            {
                if (AddonVehicles.Count > 0)
                {
                    MenuController.BindMenuItem(menu, addonCarsMenu, addonCarsBtn);
                    MenuController.AddSubmenu(menu, addonCarsMenu);
                    var unavailableCars = new Menu("Addon Spawner", "Unavailable Vehicles");
                    var unavailableCarsBtn = new MenuItem("Unavailable Vehicles", "These addon vehicles are not currently being streamed (correctly) and are not able to be spawned.") { Label = "→→→" };
                    MenuController.AddSubmenu(addonCarsMenu, unavailableCars);

                    for (var cat = 0; cat < 23; cat++)
                    {
                        var categoryMenu = new Menu("Addon Spawner", GetLabelText($"VEH_CLASS_{cat}"));
                        var categoryBtn = new MenuItem(GetLabelText($"VEH_CLASS_{cat}"), $"Spawn an addon vehicle from the {GetLabelText($"VEH_CLASS_{cat}")} class.") { Label = "→→→" };

                        addonCarsMenu.AddMenuItem(categoryBtn);

                        if (!allowedCategories[cat])
                        {
                            categoryBtn.Description = "This vehicle class is disabled by the server.";
                            categoryBtn.Enabled = false;
                            categoryBtn.LeftIcon = MenuItem.Icon.LOCK;
                            categoryBtn.Label = "";
                            continue;
                        }

                        // Loop through all addon vehicles in this class.
                        foreach (var veh in AddonVehicles.Where(v => GetVehicleClassFromName(v.Value) == cat))
                        {
                            var localizedName = GetLabelText(GetDisplayNameFromVehicleModel(veh.Value));
                            var name = localizedName != "NULL" ? localizedName : GetDisplayNameFromVehicleModel(veh.Value);
                            name = name != "CARNOTFOUND" ? name : veh.Key;

                            var carBtn = new MenuItem(name, $"Click to spawn {name}.")
                            {
                                Label = $"({veh.Key})",
                                ItemData = veh.Key // store the model name in the button data.
                            };

                            // Check if the model is in the CD image.
                            if (IsModelInCdimage(veh.Value))
                            {
                                categoryMenu.AddMenuItem(carBtn);
                            }
                            else
                            {
                                // If the model is not in the CD image, mark the vehicle as unavailable
                                carBtn.Enabled = false;
                                carBtn.Description = "This vehicle is not available. Please ask the server owner to check if the vehicle is being streamed correctly.";
                                carBtn.LeftIcon = MenuItem.Icon.LOCK;
                                unavailableCars.AddMenuItem(carBtn);
                            }
                        }

                        // Check if there are valid vehicles in the category
                        if (categoryMenu.Size > 0)
                        {
                            MenuController.AddSubmenu(addonCarsMenu, categoryMenu);
                            MenuController.BindMenuItem(addonCarsMenu, categoryMenu, categoryBtn);

                            // Use OnItemSelect on the categoryMenu to handle vehicle spawning and cooldown
                            categoryMenu.OnItemSelect += async (sender, item, index) =>
                            {
                                // Step 1: Get the cooldown time from ConVar (default to 10 seconds if not set)
                                int spawnCooldown = int.Parse(GetConvar("vmenu_vehicle_spawn_cooldown", "10"));

                                // Step 2: Check cooldown before spawning the vehicle
                                if ((DateTime.UtcNow - lastSpawnTime).TotalSeconds < spawnCooldown)
                                {
                                    Notify.Alert($"Please wait {spawnCooldown} seconds before spawning another vehicle.");
                                    return;
                                }

                                // Step 3: Proceed with vehicle spawn if cooldown has passed
                                lastSpawnTime = DateTime.UtcNow; // Update last spawn time

                                // Spawn the vehicle using its model name
                                await SpawnVehicle(item.ItemData.ToString(), SpawnInVehicle, ReplaceVehicle);
                            };
                        }
                        else
                        {
                            // Disable the category button if no vehicles are available
                            categoryBtn.Description = "There are no addon cars available in this category.";
                            categoryBtn.Enabled = false;
                            categoryBtn.LeftIcon = MenuItem.Icon.LOCK;
                            categoryBtn.Label = "";
                        }
                    }

                    if (unavailableCars.Size > 0)
                    {
                        addonCarsMenu.AddMenuItem(unavailableCarsBtn);
                        MenuController.BindMenuItem(addonCarsMenu, unavailableCars, unavailableCarsBtn);
                    }
                }
                else
                {
                    addonCarsBtn.Enabled = false;
                    addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
                    addonCarsBtn.Description = "There are no addon vehicles available on this server.";
                }
            }
            else
            {
                addonCarsBtn.Enabled = false;
                addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
                addonCarsBtn.Description = "The list containing all addon cars could not be loaded, is it configured properly?";
            }
        }
        else
        {
            addonCarsBtn.Enabled = false;
            addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
            addonCarsBtn.Description = "Access to this list has been restricted by the server owner.";
        }
        #endregion

@Ecliptedkillz
Copy link

edit: might not work 100% of the time

@ryanb9038
Copy link
Author

@Ecliptedkillz When trying to re-compile with these changes, i get this error.
C:\projects\fivem-sandbox-october-2024\vMenu\menus\VehicleSpawner.cs(23,23): error CS0246: The type or namespace name 'DateTime' could not be found (are you missing a using directive or an assembly reference?) [C:\projects\fivem-sandbox-october-2024\vMenu\vMenuClient.csproj]
Command exited with code 1
appveyor/on_failure.bat

@Ecliptedkillz
Copy link

@ryanb9038 did you add the Variables public static DateTime lastSpawnTime = DateTime.MinValue;
sorry for late response

@ryanb9038
Copy link
Author

@Ecliptedkillz I did. Copied and pasted it implemented it where you mentioned with the other variables.

@Ecliptedkillz
Copy link

@ryanb9038 this is the whole file with your vMenu

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using CitizenFX.Core;

using MenuAPI;

using vMenuClient.data;

using static CitizenFX.Core.Native.API;
using static vMenuClient.CommonFunctions;
using static vMenuShared.PermissionsManager;

namespace vMenuClient.menus
{
    public class VehicleSpawner
    {
        // Variables
        private Menu menu;
        public static Dictionary<string, uint> AddonVehicles;
        public static DateTime lastSpawnTime = DateTime.MinValue;

        public bool SpawnInVehicle { get; private set; } = UserDefaults.VehicleSpawnerSpawnInside;
        public bool ReplaceVehicle { get; private set; } = UserDefaults.VehicleSpawnerReplacePrevious;
        public static List<bool> allowedCategories;

        private void CreateMenu()
        {
            #region initial setup.
            // Create the menu.
            menu = new Menu(Game.Player.Name, "Vehicle Spawner");

            // Create the buttons and checkboxes.
            var spawnByName = new MenuItem("Spawn Vehicle By Model Name", "Enter the name of a vehicle to spawn.");
            var spawnInVeh = new MenuCheckboxItem("Spawn Inside Vehicle", "This will teleport you into the vehicle when you spawn it.", SpawnInVehicle);
            var replacePrev = new MenuCheckboxItem("~c~[Silver] ~s~Replace Previous Vehicle", "This will automatically delete your previously spawned vehicle when you spawn a new vehicle.", ReplaceVehicle);

            // Add the items to the menu.
            if (IsAllowed(Permission.VSSpawnByName))
            {
                menu.AddMenuItem(spawnByName);
            }
            menu.AddMenuItem(spawnInVeh);
            menu.AddMenuItem(replacePrev);
            #endregion

            #region addon cars menu
            // Vehicle Addons List
            var addonCarsMenu = new Menu("Addon Vehicles", "Spawn An Addon Vehicle");
            var addonCarsBtn = new MenuItem("Addon Vehicles", "A list of addon vehicles available on this server.") { Label = "→→→" };

            menu.AddMenuItem(addonCarsBtn);

            if (IsAllowed(Permission.VSAddon))
            {
                if (AddonVehicles != null)
                {
                    if (AddonVehicles.Count > 0)
                    {
                        MenuController.BindMenuItem(menu, addonCarsMenu, addonCarsBtn);
                        MenuController.AddSubmenu(menu, addonCarsMenu);
                        var unavailableCars = new Menu("Addon Spawner", "Unavailable Vehicles");
                        var unavailableCarsBtn = new MenuItem("Unavailable Vehicles", "These addon vehicles are not currently being streamed (correctly) and are not able to be spawned.") { Label = "→→→" };
                        MenuController.AddSubmenu(addonCarsMenu, unavailableCars);

                        for (var cat = 0; cat < 23; cat++)
                        {
                            var categoryMenu = new Menu("Addon Spawner", GetLabelText($"VEH_CLASS_{cat}"));
                            var categoryBtn = new MenuItem(GetLabelText($"VEH_CLASS_{cat}"), $"Spawn an addon vehicle from the {GetLabelText($"VEH_CLASS_{cat}")} class.") { Label = "→→→" };

                            addonCarsMenu.AddMenuItem(categoryBtn);

                            if (!allowedCategories[cat])
                            {
                                categoryBtn.Description = "This vehicle class is disabled by the server.";
                                categoryBtn.Enabled = false;
                                categoryBtn.LeftIcon = MenuItem.Icon.LOCK;
                                categoryBtn.Label = "";
                                continue;
                            }

                            // Loop through all addon vehicles in this class.
                            foreach (var veh in AddonVehicles.Where(v => GetVehicleClassFromName(v.Value) == cat))
                            {
                                var localizedName = GetLabelText(GetDisplayNameFromVehicleModel(veh.Value));
                                var name = localizedName != "NULL" ? localizedName : GetDisplayNameFromVehicleModel(veh.Value);
                                name = name != "CARNOTFOUND" ? name : veh.Key;

                                var carBtn = new MenuItem(name, $"Click to spawn {name}.")
                                {
                                    Label = $"({veh.Key})",
                                    ItemData = veh.Key // store the model name in the button data.
                                };

                                // Check if the model is in the CD image.
                                if (IsModelInCdimage(veh.Value))
                                {
                                    categoryMenu.AddMenuItem(carBtn);
                                }
                                else
                                {
                                    // If the model is not in the CD image, mark the vehicle as unavailable
                                    carBtn.Enabled = false;
                                    carBtn.Description = "This vehicle is not available. Please ask the server owner to check if the vehicle is being streamed correctly.";
                                    carBtn.LeftIcon = MenuItem.Icon.LOCK;
                                    unavailableCars.AddMenuItem(carBtn);
                                }
                            }

                            // Check if there are valid vehicles in the category
                            if (categoryMenu.Size > 0)
                            {
                                MenuController.AddSubmenu(addonCarsMenu, categoryMenu);
                                MenuController.BindMenuItem(addonCarsMenu, categoryMenu, categoryBtn);

                                // Use OnItemSelect on the categoryMenu to handle vehicle spawning and cooldown
                                categoryMenu.OnItemSelect += async (sender, item, index) =>
                                {
                                    // Step 1: Get the cooldown time from ConVar (default to 10 seconds if not set)
                                    int spawnCooldown = int.Parse(GetConvar("vmenu_vehicle_spawn_cooldown", "10"));

                                    // Step 2: Check cooldown before spawning the vehicle
                                    if ((DateTime.UtcNow - lastSpawnTime).TotalSeconds < spawnCooldown)
                                    {
                                        Notify.Alert($"Please wait {spawnCooldown} seconds before spawning another vehicle.");
                                        return;
                                    }

                                    // Step 3: Proceed with vehicle spawn if cooldown has passed
                                    lastSpawnTime = DateTime.UtcNow; // Update last spawn time

                                    // Spawn the vehicle using its model name
                                    await SpawnVehicle(item.ItemData.ToString(), SpawnInVehicle, ReplaceVehicle);
                                };
                            }
                            else
                            {
                                // Disable the category button if no vehicles are available
                                categoryBtn.Description = "There are no addon cars available in this category.";
                                categoryBtn.Enabled = false;
                                categoryBtn.LeftIcon = MenuItem.Icon.LOCK;
                                categoryBtn.Label = "";
                            }
                        }

                        if (unavailableCars.Size > 0)
                        {
                            addonCarsMenu.AddMenuItem(unavailableCarsBtn);
                            MenuController.BindMenuItem(addonCarsMenu, unavailableCars, unavailableCarsBtn);
                        }
                    }
                    else
                    {
                        addonCarsBtn.Enabled = false;
                        addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
                        addonCarsBtn.Description = "There are no addon vehicles available on this server.";
                    }
                }
                else
                {
                    addonCarsBtn.Enabled = false;
                    addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
                    addonCarsBtn.Description = "The list containing all addon cars could not be loaded, is it configured properly?";
                }
            }
            else
            {
                addonCarsBtn.Enabled = false;
                addonCarsBtn.LeftIcon = MenuItem.Icon.LOCK;
                addonCarsBtn.Description = "Access to this list has been restricted by the server owner.";
            }
            #endregion

            // These are the max speed, acceleration, braking and traction values per vehicle class.
            var speedValues = new float[23]
            {
                44.9374657f,
                50.0000038f,
                48.862133f,
                48.1321335f,
                50.7077942f,
                51.3333359f,
                52.3922348f,
                53.86687f,
                52.03867f,
                49.2241631f,
                39.6176529f,
                37.5559425f,
                42.72843f,
                21.0f,
                45.0f,
                65.1952744f,
                109.764259f,
                42.72843f,
                56.5962219f,
                57.5398865f,
                43.3140678f,
                26.66667f,
                53.0537224f
            };
            var accelerationValues = new float[23]
            {
                0.34f,
                0.29f,
                0.335f,
                0.28f,
                0.395f,
                0.39f,
                0.66f,
                0.42f,
                0.425f,
                0.475f,
                0.21f,
                0.3f,
                0.32f,
                0.17f,
                18.0f,
                5.88f,
                21.0700016f,
                0.33f,
                14.0f,
                6.86f,
                0.32f,
                0.2f,
                0.76f
            };
            var brakingValues = new float[23]
            {
                0.72f,
                0.95f,
                0.85f,
                0.9f,
                1.0f,
                1.0f,
                1.3f,
                1.25f,
                1.52f,
                1.1f,
                0.6f,
                0.7f,
                0.8f,
                3.0f,
                0.4f,
                3.5920403f,
                20.58f,
                0.9f,
                2.93960738f,
                3.9472363f,
                0.85f,
                5.0f,
                1.3f
            };
            var tractionValues = new float[23]
            {
                2.3f,
                2.55f,
                2.3f,
                2.6f,
                2.625f,
                2.65f,
                2.8f,
                2.782f,
                2.9f,
                2.95f,
                2.0f,
                3.3f,
                2.175f,
                2.05f,
                0.0f,
                1.6f,
                2.15f,
                2.55f,
                2.57f,
                3.7f,
                2.05f,
                2.5f,
                3.2925f
            };

            #region vehicle classes submenus
            // Loop through all the vehicle classes.
            for (var vehClass = 0; vehClass < 23; vehClass++)
            {
                // Get the class name.
                var className = GetLabelText($"VEH_CLASS_{vehClass}");

                // Create a button & a menu for it, add the menu to the menu pool and add & bind the button to the menu.
                var btn = new MenuItem(className, $"Spawn a vehicle from the ~o~{className} ~s~class.")
                {
                    Label = "→→→"
                };

                var vehicleClassMenu = new Menu("Vehicle Spawner", className);

                MenuController.AddSubmenu(menu, vehicleClassMenu);
                menu.AddMenuItem(btn);

                if (allowedCategories[vehClass])
                {
                    MenuController.BindMenuItem(menu, vehicleClassMenu, btn);
                }
                else
                {
                    btn.LeftIcon = MenuItem.Icon.LOCK;
                    btn.Description = "This category has been disabled by the server owner.";
                    btn.Enabled = false;
                }

                // Create a dictionary for the duplicate vehicle names (in this vehicle class).
                var duplicateVehNames = new Dictionary<string, int>();

                #region Add vehicles per class
                // Loop through all the vehicles in the vehicle class.
                foreach (var veh in VehicleData.Vehicles.VehicleClasses[className])
                {
                    // Convert the model name to start with a Capital letter, converting the other characters to lowercase. 
                    var properCasedModelName = veh[0].ToString().ToUpper() + veh.ToLower().Substring(1);

                    // Get the localized vehicle name, if it's "NULL" (no label found) then use the "properCasedModelName" created above.
                    var vehName = GetVehDisplayNameFromModel(veh) != "NULL" ? GetVehDisplayNameFromModel(veh) : properCasedModelName;
                    var vehModelName = veh;
                    var model = (uint)GetHashKey(vehModelName);

                    var topSpeed = Map(GetVehicleModelEstimatedMaxSpeed(model), 0f, speedValues[vehClass], 0f, 1f);
                    var acceleration = Map(GetVehicleModelAcceleration(model), 0f, accelerationValues[vehClass], 0f, 1f);
                    var maxBraking = Map(GetVehicleModelMaxBraking(model), 0f, brakingValues[vehClass], 0f, 1f);
                    var maxTraction = Map(GetVehicleModelMaxTraction(model), 0f, tractionValues[vehClass], 0f, 1f);

                    // Loop through all the menu items and check each item's title/text and see if it matches the current vehicle (display) name.
                    var duplicate = false;
                    for (var itemIndex = 0; itemIndex < vehicleClassMenu.Size; itemIndex++)
                    {
                        // If it matches...
                        if (vehicleClassMenu.GetMenuItems()[itemIndex].Text.ToString() == vehName)
                        {

                            // Check if the model was marked as duplicate before.
                            if (duplicateVehNames.Keys.Contains(vehName))
                            {
                                // If so, add 1 to the duplicate counter for this model name.
                                duplicateVehNames[vehName]++;
                            }

                            // If this is the first duplicate, then set it to 2.
                            else
                            {
                                duplicateVehNames[vehName] = 2;
                            }

                            // The model name is a duplicate, so get the modelname and add the duplicate amount for this model name to the end of the vehicle name.
                            vehName += $" ({duplicateVehNames[vehName]})";

                            // Then create and add a new button for this vehicle.

                            if (DoesModelExist(veh))
                            {
                                var vehBtn = new MenuItem(vehName)
                                {
                                    Enabled = true,
                                    Label = $"({vehModelName.ToLower()})",
                                    ItemData = new float[4] { topSpeed, acceleration, maxBraking, maxTraction }
                                };
                                vehicleClassMenu.AddMenuItem(vehBtn);
                            }
                            else
                            {
                                var vehBtn = new MenuItem(vehName, "This vehicle is not available because the model could not be found in your game files. If this is a DLC vehicle, make sure the server is streaming it.")
                                {
                                    Enabled = false,
                                    Label = $"({vehModelName.ToLower()})",
                                    ItemData = new float[4] { 0f, 0f, 0f, 0f }
                                };
                                vehicleClassMenu.AddMenuItem(vehBtn);
                                vehBtn.RightIcon = MenuItem.Icon.LOCK;
                            }

                            // Mark duplicate as true and break from the loop because we already found the duplicate.
                            duplicate = true;
                            break;
                        }
                    }

                    // If it's not a duplicate, add the model name.
                    if (!duplicate)
                    {
                        if (DoesModelExist(veh))
                        {
                            var vehBtn = new MenuItem(vehName)
                            {
                                Enabled = true,
                                Label = $"({vehModelName.ToLower()})",
                                ItemData = new float[4] { topSpeed, acceleration, maxBraking, maxTraction }
                            };
                            vehicleClassMenu.AddMenuItem(vehBtn);
                        }
                        else
                        {
                            var vehBtn = new MenuItem(vehName, "This vehicle is not available because the model could not be found in your game files. If this is a DLC vehicle, make sure the server is streaming it.")
                            {
                                Enabled = false,
                                Label = $"({vehModelName.ToLower()})",
                                ItemData = new float[4] { 0f, 0f, 0f, 0f }
                            };
                            vehicleClassMenu.AddMenuItem(vehBtn);
                            vehBtn.RightIcon = MenuItem.Icon.LOCK;
                        }
                    }
                }
                #endregion

                vehicleClassMenu.ShowVehicleStatsPanel = true;

                // Handle button presses
                vehicleClassMenu.OnItemSelect += async (sender2, item2, index2) =>
                {
                    await SpawnVehicle(VehicleData.Vehicles.VehicleClasses[className][index2], SpawnInVehicle, ReplaceVehicle);
                };

                static void HandleStatsPanel(Menu openedMenu, MenuItem currentItem)
                {
                    if (currentItem != null)
                    {
                        if (currentItem.ItemData is float[] data)
                        {
                            openedMenu.ShowVehicleStatsPanel = true;
                            openedMenu.SetVehicleStats(data[0], data[1], data[2], data[3]);
                            openedMenu.SetVehicleUpgradeStats(0f, 0f, 0f, 0f);
                        }
                        else
                        {
                            openedMenu.ShowVehicleStatsPanel = false;
                        }
                    }
                }

                vehicleClassMenu.OnMenuOpen += (m) =>
                {
                    HandleStatsPanel(m, m.GetCurrentMenuItem());
                };

                vehicleClassMenu.OnIndexChange += (m, oldItem, newItem, oldIndex, newIndex) =>
                {
                    HandleStatsPanel(m, newItem);
                };
            }
            #endregion

            #region handle events
            // Handle button presses.
            menu.OnItemSelect += async (sender, item, index) =>
            {
                if (item == spawnByName)
                {
                    // Passing "custom" as the vehicle name, will ask the user for input.
                    await SpawnVehicle("custom", SpawnInVehicle, ReplaceVehicle);
                }
            };

            // Handle checkbox changes.
            menu.OnCheckboxChange += (sender, item, index, _checked) =>
            {
                if (item == spawnInVeh)
                {
                    SpawnInVehicle = _checked;
                }
                else if (item == replacePrev)
                {
                    ReplaceVehicle = _checked;
                }
            };
            #endregion
        }

        /// <summary>
        /// Create the menu if it doesn't exist, and then returns it.
        /// </summary>
        /// <returns>The Menu</returns>
        public Menu GetMenu()
        {
            if (menu == null)
            {
                CreateMenu();
            }
            return menu;
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants