feat(Personal Vehicle): Added clone personal vehicle feature. (#326)
This commit is contained in:
parent
964347dbe4
commit
2d9021f0b8
@ -35,7 +35,7 @@ namespace big
|
||||
location.y += dist * sin(yaw) * cos(pitch);
|
||||
location.z += dist * sin(pitch);
|
||||
Vehicle veh = vehicle::spawn(
|
||||
(const char*)g->weapons.vehicle_gun_model,
|
||||
rage::joaat((const char*)g->weapons.vehicle_gun_model),
|
||||
location,
|
||||
ENTITY::GET_ENTITY_HEADING(self::ped)
|
||||
);
|
||||
|
@ -119,6 +119,60 @@ namespace big
|
||||
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
|
||||
{
|
||||
TASK_NONE,
|
||||
|
@ -181,6 +181,17 @@ namespace big
|
||||
bool preview_vehicle = false;
|
||||
bool spawn_inside = 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
|
||||
@ -228,8 +239,7 @@ namespace big
|
||||
bool vehicle_jump = false;
|
||||
bool instant_brake = false;
|
||||
bool is_targetable = true;
|
||||
bool ls_customs = false; // don't save this to disk
|
||||
bool pv_teleport_into = false;
|
||||
bool ls_customs = false; // don't save this to dis
|
||||
bool seatbelt = false;
|
||||
bool turn_signals = false;
|
||||
int auto_drive_speed = 1;
|
||||
@ -330,6 +340,7 @@ namespace big
|
||||
session session{};
|
||||
settings settings{};
|
||||
spawn spawn{};
|
||||
clone_pv clone_pv{};
|
||||
spoofing spoofing{};
|
||||
vehicle vehicle{};
|
||||
weapons weapons{};
|
||||
@ -490,12 +501,29 @@ namespace big
|
||||
this->self.no_ragdoll = j["self"]["no_ragdoll"];
|
||||
this->self.off_radar = j["self"]["off_radar"];
|
||||
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->spawn.preview_vehicle = j["spawn"]["preview_vehicle"];
|
||||
this->spawn.spawn_inside = j["spawn"]["spawn_inside"];
|
||||
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_rockstar_id = j["spoofing"]["spoof_rockstar_id"];
|
||||
@ -517,7 +545,6 @@ namespace big
|
||||
this->vehicle.vehicle_jump = j["vehicle"]["vehicle_jump"];
|
||||
this->vehicle.instant_brake = j["vehicle"]["instant_brake"];
|
||||
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.seatbelt = j["vehicle"]["seatbelt"];
|
||||
this->vehicle.turn_signals = j["vehicle"]["turn_signals"];
|
||||
@ -609,7 +636,7 @@ namespace big
|
||||
"notifications", {
|
||||
{ "gta_thread_kill", return_notify_pair(g->notifications.gta_thread_kill) },
|
||||
{ "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_shutdown", return_notify_pair(g->notifications.network_player_mgr_shutdown) },
|
||||
{ "player_join", {
|
||||
@ -714,7 +741,17 @@ namespace big
|
||||
{ "never_wanted", this->self.never_wanted },
|
||||
{ "no_ragdoll", this->self.no_ragdoll },
|
||||
{ "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", {
|
||||
{ "preview_vehicle", this->spawn.preview_vehicle },
|
||||
{ "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 },
|
||||
{ "instant_brake", this->vehicle.instant_brake },
|
||||
{ "is_targetable", this->vehicle.is_targetable },
|
||||
{ "pv_teleport_into", this->vehicle.pv_teleport_into },
|
||||
{ "rainbow_paint", this->vehicle.rainbow_paint },
|
||||
{ "turn_signals", this->vehicle.turn_signals },
|
||||
{ "seatbelt", this->vehicle.seatbelt },
|
||||
|
@ -23,6 +23,7 @@ namespace big
|
||||
SESSION,
|
||||
SETTINGS,
|
||||
SPAWN,
|
||||
PV,
|
||||
SPOOFING,
|
||||
TELEPORT,
|
||||
VEHICLE,
|
||||
@ -57,6 +58,7 @@ namespace big
|
||||
}}},
|
||||
{ tabs::LSC, {"LSC", view::lsc }},
|
||||
{ tabs::SPAWN, { "Spawn", view::spawn }},
|
||||
{ tabs::PV, { "Personal Vehicle", view::pv }},
|
||||
}}},
|
||||
{tabs::NETWORK, { "Network", nullptr, {
|
||||
{ tabs::SPOOFING, { "Spoofing", view::spoofing }},
|
||||
|
@ -7,12 +7,17 @@
|
||||
namespace big
|
||||
{
|
||||
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_state_bitfield = vehicle_idx.at(103).as<int*>();
|
||||
m_plate = m_vehicle_idx.at(1).as<char*>();
|
||||
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
|
||||
@ -30,6 +35,16 @@ namespace big
|
||||
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
|
||||
{
|
||||
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;
|
||||
m_last_update = std::chrono::high_resolution_clock::now();
|
||||
|
||||
g_fiber_pool->queue_job([this]
|
||||
{
|
||||
g_fiber_pool->queue_job([this] {
|
||||
register_vehicles();
|
||||
});
|
||||
}
|
||||
@ -75,7 +89,7 @@ namespace big
|
||||
if (STREAMING::IS_MODEL_A_VEHICLE(hash))
|
||||
{
|
||||
auto veh = std::make_unique<personal_vehicle>(i, veh_idx_global);
|
||||
|
||||
|
||||
if (exists)
|
||||
{
|
||||
// vehicle name is no longer the same, update the vehicle at that index
|
||||
|
@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
#include "script_global.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
class script_global;
|
||||
|
||||
class personal_vehicle final
|
||||
{
|
||||
std::string m_name;
|
||||
int m_id;
|
||||
Hash m_hash;
|
||||
int m_id;
|
||||
std::string m_name;
|
||||
const char* m_plate;
|
||||
int* m_state_bitfield;
|
||||
script_global m_vehicle_idx;
|
||||
|
||||
public:
|
||||
personal_vehicle(int idx, script_global vehicle_idx);
|
||||
@ -17,6 +18,8 @@ namespace big
|
||||
[[nodiscard]] std::string get_display_name() const;
|
||||
[[nodiscard]] Hash get_hash() const;
|
||||
[[nodiscard]] int get_id() const;
|
||||
[[nodiscard]] const char* get_plate() const;
|
||||
[[nodiscard]] script_global get_vehicle_idx() const;
|
||||
|
||||
void summon() const;
|
||||
};
|
||||
|
@ -9,6 +9,36 @@
|
||||
|
||||
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() :
|
||||
m_vehicle_file(g_file_manager->get_project_file("./lib/vehicles.json"))
|
||||
{
|
||||
@ -17,12 +47,12 @@ namespace big
|
||||
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...";
|
||||
});
|
||||
{
|
||||
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;
|
||||
@ -33,9 +63,45 @@ namespace big
|
||||
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()
|
||||
@ -43,61 +109,49 @@ namespace big
|
||||
if (m_running)
|
||||
return;
|
||||
m_running = true;
|
||||
|
||||
|
||||
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);
|
||||
if (m_current_veh == -1)
|
||||
while (g_running && m_running && g->spawn.preview_vehicle && g_gui.m_opened)
|
||||
{
|
||||
m_new_model = false;
|
||||
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);
|
||||
ENTITY::SET_CAN_CLIMB_ON_ENTITY(m_current_veh, false);
|
||||
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_veh, false);
|
||||
}
|
||||
else if (m_new_model)
|
||||
{
|
||||
entity::delete_entity(m_current_veh);
|
||||
auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
|
||||
if (m_current_veh == -1)
|
||||
{
|
||||
m_new_model = false;
|
||||
location.z = -10.f;
|
||||
m_current_veh = vehicle::spawn(m_model_hash, 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);
|
||||
ENTITY::SET_CAN_CLIMB_ON_ENTITY(m_current_veh, false);
|
||||
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_veh, 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);
|
||||
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);
|
||||
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;
|
||||
|
||||
script::get_current()->yield();
|
||||
}
|
||||
|
||||
if (m_heading += 0.5f; m_heading > 359) m_heading = 0;
|
||||
|
||||
script::get_current()->yield();
|
||||
}
|
||||
|
||||
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(); });
|
||||
entity::delete_entity(m_current_veh);
|
||||
m_current_veh = -1;
|
||||
m_running = false;
|
||||
});
|
||||
}
|
||||
|
||||
void vehicle_preview_service::stop_preview()
|
||||
@ -107,15 +161,35 @@ namespace big
|
||||
|
||||
void vehicle_preview_service::load()
|
||||
{
|
||||
m_hash_idx_map.clear();
|
||||
m_vehicle_preview_item_arr.clear();
|
||||
|
||||
std::ifstream file(m_vehicle_file.get_path());
|
||||
nlohmann::json all_vehicles;
|
||||
|
||||
try
|
||||
{
|
||||
file >> m_all_vehicles;
|
||||
file >> all_vehicles;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,18 @@
|
||||
|
||||
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
|
||||
{
|
||||
file m_vehicle_file;
|
||||
@ -10,10 +22,12 @@ namespace big
|
||||
std::condition_variable m_cond;
|
||||
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;
|
||||
std::string m_model;
|
||||
Hash m_model_hash;
|
||||
bool m_new_model = false;
|
||||
float m_heading = 0.f;
|
||||
bool m_running = false;
|
||||
@ -21,11 +35,11 @@ namespace big
|
||||
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 set_preview_vehicle(const nlohmann::json& item);
|
||||
void stop_preview();
|
||||
|
||||
private:
|
||||
|
@ -9,9 +9,9 @@ namespace big::math
|
||||
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)
|
||||
|
@ -89,7 +89,7 @@ namespace big::mobile
|
||||
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.");
|
||||
|
||||
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());
|
||||
|
||||
// despawn current veh
|
||||
@ -112,8 +112,10 @@ namespace big::mobile
|
||||
// blocking call till vehicle is delivered
|
||||
notify::busy_spinner("Delivering vehicle...", mechanic_global.at(958).as<int*>(), -1);
|
||||
|
||||
if (g->vehicle.pv_teleport_into)
|
||||
vehicle::bring(globals::get_personal_vehicle(), self::pos);
|
||||
if (g->clone_pv.spawn_inside)
|
||||
{
|
||||
big::vehicle::bring(globals::get_personal_vehicle(), self::pos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
|
||||
namespace big::vehicle
|
||||
{
|
||||
inline auto spawn_global = script_global(2725269);
|
||||
|
||||
inline void go_into_personal_vehicle()
|
||||
{
|
||||
*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");
|
||||
|
||||
Vector3 vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true);
|
||||
auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true);
|
||||
teleport::load_ground_at_3dcoord(vecVehicleLocation);
|
||||
|
||||
if (!entity::take_control_of(veh))
|
||||
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_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)
|
||||
{
|
||||
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_DEFORMATION_FIXED(veh);
|
||||
@ -54,45 +109,123 @@ namespace big::vehicle
|
||||
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);
|
||||
|
||||
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;
|
||||
STREAMING::REQUEST_MODEL(hash);
|
||||
|
||||
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)
|
||||
@ -108,9 +241,14 @@ namespace big::vehicle
|
||||
VEHICLE::TOGGLE_VEHICLE_MOD(veh, 17 /* Xenon Headlights */, TRUE);
|
||||
VEHICLE::SET_VEHICLE_WINDOW_TINT(veh, 1);
|
||||
VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, false);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,7 @@
|
||||
namespace big
|
||||
{
|
||||
void view::mobile() {
|
||||
components::button("Mors Mutual Fix All Vehicles", [] {
|
||||
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();
|
||||
ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always);
|
||||
|
||||
components::small_text("Lester");
|
||||
|
||||
@ -21,63 +14,11 @@ namespace big
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
components::small_text("Mechanic - Personal Vehicles");
|
||||
|
||||
static char search[64];
|
||||
static std::string lower_search;
|
||||
|
||||
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();
|
||||
|
||||
components::button("Mors Mutual Fix All Vehicles", [] {
|
||||
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")
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ namespace big
|
||||
|
||||
components::button("Clean Player", [] {
|
||||
entity::clean_ped(self::ped);
|
||||
});
|
||||
});
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
@ -111,7 +111,7 @@ namespace big
|
||||
ImGui::SliderInt("###wanted_level", &g->self.wanted_level, 0, 5) &&
|
||||
!g->self.force_wanted_level &&
|
||||
g_local_player != nullptr
|
||||
) {
|
||||
) {
|
||||
g_local_player->m_player_info->m_wanted_level = g->self.wanted_level;
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,8 @@ namespace big
|
||||
|
||||
components::small_text("Proofs");
|
||||
|
||||
if (ImGui::Button("Check all")) {
|
||||
if (ImGui::Button("Check all"))
|
||||
{
|
||||
g->self.proof_bullet = true;
|
||||
g->self.proof_fire = true;
|
||||
g->self.proof_collision = true;
|
||||
@ -133,7 +134,8 @@ namespace big
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Uncheck all")) {
|
||||
if (ImGui::Button("Uncheck all"))
|
||||
{
|
||||
g->self.proof_bullet = false;
|
||||
g->self.proof_fire = false;
|
||||
g->self.proof_collision = false;
|
||||
@ -173,31 +175,41 @@ namespace big
|
||||
ImGui::EndGroup();
|
||||
|
||||
g->self.proof_mask = 0;
|
||||
if (g->self.godmode) {
|
||||
if (g->self.godmode)
|
||||
{
|
||||
g->self.proof_mask |= static_cast<int>(eEntityProofs::GOD);
|
||||
} else {
|
||||
if (g->self.proof_bullet) {
|
||||
} else
|
||||
{
|
||||
if (g->self.proof_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);
|
||||
}
|
||||
if (g->self.proof_collision) {
|
||||
if (g->self.proof_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);
|
||||
}
|
||||
if (g->self.proof_explosion) {
|
||||
if (g->self.proof_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);
|
||||
}
|
||||
if (g->self.proof_drown) {
|
||||
if (g->self.proof_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);
|
||||
}
|
||||
}
|
||||
|
151
BigBaseV2/src/views/vehicle/view_pv.cpp
Normal file
151
BigBaseV2/src/views/vehicle/view_pv.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,15 +6,6 @@
|
||||
|
||||
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() {
|
||||
ImGui::SetWindowSize({ 0.f, (float)*g_pointers->m_resolution_y }, ImGuiCond_Always);
|
||||
|
||||
@ -24,48 +15,61 @@ namespace big
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Spawn Maxed", &g->spawn.spawn_maxed);
|
||||
|
||||
components::input_text_with_hint("Model Name", "Search", model, sizeof(model), ImGuiInputTextFlags_EnterReturnsTrue, []
|
||||
{
|
||||
const auto ped = self::ped;
|
||||
static char plate[9] = { 0 };
|
||||
strncpy(plate, g->spawn.plate.c_str(), 9);
|
||||
|
||||
const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped, 2.f, 2.f, 0.f);
|
||||
const auto veh = vehicle::spawn(model, location, g_local_player->m_player_info->m_ped->m_navigation->m_right.x + 90.f);
|
||||
|
||||
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);
|
||||
ImGui::SetNextItemWidth(300.f);
|
||||
components::input_text_with_hint("Plate", "Plate Number", plate, sizeof(plate), ImGuiInputTextFlags_None, [] {
|
||||
g->spawn.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);
|
||||
});
|
||||
|
||||
// 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"];
|
||||
std::string display_name = item["DisplayName"];
|
||||
for (auto& item : item_arr) {
|
||||
std::string display_name = item.display_name;
|
||||
std::string display_manufacturer = item.display_manufacturer;
|
||||
|
||||
std::string manufacturer;
|
||||
std::string search = model;
|
||||
std::transform(search.begin(), search.end(), search.begin(), ::tolower);
|
||||
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 (!item["ManufacturerDisplayName"].is_null())
|
||||
manufacturer = item["ManufacturerDisplayName"];
|
||||
if (
|
||||
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() ||
|
||||
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 = self::pos;
|
||||
const Vehicle veh = vehicle::spawn(item["Name"], location, 0.f);
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -77,17 +81,27 @@ namespace big
|
||||
vehicle::max_vehicle(veh);
|
||||
}
|
||||
|
||||
vehicle::set_plate(veh, plate);
|
||||
|
||||
g_vehicle_preview_service->stop_preview();
|
||||
});
|
||||
//ImGui::PopID();
|
||||
|
||||
if (g->spawn.preview_vehicle && ImGui::IsItemHovered())
|
||||
{
|
||||
g_vehicle_preview_service->set_preview_vehicle(item);
|
||||
}
|
||||
else if (g->spawn.preview_vehicle && !ImGui::IsAnyItemHovered())
|
||||
{
|
||||
g_vehicle_preview_service->stop_preview();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else ImGui::Text("No vehicles in registry.");
|
||||
else
|
||||
{
|
||||
ImGui::Text("No vehicles in registry.");
|
||||
}
|
||||
ImGui::ListBoxFooter();
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ namespace big
|
||||
static void session();
|
||||
static void settings();
|
||||
static void spawn();
|
||||
static void pv();
|
||||
static void spoofing();
|
||||
static void teleport();
|
||||
static void vehicle();
|
||||
|
Reference in New Issue
Block a user