Add more spoofing options and added clang-format (#1020)

* feat(Spoofing): add spoofing
* feat(Spoofing): prepare code for player attach
* remove(PlayerAttach): isn't going to work due to netsync architecture
* fix(GUI): fix scaling
* feat(Project): add clang-format file
* feat(Classes): update classes
* fix(BlackHole): remove unnecessary cleanup
* fix(Formatting): fix formatting for initializer lists
* feat(clang-format): Set tab width and 1 space before comment

Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
maybegreat48
2023-03-01 21:27:15 +00:00
committed by GitHub
parent 92aea20cd6
commit 97a8c5d60b
466 changed files with 55224 additions and 35596 deletions

View File

@ -4,10 +4,10 @@ namespace big
{
handling_profile::handling_profile(CVehicle* vehicle)
{
m_gravity = vehicle->m_gravity;
m_gravity = vehicle->m_gravity;
m_handling_data = *vehicle->m_handling_data;
if(std::isinf(m_handling_data.m_traction_spring_delta_max_ratio))
if (std::isinf(m_handling_data.m_traction_spring_delta_max_ratio))
m_handling_data.m_traction_spring_delta_max_ratio = 0.f;
}
@ -16,10 +16,10 @@ namespace big
const auto hash = vehicle->m_handling_data->m_model_hash;
vehicle->m_gravity = m_gravity;
// cursed but works perfectly without overriding members that we shouldn't override
nlohmann::json j = m_handling_data; // exports our binary object so we can apply it field by field instead of copying the whole object
from_json(j, *vehicle->m_handling_data); // macro is defined in global scope of which CHandlingData is part of
nlohmann::json j = m_handling_data;// exports our binary object so we can apply it field by field instead of copying the whole object
from_json(j, *vehicle->m_handling_data);// macro is defined in global scope of which CHandlingData is part of
if (restore_hash)
vehicle->m_handling_data->m_model_hash = hash;

View File

@ -6,19 +6,7 @@ namespace rage
{
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(rage::fvector3, x, y, z)
}
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CHandlingData,
m_mass, m_initial_drag_coeff, m_downforce_multiplier, m_centre_of_mass, m_inertia_mult,
m_buoyancy, m_drive_bias_rear, m_drive_bias_front, m_acceleration, m_initial_drive_gears,
m_drive_inertia, m_upshift, m_downshift, m_initial_drive_force, m_drive_max_flat_velocity,
m_initial_drive_max_flat_vel, m_brake_force, m_brake_bias_front, m_brake_bias_rear,
m_handbrake_force, m_steering_lock, m_steering_lock_ratio, m_traction_curve_max,
m_traction_curve_lateral, m_traction_curve_min, m_traction_curve_ratio, m_curve_lateral,
m_curve_lateral_ratio, m_traction_spring_delta_max, m_traction_spring_delta_max_ratio,
m_low_speed_traction_loss_mult, m_camber_stiffness, m_traction_bias_front, m_traction_bias_rear,
m_traction_loss_mult, m_suspension_force, m_suspension_comp_damp, m_suspension_rebound_damp,
m_suspension_upper_limit, m_suspension_lower_limit, m_suspension_raise, m_suspension_bias_front,
m_suspension_bias_rear, m_anti_rollbar_force, m_anti_rollbar_bias_front, m_anti_rollbar_bias_rear,
m_roll_centre_height_front, m_roll_centre_height_rear, m_collision_damage_mult)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CHandlingData, m_mass, m_initial_drag_coeff, m_downforce_multiplier, m_centre_of_mass, m_inertia_mult, m_buoyancy, m_drive_bias_rear, m_drive_bias_front, m_acceleration, m_initial_drive_gears, m_drive_inertia, m_upshift, m_downshift, m_initial_drive_force, m_drive_max_flat_velocity, m_initial_drive_max_flat_vel, m_brake_force, m_brake_bias_front, m_brake_bias_rear, m_handbrake_force, m_steering_lock, m_steering_lock_ratio, m_traction_curve_max, m_traction_curve_lateral, m_traction_curve_min, m_traction_curve_ratio, m_curve_lateral, m_curve_lateral_ratio, m_traction_spring_delta_max, m_traction_spring_delta_max_ratio, m_low_speed_traction_loss_mult, m_camber_stiffness, m_traction_bias_front, m_traction_bias_rear, m_traction_loss_mult, m_suspension_force, m_suspension_comp_damp, m_suspension_rebound_damp, m_suspension_upper_limit, m_suspension_lower_limit, m_suspension_raise, m_suspension_bias_front, m_suspension_bias_rear, m_anti_rollbar_force, m_anti_rollbar_bias_front, m_anti_rollbar_bias_rear, m_roll_centre_height_front, m_roll_centre_height_rear, m_collision_damage_mult)
namespace big
{
@ -36,6 +24,5 @@ namespace big
private:
float m_gravity;
CHandlingData m_handling_data;
};
}

