From 76bed308ae418fae5d3747670165c48db8f26548 Mon Sep 17 00:00:00 2001 From: lonelybud <139460769+lonelybud@users.noreply.github.com> Date: Sat, 7 Jun 2025 19:16:11 +0530 Subject: [PATCH] add Vehicle Editor & persist car feature (#374) * add VehicleEditor - add VehicleEditorCategory in Vehicle Submenus - add GetOwnedMods, GetVehicleFullname in Vehicle class - add VehicleColorsChameleon in VehicleValues - add VehicleHelper core/util - add lscTypes in gta/data * add persist car * fix GetProjectFolderImpl this will create saved_json_vehicles when does nt exist --- src/core/filemgr/FileMgr.cpp | 2 +- src/core/filemgr/Folder.cpp | 10 + src/core/filemgr/Folder.hpp | 12 +- src/core/util/VehicleHelper.cpp | 259 +++++ src/core/util/VehicleHelper.hpp | 14 + src/core/util/strings.hpp | 43 + .../PersistCarService/PersistCarService.cpp | 282 ++++++ .../PersistCarService/PersistCarService.hpp | 43 + src/game/frontend/submenus/Vehicle.cpp | 4 + .../submenus/Vehicle/PersistCarCategory.cpp | 149 +++ .../submenus/Vehicle/PersistCarCategory.hpp | 7 + .../Vehicle/VehicleEditorCategory.cpp | 882 ++++++++++++++++++ .../Vehicle/VehicleEditorCategory.hpp | 7 + src/game/gta/Vehicle.cpp | 88 ++ src/game/gta/Vehicle.hpp | 3 + src/game/gta/data/VehicleValues.hpp | 66 ++ src/game/gta/data/lscTypes.hpp | 344 +++++++ 17 files changed, 2209 insertions(+), 6 deletions(-) create mode 100644 src/core/util/VehicleHelper.cpp create mode 100644 src/core/util/VehicleHelper.hpp create mode 100644 src/core/util/strings.hpp create mode 100644 src/game/features/vehicle/PersistCarService/PersistCarService.cpp create mode 100644 src/game/features/vehicle/PersistCarService/PersistCarService.hpp create mode 100644 src/game/frontend/submenus/Vehicle/PersistCarCategory.cpp create mode 100644 src/game/frontend/submenus/Vehicle/PersistCarCategory.hpp create mode 100644 src/game/frontend/submenus/Vehicle/VehicleEditorCategory.cpp create mode 100644 src/game/frontend/submenus/Vehicle/VehicleEditorCategory.hpp create mode 100644 src/game/gta/data/lscTypes.hpp diff --git a/src/core/filemgr/FileMgr.cpp b/src/core/filemgr/FileMgr.cpp index 6752a29..d195f9e 100644 --- a/src/core/filemgr/FileMgr.cpp +++ b/src/core/filemgr/FileMgr.cpp @@ -52,6 +52,6 @@ namespace YimMenu if (folder.is_absolute()) throw std::invalid_argument("FileMgr::GetProjectFolder expects a relative path."); - return { m_RootFolder / folder }; + return CreateFolderIfNotExists(m_RootFolder / folder); } } \ No newline at end of file diff --git a/src/core/filemgr/Folder.cpp b/src/core/filemgr/Folder.cpp index 655b2e5..dddf74b 100644 --- a/src/core/filemgr/Folder.cpp +++ b/src/core/filemgr/Folder.cpp @@ -8,4 +8,14 @@ namespace YimMenu { } + + File Folder::GetFile(std::filesystem::path file_path) const + { + if (file_path.is_absolute()) + throw std::invalid_argument("folder#get_file requires a relative path."); + if (file_path.string().contains("..")) + throw std::invalid_argument("Relative path traversal is not allowed, refrain from using \"..\" in file paths."); + + return File(m_Path / file_path); + } } \ No newline at end of file diff --git a/src/core/filemgr/Folder.hpp b/src/core/filemgr/Folder.hpp index 0cc5f4b..11cb1d0 100644 --- a/src/core/filemgr/Folder.hpp +++ b/src/core/filemgr/Folder.hpp @@ -3,10 +3,12 @@ namespace YimMenu { - class Folder final : public BaseObj - { - public: - Folder(const std::filesystem::path& folder); + class File; + class Folder final : public BaseObj + { + public: + Folder(const std::filesystem::path& folder); - }; + File GetFile(std::filesystem::path file_path) const; + }; } \ No newline at end of file diff --git a/src/core/util/VehicleHelper.cpp b/src/core/util/VehicleHelper.cpp new file mode 100644 index 0000000..6f94579 --- /dev/null +++ b/src/core/util/VehicleHelper.cpp @@ -0,0 +1,259 @@ +#include "VehicleHelper.hpp" + +#include "core/util/Joaat.hpp" +#include "game/gta/Natives.hpp" +#include "game/gta/data/VehicleValues.hpp" + +namespace YimMenu +{ + const char* VehicleHelper::GetModSlotName(Hash model, int vehicle, int mod_slot) + { + switch ((VehicleModType)mod_slot) + { + case VehicleModType::MOD_HOOD: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_HOD"); + case VehicleModType::MOD_ARMOR: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_ARM"); + case VehicleModType::MOD_BRAKES: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_BRA"); + case VehicleModType::MOD_ENGINE: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_ENG"); + case VehicleModType::MOD_SUSPENSION: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_SUS"); + case VehicleModType::MOD_TRANSMISSION: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_TRN"); + case VehicleModType::MOD_HORNS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_HRN"); + case VehicleModType::MOD_FRONTWHEEL: + if (!VEHICLE::IS_THIS_MODEL_A_BIKE(model) && VEHICLE::IS_THIS_MODEL_A_BICYCLE(model)) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_MOD_WHEM"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_WHE0_0"); + case VehicleModType::MOD_REARWHEEL: + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_WHE0_1"); + //Bennys + case VehicleModType::MOD_PLATEHOLDER: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S0"); + case VehicleModType::MOD_VANITYPLATES: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S1"); + case VehicleModType::MOD_TRIMDESIGN: + if (model == "SULTANRS"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S2b"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S2"); + case VehicleModType::MOD_ORNAMENTS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S3"); + case VehicleModType::MOD_DASHBOARD: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S4"); + case VehicleModType::MOD_DIALDESIGN: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S5"); + case VehicleModType::MOD_DOORSPEAKERS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S6"); + case VehicleModType::MOD_SEATS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S7"); + case VehicleModType::MOD_STEERINGWHEELS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S8"); + case VehicleModType::MOD_COLUMNSHIFTERLEVERS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S9"); + case VehicleModType::MOD_PLAQUES: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S10"); + case VehicleModType::MOD_SPEAKERS: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S11"); + case VehicleModType::MOD_TRUNK: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S12"); + case VehicleModType::MOD_HYDRO: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S13"); + case VehicleModType::MOD_ENGINEBLOCK: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S14"); + case VehicleModType::MOD_AIRFILTER: + if (model == "SULTANRS"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S15b"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S15"); + case VehicleModType::MOD_STRUTS: + if (model == "SULTANRS"_J || model == "BANSHEE2"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S16b"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S16"); + case VehicleModType::MOD_ARCHCOVER: + if (model == "SULTANRS"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S17b"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S17"); + case VehicleModType::MOD_AERIALS: + if (model == "SULTANRS"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S18b"); + else if (model == "BTYPE3"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S18c"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S18"); + case VehicleModType::MOD_TRIM: + if (model == "SULTANRS"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S19b"); + else if (model == "BTYPE3"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S19c"); + else if (model == "VIRGO2"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S19d"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S19"); + case VehicleModType::MOD_TANK: + if (model == "SLAMVAN3"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S27"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S20"); + case VehicleModType::MOD_WINDOWS: + if (model == "BTYPE3"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S21b"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S21"); + case VehicleModType::MOD_DOORS: + if (model == "SLAMVAN3"_J) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("SLVAN3_RDOOR"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S22"); + case VehicleModType::MOD_LIVERY: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMM_MOD_S23"); + default: + auto name = VEHICLE::GET_MOD_SLOT_NAME(vehicle, mod_slot); + if (name == nullptr) + return ""; + if (strstr(name, "_")) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(name); + return name; + } + } + + static const std::map horn_map = {{-1, "CMOD_HRN_0"}, + {0, "CMOD_HRN_TRK"}, + {1, "CMOD_HRN_COP"}, + {2, "CMOD_HRN_CLO"}, + {3, "CMOD_HRN_MUS1"}, + {4, "CMOD_HRN_MUS2"}, + {5, "CMOD_HRN_MUS3"}, + {6, "CMOD_HRN_MUS4"}, + {7, "CMOD_HRN_MUS5"}, + {8, "CMOD_HRN_SAD"}, + {9, "HORN_CLAS1"}, + {10, "HORN_CLAS2"}, + {11, "HORN_CLAS3"}, + {12, "HORN_CLAS4"}, + {13, "HORN_CLAS5"}, + {14, "HORN_CLAS6"}, + {15, "HORN_CLAS7"}, + {16, "HORN_CNOTE_C0"}, + {17, "HORN_CNOTE_D0"}, + {18, "HORN_CNOTE_E0"}, + {19, "HORN_CNOTE_F0"}, + {20, "HORN_CNOTE_G0"}, + {21, "HORN_CNOTE_A0"}, + {22, "HORN_CNOTE_B0"}, + {23, "HORN_CNOTE_C1"}, + {24, "HORN_HIPS1"}, + {25, "HORN_HIPS2"}, + {26, "HORN_HIPS3"}, + {27, "HORN_HIPS4"}, + {28, "HORN_INDI_1"}, + {29, "HORN_INDI_2"}, + {30, "HORN_INDI_3"}, + {31, "HORN_INDI_4"}, + {32, "HORN_LUXE2"}, + {33, "HORN_LUXE1"}, + {34, "HORN_LUXE3"}, /*{35, "HORN_LUXE2"}, + {36, "HORN_LUXE1"}, {37, "HORN_LUXE3"},*/ + {38, "HORN_HWEEN1"}, + /*{39, "HORN_HWEEN1"},*/ {40, "HORN_HWEEN2"}, + /*{41, "HORN_HWEEN2"},*/ {42, "HORN_LOWRDER1"}, + /*{43, "HORN_LOWRDER1"},*/ {44, "HORN_LOWRDER2"}, /*{45, "HORN_LOWRDER2"},*/ + {46, "HORN_XM15_1"}, + {47, "HORN_XM15_2"}, + {48, "HORN_XM15_3"}}; + + const char* VehicleHelper::GetModeName(Hash model, int vehicle, int mod_slot, int mod, int mod_count) + { + if (mod_count == 0) + return ""; + if (mod < -1 || mod >= mod_count) + return ""; + if (mod_slot == (int)VehicleModType::MOD_HORNS) + { + if (horn_map.find(mod) != horn_map.end()) + { + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(horn_map.find(mod)->second); + } + return ""; + } + + if (mod_slot == (int)VehicleModType::MOD_FRONTWHEEL || mod_slot == (int)VehicleModType::MOD_REARWHEEL) + { + if (mod == -1) + { + if (!VEHICLE::IS_THIS_MODEL_A_BIKE(model) && VEHICLE::IS_THIS_MODEL_A_BICYCLE(model)) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_WHE_0"); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_WHE_B_0"); + } + if (mod >= mod_count / 2) + //return std::format("{} {}", HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CHROME"), HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(VEHICLE::GET_MOD_TEXT_LABEL(vehicle, mod_slot, mod))).c_str(); //Bug with FMT library? Returns Chrome Chrome... + return std::format("Chrome {}", HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(VEHICLE::GET_MOD_TEXT_LABEL(vehicle, mod_slot, mod))) + .c_str(); + else + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(VEHICLE::GET_MOD_TEXT_LABEL(vehicle, mod_slot, mod)); + } + + switch (mod_slot) + { + case (int)VehicleModType::MOD_ARMOR: + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(std::format("CMOD_ARM_{}", (mod + 1)).c_str()); + case (int)VehicleModType::MOD_BRAKES: + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(std::format("CMOD_BRA_{}", (mod + 1)).c_str()); + case (int)VehicleModType::MOD_ENGINE: + if (mod == -1) + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_ARM_0"); + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(std::format("CMOD_ENG_{}", (mod + 1)).c_str()); + case (int)VehicleModType::MOD_SUSPENSION: + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(std::format("CMOD_SUS_{}", (mod + 1)).c_str()); + case (int)VehicleModType::MOD_TRANSMISSION: + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(std::format("CMOD_GBX_{}", (mod + 1)).c_str()); + } + + + if (mod > -1) + { + if (mod_slot == (int)VehicleModType::MOD_SIDESKIRT && VEHICLE::GET_NUM_VEHICLE_MODS(vehicle, (int)VehicleModType::MOD_SIDESKIRT) < 2) + { + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_SKI_1"); + } + auto label = VEHICLE::GET_MOD_TEXT_LABEL(vehicle, mod_slot, mod); + if (label == nullptr || strlen(label) == 0) + return "MISSING_LABEL"; + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(label); + } + else + { + switch (mod_slot) + { + case (int)VehicleModType::MOD_AIRFILTER: break; + case (int)VehicleModType::MOD_STRUTS: + switch (model) + { + case "BANSHEE"_J: + case "BANSHEE2"_J : + case "SULTANRS"_J: return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_COL5_41"); + } + break; + } + return HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION("CMOD_DEF_0"); + } + } + + static const std::map>> mod_blacklists = { + {"BANSHEE"_J, {{(int)VehicleModType::MOD_SPOILERS, {3, 4}}, {(int)VehicleModType::MOD_COLUMNSHIFTERLEVERS, {0, 1, 2, 3}}, {(int)VehicleModType::MOD_SPEAKERS, {0}}, {(int)VehicleModType::MOD_LIVERY, {15, 16}}}}, + {"SENTINEL"_J, {{(int)VehicleModType::MOD_SPOILERS, {4, 5}}, {(int)VehicleModType::MOD_COLUMNSHIFTERLEVERS, {0, 1, 2, 3}}, {(int)VehicleModType::MOD_SPEAKERS, {0}}, {(int)VehicleModType::MOD_LIVERY, {0, 1}}}}, + }; + + bool VehicleHelper::CheckModBlacklist(Hash model, int mod_slot, int mod) + { + if (mod_blacklists.find(model) == mod_blacklists.end()) + { + return false; + } + + auto veh_slot_blacklist = mod_blacklists.find(model)->second; + if (veh_slot_blacklist.find(mod_slot) == veh_slot_blacklist.end()) + { + return false; + } + + auto veh_mod_blacklist = veh_slot_blacklist.find(mod_slot)->second; + if (std::find(veh_mod_blacklist.begin(), veh_mod_blacklist.end(), mod) != veh_mod_blacklist.end()) + { + return true; + } + + return false; + } + + bool VehicleHelper::IsBennys(int veh) + { + auto v = (WheelTypes)VEHICLE::GET_VEHICLE_WHEEL_TYPE(veh); + return v == WheelTypes::WHEEL_TYPE_BENNYS_ORIGINAL || v == WheelTypes::WHEEL_TYPE_BENNYS_BESPOKE || v == WheelTypes::WHEEL_TYPE_OPEN_WHEEL || v == WheelTypes::WHEEL_TYPE_STREET || v == WheelTypes::WHEEL_TYPE_TRACK; + } +} diff --git a/src/core/util/VehicleHelper.hpp b/src/core/util/VehicleHelper.hpp new file mode 100644 index 0000000..8f371e1 --- /dev/null +++ b/src/core/util/VehicleHelper.hpp @@ -0,0 +1,14 @@ +#pragma once +#include "types/script/types.hpp" + +namespace YimMenu +{ + class VehicleHelper + { + public: + static bool CheckModBlacklist(Hash model, int mod_slot, int mod); + static const char* GetModSlotName(Hash model, int vehicle, int mod_slot); + static const char* GetModeName(Hash model, int vehicle, int mod_slot, int mod, int mod_count); + static bool IsBennys(int veh); + }; +} diff --git a/src/core/util/strings.hpp b/src/core/util/strings.hpp new file mode 100644 index 0000000..9ab26ee --- /dev/null +++ b/src/core/util/strings.hpp @@ -0,0 +1,43 @@ + +#pragma once +#include +#include + +namespace YimMenu +{ + // Function to trim leading and trailing whitespace from a string + inline std::string trimString(std::string& str) + { + auto start = str.begin(); + auto end = str.end(); + + // Find the first non-whitespace character from the start + while (start != end && std::isspace(*start)) + { + ++start; + } + + // Find the last non-whitespace character from the end + while (start != end && std::isspace(*(end - 1))) + { + --end; + } + + return std::string(start, end); + } + + inline void strcpy_safe(char* dest, const char* src, int dest_size) + { + auto len = dest_size - 1; + strncpy(dest, src, len); + if (strlen(src) > len) + dest[len] = '\0'; + } + + inline void replace_string(std::string& str, const char* str1, const char* str2) + { + size_t pos = 0; + while ((pos = str.find(str1, pos)) != std::string::npos) + str.replace(pos, strlen(str1), str2); + } +} diff --git a/src/game/features/vehicle/PersistCarService/PersistCarService.cpp b/src/game/features/vehicle/PersistCarService/PersistCarService.cpp new file mode 100644 index 0000000..f20f8fd --- /dev/null +++ b/src/game/features/vehicle/PersistCarService/PersistCarService.cpp @@ -0,0 +1,282 @@ +#include "PersistCarService.hpp" + +#include "core/backend/FiberPool.hpp" +#include "core/backend/ScriptMgr.hpp" +#include "core/frontend/Notifications.hpp" +#include "core/util/VehicleHelper.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" +#include "game/gta/Vehicle.hpp" +#include "game/gta/data/VehicleValues.hpp" + +namespace YimMenu::Features +{ + Folder PersistCarService::CheckFolder(std::string folderName) + { + return FileMgr::GetProjectFolder("./saved_json_vehicles/" + folderName); + } + + void PersistCarService::RefreshList(std::string folderName, std::vector& folders, std::vector& files) + { + FiberPool::Push([folderName, &folders, &files] { + folders.clear(); + + const auto file_path = CheckFolder(); + for (const auto& directory_entry : std::filesystem::directory_iterator(file_path.Path())) + if (directory_entry.is_directory()) + folders.push_back(directory_entry.path().filename().generic_string()); + + files.clear(); + + const auto file_path2 = CheckFolder(folderName); + for (const auto& directory_entry : std::filesystem::directory_iterator(file_path2.Path())) + if (directory_entry.path().extension() == ".json") + files.push_back(directory_entry.path().filename().generic_string()); + }); + } + + nlohmann::json PersistCarService::GetJson(Vehicle veh) + { + nlohmann::json vehicle_json; + int primary_color, secondary_color; + int pearlescent_color, wheel_color; + auto vehicle = veh.GetHandle(); + Hash vehicle_hash = veh.GetModel(); + std::map vehicle_extras; + auto is_bennys = VehicleHelper::IsBennys(vehicle); + + for (int slot = (int)VehicleModType::MOD_SPOILERS; slot <= (int)VehicleModType::MOD_LIGHTBAR; slot++) + if (VEHICLE::GET_NUM_VEHICLE_MODS(vehicle, slot) > 0) + { + auto wheel_custom = VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, slot); + + if (wheel_custom && is_bennys) + wheel_custom = 0; + + int vehicle_mod[2] = {VEHICLE::GET_VEHICLE_MOD(vehicle, slot), wheel_custom}; + vehicle_json[mod_names[slot]] = vehicle_mod; + } + else if (VEHICLE::IS_TOGGLE_MOD_ON(vehicle, slot)) + { + vehicle_json[mod_names[slot]] = "TOGGLE"; + + if (slot == (int)VehicleModType::MOD_TYRE_SMOKE) + { + int tire_smoke_color[3]{}; + VEHICLE::GET_VEHICLE_TYRE_SMOKE_COLOR(vehicle, &tire_smoke_color[0], &tire_smoke_color[1], &tire_smoke_color[2]); + vehicle_json[tire_smoke_color_key] = tire_smoke_color; + } + else if (slot == (int)VehicleModType::MOD_XENON_LIGHTS) + vehicle_json[headlight_color_key] = VEHICLE::GET_VEHICLE_XENON_LIGHT_COLOR_INDEX(vehicle); + } + + for (int extra = (int)CustomVehicleModType::MOD_EXTRA_14; extra <= (int)CustomVehicleModType::MOD_EXTRA_1; ++extra) + if (auto id = (extra - (int)CustomVehicleModType::MOD_EXTRA_1) * -1; VEHICLE::DOES_EXTRA_EXIST(vehicle, id)) + vehicle_extras[id] = VEHICLE::IS_VEHICLE_EXTRA_TURNED_ON(vehicle, id); + + VEHICLE::GET_VEHICLE_COLOURS(vehicle, &primary_color, &secondary_color); + VEHICLE::GET_VEHICLE_EXTRA_COLOURS(vehicle, &pearlescent_color, &wheel_color); + + vehicle_json[vehicle_model_hash_key] = vehicle_hash; + vehicle_json[primary_color_key] = primary_color; + vehicle_json[secondary_color_key] = secondary_color; + + if (VEHICLE::GET_IS_VEHICLE_PRIMARY_COLOUR_CUSTOM(vehicle)) + { + int custom_primary_color[3]{}; + VEHICLE::GET_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle, &custom_primary_color[0], &custom_primary_color[1], &custom_primary_color[2]); + vehicle_json[custom_primary_color_key] = custom_primary_color; + } + + if (VEHICLE::GET_IS_VEHICLE_SECONDARY_COLOUR_CUSTOM(vehicle)) + { + int custom_secondary_color[3]{}; + VEHICLE::GET_VEHICLE_CUSTOM_SECONDARY_COLOUR(vehicle, &custom_secondary_color[0], &custom_secondary_color[1], &custom_secondary_color[2]); + vehicle_json[custom_secondary_color_key] = custom_secondary_color; + } + + vehicle_json[vehicle_window_tint_key] = VEHICLE::GET_VEHICLE_WINDOW_TINT(vehicle); + vehicle_json[pearlescent_color_key] = pearlescent_color; + vehicle_json[wheel_color_key] = wheel_color; + vehicle_json[tire_can_burst] = VEHICLE::GET_VEHICLE_TYRES_CAN_BURST(vehicle); + vehicle_json[vehicle_extras_key] = vehicle_extras; + vehicle_json[wheel_type_key] = VEHICLE::GET_VEHICLE_WHEEL_TYPE(vehicle); + + if ((VEHICLE::GET_VEHICLE_LIVERY_COUNT(vehicle) > 1) && VEHICLE::GET_VEHICLE_LIVERY(vehicle) >= 0) + vehicle_json[vehicle_livery_key] = VEHICLE::GET_VEHICLE_LIVERY(vehicle); + + if (VEHICLE::IS_THIS_MODEL_A_CAR(vehicle_hash) || VEHICLE::IS_THIS_MODEL_A_BIKE(vehicle_hash)) + { + bool neon_lights[4]{}; + for (int i = (int)NeonLightLocations::NEON_LEFT; i <= (int)NeonLightLocations::NEON_BACK; i++) + neon_lights[i] = VEHICLE::GET_VEHICLE_NEON_ENABLED(vehicle, i); + + int neon_color[3]{}; + VEHICLE::GET_VEHICLE_NEON_COLOUR(vehicle, &neon_color[0], &neon_color[1], &neon_color[2]); + + int interior_color, dashboard_color; + VEHICLE::GET_VEHICLE_EXTRA_COLOUR_5(vehicle, &interior_color); + VEHICLE::GET_VEHICLE_EXTRA_COLOUR_6(vehicle, &dashboard_color); + + vehicle_json[plate_text_key] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT(vehicle); + vehicle_json[plate_text_index_key] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle); + vehicle_json[drift_tires] = VEHICLE::GET_DRIFT_TYRES_SET(vehicle); + vehicle_json[neon_color_key] = neon_color; + vehicle_json[neon_lights_key] = neon_lights; + vehicle_json[interior_color_key] = interior_color; + vehicle_json[dash_color_key] = dashboard_color; + } + + return vehicle_json; + } + + void PersistCarService::Save(std::string folderName, std::string fileName) + { + FiberPool::Push([folderName, fileName] { + if (auto veh = Self::GetVehicle(); veh && veh.IsValid()) + { + const auto file = PersistCarService::CheckFolder(folderName).GetFile(fileName); + std::ofstream file_stream(file.Path(), std::ios::out | std::ios::trunc); + file_stream << PersistCarService::GetJson(veh).dump(4); + file_stream.close(); + } + else + Notifications::Show("Persist Car", "Tried to save a vehicle which does not exist", NotificationType::Warning); + }); + } + + void PersistCarService::Load(std::string folderName, std::string fileName) + { + if (!fileName.empty()) + FiberPool::Push([folderName, fileName] { + const auto file = CheckFolder(folderName).GetFile(fileName).Path(); + + if (!std::filesystem::exists(file)) + { + Notifications::Show("Persist Car", "File does not exist.", NotificationType::Error); + return; + } + + std::ifstream file_stream(file); + nlohmann::json vehicle_json; + + try + { + file_stream >> vehicle_json; + if (SpawnFromJson(vehicle_json)) + Notifications::Show("Persist Car", std::format("Spawned {}", fileName), NotificationType::Success); + else + Notifications::Show("Persist Car", std::format("Unable to spawn {}", fileName), NotificationType::Error); + } + catch (std::exception& e) + { + LOG(WARNING) << e.what(); + } + + file_stream.close(); + }); + else + Notifications::Show("Persist Car", "Select a file first", NotificationType::Warning); + } + + bool PersistCarService::SpawnFromJson(nlohmann::json vehicle_json) + { + const Hash vehicle_hash = vehicle_json[vehicle_model_hash_key]; + auto veh = Vehicle::Create(vehicle_hash, Self::GetPed().GetPosition(), Self::GetPed().GetHeading()); + + if (veh != nullptr) + { + ScriptMgr::Yield(); + + auto vehicle = veh.GetHandle(); + + VEHICLE::SET_VEHICLE_MOD_KIT(vehicle, 0); + + if (!(vehicle_json[primary_color_key].is_null() || vehicle_json[secondary_color_key].is_null())) + VEHICLE::SET_VEHICLE_COLOURS(vehicle, vehicle_json[primary_color_key], vehicle_json[secondary_color_key]); + + if (!vehicle_json[custom_primary_color_key].is_null()) + { + std::vector primary_custom_color = vehicle_json[custom_primary_color_key]; + VEHICLE::SET_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle, primary_custom_color[0], primary_custom_color[1], primary_custom_color[2]); + } + if (!vehicle_json[custom_secondary_color_key].is_null()) + { + std::vector secondary_custom_color = vehicle_json[custom_secondary_color_key]; + VEHICLE::SET_VEHICLE_CUSTOM_SECONDARY_COLOUR(vehicle, secondary_custom_color[0], secondary_custom_color[1], secondary_custom_color[2]); + } + + if (!vehicle_json[vehicle_window_tint_key].is_null()) + VEHICLE::SET_VEHICLE_WINDOW_TINT(vehicle, vehicle_json[vehicle_window_tint_key]); + if (!(vehicle_json[pearlescent_color_key].is_null() || vehicle_json[wheel_color_key].is_null())) + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(vehicle, vehicle_json[pearlescent_color_key], vehicle_json[wheel_color_key]); + if (!vehicle_json[tire_can_burst].is_null()) + VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(vehicle, vehicle_json[tire_can_burst]); + + if (!vehicle_json[wheel_type_key].is_null()) + VEHICLE::SET_VEHICLE_WHEEL_TYPE(vehicle, vehicle_json[wheel_type_key]); + + if (!vehicle_json[vehicle_livery_key].is_null()) + VEHICLE::SET_VEHICLE_LIVERY(vehicle, vehicle_json[vehicle_livery_key]); + + if (VEHICLE::IS_THIS_MODEL_A_CAR(vehicle_hash) || VEHICLE::IS_THIS_MODEL_A_BIKE(vehicle_hash)) + { + if (!vehicle_json[neon_color_key].is_null()) + { + std::vector neon_color = vehicle_json[neon_color_key]; + VEHICLE::SET_VEHICLE_NEON_COLOUR(vehicle, neon_color[0], neon_color[1], neon_color[2]); + } + if (!vehicle_json[neon_lights_key].is_null()) + { + std::vector neon_lights = vehicle_json[neon_lights_key]; + for (int i = (int)NeonLightLocations::NEON_LEFT; i <= (int)NeonLightLocations::NEON_BACK; i++) + VEHICLE::SET_VEHICLE_NEON_ENABLED(vehicle, i, neon_lights[i]); + } + if (!vehicle_json[plate_text_key].is_null()) + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(vehicle, vehicle_json[plate_text_key].get().c_str()); + if (!vehicle_json[plate_text_index_key].is_null()) + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle, vehicle_json[plate_text_index_key]); + if (!vehicle_json[drift_tires].is_null()) + VEHICLE::SET_DRIFT_TYRES(vehicle, vehicle_json[drift_tires]); + + if (!vehicle_json[interior_color_key].is_null()) + VEHICLE::SET_VEHICLE_EXTRA_COLOUR_5(vehicle, vehicle_json[interior_color_key]); + if (!vehicle_json[dash_color_key].is_null()) + VEHICLE::SET_VEHICLE_EXTRA_COLOUR_6(vehicle, vehicle_json[dash_color_key]); + } + + for (int i = (int)VehicleModType::MOD_SPOILERS; i < (int)VehicleModType::MOD_LIGHTBAR; i++) + if (!vehicle_json[mod_names[i]].is_null()) + { + if (vehicle_json[mod_names[i]].is_array()) + { + std::vector mod = vehicle_json[mod_names[i]]; + VEHICLE::SET_VEHICLE_MOD(vehicle, i, mod[0], mod[1]); + } + else + { + if (i == (int)VehicleModType::MOD_TYRE_SMOKE && !vehicle_json[tire_smoke_color_key].is_null()) + { + std::vector tire_smoke_color = vehicle_json[tire_smoke_color_key]; + VEHICLE::SET_VEHICLE_TYRE_SMOKE_COLOR(vehicle, tire_smoke_color[0], tire_smoke_color[1], tire_smoke_color[2]); + } + else if (i == (int)VehicleModType::MOD_XENON_LIGHTS && !vehicle_json[headlight_color_key].is_null()) + VEHICLE::SET_VEHICLE_XENON_LIGHT_COLOR_INDEX(vehicle, vehicle_json[headlight_color_key]); + + VEHICLE::TOGGLE_VEHICLE_MOD(vehicle, i, TRUE); + } + } + + if (!vehicle_json[vehicle_extras_key].is_null()) + { + std::map vehicle_extras = vehicle_json[vehicle_extras_key]; + for (const auto& [extra, extra_enabled] : vehicle_extras) + VEHICLE::SET_VEHICLE_EXTRA(vehicle, extra, extra_enabled ? 0 : 1); + } + + return true; + } + + return false; + } +} diff --git a/src/game/features/vehicle/PersistCarService/PersistCarService.hpp b/src/game/features/vehicle/PersistCarService/PersistCarService.hpp new file mode 100644 index 0000000..da8d608 --- /dev/null +++ b/src/game/features/vehicle/PersistCarService/PersistCarService.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "core/filemgr/FileMgr.hpp" +#include "game/gta/Vehicle.hpp" + +namespace YimMenu::Features +{ + class PersistCarService + { + public: + static constexpr auto vehicle_model_hash_key = "vehicle_model_hash"; + + static void RefreshList(std::string folderName, std::vector& folders, std::vector& files); + static void Save(std::string folderName, std::string fileName); + static void Load(std::string folderName, std::string fileName); + + private: + static nlohmann::json GetJson(Vehicle vehicle); + static Folder CheckFolder(std::string folderName = ""); + static bool SpawnFromJson(nlohmann::json); + + private: + static constexpr auto plate_text_key = "plate_text"; + static constexpr auto plate_text_index_key = "plate_text_index"; + static constexpr auto vehicle_extras_key = "vehicle_extras"; + static constexpr auto vehicle_livery_key = "vehicle_livery"; + static constexpr auto wheel_type_key = "wheel_type"; + static constexpr auto wheel_color_key = "wheel_color"; + static constexpr auto tire_smoke_color_key = "tire_smoke_color"; + static constexpr auto tire_can_burst = "tire_can_burst"; + static constexpr auto drift_tires = "drift_tires"; + static constexpr auto vehicle_window_tint_key = "vehicle_window_tint"; + static constexpr auto neon_lights_key = "neon_lights"; + static constexpr auto neon_color_key = "neon_color"; + static constexpr auto primary_color_key = "primary_color"; + static constexpr auto custom_primary_color_key = "custom_primary_color"; + static constexpr auto secondary_color_key = "secondary_color"; + static constexpr auto custom_secondary_color_key = "custom_secondary_color"; + static constexpr auto pearlescent_color_key = "pearlescent_color"; + static constexpr auto headlight_color_key = "headlight_color"; + static constexpr auto interior_color_key = "interior_color"; + static constexpr auto dash_color_key = "dash_color"; + }; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle.cpp b/src/game/frontend/submenus/Vehicle.cpp index 0cfc62f..66ac656 100644 --- a/src/game/frontend/submenus/Vehicle.cpp +++ b/src/game/frontend/submenus/Vehicle.cpp @@ -1,6 +1,8 @@ #include "Vehicle.hpp" #include "game/frontend/items/Items.hpp" #include "game/frontend/submenus/Vehicle/SpawnVehicle.hpp" +#include "Vehicle/VehicleEditorCategory.hpp" +#include "Vehicle/PersistCarCategory.hpp" namespace YimMenu::Submenus { @@ -37,5 +39,7 @@ namespace YimMenu::Submenus AddCategory(std::move(main)); AddCategory(BuildSpawnVehicleMenu()); + AddCategory(VehicleEditorCategory()); + AddCategory(PersistCarCategory()); } } \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle/PersistCarCategory.cpp b/src/game/frontend/submenus/Vehicle/PersistCarCategory.cpp new file mode 100644 index 0000000..0131a98 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/PersistCarCategory.cpp @@ -0,0 +1,149 @@ + +#include "PersistCarCategory.hpp" + +#include "core/backend/FiberPool.hpp" +#include "core/frontend/Notifications.hpp" +#include "core/util/strings.hpp" +#include "game/backend/Self.hpp" +#include "game/features/vehicle/PersistCarService/PersistCarService.hpp" +#include "game/gta/Vehicle.hpp" +#include "misc/cpp/imgui_stdlib.h" + +namespace YimMenu::Submenus +{ + std::shared_ptr PersistCarCategory() + { + static std::string folder{}, file{}; + static std::vector folders{}, files{}; + static char vehicle_file_name_input[64]{}; + static char save_folder[50]{}; + + auto persistCar = std::make_shared("Persist Car"); + + persistCar->AddItem(std::make_unique([] { + static auto drawSaveVehicleButton = [](const char* folderToSaveIn) { + if (!Self::GetVehicle() || !Self::GetVehicle().IsValid()) + return; + + if (ImGui::Button("Save Veh")) + { + std::string yo = vehicle_file_name_input; + ZeroMemory(vehicle_file_name_input, sizeof(vehicle_file_name_input)); + + if (!trimString(yo).size()) + { + Notifications::Show("Persist Car", "Filename empty!", NotificationType::Warning); + return; + } + + replace_string(yo, ".", ""); // so that .. does not throw error by custom file system when it sees say bob..json + yo += ".json"; + + Features::PersistCarService::Save(folderToSaveIn, yo); + Features::PersistCarService::RefreshList(folder, folders, files); + } + ImGui::SameLine(); + if (ImGui::Button("Populate Name")) + FiberPool::Push([] { + std::string name = Self::GetVehicle().GetVehicleFullname(); + strcpy(vehicle_file_name_input, name.c_str()); + }); + }; + + if (ImGui::Button("Refresh List")) + Features::PersistCarService::RefreshList(folder, folders, files); + + ImGui::SetNextItemWidth(300.f); + auto folder_display = folder.empty() ? "Root" : folder.c_str(); + if (ImGui::BeginCombo("Folder", folder_display)) + { + if (ImGui::Selectable("Root", folder == "")) + { + folder.clear(); + Features::PersistCarService::RefreshList(folder, folders, files); + } + + for (std::string folder_name : folders) + if (ImGui::Selectable(folder_name.c_str(), folder == folder_name)) + { + folder = folder_name; + Features::PersistCarService::RefreshList(folder, folders, files); + } + + ImGui::EndCombo(); + } + + static bool open_modal = false; + static std::string search; + + ImGui::SetNextItemWidth(300); + if (ImGui::InputTextWithHint("###veh_name", "Search", &search)) + std::transform(search.begin(), search.end(), search.begin(), tolower); + + ImGui::Text("Saved Vehicles"); + + static const auto over_30 = (30 * ImGui::GetTextLineHeightWithSpacing() + 2); + const auto box_height = files.size() <= 30 ? (files.size() * ImGui::GetTextLineHeightWithSpacing() + 2) : over_30; + ImGui::SetNextItemWidth(250); + if (ImGui::BeginListBox("##saved_vehs", ImVec2(300, box_height))) + { + for (const auto& pair : files) + { + std::string pair_lower = pair; + std::transform(pair_lower.begin(), pair_lower.end(), pair_lower.begin(), tolower); + if (pair_lower.contains(search)) + { + auto file_name = pair.c_str(); + if (ImGui::Selectable(file_name, file == pair, ImGuiSelectableFlags_AllowItemOverlap)) + { + file = pair; + open_modal = true; + } + } + } + ImGui::EndListBox(); + } + ImGui::SameLine(); + ImGui::BeginGroup(); + { + ImGui::Text("Vehicle File Name"); + ImGui::SetNextItemWidth(250); + ImGui::InputText("##vehiclefilename", vehicle_file_name_input, IM_ARRAYSIZE(vehicle_file_name_input)); + + if (folder.empty()) + { + ImGui::Text("Vehicle Folder Name"); + ImGui::SetNextItemWidth(250); + ImGui::InputText("##foldername", save_folder, IM_ARRAYSIZE(save_folder)); + drawSaveVehicleButton(save_folder); + } + else + drawSaveVehicleButton(folder.c_str()); + } + ImGui::EndGroup(); + + if (open_modal) + ImGui::OpenPopup("##spawncarmodel2"); + if (ImGui::BeginPopupModal("##spawncarmodel2", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove)) + { + ImGui::Text("Are you sure you want to spawn %s", file.c_str()); + ImGui::Spacing(); + if (ImGui::Button("Yes")) + { + Features::PersistCarService::Load(folder, file); + open_modal = false; + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("No")) + { + open_modal = false; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + })); + + return persistCar; + } +} diff --git a/src/game/frontend/submenus/Vehicle/PersistCarCategory.hpp b/src/game/frontend/submenus/Vehicle/PersistCarCategory.hpp new file mode 100644 index 0000000..0502ff5 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/PersistCarCategory.hpp @@ -0,0 +1,7 @@ +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr PersistCarCategory(); +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.cpp b/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.cpp new file mode 100644 index 0000000..a6e0ef2 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.cpp @@ -0,0 +1,882 @@ +#include "VehicleEditorCategory.hpp" + +#include "core/backend/FiberPool.hpp" +#include "core/backend/ScriptMgr.hpp" +#include "core/util/VehicleHelper.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" +#include "game/gta/data/VehicleValues.hpp" +#include "game/gta/data/lscTypes.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr VehicleEditorCategory() + { + static int currentVeh = 0; + static std::string vehName = ""; + static bool preparingVehicle = false; + static bool isBennys = false; + static int selected_slot = -1; + + static std::map owned_mods{}; + static std::map slot_display_names{}; + static std::map> mod_display_names{}; + + static std::map> front_wheel_map{}; + static std::map> rear_wheel_map{}; + static int front_wheel_stock_mod = -1; + static int rear_wheel_stock_mod = -1; + + static auto prepareVehicle = [] { + if (currentVeh != -1) // when == -1 dont change selected slot + selected_slot = -1; + + preparingVehicle = true; + + FiberPool::Push([] { + currentVeh = Self::GetVehicle().GetHandle(); + auto model = Self::GetVehicle().GetModel(); + front_wheel_stock_mod = -1; + rear_wheel_stock_mod = -1; + + if (!HUD::HAS_THIS_ADDITIONAL_TEXT_LOADED("MOD_MNU", 10)) + { + HUD::CLEAR_ADDITIONAL_TEXT(10, TRUE); + HUD::REQUEST_ADDITIONAL_TEXT("MOD_MNU", 10); + ScriptMgr::Yield(); + } + + vehName = Self::GetVehicle().GetVehicleFullname(); + owned_mods = Self::GetVehicle().GetOwnedMods(); + isBennys = VehicleHelper::IsBennys(currentVeh); + + VEHICLE::SET_VEHICLE_MOD_KIT(currentVeh, 0); + + std::map tmp_slot_display_names; + std::map> tmp_mod_display_names; + std::map> tmp_front_wheel_map; + std::map> tmp_rear_wheel_map; + + tmp_slot_display_names[(int)CustomVehicleModType::MOD_PLATE_STYLE] = "Plate Style"; + tmp_slot_display_names[(int)CustomVehicleModType::MOD_WINDOW_TINT] = "Window Tint"; + tmp_slot_display_names[(int)CustomVehicleModType::MOD_WHEEL_TYPE] = "Wheel Type"; + + tmp_mod_display_names[(int)CustomVehicleModType::MOD_PLATE_STYLE].insert(lscPlateStyles.begin(), + lscPlateStyles.end()); + tmp_mod_display_names[(int)CustomVehicleModType::MOD_WINDOW_TINT].insert(lscWindowTintTypes.begin(), + lscWindowTintTypes.end()); + tmp_mod_display_names[(int)CustomVehicleModType::MOD_WHEEL_TYPE].insert(lscWheelStyles.begin(), + lscWheelStyles.end()); + + for (int slot = (int)VehicleModType::MOD_SPOILERS; slot <= (int)VehicleModType::MOD_LIGHTBAR; slot++) + { + int count = VEHICLE::GET_NUM_VEHICLE_MODS(currentVeh, slot); + if (count > 0) + { + int owner_mod = owned_mods[slot]; + + std::string slot_name = VehicleHelper::GetModSlotName(model, currentVeh, slot); + if (slot_name.empty()) + continue; + + slot_name.append("##" + std::to_string(slot)); + tmp_slot_display_names[slot] = slot_name; + + std::map mod_names; + + for (int mod = -1; mod < count; mod++) + { + if (VehicleHelper::CheckModBlacklist(model, slot, mod)) + continue; + + bool is_repeated = false; + + std::string mod_name = VehicleHelper::GetModeName(model, currentVeh, slot, mod, count); + + if (mod_name.empty() || mod_name == "NULL") + continue; + + if (slot == (int)VehicleModType::MOD_FRONTWHEEL) + { + if (isBennys && mod_name.rfind("Chrome ", 0) == 0) + { + std::string new_mod_name = mod_name.substr(7); + + if (tmp_front_wheel_map[new_mod_name].size() > 0) + mod_name = new_mod_name; + } + + tmp_front_wheel_map[mod_name].push_back(mod); + + if (mod == owner_mod) + front_wheel_stock_mod = tmp_front_wheel_map[mod_name][0]; + if (tmp_front_wheel_map[mod_name].size() > 1) + is_repeated = true; + } + else if (slot == (int)VehicleModType::MOD_REARWHEEL) + { + if (isBennys && mod_name.rfind("Chrome ", 0) == 0) + { + std::string new_mod_name = mod_name.substr(7); + + if (tmp_rear_wheel_map[new_mod_name].size() > 0) + mod_name = new_mod_name; + } + + tmp_rear_wheel_map[mod_name].push_back(mod); + + if (mod == owner_mod) + rear_wheel_stock_mod = tmp_rear_wheel_map[mod_name][0]; + if (tmp_rear_wheel_map[mod_name].size() > 1) + is_repeated = true; + } + + if (!is_repeated) + mod_names[mod] = mod_name; + } + + tmp_mod_display_names[slot] = mod_names; + } + } + + if (tmp_mod_display_names.count((int)VehicleModType::MOD_HORNS) > 0) + tmp_mod_display_names[(int)VehicleModType::MOD_HORNS].insert(lscMissingHorns.begin(), + lscMissingHorns.end()); + + slot_display_names = tmp_slot_display_names; + mod_display_names = tmp_mod_display_names; + front_wheel_map = tmp_front_wheel_map; + rear_wheel_map = tmp_rear_wheel_map; + + preparingVehicle = false; + }); + }; + + auto vehicleEditor = std::make_shared("Vehicle Editor"); + + vehicleEditor->AddItem(std::make_unique([] { + if (!Self::GetVehicle()) + { + ImGui::Text("Please enter a vehicle."); + currentVeh = 0; + return; + } + + if (currentVeh != Self::GetVehicle().GetHandle()) + { + prepareVehicle(); + return; + } + + if (preparingVehicle) + return; + + ImGui::BeginGroup(); + { + ImGui::Text(vehName.c_str()); + ImGui::SameLine(); + if (ImGui::Button("Refresh Current Vehicle")) + FiberPool::Push([] { + currentVeh = -1; + }); + + ImGui::Spacing(); + { + static char plate[9]; + ImGui::SetNextItemWidth(150); + ImGui::InputTextWithHint("##plate", "Plate Number", plate, sizeof(plate), ImGuiInputTextFlags_None); + ImGui::SameLine(); + if (ImGui::Button("Change Plate")) + FiberPool::Push([] { + Self::GetVehicle().SetPlateText(plate); + }); + ImGui::SameLine(); + if (ImGui::Button("Max Vehicle")) + FiberPool::Push([] { + Self::GetVehicle().Upgrade(); + currentVeh = -1; + }); + } + ImGui::SeparatorText("Mod Options"); + { + if (ImGui::Checkbox("Burstible tires", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_TIRE_CAN_BURST])) + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_TIRE_CAN_BURST]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Low Grip Tires", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_DRIFT_TIRE])) + + FiberPool::Push([] { + VEHICLE::SET_DRIFT_TYRES(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_DRIFT_TIRE]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Turbo", (bool*)&owned_mods[(int)VehicleModType::MOD_TURBO])) + + FiberPool::Push([] { + VEHICLE::TOGGLE_VEHICLE_MOD(currentVeh, (int)VehicleModType::MOD_TURBO, owned_mods[(int)VehicleModType::MOD_TURBO]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Tire Smoke", (bool*)&owned_mods[(int)VehicleModType::MOD_TYRE_SMOKE])) + + FiberPool::Push([] { + VEHICLE::TOGGLE_VEHICLE_MOD(currentVeh, (int)VehicleModType::MOD_TYRE_SMOKE, owned_mods[(int)VehicleModType::MOD_TYRE_SMOKE]); + }); + } + ImGui::SeparatorText("Mod Slots"); + { + ImGui::BeginGroup(); + { + ImGui::Text("Slot"); + if (ImGui::BeginListBox("##slot", ImVec2(200, 200))) + { + for (const auto& [slot, name] : slot_display_names) + if (ImGui::Selectable(name.c_str(), slot == selected_slot)) + selected_slot = slot; + + ImGui::EndListBox(); + } + } + ImGui::EndGroup(); + + if (selected_slot != -1) + { + auto wheel_stock_mod = &front_wheel_stock_mod; + auto wheel_custom = &owned_mods[(int)CustomVehicleModType::MOD_FRONTWHEEL_VAR]; + bool is_wheel_mod = false; + + if (selected_slot == (int)VehicleModType::MOD_FRONTWHEEL) + is_wheel_mod = true; + else if (selected_slot == (int)VehicleModType::MOD_REARWHEEL) + { + wheel_stock_mod = &rear_wheel_stock_mod; + wheel_custom = &owned_mods[(int)CustomVehicleModType::MOD_REARWHEEL_VAR]; + is_wheel_mod = true; + } + else + is_wheel_mod = false; + + ImGui::SameLine(); + ImGui::BeginGroup(); + { + ImGui::Text("Mod"); + if (ImGui::BeginListBox("##mod", ImVec2(240, 200))) + { + for (const auto& it : mod_display_names[selected_slot]) + { + const auto& mod = it.first; + const auto& name = it.second; + + bool item_selected = mod == owned_mods[selected_slot]; + + if (is_wheel_mod) + item_selected = mod == *wheel_stock_mod; + + if (ImGui::Selectable(name.c_str(), item_selected)) + { + FiberPool::Push([&mod, is_wheel_mod, wheel_stock_mod, wheel_custom, name] { + if (selected_slot >= 0) + { + VEHICLE::SET_VEHICLE_MOD(currentVeh, selected_slot, mod, 0); + owned_mods[selected_slot] = mod; + + if (is_wheel_mod) + { + *wheel_stock_mod = mod; + *wheel_custom = 0; + } + } + else if (selected_slot == (int)CustomVehicleModType::MOD_WINDOW_TINT) + { + VEHICLE::SET_VEHICLE_WINDOW_TINT(currentVeh, mod); + owned_mods[selected_slot] = mod; + } + else if (selected_slot == (int)CustomVehicleModType::MOD_WHEEL_TYPE) + { + VEHICLE::SET_VEHICLE_WHEEL_TYPE(currentVeh, mod); + VEHICLE::SET_VEHICLE_MOD(currentVeh, (int)VehicleModType::MOD_FRONTWHEEL, 0, 0); + VEHICLE::SET_VEHICLE_MOD(currentVeh, (int)VehicleModType::MOD_REARWHEEL, 0, 0); + currentVeh = -1; + } + else if (selected_slot == (int)CustomVehicleModType::MOD_PLATE_STYLE) + { + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(currentVeh, mod); + owned_mods[selected_slot] = mod; + } + }); + } + } + ImGui::EndListBox(); + } + } + ImGui::EndGroup(); + + if (is_wheel_mod && *wheel_stock_mod != -1) + { + ImGui::SameLine(); + ImGui::BeginGroup(); + { + auto wheel_map = selected_slot == (int)VehicleModType::MOD_REARWHEEL ? rear_wheel_map : front_wheel_map; + + ImGui::Text("Style"); + if (ImGui::BeginListBox("##style", ImVec2(200, 200))) + { + std::string mod_name = mod_display_names[selected_slot][*wheel_stock_mod]; + auto wheel_mods = wheel_map[mod_name]; + + for (int i = 0; i < wheel_mods.size(); i++) + { + int& mod = wheel_mods[i]; + + int should_custom = 0; + + // bennys fix + if (!isBennys) + { + if (i == 0 && ImGui::Selectable("Stock", mod == owned_mods[selected_slot] && *wheel_custom == 0)) + FiberPool::Push([&mod] { + VEHICLE::SET_VEHICLE_MOD(currentVeh, selected_slot, mod, 0); + currentVeh = -1; + }); + should_custom = 1; + } + + if (ImGui::Selectable(("Style " + std::to_string(mod)).c_str(), mod == owned_mods[selected_slot] && *wheel_custom == should_custom)) + FiberPool::Push([&mod, should_custom] { + VEHICLE::SET_VEHICLE_MOD(currentVeh, selected_slot, mod, should_custom); + currentVeh = -1; + }); + } + ImGui::EndListBox(); + } + } + ImGui::EndGroup(); + } + } + } + ImGui::SeparatorText("Extras"); + { + for (int extra = (int)CustomVehicleModType::MOD_EXTRA_1; extra >= (int)CustomVehicleModType::MOD_EXTRA_14; extra--) + if (owned_mods.find(extra) != owned_mods.end()) + { + int id = (extra - (int)CustomVehicleModType::MOD_EXTRA_1) * -1; + bool is_extra_enabled = owned_mods[extra] == 1; + if (ImGui::Checkbox(std::format("{}###extra{}", id, id).c_str(), &is_extra_enabled)) + { + owned_mods[extra] = is_extra_enabled; + FiberPool::Push([id, is_extra_enabled] { + VEHICLE::SET_VEHICLE_EXTRA(currentVeh, id, !is_extra_enabled); + }); + } + ImGui::SameLine(); + } + ImGui::NewLine(); + } + ImGui::SeparatorText("Neon Light Options"); + { + ImGui::PushID("##headlight_en"); + if (ImGui::Checkbox("Headlight", (bool*)&owned_mods[(int)VehicleModType::MOD_XENON_LIGHTS])) + FiberPool::Push([] { + VEHICLE::TOGGLE_VEHICLE_MOD(currentVeh, (int)VehicleModType::MOD_XENON_LIGHTS, owned_mods[(int)VehicleModType::MOD_XENON_LIGHTS]); + }); + ImGui::PopID(); + ImGui::SameLine(); + if (ImGui::Checkbox("Left", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_NEON_LEFT_ON])) + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_NEON_ENABLED(currentVeh, (int)NeonLightLocations::NEON_LEFT, owned_mods[(int)CustomVehicleModType::MOD_NEON_LEFT_ON]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Right", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_NEON_RIGHT_ON])) + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_NEON_ENABLED(currentVeh, (int)NeonLightLocations::NEON_RIGHT, owned_mods[(int)CustomVehicleModType::MOD_NEON_RIGHT_ON]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Front", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_NEON_FRONT_ON])) + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_NEON_ENABLED(currentVeh, (int)NeonLightLocations::NEON_FRONT, owned_mods[(int)CustomVehicleModType::MOD_NEON_FRONT_ON]); + }); + ImGui::SameLine(); + if (ImGui::Checkbox("Back", (bool*)&owned_mods[(int)CustomVehicleModType::MOD_NEON_BACK_ON])) + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_NEON_ENABLED(currentVeh, (int)NeonLightLocations::NEON_BACK, owned_mods[(int)CustomVehicleModType::MOD_NEON_BACK_ON]); + }); + } + ImGui::SeparatorText("Color Options"); + { + static int color_to_change = 0; + static int color_type = 9; + + if ((color_to_change == 7 && !owned_mods[(int)VehicleModType::MOD_XENON_LIGHTS]) || (color_to_change == 5 && !owned_mods[(int)VehicleModType::MOD_TYRE_SMOKE])) + { + color_to_change = 0; + color_type = 9; + } + + if (ImGui::BeginListBox("##color_options", ImVec2(120, 254))) + { + if (ImGui::Selectable("Primary", color_to_change == 0)) + color_to_change = 0; + if (ImGui::Selectable("Secondary", color_to_change == 1)) + color_to_change = 1; + if (ImGui::Selectable("Pearlescent", color_to_change == 2)) + { + color_to_change = 2; + color_type = 7; + } + if (ImGui::Selectable("Interior", color_to_change == 3)) + { + color_to_change = 3; + color_type = 10; + } + if (ImGui::Selectable("Dashboard", color_to_change == 4)) + { + color_to_change = 4; + color_type = 11; + } + + if (!owned_mods[(int)VehicleModType::MOD_TYRE_SMOKE]) + ImGui::BeginDisabled(); + if (ImGui::Selectable("Tire Smoke", color_to_change == 5)) + { + color_to_change = 5; + color_type = 9; + } + if (!owned_mods[(int)VehicleModType::MOD_TYRE_SMOKE]) + ImGui::EndDisabled(); + + if (ImGui::Selectable("Wheel Color", color_to_change == 6)) + { + color_to_change = 6; + color_type = 8; + } + + if (!owned_mods[(int)VehicleModType::MOD_XENON_LIGHTS]) + ImGui::BeginDisabled(); + ImGui::PushID("##headlight_col"); + if (ImGui::Selectable("Headlight", color_to_change == 7)) + { + color_to_change = 7; + color_type = 12; + } + ImGui::PopID(); + if (!owned_mods[(int)VehicleModType::MOD_XENON_LIGHTS]) + ImGui::EndDisabled(); + + if (ImGui::Selectable("Neon", color_to_change == 8)) + { + color_to_change = 8; + color_type = 9; + } + + ImGui::EndListBox(); + } + + if (color_to_change == 0 || color_to_change == 1) + { + if (color_type > 6) + color_type = 9; + + // primary and secondary color + + ImGui::SameLine(); + if (ImGui::BeginListBox("##colors", ImVec2(140, 254))) + { + if (ImGui::Selectable("Custom", color_type == 9)) + color_type = 9; + + if (ImGui::Selectable("Remove Custom", false)) + FiberPool::Push([] { + if (color_to_change == 0) + VEHICLE::CLEAR_VEHICLE_CUSTOM_PRIMARY_COLOUR(currentVeh); + else + VEHICLE::CLEAR_VEHICLE_CUSTOM_SECONDARY_COLOUR(currentVeh); + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + + if (ImGui::Selectable("Chrome", color_type == 0)) + color_type = 0; + if (ImGui::Selectable("Classic", color_type == 1)) + color_type = 1; + if (ImGui::Selectable("Matte", color_type == 2)) + color_type = 2; + if (ImGui::Selectable("Metals", color_type == 3)) + color_type = 3; + if (ImGui::Selectable("Util", color_type == 4)) + color_type = 4; + if (ImGui::Selectable("Worn", color_type == 5)) + color_type = 5; + if (ImGui::Selectable("Chameleon", color_type == 6)) + color_type = 6; + + ImGui::EndListBox(); + } + } + else if (color_to_change == 7) + ImGui::SameLine(); + + // ********************************************************************************************************************************** + + if (color_type == 9) + { + // custom color + + static float color[3] = {1, 1, 1}; + auto color_r = &owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL_R]; + auto color_g = &owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL_G]; + auto color_b = &owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL_B]; + + if (color_to_change == 1) + { + color_r = &owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL_R]; + color_g = &owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL_G]; + color_b = &owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL_B]; + } + else if (color_to_change == 2) + { + color_r = &owned_mods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_R]; + color_g = &owned_mods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_G]; + color_b = &owned_mods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_B]; + } + else if (color_to_change == 3) + { + color_r = &owned_mods[(int)CustomVehicleModType::MOD_NEON_COL_R]; + color_g = &owned_mods[(int)CustomVehicleModType::MOD_NEON_COL_G]; + color_b = &owned_mods[(int)CustomVehicleModType::MOD_NEON_COL_B]; + } + + color[0] = (float)*color_r / 255; + color[1] = (float)*color_g / 255; + color[2] = (float)*color_b / 255; + + if (color_to_change == 5) + { + ImGui::SameLine(); + if (ImGui::BeginListBox("##tire_smoke_rgb", ImVec2(140, 254))) + { + for (const auto& it : lscTireSmokeRgb) + { + auto& name = it.first; + auto& rgb = it.second; + + if (ImGui::Selectable(name.c_str(), false)) + { + FiberPool::Push([&rgb] { + VEHICLE::SET_VEHICLE_TYRE_SMOKE_COLOR(currentVeh, rgb[0], rgb[1], rgb[2]); + }); + *color_r = rgb[0]; + *color_g = rgb[1]; + *color_b = rgb[2]; + } + } + + ImGui::EndListBox(); + } + } + else if (color_to_change == 8) + { + ImGui::SameLine(); + if (ImGui::BeginListBox("##neon_rgb", ImVec2(140, 254))) + { + for (const auto& it : lscNeonRgb) + { + auto& name = it.first; + auto& rgb = it.second; + + if (ImGui::Selectable(name.c_str(), false)) + { + FiberPool::Push([&rgb] { + VEHICLE::SET_VEHICLE_NEON_COLOUR(currentVeh, rgb[0], rgb[1], rgb[2]); + }); + *color_r = rgb[0]; + *color_g = rgb[1]; + *color_b = rgb[2]; + } + } + + ImGui::EndListBox(); + } + } + + ImGui::SameLine(); + ImGui::SetNextItemWidth(214); + if (ImGui::ColorPicker3("Custom Vehicle Color", color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex)) + { + *color_r = (int)(color[0] * 255); + *color_g = (int)(color[1] * 255); + *color_b = (int)(color[2] * 255); + + FiberPool::Push([color_r, color_g, color_b] { + switch (color_to_change) + { + case 0: + VEHICLE::SET_VEHICLE_CUSTOM_PRIMARY_COLOUR(currentVeh, *color_r, *color_g, *color_b); + break; + case 1: + VEHICLE::SET_VEHICLE_CUSTOM_SECONDARY_COLOUR(currentVeh, *color_r, *color_g, *color_b); + break; + case 5: + VEHICLE::SET_VEHICLE_TYRE_SMOKE_COLOR(currentVeh, *color_r, *color_g, *color_b); + break; + case 8: + VEHICLE::SET_VEHICLE_NEON_COLOUR(currentVeh, *color_r, *color_g, *color_b); + break; + } + }); + } + } + else + { + // standard color + + int selected_color = 0; + switch (color_type) + { + case 7: selected_color = owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL]; break; + case 8: selected_color = owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL]; break; + case 10: selected_color = owned_mods[(int)CustomVehicleModType::MOD_INTERIOR_COL]; break; + case 11: selected_color = owned_mods[(int)CustomVehicleModType::MOD_DASHBOARD_COL]; break; + case 12: selected_color = owned_mods[(int)CustomVehicleModType::MOD_XENON_COL]; break; + default: + selected_color = (color_to_change == 0) ? owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] : owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]; + } + + if (color_type != 12) + ImGui::SameLine(); + + if (ImGui::BeginListBox("##color", ImVec2(180, 254))) + { + switch (color_type) + { + case 0: //Chrome + { + if (ImGui::Selectable("Chrome", selected_color == (int)VehicleColorsChrome::COLOR_CHROME)) + { + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = (int)VehicleColorsChrome::COLOR_CHROME; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = (int)VehicleColorsChrome::COLOR_CHROME; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + break; + } + case 1: //Classic + { + for (const auto& [color, name] : lscClassicColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 2: //Matte + { + for (const auto& [color, name] : lscMatteColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 3: //Metals + { + for (const auto& [color, name] : lscMetalColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 4: //Util + { + for (const auto& [color, name] : lscUtilColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 5: //Worn + { + for (const auto& [color, name] : lscWornColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 6: //Chameleon + { + for (const auto& [color, name] : lscChameleonColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + if (color_to_change == 0) + owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL] = color; + else + owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PRIMARY_COL], owned_mods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + }); + } + } + break; + } + case 7: //Pearlescent + { + for (const auto& [color, name] : lscClassicColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL], owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL]); + }); + } + } + break; + } + case 8: //Wheel Color + { + constexpr auto alloy_color = 156; + + if (ImGui::Selectable("Alloy", selected_color == alloy_color)) + { + selected_color = alloy_color; + owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL] = alloy_color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL], owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL]); + }); + } + + for (const auto& [color, name] : lscClassicColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL], owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL]); + }); + } + } + + for (const auto& [color, name] : lscChameleonColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL], owned_mods[(int)CustomVehicleModType::MOD_WHEEL_COL]); + }); + } + } + + break; + } + case 10: //Interior Color + { + for (const auto& [color, name] : lscClassicColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_INTERIOR_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOUR_5(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_INTERIOR_COL]); + }); + } + } + break; + } + case 11: //Dashboard Color + { + for (const auto& [color, name] : lscClassicColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_DASHBOARD_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_EXTRA_COLOUR_6(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_DASHBOARD_COL]); + }); + } + } + break; + } + case 12: //Headlight Color + { + for (const auto& [color, name] : lscHeadlightColors) + { + if (ImGui::Selectable(name.c_str(), selected_color == color)) + { + selected_color = color; + owned_mods[(int)CustomVehicleModType::MOD_XENON_COL] = color; + FiberPool::Push([] { + VEHICLE::SET_VEHICLE_XENON_LIGHT_COLOR_INDEX(currentVeh, owned_mods[(int)CustomVehicleModType::MOD_XENON_COL]); + }); + } + } + break; + } + } + + ImGui::EndListBox(); + } + } + } + } + ImGui::EndGroup(); + })); + + return vehicleEditor; + } +} diff --git a/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.hpp b/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.hpp new file mode 100644 index 0000000..c7d0f51 --- /dev/null +++ b/src/game/frontend/submenus/Vehicle/VehicleEditorCategory.hpp @@ -0,0 +1,7 @@ +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr VehicleEditorCategory(); +} \ No newline at end of file diff --git a/src/game/gta/Vehicle.cpp b/src/game/gta/Vehicle.cpp index a99c35e..dec6ace 100644 --- a/src/game/gta/Vehicle.cpp +++ b/src/game/gta/Vehicle.cpp @@ -3,6 +3,7 @@ #include "core/backend/ScriptMgr.hpp" #include "game/pointers/Pointers.hpp" #include "game/gta/data/VehicleValues.hpp" +#include "game/gta/data/vehicles.hpp" namespace YimMenu { @@ -145,4 +146,91 @@ namespace YimMenu VEHICLE::SET_ROCKET_BOOST_FILL(GetHandle(), percentage); } + + std::string Vehicle::GetVehicleFullname() + { + auto model = ENTITY::GET_ENTITY_MODEL(GetHandle()); + std::string gxt = VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(model); + std::string display = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(gxt.c_str()); + + std::string finalName = display == "NULL" ? gxt : display; + + std::string maker = HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(VEHICLE::GET_MAKE_NAME_FROM_VEHICLE_MODEL(model)); + if (maker != "NULL") + finalName = maker + " " + finalName; + + int id = VEHICLE::GET_VEHICLE_CLASS_FROM_NAME(model); + finalName = std::string(g_VehicleClassNames[id]) + " " + finalName; + + return finalName; + } + + std::map Vehicle::GetOwnedMods() + { + auto vehicle = GetHandle(); + std::map ownedMods; + + for (int i = (int)CustomVehicleModType::MOD_SECONDARY_CUSTOM; i <= (int)CustomVehicleModType::MOD_MODEL_HASH; i++) + { + ownedMods[i] = 0; + } + + ownedMods[(int)CustomVehicleModType::MOD_MODEL_HASH] = ENTITY::GET_ENTITY_MODEL(vehicle); + + ownedMods[(int)CustomVehicleModType::MOD_PLATE_STYLE] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle); + ownedMods[(int)CustomVehicleModType::MOD_WINDOW_TINT] = VEHICLE::GET_VEHICLE_WINDOW_TINT(vehicle); + ownedMods[(int)CustomVehicleModType::MOD_WHEEL_TYPE] = VEHICLE::GET_VEHICLE_WHEEL_TYPE(vehicle); + + VEHICLE::GET_VEHICLE_COLOURS(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_COL], &ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_COL]); + VEHICLE::GET_VEHICLE_EXTRA_COLOURS(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_PEARLESCENT_COL], &ownedMods[(int)CustomVehicleModType::MOD_WHEEL_COL]); + VEHICLE::GET_VEHICLE_EXTRA_COLOUR_5(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_INTERIOR_COL]); + VEHICLE::GET_VEHICLE_EXTRA_COLOUR_6(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_DASHBOARD_COL]); + + ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_CUSTOM] = VEHICLE::GET_IS_VEHICLE_PRIMARY_COLOUR_CUSTOM(vehicle); + if (ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_CUSTOM]) + { + VEHICLE::GET_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_COL_R], &ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_COL_G], &ownedMods[(int)CustomVehicleModType::MOD_PRIMARY_COL_B]); + } + + ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_CUSTOM] = VEHICLE::GET_IS_VEHICLE_SECONDARY_COLOUR_CUSTOM(vehicle); + if (ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_CUSTOM]) + { + VEHICLE::GET_VEHICLE_CUSTOM_SECONDARY_COLOUR(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_COL_R], &ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_COL_G], &ownedMods[(int)CustomVehicleModType::MOD_SECONDARY_COL_B]); + } + + ownedMods[(int)VehicleModType::MOD_TYRE_SMOKE] = VEHICLE::IS_TOGGLE_MOD_ON(vehicle, (int)VehicleModType::MOD_TYRE_SMOKE); + if (ownedMods[(int)VehicleModType::MOD_TYRE_SMOKE]) + { + VEHICLE::GET_VEHICLE_TYRE_SMOKE_COLOR(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_R], &ownedMods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_G], &ownedMods[(int)CustomVehicleModType::MOD_TIRESMOKE_COL_B]); + } + + ownedMods[(int)VehicleModType::MOD_XENON_LIGHTS] = VEHICLE::IS_TOGGLE_MOD_ON(vehicle, (int)VehicleModType::MOD_XENON_LIGHTS); + if (ownedMods[(int)VehicleModType::MOD_XENON_LIGHTS]) + { + ownedMods[(int)CustomVehicleModType::MOD_XENON_COL] = (int8_t)VEHICLE::GET_VEHICLE_XENON_LIGHT_COLOR_INDEX(vehicle); + } + + ownedMods[(int)CustomVehicleModType::MOD_NEON_LEFT_ON] = VEHICLE::GET_VEHICLE_NEON_ENABLED(vehicle, (int)NeonLightLocations::NEON_LEFT); + ownedMods[(int)CustomVehicleModType::MOD_NEON_RIGHT_ON] = VEHICLE::GET_VEHICLE_NEON_ENABLED(vehicle, (int)NeonLightLocations::NEON_RIGHT); + ownedMods[(int)CustomVehicleModType::MOD_NEON_FRONT_ON] = VEHICLE::GET_VEHICLE_NEON_ENABLED(vehicle, (int)NeonLightLocations::NEON_FRONT); + ownedMods[(int)CustomVehicleModType::MOD_NEON_BACK_ON] = VEHICLE::GET_VEHICLE_NEON_ENABLED(vehicle, (int)NeonLightLocations::NEON_BACK); + VEHICLE::GET_VEHICLE_NEON_COLOUR(vehicle, &ownedMods[(int)CustomVehicleModType::MOD_NEON_COL_R], &ownedMods[(int)CustomVehicleModType::MOD_NEON_COL_G], &ownedMods[(int)CustomVehicleModType::MOD_NEON_COL_B]); + + ownedMods[(int)CustomVehicleModType::MOD_TIRE_CAN_BURST] = VEHICLE::GET_VEHICLE_TYRES_CAN_BURST(vehicle); + ownedMods[(int)CustomVehicleModType::MOD_DRIFT_TIRE] = VEHICLE::GET_DRIFT_TYRES_SET(vehicle); + ownedMods[(int)VehicleModType::MOD_TURBO] = VEHICLE::IS_TOGGLE_MOD_ON(vehicle, (int)VehicleModType::MOD_TURBO); + + ownedMods[(int)CustomVehicleModType::MOD_FRONTWHEEL_VAR] = VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, (int)VehicleModType::MOD_FRONTWHEEL); + ownedMods[(int)CustomVehicleModType::MOD_REARWHEEL_VAR] = VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, (int)VehicleModType::MOD_REARWHEEL); + + for (int slot = (int)VehicleModType::MOD_SPOILERS; slot <= (int)VehicleModType::MOD_LIGHTBAR; slot++) + if (VEHICLE::GET_NUM_VEHICLE_MODS(vehicle, slot) > 0) + ownedMods[slot] = VEHICLE::GET_VEHICLE_MOD(vehicle, slot); + + for (int extra = (int)CustomVehicleModType::MOD_EXTRA_14; extra <= (int)CustomVehicleModType::MOD_EXTRA_1; ++extra) + if (auto id = (extra - (int)CustomVehicleModType::MOD_EXTRA_1) * -1; VEHICLE::DOES_EXTRA_EXIST(vehicle, id)) + ownedMods[extra] = VEHICLE::IS_VEHICLE_EXTRA_TURNED_ON(vehicle, id); + + return ownedMods; + } } \ No newline at end of file diff --git a/src/game/gta/Vehicle.hpp b/src/game/gta/Vehicle.hpp index a288e5b..16e901a 100644 --- a/src/game/gta/Vehicle.hpp +++ b/src/game/gta/Vehicle.hpp @@ -22,6 +22,7 @@ namespace YimMenu // mods void Upgrade(); void SetPlateText(std::string_view text); + std::map GetOwnedMods(); // seats bool IsSeatFree(int seat); @@ -30,5 +31,7 @@ namespace YimMenu bool SupportsBoost(); bool IsBoostActive(); void SetBoostCharge(int percentage = 100); + + std::string GetVehicleFullname(); }; } \ No newline at end of file diff --git a/src/game/gta/data/VehicleValues.hpp b/src/game/gta/data/VehicleValues.hpp index 9677756..5441c99 100644 --- a/src/game/gta/data/VehicleValues.hpp +++ b/src/game/gta/data/VehicleValues.hpp @@ -629,6 +629,72 @@ enum class VehicleColorsClassic COLOR_CLASSIC_SECRET_GOLD = 160 }; +enum class VehicleColorsChameleon +{ + ANOD_RED = 161, + ANOD_WINE = 162, + ANOD_PURPLE = 163, + ANOD_BLUE = 164, + ANOD_GREEN = 165, + ANOD_LIME = 166, + ANOD_COPPER = 167, + ANOD_BRONZE = 168, + ANOD_CHAMPAGNE = 169, + ANOD_GOLD = 170, + GREEN_BLUE_FLIP = 171, + GREEN_RED_FLIP = 172, + GREEN_BROW_FLIP = 173, + GREEN_TURQ_FLIP = 174, + GREEN_PURP_FLIP = 175, + TEAL_PURP_FLIP = 176, + TURQ_RED_FLIP = 177, + TURQ_PURP_FLIP = 178, + CYAN_PURP_FLIP = 179, + BLUE_PINK_FLIP = 180, + BLUE_GREEN_FLIP = 181, + PURP_RED_FLIP = 182, + PURP_GREEN_FLIP = 183, + MAGEN_GREE_FLIP = 184, + MAGEN_YELL_FLIP = 185, + BURG_GREEN_FLIP = 186, + MAGEN_CYAN_FLIP = 187, + COPPE_PURP_FLIP = 188, + MAGEN_ORAN_FLIP = 189, + RED_ORANGE_FLIP = 190, + ORANG_PURP_FLIP = 191, + ORANG_BLUE_FLIP = 192, + WHITE_PURP_FLIP = 193, + RED_RAINBO_FLIP = 194, + BLU_RAINBO_FLIP = 195, + DARKGREENPEARL = 196, + DARKTEALPEARL = 197, + DARKBLUEPEARL = 198, + DARKPURPLEPEARL = 199, + OIL_SLICK_PEARL = 200, + LIT_GREEN_PEARL = 201, + LIT_BLUE_PEARL = 202, + LIT_PURP_PEARL = 203, + LIT_PINK_PEARL = 204, + OFFWHITE_PRISMA = 205, + PINK_PEARL = 206, + YELLOW_PEARL = 207, + GREEN_PEARL = 208, + BLUE_PEARL = 209, + CREAM_PEARL = 210, + WHITE_PRISMA = 211, + GRAPHITE_PRISMA = 212, + DARKBLUEPRISMA = 213, + DARKPURPPRISMA = 214, + HOT_PINK_PRISMA = 215, + RED_PRISMA = 216, + GREEN_PRISMA = 217, + BLACK_PRISMA = 218, + OIL_SLIC_PRISMA = 219, + RAINBOW_PRISMA = 220, + BLACK_HOLO = 221, + WHITE_HOLO = 222 +}; + enum class VehicleColorsMatte { COLOR_MATTE_BLACK = 12, diff --git a/src/game/gta/data/lscTypes.hpp b/src/game/gta/data/lscTypes.hpp new file mode 100644 index 0000000..4fb4bbd --- /dev/null +++ b/src/game/gta/data/lscTypes.hpp @@ -0,0 +1,344 @@ +#pragma once +#include "VehicleValues.hpp" + +inline const std::map lscPlateStyles = { + {(int)PlateTextIndexs::PLATE_BLUEONWHITE1, "Blue on White 1"}, + {(int)PlateTextIndexs::PLATE_YELLOWONBLACK, "Yellow on Black"}, + {(int)PlateTextIndexs::PLATE_YELLOWONBLUE, "Yellow on Blue"}, + {(int)PlateTextIndexs::PLATE_BLUEONWHITE2, "Blue on White 2"}, + {(int)PlateTextIndexs::PLATE_BLUEONWHITE3, "Blue on White 3"}, + {(int)PlateTextIndexs::PLATE_YANKTON, "Yankton"}, + {(int)PlateTextIndexs::PLATE_ECOLA, "Ecola"}, + {(int)PlateTextIndexs::PLATE_LASVENTURAS, "Las Venturas"}, + {(int)PlateTextIndexs::PLATE_LIBERTYCITY, "Liberty City"}, + {(int)PlateTextIndexs::PLATE_LOSSANTOSCARMEET, "Los Santos Car Meet"}, + {(int)PlateTextIndexs::PLATE_LOSSANTOSPANIC, "Los Santos Panicc"}, + {(int)PlateTextIndexs::PLATE_LOSSANTOSPOUNDERS, "Los Santos Pounders"}, + {(int)PlateTextIndexs::PLATE_SPRUNK, "Sprunk"}, +}; + +inline const std::map lscWheelStyles = { + {(int)WheelTypes::WHEEL_TYPE_SPORT, "Sport"}, + {(int)WheelTypes::WHEEL_TYPE_MUSCLE, "Muscle"}, + {(int)WheelTypes::WHEEL_TYPE_LOWRIDER, "Lowrider"}, + {(int)WheelTypes::WHEEL_TYPE_SUV, "SUV"}, + {(int)WheelTypes::WHEEL_TYPE_OFFROAD, "Offroad"}, + {(int)WheelTypes::WHEEL_TYPE_TUNER, "Tuner"}, + {(int)WheelTypes::WHEEL_TYPE_BIKEWHEELS, "Bike Wheels"}, + {(int)WheelTypes::WHEEL_TYPE_HIGHEND, "High End"}, + {(int)WheelTypes::WHEEL_TYPE_BENNYS_ORIGINAL, "Bennys Original"}, + {(int)WheelTypes::WHEEL_TYPE_BENNYS_BESPOKE, "Bennys Bespoke"}, + {(int)WheelTypes::WHEEL_TYPE_OPEN_WHEEL, "Open Wheel"}, + {(int)WheelTypes::WHEEL_TYPE_STREET, "Street"}, + {(int)WheelTypes::WHEEL_TYPE_TRACK, "Track"}, +}; + +inline const std::map lscWindowTintTypes = { + {(int)WindowTints::WINDOWTINT_NONE, "None"}, + {(int)WindowTints::WINDOWTINT_BLACK, "Black"}, + {(int)WindowTints::WINDOWTINT_DARKSMOKE, "Dark"}, + {(int)WindowTints::WINDOWTINT_LIGHTSMOKE, "Light"}, + {(int)WindowTints::WINDOWTINT_STOCK, "Stock"}, + {(int)WindowTints::WINDOWTINT_LIMO, "Limo"}, + {(int)WindowTints::WINDOWTINT_GREEN, "Green"}, +}; + +inline const std::map lscClassicColors = { + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLACK, "Black"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CARBON_BLACK, "Carbon Black"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GRAPHITE, "Graphite"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_ANTHRACITE_BLACK, "Anthracite Black"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLACK_STEEL, "Black Steel"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DARK_STEEL, "Dark Steel"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SILVER, "Silver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLUISH_SILVER, "Bluish Silver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_ROLLED_STEEL, "Rolled Steel"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SHADOW_SILVER, "Shadow SIlver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_STONE_SILVER, "Stone Silver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MIDNIGHT_SILVER, "Midnight Silver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CAST_IRON_SILVER, "Cast Iron Silver"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_RED, "Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_TORINO_RED, "Torino Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_FORMULA_RED, "Formula Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_LAVA_RED, "Lava Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLAZE_RED, "Blaze Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GRACE_RED, "Grace Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GARNET_RED, "Garnet Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SUNSET_RED, "Sunset Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CABERNET_RED, "Cabernet Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_WINE_RED, "Wine Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CANDY_RED, "Candy Red"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_HOT_PINK, "Hot Pink"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_PFSITER_PINK, "Pfister Pink"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SALMON_PINK, "Salmon Pink"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SUNRISE_ORANGE, "Sunrise Orange"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_ORANGE, "Orange"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BRIGHT_ORANGE, "Bright Orange"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GOLD, "Gold"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BRONZE, "Bronze"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_YELLOW, "Yellow"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_RACE_YELLOW, "Race Yellow"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DEW_YELLOW, "Dew Yellow"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DARK_GREEN, "Dark Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_RACING_GREEN, "Racing Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SEA_GREEN, "Sea Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_OLIVE_GREEN, "Olive Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BRIGHT_GREEN, "Bright Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GASOLINE_GREEN, "Gasoline Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_LIME_GREEN, "Lime Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MIDNIGHT_BLUE, "Midnight Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GALAXY_BLUE, "Galaxy Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DARK_BLUE, "Dark Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SAXON_BLUE, "Saxon Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLUE, "Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MARINER_BLUE, "Mariner Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_HARBOR_BLUE, "Harbor Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DIAMOND_BLUE, "Diamond Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SURF_BLUE, "Surf Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_NAUTICAL_BLUE, "Nautical Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_RACING_BLUE, "Racing Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_ULTRA_BLUE, "Ultra Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_LIGHT_BLUE, "Light Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CHOCOLATE_BROWN, "Chocolate Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BISON_BROWN, "Bison Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CREEK_BROWN, "Creek Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_FELTZER_BROWN, "Feltzer Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MAPLE_BROWN, "Maple Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BEECHWOOD_BROWN, "Beechwood Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SIENNA_BROWN, "Sienna Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SADDLE_BROWN, "Saddle Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MOSS_BROWN, "Moss Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_WOODBEECH_BROWN, "Woodbeech Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_STRAW_BROWN, "Straw Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SANDY_BROWN, "Sandy Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BLEACHED_BROWN, "Bleached Brown"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SCHAFTER_PURPLE, "Schafter Purple"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SPINNAKER_PURPLE, "Spinnaker Purple"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_MIDNIGHT_PURPLE, "Midnight Purple"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_BRIGHT_PURPLE, "Bright Purple"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CREAM, "Cream"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_ICE_WHITE, "Ice White"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_FROST_WHITE, "Frost White"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CLASSIC_GOLD, "Classic Gold"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_GREEN, "Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_HUNTER_GREEN, "Hunter Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SECURICOR_GREEN, "Securicor Green"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_EPSILON_BLUE, "Epsilon Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_FLOURESCENT_BLUE, "Flourescent Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_V_DARK_BLUE, "V Dark Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_POLICE_BLUE, "Police Blue"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_CHAMPAGNE, "Champagne"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_PURE_WHITE, "Pure White"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_DEFAULT_ALLOY, "Default Alloy"}, + {(int)VehicleColorsClassic::COLOR_CLASSIC_SECRET_GOLD, "Secret Gold"}, +}; + +inline const std::map lscMatteColors = { + {(int)VehicleColorsMatte::COLOR_MATTE_BLACK, "Black"}, + {(int)VehicleColorsMatte::COLOR_MATTE_GRAY, "Gray"}, + {(int)VehicleColorsMatte::COLOR_MATTE_LIGHT_GRAY, "Light Gray"}, + {(int)VehicleColorsMatte::COLOR_MATTE_ICE_WHITE, "Ice White"}, + {(int)VehicleColorsMatte::COLOR_MATTE_BLUE, "Blue"}, + {(int)VehicleColorsMatte::COLOR_MATTE_DARK_BLUE, "Dark Blue"}, + {(int)VehicleColorsMatte::COLOR_MATTE_MIDNIGHT_BLUE, "Midnight Blue"}, + {(int)VehicleColorsMatte::COLOR_MATTE_MIDNIGHT_PURPLE, "Midnight Purple"}, + {(int)VehicleColorsMatte::COLOR_MATTE_SCHAFTER_PURPLE, "Shafter Purple"}, + {(int)VehicleColorsMatte::COLOR_MATTE_RED, "Red"}, + {(int)VehicleColorsMatte::COLOR_MATTE_DARK_RED, "Dark Red"}, + {(int)VehicleColorsMatte::COLOR_MATTE_ORANGE, "Orange"}, + {(int)VehicleColorsMatte::COLOR_MATTE_YELLOW, "Yellow"}, + {(int)VehicleColorsMatte::COLOR_MATTE_LIME_GREEN, "Lime Green"}, + {(int)VehicleColorsMatte::COLOR_MATTE_GREEN, "Green"}, + {(int)VehicleColorsMatte::COLOR_MATTE_FOREST_GREEN, "Forest Green"}, + {(int)VehicleColorsMatte::COLOR_MATTE_FOLIAGE_GREEN, "Foliage Green"}, + {(int)VehicleColorsMatte::COLOR_MATTE_OLIVE_DRAB, "Olive Drab"}, + {(int)VehicleColorsMatte::COLOR_MATTE_DARK_EARTH, "Dark Earth"}, + {(int)VehicleColorsMatte::COLOR_MATTE_DESERT_TAN, "Desert Tan"}, + {(int)VehicleColorsMatte::COLOR_MATTE_BROWN, "Brown"}, +}; + +inline const std::map lscChameleonColors = { + {(int)VehicleColorsChameleon::ANOD_RED , "Anodized Red"}, + {(int)VehicleColorsChameleon::ANOD_WINE , "Anodized Wine"}, + {(int)VehicleColorsChameleon::ANOD_PURPLE , "Anodized Purple"}, + {(int)VehicleColorsChameleon::ANOD_BLUE , "Anodized Blue"}, + {(int)VehicleColorsChameleon::ANOD_GREEN , "Anodized Green"}, + {(int)VehicleColorsChameleon::ANOD_LIME , "Anodized Lime"}, + {(int)VehicleColorsChameleon::ANOD_COPPER , "Anodized Copper"}, + {(int)VehicleColorsChameleon::ANOD_BRONZE , "Anodized Bronze"}, + {(int)VehicleColorsChameleon::ANOD_CHAMPAGNE , "Anodized Champagne"}, + {(int)VehicleColorsChameleon::ANOD_GOLD , "Anodized Gold"}, + {(int)VehicleColorsChameleon::GREEN_BLUE_FLIP , "Green Blue Flip"}, + {(int)VehicleColorsChameleon::GREEN_RED_FLIP , "Green Red Flip"}, + {(int)VehicleColorsChameleon::GREEN_BROW_FLIP , "Green Brown Flip"}, + {(int)VehicleColorsChameleon::GREEN_TURQ_FLIP , "Green Turqoise Flip"}, + {(int)VehicleColorsChameleon::GREEN_PURP_FLIP , "Green Purple Flip"}, + {(int)VehicleColorsChameleon::TEAL_PURP_FLIP , "Teal Purple Flip"}, + {(int)VehicleColorsChameleon::TURQ_RED_FLIP , "Turqoise Red Flip"}, + {(int)VehicleColorsChameleon::TURQ_PURP_FLIP , "Turquoise Purple Flip"}, + {(int)VehicleColorsChameleon::CYAN_PURP_FLIP , "Cyan Purple Flip"}, + {(int)VehicleColorsChameleon::BLUE_PINK_FLIP , "Blue Pink Flip"}, + {(int)VehicleColorsChameleon::BLUE_GREEN_FLIP , "Blue Green Flip"}, + {(int)VehicleColorsChameleon::PURP_RED_FLIP , "Purple Red Flip"}, + {(int)VehicleColorsChameleon::PURP_GREEN_FLIP , "Purple Green Flip"}, + {(int)VehicleColorsChameleon::MAGEN_GREE_FLIP , "Magenta Green Flip"}, + {(int)VehicleColorsChameleon::MAGEN_YELL_FLIP , "Magenta Yellow Flip"}, + {(int)VehicleColorsChameleon::BURG_GREEN_FLIP , "Burgundy Green Flip"}, + {(int)VehicleColorsChameleon::MAGEN_CYAN_FLIP , "Magenta Cyan Flip"}, + {(int)VehicleColorsChameleon::COPPE_PURP_FLIP , "Copper Purple Flip"}, + {(int)VehicleColorsChameleon::MAGEN_ORAN_FLIP , "Magenta Orange Flip"}, + {(int)VehicleColorsChameleon::RED_ORANGE_FLIP , "Red Orange Flip"}, + {(int)VehicleColorsChameleon::ORANG_PURP_FLIP , "Orange Purple Flip"}, + {(int)VehicleColorsChameleon::ORANG_BLUE_FLIP , "Orange Blue Flip"}, + {(int)VehicleColorsChameleon::WHITE_PURP_FLIP , "White Purple Flip"}, + {(int)VehicleColorsChameleon::RED_RAINBO_FLIP , "Red Rainbow Flip"}, + {(int)VehicleColorsChameleon::BLU_RAINBO_FLIP , "Blue Rainbow Flip"}, + {(int)VehicleColorsChameleon::DARKGREENPEARL , "Dark Green Pearl"}, + {(int)VehicleColorsChameleon::DARKTEALPEARL , "Dark Teal Pearl"}, + {(int)VehicleColorsChameleon::DARKBLUEPEARL , "Dark Blue Pearl"}, + {(int)VehicleColorsChameleon::DARKPURPLEPEARL , "Dark Purple Pearl"}, + {(int)VehicleColorsChameleon::OIL_SLICK_PEARL , "Oil Slick Pearl"}, + {(int)VehicleColorsChameleon::LIT_GREEN_PEARL , "Light Green Pearl"}, + {(int)VehicleColorsChameleon::LIT_BLUE_PEARL , "Light Blue Pearl"}, + {(int)VehicleColorsChameleon::LIT_PURP_PEARL , "Light Purple Pearl"}, + {(int)VehicleColorsChameleon::LIT_PINK_PEARL , "Light Pink Pearl"}, + {(int)VehicleColorsChameleon::OFFWHITE_PRISMA , "Off White Pearl"}, + {(int)VehicleColorsChameleon::PINK_PEARL , "Pink Pearl"}, + {(int)VehicleColorsChameleon::YELLOW_PEARL , "Yellow Pearl"}, + {(int)VehicleColorsChameleon::GREEN_PEARL , "Green Pearl"}, + {(int)VehicleColorsChameleon::BLUE_PEARL , "Blue Pearl"}, + {(int)VehicleColorsChameleon::CREAM_PEARL , "Cream Pearl"}, + {(int)VehicleColorsChameleon::WHITE_PRISMA , "White Prismatic"}, + {(int)VehicleColorsChameleon::GRAPHITE_PRISMA , "Graphite Prismatic"}, + {(int)VehicleColorsChameleon::DARKBLUEPRISMA , "Dark Blue Prismatic"}, + {(int)VehicleColorsChameleon::DARKPURPPRISMA , "Dark Purple Prismatic"}, + {(int)VehicleColorsChameleon::HOT_PINK_PRISMA , "Hot Pink Prismatic"}, + {(int)VehicleColorsChameleon::RED_PRISMA , "Dark Red Prismatic"}, + {(int)VehicleColorsChameleon::GREEN_PRISMA , "Dark Green Prismatic"}, + {(int)VehicleColorsChameleon::BLACK_PRISMA , "Black Prismatic"}, + {(int)VehicleColorsChameleon::OIL_SLIC_PRISMA , "Black Oil Spill"}, + {(int)VehicleColorsChameleon::RAINBOW_PRISMA , "Black Rainbow"}, + {(int)VehicleColorsChameleon::BLACK_HOLO , "Black Holographic"}, + {(int)VehicleColorsChameleon::WHITE_HOLO , "White Holographic"}, +}; + +inline const std::map lscMetalColors = { + {(int)VehicleColorsMetals::COLOR_METALS_BRUSHED_STEEL, "Brushed Steel"}, + {(int)VehicleColorsMetals::COLOR_METALS_BRUSHED_BLACK_STEEL, "Brushed Black Steel"}, + {(int)VehicleColorsMetals::COLOR_METALS_BRUSHED_ALUMINUM, "Brushed Aluminium"}, + {(int)VehicleColorsMetals::COLOR_METALS_PURE_GOLD, "Pure Gold"}, + {(int)VehicleColorsMetals::COLOR_METALS_BRUSHED_GOLD, "Brushed Gold"}, +}; + +inline const std::map lscUtilColors = { + {(int)VehicleColorsUtil::COLOR_UTIL_BLACK, "Black"}, + {(int)VehicleColorsUtil::COLOR_UTIL_BLACK_POLY, "Black Poly"}, + {(int)VehicleColorsUtil::COLOR_UTIL_DARK_SILVER, "Dark Silver"}, + {(int)VehicleColorsUtil::COLOR_UTIL_SILVER, "Silver"}, + {(int)VehicleColorsUtil::COLOR_UTIL_GUN_METAL, "Gun Metal"}, + {(int)VehicleColorsUtil::COLOR_UTIL_SHADOW_SILVER, "Shadow Silver"}, + {(int)VehicleColorsUtil::COLOR_UTIL_RED, "Red"}, + {(int)VehicleColorsUtil::COLOR_UTIL_BRIGHT_RED, "Bright Red"}, + {(int)VehicleColorsUtil::COLOR_UTIL_GARNET_RED, "Garnet Red"}, + {(int)VehicleColorsUtil::COLOR_UTIL_DARK_GREEN, "Dark Green"}, + {(int)VehicleColorsUtil::COLOR_UTIL_GREEN, "Green"}, + {(int)VehicleColorsUtil::COLOR_UTIL_DARK_BLUE, "Dark Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_MIDNIGHT_BLUE, "Midnight Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_BLUE, "Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_SEA_FOAM_BLUE, "Sea Foam Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_LIGHTNING_BLUE, "Lightning Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_MAUI_BLUE_POLY, "Maui Blue Poly"}, + {(int)VehicleColorsUtil::COLOR_UTIL_BRIGHT_BLUE, "Bright Blue"}, + {(int)VehicleColorsUtil::COLOR_UTIL_BROWN, "Brown"}, + {(int)VehicleColorsUtil::COLOR_UTIL_MEDIUM_BROWN, "Medium Brown"}, + {(int)VehicleColorsUtil::COLOR_UTIL_LIGHT_BROWN, "Light Brown"}, + {(int)VehicleColorsUtil::COLOR_UTIL_OFF_WHITE, "Off White"}, +}; + +inline const std::map lscWornColors = { + {(int)VehicleColorsWorn::COLOR_WORN_BLACK, "Black"}, + {(int)VehicleColorsWorn::COLOR_WORN_GRAPHITE, "Graphite"}, + {(int)VehicleColorsWorn::COLOR_WORN_SILVER_GREY, "Silver Grey"}, + {(int)VehicleColorsWorn::COLOR_WORN_SILVER, "Silver"}, + {(int)VehicleColorsWorn::COLOR_WORN_BLUE_SILVER, "Blue Silver"}, + {(int)VehicleColorsWorn::COLOR_WORN_SHADOW_SILVER, "Shadow Silver"}, + {(int)VehicleColorsWorn::COLOR_WORN_RED, "Red"}, + {(int)VehicleColorsWorn::COLOR_WORN_GOLDEN_RED, "Golden Red"}, + {(int)VehicleColorsWorn::COLOR_WORN_DARK_RED, "Dark Red"}, + {(int)VehicleColorsWorn::COLOR_WORN_DARK_GREEN, "Dark Green"}, + {(int)VehicleColorsWorn::COLOR_WORN_GREEN, "Green"}, + {(int)VehicleColorsWorn::COLOR_WORN_SEA_WASH, "Sea Wash"}, + {(int)VehicleColorsWorn::COLOR_WORN_DARK_BLUE, "Dark blue"}, + {(int)VehicleColorsWorn::COLOR_WORN_BLUE, "Blue"}, + {(int)VehicleColorsWorn::COLOR_WORN_BABY_BLUE, "Light blue"}, + {(int)VehicleColorsWorn::COLOR_WORN_HONEY_BEIGE, "Honey Beige"}, + {(int)VehicleColorsWorn::COLOR_WORN_BROWN, "Brown"}, + {(int)VehicleColorsWorn::COLOR_WORN_DARK_BROWN, "Dark Brown"}, + {(int)VehicleColorsWorn::COLOR_WORN_STRAW_BEIGE, "straw beige"}, + {(int)VehicleColorsWorn::COLOR_WORN_OFF_WHITE, "Off White"}, + {(int)VehicleColorsWorn::COLOR_WORN_ORANGE, "Orange"}, + {(int)VehicleColorsWorn::COLOR_WORN_LIGHT_ORANGE, "Light Orange"}, + {(int)VehicleColorsWorn::COLOR_WORN_TAXI_YELLOW, "Taxi Yellow"}, + {(int)VehicleColorsWorn::COLOR_WORN_PALE_ORANGE, "Pale Orange"}, + {(int)VehicleColorsWorn::COLOR_WORN_WHITE, "White"}, + {(int)VehicleColorsWorn::COLOR_WORN_OLIVE_ARMY_GREEN, "Olive Army Green"}, +}; + +inline const std::map lscHeadlightColors = { + {(int)HeadlightColors::XENON_DEFAULT, "Default"}, + {(int)HeadlightColors::XENON_WHITE, "White"}, + {(int)HeadlightColors::XENON_BLUE, "Blue"}, + {(int)HeadlightColors::XENON_ELECTRIC_BLUE, "Electric Blue"}, + {(int)HeadlightColors::XENON_MINT_GREEN, "Mint Green"}, + {(int)HeadlightColors::XENON_LIME_GREEN, "Lime Green"}, + {(int)HeadlightColors::XENON_YELLOW, "Yellow"}, + {(int)HeadlightColors::XENON_GOLDEN_SHOWER, "Golden Shower"}, + {(int)HeadlightColors::XENON_ORANGE, "Orange"}, + {(int)HeadlightColors::XENON_RED, "Red"}, + {(int)HeadlightColors::XENON_PONY_PINK, "Pony Pink"}, + {(int)HeadlightColors::XENON_HOT_PINK, "Hot Pink"}, + {(int)HeadlightColors::XENON_PURPLE, "Purple"}, + {(int)HeadlightColors::XENON_BLACKLIGHT, "Blacklight"}, +}; + +inline const std::map lscMissingHorns = { + {(int)VehicleModHorns::HORN_XMAS_BACKGROUND, "Festival Loop 1 Bg"}, + {(int)VehicleModHorns::HORN_XMAS2_BACKGROUND, "Festival Loop 2 Bg"}, + {(int)VehicleModHorns::HORN_XMAS3_BACKGROUND, "Festival Loop 3 Bg"}, + {(int)VehicleModHorns::HORN_LOW_LONG, "Low (Long)"}, + {(int)VehicleModHorns::HORN_LOW_SHORT, "Low (Short)"}, + {(int)VehicleModHorns::HORN_MID_LONG, "Mid (Long)"}, + {(int)VehicleModHorns::HORN_MID_SHORT, "Mid (Short)"}, + {(int)VehicleModHorns::HORN_HIGH_LONG, "High (Long)"}, + {(int)VehicleModHorns::HORN_HIGH_SHORT, "High (Short)"}, +}; + +inline const std::map> lscTireSmokeRgb = { + {"White", {TIRESMOKE_COLOR_WHITE}}, + {"Black", {TIRESMOKE_COLOR_BLACK}}, + {"Blue", {TIRESMOKE_COLOR_BLUE}}, + {"Yellow", {TIRESMOKE_COLOR_YELLOW}}, + {"Purple", {TIRESMOKE_COLOR_PURPLE}}, + {"Orange", {TIRESMOKE_COLOR_ORANGE}}, + {"Green", {TIRESMOKE_COLOR_GREEN}}, + {"Red", {TIRESMOKE_COLOR_RED}}, + {"Pink", {TIRESMOKE_COLOR_PINK}}, + {"Brown", {TIRESMOKE_COLOR_BROWN}}, + {"Patriot", {TIRESMOKE_COLOR_PATRIOT}}, +}; + +inline const std::map> lscNeonRgb = { + {"White", {NEON_COLOR_WHITE}}, + {"Blue", {NEON_COLOR_BLUE}}, + {"Electro Blue", {NEON_COLOR_ELECTRICBLUE}}, + {"Mint Green", {NEON_COLOR_MINTGREEN}}, + {"Lime Green", {NEON_COLOR_LIMEGREEN}}, + {"Yellow", {NEON_COLOR_YELLOW}}, + {"Golden Shower", {NEON_COLOR_GOLDENSHOWER}}, + {"Orange", {NEON_COLOR_ORANGE}}, + {"Red", {NEON_COLOR_RED}}, + {"Pony Pink", {NEON_COLOR_PONYPINK}}, + {"Hot Pink", {NEON_COLOR_HOTPINK}}, + {"Purple", {NEON_COLOR_PURPLE}}, + {"Blacklight", {NEON_COLOR_BLACKLIGHT}}, +};