From 008d42ba9cc775d8e3299d4feeb383852a3e5f70 Mon Sep 17 00:00:00 2001 From: "Quentin E. / iDeath" Date: Thu, 28 Jul 2022 20:42:57 +0200 Subject: [PATCH] add persist car (save / load json vehicles) (#366) --- BigBaseV2/src/core/data/model_attachment.hpp | 27 + BigBaseV2/src/services/gui/gui_service.hpp | 2 + .../services/vehicle/persist_car_service.cpp | 466 ++++++++++++++++++ .../services/vehicle/persist_car_service.hpp | 80 +++ .../src/views/vehicle/view_persist_car.cpp | 87 ++++ BigBaseV2/src/views/view.hpp | 3 +- 6 files changed, 664 insertions(+), 1 deletion(-) create mode 100644 BigBaseV2/src/core/data/model_attachment.hpp create mode 100644 BigBaseV2/src/services/vehicle/persist_car_service.cpp create mode 100644 BigBaseV2/src/services/vehicle/persist_car_service.hpp create mode 100644 BigBaseV2/src/views/vehicle/view_persist_car.cpp diff --git a/BigBaseV2/src/core/data/model_attachment.hpp b/BigBaseV2/src/core/data/model_attachment.hpp new file mode 100644 index 00000000..2859c330 --- /dev/null +++ b/BigBaseV2/src/core/data/model_attachment.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "natives.hpp" + +namespace big +{ + struct model_attachment + { + Hash model_hash; + Vector3 position; + Vector3 rotation; + }; + + static void to_json(nlohmann::json& j, const model_attachment& attachment) + { + j = nlohmann::json{ {"model_hash", attachment.model_hash}, + {"position_x", attachment.position.x}, {"position_y", attachment.position.y}, {"position_z", attachment.position.z}, + {"rotation_x", attachment.rotation.x}, {"rotation_y", attachment.rotation.y}, {"rotation_z", attachment.rotation.z} }; + } + + static void from_json(const nlohmann::json& j, model_attachment& attachment) + { + j.at("model_hash").get_to(attachment.model_hash); + j.at("position_x").get_to(attachment.position.x); j.at("position_y").get_to(attachment.position.y); j.at("position_z").get_to(attachment.position.z); + j.at("rotation_x").get_to(attachment.rotation.x); j.at("rotation_y").get_to(attachment.rotation.y); j.at("rotation_z").get_to(attachment.rotation.z); + } +}; diff --git a/BigBaseV2/src/services/gui/gui_service.hpp b/BigBaseV2/src/services/gui/gui_service.hpp index 887a4a26..3bb0b4b8 100644 --- a/BigBaseV2/src/services/gui/gui_service.hpp +++ b/BigBaseV2/src/services/gui/gui_service.hpp @@ -25,6 +25,7 @@ namespace big SPAWN, PV, VEHICLE_FUN, + PERSIST_CAR, SPOOFING, TELEPORT, VEHICLE, @@ -61,6 +62,7 @@ namespace big { tabs::SPAWN, { "Spawn", view::spawn }}, { tabs::PV, { "Personal Vehicle", view::pv }}, { tabs::VEHICLE_FUN, { "Fun Features", view::vehicle_fun }}, + { tabs::PERSIST_CAR, { "Persist Car", view::persist_car }}, }}}, {tabs::NETWORK, { "Network", nullptr, { { tabs::SPOOFING, { "Spoofing", view::spoofing }}, diff --git a/BigBaseV2/src/services/vehicle/persist_car_service.cpp b/BigBaseV2/src/services/vehicle/persist_car_service.cpp new file mode 100644 index 00000000..e557577a --- /dev/null +++ b/BigBaseV2/src/services/vehicle/persist_car_service.cpp @@ -0,0 +1,466 @@ +#include "persist_car_service.hpp" +#include "util/vehicle.hpp" +#include "pointers.hpp" + + +namespace big +{ + void persist_car_service::save_vehicle(Vehicle vehicle, std::string_view file_name) + { + if (!ENTITY::DOES_ENTITY_EXIST(vehicle) || + !ENTITY::IS_ENTITY_A_VEHICLE(vehicle)) + { + g_notification_service->push_warning("Persist Car", "Tried to save a vehicle which does not exist"); + return; + } + + const auto file = check_vehicle_folder().get_file(file_name); + + std::ofstream file_stream(file.get_path(), std::ios::out | std::ios::trunc); + + file_stream << get_full_vehicle_json(vehicle).dump(4); + + file_stream.close(); + } + + Vehicle persist_car_service::load_vehicle(std::string_view file_name) + { + const auto file = check_vehicle_folder().get_file(file_name); + + std::ifstream file_stream(file.get_path()); + + nlohmann::json vehicle_json; + + file_stream >> vehicle_json; + file_stream.close(); + + return spawn_vehicle_full(vehicle_json, self::ped); + } + + std::vector persist_car_service::list_files() + { + std::vector file_paths; + + const auto file_path = check_vehicle_folder(); + for (const auto& directory_entry : std::filesystem::directory_iterator(file_path.get_path())) + if (directory_entry.path().extension() == ".json") + file_paths.push_back(directory_entry.path().filename().generic_string()); + + return file_paths; + } + + Vehicle persist_car_service::clone_ped_car(Ped ped, Vehicle vehicle) + { + return spawn_vehicle_full(get_full_vehicle_json(vehicle), ped); + } + + Vehicle persist_car_service::spawn_vehicle_full(nlohmann::json vehicle_json, Ped ped) + { + const auto vehicle = spawn_vehicle(vehicle_json, ped); + + if (!vehicle_json[tow_key].is_null()) + { + const auto tow = spawn_vehicle(vehicle_json[tow_key], ped); + + auto pos = ENTITY::GET_ENTITY_COORDS(tow, true); + pos.x -= 10; + + ENTITY::SET_ENTITY_COORDS_NO_OFFSET(tow, pos.x, pos.y, 0.f, true, true, false); + + VEHICLE::ATTACH_VEHICLE_TO_TOW_TRUCK(vehicle, tow, -1, 0.f, 0.5f, 0.f); + VEHICLE::SET_VEHICLE_TOW_TRUCK_ARM_POSITION(vehicle, 1.f); + + const auto rotation = ENTITY::GET_ENTITY_ROTATION(tow, 2); + ENTITY::SET_ENTITY_ROTATION(tow, 0, 0, rotation.z, 2, true); + } + else if (!vehicle_json[trailer_key].is_null()) + { + const auto trailer = spawn_vehicle(vehicle_json[trailer_key], ped); + VEHICLE::ATTACH_VEHICLE_TO_TRAILER(vehicle, trailer, 1.0f); + + const auto rotation = ENTITY::GET_ENTITY_ROTATION(trailer, 2); + ENTITY::SET_ENTITY_ROTATION(trailer, 0, 0, rotation.z, 2, true); + } + + const auto rotation = ENTITY::GET_ENTITY_ROTATION(vehicle, 2); + ENTITY::SET_ENTITY_ROTATION(vehicle, rotation.x, 0, rotation.z, 2, true); + + return vehicle; + } + + Vehicle persist_car_service::spawn_vehicle(nlohmann::json vehicle_json, Ped ped) + { + const auto vehicle = spawn_vehicle_json(vehicle_json, ped); + + std::vector model_attachments = vehicle_json[model_attachments_key]; + for (const auto& j : model_attachments) + { + const auto attachment = j.get(); + STREAMING::REQUEST_MODEL(attachment.model_hash); + const auto object = OBJECT::CREATE_OBJECT(attachment.model_hash, 0, 0, 0, true, false, false); + ENTITY::ATTACH_ENTITY_TO_ENTITY( + object, vehicle, + 0, + attachment.position.x, attachment.position.y, attachment.position.z, + attachment.rotation.x, attachment.rotation.y, attachment.rotation.z, + false, false, false, false, 0, true); + STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(attachment.model_hash); + } + + std::vector vehicle_attachments = vehicle_json[vehicle_attachments_key]; + for (const auto& j : vehicle_attachments) + { + const auto vehicle_to_attach = spawn_vehicle_json(j[vehicle_key], ped); + auto attachment = j[model_attachment_key].get(); + ENTITY::ATTACH_ENTITY_TO_ENTITY( + vehicle_to_attach, vehicle, + 0, + attachment.position.x, attachment.position.y, attachment.position.z, + attachment.rotation.x, attachment.rotation.y, attachment.rotation.z, + false, false, false, false, 0, true); + + VEHICLE::SET_VEHICLE_IS_CONSIDERED_BY_PLAYER(vehicle_to_attach, false); + } + + return vehicle; + } + + Vehicle persist_car_service::spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped) + { + const Hash vehicle_hash = vehicle_json[vehicle_model_hash_key]; + + const auto pos = ENTITY::GET_ENTITY_COORDS(self::ped, true); + + const auto vehicle = big::vehicle::spawn(vehicle_hash, pos, ENTITY::GET_ENTITY_HEADING(ped)); + + VEHICLE::SET_VEHICLE_DIRT_LEVEL(vehicle, 0.0f); + VEHICLE::SET_VEHICLE_MOD_KIT(vehicle, 0); + VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(vehicle, false); + 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]); + } + + VEHICLE::SET_VEHICLE_WINDOW_TINT(vehicle, vehicle_json[vehicle_window_tint_key]); + + if (!vehicle_json[radio_station_key].is_null()) + AUDIO::SET_VEH_RADIO_STATION(vehicle, vehicle_json[radio_station_key].get().c_str()); + + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(vehicle, vehicle_json[plate_text_key].get().c_str()); + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle, vehicle_json[plate_text_index_key]); + VEHICLE::SET_VEHICLE_EXTRA_COLOURS(vehicle, vehicle_json[pearlescent_color_key], vehicle_json[wheel_color_key]); + + std::map vehicle_extras = vehicle_json[vehicle_extras_key]; + for (int i = 0; i <= 20; i++) + { + if (VEHICLE::DOES_EXTRA_EXIST(vehicle, i)) + VEHICLE::SET_VEHICLE_EXTRA(vehicle, i, vehicle_extras[i]); + } + + 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(ENTITY::GET_ENTITY_MODEL(vehicle)) || VEHICLE::IS_THIS_MODEL_A_BIKE(ENTITY::GET_ENTITY_MODEL(vehicle))) + { + VEHICLE::SET_VEHICLE_WHEEL_TYPE(vehicle, vehicle_json[wheel_type_key]); + for (int i = MOD_SPOILERS; i <= MOD_LIGHTBAR; i++) + { + const bool has_mod = !vehicle_json[mod_names[i]].is_null(); + if (has_mod) + { + if (i == MOD_TYRE_SMOKE) + { + 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]); + VEHICLE::TOGGLE_VEHICLE_MOD(vehicle, MOD_TYRE_SMOKE, true); + } + else 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 + { + VEHICLE::TOGGLE_VEHICLE_MOD(vehicle, i, true); + } + } + } + std::vector neon_lights = vehicle_json[neon_lights_key]; + for (int i = NEON_LEFT; i <= NEON_BACK; i++) + VEHICLE::SET_VEHICLE_NEON_LIGHT_ENABLED_(vehicle, i, neon_lights[i]); + std::vector neon_color = vehicle_json[neon_color_key]; + VEHICLE::SET_VEHICLE_NEON_LIGHTS_COLOUR_(vehicle, neon_color[0], neon_color[1], neon_color[2]); + + if (VEHICLE::IS_VEHICLE_A_CONVERTIBLE(vehicle, 0)) + { + int convertable_state = vehicle_json[convertable_state_key]; + if (convertable_state == 0 || convertable_state == 3 || convertable_state == 5) + VEHICLE::RAISE_CONVERTIBLE_ROOF(vehicle, true); + else + VEHICLE::LOWER_CONVERTIBLE_ROOF(vehicle, true); + } + + VEHICLE::SET_VEHICLE_INTERIOR_COLOR_(vehicle, vehicle_json[interior_color_key]); + + VEHICLE::SET_VEHICLE_DASHBOARD_COLOR_(vehicle, vehicle_json[dash_color_key]); + + const BOOL have_clan_logo = vehicle_json[clan_logo_key]; + if (have_clan_logo) + vehicle_helper::add_clan_logo_to_vehicle(vehicle, ped); + + VEHICLE::SET_VEHICLE_XENON_LIGHTS_COLOR_(vehicle, vehicle_json[headlight_color_key]); + } + + return vehicle; + } + + nlohmann::json persist_car_service::get_full_vehicle_json(Vehicle vehicle) + { + // The car needs to be rotated at (0, 0, 0) for the relative offset calculations to be accurate. + ENTITY::SET_ENTITY_ROTATION(vehicle, 0, 0, 0, 0, true); + script::get_current()->yield(); + ENTITY::SET_ENTITY_ROTATION(vehicle, 0, 0, 0, 0, true); + + nlohmann::json vehicle_json = get_vehicle_json(vehicle); + + vehicle_json[model_attachments_key] = get_model_attachments(vehicle); + vehicle_json[vehicle_attachments_key] = get_vehicle_attachents(vehicle); + + Vehicle tow = VEHICLE::GET_ENTITY_ATTACHED_TO_TOW_TRUCK(vehicle); + if (ENTITY::DOES_ENTITY_EXIST(tow)) + { + vehicle_json[tow_key] = get_vehicle_json(tow); + vehicle_json[tow_key][model_attachments_key] = get_model_attachments(tow, true); + vehicle_json[tow_key][vehicle_attachments_key] = get_vehicle_attachents(tow); + } + if (VEHICLE::IS_VEHICLE_ATTACHED_TO_TRAILER(vehicle)) + { + Vehicle trailer; + VEHICLE::GET_VEHICLE_TRAILER_VEHICLE(vehicle, &trailer); + + vehicle_json[trailer_key] = get_vehicle_json(trailer); + vehicle_json[trailer_key][model_attachments_key] = get_model_attachments(trailer); + vehicle_json[trailer_key][vehicle_attachments_key] = get_vehicle_attachents(trailer); + } + + return vehicle_json; + } + + model_attachment persist_car_service::get_model_attachment(Vehicle vehicle, Object object) + { + const auto object_location = ENTITY::GET_ENTITY_COORDS(object, 0); + const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehicle, object_location.x, object_location.y, object_location.z); + + const auto object_rotation = ENTITY::GET_ENTITY_ROTATION(object, 0); + const auto vehicle_rotation = ENTITY::GET_ENTITY_ROTATION(vehicle, 0); + + Vector3 rotation; + rotation.x = (object_rotation.x - vehicle_rotation.x); + rotation.y = (object_rotation.y - vehicle_rotation.y); + rotation.z = (object_rotation.z - vehicle_rotation.z); + + model_attachment attachment = { ENTITY::GET_ENTITY_MODEL(object), location, rotation }; + + return attachment; + } + + nlohmann::json persist_car_service::get_model_attachments(Vehicle vehicle, bool is_towed_vehicle) + { + const auto replay_interface = *g_pointers->m_replay_interface; + + std::vector attached_objects; + + const auto object_interface = replay_interface->m_object_interface; + for (int i = 0; i < object_interface->m_max_objects; i++) + { + const auto object_ptr = object_interface->get_object(i); + if (!object_ptr) + continue; + + const auto object = g_pointers->m_ptr_to_handle(object_ptr); + if (!object) + break; + + if (!ENTITY::IS_ENTITY_ATTACHED_TO_ENTITY(vehicle, object)) + continue; + + // Don't save tow hook. + if (is_towed_vehicle && ENTITY::GET_ENTITY_MODEL(object) == 0xBC344305) + continue; + + attached_objects.push_back(get_model_attachment(vehicle, object)); + }; + + return attached_objects; + } + + nlohmann::json persist_car_service::get_vehicle_attachents(Vehicle vehicle) + { + const auto replay_interface = *g_pointers->m_replay_interface; + + const auto vehicle_interface = replay_interface->m_vehicle_interface; + + std::vector attached_vehicles; + + Vehicle trailer; + VEHICLE::GET_VEHICLE_TRAILER_VEHICLE(vehicle, &trailer); + + for (int i = 0; i < vehicle_interface->m_max_vehicles; i++) + { + const auto vehicle_ptr = vehicle_interface->get_vehicle(i); + if (!vehicle_ptr) + continue; + + const auto object = g_pointers->m_ptr_to_handle(vehicle_ptr); + if (!object) + break; + + if (!ENTITY::IS_ENTITY_ATTACHED_TO_ENTITY(vehicle, object)) + continue; + + if (object == VEHICLE::GET_ENTITY_ATTACHED_TO_TOW_TRUCK(vehicle) || + VEHICLE::IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(object, vehicle)) + continue; + + if (object == trailer || + VEHICLE::IS_VEHICLE_ATTACHED_TO_TRAILER(object)) + continue; + + nlohmann::json model_attachment; + model_attachment[vehicle_key] = get_vehicle_json(object); + model_attachment[model_attachment_key] = get_model_attachment(vehicle, object); + + attached_vehicles.push_back(model_attachment); + } + + return attached_vehicles; + } + + nlohmann::json persist_car_service::get_vehicle_json(Vehicle vehicle) + { + nlohmann::json vehicle_json; + + vehicle_json[vehicle_model_hash_key] = ENTITY::GET_ENTITY_MODEL(vehicle); + + int primary_color, secondary_color; + VEHICLE::GET_VEHICLE_COLOURS(vehicle, &primary_color, &secondary_color); + 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); + + auto radio_station = AUDIO::GET_PLAYER_RADIO_STATION_NAME(); + + if (!radio_station) + radio_station = "OFF"; + + vehicle_json[radio_station_key] = radio_station; + + 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); + + int pearlescent_color, wheel_color; + VEHICLE::GET_VEHICLE_EXTRA_COLOURS(vehicle, &pearlescent_color, &wheel_color); + + vehicle_json[pearlescent_color_key] = pearlescent_color; + vehicle_json[wheel_color_key] = wheel_color; + + std::map vehicle_extras; + for (int i = 0; i <= 20; i++) + { + if (VEHICLE::DOES_EXTRA_EXIST(vehicle, i)) + vehicle_extras[i] = !VEHICLE::IS_VEHICLE_EXTRA_TURNED_ON(vehicle, i); + } + + vehicle_json[vehicle_extras_key] = vehicle_extras; + + 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(ENTITY::GET_ENTITY_MODEL(vehicle)) || + VEHICLE::IS_THIS_MODEL_A_BIKE(ENTITY::GET_ENTITY_MODEL(vehicle))) + { + vehicle_json[wheel_type_key] = VEHICLE::GET_VEHICLE_WHEEL_TYPE(vehicle); + + for (int i = MOD_SPOILERS; i <= MOD_LIVERY; i++) + { + const auto is_mod_on = VEHICLE::IS_TOGGLE_MOD_ON(vehicle, i); + if (is_mod_on) + { + if (i == 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 + { + vehicle_json[mod_names[i]] = "TOGGLE"; + } + } + + if (VEHICLE::GET_VEHICLE_MOD(vehicle, i) != -1) + { + int vehicle_mod[2] = { VEHICLE::GET_VEHICLE_MOD(vehicle, i), VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, i) }; + vehicle_json[mod_names[i]] = vehicle_mod; + } + } + + bool neon_lights[4]{}; + for (int i = NEON_LEFT; i <= NEON_BACK; i++) + neon_lights[i] = VEHICLE::IS_VEHICLE_NEON_LIGHT_ENABLED_(vehicle, i); + + int neon_color[3]{}; + VEHICLE::GET_VEHICLE_NEON_LIGHTS_COLOUR_(vehicle, &neon_color[0], &neon_color[1], &neon_color[2]); + vehicle_json[neon_color_key] = neon_color; + vehicle_json[neon_lights_key] = neon_lights; + + if (VEHICLE::IS_VEHICLE_A_CONVERTIBLE(vehicle, 0)) + vehicle_json[convertable_state_key] = VEHICLE::GET_CONVERTIBLE_ROOF_STATE(vehicle); + + int interior_color, dashboard_color; + VEHICLE::GET_VEHICLE_INTERIOR_COLOR_(vehicle, &interior_color); + VEHICLE::GET_VEHICLE_DASHBOARD_COLOR_(vehicle, &dashboard_color); + vehicle_json[interior_color_key] = interior_color; + vehicle_json[dash_color_key] = dashboard_color; + + vehicle_json[clan_logo_key] = GRAPHICS::DOES_VEHICLE_HAVE_CREW_EMBLEM(vehicle, 0); + vehicle_json[headlight_color_key] = VEHICLE::GET_VEHICLE_XENON_LIGHTS_COLOR_(vehicle); + } + + return vehicle_json; + } + + big::folder persist_car_service::check_vehicle_folder() + { + const auto folder = g_file_manager->get_project_folder("./saved_json_vehicles"); + + return folder; + } +} diff --git a/BigBaseV2/src/services/vehicle/persist_car_service.hpp b/BigBaseV2/src/services/vehicle/persist_car_service.hpp new file mode 100644 index 00000000..4b1c5a79 --- /dev/null +++ b/BigBaseV2/src/services/vehicle/persist_car_service.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "natives.hpp" +#include "core/data/model_attachment.hpp" + +namespace big +{ + class persist_car_service + { + public: + static std::vector list_files(); + + static Vehicle clone_ped_car(Ped ped, Vehicle vehicle); + + static void save_vehicle(Vehicle vehicle, std::string_view file_name); + static Vehicle load_vehicle(std::string_view file_name); + + private: + static constexpr auto model_attachment_key = "model_attachment"; + static constexpr auto model_attachments_key = "model_attachments"; + + static constexpr auto vehicle_attachments_key = "vehicle_attachments"; + + static constexpr auto vehicle_model_hash_key = "vehicle_model_hash"; + + static constexpr auto vehicle_key = "vehicle"; + + static constexpr auto tow_key = "tow"; + static constexpr auto trailer_key = "trailer"; + + static constexpr auto radio_station_key = "radio_station"; + + 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 convertable_state_key = "convertable_state"; + + 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"; + + static constexpr auto clan_logo_key = "clan_logo"; + + + static Vehicle spawn_vehicle_full(nlohmann::json vehicle_json, Ped ped); + static Vehicle spawn_vehicle(nlohmann::json vehicle_json, Ped ped); + static Vehicle spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped); + + static nlohmann::json get_full_vehicle_json(Vehicle vehicle); + + static model_attachment get_model_attachment(Vehicle vehicle, Object object); + static nlohmann::json get_model_attachments(Vehicle vehicle, bool is_towed_vehicle = false); + + static nlohmann::json get_vehicle_attachents(Vehicle vehicle); + + static nlohmann::json get_vehicle_json(Vehicle vehicle); + + static big::folder check_vehicle_folder(); + }; +} diff --git a/BigBaseV2/src/views/vehicle/view_persist_car.cpp b/BigBaseV2/src/views/vehicle/view_persist_car.cpp new file mode 100644 index 00000000..9473244e --- /dev/null +++ b/BigBaseV2/src/views/vehicle/view_persist_car.cpp @@ -0,0 +1,87 @@ +#include "fiber_pool.hpp" +#include "gui/handling/handling_tabs.hpp" +#include "script.hpp" +#include "util/vehicle.hpp" +#include "views/view.hpp" +#include "util/mobile.hpp" +#include "core/data/speed_units.hpp" +#include "services/vehicle/persist_car_service.hpp" + +namespace big +{ + static void save_vehicle(char* vehicle_file_name_input) + { + if (ENTITY::DOES_ENTITY_EXIST(self::veh)) + { + const auto vehicle_file_name = std::string(vehicle_file_name_input).append(".json"); + persist_car_service::save_vehicle(self::veh, vehicle_file_name); + ZeroMemory(vehicle_file_name_input, sizeof(vehicle_file_name_input)); + } + } + + static void load_vehicle(std::string& selected_vehicle_file) + { + if (!selected_vehicle_file.empty()) + { + const auto vehicle = persist_car_service::load_vehicle(selected_vehicle_file); + if (!vehicle) + { + g_notification_service->push_warning("Persist Car", "Vehicle failed to spawn, there is most likely too many spawned vehicles in the area"); + } + else if (g->spawn.spawn_inside) + teleport::into_vehicle(vehicle); + + selected_vehicle_file.clear(); + } + else + { + g_notification_service->push_warning("Persist Car", "Select a file first"); + } + } + + void view::persist_car() + { + static std::string selected_vehicle_file; + + const auto vehicle_files = persist_car_service::list_files(); + + ImGui::PushItemWidth(250); + ImGui::Text("Saved Vehicles"); + + if (ImGui::ListBoxHeader("##empty", ImVec2(200, 200))) + { + for (const auto& pair : vehicle_files) + { + if (ImGui::Selectable(pair.c_str(), selected_vehicle_file == pair)) + selected_vehicle_file = pair; + } + + ImGui::ListBoxFooter(); + } + + ImGui::SameLine(); + + ImGui::BeginGroup(); + static char vehicle_file_name_input[50]{}; + + ImGui::PushItemWidth(250); + components::input_text_with_hint( + "Vehicle File Name", + "Ex: My Cool Car", + vehicle_file_name_input, IM_ARRAYSIZE(vehicle_file_name_input)); + + ImGui::SameLine(); + + components::button("Save Vehicle", [] + { + save_vehicle(vehicle_file_name_input); + }); + + components::button("Load Vehicle", [] + { + load_vehicle(selected_vehicle_file); + }); + + ImGui::EndGroup(); + } +} diff --git a/BigBaseV2/src/views/view.hpp b/BigBaseV2/src/views/view.hpp index 7a2a842d..5f9e2826 100644 --- a/BigBaseV2/src/views/view.hpp +++ b/BigBaseV2/src/views/view.hpp @@ -35,6 +35,7 @@ namespace big static void spawn(); static void pv(); static void vehicle_fun(); + static void persist_car(); static void spoofing(); static void teleport(); static void vehicle(); @@ -51,4 +52,4 @@ namespace big notifications(); } }; -} \ No newline at end of file +}