Redesigned the preview system entirely. (#2888)
This commit is contained in:
parent
21da47f3e5
commit
1f556a8c78
@ -210,4 +210,6 @@ namespace big::functions
|
|||||||
using get_ped_seat = CGetPedSeatReturnClass*(*)(PVOID seat_info, CPed* ped);
|
using get_ped_seat = CGetPedSeatReturnClass*(*)(PVOID seat_info, CPed* ped);
|
||||||
|
|
||||||
using received_clone_remove = void (*)(CNetworkObjectMgr*, CNetGamePlayer*, CNetGamePlayer*, int16_t, uint32_t);
|
using received_clone_remove = void (*)(CNetworkObjectMgr*, CNetGamePlayer*, CNetGamePlayer*, int16_t, uint32_t);
|
||||||
|
|
||||||
|
using can_create_vehicle = bool (*)();
|
||||||
}
|
}
|
||||||
|
@ -365,6 +365,8 @@ namespace big
|
|||||||
functions::received_clone_remove m_received_clone_remove;
|
functions::received_clone_remove m_received_clone_remove;
|
||||||
|
|
||||||
CWeaponInfoManager* m_weapon_info_manager;
|
CWeaponInfoManager* m_weapon_info_manager;
|
||||||
|
|
||||||
|
functions::can_create_vehicle m_can_create_vehicle;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
||||||
|
@ -140,6 +140,8 @@ namespace big
|
|||||||
|
|
||||||
detour_hook_helper::add<hooks::received_clone_remove>("RCR", g_pointers->m_gta.m_received_clone_remove);
|
detour_hook_helper::add<hooks::received_clone_remove>("RCR", g_pointers->m_gta.m_received_clone_remove);
|
||||||
|
|
||||||
|
detour_hook_helper::add<hooks::can_create_vehicle>("CCV", g_pointers->m_gta.m_can_create_vehicle);
|
||||||
|
|
||||||
g_hooking = this;
|
g_hooking = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,8 @@ namespace big
|
|||||||
static bool sync_reader_serialize_vec3(void* _this, rage::fvector3* vec, float divisor, int size);
|
static bool sync_reader_serialize_vec3(void* _this, rage::fvector3* vec, float divisor, int size);
|
||||||
static bool sync_reader_serialize_vec3_signed(void* _this, rage::fvector3* vec, float divisor, int size);
|
static bool sync_reader_serialize_vec3_signed(void* _this, rage::fvector3* vec, float divisor, int size);
|
||||||
static bool sync_reader_serialize_array(void* _this, void* array, int size);
|
static bool sync_reader_serialize_array(void* _this, void* array, int size);
|
||||||
|
|
||||||
|
static bool can_create_vehicle();
|
||||||
};
|
};
|
||||||
|
|
||||||
class minhook_keepalive
|
class minhook_keepalive
|
||||||
|
10
src/hooks/script/can_create_vehicle.cpp
Normal file
10
src/hooks/script/can_create_vehicle.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "hooking/hooking.hpp"
|
||||||
|
#include "gta/pools.hpp"
|
||||||
|
|
||||||
|
namespace big
|
||||||
|
{
|
||||||
|
bool hooks::can_create_vehicle()
|
||||||
|
{
|
||||||
|
return (**g_pointers->m_gta.m_vehicle_pool)->m_item_count < (**g_pointers->m_gta.m_vehicle_pool)->m_size;
|
||||||
|
}
|
||||||
|
}
|
@ -1772,6 +1772,15 @@ namespace big
|
|||||||
{
|
{
|
||||||
g_pointers->m_gta.m_weapon_info_manager = ptr.add(3).rip().sub(72).as<CWeaponInfoManager*>();
|
g_pointers->m_gta.m_weapon_info_manager = ptr.add(3).rip().sub(72).as<CWeaponInfoManager*>();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Can Create Vehicle
|
||||||
|
{
|
||||||
|
"CCV",
|
||||||
|
"8B 0D ? ? ? ? 39 0D ? ? ? ? 0F 9C C0",
|
||||||
|
[](memory::handle ptr)
|
||||||
|
{
|
||||||
|
g_pointers->m_gta.m_can_create_vehicle = ptr.as<functions::can_create_vehicle>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
>(); // don't leave a trailing comma at the end
|
>(); // don't leave a trailing comma at the end
|
||||||
|
|
||||||
|
@ -22,107 +22,92 @@ namespace big
|
|||||||
|
|
||||||
void model_preview_service::show_ped(Hash hash)
|
void model_preview_service::show_ped(Hash hash)
|
||||||
{
|
{
|
||||||
m_ped_clone = 0;
|
if (m_running && m_ped_model_hash != hash)
|
||||||
m_veh_model_hash = 0;
|
{
|
||||||
m_veh_owned_mods.clear();
|
stop_preview();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ped_model_hash != hash)
|
if (!m_running)
|
||||||
{
|
{
|
||||||
m_ped_model_hash = hash;
|
m_ped_model_hash = hash;
|
||||||
|
|
||||||
if (m_ped_model_hash != 0)
|
|
||||||
{
|
|
||||||
m_new_model = true;
|
|
||||||
|
|
||||||
preview_loop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_preview_service::show_ped(Hash hash, Ped clone)
|
void model_preview_service::show_ped(Hash hash, Ped clone)
|
||||||
{
|
{
|
||||||
m_veh_model_hash = 0;
|
if (m_running && (m_ped_model_hash != hash || m_ped_clone != clone ))
|
||||||
m_veh_owned_mods.clear();
|
{
|
||||||
|
stop_preview();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ped_model_hash != hash || m_ped_clone != clone)
|
if (!m_running)
|
||||||
{
|
{
|
||||||
m_ped_model_hash = hash;
|
m_ped_model_hash = hash;
|
||||||
m_ped_clone = clone;
|
m_ped_clone = clone;
|
||||||
|
|
||||||
if (m_ped_model_hash != 0)
|
|
||||||
{
|
|
||||||
m_new_model = true;
|
|
||||||
|
|
||||||
preview_loop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_preview_service::show_vehicle(Hash hash, bool spawn_max)
|
void model_preview_service::show_vehicle(Hash hash, bool spawn_max)
|
||||||
{
|
{
|
||||||
m_ped_model_hash = 0;
|
if (m_running && m_veh_model_hash != hash)
|
||||||
m_ped_clone = 0;
|
{
|
||||||
m_veh_owned_mods.clear();
|
stop_preview();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_veh_model_hash != hash || m_veh_spawn_max != spawn_max)
|
if (!m_running)
|
||||||
{
|
{
|
||||||
m_veh_model_hash = hash;
|
m_veh_model_hash = hash;
|
||||||
m_current_persisted_vehicle_name.clear();
|
|
||||||
|
|
||||||
if (m_veh_model_hash != 0)
|
|
||||||
{
|
|
||||||
m_veh_spawn_max = spawn_max;
|
|
||||||
m_new_model = true;
|
|
||||||
|
|
||||||
preview_loop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_preview_service::show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max)
|
void model_preview_service::show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max)
|
||||||
{
|
{
|
||||||
m_ped_model_hash = 0;
|
if (m_running && m_veh_model_hash != owned_mods.find(MOD_MODEL_HASH)->second)
|
||||||
m_ped_clone = 0;
|
|
||||||
m_current_persisted_vehicle_name.clear();
|
|
||||||
|
|
||||||
if (m_veh_spawn_max != spawn_max || m_veh_owned_mods.size() != owned_mods.size()
|
|
||||||
|| !std::equal(m_veh_owned_mods.begin(), m_veh_owned_mods.end(), owned_mods.begin()))
|
|
||||||
{
|
{
|
||||||
m_veh_owned_mods.clear();
|
stop_preview();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_running)
|
||||||
|
{
|
||||||
auto hash_item = owned_mods.find(MOD_MODEL_HASH);
|
auto hash_item = owned_mods.find(MOD_MODEL_HASH);
|
||||||
|
|
||||||
m_veh_model_hash = hash_item->second;
|
m_veh_model_hash = hash_item->second;
|
||||||
|
m_veh_owned_mods.insert(owned_mods.begin(), owned_mods.end());
|
||||||
if (m_veh_model_hash != 0)
|
m_veh_spawn_max = spawn_max;
|
||||||
{
|
|
||||||
m_veh_owned_mods.insert(owned_mods.begin(), owned_mods.end());
|
|
||||||
m_veh_spawn_max = spawn_max;
|
|
||||||
m_new_model = true;
|
|
||||||
|
|
||||||
preview_loop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_preview_service::show_vehicle_persisted(std::string vehicle_name)
|
void model_preview_service::show_vehicle_persisted(std::string vehicle_name)
|
||||||
{
|
{
|
||||||
m_ped_model_hash = 0;
|
if (m_running && m_current_persisted_vehicle_name != vehicle_name)
|
||||||
m_ped_clone = 0;
|
{
|
||||||
m_veh_model_hash = 0;
|
stop_preview();
|
||||||
|
return;
|
||||||
if (m_current_persisted_vehicle_name != vehicle_name)
|
}
|
||||||
|
|
||||||
|
if (!m_running)
|
||||||
{
|
{
|
||||||
m_current_persisted_vehicle_name = vehicle_name;
|
m_current_persisted_vehicle_name = vehicle_name;
|
||||||
m_new_model = true;
|
|
||||||
|
|
||||||
preview_loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_preview_service::preview_loop()
|
void model_preview_service::preview_loop()
|
||||||
{
|
{
|
||||||
if (m_running || m_loop_running)
|
if (m_running)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -130,28 +115,15 @@ namespace big
|
|||||||
m_running = true;
|
m_running = true;
|
||||||
|
|
||||||
g_fiber_pool->queue_job([this] {
|
g_fiber_pool->queue_job([this] {
|
||||||
m_loop_running = true;
|
m_heading = 0.f;
|
||||||
m_heading = 0;
|
m_rotation_start_time = std::chrono::steady_clock::now();
|
||||||
start_time = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
while (g_running && m_running && g_gui->is_open() && (m_ped_model_hash || m_veh_model_hash || !m_current_persisted_vehicle_name.empty()))
|
while (!m_shutdown_preview && g_running && g_gui->is_open() )
|
||||||
{
|
{
|
||||||
Vector3 location;
|
Vector3 location{};
|
||||||
|
|
||||||
if (m_ped_model_hash)
|
|
||||||
{
|
|
||||||
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 5.f, -.5f);
|
|
||||||
}
|
|
||||||
else if (m_veh_model_hash || !m_current_persisted_vehicle_name.empty())
|
|
||||||
{
|
|
||||||
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_current_ent == 0)
|
if (m_current_ent == 0)
|
||||||
{
|
{
|
||||||
m_new_model = false;
|
|
||||||
location.z = -10.f;
|
|
||||||
|
|
||||||
if (m_ped_model_hash)
|
if (m_ped_model_hash)
|
||||||
{
|
{
|
||||||
m_current_ent = ped::spawn(ePedType::PED_TYPE_ARMY, m_ped_model_hash, m_ped_clone, location, 0.f, false);
|
m_current_ent = ped::spawn(ePedType::PED_TYPE_ARMY, m_ped_model_hash, m_ped_clone, location, 0.f, false);
|
||||||
@ -174,7 +146,7 @@ namespace big
|
|||||||
}
|
}
|
||||||
else if (!m_current_persisted_vehicle_name.empty())
|
else if (!m_current_persisted_vehicle_name.empty())
|
||||||
{
|
{
|
||||||
m_current_ent = persist_car_service::load_vehicle(m_current_persisted_vehicle_name, g.persist_car.persist_vehicle_sub_folder, Vector3());
|
m_current_ent = persist_car_service::preview_vehicle(m_current_persisted_vehicle_name, g.persist_car.persist_vehicle_sub_folder, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_current_ent)
|
if (m_current_ent)
|
||||||
@ -191,23 +163,28 @@ namespace big
|
|||||||
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_ent, false);
|
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_ent, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_new_model)
|
|
||||||
{
|
|
||||||
entity::delete_entity(m_current_ent, true);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (const int alpha = ENTITY::GET_ENTITY_ALPHA(m_current_ent); alpha < 255)
|
if (m_ped_model_hash)
|
||||||
{
|
{
|
||||||
ENTITY::SET_ENTITY_ALPHA(m_current_ent, std::min<int>(255, alpha + 20), false);
|
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 5.f, -.5f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTITY::SET_ENTITY_HEADING(m_current_ent, m_heading);
|
|
||||||
ENTITY::SET_ENTITY_COORDS(m_current_ent, location.x, location.y, location.z, 0, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto alpha = ENTITY::GET_ENTITY_ALPHA(m_current_ent); alpha < 255)
|
||||||
|
{
|
||||||
|
ENTITY::SET_ENTITY_ALPHA(m_current_ent, std::min<int>(255, alpha + 20), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTITY::SET_ENTITY_HEADING(m_current_ent, m_heading);
|
||||||
|
ENTITY::SET_ENTITY_COORDS(m_current_ent, location.x, location.y, location.z, 0, 0, 0, 0);
|
||||||
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() / 1000.0; // Convert to seconds
|
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_rotation_start_time).count() / 1000.0; // Convert to seconds
|
||||||
|
|
||||||
m_heading = (elapsed_time / 10.0) * 360.0; // Rotate 360 degrees every 10 seconds
|
m_heading = (elapsed_time / 10.0) * 360.0; // Rotate 360 degrees every 10 seconds
|
||||||
m_heading = fmod(m_heading, 360.0); // Ensure rotation is always between 0 and 360
|
m_heading = fmod(m_heading, 360.0); // Ensure rotation is always between 0 and 360
|
||||||
@ -215,21 +192,27 @@ namespace big
|
|||||||
script::get_current()->yield();
|
script::get_current()->yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
entity::delete_entity(m_current_ent, true);
|
ENTITY::DELETE_ENTITY(&m_current_ent);
|
||||||
|
|
||||||
m_current_ent = 0;
|
clear_data();
|
||||||
m_ped_model_hash = 0;
|
|
||||||
m_veh_model_hash = 0;
|
|
||||||
m_veh_owned_mods.clear();
|
|
||||||
m_current_persisted_vehicle_name.clear();
|
|
||||||
m_running = false;
|
|
||||||
m_loop_running = false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void model_preview_service::clear_data()
|
||||||
|
{
|
||||||
|
m_veh_owned_mods.clear();
|
||||||
|
m_ped_model_hash = {};
|
||||||
|
m_veh_model_hash = {};
|
||||||
|
m_ped_clone = {};
|
||||||
|
m_current_persisted_vehicle_name = {};
|
||||||
|
m_shutdown_preview = false;
|
||||||
|
m_running = false;
|
||||||
|
m_current_ent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void model_preview_service::stop_preview()
|
void model_preview_service::stop_preview()
|
||||||
{
|
{
|
||||||
m_veh_owned_mods.clear();
|
if (m_running)
|
||||||
m_running = false;
|
m_shutdown_preview = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,24 +5,21 @@ namespace big
|
|||||||
{
|
{
|
||||||
class model_preview_service
|
class model_preview_service
|
||||||
{
|
{
|
||||||
Entity m_current_ent = 0;
|
Entity m_current_ent{};
|
||||||
|
float m_heading{};
|
||||||
|
|
||||||
|
Hash m_ped_model_hash{};
|
||||||
|
Hash m_veh_model_hash{};
|
||||||
|
Ped m_ped_clone{};
|
||||||
|
std::string m_current_persisted_vehicle_name;
|
||||||
|
|
||||||
Hash m_veh_model_hash = 0;
|
|
||||||
std::map<int, int32_t> m_veh_owned_mods;
|
std::map<int, int32_t> m_veh_owned_mods;
|
||||||
bool m_veh_spawn_max = false;
|
bool m_veh_spawn_max = false;
|
||||||
|
|
||||||
Hash m_ped_model_hash = 0;
|
bool m_running = false;
|
||||||
Ped m_ped_clone = 0;
|
bool m_shutdown_preview = false;
|
||||||
|
|
||||||
bool m_new_model = false;
|
|
||||||
float m_heading = 0.f;
|
|
||||||
bool m_loop_running = false;
|
|
||||||
bool m_running = false;
|
|
||||||
|
|
||||||
std::string m_current_persisted_vehicle_name;
|
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> start_time;
|
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> m_rotation_start_time;
|
||||||
public:
|
public:
|
||||||
model_preview_service();
|
model_preview_service();
|
||||||
~model_preview_service();
|
~model_preview_service();
|
||||||
@ -34,12 +31,11 @@ namespace big
|
|||||||
void show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max);
|
void show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max);
|
||||||
void show_vehicle_persisted(std::string vehicle_name);
|
void show_vehicle_persisted(std::string vehicle_name);
|
||||||
void show_vehicle(Vehicle veh);
|
void show_vehicle(Vehicle veh);
|
||||||
|
void stop_preview();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void clear_data();
|
||||||
void preview_loop();
|
void preview_loop();
|
||||||
|
|
||||||
public:
|
|
||||||
void stop_preview();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline model_preview_service* g_model_preview_service{};
|
inline model_preview_service* g_model_preview_service{};
|
||||||
|
@ -27,6 +27,28 @@ namespace big
|
|||||||
file_stream.close();
|
file_stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vehicle persist_car_service::preview_vehicle(std::string_view file_name, std::string folder_name, const std::optional<Vector3>& spawn_coords)
|
||||||
|
{
|
||||||
|
const auto file = check_vehicle_folder(folder_name).get_file(file_name);
|
||||||
|
|
||||||
|
std::ifstream file_stream(file.get_path());
|
||||||
|
|
||||||
|
nlohmann::json vehicle_json;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file_stream >> vehicle_json;
|
||||||
|
file_stream.close();
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
g_notification_service.push_warning("PERSIST_CAR_TITLE"_T.data(), "Failed to load JSON file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spawn_vehicle_json(vehicle_json, self::ped, spawn_coords, true);
|
||||||
|
}
|
||||||
|
|
||||||
Vehicle persist_car_service::load_vehicle(std::string_view file_name, std::string folder_name, const std::optional<Vector3>& spawn_coords)
|
Vehicle persist_car_service::load_vehicle(std::string_view file_name, std::string folder_name, const std::optional<Vector3>& spawn_coords)
|
||||||
{
|
{
|
||||||
const auto file = check_vehicle_folder(folder_name).get_file(file_name);
|
const auto file = check_vehicle_folder(folder_name).get_file(file_name);
|
||||||
@ -188,16 +210,16 @@ namespace big
|
|||||||
return vehicle;
|
return vehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vehicle persist_car_service::spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords)
|
Vehicle persist_car_service::spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords, bool is_preview)
|
||||||
{
|
{
|
||||||
const Hash vehicle_hash = vehicle_json[vehicle_model_hash_key];
|
const Hash vehicle_hash = vehicle_json[vehicle_model_hash_key];
|
||||||
const Vector3& spawn_location = spawn_coords.has_value() ? spawn_coords.value() : vehicle::get_spawn_location(g.persist_car.spawn_inside, vehicle_hash);
|
const Vector3& spawn_location = spawn_coords.has_value() ? spawn_coords.value() : vehicle::get_spawn_location(g.persist_car.spawn_inside, vehicle_hash);
|
||||||
const float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped);
|
const float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped);
|
||||||
|
|
||||||
Vehicle vehicle = self::veh;
|
Vehicle vehicle = self::veh;
|
||||||
if (spawn_coords.has_value() || (!spawn_coords.has_value() && ENTITY::GET_ENTITY_MODEL(vehicle) != vehicle_hash))
|
if (is_preview || (!is_preview && ENTITY::GET_ENTITY_MODEL(vehicle) != vehicle_hash))
|
||||||
{
|
{
|
||||||
vehicle = big::vehicle::spawn(vehicle_hash, spawn_location, spawn_heading);
|
vehicle = big::vehicle::spawn(vehicle_hash, spawn_location, spawn_heading, !is_preview);
|
||||||
|
|
||||||
if (spawn_location.x + spawn_location.y + spawn_location.z != 0)
|
if (spawn_location.x + spawn_location.y + spawn_location.z != 0)
|
||||||
script::get_current()->yield(); //This is needed to wait for the engine to instantiate things like the radio station so it won't overwrite it on the next frame.
|
script::get_current()->yield(); //This is needed to wait for the engine to instantiate things like the radio station so it won't overwrite it on the next frame.
|
||||||
|
@ -13,6 +13,7 @@ namespace big
|
|||||||
static Vehicle clone_ped_car(Ped ped, Vehicle vehicle);
|
static Vehicle clone_ped_car(Ped ped, Vehicle vehicle);
|
||||||
static void save_vehicle(Vehicle vehicle, std::string_view file_name, std::string folder_name);
|
static void save_vehicle(Vehicle vehicle, std::string_view file_name, std::string folder_name);
|
||||||
static Vehicle load_vehicle(std::string_view file_name, std::string folder_name = "", const std::optional<Vector3>& = std::nullopt);
|
static Vehicle load_vehicle(std::string_view file_name, std::string folder_name = "", const std::optional<Vector3>& = std::nullopt);
|
||||||
|
static Vehicle preview_vehicle(std::string_view file_name, std::string folder_name = "", const std::optional<Vector3>& = std::nullopt);
|
||||||
static void delete_vehicle(std::string_view file_name, std::string folder_name);
|
static void delete_vehicle(std::string_view file_name, std::string folder_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -68,7 +69,7 @@ namespace big
|
|||||||
|
|
||||||
static Vehicle spawn_vehicle_full(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt);
|
static Vehicle spawn_vehicle_full(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt);
|
||||||
static Vehicle spawn_vehicle(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords);
|
static Vehicle spawn_vehicle(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords);
|
||||||
static Vehicle spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt);
|
static Vehicle spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt, bool is_preview = false);
|
||||||
|
|
||||||
static nlohmann::json get_full_vehicle_json(Vehicle vehicle);
|
static nlohmann::json get_full_vehicle_json(Vehicle vehicle);
|
||||||
|
|
||||||
|
@ -26,7 +26,10 @@ namespace big::entity
|
|||||||
void delete_entity(Entity& ent, bool force)
|
void delete_entity(Entity& ent, bool force)
|
||||||
{
|
{
|
||||||
if (!ENTITY::DOES_ENTITY_EXIST(ent))
|
if (!ENTITY::DOES_ENTITY_EXIST(ent))
|
||||||
|
{
|
||||||
|
ent = NULL;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (!force && !take_control_of(ent))
|
if (!force && !take_control_of(ent))
|
||||||
{
|
{
|
||||||
LOG(VERBOSE) << "Failed to take control of entity before deleting";
|
LOG(VERBOSE) << "Failed to take control of entity before deleting";
|
||||||
|
@ -354,9 +354,9 @@ namespace big::vehicle
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked)
|
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked, bool is_script_vehicle)
|
||||||
{
|
{
|
||||||
auto vehicle = spawn(owned_mods[MOD_MODEL_HASH], location, heading, is_networked);
|
auto vehicle = spawn(owned_mods[MOD_MODEL_HASH], location, heading, is_networked, is_script_vehicle);
|
||||||
if (vehicle == 0)
|
if (vehicle == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -29,7 +29,7 @@ namespace big::vehicle
|
|||||||
Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked = true, bool script_veh = false);
|
Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked = true, bool script_veh = false);
|
||||||
Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading);
|
Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading);
|
||||||
std::map<int, int32_t> get_owned_mods_from_vehicle_idx(script_global vehicle_idx);
|
std::map<int, int32_t> get_owned_mods_from_vehicle_idx(script_global vehicle_idx);
|
||||||
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked = true);
|
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked = true, bool is_script_vehicle = false);
|
||||||
std::map<int, int32_t> get_owned_mods_from_vehicle(Vehicle vehicle);
|
std::map<int, int32_t> get_owned_mods_from_vehicle(Vehicle vehicle);
|
||||||
void teleport_into_vehicle(Vehicle veh);
|
void teleport_into_vehicle(Vehicle veh);
|
||||||
void max_vehicle(Vehicle veh);
|
void max_vehicle(Vehicle veh);
|
||||||
|
Reference in New Issue
Block a user