refactor: move Request Model logic to helper function (#2669)

This commit is contained in:
Anvar 2024-01-31 04:47:03 -05:00 committed by GitHub
parent 7efbee2e85
commit ad1dfc71d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 147 additions and 137 deletions

View File

@ -25,8 +25,8 @@ namespace big
virtual void execute(const command_arguments& args, const std::shared_ptr<command_context> ctx) override virtual void execute(const command_arguments& args, const std::shared_ptr<command_context> ctx) override
{ {
const auto hash = args.get<rage::joaat_t>(0); const auto hash = args.get<rage::joaat_t>(0);
if (!STREAMING::IS_MODEL_IN_CDIMAGE(hash) || !STREAMING::IS_MODEL_A_VEHICLE(hash)) if (!entity::request_model(hash))
{ {
ctx->report_error("BACKEND_SPAWN_VEHICLE_INVALID_MODEL"_T.data()); ctx->report_error("BACKEND_SPAWN_VEHICLE_INVALID_MODEL"_T.data());
return; return;
@ -61,8 +61,6 @@ namespace big
}; };
spawn_vehicle g_spawn_vehicle("spawn", "GUI_TAB_SPAWN_VEHICLE", "BACKEND_SPAWN_VEHICLE_DESC", 1); spawn_vehicle g_spawn_vehicle("spawn", "GUI_TAB_SPAWN_VEHICLE", "BACKEND_SPAWN_VEHICLE_DESC", 1);
bool_command g_spawn_maxed("spawnmaxed", "SPAWN_MAXED", "SPAWN_MAXED_DESC", bool_command g_spawn_maxed("spawnmaxed", "SPAWN_MAXED", "SPAWN_MAXED_DESC", g.spawn_vehicle.spawn_maxed);
g.spawn_vehicle.spawn_maxed); bool_command g_spawn_inside("spawnin", "SPAWN_IN", "SPAWN_IN_DESC", g.spawn_vehicle.spawn_inside);
bool_command g_spawn_inside("spawnin", "SPAWN_IN", "SPAWN_IN_DESC",
g.spawn_vehicle.spawn_inside);
} }

View File

@ -7,6 +7,7 @@
#include "util/explosion_anti_cheat_bypass.hpp" #include "util/explosion_anti_cheat_bypass.hpp"
#include "util/police.hpp" #include "util/police.hpp"
#include "util/vehicle.hpp" #include "util/vehicle.hpp"
#include "util/world_model.hpp"
extern "C" void sound_overload_detour(); extern "C" void sound_overload_detour();
uint64_t g_sound_overload_ret_addr; uint64_t g_sound_overload_ret_addr;
@ -21,6 +22,10 @@ namespace big
police::m_max_wanted_level_2 = 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(); 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
world_model_bypass::m_world_model_spawn_bypass =
memory::byte_patch::make(g_pointers->m_gta.m_world_model_spawn_bypass.as<PVOID*>(), 0).get();
// Patch blocked explosions // Patch blocked explosions
explosion_anti_cheat_bypass::m_can_blame_others = explosion_anti_cheat_bypass::m_can_blame_others =
memory::byte_patch::make(g_pointers->m_gta.m_blame_explode.as<uint16_t*>(), 0xE990).get(); memory::byte_patch::make(g_pointers->m_gta.m_blame_explode.as<uint16_t*>(), 0xE990).get();
@ -98,4 +103,4 @@ namespace big
g_byte_patch_manager = nullptr; g_byte_patch_manager = nullptr;
} }
} }

View File

@ -42,6 +42,8 @@ namespace big
{ {
memory::handle m_max_wanted_level; memory::handle m_max_wanted_level;
memory::handle m_world_model_spawn_bypass;
memory::handle m_blame_explode; memory::handle m_blame_explode;
memory::handle m_explosion_patch; memory::handle m_explosion_patch;
@ -100,7 +102,6 @@ namespace big
float* m_gravity_level; float* m_gravity_level;
functions::set_gravity_level m_set_gravity_level; functions::set_gravity_level m_set_gravity_level;
PVOID m_world_model_spawn_bypass;
PVOID m_native_return; PVOID m_native_return;
PVOID m_get_label_text; PVOID m_get_label_text;
functions::check_chat_profanity* m_check_chat_profanity; functions::check_chat_profanity* m_check_chat_profanity;
@ -363,4 +364,4 @@ namespace big
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
} }

View File

