feat(Personal Vehicle): Added clone personal vehicle feature. (#326)

This commit is contained in:
aa15032261 2022-07-10 06:33:14 +08:00 committed by GitHub
parent 964347dbe4
commit 2d9021f0b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 715 additions and 248 deletions

View File

@ -35,7 +35,7 @@ namespace big
location.y += dist * sin(yaw) * cos(pitch); location.y += dist * sin(yaw) * cos(pitch);
location.z += dist * sin(pitch); location.z += dist * sin(pitch);
Vehicle veh = vehicle::spawn( Vehicle veh = vehicle::spawn(
(const char*)g->weapons.vehicle_gun_model, rage::joaat((const char*)g->weapons.vehicle_gun_model),
location, location,
ENTITY::GET_ENTITY_HEADING(self::ped) ENTITY::GET_ENTITY_HEADING(self::ped)
); );

View File

@ -119,6 +119,60 @@ namespace big
UNK2 = 1 << 16 UNK2 = 1 << 16
}; };
enum eVehicleModType
{
VMT_SPOILER = 0,
VMT_BUMPER_F = 1,
VMT_BUMPER_R = 2,
VMT_SKIRT = 3,
VMT_EXHAUST = 4,
VMT_CHASSIS = 5,
VMT_GRILL = 6,
VMT_BONNET = 7,
VMT_WING_L = 8,
VMT_WING_R = 9,
VMT_ROOF = 10,
VMT_ENGINE = 11,
VMT_BRAKES = 12,
VMT_GEARBOX = 13,
VMT_HORN = 14,
VMT_SUSPENSION = 15,
VMT_ARMOUR = 16,
VMT_NITROUS = 17,
VMT_TURBO = 18,
VMT_SUBWOOFER = 19,
VMT_TYRE_SMOKE = 20,
VMT_HYDRAULICS = 21,
VMT_XENON_LIGHTS = 22,
VMT_WHEELS = 23,
VMT_WHEELS_REAR_OR_HYDRAULICS = 24,
VMT_PLTHOLDER = 25,
VMT_PLTVANITY = 26,
VMT_INTERIOR1 = 27,
VMT_INTERIOR2 = 28,
VMT_INTERIOR3 = 29,
VMT_INTERIOR4 = 30,
VMT_INTERIOR5 = 31,
VMT_SEATS = 32,
VMT_STEERING = 33,
VMT_KNOB = 34,
VMT_PLAQUE = 35,
VMT_ICE = 36,
VMT_TRUNK = 37,
VMT_HYDRO = 38,
VMT_ENGINEBAY1 = 39,
VMT_ENGINEBAY2 = 40,
VMT_ENGINEBAY3 = 41,
VMT_CHASSIS2 = 42,
VMT_CHASSIS3 = 43,
VMT_CHASSIS4 = 44,
VMT_CHASSIS5 = 45,
VMT_DOOR_L = 46,
VMT_DOOR_R = 47,
VMT_LIVERY_MOD = 48,
VMT_LIGHTBAR = 49
};
enum class ePedTask enum class ePedTask
{ {
TASK_NONE, TASK_NONE,

View File

@ -181,6 +181,17 @@ namespace big
bool preview_vehicle = false; bool preview_vehicle = false;
bool spawn_inside = false; bool spawn_inside = false;
bool spawn_maxed = false; bool spawn_maxed = false;
std::string plate = "";
};
struct clone_pv
{
bool preview_vehicle = false;
bool spawn_inside = false;
bool spawn_clone = false;
bool spawn_maxed = false;
bool clone_plate = false;
std::string plate = "";
}; };
struct spoofing struct spoofing
@ -228,8 +239,7 @@ namespace big
bool vehicle_jump = false; bool vehicle_jump = false;
bool instant_brake = false; bool instant_brake = false;
bool is_targetable = true; bool is_targetable = true;
bool ls_customs = false; // don't save this to disk bool ls_customs = false; // don't save this to dis
bool pv_teleport_into = false;
bool seatbelt = false; bool seatbelt = false;
bool turn_signals = false; bool turn_signals = false;
int auto_drive_speed = 1; int auto_drive_speed = 1;
@ -330,6 +340,7 @@ namespace big
session session{}; session session{};
settings settings{}; settings settings{};
spawn spawn{}; spawn spawn{};
clone_pv clone_pv{};
spoofing spoofing{}; spoofing spoofing{};
vehicle vehicle{}; vehicle vehicle{};
weapons weapons{}; weapons weapons{};
@ -490,12 +501,29 @@ namespace big
this->self.no_ragdoll = j["self"]["no_ragdoll"]; this->self.no_ragdoll = j["self"]["no_ragdoll"];
this->self.off_radar = j["self"]["off_radar"]; this->self.off_radar = j["self"]["off_radar"];
this->self.super_run = j["self"]["super_run"]; this->self.super_run = j["self"]["super_run"];
this->self.proof_bullet = j["self"]["proof_bullet"];
this->self.proof_fire = j["self"]["proof_fire"];
this->self.proof_collision = j["self"]["proof_collision"];
this->self.proof_melee = j["self"]["proof_melee"];
this->self.proof_explosion = j["self"]["proof_explosion"];
this->self.proof_steam = j["self"]["proof_steam"];
this->self.proof_drown = j["self"]["proof_drown"];
this->self.proof_water = j["self"]["proof_water"];
this->self.proof_mask = j["self"]["proof_mask"];
this->settings.hotkeys.menu_toggle = j["settings"]["hotkeys"]["menu_toggle"]; this->settings.hotkeys.menu_toggle = j["settings"]["hotkeys"]["menu_toggle"];
this->spawn.preview_vehicle = j["spawn"]["preview_vehicle"]; this->spawn.preview_vehicle = j["spawn"]["preview_vehicle"];
this->spawn.spawn_inside = j["spawn"]["spawn_inside"]; this->spawn.spawn_inside = j["spawn"]["spawn_inside"];
this->spawn.spawn_maxed = j["spawn"]["spawn_maxed"]; this->spawn.spawn_maxed = j["spawn"]["spawn_maxed"];
this->spawn.plate = j["spawn"]["plate"];
this->clone_pv.preview_vehicle = j["clone_pv"]["preview_vehicle"];
this->clone_pv.spawn_inside = j["clone_pv"]["spawn_inside"];
this->clone_pv.spawn_clone = j["clone_pv"]["spawn_clone"];
this->clone_pv.spawn_maxed = j["clone_pv"]["spawn_maxed"];
this->clone_pv.clone_plate = j["clone_pv"]["clone_plate"];
this->clone_pv.plate = j["clone_pv"]["plate"];
this->spoofing.spoof_ip = j["spoofing"]["spoof_ip"]; this->spoofing.spoof_ip = j["spoofing"]["spoof_ip"];
this->spoofing.spoof_rockstar_id = j["spoofing"]["spoof_rockstar_id"]; this->spoofing.spoof_rockstar_id = j["spoofing"]["spoof_rockstar_id"];
@ -517,7 +545,6 @@ namespace big
this->vehicle.vehicle_jump = j["vehicle"]["vehicle_jump"]; this->vehicle.vehicle_jump = j["vehicle"]["vehicle_jump"];
this->vehicle.instant_brake = j["vehicle"]["instant_brake"]; this->vehicle.instant_brake = j["vehicle"]["instant_brake"];
this->vehicle.is_targetable = j["vehicle"]["is_targetable"]; this->vehicle.is_targetable = j["vehicle"]["is_targetable"];
this->vehicle.pv_teleport_into = j["vehicle"]["pv_teleport_into"];
this->vehicle.rainbow_paint = j["vehicle"]["rainbow_paint"]; this->vehicle.rainbow_paint = j["vehicle"]["rainbow_paint"];
this->vehicle.seatbelt = j["vehicle"]["seatbelt"]; this->vehicle.seatbelt = j["vehicle"]["seatbelt"];
this->vehicle.turn_signals = j["vehicle"]["turn_signals"]; this->vehicle.turn_signals = j["vehicle"]["turn_signals"];
@ -609,7 +636,7 @@ namespace big
"notifications", { "notifications", {
{ "gta_thread_kill", return_notify_pair(g->notifications.gta_thread_kill) }, { "gta_thread_kill", return_notify_pair(g->notifications.gta_thread_kill) },
{ "gta_thread_start", return_notify_pair(g->notifications.gta_thread_start) }, { "gta_thread_start", return_notify_pair(g->notifications.gta_thread_start) },
{"net_array_error", return_notify_pair(g->notifications.net_array_error)}, { "net_array_error", return_notify_pair(g->notifications.net_array_error) },
{ "network_player_mgr_init", return_notify_pair(g->notifications.network_player_mgr_init) }, { "network_player_mgr_init", return_notify_pair(g->notifications.network_player_mgr_init) },
{ "network_player_mgr_shutdown", return_notify_pair(g->notifications.network_player_mgr_shutdown) }, { "network_player_mgr_shutdown", return_notify_pair(g->notifications.network_player_mgr_shutdown) },
{ "player_join", { { "player_join", {
@ -714,7 +741,17 @@ namespace big
{ "never_wanted", this->self.never_wanted }, { "never_wanted", this->self.never_wanted },
{ "no_ragdoll", this->self.no_ragdoll }, { "no_ragdoll", this->self.no_ragdoll },
{ "off_radar", this->self.off_radar }, { "off_radar", this->self.off_radar },
{ "super_run", this->self.super_run } { "super_run", this->self.super_run },
{ "proof_bullet", this->self.proof_bullet },
{ "proof_fire", this->self.proof_fire },
{ "proof_collision", this->self.proof_collision },
{ "proof_melee", this->self.proof_melee },
{ "proof_explosion", this->self.proof_explosion },
{ "proof_steam", this->self.proof_steam },
{ "proof_drown", this->self.proof_drown },
{ "proof_water", this->self.proof_water },
{ "proof_mask", this->self.proof_mask }
} }
}, },
{ {
@ -725,11 +762,22 @@ namespace big
} }
} }
}, },
{
"clone_pv", {
{ "preview_vehicle", this->clone_pv.preview_vehicle },
{ "spawn_inside", this->clone_pv.spawn_inside },
{ "spawn_clone", this->clone_pv.spawn_clone },
{ "spawn_maxed", this->clone_pv.spawn_maxed },
{ "clone_plate", this->clone_pv.clone_plate },
{ "plate", this->clone_pv.plate }
}
},
{ {
"spawn", { "spawn", {
{ "preview_vehicle", this->spawn.preview_vehicle }, { "preview_vehicle", this->spawn.preview_vehicle },
{ "spawn_inside", this->spawn.spawn_inside }, { "spawn_inside", this->spawn.spawn_inside },
{ "spawn_maxed", this->spawn.spawn_maxed} { "spawn_maxed", this->spawn.spawn_maxed},
{ "plate", this->spawn.plate }
} }
}, },
{ {
@ -760,7 +808,6 @@ namespace big
{ "vehicle_jump", this->vehicle.vehicle_jump }, { "vehicle_jump", this->vehicle.vehicle_jump },
{ "instant_brake", this->vehicle.instant_brake }, { "instant_brake", this->vehicle.instant_brake },
{ "is_targetable", this->vehicle.is_targetable }, { "is_targetable", this->vehicle.is_targetable },
{ "pv_teleport_into", this->vehicle.pv_teleport_into },
{ "rainbow_paint", this->vehicle.rainbow_paint }, { "rainbow_paint", this->vehicle.rainbow_paint },
{ "turn_signals", this->vehicle.turn_signals }, { "turn_signals", this->vehicle.turn_signals },
{ "seatbelt", this->vehicle.seatbelt }, { "seatbelt", this->vehicle.seatbelt },

View File

@ -23,6 +23,7 @@ namespace big
SESSION, SESSION,
SETTINGS, SETTINGS,
SPAWN, SPAWN,
PV,
SPOOFING, SPOOFING,
TELEPORT, TELEPORT,
VEHICLE, VEHICLE,
@ -57,6 +58,7 @@ namespace big
}}}, }}},
{ tabs::LSC, {"LSC", view::lsc }}, { tabs::LSC, {"LSC", view::lsc }},
{ tabs::SPAWN, { "Spawn", view::spawn }}, { tabs::SPAWN, { "Spawn", view::spawn }},
{ tabs::PV, { "Personal Vehicle", view::pv }},
}}}, }}},
{tabs::NETWORK, { "Network", nullptr, { {tabs::NETWORK, { "Network", nullptr, {
{ tabs::SPOOFING, { "Spoofing", view::spoofing }}, { tabs::SPOOFING, { "Spoofing", view::spoofing }},

View File

@ -7,12 +7,17 @@
namespace big namespace big
{ {
personal_vehicle::personal_vehicle(int idx, script_global vehicle_idx) personal_vehicle::personal_vehicle(int idx, script_global vehicle_idx)
: m_id(idx) : m_id(idx), m_vehicle_idx(vehicle_idx)
{ {
m_hash = *vehicle_idx.at(66).as<Hash*>(); m_plate = m_vehicle_idx.at(1).as<char*>();
m_state_bitfield = vehicle_idx.at(103).as<int*>(); m_hash = *m_vehicle_idx.at(66).as<Hash*>();
m_state_bitfield = m_vehicle_idx.at(103).as<int*>();
m_name = HUD::GET_LABEL_TEXT_(VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(m_hash)); m_name = fmt::format(
"{} ({})",
HUD::GET_LABEL_TEXT_(VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(m_hash)),
m_plate
);
} }
std::string personal_vehicle::get_display_name() const std::string personal_vehicle::get_display_name() const
@ -30,6 +35,16 @@ namespace big
return m_id; return m_id;
} }
const char* personal_vehicle::get_plate() const
{
return m_plate;
}
script_global personal_vehicle::get_vehicle_idx() const
{
return m_vehicle_idx;
}
void personal_vehicle::summon() const void personal_vehicle::summon() const
{ {
mobile::mechanic::summon_vehicle_by_index(m_id); mobile::mechanic::summon_vehicle_by_index(m_id);
@ -51,8 +66,7 @@ namespace big
if (std::chrono::duration_cast<std::chrono::seconds>(now - m_last_update) < 10s) return; if (std::chrono::duration_cast<std::chrono::seconds>(now - m_last_update) < 10s) return;
m_last_update = std::chrono::high_resolution_clock::now(); m_last_update = std::chrono::high_resolution_clock::now();
g_fiber_pool->queue_job([this] g_fiber_pool->queue_job([this] {
{
register_vehicles(); register_vehicles();
}); });
} }
@ -75,7 +89,7 @@ namespace big
if (STREAMING::IS_MODEL_A_VEHICLE(hash)) if (STREAMING::IS_MODEL_A_VEHICLE(hash))
{ {
auto veh = std::make_unique<personal_vehicle>(i, veh_idx_global); auto veh = std::make_unique<personal_vehicle>(i, veh_idx_global);
if (exists) if (exists)
{ {
// vehicle name is no longer the same, update the vehicle at that index // vehicle name is no longer the same, update the vehicle at that index

View File

@ -1,15 +1,16 @@
#pragma once #pragma once
#include "script_global.hpp"
namespace big namespace big
{ {
class script_global;
class personal_vehicle final class personal_vehicle final
{ {
std::string m_name;
int m_id;
Hash m_hash; Hash m_hash;
int m_id;
std::string m_name;
const char* m_plate;
int* m_state_bitfield; int* m_state_bitfield;
script_global m_vehicle_idx;
public: public:
personal_vehicle(int idx, script_global vehicle_idx); personal_vehicle(int idx, script_global vehicle_idx);
@ -17,6 +18,8 @@ namespace big
[[nodiscard]] std::string get_display_name() const; [[nodiscard]] std::string get_display_name() const;
[[nodiscard]] Hash get_hash() const; [[nodiscard]] Hash get_hash() const;
[[nodiscard]] int get_id() const; [[nodiscard]] int get_id() const;
[[nodiscard]] const char* get_plate() const;
[[nodiscard]] script_global get_vehicle_idx() const;
void summon() const; void summon() const;
}; };

View File

@ -9,6 +9,36 @@
namespace big namespace big
{ {
vehicle_preview_item::vehicle_preview_item()
{
this->name = "";
this->display_name = "";
this->display_manufacturer = "";
this->hash = 0;
}
vehicle_preview_item::vehicle_preview_item(nlohmann::json& item_json)
{
this->name = item_json["Name"];
this->display_name = item_json["Name"];
this->display_manufacturer = "";
this->hash = item_json["Hash"];
if (!item_json["DisplayName"].is_null())
{
this->display_name = item_json["DisplayName"];
}
if (!item_json["ManufacturerDisplayName"].is_null())
{
this->display_manufacturer = item_json["ManufacturerDisplayName"];
}
else if (!item_json["Manufacturer"].is_null())
{
this->display_manufacturer = item_json["Manufacturer"];
}
}
vehicle_preview_service::vehicle_preview_service() : vehicle_preview_service::vehicle_preview_service() :
m_vehicle_file(g_file_manager->get_project_file("./lib/vehicles.json")) m_vehicle_file(g_file_manager->get_project_file("./lib/vehicles.json"))
{ {
@ -17,12 +47,12 @@ namespace big
else else
{ {
g_thread_pool->push([this]() 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())) if (remote::download_binary("http://github-proxy.damon.sh/DurtyFree/gta-v-data-dumps/master/vehicles.json", m_vehicle_file.get_path()))
this->load(); this->load();
else else
LOG(WARNING) << "Failed to download vehicles.json data..."; LOG(WARNING) << "Failed to download vehicles.json data...";
}); });
} }
g_vehicle_preview_service = this; g_vehicle_preview_service = this;
@ -33,9 +63,45 @@ namespace big
g_vehicle_preview_service = nullptr; g_vehicle_preview_service = nullptr;
} }
nlohmann::json& vehicle_preview_service::get_vehicle_list() const vehicle_preview_item& vehicle_preview_service::find_vehicle_item_by_hash(int hash)
{ {
return m_all_vehicles; int idx = -1;
if (m_hash_idx_map.count(hash))
{
idx = m_hash_idx_map[hash];
}
if (idx == -1)
{
return empty_item;
}
else
{
return m_vehicle_preview_item_arr[idx];
}
}
std::vector<vehicle_preview_item>& vehicle_preview_service::get_vehicle_preview_item_arr()
{
return m_vehicle_preview_item_arr;
}
void vehicle_preview_service::set_preview_vehicle(const vehicle_preview_item& item)
{
if (item.hash != 0)
{
if (m_model_hash != item.hash)
{
m_model_hash = item.hash;
m_new_model = true;
}
if (!m_running)
{
g_thread_pool->push([this] { preview_loop(); });
}
}
} }
void vehicle_preview_service::preview_loop() void vehicle_preview_service::preview_loop()
@ -43,61 +109,49 @@ namespace big
if (m_running) if (m_running)
return; return;
m_running = true; m_running = true;
g_fiber_pool->queue_job([this] g_fiber_pool->queue_job([this]
{
while (g_running && m_running && g->spawn.preview_vehicle && g_gui.m_opened)
{ {
auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 2.5f, 2.5f, .5f); while (g_running && m_running && g->spawn.preview_vehicle && g_gui.m_opened)
if (m_current_veh == -1)
{ {
m_new_model = false; auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
location.z = -10.f; if (m_current_veh == -1)
m_current_veh = vehicle::spawn(m_model, location, 0.f, false); {
ENTITY::FREEZE_ENTITY_POSITION(m_current_veh, true); m_new_model = false;
ENTITY::SET_ENTITY_ALPHA(m_current_veh, 0, 0); location.z = -10.f;
ENTITY::SET_ENTITY_COLLISION(m_current_veh, false, false); m_current_veh = vehicle::spawn(m_model_hash, location, 0.f, false);
ENTITY::SET_CAN_CLIMB_ON_ENTITY(m_current_veh, false); ENTITY::FREEZE_ENTITY_POSITION(m_current_veh, true);
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_veh, false); ENTITY::SET_ENTITY_ALPHA(m_current_veh, 0, 0);
} ENTITY::SET_ENTITY_COLLISION(m_current_veh, false, false);
else if (m_new_model) ENTITY::SET_CAN_CLIMB_ON_ENTITY(m_current_veh, false);
{ OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_veh, false);
entity::delete_entity(m_current_veh); }
else if (m_new_model)
{
entity::delete_entity(m_current_veh);
m_current_veh = -1; m_current_veh = -1;
} }
else else
{ {
if (const int alpha = ENTITY::GET_ENTITY_ALPHA(m_current_veh); alpha < 250) 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_ALPHA(m_current_veh, std::min<int>(255, alpha + 10), 0);
}
ENTITY::SET_ENTITY_HEADING(m_current_veh, m_heading); 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); 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;
script::get_current()->yield();
} }
if (m_heading += 0.5f; m_heading > 359) m_heading = 0; entity::delete_entity(m_current_veh);
m_current_veh = -1;
script::get_current()->yield(); m_running = false;
} });
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::stop_preview() void vehicle_preview_service::stop_preview()
@ -107,15 +161,35 @@ namespace big
void vehicle_preview_service::load() void vehicle_preview_service::load()
{ {
m_hash_idx_map.clear();
m_vehicle_preview_item_arr.clear();
std::ifstream file(m_vehicle_file.get_path()); std::ifstream file(m_vehicle_file.get_path());
nlohmann::json all_vehicles;
try try
{ {
file >> m_all_vehicles; file >> all_vehicles;
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
LOG(WARNING) << "Failed to load vehicles.json:\n" << ex.what(); LOG(WARNING) << "Failed to load vehicles.json:\n" << ex.what();
} }
for (auto& item_json : all_vehicles)
{
if (
item_json["Hash"].is_null() ||
item_json["Name"].is_null() ||
!item_json["Bones"].is_array() ||
item_json["Bones"][0] == "stub"
)
{
continue;
}
m_hash_idx_map[item_json["SignedHash"]] = (int)m_vehicle_preview_item_arr.size();
m_vehicle_preview_item_arr.push_back(vehicle_preview_item(item_json));
}
} }
} }

View File

@ -3,6 +3,18 @@
namespace big namespace big
{ {
class vehicle_preview_item {
public:
vehicle_preview_item();
vehicle_preview_item(nlohmann::json& item_json);
std::string name;
std::string display_name;
std::string display_manufacturer;
Hash hash;
};
class vehicle_preview_service class vehicle_preview_service
{ {
file m_vehicle_file; file m_vehicle_file;
@ -10,10 +22,12 @@ namespace big
std::condition_variable m_cond; std::condition_variable m_cond;
std::mutex m_mutex; std::mutex m_mutex;
nlohmann::json m_all_vehicles; std::map<Hash, int> m_hash_idx_map;
std::vector<vehicle_preview_item> m_vehicle_preview_item_arr;
const vehicle_preview_item empty_item = vehicle_preview_item();
Vehicle m_current_veh = -1; Vehicle m_current_veh = -1;
std::string m_model; Hash m_model_hash;
bool m_new_model = false; bool m_new_model = false;
float m_heading = 0.f; float m_heading = 0.f;
bool m_running = false; bool m_running = false;
@ -21,11 +35,11 @@ namespace big
vehicle_preview_service(); vehicle_preview_service();
~vehicle_preview_service(); ~vehicle_preview_service();
nlohmann::json& get_vehicle_list(); const vehicle_preview_item& find_vehicle_item_by_hash(int hash);
std::vector<vehicle_preview_item>& get_vehicle_preview_item_arr();
void set_preview_vehicle(const vehicle_preview_item& item);
void preview_loop(); void preview_loop();
void set_preview_vehicle(const nlohmann::json& item);
void stop_preview(); void stop_preview();
private: private:

View File

@ -9,9 +9,9 @@ namespace big::math
return (float)radian; return (float)radian;
} }
inline double distance_between_vectors(Vector3 a, Vector3 b) inline float distance_between_vectors(Vector3 a, Vector3 b)
{ {
return sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2)); return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2));
} }
inline Vector3 rotation_to_direction(Vector3 rotation) inline Vector3 rotation_to_direction(Vector3 rotation)

View File

@ -89,7 +89,7 @@ namespace big::mobile
if (*mechanic_global.at(958).as<int*>() != -1) if (*mechanic_global.at(958).as<int*>() != -1)
return g_notification_service->push_warning("Vehicle", "Mechanic is not ready to deliver a vehicle right now."); return g_notification_service->push_warning("Vehicle", "Mechanic is not ready to deliver a vehicle right now.");
if (g->vehicle.pv_teleport_into && self::veh) if (g->clone_pv.spawn_inside && self::veh)
TASK::CLEAR_PED_TASKS_IMMEDIATELY(PLAYER::PLAYER_PED_ID()); TASK::CLEAR_PED_TASKS_IMMEDIATELY(PLAYER::PLAYER_PED_ID());
// despawn current veh // despawn current veh
@ -112,8 +112,10 @@ namespace big::mobile
// blocking call till vehicle is delivered // blocking call till vehicle is delivered
notify::busy_spinner("Delivering vehicle...", mechanic_global.at(958).as<int*>(), -1); notify::busy_spinner("Delivering vehicle...", mechanic_global.at(958).as<int*>(), -1);
if (g->vehicle.pv_teleport_into) if (g->clone_pv.spawn_inside)
vehicle::bring(globals::get_personal_vehicle(), self::pos); {
big::vehicle::bring(globals::get_personal_vehicle(), self::pos, true);
}
} }
} }
} }

