
* Removed summon distance & car only check * Changed raw UI elements to components. * Added selection methods * feat(VehicleController): add translation strings Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
417 lines
14 KiB
C++
417 lines
14 KiB
C++
#include "backend/bool_command.hpp"
|
|
#include "backend/float_command.hpp"
|
|
#include "gta_util.hpp"
|
|
#include "gui.hpp"
|
|
#include "pointers.hpp"
|
|
#include "services/vehicle/vehicle_control_service.hpp"
|
|
#include "util/ped.hpp"
|
|
#include "util/vehicle.hpp"
|
|
#include "views/view.hpp"
|
|
|
|
namespace big
|
|
{
|
|
void render_doors_tab()
|
|
{
|
|
const char* const doornames[MAX_VEHICLE_DOORS]{
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_0"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_1"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_2"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_3"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_4"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_5"_T.data(),
|
|
};
|
|
|
|
const char* const locknames[MAX_VEHICLE_LOCK_STATES]{
|
|
"VIEW_SQUAD_SPAWN_PERSISTENT_VEHICLE_NONE"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_1"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_2"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_3"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_4"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_5"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_6"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_7"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_8"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_9"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOCKNAMES_10"_T.data(),
|
|
};
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::SetNextItemWidth(200);
|
|
if (ImGui::BeginCombo("##alldoorslock", "VEHICLE_CONTROLLER_ALL_DOORS"_T.data()))
|
|
{
|
|
for (int lockindex = 0; lockindex < MAX_VEHICLE_LOCK_STATES; lockindex++)
|
|
{
|
|
components::selectable(locknames[lockindex], false, [lockindex] {
|
|
g_vehicle_control_service.vehicle_operation([lockindex] {
|
|
vehicle::change_vehicle_door_lock_state(g_vehicle_control_service.m_controlled_vehicle.handle, eDoorId::VEH_EXT_DOOR_INVALID_ID, (eVehicleLockState)lockindex);
|
|
});
|
|
});
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
components::button("OPEN_ALL_DOORS"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
vehicle::operate_vehicle_door(g_vehicle_control_service.m_controlled_vehicle.handle, eDoorId::VEH_EXT_DOOR_INVALID_ID, true);
|
|
});
|
|
});
|
|
|
|
ImGui::SameLine();
|
|
|
|
components::button("CLOSE_ALL_DOORS"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
vehicle::operate_vehicle_door(g_vehicle_control_service.m_controlled_vehicle.handle, eDoorId::VEH_EXT_DOOR_INVALID_ID, false);
|
|
});
|
|
});
|
|
|
|
ImGui::EndGroup();
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
for (int i = 0; i < MAX_VEHICLE_DOORS; i++)
|
|
{
|
|
if (!g_vehicle_control_service.m_controlled_vehicle.doors[i].valid)
|
|
continue;
|
|
ImGui::SetNextItemWidth(200);
|
|
ImGui::PushID(i);
|
|
if (ImGui::BeginCombo(doornames[i], locknames[(int)g_vehicle_control_service.m_controlled_vehicle.doors[i].lockstate]))
|
|
{
|
|
for (int lockindex = 0; lockindex < MAX_VEHICLE_LOCK_STATES; lockindex++)
|
|
{
|
|
components::selectable(locknames[lockindex], false, [i, lockindex] {
|
|
g_vehicle_control_service.vehicle_operation([i, lockindex] {
|
|
vehicle::change_vehicle_door_lock_state(g_vehicle_control_service.m_controlled_vehicle.handle, (eDoorId)i, (eVehicleLockState)lockindex);
|
|
});
|
|
});
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
ImGui::SameLine(300);
|
|
|
|
const auto button_label = g_vehicle_control_service.m_controlled_vehicle.doors[i].open ? "CLOSE"_T : "OPEN"_T;
|
|
components::button(button_label, [i] {
|
|
g_vehicle_control_service.vehicle_operation([i] {
|
|
vehicle::operate_vehicle_door(g_vehicle_control_service.m_controlled_vehicle.handle,
|
|
(eDoorId)i,
|
|
!g_vehicle_control_service.m_controlled_vehicle.doors[i].open);
|
|
});
|
|
});
|
|
|
|
ImGui::PopID();
|
|
}
|
|
|
|
ImGui::EndGroup();
|
|
}
|
|
|
|
void render_windows_tab()
|
|
{
|
|
const char* const windownames[4]{
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_0"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_1"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_2"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_DOOR_NAME_3"_T.data(),
|
|
};
|
|
|
|
ImGui::BeginGroup();
|
|
ImGui::Spacing();
|
|
ImGui::SetNextItemWidth(200);
|
|
components::button("VIEW_VEHICLE_CONTROL_ROLL_DOWN_ALL"_T, [] {
|
|
vehicle::operate_vehicle_window(g_vehicle_control_service.m_controlled_vehicle.handle, eWindowId::WINDOW_INVALID_ID, true);
|
|
});
|
|
ImGui::SameLine();
|
|
components::button("VIEW_VEHICLE_CONTROL_ROLL_UP_ALL"_T, [] {
|
|
vehicle::operate_vehicle_window(g_vehicle_control_service.m_controlled_vehicle.handle, eWindowId::WINDOW_INVALID_ID, false);
|
|
});
|
|
ImGui::EndGroup();
|
|
|
|
ImGui::Spacing();
|
|
ImGui::Separator();
|
|
|
|
ImGui::BeginGroup();
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
ImGui::SetNextItemWidth(200);
|
|
ImGui::PushID(i);
|
|
ImGui::Text(windownames[i]);
|
|
ImGui::SameLine(300);
|
|
components::button("VIEW_VEHICLE_CONTROL_ROLL_DOWN"_T, [i] {
|
|
vehicle::operate_vehicle_window(g_vehicle_control_service.m_controlled_vehicle.handle, (eWindowId)i, true);
|
|
});
|
|
ImGui::SameLine();
|
|
components::button("VIEW_VEHICLE_CONTROL_ROLL_UP"_T, [i] {
|
|
vehicle::operate_vehicle_window(g_vehicle_control_service.m_controlled_vehicle.handle, (eWindowId)i, false);
|
|
});
|
|
ImGui::PopID();
|
|
}
|
|
}
|
|
|
|
void render_lights_tab()
|
|
{
|
|
const char* const neonnames[4]{
|
|
"LEFT"_T.data(),
|
|
"RIGHT"_T.data(),
|
|
"FRONT"_T.data(),
|
|
"BACK"_T.data(),
|
|
};
|
|
|
|
components::button("VEHICLE_CONTROLLER_TOGGLE_LIGHTS"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([=] {
|
|
vehicle::operate_vehicle_headlights(g_vehicle_control_service.m_controlled_vehicle.handle,
|
|
!g_vehicle_control_service.m_controlled_vehicle.headlights,
|
|
false);
|
|
});
|
|
});
|
|
|
|
ImGui::SameLine();
|
|
components::button("VEHICLE_CONTROLLER_TOGGLE_HIGH_BEAMS"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([=] {
|
|
vehicle::operate_vehicle_headlights(g_vehicle_control_service.m_controlled_vehicle.handle,
|
|
g_vehicle_control_service.m_controlled_vehicle.headlights,
|
|
!g_vehicle_control_service.m_controlled_vehicle.highbeams);
|
|
});
|
|
});
|
|
|
|
components::button("VEHICLE_CONTROLLER_INTERIOR_LIGHTS_ON"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
VEHICLE::SET_VEHICLE_INTERIORLIGHT(g_vehicle_control_service.m_controlled_vehicle.handle, true);
|
|
});
|
|
});
|
|
|
|
ImGui::SameLine();
|
|
|
|
components::button("VEHICLE_CONTROLLER_INTERIOR_LIGHTS_OFF"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
VEHICLE::SET_VEHICLE_INTERIORLIGHT(g_vehicle_control_service.m_controlled_vehicle.handle, false);
|
|
});
|
|
});
|
|
|
|
ImGui::Text("VEHICLE_CONTROLLER_NEON_LIGHTS"_T.data());
|
|
ImGui::Separator();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (ImGui::Checkbox(neonnames[i], &g_vehicle_control_service.m_controlled_vehicle.neons[i]))
|
|
{
|
|
g_fiber_pool->queue_job([=] {
|
|
g_vehicle_control_service.vehicle_operation([i] {
|
|
vehicle::operate_vehicle_neons(g_vehicle_control_service.m_controlled_vehicle.handle,
|
|
i,
|
|
!g_vehicle_control_service.m_controlled_vehicle.neons[i]);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void render_seats_tab()
|
|
{
|
|
/*
|
|
* Seats start at index -1, compensate accordingly
|
|
*/
|
|
const char* const seatnames[6]{
|
|
"DRIVER"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_PASSENGER"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LEFT_REAR"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_RIGHT_REAR"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_OUTSIDE_LEFT"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_OUTSIDE_RIGHT"_T.data(),
|
|
};
|
|
|
|
static int movespeed = 1;
|
|
|
|
if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_WALKING"_T.data(), movespeed == 1))
|
|
movespeed = 1;
|
|
ImGui::SameLine();
|
|
if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_RUNNING"_T.data(), movespeed == 2))
|
|
movespeed = 2;
|
|
ImGui::SameLine();
|
|
if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_SPRINTING"_T.data(), movespeed == 3))
|
|
movespeed = 3;
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
if (components::button(seatnames[i]))
|
|
{
|
|
g_fiber_pool->queue_job([=] {
|
|
if (g.window.vehicle_control.operation_animation)
|
|
ped::ped_enter_vehicle_animated(self::ped, g_vehicle_control_service.m_controlled_vehicle.handle, (eVehicleSeats)(i - 1), movespeed);
|
|
else
|
|
PED::SET_PED_INTO_VEHICLE(self::ped, g_vehicle_control_service.m_controlled_vehicle.handle, (i - 1));
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void render_misc_tab()
|
|
{
|
|
const char* const convertiblestates[4]{
|
|
"VIEW_TELEPORT_UP"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_LOWERING"_T.data(),
|
|
"VIEW_TELEPORT_DOWN"_T.data(),
|
|
"VIEW_VEHICLE_CONTROL_RAISING"_T.data(),
|
|
};
|
|
|
|
if (g_vehicle_control_service.m_controlled_vehicle.isconvertible)
|
|
{
|
|
components::button(g_vehicle_control_service.m_controlled_vehicle.convertibelstate ? "VIEW_VEHICLE_CONTROL_RAISE"_T : "VIEW_VEHICLE_CONTROL_LOWER"_T, [] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
if (g_vehicle_control_service.m_controlled_vehicle.convertibelstate > 0)
|
|
VEHICLE::RAISE_CONVERTIBLE_ROOF(g_vehicle_control_service.m_controlled_vehicle.handle, false);
|
|
else
|
|
VEHICLE::LOWER_CONVERTIBLE_ROOF(g_vehicle_control_service.m_controlled_vehicle.handle, false);
|
|
});
|
|
});
|
|
|
|
ImGui::SameLine();
|
|
ImGui::Text(std::format("{}: {}",
|
|
"VIEW_VEHICLE_CONTROL_CONVERTIBLE_STATE"_T,
|
|
convertiblestates[g_vehicle_control_service.m_controlled_vehicle.convertibelstate])
|
|
.c_str());
|
|
}
|
|
|
|
if (ImGui::Checkbox(g_vehicle_control_service.m_controlled_vehicle.engine ?
|
|
"VIEW_DEBUG_ANIMATIONS_STOP"_T.data() :
|
|
"SETTINGS_NOTIFY_GTA_THREADS_START"_T.data(),
|
|
&g_vehicle_control_service.m_controlled_vehicle.engine))
|
|
{
|
|
g_fiber_pool->queue_job([=] {
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
VEHICLE::SET_VEHICLE_ENGINE_ON(g_vehicle_control_service.m_controlled_vehicle.handle,
|
|
!g_vehicle_control_service.m_controlled_vehicle.engine,
|
|
true,
|
|
false);
|
|
});
|
|
});
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
ImGui::Text(
|
|
std::format("{}: {}", "VIEW_VEHICLE_CONTROL_ENGINE"_T, g_vehicle_control_service.m_controlled_vehicle.engine ? "VIEW_VEHICLE_CONTROL_ENGINE_RUNNING"_T : "OFF"_T)
|
|
.c_str());
|
|
|
|
components::button(g_vehicle_control_service.m_driver_performing_task ? "CANCEL"_T : "VIEW_VEHICLE_CONTROL_SUMMON"_T, [] {
|
|
if (!g_vehicle_control_service.m_driver_performing_task)
|
|
g_vehicle_control_service.vehicle_operation([] {
|
|
g_vehicle_control_service.summon_vehicle();
|
|
});
|
|
else
|
|
g_vehicle_control_service.m_driver_performing_task = false;
|
|
});
|
|
|
|
if (g_vehicle_control_service.m_driver_performing_task)
|
|
{
|
|
ImGui::SameLine();
|
|
ImGui::Text(std::format("{}: {}", "VIEW_SELF_CUSTOM_TELEPORT_DISTANCE"_T, g_vehicle_control_service.m_distance_to_destination)
|
|
.c_str());
|
|
|
|
|
|
ImGui::Text(std::format("{}: {}", "OUTFIT_TASK"_T, g_vehicle_control_service.m_currentask).c_str());
|
|
}
|
|
}
|
|
|
|
bool_command use_animations("vehcontroluseanims", "VIEW_VEHICLE_CONTROL_USE_ANIMATIONS", "VIEW_VEHICLE_CONTROL_USE_ANIMATIONS_DESC",
|
|
g.window.vehicle_control.operation_animation);
|
|
bool_command render_veh_dist("vehcontrolrendervehdist", "VIEW_VEHICLE_CONTROL_RENDER_DISTANCE_ON_VEHICLE", "VIEW_VEHICLE_CONTROL_RENDER_DISTANCE_ON_VEHICLE_DESC",
|
|
g.window.vehicle_control.render_distance_on_veh);
|
|
bool_command show_vehicle_info("vehcontrolshowvehinfo", "VIEW_VEHICLE_CONTROL_SHOW_VEHICLE_INFO", "VIEW_VEHICLE_CONTROL_SHOW_VEHICLE_INFO_DESC",
|
|
g.window.vehicle_control.show_info);
|
|
|
|
void render_settings_tab()
|
|
{
|
|
components::command_checkbox<"vehcontroluseanims">();
|
|
components::command_checkbox<"vehcontrolrendervehdist">();
|
|
components::command_checkbox<"vehcontrolshowvehinfo">();
|
|
|
|
ImGui::SeparatorText("VIEW_VEHICLE_CONTROL_SELECTION_MODE"_T.data());
|
|
ImGui::RadioButton("VIEW_VEHICLE_CONTROL_SELECTION_MODE_LAST_DRIVEN"_T.data(), (int*)&g_vehicle_control_service.m_selection_mode, (int)eControlledVehSelectionMode::LAST_DRIVEN);
|
|
ImGui::SameLine();
|
|
ImGui::RadioButton("VIEW_VEHICLE_CONTROL_SELECTION_MODE_PERSONAL_VEHICLE"_T.data(),
|
|
(int*)&g_vehicle_control_service.m_selection_mode,
|
|
(int)eControlledVehSelectionMode::PERSONAL);
|
|
ImGui::SameLine();
|
|
ImGui::RadioButton("VIEW_VEHICLE_CONTROL_SELECTION_MODE_CLOSEST"_T.data(), (int*)&g_vehicle_control_service.m_selection_mode, (int)eControlledVehSelectionMode::CLOSEST);
|
|
}
|
|
|
|
void view::vehicle_control()
|
|
{
|
|
if (!g.window.vehicle_control.opened)
|
|
return;
|
|
|
|
ImGui::SetNextWindowPos(ImVec2(500.0f, 10.0f), ImGuiCond_FirstUseEver, ImVec2(0.0f, 0.0f));
|
|
ImGui::SetNextWindowBgAlpha(0.5f);
|
|
if (ImGui::Begin("VEHICLE_CONTROLLER"_T.data(), nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
|
{
|
|
if (g_vehicle_control_service.m_controlled_vehicle_exists)
|
|
{
|
|
ImGui::Text(g_vehicle_control_service.m_controlled_vehicle.model_name);
|
|
if (g.window.vehicle_control.show_info)
|
|
{
|
|
ImGui::Text(std::vformat("VIEW_VEHICLE_CONTROL_HEALTH_N_PASSENGERS"_T,
|
|
std::make_format_args(g_vehicle_control_service.m_controlled_vehicle.ptr->m_health,
|
|
g_vehicle_control_service.m_controlled_vehicle.ptr->m_num_of_passengers,
|
|
g_vehicle_control_service.m_controlled_vehicle.ptr->m_max_passengers))
|
|
.c_str());
|
|
}
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
if (ImGui::BeginTabBar("##vehiclecontroltabbar"))
|
|
{
|
|
if (ImGui::BeginTabItem("VIEW_VEHICLE_CONTROL_DOORS"_T.data()))
|
|
{
|
|
render_doors_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("VIEW_VEHICLE_CONTROL_WINDOWS"_T.data()))
|
|
{
|
|
render_windows_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("VEHICLE_CONTROLLER_NEON_LIGHTS"_T.data()))
|
|
{
|
|
render_lights_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("FUN_VEHICLE_SEAT"_T.data()))
|
|
{
|
|
render_seats_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("SETTINGS_MISC"_T.data()))
|
|
{
|
|
render_misc_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("GUI_TAB_SETTINGS"_T.data()))
|
|
{
|
|
render_settings_tab();
|
|
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
ImGui::EndTabBar();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui::Text("PLAYER_INFO_NO_VEHICLE"_T.data());
|
|
}
|
|
}
|
|
ImGui::End();
|
|
}
|
|
} |