refactor: move Request Model logic to helper function (#2669)
This commit is contained in:
parent
7efbee2e85
commit
ad1dfc71d2
@ -25,8 +25,8 @@ namespace big
|
||||
|
||||
virtual void execute(const command_arguments& args, const std::shared_ptr<command_context> ctx) override
|
||||
{
|
||||
const auto hash = args.get<rage::joaat_t>(0);
|
||||
if (!STREAMING::IS_MODEL_IN_CDIMAGE(hash) || !STREAMING::IS_MODEL_A_VEHICLE(hash))
|
||||
const auto hash = args.get<rage::joaat_t>(0);
|
||||
if (!entity::request_model(hash))
|
||||
{
|
||||
ctx->report_error("BACKEND_SPAWN_VEHICLE_INVALID_MODEL"_T.data());
|
||||
return;
|
||||
@ -61,8 +61,6 @@ namespace big
|
||||
};
|
||||
|
||||
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",
|
||||
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_maxed("spawnmaxed", "SPAWN_MAXED", "SPAWN_MAXED_DESC", g.spawn_vehicle.spawn_maxed);
|
||||
bool_command g_spawn_inside("spawnin", "SPAWN_IN", "SPAWN_IN_DESC", g.spawn_vehicle.spawn_inside);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "util/explosion_anti_cheat_bypass.hpp"
|
||||
#include "util/police.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "util/world_model.hpp"
|
||||
|
||||
extern "C" void sound_overload_detour();
|
||||
uint64_t g_sound_overload_ret_addr;
|
||||
@ -21,6 +22,10 @@ namespace big
|
||||
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
|
||||
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
|
||||
explosion_anti_cheat_bypass::m_can_blame_others =
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ namespace big
|
||||
{
|
||||
memory::handle m_max_wanted_level;
|
||||
|
||||
memory::handle m_world_model_spawn_bypass;
|
||||
|
||||
memory::handle m_blame_explode;
|
||||
|
||||
memory::handle m_explosion_patch;
|
||||
@ -100,7 +102,6 @@ namespace big
|
||||
float* m_gravity_level;
|
||||
functions::set_gravity_level m_set_gravity_level;
|
||||
|
||||
PVOID m_world_model_spawn_bypass;
|
||||
PVOID m_native_return;
|
||||
PVOID m_get_label_text;
|
||||
functions::check_chat_profanity* m_check_chat_profanity;
|
||||
@ -363,4 +364,4 @@ namespace big
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "pointers.hpp"
|
||||
|
||||
#include "gta_pointers_layout_info.hpp"
|
||||
#include "sc_pointers_layout_info.hpp"
|
||||
#include "memory/all.hpp"
|
||||
#include "sc_pointers_layout_info.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
@ -159,15 +159,6 @@ namespace big
|
||||
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
|
||||
{
|
||||
"NRF",
|
||||
@ -1517,6 +1508,15 @@ namespace big
|
||||
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
|
||||
{
|
||||
"BE",
|
||||
|
@ -56,7 +56,7 @@ namespace big::entity
|
||||
ENTITY::DELETE_ENTITY(&vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ENTITY::DETACH_ENTITY(ent, 1, 1);
|
||||
ENTITY::SET_ENTITY_COORDS_NO_OFFSET(ent, 7000.f, 7000.f, 15.f, 0, 0, 0);
|
||||
if (!ENTITY::IS_ENTITY_A_MISSION_ENTITY(ent))
|
||||
@ -193,33 +193,71 @@ namespace big::entity
|
||||
|
||||
bool load_ground_at_3dcoord(Vector3& location)
|
||||
{
|
||||
constexpr float max_ground_check = 1000.f;
|
||||
constexpr int max_attempts = 300;
|
||||
float ground_z = location.z;
|
||||
int current_attempts = 0;
|
||||
bool found_ground;
|
||||
constexpr float max_ground_check = 1000.f;
|
||||
constexpr int max_attempts = 300;
|
||||
float ground_z = location.z;
|
||||
int current_attempts = 0;
|
||||
bool found_ground;
|
||||
float height;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if (current_attempts % 10 == 0)
|
||||
{
|
||||
location.z += 25.f;
|
||||
}
|
||||
if (current_attempts % 10 == 0)
|
||||
{
|
||||
location.z += 25.f;
|
||||
}
|
||||
|
||||
++current_attempts;
|
||||
++current_attempts;
|
||||
|
||||
script::get_current()->yield();
|
||||
} while (!found_ground && current_attempts < max_attempts);
|
||||
script::get_current()->yield();
|
||||
} while (!found_ground && current_attempts < max_attempts);
|
||||
|
||||
if (!found_ground)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!found_ground)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
location.z = ground_z + 1.f;
|
||||
return true;
|
||||
if (WATER::GET_WATER_HEIGHT(location.x, location.y, location.z, &height))
|
||||
{
|
||||
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)
|
||||
@ -303,4 +341,4 @@ namespace big::entity
|
||||
|
||||
return closest_entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ namespace big::entity
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
@ -446,24 +446,19 @@ namespace big::ped
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++)
|
||||
if (entity::request_model(hash))
|
||||
{
|
||||
STREAMING::REQUEST_MODEL(hash);
|
||||
script::get_current()->yield();
|
||||
Ped 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;
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void set_ped_random_component_variation(Ped ped)
|
||||
|
@ -6,8 +6,8 @@ namespace big::vehicle
|
||||
{
|
||||
switch (speed_unit)
|
||||
{
|
||||
case SpeedUnit::KMPH: return mps * 3.6f; break;
|
||||
case SpeedUnit::MIPH: return mps * 2.2369f; break;
|
||||
case SpeedUnit::KMPH: return mps * 3.6f;
|
||||
case SpeedUnit::MIPH: return mps * 2.2369f;
|
||||
}
|
||||
|
||||
return mps;
|
||||
@ -17,8 +17,8 @@ namespace big::vehicle
|
||||
{
|
||||
switch (speed_unit)
|
||||
{
|
||||
case SpeedUnit::KMPH: return speed / 3.6f; break;
|
||||
case SpeedUnit::MIPH: return speed / 2.2369f; break;
|
||||
case SpeedUnit::KMPH: return speed / 3.6f;
|
||||
case SpeedUnit::MIPH: return speed / 2.2369f;
|
||||
}
|
||||
|
||||
return speed;
|
||||
@ -77,7 +77,7 @@ namespace big::vehicle
|
||||
|
||||
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);
|
||||
}
|
||||
@ -152,27 +152,20 @@ namespace big::vehicle
|
||||
|
||||
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);
|
||||
script::get_current()->yield();
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading)
|
||||
@ -226,7 +219,7 @@ namespace big::vehicle
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto veh = vehicle::get_closest_to_location(tmpLocation, 200);
|
||||
auto veh = get_closest_to_location(tmpLocation, 200);
|
||||
if (veh == 0)
|
||||
{
|
||||
return 0;
|
||||
@ -551,8 +544,6 @@ namespace big::vehicle
|
||||
|
||||
void max_vehicle(Vehicle veh)
|
||||
{
|
||||
Hash model = ENTITY::GET_ENTITY_MODEL(veh);
|
||||
|
||||
VEHICLE::SET_VEHICLE_MOD_KIT(veh, 0);
|
||||
|
||||
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);
|
||||
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;
|
||||
|
@ -3,38 +3,29 @@
|
||||
#include "pointers.hpp"
|
||||
#include "script.hpp"
|
||||
|
||||
struct world_model_bypass
|
||||
{
|
||||
inline static memory::byte_patch* m_world_model_spawn_bypass;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
STREAMING::REQUEST_MODEL(hash);
|
||||
for (int i = 0; i < 100 && !STREAMING::HAS_MODEL_LOADED(hash); i++)
|
||||
if (entity::request_model(hash))
|
||||
{
|
||||
script::get_current()->yield();
|
||||
}
|
||||
if (!STREAMING::HAS_MODEL_LOADED(hash))
|
||||
{
|
||||
LOG(WARNING) << "Failed to load model " << HEX_TO_UPPER(hash);
|
||||
return 0;
|
||||
world_model_bypass::m_world_model_spawn_bypass->apply();
|
||||
|
||||
const auto object = OBJECT::CREATE_OBJECT(hash, location.x, location.y, location.z, is_networked, false, false);
|
||||
|
||||
world_model_bypass::m_world_model_spawn_bypass->restore();
|
||||
|
||||
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
std::call_once(once_flag, setup_backup);
|
||||
memset(g_pointers->m_gta.m_world_model_spawn_bypass, 0x90, patch_size);
|
||||
|
||||
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;
|
||||
LOG(WARNING) << "Failed to load model " << HEX_TO_UPPER(hash);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user