View File

@ -10,6 +10,8 @@
namespace big::vehicle namespace big::vehicle
{ {
inline auto spawn_global = script_global(2725269);
inline void go_into_personal_vehicle() inline void go_into_personal_vehicle()
{ {
*script_global(2671447).at(8).as<int*>() = 1; *script_global(2671447).at(8).as<int*>() = 1;
@ -19,12 +21,12 @@ namespace big::vehicle
{ {
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh)) return g_notification_service->push_error("Vehicle", "Invalid handle"); if (!ENTITY::IS_ENTITY_A_VEHICLE(veh)) return g_notification_service->push_error("Vehicle", "Invalid handle");
Vector3 vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true); auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true);
teleport::load_ground_at_3dcoord(vecVehicleLocation); teleport::load_ground_at_3dcoord(vecVehicleLocation);
if (!entity::take_control_of(veh)) if (!entity::take_control_of(veh))
return g_notification_service->push_warning("Vehicle", "Failed to take control of remote vehicle."); return g_notification_service->push_warning("Vehicle", "Failed to take control of remote vehicle.");
Ped ped = self::ped; auto ped = self::ped;
ENTITY::SET_ENTITY_COORDS(veh, location.x, location.y, location.z + 1.f, 0, 0, 0, 0); ENTITY::SET_ENTITY_COORDS(veh, location.x, location.y, location.z + 1.f, 0, 0, 0, 0);
ENTITY::SET_ENTITY_HEADING(veh, ENTITY::GET_ENTITY_HEADING(ped)); ENTITY::SET_ENTITY_HEADING(veh, ENTITY::GET_ENTITY_HEADING(ped));
@ -38,14 +40,67 @@ namespace big::vehicle
} }
} }
inline Vehicle get_closest_to_location(Vector3 location, float range, int flags = 70) inline Vehicle get_closest_to_location(Vector3 location, float range)
{ {
return VEHICLE::GET_CLOSEST_VEHICLE(location.x, location.y, location.z, range, 0, flags); if (const auto replay = *g_pointers->m_replay_interface; replay)
{
if (const auto veh_interface = replay->m_vehicle_interface; veh_interface)
{
const auto veh_interface_size = veh_interface->m_max_vehicles;
float min_dist = range + 1;
int32_t m_handle = 0;
for (int32_t i = 0; i < veh_interface_size; i++)
{
auto veh_entity = veh_interface->m_vehicle_list->m_vehicles[i];
auto veh_ptr = veh_entity.m_entity_ptr;
if (!veh_ptr || !veh_ptr->m_navigation)
{
continue;
}
auto veh_pos_arr = veh_ptr->m_navigation->m_position;
Vector3 veh_pos(veh_pos_arr.x, veh_pos_arr.y, veh_pos_arr.z);
float dist = math::distance_between_vectors(veh_pos, location);
if (dist < min_dist)
{
min_dist = dist;
m_handle = g_pointers->m_ptr_to_handle(veh_ptr);
}
}
return m_handle;
}
}
return 0;
}
inline bool set_plate(Vehicle veh, const char* plate)
{
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh) || !entity::take_control_of(veh))
{
return false;
}
if (plate != nullptr && plate[0] != 0)
{
VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(veh, plate);
}
return true;
} }
inline bool repair(Vehicle veh) inline bool repair(Vehicle veh)
{ {
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh) || !entity::take_control_of(veh)) return false; if (!ENTITY::IS_ENTITY_A_VEHICLE(veh) || !entity::take_control_of(veh))
{
return false;
}
VEHICLE::SET_VEHICLE_FIXED(veh); VEHICLE::SET_VEHICLE_FIXED(veh);
VEHICLE::SET_VEHICLE_DEFORMATION_FIXED(veh); VEHICLE::SET_VEHICLE_DEFORMATION_FIXED(veh);
@ -54,45 +109,123 @@ namespace big::vehicle
return true; return true;
} }
inline int spawn(std::string_view model, Vector3 location, float heading, bool is_networked = true) inline int spawn(Hash hash, Vector3 location, float heading, bool is_networked = true)
{ {
if (const Hash hash = rage::joaat(model.data()); hash) for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++)
{ {
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++) STREAMING::REQUEST_MODEL(hash);
{
STREAMING::REQUEST_MODEL(hash);
script::get_current()->yield();
}
if (!STREAMING::HAS_MODEL_LOADED(hash))
{
g_notification_service->push_warning("Spawn", "Failed to spawn model, did you give an incorrect model?");
return -1;
}
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
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(); script::get_current()->yield();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
if (*g_pointers->m_is_session_started)
{
DECORATOR::DECOR_SET_INT(veh, "MPBitset", 0);
ENTITY::SET_ENTITY_CLEANUP_BY_ENGINE_(veh, true);
int networkId = NETWORK::VEH_TO_NET(veh);
if (NETWORK::NETWORK_GET_ENTITY_IS_NETWORKED(veh))
NETWORK::SET_NETWORK_ID_EXISTS_ON_ALL_MACHINES(networkId, true);
VEHICLE::SET_VEHICLE_IS_STOLEN(veh, false);
}
return veh;
} }
return -1; if (!STREAMING::HAS_MODEL_LOADED(hash))
{
g_notification_service->push_warning("Spawn", "Failed to spawn model, did you give an incorrect model?");
return -1;
}
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
auto 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();
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);
if (*g_pointers->m_is_session_started)
{
DECORATOR::DECOR_SET_INT(veh, "MPBitset", 0);
ENTITY::SET_ENTITY_CLEANUP_BY_ENGINE_(veh, true);
int networkId = NETWORK::VEH_TO_NET(veh);
if (NETWORK::NETWORK_GET_ENTITY_IS_NETWORKED(veh))
NETWORK::SET_NETWORK_ID_EXISTS_ON_ALL_MACHINES(networkId, true);
VEHICLE::SET_VEHICLE_IS_STOLEN(veh, false);
}
return veh;
}
inline Vehicle clone(std::map<int, int32_t>& data, Vector3 location, float heading)
{
Vector3 tmpLocation = { location.x, location.y, 1200.0f };
if (location.z > 1000.0f && location.z < 1400.0)
{
tmpLocation.z = 800.0f;
}
// vehicle data
for (const auto& [idx, val] : data)
{
if (idx >= 0 && idx < 142)
{
*spawn_global.at(27).at(idx).as<int32_t*>() = val;
}
}
// permission fix
*spawn_global.at(27).at(19).as<int32_t*>() = -1;
*spawn_global.at(27).at(60).as<int32_t*>() = 1;
*spawn_global.at(27).at(77).as<int32_t*>() = 4030726305;
// personal car flag
*spawn_global.at(27).at(94).as<int32_t*>() = 0;
*spawn_global.at(27).at(95).as<int32_t*>() = 0;
// mmi
*spawn_global.at(27).at(103).as<int32_t*>() = 0;
// spawn location
*spawn_global.at(7).at(0).as<float*>() = tmpLocation.x;
*spawn_global.at(7).at(1).as<float*>() = tmpLocation.y;
*spawn_global.at(7).at(2).as<float*>() = tmpLocation.z;
// spawn non pegasus
*spawn_global.at(3).as<int*>() = 0;
// spawn signal
int* spawn_signal = spawn_global.at(2).as<int32_t*>();
*spawn_global.at(5).as<int32_t*>() = 1;
*spawn_signal = 1;
// wait until the vehicle is spawned
for (size_t retry = 0; *spawn_signal != 0 && retry < 200; retry++)
{
script::get_current()->yield(10ms);
}
if (*spawn_signal == 1)
{
g_notification_service->push_error("Vehicle", "Unable to clone vehicle");
return 0;
}
auto veh = vehicle::get_closest_to_location(tmpLocation, 200);
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh))
{
g_notification_service->push_error("Vehicle", "Unable to clone vehicle");
return 0;
}
ENTITY::SET_ENTITY_COORDS(veh, location.x, location.y, location.z + 1.f, 0, 0, 0, 0);
ENTITY::SET_ENTITY_HEADING(veh, heading);
return veh;
}
inline std::map<int, int32_t> get_vehicle_data_from_vehicle_idx(script_global vehicle_idx)
{
std::map<int, int32_t> veh_data;
for (int i = 0; i < 142; i++)
{
veh_data[i] = *vehicle_idx.at(i).as<int32_t*>();
}
veh_data.erase(1); veh_data.erase(19); veh_data.erase(60); veh_data.erase(77);
veh_data.erase(94); veh_data.erase(95); veh_data.erase(103);
return veh_data;
} }
inline void telport_into_veh(Vehicle veh) inline void telport_into_veh(Vehicle veh)
@ -108,9 +241,14 @@ namespace big::vehicle
VEHICLE::TOGGLE_VEHICLE_MOD(veh, 17 /* Xenon Headlights */, TRUE); VEHICLE::TOGGLE_VEHICLE_MOD(veh, 17 /* Xenon Headlights */, TRUE);
VEHICLE::SET_VEHICLE_WINDOW_TINT(veh, 1); VEHICLE::SET_VEHICLE_WINDOW_TINT(veh, 1);
VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, false); VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, false);
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
VEHICLE::SET_VEHICLE_MOD(veh, i, VEHICLE::GET_NUM_VEHICLE_MODS(veh, i) - 1, true); if (
i != eVehicleModType::VMT_LIVERY_MOD
) {
VEHICLE::SET_VEHICLE_MOD(veh, i, VEHICLE::GET_NUM_VEHICLE_MODS(veh, i) - 1, true);
}
} }
} }

