feat(world): model swapper (#1003)

This commit is contained in:
Aure7138 2023-02-21 06:20:40 +08:00 committed by GitHub
parent 99818d5301
commit 9c9164bfef
11 changed files with 167 additions and 3 deletions

View File

@ -472,7 +472,15 @@ namespace big
NLOHMANN_DEFINE_TYPE_INTRUSIVE(blackhole, enable, include_peds, include_vehicles, color, alpha)
} blackhole{};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(world, water, spawn_ped, custom_time, blackhole)
struct model_swapper
{
std::vector<std::pair<std::string, std::string>> models;
std::mutex m;
bool update = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(model_swapper, models)
} model_swapper{};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(world, water, spawn_ped, custom_time, blackhole, model_swapper)
} world{};
struct spoofing

View File

@ -104,6 +104,8 @@ namespace big
detour_hook_helper::add<hooks::write_player_camera_data_node>("WPCDN", g_pointers->m_write_player_camera_data_node);
detour_hook_helper::add<hooks::get_model_info>("GMI", g_pointers->m_get_model_info);
g_hooking = this;
}

View File

@ -150,6 +150,8 @@ namespace big
static bool receive_pickup(rage::netObject* netobject, void* unk, CPed* ped);
static bool write_player_camera_data_node(rage::netObject* player, CPlayerCameraDataNode* node);
static CBaseModelInfo* get_model_info(rage::joaat_t hash, uint32_t* a2);
};
class minhook_keepalive

View File

@ -0,0 +1,37 @@
#include "hooking.hpp"
#include "util/model_info.hpp"
namespace big
{
static auto get_hash(const std::string& str)
{
rage::joaat_t hash = 0;
if (str.substr(0, 2) == "0x")
std::stringstream(str.substr(2)) >> std::hex >> hash;
else
hash = rage::joaat(str.c_str());
return hash;
}
static std::vector<std::pair<rage::joaat_t, rage::joaat_t>> cache_models;
static void update()
{
std::lock_guard lock(g.world.model_swapper.m);
cache_models.clear();
for (size_t i = 0; i < g.world.model_swapper.models.size(); i++)
cache_models.push_back(std::make_pair(get_hash(g.world.model_swapper.models[i].first), get_hash(g.world.model_swapper.models[i].second)));
g.world.model_swapper.update = false;
}
CBaseModelInfo* hooks::get_model_info(rage::joaat_t hash, uint32_t* a2)
{
static bool init = ([] { update(); }(), true);
if (g.world.model_swapper.update)
update();
for (size_t i = 0; i < cache_models.size(); i++)
if (cache_models[i].first == hash)
return g_hooking->get_original<get_model_info>()(cache_models[i].second, a2);
return g_hooking->get_original<get_model_info>()(hash, a2);
}
}

View File

@ -337,6 +337,12 @@ namespace big
m_model_table = ptr.add(3).rip().as<HashTable<CBaseModelInfo*>*>();
});
// Get Model Info
main_batch.add("GMI", "41 3B 0A 74 54", [this](memory::handle ptr)
{
m_get_model_info = ptr.sub(46).as<PVOID>();
});
// Get Label Text
main_batch.add("GLT", "75 ? E8 ? ? ? ? 8B 0D ? ? ? ? 65 48 8B 04 25 ? ? ? ? BA ? ? ? ? 48 8B 04 C8 8B 0C 02 D1 E9", [this](memory::handle ptr)
{

View File

@ -79,6 +79,7 @@ namespace big
functions::get_screen_coords_for_world_coords m_get_screen_coords_for_world_coords{};
HashTable<CBaseModelInfo*>* m_model_table;
PVOID m_get_model_info;
PVOID m_gta_thread_start{};
PVOID m_gta_thread_kill{};
@ -88,8 +89,6 @@ namespace big
functions::get_gameplay_cam_coords m_get_gameplay_cam_coords;
functions::give_pickup_rewards m_give_pickup_rewards{};
PVOID m_write_player_gamer_data_node{};
functions::trigger_script_event m_trigger_script_event{};
@ -187,6 +186,7 @@ namespace big
PVOID m_serialize_join_request_message;
functions::give_pickup_rewards m_give_pickup_rewards{};
functions::send_network_damage m_send_network_damage;
functions::request_ragdoll m_request_ragdoll;
functions::request_control m_request_control;

View File

@ -103,6 +103,10 @@ namespace big
rage::fvector3 pos = *m_pointer->m_navigation->get_position();
teleport::to_coords({ pos.x, pos.y, pos.z });
}},
{"COPY HASH", [this] {
ImGui::SetClipboardText(std::format("0x{:08X}", (rage::joaat_t)m_pointer->m_model_info->m_hash).c_str());
g_notification_service->push("Context Menu", std::format("Copy hash 0x{:08X}", (rage::joaat_t)m_pointer->m_model_info->m_hash).c_str());
}}
}
};

