diff --git a/scripts/gtav-classes.cmake b/scripts/gtav-classes.cmake index 26c4ec79..5392f755 100644 --- a/scripts/gtav-classes.cmake +++ b/scripts/gtav-classes.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare( gtav_classes GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git - GIT_TAG 9e76175d28b3de21c24a69e71bee779d704d8304 + GIT_TAG b93fcb4848c935b6b11ce9d5e82fb38aba3a59f4 GIT_PROGRESS TRUE CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/src/backend/looped/vehicle/vehicle_abilities.cpp b/src/backend/looped/vehicle/vehicle_abilities.cpp new file mode 100644 index 00000000..ae35488b --- /dev/null +++ b/src/backend/looped/vehicle/vehicle_abilities.cpp @@ -0,0 +1,175 @@ +#include "backend/looped_command.hpp" +#include "gta/enums.hpp" +#include "util/misc.hpp" +#include "util/vehicle.hpp" + +#include + +namespace big +{ + class vehicle_ability : looped_command + { + using looped_command::looped_command; + + class vehicle_ability_helper + { + private: + static constexpr std::array m_abilities = { + eVehicleAbilities::JUMP, + eVehicleAbilities::ROCKET, + eVehicleAbilities::PARACHUTE, + eVehicleAbilities::RAMP_BUGGY, + }; + + private: + std::unordered_set m_stock_abilities; + CVehicle* m_vehicle = nullptr; + uint16_t m_original_abilities; + + public: + vehicle_ability_helper() = default; + vehicle_ability_helper(CVehicle* vehicle) + { + if (vehicle == nullptr || vehicle->m_model_info == nullptr) + return; + m_vehicle = vehicle; + + const auto model_info = reinterpret_cast(vehicle->m_model_info); + m_original_abilities = model_info->m_ability_flag; + + for (const auto ability : m_abilities) + { + if (m_original_abilities >> (uint16_t)ability & 1) + { + m_stock_abilities.insert(ability); + } + } + } + + /** + * @brief Gets the initial ability value of the vehicle. + * + * @param ability + * @return true + * @return false + */ + bool get_ability_default(eVehicleAbilities ability) + { + return m_stock_abilities.contains(ability); + } + + /** + * @brief Checks if the currently bound CVehicle ptr has the flag enabled. + * + * @param ability + * @return true + * @return false + */ + bool has_ability(eVehicleAbilities ability) + { + return m_vehicle && m_vehicle->m_model_info && reinterpret_cast(m_vehicle->m_model_info)->m_ability_flag >> (uint16_t)ability & 1; + } + + /** + * @brief Resets the vehicle to its defaults safely! + */ + void reset_defaults() + { + if (m_vehicle && m_vehicle->m_model_info) + { + const auto model_info = reinterpret_cast(m_vehicle->m_model_info); + + model_info->m_ability_flag = m_original_abilities; + } + } + + /** + * @brief Safely set the ability state of a vehicle. + * + * @param ability + * @param toggle + */ + void toggle_ability(eVehicleAbilities ability, bool toggle) + { + if (m_vehicle && m_vehicle->m_model_info) + { + const auto model_info = reinterpret_cast(m_vehicle->m_model_info); + if (toggle) + misc::set_bits(&model_info->m_ability_flag, (uint16_t)ability); + else + misc::clear_bits(&model_info->m_ability_flag, (uint16_t)ability); + } + } + + bool operator ==(const CVehicle* vehicle) const + { + return m_vehicle == vehicle; + } + + } m_vehicle_ability_helper {}; + + virtual void on_enable() override + { + reset(g_local_player->m_vehicle); + } + + virtual void on_tick() override + { + const auto curr_veh = g_local_player->m_vehicle; + if (curr_veh && !(g_local_player->m_ped_task_flag & (int)ePedTask::TASK_DRIVING)) + { + m_vehicle_ability_helper.reset_defaults(); + return; + } + + if (m_vehicle_ability_helper != curr_veh) + { + reset(curr_veh); + } + + m_vehicle_ability_helper.toggle_ability(eVehicleAbilities::JUMP, g.vehicle.abilities.jump); + m_vehicle_ability_helper.toggle_ability(eVehicleAbilities::ROCKET, g.vehicle.abilities.rocket); + m_vehicle_ability_helper.toggle_ability(eVehicleAbilities::PARACHUTE, g.vehicle.abilities.parachute); + m_vehicle_ability_helper.toggle_ability(eVehicleAbilities::RAMP_BUGGY, g.vehicle.abilities.ramp); + } + + virtual void on_disable() override + { + reset(nullptr); + } + + void reset(CVehicle* vehicle) + { + if (vehicle == nullptr) + { + m_vehicle_ability_helper = {}; + g.vehicle.abilities = {}; + + return; + } + + m_vehicle_ability_helper.reset_defaults(); + m_vehicle_ability_helper = { vehicle }; + + // currently I'd keep overwriting the display values for what is default for the current vehicle + // should we always persist the user's choice onto the vehicle? or only the ones that are enabled? + // doesn't sound like too great of an idea for vehicles that have abilities by default and then suddenly they're disabled + g.vehicle.abilities.jump = m_vehicle_ability_helper.get_ability_default(eVehicleAbilities::JUMP); + g.vehicle.abilities.rocket = m_vehicle_ability_helper.get_ability_default(eVehicleAbilities::ROCKET); + g.vehicle.abilities.parachute = m_vehicle_ability_helper.get_ability_default(eVehicleAbilities::PARACHUTE); + g.vehicle.abilities.ramp = m_vehicle_ability_helper.get_ability_default(eVehicleAbilities::RAMP_BUGGY); + } + }; + + vehicle_ability + g_vehicle_ability("modifyvehicleability", "MODIFY_VEHICLE_ABILITY", "MODIFY_VEHICLE_ABILITY_DESC", g.vehicle.abilities.enabled); + + bool_command g_jump_ability("jumpability", "BACKEND_LOOPED_VEHICLE_ABILITY_JUMP", "BACKEND_LOOPED_VEHICLE_ABILITY_JUMP_DESC", + g.vehicle.abilities.jump); + bool_command g_rocket_ability("rocketability", "BACKEND_LOOPED_VEHICLE_ABILITY_ROCKET", "BACKEND_LOOPED_VEHICLE_ABILITY_ROCKET_DESC", + g.vehicle.abilities.rocket); + bool_command g_parachute_ability("parachuteability", "BACKEND_LOOPED_VEHICLE_ABILITY_PARACHUTE", "BACKEND_LOOPED_VEHICLE_ABILITY_PARACHUTE_DESC", + g.vehicle.abilities.parachute); + bool_command g_ramp_ability("rampability", "BACKEND_LOOPED_VEHICLE_ABILITY_RAMP", "BACKEND_LOOPED_VEHICLE_ABILITY_RAMP_DESC", + g.vehicle.abilities.ramp); +} \ No newline at end of file diff --git a/src/core/settings.hpp b/src/core/settings.hpp index 37c8d0f8..e5302245 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #define IMGUI_DEFINE_MATH_OPERATORS #include @@ -451,7 +451,7 @@ namespace big struct hotkeys { - bool editing_menu_toggle = false; + bool editing_menu_toggle = false; std::atomic is_mp_chat_active; int menu_toggle = VK_INSERT; int teleport_waypoint = 0; @@ -554,9 +554,9 @@ namespace big struct ocean { - bool modify_ocean = false; - bool disable_ocean = false; - int ocean_opacity = 100; + bool modify_ocean = false; + bool disable_ocean = false; + int ocean_opacity = 100; NLOHMANN_DEFINE_TYPE_INTRUSIVE(ocean, modify_ocean, disable_ocean, ocean_opacity) } ocean{}; @@ -764,6 +764,17 @@ namespace big bool siren_mute = false; bool all_vehs_in_heists = false; + struct abilities + { + bool enabled = false; + bool jump = false; + bool rocket = false; + bool parachute = false; + bool ramp = false; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(abilities, enabled) + } abilities{}; + struct vehicle_ammo_special { bool enabled = false; @@ -787,7 +798,7 @@ namespace big NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle_ammo_special, enabled, type, explosion_tag, speed, time_between_shots, alternate_wait_time, weapon_range, rocket_time_between_shots, rocket_alternate_wait_time, rocket_lock_on_range, rocket_range, rocket_reload_time, rocket_explosion_tag, rocket_lifetime, rocket_launch_speed, rocket_time_before_homing, rocket_improve_tracking) } vehicle_ammo_special{}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, keep_engine_running, keep_vehicle_clean, vehinvisibility, localveh_visibility, keep_on_ground, no_collision, unlimited_weapons, siren_mute, all_vehs_in_heists, vehicle_ammo_special) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, keep_engine_running, keep_vehicle_clean, vehinvisibility, localveh_visibility, keep_on_ground, no_collision, unlimited_weapons, siren_mute, all_vehs_in_heists, abilities, vehicle_ammo_special) } vehicle{}; struct weapons diff --git a/src/gta/enums.hpp b/src/gta/enums.hpp index 6edf40d0..ebec367b 100644 --- a/src/gta/enums.hpp +++ b/src/gta/enums.hpp @@ -2004,6 +2004,14 @@ enum class eVehicleSeats OUTSIDE_RIGHT, }; +enum class eVehicleAbilities : uint16_t +{ + JUMP = 1 << 5, + ROCKET = 1 << 6, + PARACHUTE = 1 << 8, + RAMP_BUGGY = 1 << 9 +}; + enum class eKnockOffVehicle { KNOCKOFFVEHICLE_DEFAULT, diff --git a/src/util/misc.hpp b/src/util/misc.hpp index 72c8408d..bafe5a92 100644 --- a/src/util/misc.hpp +++ b/src/util/misc.hpp @@ -2,17 +2,20 @@ namespace big::misc { - inline void clear_bit(int* address, int pos) + template + inline void clear_bit(T* address, int pos) { *address &= ~(1 << pos); } - - inline void clear_bits(int* address, int bits) + + template + inline void clear_bits(T* address, int bits) { *address &= ~(bits); } - inline bool has_bit_set(int* address, int pos) + template + inline bool has_bit_set(T* address, int pos) { return *address & 1 << pos; } @@ -23,17 +26,14 @@ namespace big::misc return (*address & bits) == bits; } - inline bool has_bits_set(int* address, int bits) - { - return (*address & bits) == bits; - } - - inline void set_bit(int* address, int pos) + template + inline void set_bit(T* address, int pos) { *address |= 1 << pos; } - inline void set_bits(int* address, int bits) + template + inline void set_bits(T* address, int bits) { *address |= bits; } diff --git a/src/views/vehicle/view_fun_vehicle.cpp b/src/views/vehicle/view_fun_vehicle.cpp index 9f7a41ba..5793cee1 100644 --- a/src/views/vehicle/view_fun_vehicle.cpp +++ b/src/views/vehicle/view_fun_vehicle.cpp @@ -220,6 +220,18 @@ namespace big ImGui::EndCombo(); } + ImGui::SeparatorText("VEHICLE_ABILITIES"_T.data()); + { + components::command_checkbox<"modifyvehicleability">(); + + if (g.vehicle.abilities.enabled) + { + components::command_checkbox<"rocketability">(); + components::command_checkbox<"jumpability">(); + components::command_checkbox<"parachuteability">(); + components::command_checkbox<"rampability">(); + } + } ImGui::SeparatorText("VEHICLE_FLY"_T.data()); { ImGui::BeginGroup();