@ -1,8 +1,8 @@
#include "pointers.hpp" #include "pointers.hpp"
#include "gta_pointers_layout_info.hpp" #include "gta_pointers_layout_info.hpp"
#include "sc_pointers_layout_info.hpp"
#include "memory/all.hpp" #include "memory/all.hpp"
#include "sc_pointers_layout_info.hpp"
namespace big namespace big
{ {
@ -159,15 +159,6 @@ namespace big
g_pointers->m_gta.m_swapchain = ptr.add(3).rip().as<IDXGISwapChain**>(); g_pointers->m_gta.m_swapchain = ptr.add(3).rip().as<IDXGISwapChain**>();
} }
}, },
// World Model Spawn Bypass
{
"WMSB",
"48 85 C0 0F 84 ? ? ? ? 8B 48 50",
[](memory::handle ptr)
{
g_pointers->m_gta.m_world_model_spawn_bypass = ptr.as<PVOID>();
}
},
// Native Return Spoofer // Native Return Spoofer
{ {
"NRF", "NRF",
@ -1517,6 +1508,15 @@ namespace big
g_pointers->m_gta.m_max_wanted_level = ptr; g_pointers->m_gta.m_max_wanted_level = ptr;
} }
}, },
// World Model Spawn Bypass
{
"WMSB",
"48 85 C0 0F 84 ? ? ? ? 8B 48 50",
[](memory::handle ptr)
{
g_pointers->m_gta.m_world_model_spawn_bypass = ptr;
}
},
// Blame Explode // Blame Explode
{ {
"BE", "BE",

View File

@ -56,7 +56,7 @@ namespace big::entity
ENTITY::DELETE_ENTITY(&vehicle); ENTITY::DELETE_ENTITY(&vehicle);
} }
} }
ENTITY::DETACH_ENTITY(ent, 1, 1); ENTITY::DETACH_ENTITY(ent, 1, 1);
ENTITY::SET_ENTITY_COORDS_NO_OFFSET(ent, 7000.f, 7000.f, 15.f, 0, 0, 0); ENTITY::SET_ENTITY_COORDS_NO_OFFSET(ent, 7000.f, 7000.f, 15.f, 0, 0, 0);
if (!ENTITY::IS_ENTITY_A_MISSION_ENTITY(ent)) if (!ENTITY::IS_ENTITY_A_MISSION_ENTITY(ent))
@ -193,33 +193,71 @@ namespace big::entity
bool load_ground_at_3dcoord(Vector3& location) bool load_ground_at_3dcoord(Vector3& location)
{ {
constexpr float max_ground_check = 1000.f; constexpr float max_ground_check = 1000.f;
constexpr int max_attempts = 300; constexpr int max_attempts = 300;
float ground_z = location.z; float ground_z = location.z;
int current_attempts = 0; int current_attempts = 0;
bool found_ground; bool found_ground;
float height;
do { do
found_ground = MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, max_ground_check, &ground_z, FALSE, FALSE); {
STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, location.z); found_ground = MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, max_ground_check, &ground_z, FALSE, FALSE);
STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, location.z);
if (current_attempts % 10 == 0) if (current_attempts % 10 == 0)
{ {
location.z += 25.f; location.z += 25.f;
} }
++current_attempts; ++current_attempts;
script::get_current()->yield(); script::get_current()->yield();
} while (!found_ground && current_attempts < max_attempts); } while (!found_ground && current_attempts < max_attempts);
if (!found_ground) if (!found_ground)
{ {
return false; return false;
} }
location.z = ground_z + 1.f; if (WATER::GET_WATER_HEIGHT(location.x, location.y, location.z, &height))
return true; {
location.z = height;
}
else
{
location.z = ground_z + 1.f;
}
return true;
}
bool request_model(rage::joaat_t hash)
{
if (STREAMING::HAS_MODEL_LOADED(hash))
{
return true;
}
bool has_loaded;
if (STREAMING::IS_MODEL_VALID(hash) && STREAMING::IS_MODEL_IN_CDIMAGE(hash))
{
do
{
has_loaded = STREAMING::HAS_MODEL_LOADED(hash);
if (has_loaded)
break;
STREAMING::REQUEST_MODEL(hash);
script::get_current()->yield();
} while (!has_loaded);
return true;
}
return false;
} }
double distance_to_middle_of_screen(const rage::fvector2& screen_pos) double distance_to_middle_of_screen(const rage::fvector2& screen_pos)
@ -303,4 +341,4 @@ namespace big::entity
return closest_entity; return closest_entity;
} }
} }

View File