View File

@ -30,6 +30,7 @@ namespace big
TRAIN,
WATER,
BLACKHOLE,
MODEL_SWAPPER,
NETWORK,
SESSION,
@ -88,6 +89,7 @@ namespace big
{ tabs::TRAIN, { "Train", view::train }},
{ tabs::WATER, { "Water", view::water }},
{ tabs::BLACKHOLE, { "Blackhole", view::blackhole }},
{ tabs::MODEL_SWAPPER, { "Model Swapper", view::model_swapper }},
}}},
{tabs::NETWORK, { "Network", nullptr, {
{ tabs::SPOOFING, { "Spoofing", view::spoofing }},

View File

@ -1,6 +1,7 @@
#pragma once
#include "gta/joaat.hpp"
#include "pointers.hpp"
#include "vehicle/CVehicleModelInfo.hpp"
namespace big
{

View File

@ -55,6 +55,7 @@ namespace big
static void train();
static void water();
static void blackhole();
static void model_swapper();
static void player_info();
static void player_troll();

View File

@ -0,0 +1,101 @@
#include "views/view.hpp"
#include "pointers.hpp"
namespace big
{
void view::model_swapper()
{
ImGui::Text("Models that have already been created will not be affected much");
ImGui::Text("Prefix 0x for hexadecimal hash");
ImGui::Text("Use context menu to copy entity hash");
static char dst_text[256];
static char src_text[256];
static size_t selected_index = -1;
static float width = *g_pointers->m_resolution_x / 5.0;
ImGui::SetNextItemWidth(width);
ImGui::InputText("Dst", dst_text, IM_ARRAYSIZE(dst_text)); ImGui::SameLine();
ImGui::SetNextItemWidth(width);
ImGui::InputText("Src", src_text, IM_ARRAYSIZE(src_text)); ImGui::SameLine();
if (ImGui::Button("Add/Change"))
{
std::lock_guard lock(g.world.model_swapper.m);
if (dst_text[0] == '\0' || src_text[0] == '\0')
{
g_notification_service->push_error("Model Swapper", "Wrong input");
return;
}
std::string str = dst_text;
transform(str.begin(), str.end(), str.begin(), ::tolower);
size_t i = 0;
for (; i < g.world.model_swapper.models.size(); i++)
{
std::string tmp = g.world.model_swapper.models[i].first;
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
if (str == tmp)
{
g.world.model_swapper.models[i].first = dst_text;
g.world.model_swapper.models[i].second = src_text;
break;
}
}
if (i == g.world.model_swapper.models.size())
g.world.model_swapper.models.push_back(std::make_pair(dst_text, src_text));
g.world.model_swapper.update = true;
} ImGui::SameLine();
if (ImGui::Button("Delete"))
{
std::lock_guard lock(g.world.model_swapper.m);
if (!g.world.model_swapper.models.size() || selected_index < 0 || selected_index >= g.world.model_swapper.models.size())
{
g_notification_service->push_error("Model Swapper", "Invalid index");
return;
}
g.world.model_swapper.models.erase(std::begin(g.world.model_swapper.models) + selected_index);
g.world.model_swapper.update = true;
} ImGui::SameLine();
if (ImGui::Button("Clear"))
{
std::lock_guard lock(g.world.model_swapper.m);
g.world.model_swapper.models.clear();
g.world.model_swapper.update = true;
}
ImGui::SetNextItemWidth(width);
if (ImGui::BeginListBox("Dst##model_swapper_dst"))
{
for (size_t i = 0; i < g.world.model_swapper.models.size(); i++)
{
if (ImGui::Selectable(g.world.model_swapper.models[i].first.c_str(), selected_index == i))
{
selected_index = i;
strcpy_s(dst_text, sizeof(dst_text), g.world.model_swapper.models[i].first.c_str());
strcpy_s(src_text, sizeof(src_text), g.world.model_swapper.models[i].second.c_str());
}
if (selected_index == i)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
} ImGui::SameLine();
ImGui::SetNextItemWidth(width);
if (ImGui::BeginListBox("Src##model_swapper_src"))
{
for (size_t i = 0; i < g.world.model_swapper.models.size(); i++)
{
if (ImGui::Selectable(g.world.model_swapper.models[i].second.c_str(), selected_index == i))
{
selected_index = i;
strcpy_s(dst_text, sizeof(dst_text), g.world.model_swapper.models[i].first.c_str());
strcpy_s(src_text, sizeof(src_text), g.world.model_swapper.models[i].second.c_str());
}
if (selected_index == i)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
}
}