View File

@ -6,14 +6,7 @@
namespace big namespace big
{ {
void view::mobile() { void view::mobile() {
components::button("Mors Mutual Fix All Vehicles", [] { ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always);
int amount_fixed = mobile::mors_mutual::fix_all();
g_notification_service->push("Mobile",
fmt::format("{} vehicle{} been fixed.", amount_fixed, amount_fixed == 1 ? " has" : "s have")
);
});
ImGui::Separator();
components::small_text("Lester"); components::small_text("Lester");
@ -21,63 +14,11 @@ namespace big
ImGui::Separator(); ImGui::Separator();
components::small_text("Mechanic - Personal Vehicles"); components::button("Mors Mutual Fix All Vehicles", [] {
int amount_fixed = mobile::mors_mutual::fix_all();
static char search[64]; g_notification_service->push("Mobile",
static std::string lower_search; fmt::format("{} vehicle{} been fixed.", amount_fixed, amount_fixed == 1 ? " has" : "s have")
);
ImGui::BeginGroup(); });
ImGui::SetNextItemWidth(400.f);
if (ImGui::InputTextWithHint("##search_pv_list", "Search", search, sizeof(search)))
{
lower_search = search;
std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower);
}
g_mobile_service->refresh_personal_vehicles();
if (ImGui::ListBoxHeader("##personal_veh_list", { 400.f, 500.f }))
{
if (g_mobile_service->personal_vehicles().empty())
{
ImGui::Text("No personal vehicles found, are you online?");
}
else
{
const auto personal_veh_idx = mobile::util::get_current_personal_vehicle();
for (const auto& it : g_mobile_service->personal_vehicles())
{
const auto& label = it.first;
const auto& personal_veh = it.second;
auto lower = label;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
if (lower.find(lower_search) != std::string::npos)
{
if (ImGui::Selectable(label.c_str(), personal_veh->get_id() == personal_veh_idx))
{
strcpy(search, "");
lower_search = search;
g_fiber_pool->queue_job([&personal_veh] {
personal_veh->summon();
});
}
}
}
}
ImGui::ListBoxFooter();
}
ImGui::EndGroup();
ImGui::BeginGroup();
ImGui::Checkbox("Spawn in Vehicle", &g->vehicle.pv_teleport_into);
ImGui::EndGroup();
} }
} }