View File

@ -1,10 +1,11 @@
#include "gta_util.hpp"
#include "handling_service.hpp"
#include "gta_util.hpp"
namespace big
{
handling_service::handling_service() :
m_profiles_folder(g_file_manager->get_project_folder("./handling_profiles"))
m_profiles_folder(g_file_manager->get_project_folder("./handling_profiles"))
{
g_handling_service = this;
@ -26,7 +27,7 @@ namespace big
if (!item.is_regular_file())
continue;
auto file_path = item.path();
auto file_path = item.path();
if (file_path.extension() == ".json")
{
auto profile_file = std::ifstream(file_path, std::ios::binary);
@ -44,16 +45,16 @@ namespace big
LOG(WARNING) << "Attempting to convert old handling files, this feature will be removed in the future.";
auto profile_file = std::ifstream(file_path, std::ios::binary);
auto profile = handling_profile();
profile_file.read(reinterpret_cast<char*>(&profile), 328); // hardcoded old size to prevent overreading
auto profile = handling_profile();
profile_file.read(reinterpret_cast<char*>(&profile), 328);// hardcoded old size to prevent overreading
profile_file.close();
const auto new_save = file_path.stem().string();
// this will make sure we only copy the fields we want to copy
nlohmann::json j = profile;
nlohmann::json j = profile;
const auto save_file_path = m_profiles_folder.get_file("./" + new_save + ".json");
auto save_file = std::ofstream(save_file_path.get_path(), std::ios::binary);
auto save_file = std::ofstream(save_file_path.get_path(), std::ios::binary);
save_file << j.dump(4);
// remove old file
@ -98,7 +99,7 @@ namespace big
auto profile = handling_profile(vehicle);
auto save_file = std::ofstream(save.get_path(), std::ios::binary);
auto save_file = std::ofstream(save.get_path(), std::ios::binary);
nlohmann::json j = profile;
save_file << j.dump(4);
save_file.close();

View File

@ -10,9 +10,9 @@ namespace big
handling_service();
~handling_service();
handling_service(const handling_service&) = delete;
handling_service(handling_service&&) noexcept = delete;
handling_service& operator=(const handling_service&) = delete;
handling_service(const handling_service&) = delete;
handling_service(handling_service&&) noexcept = delete;
handling_service& operator=(const handling_service&) = delete;
handling_service& operator=(handling_service&&) noexcept = delete;
std::size_t load_files();
@ -33,7 +33,6 @@ namespace big
// contains the handling profiles of a vehicles before they're been modified
std::unordered_map<std::uint32_t, handling_profile> m_vehicle_backups;
};
inline handling_service* g_handling_service{};

View File

@ -1,6 +1,6 @@
#pragma once
#include "natives.hpp"
#include "json_util.hpp"
#include "natives.hpp"
namespace big
{
@ -12,18 +12,20 @@ namespace big
bool has_collision;
bool is_visible;
bool is_invincible;
};
static void to_json(nlohmann::json& j, const model_attachment& attachment)
{
j = nlohmann::json{ {"model_hash", attachment.model_hash},
{"position_x", attachment.position.x}, {"position_y", attachment.position.y}, {"position_z", attachment.position.z},
{"rotation_x", attachment.rotation.x}, {"rotation_y", attachment.rotation.y}, {"rotation_z", attachment.rotation.z},
{"has_collision", attachment.has_collision},
{"is_visible", attachment.is_visible},
{"is_invincible", attachment.is_invincible}
j = nlohmann::json{{"model_hash", attachment.model_hash},
{"position_x", attachment.position.x},
{"position_y", attachment.position.y},
{"position_z", attachment.position.z},
{"rotation_x", attachment.rotation.x},
{"rotation_y", attachment.rotation.y},
{"rotation_z", attachment.rotation.z},
{"has_collision", attachment.has_collision},
{"is_visible", attachment.is_visible},
{"is_invincible", attachment.is_invincible}
};
};

View File

@ -1,19 +1,20 @@
#include "persist_car_service.hpp"
#include "util/vehicle.hpp"
#include "util/world_model.hpp"
#include "util/misc.hpp"
#include "vehicle/CVehicle.hpp"
#include "base/CObject.hpp"
#include "pointers.hpp"
#include "util/misc.hpp"
#include "util/vehicle.hpp"
#include "util/world_model.hpp"
#include "vehicle/CVehicle.hpp"
namespace big
{
void persist_car_service::save_vehicle(Vehicle vehicle, std::string_view file_name)
{
if (!ENTITY::DOES_ENTITY_EXIST(vehicle) ||
!ENTITY::IS_ENTITY_A_VEHICLE(vehicle))
if (!ENTITY::DOES_ENTITY_EXIST(vehicle) || !ENTITY::IS_ENTITY_A_VEHICLE(vehicle))
{
g_notification_service->push_warning("PERSIST_CAR_TITLE"_T.data(), "PERSIST_CAR_INVALID_VEHICLE_SAVE_ATTEMPT"_T.data());
g_notification_service->push_warning("PERSIST_CAR_TITLE"_T.data(),
"PERSIST_CAR_INVALID_VEHICLE_SAVE_ATTEMPT"_T.data());
return;
}
@ -99,15 +100,25 @@ namespace big
for (const auto& j : model_attachments)
{
const auto attachment = j.get<model_attachment>();
const auto object = world_model::spawn(attachment.model_hash);
const auto object = world_model::spawn(attachment.model_hash);
if (object)
{
ENTITY::ATTACH_ENTITY_TO_ENTITY(
object, vehicle,
0,
attachment.position.x, attachment.position.y, attachment.position.z,
attachment.rotation.x, attachment.rotation.y, attachment.rotation.z,
false, false, false, false, 0, true, 0);
ENTITY::ATTACH_ENTITY_TO_ENTITY(object,
vehicle,
0,
attachment.position.x,
attachment.position.y,
attachment.position.z,
attachment.rotation.x,
attachment.rotation.y,
attachment.rotation.z,
false,
false,
false,
false,
0,
true,
0);
ENTITY::SET_ENTITY_VISIBLE(object, attachment.is_visible, 0);
ENTITY::SET_ENTITY_COLLISION(object, attachment.has_collision, true);
@ -119,15 +130,25 @@ namespace big
for (const auto& j : vehicle_attachments)
{
const auto vehicle_to_attach = spawn_vehicle_json(j[vehicle_key], ped);
auto attachment = j[model_attachment_key].get<big::model_attachment>();
ENTITY::ATTACH_ENTITY_TO_ENTITY(
vehicle_to_attach, vehicle,
0,
attachment.position.x, attachment.position.y, attachment.position.z,
attachment.rotation.x, attachment.rotation.y, attachment.rotation.z,
auto attachment = j[model_attachment_key].get<big::model_attachment>();
ENTITY::ATTACH_ENTITY_TO_ENTITY(vehicle_to_attach,
vehicle,
0,
attachment.position.x,
attachment.position.y,
attachment.position.z,
attachment.rotation.x,
attachment.rotation.y,
attachment.rotation.z,
false,
false,
false,
false,
0,
true,
0);
false, false, false, false, 0, true, 0);
ENTITY::SET_ENTITY_VISIBLE(vehicle_to_attach, attachment.is_visible, 0);
ENTITY::SET_ENTITY_COLLISION(vehicle_to_attach, attachment.has_collision, true);
ENTITY::SET_ENTITY_INVINCIBLE(vehicle_to_attach, attachment.is_invincible);
@ -264,14 +285,14 @@ namespace big
nlohmann::json vehicle_json = get_vehicle_json(vehicle);
vehicle_json[model_attachments_key] = get_model_attachments(vehicle);
vehicle_json[model_attachments_key] = get_model_attachments(vehicle);
vehicle_json[vehicle_attachments_key] = get_vehicle_attachents(vehicle);
Vehicle tow = VEHICLE::GET_ENTITY_ATTACHED_TO_TOW_TRUCK(vehicle);
if (ENTITY::DOES_ENTITY_EXIST(tow))
{
vehicle_json[tow_key] = get_vehicle_json(tow);
vehicle_json[tow_key][model_attachments_key] = get_model_attachments(tow, true);
vehicle_json[tow_key] = get_vehicle_json(tow);
vehicle_json[tow_key][model_attachments_key] = get_model_attachments(tow, true);
vehicle_json[tow_key][vehicle_attachments_key] = get_vehicle_attachents(tow);
}
if (VEHICLE::IS_VEHICLE_ATTACHED_TO_TRAILER(vehicle))
@ -279,8 +300,8 @@ namespace big
Vehicle trailer;
VEHICLE::GET_VEHICLE_TRAILER_VEHICLE(vehicle, &trailer);
vehicle_json[trailer_key] = get_vehicle_json(trailer);
vehicle_json[trailer_key][model_attachments_key] = get_model_attachments(trailer);
vehicle_json[trailer_key] = get_vehicle_json(trailer);
vehicle_json[trailer_key][model_attachments_key] = get_model_attachments(trailer);
vehicle_json[trailer_key][vehicle_attachments_key] = get_vehicle_attachents(trailer);
}
@ -290,21 +311,24 @@ namespace big
model_attachment persist_car_service::get_model_attachment(Vehicle vehicle, Object object)
{
const auto object_location = ENTITY::GET_ENTITY_COORDS(object, 0);
const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehicle, object_location.x, object_location.y, object_location.z);
const auto location = ENTITY::GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehicle,
object_location.x,
object_location.y,
object_location.z);
const auto object_rotation = ENTITY::GET_ENTITY_ROTATION(object, 0);
const auto object_rotation = ENTITY::GET_ENTITY_ROTATION(object, 0);
const auto vehicle_rotation = ENTITY::GET_ENTITY_ROTATION(vehicle, 0);
bool has_collision = ENTITY::GET_ENTITY_COLLISION_DISABLED(object);
bool is_visible = ENTITY::IS_ENTITY_VISIBLE(object);
CObject* cobject = (CObject*)g_pointers->m_handle_to_ptr(vehicle);
bool is_invincible = misc::has_bit_set(&(int&)cobject->m_damage_bits, 8);
bool has_collision = ENTITY::GET_ENTITY_COLLISION_DISABLED(object);
bool is_visible = ENTITY::IS_ENTITY_VISIBLE(object);
CObject* cobject = (CObject*)g_pointers->m_handle_to_ptr(vehicle);
bool is_invincible = misc::has_bit_set(&(int&)cobject->m_damage_bits, 8);
Vector3 rotation;
rotation.x = (object_rotation.x - vehicle_rotation.x);
rotation.y = (object_rotation.y - vehicle_rotation.y);
rotation.z = (object_rotation.z - vehicle_rotation.z);
model_attachment attachment = { ENTITY::GET_ENTITY_MODEL(object), location, rotation, !has_collision, is_visible, is_invincible };
model_attachment attachment = {ENTITY::GET_ENTITY_MODEL(object), location, rotation, !has_collision, is_visible, is_invincible};
return attachment;
}
@ -363,16 +387,14 @@ namespace big
if (!ENTITY::IS_ENTITY_ATTACHED_TO_ENTITY(vehicle, object))
continue;
if (object == VEHICLE::GET_ENTITY_ATTACHED_TO_TOW_TRUCK(vehicle) ||
VEHICLE::IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(object, vehicle))
if (object == VEHICLE::GET_ENTITY_ATTACHED_TO_TOW_TRUCK(vehicle) || VEHICLE::IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(object, vehicle))
continue;
if (object == trailer ||
VEHICLE::IS_VEHICLE_ATTACHED_TO_TRAILER(object))
if (object == trailer || VEHICLE::IS_VEHICLE_ATTACHED_TO_TRAILER(object))
continue;
nlohmann::json model_attachment;
model_attachment[vehicle_key] = get_vehicle_json(object);
model_attachment[vehicle_key] = get_vehicle_json(object);
model_attachment[model_attachment_key] = get_model_attachment(vehicle, object);
attached_vehicles.push_back(model_attachment);
@ -389,7 +411,7 @@ namespace big
int primary_color, secondary_color;
VEHICLE::GET_VEHICLE_COLOURS(vehicle, &primary_color, &secondary_color);
vehicle_json[primary_color_key] = primary_color;
vehicle_json[primary_color_key] = primary_color;
vehicle_json[secondary_color_key] = secondary_color;
if (VEHICLE::GET_IS_VEHICLE_PRIMARY_COLOUR_CUSTOM(vehicle))
{
@ -414,21 +436,21 @@ namespace big
vehicle_json[radio_station_key] = radio_station;
vehicle_json[plate_text_key] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT(vehicle);
vehicle_json[plate_text_key] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT(vehicle);
vehicle_json[plate_text_index_key] = VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle);
int pearlescent_color, wheel_color;
VEHICLE::GET_VEHICLE_EXTRA_COLOURS(vehicle, &pearlescent_color, &wheel_color);
vehicle_json[pearlescent_color_key] = pearlescent_color;
bool has_collision = ENTITY::GET_ENTITY_COLLISION_DISABLED(vehicle);
bool is_visible = ENTITY::IS_ENTITY_VISIBLE(vehicle);
CVehicle* cvehicle = (CVehicle*)g_pointers->m_handle_to_ptr(vehicle);
bool is_invincible = misc::has_bit_set(&(int&)cvehicle->m_damage_bits, 8);
vehicle_json[has_collision_key] = !has_collision;
vehicle_json[is_visible_key] = is_visible;
vehicle_json[is_invincible_key] = is_invincible;
vehicle_json[wheel_color_key] = wheel_color;
bool has_collision = ENTITY::GET_ENTITY_COLLISION_DISABLED(vehicle);
bool is_visible = ENTITY::IS_ENTITY_VISIBLE(vehicle);
CVehicle* cvehicle = (CVehicle*)g_pointers->m_handle_to_ptr(vehicle);
bool is_invincible = misc::has_bit_set(&(int&)cvehicle->m_damage_bits, 8);
vehicle_json[has_collision_key] = !has_collision;
vehicle_json[is_visible_key] = is_visible;
vehicle_json[is_invincible_key] = is_invincible;
vehicle_json[wheel_color_key] = wheel_color;
std::map<int, bool> vehicle_extras;
for (int i = 0; i <= 20; i++)
@ -444,8 +466,7 @@ namespace big
vehicle_json[vehicle_livery_key] = VEHICLE::GET_VEHICLE_LIVERY(vehicle);
}
if (VEHICLE::IS_THIS_MODEL_A_CAR(ENTITY::GET_ENTITY_MODEL(vehicle)) ||
VEHICLE::IS_THIS_MODEL_A_BIKE(ENTITY::GET_ENTITY_MODEL(vehicle)))
if (VEHICLE::IS_THIS_MODEL_A_CAR(ENTITY::GET_ENTITY_MODEL(vehicle)) || VEHICLE::IS_THIS_MODEL_A_BIKE(ENTITY::GET_ENTITY_MODEL(vehicle)))
{
vehicle_json[wheel_type_key] = VEHICLE::GET_VEHICLE_WHEEL_TYPE(vehicle);
@ -468,7 +489,7 @@ namespace big
if (VEHICLE::GET_VEHICLE_MOD(vehicle, i) != -1)
{
int vehicle_mod[2] = { VEHICLE::GET_VEHICLE_MOD(vehicle, i), VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, i) };
int vehicle_mod[2] = {VEHICLE::GET_VEHICLE_MOD(vehicle, i), VEHICLE::GET_VEHICLE_MOD_VARIATION(vehicle, i)};
vehicle_json[mod_names[i]] = vehicle_mod;
}
}
@ -479,7 +500,7 @@ namespace big
int neon_color[3]{};
VEHICLE::GET_VEHICLE_NEON_COLOUR(vehicle, &neon_color[0], &neon_color[1], &neon_color[2]);
vehicle_json[neon_color_key] = neon_color;
vehicle_json[neon_color_key] = neon_color;
vehicle_json[neon_lights_key] = neon_lights;
if (VEHICLE::IS_VEHICLE_A_CONVERTIBLE(vehicle, 0))
@ -489,9 +510,9 @@ namespace big
VEHICLE::GET_VEHICLE_EXTRA_COLOUR_5(vehicle, &interior_color);
VEHICLE::GET_VEHICLE_EXTRA_COLOUR_6(vehicle, &dashboard_color);
vehicle_json[interior_color_key] = interior_color;
vehicle_json[dash_color_key] = dashboard_color;
vehicle_json[dash_color_key] = dashboard_color;
vehicle_json[clan_logo_key] = GRAPHICS::DOES_VEHICLE_HAVE_CREW_EMBLEM(vehicle, 0);
vehicle_json[clan_logo_key] = GRAPHICS::DOES_VEHICLE_HAVE_CREW_EMBLEM(vehicle, 0);
vehicle_json[headlight_color_key] = VEHICLE::GET_VEHICLE_XENON_LIGHT_COLOR_INDEX(vehicle);
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "natives.hpp"
#include "model_attachment.hpp"
#include "natives.hpp"
namespace big
{
@ -14,32 +14,32 @@ namespace big
static Vehicle load_vehicle(std::string_view file_name);
private:
static constexpr auto model_attachment_key = "model_attachment";
static constexpr auto model_attachment_key = "model_attachment";
static constexpr auto model_attachments_key = "model_attachments";
static constexpr auto vehicle_attachments_key = "vehicle_attachments";
static constexpr auto is_invincible_key = "is_invincible";
static constexpr auto is_visible_key = "is_visible";
static constexpr auto has_collision_key = "has_collision";
static constexpr auto is_invincible_key = "is_invincible";
static constexpr auto is_visible_key = "is_visible";
static constexpr auto has_collision_key = "has_collision";
static constexpr auto vehicle_model_hash_key = "vehicle_model_hash";
static constexpr auto vehicle_key = "vehicle";
static constexpr auto tow_key = "tow";
static constexpr auto tow_key = "tow";
static constexpr auto trailer_key = "trailer";
static constexpr auto radio_station_key = "radio_station";
static constexpr auto plate_text_key = "plate_text";
static constexpr auto plate_text_key = "plate_text";
static constexpr auto plate_text_index_key = "plate_text_index";
static constexpr auto vehicle_extras_key = "vehicle_extras";
static constexpr auto vehicle_livery_key = "vehicle_livery";
static constexpr auto wheel_type_key = "wheel_type";
static constexpr auto wheel_color_key = "wheel_color";
static constexpr auto wheel_type_key = "wheel_type";
static constexpr auto wheel_color_key = "wheel_color";
static constexpr auto tire_smoke_color_key = "tire_smoke_color";
static constexpr auto convertable_state_key = "convertable_state";
@ -47,18 +47,18 @@ namespace big
static constexpr auto vehicle_window_tint_key = "vehicle_window_tint";
static constexpr auto neon_lights_key = "neon_lights";
static constexpr auto neon_color_key = "neon_color";
static constexpr auto neon_color_key = "neon_color";
static constexpr auto primary_color_key = "primary_color";
static constexpr auto primary_color_key = "primary_color";
static constexpr auto custom_primary_color_key = "custom_primary_color";
static constexpr auto secondary_color_key = "secondary_color";
static constexpr auto secondary_color_key = "secondary_color";
static constexpr auto custom_secondary_color_key = "custom_secondary_color";
static constexpr auto pearlescent_color_key = "pearlescent_color";
static constexpr auto headlight_color_key = "headlight_color";
static constexpr auto interior_color_key = "interior_color";
static constexpr auto dash_color_key = "dash_color";
static constexpr auto headlight_color_key = "headlight_color";
static constexpr auto interior_color_key = "interior_color";
static constexpr auto dash_color_key = "dash_color";
static constexpr auto clan_logo_key = "clan_logo";