From 543c229be24ba879be677d60c579a9b519334858 Mon Sep 17 00:00:00 2001 From: "R.K" <rkkwapisz@gmail.com> Date: Wed, 8 May 2024 01:24:00 -0700 Subject: [PATCH] Refactor of Player Wanted Level (#3070) --- src/backend/backend.cpp | 2 +- src/backend/commands/self/clearwanted.cpp | 22 ------ src/backend/looped/looped.hpp | 2 +- src/backend/looped/self/police.cpp | 33 -------- src/backend/looped/self/wanted_level.cpp | 93 +++++++++++++++++++++++ src/byte_patch_manager.cpp | 7 -- src/core/settings.hpp | 5 +- src/util/police.hpp | 10 --- src/views/self/view_self.cpp | 43 ++++++----- 9 files changed, 124 insertions(+), 93 deletions(-) delete mode 100644 src/backend/commands/self/clearwanted.cpp delete mode 100644 src/backend/looped/self/police.cpp create mode 100644 src/backend/looped/self/wanted_level.cpp delete mode 100644 src/util/police.hpp diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp index 09e108b4..70686347 100644 --- a/src/backend/backend.cpp +++ b/src/backend/backend.cpp @@ -54,7 +54,7 @@ namespace big while (g_running) { - looped::self_police(); + looped::self_wanted(); looped::self_hud(); looped::self_dance_mode(); looped::self_persist_outfit(); diff --git a/src/backend/commands/self/clearwanted.cpp b/src/backend/commands/self/clearwanted.cpp deleted file mode 100644 index 8a281d1b..00000000 --- a/src/backend/commands/self/clearwanted.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "backend/command.hpp" -#include "natives.hpp" - -namespace big -{ - class clear_wanted : command - { - using command::command; - - virtual void execute(const command_arguments&, const std::shared_ptr<command_context> ctx) override - { - if(g_local_player && g_local_player !=nullptr && !g.self.force_wanted_level) - { - g_local_player->m_player_info->m_wanted_level = 0; - g.self.wanted_level = 0; - g_local_player->m_player_info->m_is_wanted = false; - } - } - }; - - clear_wanted g_clear_wanted("clearwantedlvl", "CLEAR_WANTED_LEVEL", "CLEAR_WANTED_LEVEL_DESC_SELF", 0); -} \ No newline at end of file diff --git a/src/backend/looped/looped.hpp b/src/backend/looped/looped.hpp index 0ef170c5..7543d267 100644 --- a/src/backend/looped/looped.hpp +++ b/src/backend/looped/looped.hpp @@ -25,7 +25,7 @@ namespace big static void player_spectate(); static void player_remote_control_vehicle(); - static void self_police(); + static void self_wanted(); static void self_hud(); static void self_dance_mode(); static void self_persist_outfit(); diff --git a/src/backend/looped/self/police.cpp b/src/backend/looped/self/police.cpp deleted file mode 100644 index cb43874d..00000000 --- a/src/backend/looped/self/police.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "backend/looped/looped.hpp" -#include "pointers.hpp" -#include "util/police.hpp" - -namespace big -{ - void looped::self_police() - { - if (g_local_player == nullptr || g_local_player->m_player_info == nullptr) [[unlikely]] - return; - - static bool bLast = false; - - bool b = g.self.never_wanted; - - if (b) - { - g_local_player->m_player_info->m_wanted_level = 0; - police::m_max_wanted_level->apply(); - police::m_max_wanted_level_2->apply(); - bLast = b; - } - else if (b != bLast) - { - police::m_max_wanted_level->restore(); - police::m_max_wanted_level_2->restore(); - bLast = b; - } - - if (g.self.force_wanted_level && !b) - g_local_player->m_player_info->m_wanted_level = g.self.wanted_level; - } -} \ No newline at end of file diff --git a/src/backend/looped/self/wanted_level.cpp b/src/backend/looped/self/wanted_level.cpp new file mode 100644 index 00000000..2ea5f472 --- /dev/null +++ b/src/backend/looped/self/wanted_level.cpp @@ -0,0 +1,93 @@ +#include "backend/command.hpp" +#include "backend/looped_command.hpp" +#include "backend/looped/looped.hpp" +#include "pointers.hpp" + +namespace big +{ + bool user_updated_wanted_level = false; + + class clear_wanted : command + { + using command::command; + + virtual void execute(const command_arguments&, const std::shared_ptr<command_context> ctx) override + { + // If we're never wanted... don't bother since there is no wanted level to clear anyway (this button won't even be shown if never_wanted is enabled) + if (g.self.never_wanted) + return; + + // Clear current wanted level + g_local_player->m_player_info->m_wanted_level = 0; + g_local_player->m_player_info->m_is_wanted = false; + + // Keep the lock if it's on, but reset the wanted level + g.self.wanted_level = 0; + } + }; + + clear_wanted g_clear_wanted("clearwanted", "CLEAR_WANTED_LEVEL", "CLEAR_WANTED_LEVEL_DESC_SELF", 0); + + class never_wanted : looped_command + { + using looped_command::looped_command; + + virtual void on_tick() override + { + // Clear current wanted level + g_local_player->m_player_info->m_wanted_level = 0; + g_local_player->m_player_info->m_is_wanted = false; + + // Since we're hiding the force wanted checkbox and wanted slider, we don't need to do anything else + } + virtual void on_disable() override + { + // If we turn off never wanted, be sure to disable force wanted to restore to a "default" setting + g.self.force_wanted_level = false; + } + }; + + never_wanted g_never_wanted("neverwanted", "NEVER_WANTED", "NEVER_WANTED", g.self.never_wanted); + + void looped::self_wanted() + { + // Don't do anything if we're supposed to be never wanted (this slider won't be shown if never_wanted is enabled) + if (g.self.never_wanted) + return; + + if (g_local_player && g_local_player->m_player_info) + { + // We only want the wanted level to update when the player changed it via the ImGui slider + if (user_updated_wanted_level) + { + g_local_player->m_player_info->m_wanted_level = g.self.wanted_level; + + if (g.self.wanted_level == 0) + g_local_player->m_player_info->m_is_wanted = false; + else + g_local_player->m_player_info->m_is_wanted = true; + + // I don't know if ImGui resets this every tick, let's assume it doesn't + user_updated_wanted_level = false; + return; + } + + // Otherwise, if we're locking the wanted level, then just keep it consistently at what the player set + if (g.self.force_wanted_level) + { + g_local_player->m_player_info->m_wanted_level = g.self.wanted_level; + + if (g.self.wanted_level == 0) + g_local_player->m_player_info->m_is_wanted = false; + else + g_local_player->m_player_info->m_is_wanted = true; + } + + if (!user_updated_wanted_level && !g.self.force_wanted_level) + { + // If the player hasn't updated the wanted level and we're not locking, then YimMenu should update its own slider value to reflect the actual in-game wanted level since it may have changed + g.self.wanted_level = g_local_player->m_player_info->m_wanted_level; + } + } + } +} \ No newline at end of file diff --git a/src/byte_patch_manager.cpp b/src/byte_patch_manager.cpp index 6e48fab3..691a2ec4 100644 --- a/src/byte_patch_manager.cpp +++ b/src/byte_patch_manager.cpp @@ -5,7 +5,6 @@ #include "memory/byte_patch.hpp" #include "pointers.hpp" #include "util/explosion_anti_cheat_bypass.hpp" -#include "util/police.hpp" #include "util/vehicle.hpp" #include "util/world_model.hpp" @@ -16,12 +15,6 @@ namespace big { static void init() { - // Restore max wanted level after menu unload - police::m_max_wanted_level = - memory::byte_patch::make(g_pointers->m_gta.m_max_wanted_level.add(5).rip().as<uint32_t*>(), 0).get(); - police::m_max_wanted_level_2 = - memory::byte_patch::make(g_pointers->m_gta.m_max_wanted_level.add(14).rip().as<uint32_t*>(), 0).get(); - // Patch World Model Spawn Bypass std::array<uint8_t, 24> world_spawn_patch; std::fill(world_spawn_patch.begin(), world_spawn_patch.end(), 0x90); diff --git a/src/core/settings.hpp b/src/core/settings.hpp index 3ee7113a..456cef41 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -311,12 +311,12 @@ namespace big } ipls{}; bool clean_player = false; + bool never_wanted = false; bool force_wanted_level = false; bool passive = false; bool free_cam = false; bool invisibility = false; bool local_visibility = true; - bool never_wanted = false; bool no_ragdoll = false; bool noclip = false; float noclip_aim_speed_multiplier = 0.25f; @@ -387,7 +387,8 @@ namespace big NLOHMANN_DEFINE_TYPE_INTRUSIVE(super_hero_fly, gradual, explosions, auto_land, charge, ptfx, fly_speed, initial_launch) } super_hero_fly{}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, force_wanted_level, passive, free_cam, invisibility, local_visibility, never_wanted, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis, interaction_menu_freedom, super_hero_fly) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, never_wanted, force_wanted_level, passive, free_cam, invisibility, local_visibility, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis, interaction_menu_freedom, super_hero_fly) + } self{}; struct session diff --git a/src/util/police.hpp b/src/util/police.hpp deleted file mode 100644 index e2c393d7..00000000 --- a/src/util/police.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace big -{ - struct police - { - inline static memory::byte_patch* m_max_wanted_level; - inline static memory::byte_patch* m_max_wanted_level_2; - }; -} \ No newline at end of file diff --git a/src/views/self/view_self.cpp b/src/views/self/view_self.cpp index ed68eb14..e92eeb61 100644 --- a/src/views/self/view_self.cpp +++ b/src/views/self/view_self.cpp @@ -10,6 +10,8 @@ namespace big { + extern bool user_updated_wanted_level; + void view::self() { components::command_button<"suicide">(); @@ -204,25 +206,32 @@ namespace big } }); - ImGui::Checkbox("NEVER_WANTED"_T.data(), &g.self.never_wanted); - components::options_modal("POLICE"_T.data(), [] { - ImGui::Checkbox("NEVER_WANTED"_T.data(), &g.self.never_wanted); - components::command_button<"clearwantedlvl">(); - if (!g.self.never_wanted) - { - ImGui::Checkbox("FORCE_WANTED_LVL"_T.data(), &g.self.force_wanted_level); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("FORCE_WANTED_LVL_INFO"_T.data()); - ImGui::Text("WANTED_LVL"_T.data()); - if (ImGui::SliderInt("###wanted_level", &g.self.wanted_level, 0, 5) && !g.self.force_wanted_level && g_local_player != nullptr) - { - g_local_player->m_player_info->m_wanted_level = g.self.wanted_level; - } - } - }); - ImGui::EndGroup(); + ImGui::SeparatorText("WANTED_LEVEL"_T.data()); + + ImGui::Checkbox("NEVER_WANTED"_T.data(), &g.self.never_wanted); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("NEVER_WANTED_DESC"_T.data()); + + // Only show all the other stuff like clear wanted, force wanted, and the slider if we don't have never_wanted enabled, since never_wanted overrides all of that + if (!g.self.never_wanted) + { + ImGui::SameLine(); + components::command_button<"clearwanted">(); + + // Most ImGui widgets return true when they've been changed, so this is useful to prevent us from overwriting the wanted level's natural decay/progression if we're not keeping it locked + ImGui::SetNextItemWidth(200); + user_updated_wanted_level = ImGui::SliderInt("###wanted_level", &g.self.wanted_level, 0, 5); + + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("WANTED_LEVEL_SLIDER_DESC"_T.data()); + ImGui::SameLine(); + ImGui::Checkbox("FORCE_WANTED_LEVEL"_T.data(), &g.self.force_wanted_level); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("FORCE_WANTED_LEVEL_DESC"_T.data()); + } + ImGui::SeparatorText("PROOFS"_T.data()); if (ImGui::Button("CHECK_ALL"_T.data()))