View File

@ -93,7 +93,7 @@ namespace big
components::button("Clean Player", [] { components::button("Clean Player", [] {
entity::clean_ped(self::ped); entity::clean_ped(self::ped);
}); });
ImGui::EndGroup(); ImGui::EndGroup();
@ -111,7 +111,7 @@ namespace big
ImGui::SliderInt("###wanted_level", &g->self.wanted_level, 0, 5) && ImGui::SliderInt("###wanted_level", &g->self.wanted_level, 0, 5) &&
!g->self.force_wanted_level && !g->self.force_wanted_level &&
g_local_player != nullptr g_local_player != nullptr
) { ) {
g_local_player->m_player_info->m_wanted_level = g->self.wanted_level; g_local_player->m_player_info->m_wanted_level = g->self.wanted_level;
} }
} }
@ -120,7 +120,8 @@ namespace big
components::small_text("Proofs"); components::small_text("Proofs");
if (ImGui::Button("Check all")) { if (ImGui::Button("Check all"))
{
g->self.proof_bullet = true; g->self.proof_bullet = true;
g->self.proof_fire = true; g->self.proof_fire = true;
g->self.proof_collision = true; g->self.proof_collision = true;
@ -133,7 +134,8 @@ namespace big
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Uncheck all")) { if (ImGui::Button("Uncheck all"))
{
g->self.proof_bullet = false; g->self.proof_bullet = false;
g->self.proof_fire = false; g->self.proof_fire = false;
g->self.proof_collision = false; g->self.proof_collision = false;
@ -173,31 +175,41 @@ namespace big
ImGui::EndGroup(); ImGui::EndGroup();
g->self.proof_mask = 0; g->self.proof_mask = 0;
if (g->self.godmode) { if (g->self.godmode)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::GOD); g->self.proof_mask |= static_cast<int>(eEntityProofs::GOD);
} else { } else
if (g->self.proof_bullet) { {
if (g->self.proof_bullet)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::BULLET); g->self.proof_mask |= static_cast<int>(eEntityProofs::BULLET);
} }
if (g->self.proof_fire) { if (g->self.proof_fire)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::FIRE); g->self.proof_mask |= static_cast<int>(eEntityProofs::FIRE);
} }
if (g->self.proof_collision) { if (g->self.proof_collision)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::COLLISION); g->self.proof_mask |= static_cast<int>(eEntityProofs::COLLISION);
} }
if (g->self.proof_melee) { if (g->self.proof_melee)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::MELEE); g->self.proof_mask |= static_cast<int>(eEntityProofs::MELEE);
} }
if (g->self.proof_explosion) { if (g->self.proof_explosion)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::EXPLOSION); g->self.proof_mask |= static_cast<int>(eEntityProofs::EXPLOSION);
} }
if (g->self.proof_steam) { if (g->self.proof_steam)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::STEAM); g->self.proof_mask |= static_cast<int>(eEntityProofs::STEAM);
} }
if (g->self.proof_drown) { if (g->self.proof_drown)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::DROWN); g->self.proof_mask |= static_cast<int>(eEntityProofs::DROWN);
} }
if (g->self.proof_water) { if (g->self.proof_water)
{
g->self.proof_mask |= static_cast<int>(eEntityProofs::WATER); g->self.proof_mask |= static_cast<int>(eEntityProofs::WATER);
} }
} }

