From 735513ee72ac2f0f103c30e0af179a9a2edde695 Mon Sep 17 00:00:00 2001 From: Arthur <121949966+ShinyWasabi@users.noreply.github.com> Date: Tue, 20 May 2025 21:01:47 +0300 Subject: [PATCH] Vehicle Stuff (#326) * Vehicle Stuff - Added feature "Call Mechanic". - Added safety check to prevent saving forbidden vehicles. - Added vehicle spawner with search box. - Added ped & object spawner. - Moved vehicle related things to a separate submenu. * Fix notification title * Bypass Delivery Cooldown --- src/game/features/vehicle/CallMechanic.cpp | 60 ++ .../{recovery => vehicle}/DLCVehicles.cpp | 0 .../SavePersonalVehicle.cpp} | 46 +- .../SavePersonalVehicle.hpp} | 10 +- src/game/features/vehicle/Spawn.cpp | 72 -- src/game/features/world/Spawn.cpp | 91 ++ src/game/frontend/Menu.cpp | 2 + src/game/frontend/submenus/Recovery.cpp | 16 - src/game/frontend/submenus/Self.cpp | 20 - src/game/frontend/submenus/Vehicle.cpp | 40 + src/game/frontend/submenus/Vehicle.hpp | 11 + .../submenus/Vehicle/SpawnVehicle.cpp | 144 +++ .../submenus/Vehicle/SpawnVehicle.hpp | 8 + src/game/frontend/submenus/World.cpp | 26 +- src/game/gta/data/Vehicles.hpp | 922 ++++++++++++++++++ src/main.cpp | 4 +- 16 files changed, 1333 insertions(+), 139 deletions(-) create mode 100644 src/game/features/vehicle/CallMechanic.cpp rename src/game/features/{recovery => vehicle}/DLCVehicles.cpp (100%) rename src/game/features/{recovery/GiveVehicleReward.cpp => vehicle/SavePersonalVehicle.cpp} (66%) rename src/game/features/{recovery/GiveVehicleReward.hpp => vehicle/SavePersonalVehicle.hpp} (71%) delete mode 100644 src/game/features/vehicle/Spawn.cpp create mode 100644 src/game/features/world/Spawn.cpp create mode 100644 src/game/frontend/submenus/Vehicle.cpp create mode 100644 src/game/frontend/submenus/Vehicle.hpp create mode 100644 src/game/frontend/submenus/Vehicle/SpawnVehicle.cpp create mode 100644 src/game/frontend/submenus/Vehicle/SpawnVehicle.hpp create mode 100644 src/game/gta/data/Vehicles.hpp diff --git a/src/game/features/vehicle/CallMechanic.cpp b/src/game/features/vehicle/CallMechanic.cpp new file mode 100644 index 0000000..c90c38c --- /dev/null +++ b/src/game/features/vehicle/CallMechanic.cpp @@ -0,0 +1,60 @@ +#include "core/commands/Command.hpp" +#include "core/backend/ScriptMgr.hpp" +#include "core/frontend/Notifications.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/data/StackSizes.hpp" +#include "game/gta/Natives.hpp" +#include "game/gta/Scripts.hpp" +#include "game/gta/ScriptLocal.hpp" +#include "game/gta/ScriptGlobal.hpp" +#include "types/script/Timer.hpp" + +namespace YimMenu::Features +{ + class CallMechanic : public Command + { + using Command::Command; + + virtual void OnCall() override + { + if (!*Pointers.IsSessionStarted || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("AM_CONTACT_REQUESTS"_J) > 0) + { + Notifications::Show("Mechanic", "Not safe to call the mechanic at the moment.", NotificationType::Error); + return; + } + + if (auto freemode = Scripts::FindScriptThread("freemode"_J)) + { + auto data = ScriptLocal(freemode, 8732); + *data.At(3).As() = 215; + *data.At(3).At(16).As() = Self::GetPlayer().GetId(); + *data.At(3).At(1).As() = 89; + *data.At(2).As() = "AM_CONTACT_REQUESTS"_J; + + while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED("AM_CONTACT_REQUESTS"_J)) + { + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("AM_CONTACT_REQUESTS"_J); + ScriptMgr::Yield(); + } + + auto args = data.At(3).As(); + if (auto id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS("AM_CONTACT_REQUESTS"_J, args, 21, eStackSizes::SCRIPT_XML)) + { + if (auto thread = Scripts::FindScriptThreadByID(id)) + { + *ScriptLocal(thread, 519).As() = 1; + ScriptGlobal(2685663).At(4344).At(251).At(7, 2).As()->Destroy(); + } + } + else + { + Notifications::Show("Mechanic", "Failed to call the mechanic.", NotificationType::Error); + } + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED("AM_CONTACT_REQUESTS"_J); + } + } + }; + + static CallMechanic _CallMechanic{"callmechanic", "Call Mechanic", "Allows you to request your personal vehicles."}; +} \ No newline at end of file diff --git a/src/game/features/recovery/DLCVehicles.cpp b/src/game/features/vehicle/DLCVehicles.cpp similarity index 100% rename from src/game/features/recovery/DLCVehicles.cpp rename to src/game/features/vehicle/DLCVehicles.cpp diff --git a/src/game/features/recovery/GiveVehicleReward.cpp b/src/game/features/vehicle/SavePersonalVehicle.cpp similarity index 66% rename from src/game/features/recovery/GiveVehicleReward.cpp rename to src/game/features/vehicle/SavePersonalVehicle.cpp index 46b3264..a4c5705 100644 --- a/src/game/features/recovery/GiveVehicleReward.cpp +++ b/src/game/features/vehicle/SavePersonalVehicle.cpp @@ -1,6 +1,8 @@ -#include "GiveVehicleReward.hpp" +#include "SavePersonalVehicle.hpp" +#include "core/commands/Command.hpp" #include "core/backend/ScriptMgr.hpp" #include "game/backend/Self.hpp" +#include "core/frontend/Notifications.hpp" #include "game/gta/data/StackSizes.hpp" #include "game/gta/Natives.hpp" #include "game/gta/Scripts.hpp" @@ -8,14 +10,9 @@ #include "game/gta/ScriptLocal.hpp" #include "types/script/locals/VehicleRewardData.hpp" -namespace YimMenu +namespace YimMenu::Features { - bool GiveVehicleReward::IsSafeToRunScript() - { - return Self::GetVehicle().IsValid() && *Pointers.IsSessionStarted; - } - - void GiveVehicleReward::RunScriptImpl() + void SavePersonalVehicle::RunScriptImpl() { while (g_Running) { @@ -24,7 +21,7 @@ namespace YimMenu if (!m_ShouldRunScript) continue; - if (!IsSafeToRunScript()) + if (!*Pointers.IsSessionStarted || !Self::GetVehicle().IsValid()) { if (m_StartedByUs && m_Thread) { @@ -88,4 +85,35 @@ namespace YimMenu } } } + + class _SavePersonalVehicle : public Command + { + using Command::Command; + + virtual void OnCall() override + { + if (!*Pointers.IsSessionStarted) + { + Notifications::Show("Save Personal Vehicle", "Please join GTA Online.", NotificationType::Error); + return; + } + + if (!Self::GetVehicle().IsValid()) + { + Notifications::Show("Save Personal Vehicle", "Please get in a vehicle.", NotificationType::Error); + return; + } + + static ScriptFunction isVehicleValidForPV("freemode"_J, ScriptPointer("IsVehicleValidForPV", "5D ? ? ? 2A 06 56 13 00 38 00").Add(1).Rip()); + if (!isVehicleValidForPV.Call(Self::GetVehicle().GetModel())) + { + Notifications::Show("Save Personal Vehicle", "This vehicle cannot be saved as a personal vehicle.", NotificationType::Error); + return; + } + + SavePersonalVehicle::SetShouldRunScript(true); + } + }; + + static _SavePersonalVehicle __SavePersonalVehicle{"savepersonalvehicle", "Save Personal Vehicle", "Saves the current vehicle you are in as your personal vehicle."}; } \ No newline at end of file diff --git a/src/game/features/recovery/GiveVehicleReward.hpp b/src/game/features/vehicle/SavePersonalVehicle.hpp similarity index 71% rename from src/game/features/recovery/GiveVehicleReward.hpp rename to src/game/features/vehicle/SavePersonalVehicle.hpp index 52923b5..e395361 100644 --- a/src/game/features/recovery/GiveVehicleReward.hpp +++ b/src/game/features/vehicle/SavePersonalVehicle.hpp @@ -5,13 +5,13 @@ namespace rage class scrThread; } -namespace YimMenu +namespace YimMenu::Features { - class GiveVehicleReward + class SavePersonalVehicle { - static GiveVehicleReward& GetInstance() + static SavePersonalVehicle& GetInstance() { - static GiveVehicleReward instance; + static SavePersonalVehicle instance; return instance; } @@ -22,8 +22,6 @@ namespace YimMenu rage::scrThread* m_Thread = nullptr; public: - static bool IsSafeToRunScript(); - static void RunScript() { GetInstance().RunScriptImpl(); diff --git a/src/game/features/vehicle/Spawn.cpp b/src/game/features/vehicle/Spawn.cpp deleted file mode 100644 index 550ad49..0000000 --- a/src/game/features/vehicle/Spawn.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "core/commands/StringCommand.hpp" -#include "game/backend/Self.hpp" -#include "game/gta/Natives.hpp" -#include "core/backend/ScriptMgr.hpp" -#include "core/commands/BoolCommand.hpp" -#include "game/gta/data/VehicleValues.hpp" -#include "core/frontend/Notifications.hpp" - -namespace YimMenu::Features -{ - static StringCommand _VehicleModelname{"vehmodelname", "Vehicle model name", "The model name of the vehicle you wish to spawn."}; - static BoolCommand _SpawnInVehicle{"spawninvehicle", "Spawn in vehicle", "Enter vehicle once it is spawned", false}; - static BoolCommand _SpawnWithMaximumUpgrades{"spawnupgraded", "Spawn with maximum upgrades", "Spawn vehicle with maximum upgrades", false}; - static BoolCommand _UseCustomLicensePlate{"usecustomlicenseplate", "Use custom license plate", "Use a custom license plate for the vehicle", false}; - static StringCommand _CustomLicensePlate{"customlicenseplate", "Custom license plate", "The custom license plate for the vehicle"}; - - class SpawnVehicle : public Command { - using Command::Command; - - virtual void OnCall() override - { - auto model = _VehicleModelname.GetString(); - - if (!model.length()) - { - Notifications::Show("Spawn Vehicle", "No model name provided.", NotificationType::Error); - return; - } - - Hash modelHash = Joaat(model); - - assert(modelHash != 0); - - if (STREAMING::IS_MODEL_IN_CDIMAGE(modelHash)) - { - rage::fvector3 coords = Self::GetPed().GetPosition(); - auto veh = Vehicle::Create(modelHash, coords, Self::GetPed().GetHeading()); - auto vehHandle = veh.GetHandle(); - - if (_SpawnInVehicle.GetState()) - { - PED::SET_PED_INTO_VEHICLE(Self::GetPed().GetHandle(), vehHandle, (int)SeatPositions::SEAT_DRIVER); - } - - if (_SpawnWithMaximumUpgrades.GetState()) - { - veh.Upgrade(); - } - - if (_UseCustomLicensePlate.GetState()) - { - std::string licensePlate = _CustomLicensePlate.GetString(); - - if (licensePlate.length() > 8) - { - Notifications::Show("Spawn Vehicle", "License plate must be 8 characters or less.", NotificationType::Error); - } - else if (licensePlate.length() > 0) - { - veh.SetPlateText(licensePlate); - } - } - } - else - { - Notifications::Show("Spawn Vehicle", "Invalid model name provided.", NotificationType::Error); - } - } - }; - - static SpawnVehicle _SpawnVehicle{"spawnvehicle", "Spawn Vehicle", "Spawns a vehicle at your current location"}; -} \ No newline at end of file diff --git a/src/game/features/world/Spawn.cpp b/src/game/features/world/Spawn.cpp new file mode 100644 index 0000000..c5d92ce --- /dev/null +++ b/src/game/features/world/Spawn.cpp @@ -0,0 +1,91 @@ +#include "core/commands/StringCommand.hpp" +#include "core/frontend/Notifications.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Object.hpp" +#include "game/gta/Natives.hpp" + +namespace YimMenu::Features +{ + static StringCommand _VehicleModelName{"vehmodelname", "Vehicle Model", "The model name of the vehicle you wish to spawn."}; + static StringCommand _PedModelName{"pedmodelname", "Ped Model", "The model name of the ped you wish to spawn."}; + static StringCommand _ObjectModelName{"objectmodelname", "Object Model", "The model name of the object you wish to spawn."}; + + class SpawnVehicle : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto model = _VehicleModelName.GetString(); + if (!model.length()) + { + Notifications::Show("Spawn Vehicle", "No model name provided.", NotificationType::Error); + return; + } + + auto modelHash = Joaat(model); + if (STREAMING::IS_MODEL_IN_CDIMAGE(modelHash)) + { + Vehicle::Create(modelHash, Self::GetPed().GetPosition(), Self::GetPed().GetHeading()); + } + else + { + Notifications::Show("Spawn Vehicle", "Invalid model name provided.", NotificationType::Error); + } + } + }; + + class SpawnPed : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto model = _PedModelName.GetString(); + if (!model.length()) + { + Notifications::Show("Spawn Ped", "No model name provided.", NotificationType::Error); + return; + } + + auto modelHash = Joaat(model); + if (STREAMING::IS_MODEL_IN_CDIMAGE(modelHash)) + { + Ped::Create(modelHash, Self::GetPed().GetPosition(), Self::GetPed().GetHeading()); + } + else + { + Notifications::Show("Spawn Ped", "Invalid model name provided.", NotificationType::Error); + } + } + }; + + class SpawnObject : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto model = _ObjectModelName.GetString(); + if (!model.length()) + { + Notifications::Show("Spawn Object", "No model name provided.", NotificationType::Error); + return; + } + + auto modelHash = Joaat(model); + if (STREAMING::IS_MODEL_IN_CDIMAGE(modelHash)) + { + Object::Create(modelHash, Self::GetPed().GetPosition()); + } + else + { + Notifications::Show("Spawn Object", "Invalid model name provided.", NotificationType::Error); + } + } + }; + + static SpawnVehicle _SpawnVehicle{"spawnvehicle", "Spawn Vehicle", "Spawns a vehicle at your current location."}; + static SpawnPed _SpawnPed{"spawnped", "Spawn Ped", "Spawns a ped at your current location."}; + static SpawnObject _SpawnObject{"spawnobject", "Spawn Object", "Spawns an object at your current location."}; +} \ No newline at end of file diff --git a/src/game/frontend/Menu.cpp b/src/game/frontend/Menu.cpp index f392acc..12bb7e4 100644 --- a/src/game/frontend/Menu.cpp +++ b/src/game/frontend/Menu.cpp @@ -9,6 +9,7 @@ #include "game/frontend/fonts/Fonts.hpp" #include "game/pointers/Pointers.hpp" #include "submenus/Self.hpp" +#include "submenus/Vehicle.hpp" #include "submenus/Teleport.hpp" #include "submenus/Network.hpp" #include "submenus/Players.hpp" @@ -23,6 +24,7 @@ namespace YimMenu { // Arguably the only place this file should be edited at for more menus UIManager::AddSubmenu(std::make_shared()); + UIManager::AddSubmenu(std::make_shared()); UIManager::AddSubmenu(std::make_shared()); UIManager::AddSubmenu(std::make_shared()); UIManager::AddSubmenu(std::make_shared()); diff --git a/src/game/frontend/submenus/Recovery.cpp b/src/game/frontend/submenus/Recovery.cpp index 60e76fc..d9dcdb9 100644 --- a/src/game/frontend/submenus/Recovery.cpp +++ b/src/game/frontend/submenus/Recovery.cpp @@ -1,6 +1,5 @@ #include "Recovery.hpp" #include "game/frontend/items/Items.hpp" -#include "game/features/recovery/GiveVehicleReward.hpp" #include "Recovery/StatEditor.hpp" #include "Recovery/Transactions.hpp" #include "Recovery/HeistModifier.hpp" @@ -10,29 +9,14 @@ namespace YimMenu::Submenus Recovery::Recovery() : Submenu::Submenu("Recovery") { - auto shopping = std::make_shared("Shopping"); auto missions = std::make_shared("Missions"); auto vehiclesGroup = std::make_shared("Vehicles"); auto generalGroup = std::make_shared("General"); - vehiclesGroup->AddItem(std::make_shared("dlcvehicles"_J)); - - vehiclesGroup->AddItem(std::make_unique([] { - if (ImGui::Button("Save This Vehicle as Personal Vehicle")) - { - if (GiveVehicleReward::IsSafeToRunScript()) - { - GiveVehicleReward::SetShouldRunScript(true); - } - } - })); - generalGroup->AddItem(std::make_shared("playallmissionssolo"_J)); generalGroup->AddItem(std::make_shared("forcelaunchheist"_J)); - shopping->AddItem(vehiclesGroup); missions->AddItem(generalGroup); - AddCategory(std::move(shopping)); AddCategory(std::move(missions)); AddCategory(BuildStatEditorMenu()); AddCategory(BuildTransactionsMenu()); diff --git a/src/game/frontend/submenus/Self.cpp b/src/game/frontend/submenus/Self.cpp index 062a691..122a7b7 100644 --- a/src/game/frontend/submenus/Self.cpp +++ b/src/game/frontend/submenus/Self.cpp @@ -78,26 +78,6 @@ namespace YimMenu::Submenus weapons->AddItem(weaponsAimbotGroup); AddCategory(std::move(weapons)); - auto vehicle = std::make_shared("Vehicle"); - auto vehicleGlobalsGroup = std::make_shared("Globals"); - auto vehicleMiscGroup = std::make_shared("Misc"); - - vehicleGlobalsGroup->AddItem(std::make_shared("vehiclegodmode"_J, "Godmode")); - vehicleGlobalsGroup->AddItem(std::make_shared("keepfixed"_J, "Keep Fixed")); - vehicleGlobalsGroup->AddItem(std::make_shared("hornboost"_J)); - vehicleGlobalsGroup->AddItem(std::make_shared("modifyboostbehavior"_J)); - vehicleGlobalsGroup->AddItem(std::make_shared("modifyboostbehavior"_J, std::make_shared("boostbehavior"_J))); - vehicleGlobalsGroup->AddItem(std::make_shared("repairvehicle"_J)); - vehicleGlobalsGroup->AddItem(std::make_shared("enterlastvehicle"_J)); - - vehicleMiscGroup->AddItem(std::make_shared("speedometer"_J)); - vehicleMiscGroup->AddItem(std::make_shared("seatbelt"_J)); - vehicleMiscGroup->AddItem(std::make_shared("allowhatsinvehicles"_J)); - - vehicle->AddItem(vehicleGlobalsGroup); - vehicle->AddItem(vehicleMiscGroup); - AddCategory(std::move(vehicle)); - auto outfitEditorCategory = YimMenu::CreateOutfitsMenu(); AddCategory(std::move(outfitEditorCategory)); } diff --git a/src/game/frontend/submenus/Vehicle.cpp b/src/game/frontend/submenus/Vehicle.cpp new file mode 100644 index 0000000..8885d95 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle.cpp @@ -0,0 +1,40 @@ +#include "Vehicle.hpp" +#include "game/frontend/items/Items.hpp" +#include "game/frontend/submenus/Vehicle/SpawnVehicle.hpp" + +namespace YimMenu::Submenus +{ + Vehicle::Vehicle() : + Submenu::Submenu("Vehicle") + { + auto main = std::make_shared("Main"); + + auto globals = std::make_shared("Globals"); + auto tools = std::make_shared("Tools", 1); + auto misc = std::make_shared("Misc"); + + globals->AddItem(std::make_shared("vehiclegodmode"_J, "Godmode")); + globals->AddItem(std::make_shared("keepfixed"_J, "Keep Fixed")); + globals->AddItem(std::make_shared("hornboost"_J)); + globals->AddItem(std::make_shared("modifyboostbehavior"_J)); + globals->AddItem(std::make_shared("modifyboostbehavior"_J, std::make_shared("boostbehavior"_J))); + + tools->AddItem(std::make_shared("repairvehicle"_J)); + tools->AddItem(std::make_shared("enterlastvehicle"_J)); + tools->AddItem(std::make_shared("callmechanic"_J)); + tools->AddItem(std::make_shared("savepersonalvehicle"_J)); + + misc->AddItem(std::make_shared("speedometer"_J)); + misc->AddItem(std::make_shared("seatbelt"_J)); + misc->AddItem(std::make_shared("allowhatsinvehicles"_J)); + misc->AddItem(std::make_shared("lsccustomsbypass"_J)); + misc->AddItem(std::make_shared("dlcvehicles"_J)); + + main->AddItem(globals); + main->AddItem(tools); + main->AddItem(misc); + + AddCategory(std::move(main)); + AddCategory(BuildSpawnVehicleMenu()); + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle.hpp b/src/game/frontend/submenus/Vehicle.hpp new file mode 100644 index 0000000..425cf32 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "core/frontend/manager/UIManager.hpp" + +namespace YimMenu::Submenus +{ + class Vehicle : public Submenu + { + public: + Vehicle(); + }; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle/SpawnVehicle.cpp b/src/game/frontend/submenus/Vehicle/SpawnVehicle.cpp new file mode 100644 index 0000000..a3d7004 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/SpawnVehicle.cpp @@ -0,0 +1,144 @@ +#include "SpawnVehicle.hpp" +#include "core/backend/ScriptMgr.hpp" +#include "core/backend/FiberPool.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/data/Vehicles.hpp" +#include "game/gta/Vehicle.hpp" +#include "game/gta/Natives.hpp" + +namespace YimMenu::Submenus +{ + static Vector3 GetVehicleSpawnLoc(joaat_t hash, bool spawnInside) + { + float y_offset = 0; + + if (Self::GetVehicle().IsValid()) + { + Vector3 min, max, result; + MISC::GET_MODEL_DIMENSIONS(hash, &min, &max); + result = max - min; + y_offset = result.y; + } + else if (!spawnInside) + { + y_offset = 5.f; + } + + return ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(Self::GetPed().GetHandle(), 0.f, y_offset, 0.f); + } + + std::shared_ptr BuildSpawnVehicleMenu() + { + auto menu = std::make_shared("Spawn Vehicle"); + + static std::vector vehicleNames{}; + static std::vector vehicleClasses{}; + static int selectedClass{-1}; + static bool spawnInside{}; + static bool spawnMaxed{}; + + menu->AddItem(std::make_unique([] { + static bool init = [] { + FiberPool::Push([] { + std::unordered_map nameCount; + + for (auto& veh : g_VehicleHashes) + { + std::string gxt = VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(veh); + std::string display = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(gxt.c_str()); + + int& count = nameCount[display == "NULL" ? gxt : display]; + std::string finalName = display == "NULL" ? gxt : display; + if (count > 0) + { + finalName += " " + std::to_string(count + 1); + } + ++count; + + std::string maker = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(VEHICLE::GET_MAKE_NAME_FROM_VEHICLE_MODEL(veh)); + if (maker != "NULL") + { + finalName = maker + " " + finalName; + } + + vehicleNames.push_back(finalName); + + int id = VEHICLE::GET_VEHICLE_CLASS_FROM_NAME(veh); + vehicleClasses.push_back(id); + } + }); + + return true; + }(); + + if (vehicleNames.empty()) + return ImGui::TextDisabled("Loading..."); + + static char search[64]; + ImGui::SetNextItemWidth(300.f); + ImGui::InputTextWithHint("Name", "Search", search, sizeof(search)); + + ImGui::SetNextItemWidth(300.f); + if (ImGui::BeginCombo("Class", selectedClass == -1 ? "All" : g_VehicleClassNames[selectedClass])) + { + if (ImGui::Selectable("All", selectedClass == -1)) + { + selectedClass = -1; + } + + for (int i = 0; i < g_VehicleClassNames.size(); i++) + { + if (ImGui::Selectable(g_VehicleClassNames[i], selectedClass == i)) + { + selectedClass = i; + } + } + + ImGui::EndCombo(); + } + + const int visible = std::min(10, static_cast(vehicleNames.size())); + const float height = visible * ImGui::GetTextLineHeightWithSpacing(); + if (ImGui::BeginListBox("##vehicles", {300.f, height})) + { + std::string lower = search; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + for (int veh = 0; veh < vehicleNames.size(); veh++) + { + auto hash = g_VehicleHashes[veh]; + auto name = vehicleNames[veh]; + auto lowerName = name; + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); + + bool matchesSearch = lowerName.find(lower) != std::string::npos; + bool matchesClass = selectedClass == -1 || vehicleClasses[veh] == selectedClass; + if (matchesSearch && matchesClass) + { + ImGui::PushID(hash); + if (ImGui::Selectable(name.c_str())) + { + FiberPool::Push([hash] { + auto handle = Vehicle::Create(hash, GetVehicleSpawnLoc(hash, spawnInside), Self::GetPed().GetHeading()); + + if (spawnInside) + Self::GetPed().SetInVehicle(handle); + + if (spawnMaxed) + handle.Upgrade(); + }); + } + ImGui::PopID(); + } + } + + ImGui::EndListBox(); + } + + ImGui::Checkbox("Spawn Inside", &spawnInside); + ImGui::SameLine(); + ImGui::Checkbox("Spawn Maxed", &spawnMaxed); + })); + + return menu; + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle/SpawnVehicle.hpp b/src/game/frontend/submenus/Vehicle/SpawnVehicle.hpp new file mode 100644 index 0000000..c49d150 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/SpawnVehicle.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr BuildSpawnVehicleMenu(); +} \ No newline at end of file diff --git a/src/game/frontend/submenus/World.cpp b/src/game/frontend/submenus/World.cpp index fd8d64f..08fdad5 100644 --- a/src/game/frontend/submenus/World.cpp +++ b/src/game/frontend/submenus/World.cpp @@ -38,29 +38,27 @@ namespace YimMenu::Submenus main->AddItem(std::move(weatherOpts)); main->AddItem(std::move(otherOpts)); - auto spawnGroup = std::make_shared("Vehicle"); - auto modsGroup = std::make_shared("Modifications"); + auto spawnVehicle = std::make_shared("Vehicle"); + spawnVehicle->AddItem(std::make_shared("vehmodelname"_J)); + spawnVehicle->AddItem(std::make_shared("spawnvehicle"_J)); - spawnGroup->AddItem(std::make_shared("vehmodelname"_J)); - spawnGroup->AddItem(std::make_shared("spawninvehicle"_J)); - spawnGroup->AddItem(std::make_shared("spawnupgraded"_J)); - spawnGroup->AddItem(std::make_shared("usecustomlicenseplate"_J)); - spawnGroup->AddItem(std::make_shared("usecustomlicenseplate"_J, std::make_shared("customlicenseplate"_J))); - spawnGroup->AddItem(std::make_shared("spawnvehicle"_J)); + auto spawnPed = std::make_shared("Ped"); + spawnPed->AddItem(std::make_shared("pedmodelname"_J)); + spawnPed->AddItem(std::make_shared("spawnped"_J)); - modsGroup->AddItem(std::make_shared("lsccustomsbypass"_J)); + auto spawnObject = std::make_shared("Object"); + spawnObject->AddItem(std::make_shared("objectmodelname"_J)); + spawnObject->AddItem(std::make_shared("spawnobject"_J)); - spawnersGroup->AddItem(spawnGroup); - spawnersGroup->AddItem(modsGroup); + spawnersGroup->AddItem(spawnVehicle); + spawnersGroup->AddItem(spawnPed); + spawnersGroup->AddItem(spawnObject); iplsGroup->AddItem(std::make_shared("iplselector"_J)); iplsGroup->AddItem(std::make_shared("loadipl"_J)); iplsGroup->AddItem(std::make_shared("unloadipl"_J)); iplsGroup->AddItem(std::make_shared("ipltp"_J)); - - - AddCategory(std::move(main)); AddCategory(std::move(spawnersGroup)); AddCategory(std::move(iplsGroup)); diff --git a/src/game/gta/data/Vehicles.hpp b/src/game/gta/data/Vehicles.hpp new file mode 100644 index 0000000..b3fecdf --- /dev/null +++ b/src/game/gta/data/Vehicles.hpp @@ -0,0 +1,922 @@ +#pragma once +#include "core/util/Joaat.hpp" +#include + +namespace YimMenu +{ + static constexpr auto g_VehicleClassNames = std::to_array({ + "Compact", + "Sedan", + "SUV", + "Coupe", + "Muscle", + "Sport Classic", + "Sport", + "Super", + "Motorcycle", + "Off-road", + "Industrial", + "Utility", + "Van", + "Cycle", + "Boat", + "Helicopter", + "Plane", + "Service", + "Emergency", + "Military", + "Commercial", + "Rail", + "Open Wheel" + }); + + static constexpr auto g_VehicleHashes = std::to_array({ + "adder"_J, + "airbus"_J, + "airtug"_J, + "akula"_J, + "akuma"_J, + "aleutian"_J, + "alkonost"_J, + "alpha"_J, + "alphaz1"_J, + "ambulance"_J, + "annihilator"_J, + "annihilator2"_J, + "apc"_J, + "arbitergt"_J, + "ardent"_J, + "armytanker"_J, + "armytrailer"_J, + "armytrailer2"_J, + "asbo"_J, + "asea"_J, + "asea2"_J, + "asterope"_J, + "asterope2"_J, + "astron"_J, + "astron2"_J, + "autarch"_J, + "avarus"_J, + "avenger"_J, + "avenger2"_J, + "avenger3"_J, + "avenger4"_J, + "avisa"_J, + "bagger"_J, + "baletrailer"_J, + "baller"_J, + "baller2"_J, + "baller3"_J, + "baller4"_J, + "baller5"_J, + "baller6"_J, + "baller7"_J, + "baller8"_J, + "banshee"_J, + "banshee2"_J, + "banshee3"_J, + "barracks"_J, + "barracks2"_J, + "barracks3"_J, + "barrage"_J, + "bati"_J, + "bati2"_J, + "benson"_J, + "benson2"_J, + "besra"_J, + "bestiagts"_J, + "bf400"_J, + "bfinjection"_J, + "biff"_J, + "bifta"_J, + "bison"_J, + "bison2"_J, + "bison3"_J, + "bjxl"_J, + "blade"_J, + "blazer"_J, + "blazer2"_J, + "blazer3"_J, + "blazer4"_J, + "blazer5"_J, + "blimp"_J, + "blimp2"_J, + "blimp3"_J, + "blista"_J, + "blista2"_J, + "blista3"_J, + "bmx"_J, + "boattrailer"_J, + "boattrailer2"_J, + "boattrailer3"_J, + "bobcatxl"_J, + "bodhi2"_J, + "bombushka"_J, + "boor"_J, + "boxville"_J, + "boxville2"_J, + "boxville3"_J, + "boxville4"_J, + "boxville5"_J, + "boxville6"_J, + "brawler"_J, + "brickade"_J, + "brickade2"_J, + "brigham"_J, + "brioso"_J, + "brioso2"_J, + "brioso3"_J, + "broadway"_J, + "bruiser"_J, + "bruiser2"_J, + "bruiser3"_J, + "brutus"_J, + "brutus2"_J, + "brutus3"_J, + "btype"_J, + "btype2"_J, + "btype3"_J, + "buccaneer"_J, + "buccaneer2"_J, + "buffalo"_J, + "buffalo2"_J, + "buffalo3"_J, + "buffalo4"_J, + "buffalo5"_J, + "bulldozer"_J, + "bullet"_J, + "burrito"_J, + "burrito2"_J, + "burrito3"_J, + "burrito4"_J, + "burrito5"_J, + "bus"_J, + "buzzard"_J, + "buzzard2"_J, + "cablecar"_J, + "caddy"_J, + "caddy2"_J, + "caddy3"_J, + "calico"_J, + "camper"_J, + "caracara"_J, + "caracara2"_J, + "carbonizzare"_J, + "carbonrs"_J, + "cargobob"_J, + "cargobob2"_J, + "cargobob3"_J, + "cargobob4"_J, + "cargobob5"_J, + "cargoplane"_J, + "cargoplane2"_J, + "casco"_J, + "castigator"_J, + "cavalcade"_J, + "cavalcade2"_J, + "cavalcade3"_J, + "cerberus"_J, + "cerberus2"_J, + "cerberus3"_J, + "champion"_J, + "chavosv6"_J, + "cheburek"_J, + "cheetah"_J, + "cheetah2"_J, + "chernobog"_J, + "chimera"_J, + "chino"_J, + "chino2"_J, + "cinquemila"_J, + "cliffhanger"_J, + "clique"_J, + "clique2"_J, + "club"_J, + "coach"_J, + "cog55"_J, + "cog552"_J, + "cogcabrio"_J, + "cognoscenti"_J, + "cognoscenti2"_J, + "comet2"_J, + "comet3"_J, + "comet4"_J, + "comet5"_J, + "comet6"_J, + "comet7"_J, + "conada"_J, + "conada2"_J, + "contender"_J, + "coquette"_J, + "coquette2"_J, + "coquette3"_J, + "coquette4"_J, + "coquette5"_J, + "coquette6"_J, + "corsita"_J, + "coureur"_J, + "cruiser"_J, + "crusader"_J, + "cuban800"_J, + "cutter"_J, + "cyclone"_J, + "cyclone2"_J, + "cypher"_J, + "daemon"_J, + "daemon2"_J, + "deathbike"_J, + "deathbike2"_J, + "deathbike3"_J, + "defiler"_J, + "deity"_J, + "deluxo"_J, + "deveste"_J, + "deviant"_J, + "diablous"_J, + "diablous2"_J, + "dilettante"_J, + "dilettante2"_J, + "dinghy"_J, + "dinghy2"_J, + "dinghy3"_J, + "dinghy4"_J, + "dinghy5"_J, + "dloader"_J, + "docktrailer"_J, + "docktug"_J, + "dodo"_J, + "dominator"_J, + "dominator10"_J, + "dominator2"_J, + "dominator3"_J, + "dominator4"_J, + "dominator5"_J, + "dominator6"_J, + "dominator7"_J, + "dominator8"_J, + "dominator9"_J, + "dorado"_J, + "double"_J, + "drafter"_J, + "draugur"_J, + "driftcheburek"_J, + "driftcypher"_J, + "drifteuros"_J, + "driftfr36"_J, + "driftfuto"_J, + "driftfuto2"_J, + "driftjester"_J, + "driftjester3"_J, + "driftnebula"_J, + "driftremus"_J, + "driftsentinel"_J, + "drifttampa"_J, + "driftvorschlag"_J, + "driftyosemite"_J, + "driftzr350"_J, + "dubsta"_J, + "dubsta2"_J, + "dubsta3"_J, + "dukes"_J, + "dukes2"_J, + "dukes3"_J, + "dump"_J, + "dune"_J, + "dune2"_J, + "dune3"_J, + "dune4"_J, + "dune5"_J, + "duster"_J, + "duster2"_J, + "dynasty"_J, + "elegy"_J, + "elegy2"_J, + "ellie"_J, + "emerus"_J, + "emperor"_J, + "emperor2"_J, + "emperor3"_J, + "enduro"_J, + "entity2"_J, + "entity3"_J, + "entityxf"_J, + "envisage"_J, + "esskey"_J, + "eudora"_J, + "euros"_J, + "eurosx32"_J, + "everon"_J, + "everon2"_J, + "exemplar"_J, + "f620"_J, + "faction"_J, + "faction2"_J, + "faction3"_J, + "fagaloa"_J, + "faggio"_J, + "faggio2"_J, + "faggio3"_J, + "fbi"_J, + "fbi2"_J, + "fcr"_J, + "fcr2"_J, + "felon"_J, + "felon2"_J, + "feltzer2"_J, + "feltzer3"_J, + "firebolt"_J, + "firetruk"_J, + "fixter"_J, + "flashgt"_J, + "flatbed"_J, + "fmj"_J, + "forklift"_J, + "formula"_J, + "formula2"_J, + "fq2"_J, + "fr36"_J, + "freecrawler"_J, + "freight"_J, + "freight2"_J, + "freightcar"_J, + "freightcar2"_J, + "freightcar3"_J, + "freightcont1"_J, + "freightcont2"_J, + "freightgrain"_J, + "freighttrailer"_J, + "frogger"_J, + "frogger2"_J, + "fugitive"_J, + "furia"_J, + "furoregt"_J, + "fusilade"_J, + "futo"_J, + "futo2"_J, + "gargoyle"_J, + "gauntlet"_J, + "gauntlet2"_J, + "gauntlet3"_J, + "gauntlet4"_J, + "gauntlet5"_J, + "gauntlet6"_J, + "gb200"_J, + "gburrito"_J, + "gburrito2"_J, + "glendale"_J, + "glendale2"_J, + "gp1"_J, + "graintrailer"_J, + "granger"_J, + "granger2"_J, + "greenwood"_J, + "gresley"_J, + "growler"_J, + "gt500"_J, + "guardian"_J, + "habanero"_J, + "hakuchou"_J, + "hakuchou2"_J, + "halftrack"_J, + "handler"_J, + "hauler"_J, + "hauler2"_J, + "havok"_J, + "hellion"_J, + "hermes"_J, + "hexer"_J, + "hotknife"_J, + "hotring"_J, + "howard"_J, + "hunter"_J, + "huntley"_J, + "hustler"_J, + "hydra"_J, + "ignus"_J, + "ignus2"_J, + "imorgon"_J, + "impaler"_J, + "impaler2"_J, + "impaler3"_J, + "impaler4"_J, + "impaler5"_J, + "impaler6"_J, + "imperator"_J, + "imperator2"_J, + "imperator3"_J, + "inductor"_J, + "inductor2"_J, + "infernus"_J, + "infernus2"_J, + "ingot"_J, + "innovation"_J, + "insurgent"_J, + "insurgent2"_J, + "insurgent3"_J, + "intruder"_J, + "issi2"_J, + "issi3"_J, + "issi4"_J, + "issi5"_J, + "issi6"_J, + "issi7"_J, + "issi8"_J, + "italigtb"_J, + "italigtb2"_J, + "italigto"_J, + "italirsx"_J, + "iwagen"_J, + "jackal"_J, + "jb700"_J, + "jb7002"_J, + "jester"_J, + "jester2"_J, + "jester3"_J, + "jester4"_J, + "jester5"_J, + "jet"_J, + "jetmax"_J, + "journey"_J, + "journey2"_J, + "jubilee"_J, + "jugular"_J, + "kalahari"_J, + "kamacho"_J, + "kanjo"_J, + "kanjosj"_J, + "khamelion"_J, + "khanjali"_J, + "komoda"_J, + "kosatka"_J, + "krieger"_J, + "kuruma"_J, + "kuruma2"_J, + "l35"_J, + "landstalker"_J, + "landstalker2"_J, + "lazer"_J, + "le7b"_J, + "lectro"_J, + "lguard"_J, + "limo2"_J, + "lm87"_J, + "locust"_J, + "longfin"_J, + "lurcher"_J, + "luxor"_J, + "luxor2"_J, + "lynx"_J, + "mamba"_J, + "mammatus"_J, + "manana"_J, + "manana2"_J, + "manchez"_J, + "manchez2"_J, + "manchez3"_J, + "marquis"_J, + "marshall"_J, + "massacro"_J, + "massacro2"_J, + "maverick"_J, + "menacer"_J, + "mesa"_J, + "mesa2"_J, + "mesa3"_J, + "metrotrain"_J, + "michelli"_J, + "microlight"_J, + "miljet"_J, + "minitank"_J, + "minivan"_J, + "minivan2"_J, + "mixer"_J, + "mixer2"_J, + "mogul"_J, + "molotok"_J, + "monroe"_J, + "monster"_J, + "monster3"_J, + "monster4"_J, + "monster5"_J, + "monstrociti"_J, + "moonbeam"_J, + "moonbeam2"_J, + "mower"_J, + "mule"_J, + "mule2"_J, + "mule3"_J, + "mule4"_J, + "mule5"_J, + "nebula"_J, + "nemesis"_J, + "neo"_J, + "neon"_J, + "nero"_J, + "nero2"_J, + "nightblade"_J, + "nightshade"_J, + "nightshark"_J, + "nimbus"_J, + "ninef"_J, + "ninef2"_J, + "niobe"_J, + "nokota"_J, + "novak"_J, + "omnis"_J, + "omnisegt"_J, + "openwheel1"_J, + "openwheel2"_J, + "oppressor"_J, + "oppressor2"_J, + "oracle"_J, + "oracle2"_J, + "osiris"_J, + "outlaw"_J, + "packer"_J, + "panthere"_J, + "panto"_J, + "paradise"_J, + "paragon"_J, + "paragon2"_J, + "paragon3"_J, + "pariah"_J, + "patriot"_J, + "patriot2"_J, + "patriot3"_J, + "patrolboat"_J, + "pbus"_J, + "pbus2"_J, + "pcj"_J, + "penetrator"_J, + "penumbra"_J, + "penumbra2"_J, + "peyote"_J, + "peyote2"_J, + "peyote3"_J, + "pfister811"_J, + "phantom"_J, + "phantom2"_J, + "phantom3"_J, + "phantom4"_J, + "phoenix"_J, + "picador"_J, + "pigalle"_J, + "pipistrello"_J, + "pizzaboy"_J, + "polcaracara"_J, + "polcoquette4"_J, + "poldominator10"_J, + "poldorado"_J, + "polfaction2"_J, + "polgauntlet"_J, + "polgreenwood"_J, + "police"_J, + "police2"_J, + "police3"_J, + "police4"_J, + "police5"_J, + "policeb"_J, + "policeold1"_J, + "policeold2"_J, + "policet"_J, + "policet3"_J, + "polimpaler5"_J, + "polimpaler6"_J, + "polmav"_J, + "polterminus"_J, + "pony"_J, + "pony2"_J, + "postlude"_J, + "pounder"_J, + "pounder2"_J, + "powersurge"_J, + "prairie"_J, + "pranger"_J, + "predator"_J, + "premier"_J, + "previon"_J, + "primo"_J, + "primo2"_J, + "proptrailer"_J, + "prototipo"_J, + "pyro"_J, + "r300"_J, + "radi"_J, + "raiden"_J, + "raiju"_J, + "raketrailer"_J, + "rallytruck"_J, + "rancherxl"_J, + "rancherxl2"_J, + "rapidgt"_J, + "rapidgt2"_J, + "rapidgt3"_J, + "raptor"_J, + "ratbike"_J, + "ratel"_J, + "ratloader"_J, + "ratloader2"_J, + "rcbandito"_J, + "reaper"_J, + "rebel"_J, + "rebel2"_J, + "rebla"_J, + "reever"_J, + "regina"_J, + "remus"_J, + "rentalbus"_J, + "retinue"_J, + "retinue2"_J, + "revolter"_J, + "rhapsody"_J, + "rhinehart"_J, + "rhino"_J, + "riata"_J, + "riot"_J, + "riot2"_J, + "ripley"_J, + "rocoto"_J, + "rogue"_J, + "romero"_J, + "rrocket"_J, + "rt3000"_J, + "rubble"_J, + "ruffian"_J, + "ruiner"_J, + "ruiner2"_J, + "ruiner3"_J, + "ruiner4"_J, + "rumpo"_J, + "rumpo2"_J, + "rumpo3"_J, + "ruston"_J, + "s80"_J, + "s95"_J, + "sabregt"_J, + "sabregt2"_J, + "sadler"_J, + "sadler2"_J, + "sanchez"_J, + "sanchez2"_J, + "sanctus"_J, + "sandking"_J, + "sandking2"_J, + "savage"_J, + "savestra"_J, + "sc1"_J, + "scarab"_J, + "scarab2"_J, + "scarab3"_J, + "schafter2"_J, + "schafter3"_J, + "schafter4"_J, + "schafter5"_J, + "schafter6"_J, + "schlagen"_J, + "schwarzer"_J, + "scorcher"_J, + "scramjet"_J, + "scrap"_J, + "seabreeze"_J, + "seashark"_J, + "seashark2"_J, + "seashark3"_J, + "seasparrow"_J, + "seasparrow2"_J, + "seasparrow3"_J, + "seminole"_J, + "seminole2"_J, + "sentinel"_J, + "sentinel2"_J, + "sentinel3"_J, + "sentinel4"_J, + "serrano"_J, + "seven70"_J, + "shamal"_J, + "sheava"_J, + "sheriff"_J, + "sheriff2"_J, + "shinobi"_J, + "shotaro"_J, + "skylift"_J, + "slamtruck"_J, + "slamvan"_J, + "slamvan2"_J, + "slamvan3"_J, + "slamvan4"_J, + "slamvan5"_J, + "slamvan6"_J, + "sm722"_J, + "sovereign"_J, + "specter"_J, + "specter2"_J, + "speeder"_J, + "speeder2"_J, + "speedo"_J, + "speedo2"_J, + "speedo4"_J, + "speedo5"_J, + "squaddie"_J, + "squalo"_J, + "stafford"_J, + "stalion"_J, + "stalion2"_J, + "stanier"_J, + "starling"_J, + "stinger"_J, + "stingergt"_J, + "stingertt"_J, + "stockade"_J, + "stockade3"_J, + "stratum"_J, + "streamer216"_J, + "streiter"_J, + "stretch"_J, + "strikeforce"_J, + "stromberg"_J, + "stryder"_J, + "stunt"_J, + "submersible"_J, + "submersible2"_J, + "sugoi"_J, + "sultan"_J, + "sultan2"_J, + "sultan3"_J, + "sultanrs"_J, + "suntrap"_J, + "superd"_J, + "supervolito"_J, + "supervolito2"_J, + "surano"_J, + "surfer"_J, + "surfer2"_J, + "surfer3"_J, + "surge"_J, + "swift"_J, + "swift2"_J, + "swinger"_J, + "t20"_J, + "taco"_J, + "tahoma"_J, + "tailgater"_J, + "tailgater2"_J, + "taipan"_J, + "tampa"_J, + "tampa2"_J, + "tampa3"_J, + "tanker"_J, + "tanker2"_J, + "tankercar"_J, + "taxi"_J, + "technical"_J, + "technical2"_J, + "technical3"_J, + "tempesta"_J, + "tenf"_J, + "tenf2"_J, + "terbyte"_J, + "terminus"_J, + "tezeract"_J, + "thrax"_J, + "thrust"_J, + "thruster"_J, + "tigon"_J, + "tiptruck"_J, + "tiptruck2"_J, + "titan"_J, + "titan2"_J, + "toreador"_J, + "torero"_J, + "torero2"_J, + "tornado"_J, + "tornado2"_J, + "tornado3"_J, + "tornado4"_J, + "tornado5"_J, + "tornado6"_J, + "toro"_J, + "toro2"_J, + "toros"_J, + "tourbus"_J, + "towtruck"_J, + "towtruck2"_J, + "towtruck3"_J, + "towtruck4"_J, + "tr2"_J, + "tr3"_J, + "tr4"_J, + "tractor"_J, + "tractor2"_J, + "tractor3"_J, + "trailerlarge"_J, + "trailerlogs"_J, + "trailers"_J, + "trailers2"_J, + "trailers3"_J, + "trailers4"_J, + "trailers5"_J, + "trailersmall"_J, + "trailersmall2"_J, + "trash"_J, + "trash2"_J, + "trflat"_J, + "tribike"_J, + "tribike2"_J, + "tribike3"_J, + "trophytruck"_J, + "trophytruck2"_J, + "tropic"_J, + "tropic2"_J, + "tropos"_J, + "tug"_J, + "tula"_J, + "tulip"_J, + "tulip2"_J, + "turismo2"_J, + "turismo3"_J, + "turismor"_J, + "tvtrailer"_J, + "tvtrailer2"_J, + "tyrant"_J, + "tyrus"_J, + "uranus"_J, + "utillitruck"_J, + "utillitruck2"_J, + "utillitruck3"_J, + "vacca"_J, + "vader"_J, + "vagner"_J, + "vagrant"_J, + "valkyrie"_J, + "valkyrie2"_J, + "vamos"_J, + "vectre"_J, + "velum"_J, + "velum2"_J, + "verlierer2"_J, + "verus"_J, + "vestra"_J, + "vetir"_J, + "veto"_J, + "veto2"_J, + "vigero"_J, + "vigero2"_J, + "vigero3"_J, + "vigilante"_J, + "vindicator"_J, + "virgo"_J, + "virgo2"_J, + "virgo3"_J, + "virtue"_J, + "viseris"_J, + "visione"_J, + "vivanite"_J, + "volatol"_J, + "volatus"_J, + "voltic"_J, + "voltic2"_J, + "voodoo"_J, + "voodoo2"_J, + "vorschlaghammer"_J, + "vortex"_J, + "vstr"_J, + "warrener"_J, + "warrener2"_J, + "washington"_J, + "wastelander"_J, + "weevil"_J, + "weevil2"_J, + "windsor"_J, + "windsor2"_J, + "winky"_J, + "wolfsbane"_J, + "xa21"_J, + "xls"_J, + "xls2"_J, + "yosemite"_J, + "yosemite1500"_J, + "yosemite2"_J, + "yosemite3"_J, + "youga"_J, + "youga2"_J, + "youga3"_J, + "youga4"_J, + "youga5"_J, + "z190"_J, + "zeno"_J, + "zentorno"_J, + "zhaba"_J, + "zion"_J, + "zion2"_J, + "zion3"_J, + "zombiea"_J, + "zombieb"_J, + "zorrusso"_J, + "zr350"_J, + "zr380"_J, + "zr3802"_J, + "zr3803"_J, + "ztype"_J + }); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4bb402e..e5ed38c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,7 @@ #include "game/backend/ScriptPointers.hpp" #include "game/frontend/GUI.hpp" #include "game/pointers/Pointers.hpp" -#include "game/features/recovery/GiveVehicleReward.hpp" +#include "game/features/vehicle/SavePersonalVehicle.hpp" namespace YimMenu { @@ -63,7 +63,7 @@ namespace YimMenu FiberPool::Init(16); ScriptMgr::AddScript(std::make_unique