@ -18,6 +18,7 @@ namespace big::entity
bool network_has_control_of_entity(rage::netObject* net_object); bool network_has_control_of_entity(rage::netObject* net_object);
std::vector<Entity> get_entities(bool vehicles, bool peds, bool props = false, bool include_self_veh = false); std::vector<Entity> get_entities(bool vehicles, bool peds, bool props = false, bool include_self_veh = false);
bool load_ground_at_3dcoord(Vector3& location); bool load_ground_at_3dcoord(Vector3& location);
bool request_model(rage::joaat_t hash);
double distance_to_middle_of_screen(const rage::fvector2& screen_pos); double distance_to_middle_of_screen(const rage::fvector2& screen_pos);
Entity get_entity_closest_to_middle_of_screen(rage::fwEntity** pointer = nullptr, std::vector<Entity> ignore_entities = {}, bool include_veh = true, bool include_ped = true, bool include_prop = true, bool include_players = true); Entity get_entity_closest_to_middle_of_screen(rage::fwEntity** pointer = nullptr, std::vector<Entity> ignore_entities = {}, bool include_veh = true, bool include_ped = true, bool include_prop = true, bool include_players = true);
} }

View File

@ -446,24 +446,19 @@ namespace big::ped
inline bool change_player_model(const Hash hash) inline bool change_player_model(const Hash hash)
{ {
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++) if (entity::request_model(hash))
{ {
STREAMING::REQUEST_MODEL(hash); self::ped = PLAYER::PLAYER_PED_ID();
PLAYER::SET_PLAYER_MODEL(self::id, hash);
script::get_current()->yield(); script::get_current()->yield();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
for (int i = 0; i < 12; i++)
{
PED::SET_PED_COMPONENT_VARIATION(self::ped, i, PED::GET_PED_DRAWABLE_VARIATION(self::ped, i), PED::GET_PED_TEXTURE_VARIATION(self::ped, i), PED::GET_PED_PALETTE_VARIATION(self::ped, i));
}
return true;
} }
if (!STREAMING::HAS_MODEL_LOADED(hash)) return false;
{
return false;
}
PLAYER::SET_PLAYER_MODEL(self::id, hash);
self::ped = PLAYER::PLAYER_PED_ID();
script::get_current()->yield();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
for (int i = 0; i < 12; i++)
{
PED::SET_PED_COMPONENT_VARIATION(self::ped, i, PED::GET_PED_DRAWABLE_VARIATION(self::ped, i), PED::GET_PED_TEXTURE_VARIATION(self::ped, i), PED::GET_PED_PALETTE_VARIATION(self::ped, i));
}
return true;
} }
inline bool steal_outfit(const Ped target) inline bool steal_outfit(const Ped target)
@ -512,29 +507,22 @@ namespace big::ped
inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true) inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true)
{ {
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++) if (entity::request_model(hash))
{ {
STREAMING::REQUEST_MODEL(hash); Ped ped = PED::CREATE_PED(pedType, hash, location.x, location.y, location.z, heading, is_networked, false);
script::get_current()->yield();
script::get_current()->yield();
if (clone)
{
PED::CLONE_PED_TO_TARGET(clone, ped);
}
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
return ped;
} }
return 0;
if (!STREAMING::HAS_MODEL_LOADED(hash))
{
return 0;
}
auto ped = PED::CREATE_PED(pedType, hash, location.x, location.y, location.z, heading, is_networked, false);
script::get_current()->yield();
if (clone)
{
PED::CLONE_PED_TO_TARGET(clone, ped);
}
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
return ped;
} }
inline void set_ped_random_component_variation(Ped ped) inline void set_ped_random_component_variation(Ped ped)

View File