View File

@ -0,0 +1,151 @@
#include "views/view.hpp"
#include "fiber_pool.hpp"
#include "natives.hpp"
#include "services/mobile/mobile_service.hpp"
#include "services/vehicle_preview/vehicle_preview_service.hpp"
#include "util/vehicle.hpp"
namespace big
{
void view::pv() {
ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always);
ImGui::Checkbox("Preview", &g->clone_pv.preview_vehicle);
ImGui::SameLine();
ImGui::Checkbox("Spawn In", &g->clone_pv.spawn_inside);
ImGui::SameLine();
static char plate[9] = { 0 };
int num_of_rows = 2;
ImGui::Checkbox("Spawn Clone", &g->clone_pv.spawn_clone);
if (g->clone_pv.spawn_clone)
{
num_of_rows = 4;
ImGui::Checkbox("Spawn Maxed", &g->clone_pv.spawn_maxed);
ImGui::SameLine();
strncpy(plate, g->clone_pv.plate.c_str(), 9);
ImGui::Checkbox("Clone PV Plate", &g->clone_pv.clone_plate);
if (g->clone_pv.clone_plate)
{
num_of_rows = 3;
}
else
{
ImGui::SetNextItemWidth(300.f);
components::input_text_with_hint("Plate", "Plate Number", plate, sizeof(plate), ImGuiInputTextFlags_None, [] {
g->clone_pv.plate = plate;
});
}
}
static char search[64];
static std::string lower_search;
ImGui::SetNextItemWidth(300.f);
components::input_text_with_hint("Model Name", "Search", search, sizeof(search), ImGuiInputTextFlags_None, [] {
lower_search = search;
std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower);
});
g_mobile_service->refresh_personal_vehicles();
if (ImGui::ListBoxHeader("##personal_veh_list", { 300, static_cast<float>(*g_pointers->m_resolution_y - 184 - 38 * num_of_rows) }))
{
if (g_mobile_service->personal_vehicles().empty())
{
ImGui::Text("No personal vehicles found, \nare you online?");
}
else
{
for (const auto& it : g_mobile_service->personal_vehicles())
{
const auto& label = it.first;
const auto& personal_veh = it.second;
auto item = g_vehicle_preview_service->find_vehicle_item_by_hash(personal_veh->get_hash());
std::string display_name = label;
std::string display_manufacturer = item.display_manufacturer;
std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower);
std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower);
if (
display_name.find(lower_search) != std::string::npos ||
display_manufacturer.find(lower_search) != std::string::npos
) {
ImGui::PushID(personal_veh->get_id());
if (ImGui::Selectable(label.c_str(), false)) {
if (g->clone_pv.spawn_clone)
{
g_fiber_pool->queue_job([&personal_veh] {
auto vehicle_idx = personal_veh->get_vehicle_idx();
auto veh_data = vehicle::get_vehicle_data_from_vehicle_idx(vehicle_idx);
float y_offset = 0;
if (PED::IS_PED_IN_ANY_VEHICLE(self::ped, false))
{
y_offset = 10.f;
}
else if (!g->spawn.spawn_inside)
{
y_offset = 5.f;
}
auto spawn_location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, y_offset, 0.f);
float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped);
const char* spawn_plate = plate;
if (g->clone_pv.clone_plate)
{
spawn_plate = personal_veh->get_plate();
}
auto veh = vehicle::clone(veh_data, spawn_location, spawn_heading);
if (g->clone_pv.spawn_inside)
{
vehicle::telport_into_veh(veh);
}
if (g->clone_pv.spawn_maxed)
{
vehicle::max_vehicle(veh);
}
vehicle::set_plate(veh, spawn_plate);
});
}
else
{
strcpy(search, "");
lower_search = search;
g_fiber_pool->queue_job([&personal_veh] {
personal_veh->summon();
});
}
}
ImGui::PopID();
if (g->clone_pv.preview_vehicle && ImGui::IsItemHovered())
{
g_vehicle_preview_service->set_preview_vehicle(item);
}
else if (g->clone_pv.preview_vehicle && !ImGui::IsAnyItemHovered())
{
g_vehicle_preview_service->stop_preview();
}
}
}
}
ImGui::ListBoxFooter();
}
}
}

