From 49235195b52f764bf4baf30393d20df3ec2616f3 Mon Sep 17 00:00:00 2001 From: FireFox101889 <87771170+FireFox101889@users.noreply.github.com> Date: Wed, 10 May 2023 17:11:59 -0400 Subject: [PATCH] feat: Keep model dimension in mind when determining spawn location (#1316) --- src/backend/commands/spawn/spawn_vehicle.cpp | 95 +++--- src/util/vehicle.hpp | 7 +- src/views/vehicle/view_pv.cpp | 287 ++++++++--------- src/views/vehicle/view_spawn_vehicle.cpp | 311 ++++++++++--------- 4 files changed, 353 insertions(+), 347 deletions(-) diff --git a/src/backend/commands/spawn/spawn_vehicle.cpp b/src/backend/commands/spawn/spawn_vehicle.cpp index ae590204..315b36b8 100644 --- a/src/backend/commands/spawn/spawn_vehicle.cpp +++ b/src/backend/commands/spawn/spawn_vehicle.cpp @@ -6,58 +6,59 @@ namespace big { - class spawn_vehicle : command - { - using command::command; + class spawn_vehicle : command + { + using command::command; - virtual std::optional> parse_args(const std::vector& args, const std::shared_ptr ctx) - { - auto hash = rage::joaat(args[0]); - return std::vector{hash}; - } + virtual std::optional> parse_args(const std::vector& args, const std::shared_ptr ctx) + { + auto hash = rage::joaat(args[0]); + return std::vector{hash}; + } - virtual CommandAccessLevel get_access_level() - { - return CommandAccessLevel::FRIENDLY; - } + virtual CommandAccessLevel get_access_level() + { + return CommandAccessLevel::FRIENDLY; + } - virtual void execute(const std::vector& args, const std::shared_ptr ctx) - { - if (!STREAMING::IS_MODEL_IN_CDIMAGE(args[0]) || !STREAMING::IS_MODEL_A_VEHICLE(args[0])) - { - ctx->report_error("Specified model is invalid"); - return; - } + virtual void execute(const std::vector& args, const std::shared_ptr ctx) + { + if (!STREAMING::IS_MODEL_IN_CDIMAGE(args[0]) || !STREAMING::IS_MODEL_A_VEHICLE(args[0])) + { + ctx->report_error("Specified model is invalid"); + return; + } - const auto spawn_location = - vehicle::get_spawn_location(ctx->get_sender()->id() == self::id ? g.spawn_vehicle.spawn_inside : false, - PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(ctx->get_sender()->id())); - const auto spawn_heading = ENTITY::GET_ENTITY_HEADING(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(ctx->get_sender()->id())); + const auto spawn_location = + vehicle::get_spawn_location(ctx->get_sender()->id() == self::id ? g.spawn_vehicle.spawn_inside : false, + args[0], + PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(ctx->get_sender()->id())); + const auto spawn_heading = ENTITY::GET_ENTITY_HEADING(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(ctx->get_sender()->id())); - const auto veh = vehicle::spawn(args[0], spawn_location, spawn_heading); + const auto veh = vehicle::spawn(args[0], spawn_location, spawn_heading); - if (veh == 0) - { - g_notification_service->push_error("Vehicle", "Unable to spawn vehicle"); - } - else - { - if (g.spawn_vehicle.spawn_maxed) - { - vehicle::max_vehicle(veh); - } + if (veh == 0) + { + g_notification_service->push_error("Vehicle", "Unable to spawn vehicle"); + } + else + { + if (g.spawn_vehicle.spawn_maxed) + { + vehicle::max_vehicle(veh); + } - if (g.spawn_vehicle.spawn_inside && ctx->get_sender()->id() == self::id) - { - vehicle::teleport_into_vehicle(veh); - } - } - } - }; + if (g.spawn_vehicle.spawn_inside && ctx->get_sender()->id() == self::id) + { + vehicle::teleport_into_vehicle(veh); + } + } + } + }; - spawn_vehicle g_spawn_vehicle("spawn", "Spawn Vehicle", "Spawn a vehicle with the specified model", 1); - bool_command g_spawn_maxed("spawnmaxed", "Spawn Maxed", "Controls whether the vehicle spawned will have its mods maxed out", - g.spawn_vehicle.spawn_maxed); - bool_command g_spawn_inside("spawnin", "Spawn Inside", "Controls whether the player should be set inside the vehicle after it spawns", - g.spawn_vehicle.spawn_inside); -} \ No newline at end of file + spawn_vehicle g_spawn_vehicle("spawn", "Spawn Vehicle", "Spawn a vehicle with the specified model", 1); + bool_command g_spawn_maxed("spawnmaxed", "Spawn Maxed", "Controls whether the vehicle spawned will have its mods maxed out", + g.spawn_vehicle.spawn_maxed); + bool_command g_spawn_inside("spawnin", "Spawn Inside", "Controls whether the player should be set inside the vehicle after it spawns", + g.spawn_vehicle.spawn_inside); +} diff --git a/src/util/vehicle.hpp b/src/util/vehicle.hpp index 75f39bdc..517f28ce 100644 --- a/src/util/vehicle.hpp +++ b/src/util/vehicle.hpp @@ -40,13 +40,16 @@ namespace big::vehicle return speed; } - inline Vector3 get_spawn_location(bool spawn_inside, Ped ped = self::ped) + inline Vector3 get_spawn_location(bool spawn_inside, Hash hash, Ped ped = self::ped) { float y_offset = 0; if (self::veh != 0) { - y_offset = 10.f; + Vector3 min, max, result; + MISC::GET_MODEL_DIMENSIONS(hash, &min, &max); + result = max - min; + y_offset = result.y; } else if (!spawn_inside) { diff --git a/src/views/vehicle/view_pv.cpp b/src/views/vehicle/view_pv.cpp index 602ef76d..25553a10 100644 --- a/src/views/vehicle/view_pv.cpp +++ b/src/views/vehicle/view_pv.cpp @@ -8,174 +8,175 @@ namespace big { - void view::pv() - { - ImGui::SetWindowSize({0.f, (float)*g_pointers->m_gta.m_resolution_y}, ImGuiCond_Always); + void view::pv() + { + ImGui::SetWindowSize({0.f, (float)*g_pointers->m_gta.m_resolution_y}, ImGuiCond_Always); - if (ImGui::Checkbox("PREVIEW"_T.data(), &g.clone_pv.preview_vehicle)) - { - if (!g.clone_pv.preview_vehicle) - { - g_model_preview_service->stop_preview(); - } - } - ImGui::SameLine(); - ImGui::Checkbox("SPAWN_IN"_T.data(), &g.clone_pv.spawn_inside); - ImGui::SameLine(); + if (ImGui::Checkbox("PREVIEW"_T.data(), &g.clone_pv.preview_vehicle)) + { + if (!g.clone_pv.preview_vehicle) + { + g_model_preview_service->stop_preview(); + } + } + ImGui::SameLine(); + ImGui::Checkbox("SPAWN_IN"_T.data(), &g.clone_pv.spawn_inside); + ImGui::SameLine(); - static char plate_buf[9] = {0}; - int num_of_rows = 3; + static char plate_buf[9] = {0}; + int num_of_rows = 3; - ImGui::Checkbox("SPAWN_CLONE"_T.data(), &g.clone_pv.spawn_clone); - if (g.clone_pv.spawn_clone) - { - num_of_rows = 5; + ImGui::Checkbox("SPAWN_CLONE"_T.data(), &g.clone_pv.spawn_clone); + if (g.clone_pv.spawn_clone) + { + num_of_rows = 5; - ImGui::Checkbox("SPAWN_MAXED"_T.data(), &g.clone_pv.spawn_maxed); + ImGui::Checkbox("SPAWN_MAXED"_T.data(), &g.clone_pv.spawn_maxed); - ImGui::SameLine(); - ImGui::Checkbox("CLONE_PV_PLATE"_T.data(), &g.clone_pv.clone_plate); - if (g.clone_pv.clone_plate) - { - num_of_rows = 4; - } - else - { - ImGui::SetNextItemWidth(300.f); + ImGui::SameLine(); + ImGui::Checkbox("CLONE_PV_PLATE"_T.data(), &g.clone_pv.clone_plate); + if (g.clone_pv.clone_plate) + { + num_of_rows = 4; + } + else + { + ImGui::SetNextItemWidth(300.f); - strncpy(plate_buf, g.clone_pv.plate.c_str(), 9); - components::input_text_with_hint("PLATE"_T, "PLATE_NUMBER"_T, plate_buf, sizeof(plate_buf), ImGuiInputTextFlags_None, [] { - g.clone_pv.plate = plate_buf; - }); - } - } + strncpy(plate_buf, g.clone_pv.plate.c_str(), 9); + components::input_text_with_hint("PLATE"_T, "PLATE_NUMBER"_T, plate_buf, sizeof(plate_buf), ImGuiInputTextFlags_None, [] { + g.clone_pv.plate = plate_buf; + }); + } + } - static int selected_class = -1; - const auto& class_arr = g_gta_data_service->vehicle_classes(); + static int selected_class = -1; + const auto& class_arr = g_gta_data_service->vehicle_classes(); - ImGui::SetNextItemWidth(300.f); - if (ImGui::BeginCombo("VEHICLE_CLASS"_T.data(), - selected_class == -1 ? "ALL"_T.data() : class_arr[selected_class].c_str())) - { - if (ImGui::Selectable("ALL"_T.data(), selected_class == -1)) - { - selected_class = -1; - } + ImGui::SetNextItemWidth(300.f); + if (ImGui::BeginCombo("VEHICLE_CLASS"_T.data(), + selected_class == -1 ? "ALL"_T.data() : class_arr[selected_class].c_str())) + { + if (ImGui::Selectable("ALL"_T.data(), selected_class == -1)) + { + selected_class = -1; + } - for (int i = 0; i < class_arr.size(); i++) - { - if (ImGui::Selectable(class_arr[i].c_str(), selected_class == i)) - { - selected_class = i; - } + for (int i = 0; i < class_arr.size(); i++) + { + if (ImGui::Selectable(class_arr[i].c_str(), selected_class == i)) + { + selected_class = i; + } - if (selected_class == i) - { - ImGui::SetItemDefaultFocus(); - } - } + if (selected_class == i) + { + ImGui::SetItemDefaultFocus(); + } + } - ImGui::EndCombo(); - } + ImGui::EndCombo(); + } - static char search[64]; + static char search[64]; - ImGui::SetNextItemWidth(300.f); - components::input_text_with_hint("MODEL_NAME"_T, "SEARCH"_T, search, sizeof(search), ImGuiInputTextFlags_None); + ImGui::SetNextItemWidth(300.f); + components::input_text_with_hint("MODEL_NAME"_T, "SEARCH"_T, search, sizeof(search), ImGuiInputTextFlags_None); - g_mobile_service->refresh_personal_vehicles(); - if (ImGui::ListBoxHeader("###personal_veh_list", {300, static_cast(*g_pointers->m_gta.m_resolution_y - 188 - 38 * num_of_rows)})) - { - if (g_mobile_service->personal_vehicles().empty()) - { - ImGui::Text("NO_PERSONAL_VEHICLES"_T.data()); - } - else - { - std::string lower_search = search; - std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower); + g_mobile_service->refresh_personal_vehicles(); + if (ImGui::ListBoxHeader("###personal_veh_list", {300, static_cast(*g_pointers->m_gta.m_resolution_y - 188 - 38 * num_of_rows)})) + { + if (g_mobile_service->personal_vehicles().empty()) + { + ImGui::Text("NO_PERSONAL_VEHICLES"_T.data()); + } + else + { + std::string lower_search = search; + std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower); - for (const auto& it : g_mobile_service->personal_vehicles()) - { - const auto& label = it.first; - const auto& personal_veh = it.second; - const auto& item = g_gta_data_service->vehicle_by_hash(personal_veh->get_hash()); + for (const auto& it : g_mobile_service->personal_vehicles()) + { + const auto& label = it.first; + const auto& personal_veh = it.second; + const auto& item = g_gta_data_service->vehicle_by_hash(personal_veh->get_hash()); - std::string vehicle_class = item.m_vehicle_class; - std::string display_name = label; - std::string display_manufacturer = item.m_display_manufacturer; - std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower); - std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower); + std::string vehicle_class = item.m_vehicle_class; + std::string display_name = label; + std::string display_manufacturer = item.m_display_manufacturer; + std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower); + std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower); - if ((selected_class == -1 || class_arr[selected_class] == vehicle_class) - && (display_name.find(lower_search) != std::string::npos || display_manufacturer.find(lower_search) != std::string::npos)) - { - ImGui::PushID('v' << 24 & personal_veh->get_id()); - components::selectable(label, false, [&personal_veh] { - if (g.clone_pv.spawn_clone) - { - Vector3 spawn_location = vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside); - float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); + if ((selected_class == -1 || class_arr[selected_class] == vehicle_class) + && (display_name.find(lower_search) != std::string::npos || display_manufacturer.find(lower_search) != std::string::npos)) + { + ImGui::PushID('v' << 24 & personal_veh->get_id()); + components::selectable(label, false, [&personal_veh] { + if (g.clone_pv.spawn_clone) + { + Vector3 spawn_location = + vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside, personal_veh->get_hash()); + float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); - auto vehicle_idx = personal_veh->get_vehicle_idx(); - auto owned_mods = vehicle::get_owned_mods_from_vehicle_idx(vehicle_idx); + auto vehicle_idx = personal_veh->get_vehicle_idx(); + auto owned_mods = vehicle::get_owned_mods_from_vehicle_idx(vehicle_idx); - const char* spawn_plate_buf = plate_buf; - if (g.clone_pv.clone_plate) - { - spawn_plate_buf = personal_veh->get_plate(); - } + const char* spawn_plate_buf = plate_buf; + if (g.clone_pv.clone_plate) + { + spawn_plate_buf = personal_veh->get_plate(); + } - auto veh = vehicle::clone_from_owned_mods(owned_mods, spawn_location, spawn_heading); + auto veh = vehicle::clone_from_owned_mods(owned_mods, spawn_location, spawn_heading); - if (veh == 0) - { - g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); - } - else - { - if (g.clone_pv.spawn_maxed) - { - vehicle::max_vehicle(veh); - } + if (veh == 0) + { + g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); + } + else + { + if (g.clone_pv.spawn_maxed) + { + vehicle::max_vehicle(veh); + } - vehicle::set_plate(veh, spawn_plate_buf); + vehicle::set_plate(veh, spawn_plate_buf); - if (g.clone_pv.spawn_inside) - { - vehicle::teleport_into_vehicle(veh); - } - } - } - else - { - strcpy(search, ""); - personal_veh->summon(); - } + if (g.clone_pv.spawn_inside) + { + vehicle::teleport_into_vehicle(veh); + } + } + } + else + { + strcpy(search, ""); + personal_veh->summon(); + } - g_model_preview_service->stop_preview(); - }); - ImGui::PopID(); + g_model_preview_service->stop_preview(); + }); + ImGui::PopID(); - if (!g.clone_pv.preview_vehicle || (g.clone_pv.preview_vehicle && !ImGui::IsAnyItemHovered())) - { - g_model_preview_service->stop_preview(); - } - else if (ImGui::IsItemHovered()) - { - g_fiber_pool->queue_job([&personal_veh] { - g_model_preview_service->show_vehicle( - vehicle::get_owned_mods_from_vehicle_idx(personal_veh->get_vehicle_idx()), - g.clone_pv.spawn_maxed); - }); - } - } - } - } + if (!g.clone_pv.preview_vehicle || (g.clone_pv.preview_vehicle && !ImGui::IsAnyItemHovered())) + { + g_model_preview_service->stop_preview(); + } + else if (ImGui::IsItemHovered()) + { + g_fiber_pool->queue_job([&personal_veh] { + g_model_preview_service->show_vehicle( + vehicle::get_owned_mods_from_vehicle_idx(personal_veh->get_vehicle_idx()), + g.clone_pv.spawn_maxed); + }); + } + } + } + } - ImGui::ListBoxFooter(); - } - } -} \ No newline at end of file + ImGui::ListBoxFooter(); + } + } +} diff --git a/src/views/vehicle/view_spawn_vehicle.cpp b/src/views/vehicle/view_spawn_vehicle.cpp index 02fe1fa3..0df88329 100644 --- a/src/views/vehicle/view_spawn_vehicle.cpp +++ b/src/views/vehicle/view_spawn_vehicle.cpp @@ -7,192 +7,193 @@ namespace big { - void view::spawn_vehicle() - { - ImGui::SetWindowSize({0.f, (float)*g_pointers->m_gta.m_resolution_y}, ImGuiCond_Always); + void view::spawn_vehicle() + { + ImGui::SetWindowSize({0.f, (float)*g_pointers->m_gta.m_resolution_y}, ImGuiCond_Always); - if (ImGui::Checkbox("PREVIEW"_T.data(), &g.spawn_vehicle.preview_vehicle)) - { - if (!g.spawn_vehicle.preview_vehicle) - { - g_model_preview_service->stop_preview(); - } - } - ImGui::SameLine(); - components::command_checkbox<"spawnin">(); - ImGui::SameLine(); - components::command_checkbox<"spawnmaxed">(); + if (ImGui::Checkbox("PREVIEW"_T.data(), &g.spawn_vehicle.preview_vehicle)) + { + if (!g.spawn_vehicle.preview_vehicle) + { + g_model_preview_service->stop_preview(); + } + } + ImGui::SameLine(); + components::command_checkbox<"spawnin">(); + ImGui::SameLine(); + components::command_checkbox<"spawnmaxed">(); - static char plate_buf[9] = {0}; - strncpy(plate_buf, g.spawn_vehicle.plate.c_str(), 9); + static char plate_buf[9] = {0}; + strncpy(plate_buf, g.spawn_vehicle.plate.c_str(), 9); - ImGui::SetNextItemWidth(300.f); - components::input_text_with_hint("PLATE"_T, "PLATE_NUMBER"_T, plate_buf, sizeof(plate_buf), ImGuiInputTextFlags_None, [] { - g.spawn_vehicle.plate = plate_buf; - }); + ImGui::SetNextItemWidth(300.f); + components::input_text_with_hint("PLATE"_T, "PLATE_NUMBER"_T, plate_buf, sizeof(plate_buf), ImGuiInputTextFlags_None, [] { + g.spawn_vehicle.plate = plate_buf; + }); - static int selected_class = -1; - const auto& class_arr = g_gta_data_service->vehicle_classes(); + static int selected_class = -1; + const auto& class_arr = g_gta_data_service->vehicle_classes(); - ImGui::SetNextItemWidth(300.f); - if (ImGui::BeginCombo("VEHICLE_CLASS"_T.data(), - selected_class == -1 ? "ALL"_T.data() : class_arr[selected_class].c_str())) - { - if (ImGui::Selectable("ALL"_T.data(), selected_class == -1)) - { - selected_class = -1; - } + ImGui::SetNextItemWidth(300.f); + if (ImGui::BeginCombo("VEHICLE_CLASS"_T.data(), + selected_class == -1 ? "ALL"_T.data() : class_arr[selected_class].c_str())) + { + if (ImGui::Selectable("ALL"_T.data(), selected_class == -1)) + { + selected_class = -1; + } - for (int i = 0; i < class_arr.size(); i++) - { - if (ImGui::Selectable(class_arr[i].c_str(), selected_class == i)) - { - selected_class = i; - } + for (int i = 0; i < class_arr.size(); i++) + { + if (ImGui::Selectable(class_arr[i].c_str(), selected_class == i)) + { + selected_class = i; + } - if (selected_class == i) - { - ImGui::SetItemDefaultFocus(); - } - } + if (selected_class == i) + { + ImGui::SetItemDefaultFocus(); + } + } - ImGui::EndCombo(); - } + ImGui::EndCombo(); + } - static char search[64]; + static char search[64]; - ImGui::SetNextItemWidth(300.f); - components::input_text_with_hint("MODEL_NAME"_T, "SEARCH"_T, search, sizeof(search), ImGuiInputTextFlags_None); + ImGui::SetNextItemWidth(300.f); + components::input_text_with_hint("MODEL_NAME"_T, "SEARCH"_T, search, sizeof(search), ImGuiInputTextFlags_None); - if (ImGui::ListBoxHeader("###vehicles", {300, static_cast(*g_pointers->m_gta.m_resolution_y - 188 - 38 * 4)})) - { - if (self::veh) - { - static auto veh_hash = 0; + if (ImGui::ListBoxHeader("###vehicles", {300, static_cast(*g_pointers->m_gta.m_resolution_y - 188 - 38 * 4)})) + { + if (self::veh) + { + static auto veh_hash = 0; - g_fiber_pool->queue_job([] { - veh_hash = ENTITY::GET_ENTITY_MODEL(self::veh); - }); + g_fiber_pool->queue_job([] { + veh_hash = ENTITY::GET_ENTITY_MODEL(self::veh); + }); - if (veh_hash) - { - const auto& item = g_gta_data_service->vehicle_by_hash(veh_hash); + if (veh_hash) + { + const auto& item = g_gta_data_service->vehicle_by_hash(veh_hash); - components::selectable(std::vformat("SPAWN_VEHICLE_CURRENT_VEHICLE"_T, std::make_format_args(item.m_display_name)), false, [] { - if (self::veh) - { - Vector3 spawn_location = vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside); - float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); + components::selectable(std::vformat("SPAWN_VEHICLE_CURRENT_VEHICLE"_T, std::make_format_args(item.m_display_name)), false, [] { + if (self::veh) + { + Vector3 spawn_location = vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside, veh_hash); + float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); - auto owned_mods = vehicle::get_owned_mods_from_vehicle(self::veh); + auto owned_mods = vehicle::get_owned_mods_from_vehicle(self::veh); - auto veh = vehicle::clone_from_owned_mods(owned_mods, spawn_location, spawn_heading); + auto veh = vehicle::clone_from_owned_mods(owned_mods, spawn_location, spawn_heading); - if (veh == 0) - { - g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); - } - else - { - if (g.spawn_vehicle.spawn_maxed) - { - vehicle::max_vehicle(veh); - } + if (veh == 0) + { + g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); + } + else + { + if (g.spawn_vehicle.spawn_maxed) + { + vehicle::max_vehicle(veh); + } - vehicle::set_plate(veh, plate_buf); + vehicle::set_plate(veh, plate_buf); - if (g.spawn_vehicle.spawn_inside) - { - vehicle::teleport_into_vehicle(veh); - } - } - } + if (g.spawn_vehicle.spawn_inside) + { + vehicle::teleport_into_vehicle(veh); + } + } + } - g_model_preview_service->stop_preview(); - }); + g_model_preview_service->stop_preview(); + }); - if (!g.spawn_vehicle.preview_vehicle || (g.spawn_vehicle.preview_vehicle && !ImGui::IsAnyItemHovered())) - { - g_model_preview_service->stop_preview(); - } - else if (ImGui::IsItemHovered()) - { - g_fiber_pool->queue_job([] { - g_model_preview_service->show_vehicle(vehicle::get_owned_mods_from_vehicle(self::veh), - g.spawn_vehicle.spawn_maxed); - }); - } - } - } + if (!g.spawn_vehicle.preview_vehicle || (g.spawn_vehicle.preview_vehicle && !ImGui::IsAnyItemHovered())) + { + g_model_preview_service->stop_preview(); + } + else if (ImGui::IsItemHovered()) + { + g_fiber_pool->queue_job([] { + g_model_preview_service->show_vehicle(vehicle::get_owned_mods_from_vehicle(self::veh), + g.spawn_vehicle.spawn_maxed); + }); + } + } + } - const auto& item_arr = g_gta_data_service->vehicles(); - if (item_arr.size() > 0) - { - std::string lower_search = search; - std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower); + const auto& item_arr = g_gta_data_service->vehicles(); + if (item_arr.size() > 0) + { + std::string lower_search = search; + std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower); - for (auto& item : item_arr) - { - const auto& vehicle = item.second; + for (auto& item : item_arr) + { + const auto& vehicle = item.second; - std::string display_name = vehicle.m_display_name; - std::string display_manufacturer = vehicle.m_display_manufacturer; - std::string clazz = vehicle.m_vehicle_class; + std::string display_name = vehicle.m_display_name; + std::string display_manufacturer = vehicle.m_display_manufacturer; + std::string clazz = vehicle.m_vehicle_class; - std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower); - std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower); + std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower); + std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower); - if ((selected_class == -1 || class_arr[selected_class] == clazz) - && (display_name.find(lower_search) != std::string::npos || display_manufacturer.find(lower_search) != std::string::npos)) - { - ImGui::PushID(vehicle.m_hash); - components::selectable(vehicle.m_display_name, false, [&vehicle] { - const auto spawn_location = vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside); - const auto spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); + if ((selected_class == -1 || class_arr[selected_class] == clazz) + && (display_name.find(lower_search) != std::string::npos || display_manufacturer.find(lower_search) != std::string::npos)) + { + ImGui::PushID(vehicle.m_hash); + components::selectable(vehicle.m_display_name, false, [&vehicle] { + const auto spawn_location = + vehicle::get_spawn_location(g.spawn_vehicle.spawn_inside, vehicle.m_hash); + const auto spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped); - const auto veh = vehicle::spawn(vehicle.m_hash, spawn_location, spawn_heading); + const auto veh = vehicle::spawn(vehicle.m_hash, spawn_location, spawn_heading); - if (veh == 0) - { - g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); - } - else - { - if (g.spawn_vehicle.spawn_maxed) - { - vehicle::max_vehicle(veh); - } + if (veh == 0) + { + g_notification_service->push_error("VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data()); + } + else + { + if (g.spawn_vehicle.spawn_maxed) + { + vehicle::max_vehicle(veh); + } - vehicle::set_plate(veh, plate_buf); + vehicle::set_plate(veh, plate_buf); - if (g.spawn_vehicle.spawn_inside) - { - vehicle::teleport_into_vehicle(veh); - } - } + if (g.spawn_vehicle.spawn_inside) + { + vehicle::teleport_into_vehicle(veh); + } + } - g_model_preview_service->stop_preview(); - }); - ImGui::PopID(); + g_model_preview_service->stop_preview(); + }); + ImGui::PopID(); - if (!g.spawn_vehicle.preview_vehicle || (g.spawn_vehicle.preview_vehicle && !ImGui::IsAnyItemHovered())) - { - g_model_preview_service->stop_preview(); - } - else if (ImGui::IsItemHovered()) - { - g_model_preview_service->show_vehicle(vehicle.m_hash, g.spawn_vehicle.spawn_maxed); - } - } - } - } - else - { - ImGui::Text("NO_VEHICLE_IN_REGISTRY"_T.data()); - } - ImGui::ListBoxFooter(); - } - } -} \ No newline at end of file + if (!g.spawn_vehicle.preview_vehicle || (g.spawn_vehicle.preview_vehicle && !ImGui::IsAnyItemHovered())) + { + g_model_preview_service->stop_preview(); + } + else if (ImGui::IsItemHovered()) + { + g_model_preview_service->show_vehicle(vehicle.m_hash, g.spawn_vehicle.spawn_maxed); + } + } + } + } + else + { + ImGui::Text("NO_VEHICLE_IN_REGISTRY"_T.data()); + } + ImGui::ListBoxFooter(); + } + } +}