@ -6,8 +6,8 @@ namespace big::vehicle
{ {
switch (speed_unit) switch (speed_unit)
{ {
case SpeedUnit::KMPH: return mps * 3.6f; break; case SpeedUnit::KMPH: return mps * 3.6f;
case SpeedUnit::MIPH: return mps * 2.2369f; break; case SpeedUnit::MIPH: return mps * 2.2369f;
} }
return mps; return mps;
@ -17,8 +17,8 @@ namespace big::vehicle
{ {
switch (speed_unit) switch (speed_unit)
{ {
case SpeedUnit::KMPH: return speed / 3.6f; break; case SpeedUnit::KMPH: return speed / 3.6f;
case SpeedUnit::MIPH: return speed / 2.2369f; break; case SpeedUnit::MIPH: return speed / 2.2369f;
} }
return speed; return speed;
@ -77,7 +77,7 @@ namespace big::vehicle
if (driver_ped != 0) if (driver_ped != 0)
{ {
if (PED::GET_PED_TYPE(driver_ped) == ePedType::PED_TYPE_NETWORK_PLAYER) if (PED::GET_PED_TYPE(driver_ped) == PED_TYPE_NETWORK_PLAYER)
{ {
TASK::CLEAR_PED_TASKS_IMMEDIATELY(driver_ped); TASK::CLEAR_PED_TASKS_IMMEDIATELY(driver_ped);
} }
@ -152,27 +152,20 @@ namespace big::vehicle
Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked, bool script_veh) Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked, bool script_veh)
{ {
for (int i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++) if (entity::request_model(hash))
{ {
STREAMING::REQUEST_MODEL(hash); auto veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, is_networked, script_veh, false);
script::get_current()->yield();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
if (*g_pointers->m_gta.m_is_session_started)
{
set_mp_bitset(veh);
}
return veh;
} }
return 0;
if (!STREAMING::HAS_MODEL_LOADED(hash))
{
return 0;
}
auto veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, is_networked, script_veh, false);
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
if (*g_pointers->m_gta.m_is_session_started)
{
set_mp_bitset(veh);
}
return veh;
} }
Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading) Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading)
@ -226,7 +219,7 @@ namespace big::vehicle
return 0; return 0;
} }
auto veh = vehicle::get_closest_to_location(tmpLocation, 200); auto veh = get_closest_to_location(tmpLocation, 200);
if (veh == 0) if (veh == 0)
{ {
return 0; return 0;
@ -551,8 +544,6 @@ namespace big::vehicle
void max_vehicle(Vehicle veh) void max_vehicle(Vehicle veh)
{ {
Hash model = ENTITY::GET_ENTITY_MODEL(veh);
VEHICLE::SET_VEHICLE_MOD_KIT(veh, 0); VEHICLE::SET_VEHICLE_MOD_KIT(veh, 0);
VEHICLE::TOGGLE_VEHICLE_MOD(veh, MOD_TURBO, TRUE); VEHICLE::TOGGLE_VEHICLE_MOD(veh, MOD_TURBO, TRUE);
@ -688,13 +679,10 @@ namespace big::vehicle
VEHICLE::SET_VEHICLE_INDIVIDUAL_DOORS_LOCKED(veh, i, (int)state); VEHICLE::SET_VEHICLE_INDIVIDUAL_DOORS_LOCKED(veh, i, (int)state);
return VEHICLE::GET_VEHICLE_DOOR_LOCK_STATUS(veh) == (int)state; return VEHICLE::GET_VEHICLE_DOOR_LOCK_STATUS(veh) == (int)state;
} }
else if (VEHICLE::GET_IS_DOOR_VALID(veh, (int)doorId))
{ VEHICLE::SET_VEHICLE_INDIVIDUAL_DOORS_LOCKED(veh, (int)doorId, (int)state);
if (VEHICLE::GET_IS_DOOR_VALID(veh, (int)doorId))
VEHICLE::SET_VEHICLE_INDIVIDUAL_DOORS_LOCKED(veh, (int)doorId, (int)state);
return VEHICLE::GET_VEHICLE_INDIVIDUAL_DOOR_LOCK_STATUS(veh, (int)doorId) == (int)state; return VEHICLE::GET_VEHICLE_INDIVIDUAL_DOOR_LOCK_STATUS(veh, (int)doorId) == (int)state;
}
} }
return false; return false;

View File

@ -3,38 +3,29 @@
#include "pointers.hpp" #include "pointers.hpp"
#include "script.hpp" #include "script.hpp"
struct world_model_bypass
{
inline static memory::byte_patch* m_world_model_spawn_bypass;
};
namespace big::world_model namespace big::world_model
{ {
constexpr size_t patch_size = 24;
static inline std::once_flag once_flag;
static inline std::array<byte, patch_size> backup;
static inline void setup_backup()
{
memcpy(backup.data(), g_pointers->m_gta.m_world_model_spawn_bypass, patch_size);
}
inline Object spawn(Hash hash, Vector3 location = Vector3(), bool is_networked = true) inline Object spawn(Hash hash, Vector3 location = Vector3(), bool is_networked = true)
{ {
STREAMING::REQUEST_MODEL(hash); if (entity::request_model(hash))
for (int i = 0; i < 100 && !STREAMING::HAS_MODEL_LOADED(hash); i++)
{ {
script::get_current()->yield(); world_model_bypass::m_world_model_spawn_bypass->apply();
}
if (!STREAMING::HAS_MODEL_LOADED(hash)) const auto object = OBJECT::CREATE_OBJECT(hash, location.x, location.y, location.z, is_networked, false, false);
{
LOG(WARNING) << "Failed to load model " << HEX_TO_UPPER(hash); world_model_bypass::m_world_model_spawn_bypass->restore();
return 0;
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
return object;
} }
std::call_once(once_flag, setup_backup); LOG(WARNING) << "Failed to load model " << HEX_TO_UPPER(hash);
memset(g_pointers->m_gta.m_world_model_spawn_bypass, 0x90, patch_size); return 0;
const auto object = OBJECT::CREATE_OBJECT(hash, location.x, location.y, location.z, is_networked, false, false);
memcpy(g_pointers->m_gta.m_world_model_spawn_bypass, backup.data(), patch_size);
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
return object;
} }
} }