mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-01-04 00:23:27 +08:00
feat(world): model swapper (#1003)
This commit is contained in:
parent
99818d5301
commit
9c9164bfef
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
37
src/hooks/misc/get_model_info.cpp
Normal file
37
src/hooks/misc/get_model_info.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 }},
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "gta/joaat.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "vehicle/CVehicleModelInfo.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
@ -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();
|
||||
|
101
src/views/world/model_swapper.cpp
Normal file
101
src/views/world/model_swapper.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user