View File

@ -6,15 +6,6 @@
namespace big namespace big
{ {
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() { void view::spawn() {
ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always); ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always);
@ -24,48 +15,61 @@ namespace big
ImGui::SameLine(); ImGui::SameLine();
ImGui::Checkbox("Spawn Maxed", &g->spawn.spawn_maxed); ImGui::Checkbox("Spawn Maxed", &g->spawn.spawn_maxed);
components::input_text_with_hint("Model Name", "Search", model, sizeof(model), ImGuiInputTextFlags_EnterReturnsTrue, [] static char plate[9] = { 0 };
{ strncpy(plate, g->spawn.plate.c_str(), 9);
const auto ped = self::ped;
const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped, 2.f, 2.f, 0.f); ImGui::SetNextItemWidth(300.f);
const auto veh = vehicle::spawn(model, location, g_local_player->m_player_info->m_ped->m_navigation->m_right.x + 90.f); components::input_text_with_hint("Plate", "Plate Number", plate, sizeof(plate), ImGuiInputTextFlags_None, [] {
g->spawn.plate = plate;
if (g->spawn.spawn_inside)
PED::SET_PED_INTO_VEHICLE(PLAYER::PLAYER_PED_ID(), veh, -1);
if (g->spawn.spawn_maxed)
vehicle::max_vehicle(veh);
}); });
static char search[64];
static std::string lower_search;
ImGui::SetNextItemWidth(300.f);
components::input_text_with_hint("Model Name", "Search", search, sizeof(search), ImGuiInputTextFlags_None, [] {
lower_search = search;
std::transform(lower_search.begin(), lower_search.end(), lower_search.begin(), tolower);
});
// arbitrary subtraction this looked nice so idc, works for all resolutions as well // arbitrary subtraction this looked nice so idc, works for all resolutions as well
if (ImGui::ListBoxHeader("###vehicles", { 0, static_cast<float>(*g_pointers->m_resolution_y - 260)})) if (ImGui::ListBoxHeader("###vehicles", { 300, static_cast<float>(*g_pointers->m_resolution_y - 184 - 38 * 3) }))
{ {
if (!g_vehicle_preview_service->get_vehicle_list().is_null())
auto item_arr = g_vehicle_preview_service->get_vehicle_preview_item_arr();
if (item_arr.size() > 0)
{ {
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"]; for (auto& item : item_arr) {
std::string display_name = item["DisplayName"]; std::string display_name = item.display_name;
std::string display_manufacturer = item.display_manufacturer;
std::string manufacturer; std::transform(display_name.begin(), display_name.end(), display_name.begin(), ::tolower);
std::string search = model; std::transform(display_manufacturer.begin(), display_manufacturer.end(), display_manufacturer.begin(), ::tolower);
std::transform(search.begin(), search.end(), search.begin(), ::tolower);
if (!item["ManufacturerDisplayName"].is_null()) if (
manufacturer = item["ManufacturerDisplayName"]; display_name.find(lower_search) != std::string::npos ||
display_manufacturer.find(lower_search) != std::string::npos
) {
//ImGui::PushID(item.hash);
components::selectable(item.display_name, false, [item] {
if (search.empty() || float y_offset = 0;
does_search_match(name, search) ||
does_search_match(display_name, search) || if (PED::IS_PED_IN_ANY_VEHICLE(self::ped, false))
does_search_match(manufacturer, search)) {
{ y_offset = 10.f;
components::selectable(item["DisplayName"], item["Name"] == search, [&item] }
{ else if (!g->spawn.spawn_inside)
const auto location = self::pos; {
const Vehicle veh = vehicle::spawn(item["Name"], location, 0.f); y_offset = 5.f;
}
Vector3 spawn_location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, y_offset, 0.f);
float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped);
const Vehicle veh = vehicle::spawn(item.hash, spawn_location, spawn_heading);
if (g->spawn.spawn_inside) if (g->spawn.spawn_inside)
{ {
@ -77,17 +81,27 @@ namespace big
vehicle::max_vehicle(veh); vehicle::max_vehicle(veh);
} }
vehicle::set_plate(veh, plate);
g_vehicle_preview_service->stop_preview(); g_vehicle_preview_service->stop_preview();
}); });
//ImGui::PopID();
if (g->spawn.preview_vehicle && ImGui::IsItemHovered()) if (g->spawn.preview_vehicle && ImGui::IsItemHovered())
{
g_vehicle_preview_service->set_preview_vehicle(item); g_vehicle_preview_service->set_preview_vehicle(item);
}
else if (g->spawn.preview_vehicle && !ImGui::IsAnyItemHovered()) else if (g->spawn.preview_vehicle && !ImGui::IsAnyItemHovered())
{
g_vehicle_preview_service->stop_preview(); g_vehicle_preview_service->stop_preview();
}
} }
} }
} }
else ImGui::Text("No vehicles in registry."); else
{
ImGui::Text("No vehicles in registry.");
}
ImGui::ListBoxFooter(); ImGui::ListBoxFooter();
} }
} }

View File

@ -33,6 +33,7 @@ namespace big
static void session(); static void session();
static void settings(); static void settings();
static void spawn(); static void spawn();
static void pv();
static void spoofing(); static void spoofing();
static void teleport(); static void teleport();
static void vehicle(); static void vehicle();