mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-01-09 02:43:38 +08:00
feat(Spawner): Preview vehicle before spawning (#113)
This commit is contained in:
parent
bb8703520a
commit
54bdb6da56
30
BigBaseV2/src/api/remote.hpp
Normal file
30
BigBaseV2/src/api/remote.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "api/http_request.hpp"
|
||||
|
||||
namespace big::remote
|
||||
{
|
||||
inline bool download_binary(const std::string_view file_url, const std::filesystem::path& location)
|
||||
{
|
||||
std::ofstream file(location, std::ios::binary | std::ios::trunc);
|
||||
|
||||
try
|
||||
{
|
||||
http::Request req(file_url.data());
|
||||
http::Response res = req.send("GET", "", {}, 2500ms);
|
||||
|
||||
std::ostream_iterator<std::uint8_t> outputIter(file);
|
||||
std::copy(res.body.begin(), res.body.end(), outputIter);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG(INFO) << "Failed to download binary, is the host down?: " << e.what();
|
||||
|
||||
file.close();
|
||||
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -90,6 +90,12 @@ namespace big
|
||||
hotkeys hotkeys{};
|
||||
};
|
||||
|
||||
struct spawn
|
||||
{
|
||||
bool preview_vehicle = false;
|
||||
bool spawn_inside = false;
|
||||
};
|
||||
|
||||
struct spoofing
|
||||
{
|
||||
bool spoof_username = false;
|
||||
@ -175,6 +181,7 @@ namespace big
|
||||
protections protections{};
|
||||
self self{};
|
||||
settings settings{};
|
||||
spawn spawn{};
|
||||
spoofing spoofing{};
|
||||
vehicle vehicle{};
|
||||
weapons weapons{};
|
||||
@ -234,6 +241,9 @@ namespace big
|
||||
|
||||
this->settings.hotkeys.menu_toggle = j["settings"]["hotkeys"]["menu_toggle"];
|
||||
|
||||
this->spawn.preview_vehicle = j["spawn"]["preview_vehicle"];
|
||||
this->spawn.spawn_inside = j["spawn"]["spawn_inside"];
|
||||
|
||||
this->spoofing.spoof_ip = j["spoofing"]["spoof_ip"];
|
||||
this->spoofing.spoof_rockstar_id = j["spoofing"]["spoof_rockstar_id"];
|
||||
this->spoofing.spoof_username = j["spoofing"]["spoof_username"];
|
||||
@ -355,6 +365,12 @@ namespace big
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"spawn", {
|
||||
{ "preview_vehicle", this->spawn.preview_vehicle },
|
||||
{ "spawn_inside", this->spawn.spawn_inside }
|
||||
}
|
||||
},
|
||||
{
|
||||
"spoofing", {
|
||||
{ "spoof_ip", this->spoofing.spoof_ip },
|
||||
|
@ -13,5 +13,12 @@ namespace big
|
||||
static void sub_title(const std::string_view);
|
||||
static void title(const std::string_view);
|
||||
static void button(const std::string_view, std::function<void()>);
|
||||
|
||||
static void input_text_with_hint(const std::string_view label, const std::string_view hint, char* buf, size_t buf_size, ImGuiInputTextFlags_ flag = ImGuiInputTextFlags_None, std::function<void()> cb = nullptr);
|
||||
|
||||
static bool selectable(const std::string_view, bool);
|
||||
static bool selectable(const std::string_view, bool, ImGuiSelectableFlags);
|
||||
static void selectable(const std::string_view, bool, std::function<void()>);
|
||||
static void selectable(const std::string_view, bool, ImGuiSelectableFlags, std::function<void()>);
|
||||
};
|
||||
}
|
17
BigBaseV2/src/gui/components/input_text_with_hint.cpp
Normal file
17
BigBaseV2/src/gui/components/input_text_with_hint.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "gui/components/components.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
#include "natives.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
void components::input_text_with_hint(const std::string_view label, const std::string_view hint, char* buf, size_t buf_size, ImGuiInputTextFlags_ flag, std::function<void()> cb) {
|
||||
if (ImGui::InputTextWithHint(label.data(), hint.data(), buf, buf_size, flag))
|
||||
if (cb)
|
||||
g_fiber_pool->queue_job(std::move(cb));
|
||||
|
||||
if (ImGui::IsItemActive())
|
||||
g_fiber_pool->queue_job([] {
|
||||
PAD::DISABLE_ALL_CONTROL_ACTIONS(0);
|
||||
});
|
||||
}
|
||||
}
|
29
BigBaseV2/src/gui/components/selectable.cpp
Normal file
29
BigBaseV2/src/gui/components/selectable.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "gui/components/components.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
bool components::selectable(const std::string_view text, bool selected)
|
||||
{
|
||||
return ImGui::Selectable(text.data(), selected);
|
||||
}
|
||||
|
||||
bool components::selectable(const std::string_view text, bool selected, ImGuiSelectableFlags flag)
|
||||
{
|
||||
return ImGui::Selectable(text.data(), selected, flag);
|
||||
}
|
||||
|
||||
void components::selectable(const std::string_view text, bool selected, std::function<void()> cb)
|
||||
{
|
||||
if (components::selectable(text.data(), selected))
|
||||
g_fiber_pool->queue_job(std::move(cb));
|
||||
}
|
||||
|
||||
void components::selectable(const std::string_view text, bool selected, ImGuiSelectableFlags flag, std::function<void()> cb)
|
||||
{
|
||||
if (components::selectable(text.data(), selected, flag))
|
||||
{
|
||||
g_fiber_pool->queue_job(std::move(cb));
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
#include "services/player_service.hpp"
|
||||
#include "services/mobile_service.hpp"
|
||||
#include "services/notification_service.hpp"
|
||||
#include "services/vehicle_preview_service.hpp"
|
||||
#include "services/vehicle_service.hpp"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
@ -67,6 +68,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
auto mobile_service_instance = std::make_unique<mobile_service>();
|
||||
auto notification_service_instance = std::make_unique<notification_service>();
|
||||
auto player_service_instance = std::make_unique<player_service>();
|
||||
auto vehicle_preview_service_instance = std::make_unique<vehicle_preview_service>();
|
||||
auto vehicle_service_instance = std::make_unique<vehicle_service>();
|
||||
LOG(INFO) << "Registered service instances...";
|
||||
|
||||
@ -96,6 +98,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
|
||||
vehicle_service_instance.reset();
|
||||
LOG(INFO) << "Vehicle Service reset.";
|
||||
vehicle_preview_service_instance.reset();
|
||||
LOG(INFO) << "Vehicle Preview Service reset.";
|
||||
mobile_service_instance.reset();
|
||||
LOG(INFO) << "Mobile Service reset.";
|
||||
player_service_instance.reset();
|
||||
|
125
BigBaseV2/src/services/vehicle_preview_service.cpp
Normal file
125
BigBaseV2/src/services/vehicle_preview_service.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include "api/remote.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
#include "file_manager.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
#include "util/entity.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "vehicle_preview_service.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
vehicle_preview_service::vehicle_preview_service() :
|
||||
m_vehicle_file(g_file_manager->get_project_file("./lib/vehicles.json"))
|
||||
{
|
||||
if (m_vehicle_file.exists())
|
||||
this->load();
|
||||
else
|
||||
{
|
||||
g_thread_pool->push([this]()
|
||||
{
|
||||
if (remote::download_binary("http://github-proxy.damon.sh/DurtyFree/gta-v-data-dumps/master/vehicles.json", m_vehicle_file.get_path()))
|
||||
this->load();
|
||||
else
|
||||
LOG(WARNING) << "Failed to download vehicles.json data...";
|
||||
});
|
||||
}
|
||||
|
||||
g_vehicle_preview_service = this;
|
||||
}
|
||||
|
||||
vehicle_preview_service::~vehicle_preview_service()
|
||||
{
|
||||
g_vehicle_preview_service = nullptr;
|
||||
}
|
||||
|
||||
nlohmann::json& vehicle_preview_service::get_vehicle_list()
|
||||
{
|
||||
return m_all_vehicles;
|
||||
}
|
||||
|
||||
void vehicle_preview_service::preview_loop()
|
||||
{
|
||||
if (m_running)
|
||||
return;
|
||||
|
||||
m_running = true;
|
||||
static bool busy = false;
|
||||
while (g_running && g->spawn.preview_vehicle && g_gui.m_opened)
|
||||
{
|
||||
if (busy)
|
||||
continue;
|
||||
busy = true;
|
||||
|
||||
g_fiber_pool->queue_job([this]
|
||||
{
|
||||
auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PLAYER::PLAYER_PED_ID(), 2.5f, 2.5f, .5f);
|
||||
if (m_current_veh == -1)
|
||||
{
|
||||
location.z = -10.f;
|
||||
m_current_veh = vehicle::spawn(m_model, location, 0.f, false);
|
||||
ENTITY::FREEZE_ENTITY_POSITION(m_current_veh, true);
|
||||
ENTITY::SET_ENTITY_ALPHA(m_current_veh, 0, 0);
|
||||
ENTITY::SET_ENTITY_COLLISION(m_current_veh, false, false);
|
||||
|
||||
m_new_model = false;
|
||||
}
|
||||
else if (m_new_model)
|
||||
{
|
||||
entity::delete_entity(m_current_veh);
|
||||
|
||||
m_current_veh = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (const int alpha = ENTITY::GET_ENTITY_ALPHA(m_current_veh); alpha < 250)
|
||||
ENTITY::SET_ENTITY_ALPHA(m_current_veh, std::min<int>(255, alpha + 10), 0);
|
||||
|
||||
ENTITY::SET_ENTITY_HEADING(m_current_veh, m_heading);
|
||||
ENTITY::SET_ENTITY_COORDS(m_current_veh, location.x, location.y, location.z, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (m_heading += 0.5f; m_heading > 359) m_heading = 0;
|
||||
|
||||
busy = false;
|
||||
});
|
||||
}
|
||||
|
||||
g_fiber_pool->queue_job([this]
|
||||
{
|
||||
entity::delete_entity(m_current_veh);
|
||||
|
||||
m_current_veh = -1;
|
||||
});
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
|
||||
void vehicle_preview_service::set_preview_vehicle(const nlohmann::json& item)
|
||||
{
|
||||
if (m_model != item["Name"])
|
||||
{
|
||||
m_model = item["Name"];
|
||||
|
||||
m_new_model = true;
|
||||
}
|
||||
|
||||
if (!m_running)
|
||||
g_thread_pool->push([this] { preview_loop(); });
|
||||
}
|
||||
|
||||
void vehicle_preview_service::load()
|
||||
{
|
||||
std::ifstream file(m_vehicle_file.get_path());
|
||||
|
||||
try
|
||||
{
|
||||
file >> m_all_vehicles;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
LOG(WARNING) << "Failed to load vehicles.json:\n" << ex.what();
|
||||
}
|
||||
}
|
||||
}
|
36
BigBaseV2/src/services/vehicle_preview_service.hpp
Normal file
36
BigBaseV2/src/services/vehicle_preview_service.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "file_manager/file.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
class vehicle_preview_service
|
||||
{
|
||||
file m_vehicle_file;
|
||||
|
||||
std::condition_variable m_cond;
|
||||
std::mutex m_mutex;
|
||||
|
||||
nlohmann::json m_all_vehicles;
|
||||
|
||||
Vehicle m_current_veh = -1;
|
||||
std::string m_model;
|
||||
bool m_new_model = false;
|
||||
float m_heading = 0.f;
|
||||
bool m_running = false;
|
||||
public:
|
||||
vehicle_preview_service();
|
||||
~vehicle_preview_service();
|
||||
|
||||
nlohmann::json& get_vehicle_list();
|
||||
|
||||
void preview_loop();
|
||||
|
||||
void set_preview_vehicle(const nlohmann::json& item);
|
||||
|
||||
private:
|
||||
void load();
|
||||
|
||||
};
|
||||
|
||||
inline vehicle_preview_service* g_vehicle_preview_service{};
|
||||
}
|
@ -44,11 +44,9 @@ namespace big::vehicle
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int spawn(const char* model, Vector3 location, float heading)
|
||||
inline int spawn(std::string_view model, Vector3 location, float heading, bool is_networked = true)
|
||||
{
|
||||
Hash hash = rage::joaat(model);
|
||||
|
||||
if (hash)
|
||||
if (const Hash hash = rage::joaat(model.data()); hash)
|
||||
{
|
||||
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++)
|
||||
{
|
||||
@ -64,7 +62,7 @@ namespace big::vehicle
|
||||
}
|
||||
|
||||
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
|
||||
Vehicle veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, true, false, false);
|
||||
Vehicle veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, is_networked, false, false);
|
||||
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x0574;
|
||||
|
||||
script::get_current()->yield();
|
||||
|
@ -1,29 +1,72 @@
|
||||
#include "views/view.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "script.hpp"
|
||||
#include "services/vehicle_preview_service.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
static char model[12];
|
||||
static char model[12] = "";
|
||||
|
||||
bool does_search_match(std::string& input, const std::string& search)
|
||||
{
|
||||
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
|
||||
|
||||
return input.find(search) != std::string::npos;
|
||||
}
|
||||
|
||||
void view::spawn() {
|
||||
g_fiber_pool->queue_job([] {
|
||||
PAD::DISABLE_ALL_CONTROL_ACTIONS(0);
|
||||
});
|
||||
ImGui::Checkbox("Preview", &g->spawn.preview_vehicle);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Spawn In", &g->spawn.spawn_inside);
|
||||
|
||||
if (
|
||||
ImGui::InputText("Model Name", model, sizeof(model), ImGuiInputTextFlags_EnterReturnsTrue) ||
|
||||
ImGui::Button("Spawn")
|
||||
)
|
||||
components::input_text_with_hint("Model Name", "Search", model, sizeof(model), ImGuiInputTextFlags_EnterReturnsTrue, []
|
||||
{
|
||||
g_fiber_pool->queue_job([] {
|
||||
Ped player = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(PLAYER::GET_PLAYER_INDEX());
|
||||
Vector3 location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(player, .0, 8.0, .5);
|
||||
const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PLAYER::PLAYER_PED_ID(), 2.f, 2.f, 0.f);
|
||||
const Vehicle veh = vehicle::spawn(model, location, g_local_player->m_player_info->m_ped->m_navigation->m_heading + 90.f);
|
||||
|
||||
vehicle::spawn((const char*)model, location, ENTITY::GET_ENTITY_HEADING(player) + 90.f);
|
||||
});
|
||||
if (g->spawn.spawn_inside)
|
||||
PED::SET_PED_INTO_VEHICLE(PLAYER::PLAYER_PED_ID(), veh, -1);
|
||||
});
|
||||
if (ImGui::ListBoxHeader("###vehicles", { ImGui::GetWindowWidth(), ImGui::GetWindowHeight() }))
|
||||
{
|
||||
if (!g_vehicle_preview_service->get_vehicle_list().is_null())
|
||||
{
|
||||
for (auto& item : g_vehicle_preview_service->get_vehicle_list())
|
||||
{
|
||||
if (item["Name"].is_null() || item["DisplayName"].is_null())
|
||||
continue;
|
||||
|
||||
std::string name = item["Name"];
|
||||
std::string display_name = item["DisplayName"];
|
||||
|
||||
std::string manufacturer;
|
||||
std::string search = model;
|
||||
std::transform(search.begin(), search.end(), search.begin(), ::tolower);
|
||||
|
||||
if (!item["ManufacturerDisplayName"].is_null())
|
||||
manufacturer = item["ManufacturerDisplayName"];
|
||||
|
||||
if (search.empty() ||
|
||||
does_search_match(name, search) ||
|
||||
does_search_match(display_name, search) ||
|
||||
does_search_match(manufacturer, search))
|
||||
{
|
||||
components::selectable(item["DisplayName"], item["Name"] == search, [&item]
|
||||
{
|
||||
const auto location = ENTITY::GET_ENTITY_COORDS(PLAYER::PLAYER_PED_ID(), true);
|
||||
const Vehicle veh = vehicle::spawn(item["Name"], location, 0.f);
|
||||
|
||||
if (g->spawn.spawn_inside)
|
||||
PED::SET_PED_INTO_VEHICLE(PLAYER::PLAYER_PED_ID(), veh, -1);
|
||||
});
|
||||
|
||||
if (g->spawn.preview_vehicle && ImGui::IsItemHovered())
|
||||
g_vehicle_preview_service->set_preview_vehicle(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else ImGui::Text("No vehicles in registry.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user