CheatMenuSA/src/vehicle.cpp

1560 lines
60 KiB
C++
Raw Normal View History

2021-10-25 10:03:27 -04:00
#include "pch.h"
2021-09-20 08:41:40 -04:00
#include "vehicle.h"
#include "menu.h"
2022-06-29 19:56:53 -04:00
#include "widget.h"
2021-09-20 08:41:40 -04:00
#include "util.h"
2022-07-17 18:07:30 -04:00
#include "teleport.h"
2021-10-25 10:03:27 -04:00
#include "filehandler.h"
2021-10-24 18:08:00 -04:00
#include <CPopulation.h>
2021-10-25 10:03:27 -04:00
#include <CDamageManager.h>
2021-08-09 14:26:49 -04:00
2022-01-04 17:33:07 -05:00
#ifdef GTASA
#include "tHandlingData.h"
2022-01-04 17:33:07 -05:00
#include "neon.h"
#include "paint.h"
#endif
void Vehicle::Init()
2020-12-02 16:19:16 -05:00
{
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
FileHandler::FetchHandlingID(m_VehicleIDE);
Neon::InjectHooks();
Paint::InjectHooks();
2021-08-09 14:26:49 -04:00
#endif
2022-01-04 17:33:07 -05:00
2022-01-07 03:18:00 -05:00
FileHandler::FetchColorData(m_CarcolsColorData);
2022-06-24 13:32:43 -04:00
// Get config data
2022-06-26 08:08:55 -04:00
Spawner::m_bSpawnInAir = gConfig.Get("Features.SpawnAircraftInAir", true);
Spawner::m_bSpawnInside = gConfig.Get("Features.SpawnInsideVehicle", true);
2022-06-24 13:32:43 -04:00
Events::processScriptsEvent += []
2022-01-07 03:18:00 -05:00
{
uint timer = CTimer::m_snTimeInMilliseconds;
CPlayerPed* pPlayer = FindPlayerPed();
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
if (pPlayer && Util::IsInVehicle())
2022-01-07 03:18:00 -05:00
{
int hveh = CPools::GetVehicleRef(pVeh);
2022-07-16 14:29:32 -04:00
float speed = pVeh->m_vecMoveSpeed.Magnitude() * 50.0f;
if (m_bAutoUnflip && pVeh->IsUpsideDown() && speed < 2.0f)
{
Util::UnFlipVehicle(pVeh);
}
2022-01-07 03:18:00 -05:00
2022-07-16 14:29:32 -04:00
if (unflipVeh.Pressed())
2022-01-07 03:18:00 -05:00
{
2022-07-16 14:29:32 -04:00
Util::UnFlipVehicle(pVeh);
2022-01-07 03:18:00 -05:00
}
if (fixVeh.Pressed())
{
Util::FixVehicle(pVeh);
2022-03-18 03:23:43 -04:00
SetHelpMessage("Vehicle fixed");
2022-01-07 03:18:00 -05:00
}
if (vehEngine.Pressed())
{
bool state = BY_GAME(!pVeh->m_nVehicleFlags.bEngineBroken, true, true) || pVeh->m_nVehicleFlags.bEngineOn;
if (state)
{
2022-03-18 03:23:43 -04:00
SetHelpMessage("Vehicle engine off");
2022-01-07 03:18:00 -05:00
}
else
{
2022-03-18 03:23:43 -04:00
SetHelpMessage("Vehicle engine on");
2022-01-07 03:18:00 -05:00
}
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bEngineBroken = state;
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bEngineOn = !state;
}
2021-02-02 02:59:01 -05:00
2022-01-07 03:18:00 -05:00
if (vehInstantStart.Pressed())
{
Util::SetCarForwardSpeed(pVeh, 40.0f);
2022-01-07 03:18:00 -05:00
}
2021-02-02 02:59:01 -05:00
2022-01-07 03:18:00 -05:00
if (vehInstantStop.Pressed())
{
Util::SetCarForwardSpeed(pVeh, 0.0f);
2022-01-07 03:18:00 -05:00
}
2021-02-24 16:54:45 -05:00
2022-01-07 03:18:00 -05:00
if (m_bNoDamage)
{
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
pVeh->m_nPhysicalFlags.bBulletProof = true;
pVeh->m_nPhysicalFlags.bExplosionProof = true;
pVeh->m_nPhysicalFlags.bFireProof = true;
pVeh->m_nPhysicalFlags.bCollisionProof = true;
pVeh->m_nPhysicalFlags.bMeleeProof = true;
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bCanBeDamaged = true;
2021-08-09 14:26:49 -04:00
#elif GTAVC
2022-01-07 03:18:00 -05:00
pVeh->m_nFlags.bBulletProof = true;
pVeh->m_nFlags.bExplosionProof = true;
pVeh->m_nFlags.bFireProof = true;
pVeh->m_nFlags.bCollisionProof = true;
pVeh->m_nFlags.bMeleeProof = true;
2022-02-20 12:00:35 -05:00
pVeh->m_nFlags.bImmuneToNonPlayerDamage = true;
#else
pVeh->m_nFlags.bBulletProof = true;
pVeh->m_nFlags.bExplosionProof = true;
pVeh->m_nFlags.bFireProof = true;
pVeh->m_nFlags.bCollisionProof = true;
pVeh->m_nFlags.bMeleeProof = true;
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
2022-01-07 03:18:00 -05:00
Command<Commands::SET_CAR_HEAVY>(hveh, m_bVehHeavy);
Command<Commands::SET_CAR_WATERTIGHT>(hveh, m_bVehWatertight);
2020-12-02 16:19:16 -05:00
2022-01-07 03:18:00 -05:00
if (m_bLockSpeed)
{
Util::SetCarForwardSpeed(pVeh, m_fLockSpeed);
2022-01-07 03:18:00 -05:00
}
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-06-26 08:08:55 -04:00
if (UnlimitedNitro::m_bEnabled && pVeh->m_nVehicleSubClass == VEHICLE_AUTOMOBILE)
2022-01-07 03:18:00 -05:00
{
patch::Set<BYTE>(0x969165, 0, true); // All cars have nitro
patch::Set<BYTE>(0x96918B, 0, true); // All taxis have nitro
if (KeyPressed(VK_LBUTTON))
{
2022-06-26 08:08:55 -04:00
if (!UnlimitedNitro::m_bCompAdded)
2022-01-07 03:18:00 -05:00
{
AddComponent("1010", false);
2022-06-26 08:08:55 -04:00
UnlimitedNitro::m_bCompAdded = true;
2022-01-07 03:18:00 -05:00
}
}
else
{
2022-06-26 08:08:55 -04:00
if (UnlimitedNitro::m_bCompAdded)
2022-01-07 03:18:00 -05:00
{
RemoveComponent("1010", false);
2022-06-26 08:08:55 -04:00
UnlimitedNitro::m_bCompAdded = false;
2022-01-07 03:18:00 -05:00
}
}
}
2022-06-26 08:08:55 -04:00
if (NeonData::m_bRainbowEffect && timer - NeonData::m_nRainbowTimer > 50)
2022-01-07 03:18:00 -05:00
{
int red, green, blue;
Util::RainbowValues(red, green, blue, 0.25);
Neon::Install(pVeh, red, green, blue);
2022-06-26 08:08:55 -04:00
NeonData::m_nRainbowTimer = timer;
2022-01-07 03:18:00 -05:00
}
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
2020-12-02 16:19:16 -05:00
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
// Traffic neons
2022-06-26 08:08:55 -04:00
if (NeonData::m_bApplyOnTraffic && timer - NeonData::m_bTrafficTimer > 1000)
2022-01-07 03:18:00 -05:00
{
for (CVehicle* veh : CPools::ms_pVehiclePool)
{
int chance = 0;
if (veh->m_nVehicleClass == CLASS_NORMAL) // Normal
{
chance = Random(1, 20);
}
if (veh->m_nVehicleClass == CLASS_RICHFAMILY) // Rich family
{
chance = Random(1, 4);
}
if (veh->m_nVehicleClass == CLASS_EXECUTIVE) // Executive
{
chance = Random(1, 3);
}
if (chance == 1 && !Neon::IsInstalled(veh) && veh->m_pDriver != pPlayer)
{
Neon::Install(veh, Random(0, 255), Random(0, 255), Random(0, 255));
}
}
2022-06-26 08:08:55 -04:00
NeonData::m_bTrafficTimer = timer;
2022-01-07 03:18:00 -05:00
}
if (m_bBikeFly && pVeh && pVeh->IsDriver(pPlayer))
{
if (pVeh->m_nVehicleSubClass == VEHICLE_BIKE || pVeh->m_nVehicleSubClass == VEHICLE_BMX)
{
if (sqrt(pVeh->m_vecMoveSpeed.x * pVeh->m_vecMoveSpeed.x
+ pVeh->m_vecMoveSpeed.y * pVeh->m_vecMoveSpeed.y
+ pVeh->m_vecMoveSpeed.z * pVeh->m_vecMoveSpeed.z
) > 0.0
&& CTimer::ms_fTimeStep > 0.0)
{
pVeh->FlyingControl(3, -9999.9902f, -9999.9902f, -9999.9902f, -9999.9902f);
}
}
}
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
};
2020-12-02 16:19:16 -05:00
}
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2021-10-25 10:03:27 -04:00
void Vehicle::AddComponent(const std::string& component, const bool display_message)
2020-12-02 16:19:16 -05:00
{
2022-01-07 03:18:00 -05:00
try
{
CPlayerPed* player = FindPlayerPed();
int icomp = std::stoi(component);
int hveh = CPools::GetVehicleRef(player->m_pVehicle);
CStreaming::RequestModel(icomp, eStreamingFlags::PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(true);
player->m_pVehicle->AddVehicleUpgrade(icomp);
CStreaming::SetModelIsDeletable(icomp);
if (display_message)
{
2022-03-18 03:23:43 -04:00
SetHelpMessage("Component added");
}
2022-01-07 03:18:00 -05:00
}
catch (...)
{
2022-06-15 06:45:43 -04:00
Log::Print<eLogLevel::Warn>("Failed to add component to vehicle {}", component);
2022-01-07 03:18:00 -05:00
}
2020-12-02 16:19:16 -05:00
}
2021-10-25 10:03:27 -04:00
void Vehicle::RemoveComponent(const std::string& component, const bool display_message)
2020-12-02 16:19:16 -05:00
{
2022-01-07 03:18:00 -05:00
try
{
CPlayerPed* player = FindPlayerPed();
int icomp = std::stoi(component);
int hveh = CPools::GetVehicleRef(player->m_pVehicle);
player->m_pVehicle->RemoveVehicleUpgrade(icomp);
if (display_message)
{
2022-03-18 03:23:43 -04:00
SetHelpMessage("Component removed");
2022-01-07 03:18:00 -05:00
}
}
catch (...)
{
2022-06-15 06:45:43 -04:00
Log::Print<eLogLevel::Warn>("Failed to remove component from vehicle {}", component);
2022-01-07 03:18:00 -05:00
}
2020-12-02 16:19:16 -05:00
}
2021-08-09 14:26:49 -04:00
// hardcoded for now
2020-12-02 16:19:16 -05:00
int Vehicle::GetRandomTrainIdForModel(int model)
{
2022-01-07 03:18:00 -05:00
static int train_ids[] =
{
8, 9, // model 449
0, 3, 6, 10, 12, 13, // model 537
1, 5, 15 // model 538
};
int _start = 0, _end = 0;
switch (model)
{
case 449:
_start = 0;
_end = 1;
break;
case 537:
_start = 2;
_end = 7;
break;
case 538:
_start = 8;
_end = 10;
break;
default:
2022-03-18 03:23:43 -04:00
SetHelpMessage("Invalid train model");
2022-01-07 03:18:00 -05:00
return -1;
}
int id = Random(_start, _end);
return train_ids[id];
2020-12-02 16:19:16 -05:00
}
2021-10-07 08:30:44 -04:00
#elif GTAVC
void WarpPlayerIntoVehicle(CVehicle *pVeh, int seatId)
{
2022-01-07 03:18:00 -05:00
CPlayerPed *pPlayer = FindPlayerPed();
pPlayer->m_bInVehicle = true;
pPlayer->m_pVehicle = pVeh;
pPlayer->RegisterReference((CEntity**)&pPlayer->m_pVehicle);
pPlayer->m_pObjectiveVehicle = pVeh;
pPlayer->RegisterReference((CEntity**)&pPlayer->m_pObjectiveVehicle);
pPlayer->m_ePedState = ePedState::PEDSTATE_DRIVING;
pPlayer->m_nObjective = OBJECTIVE_NO_OBJ;
2022-01-07 03:18:00 -05:00
patch::Set<BYTE>(0x7838CD, 1); // player got in car flag
Call<0x41D370>(pVeh); // CCarCtrl::RegisterVehicleOfInterest
if (pVeh->m_passengers[seatId])
{
pVeh->m_passengers[seatId]->Remove();
}
pVeh->m_passengers[seatId] = pPlayer;
pVeh->RegisterReference((CEntity**)&pVeh->m_passengers[seatId]);
// Set player position
CWorld::Remove(pPlayer);
pPlayer->m_placement.pos.x = pVeh->m_placement.pos.x;
pPlayer->m_placement.pos.y = pVeh->m_placement.pos.y;
pPlayer->m_placement.pos.z = pVeh->m_placement.pos.z;
CWorld::Add(pPlayer);
pPlayer->m_nFlags.bUseCollision = false;
pPlayer->m_nPedFlags.bIsStanding = false;
pPlayer->m_nPedFlags.b03 = 0;
RpAnimBlendClumpSetBlendDeltas(pPlayer->m_pRwClump, 16, -1000);
pPlayer->AddInCarAnims(pVeh, false);
CallMethod<0x4FF6A0>(pPlayer); // char __thiscall RemoveWeaponWhenEnteringVehicle(CPed*)
2021-10-07 08:30:44 -04:00
}
2022-01-07 03:18:00 -05:00
#endif
2020-12-02 16:19:16 -05:00
#ifdef GTASA
2022-06-29 19:56:53 -04:00
void Vehicle::SpawnVehicle(std::string& smodel)
2022-01-07 03:18:00 -05:00
#else
2022-06-29 19:56:53 -04:00
void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::string& smodel)
#endif
2020-12-02 16:19:16 -05:00
{
2022-01-07 03:18:00 -05:00
CPlayerPed* player = FindPlayerPed();
int hplayer = CPools::GetPedRef(player);
int imodel = std::stoi(smodel);
CVehicle* veh = nullptr;
int interior = BY_GAME(player->m_nAreaCode, player->m_nAreaCode, NULL);
2021-02-24 16:54:45 -05:00
2022-01-07 03:18:00 -05:00
CVector pos = player->GetPosition();
float speed = 0;
2020-12-02 16:19:16 -05:00
2022-01-07 03:18:00 -05:00
bool bInVehicle = Command<Commands::IS_CHAR_IN_ANY_CAR>(hplayer);
2022-06-26 08:08:55 -04:00
if (bInVehicle && Spawner::m_bSpawnInside)
2022-01-07 03:18:00 -05:00
{
CVehicle* pveh = player->m_pVehicle;
int hveh = CPools::GetVehicleRef(pveh);
pos = pveh->GetPosition();
2020-12-02 16:19:16 -05:00
2022-01-07 03:18:00 -05:00
Command<Commands::GET_CAR_SPEED>(hveh, &speed);
Command<Commands::WARP_CHAR_FROM_CAR_TO_COORD>(hplayer, pos.x, pos.y, pos.z);
2020-12-02 16:19:16 -05:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
if (pveh->m_nVehicleClass == VEHICLE_TRAIN)
{
Command<Commands::DELETE_MISSION_TRAIN>(hveh);
}
else
{
2022-01-07 03:18:00 -05:00
Command<Commands::DELETE_CAR>(hveh);
}
#else
Command<Commands::DELETE_CAR>(hveh);
2021-10-23 16:57:34 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
if (interior == 0)
{
2022-06-26 08:08:55 -04:00
if (Spawner::m_bSpawnInAir && (CModelInfo::IsHeliModel(imodel) || CModelInfo::IsPlaneModel(imodel)))
2022-01-07 03:18:00 -05:00
{
pos.z = 400;
}
else
{
pos.z -= 5;
}
}
2021-02-24 16:54:45 -05:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
if (CModelInfo::IsTrainModel(imodel))
{
int train_id = GetRandomTrainIdForModel(imodel);
if (train_id == -1) // Unknown train id
return;
int hveh = 0;
// Loading all train related models
CStreaming::RequestModel(590, PRIORITY_REQUEST);
CStreaming::RequestModel(538, PRIORITY_REQUEST);
CStreaming::RequestModel(570, PRIORITY_REQUEST);
CStreaming::RequestModel(569, PRIORITY_REQUEST);
CStreaming::RequestModel(537, PRIORITY_REQUEST);
CStreaming::RequestModel(449, PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
CTrain* train = nullptr;
CTrain* carraige = nullptr;
int track = Random(0, 1);
int node = CTrain::FindClosestTrackNode(pos, &track);
CTrain::CreateMissionTrain(pos, (Random(0, 1)) == 1 ? true : false, train_id, &train, &carraige, node,
track, false);
veh = (CVehicle*)train;
hveh = CPools::GetVehicleRef(veh);
if (veh->m_pDriver)
Command<Commands::DELETE_CHAR>(CPools::GetPedRef(veh->m_pDriver));
2022-06-26 08:08:55 -04:00
if (Spawner::m_bSpawnInside)
2022-01-07 03:18:00 -05:00
{
Command<Commands::WARP_CHAR_INTO_CAR>(hplayer, hveh);
Util::SetCarForwardSpeed(veh, speed);
2022-01-07 03:18:00 -05:00
}
Command<Commands::MARK_MISSION_TRAIN_AS_NO_LONGER_NEEDED>(hveh);
Command<Commands::MARK_CAR_AS_NO_LONGER_NEEDED>(hveh);
CStreaming::SetModelIsDeletable(590);
CStreaming::SetModelIsDeletable(538);
CStreaming::SetModelIsDeletable(570);
CStreaming::SetModelIsDeletable(569);
CStreaming::SetModelIsDeletable(537);
CStreaming::SetModelIsDeletable(449);
}
else
{
#endif
2022-01-07 03:18:00 -05:00
CStreaming::RequestModel(imodel, PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
#ifdef GTASA
2022-06-26 08:08:55 -04:00
if (Spawner::m_nLicenseText[0] != '\0')
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
Command<Commands::CUSTOM_PLATE_FOR_NEXT_CAR>(imodel, Spawner::m_nLicenseText);
2022-01-07 03:18:00 -05:00
}
#endif
2022-01-07 03:18:00 -05:00
int hveh = 0;
2022-06-26 08:08:55 -04:00
if (Spawner::m_bSpawnInside)
2022-01-07 03:18:00 -05:00
{
Command<Commands::CREATE_CAR>(imodel, pos.x, pos.y, pos.z + 4.0f, &hveh);
veh = CPools::GetVehicle(hveh);
#ifdef GTASA
2022-01-07 03:18:00 -05:00
veh->SetHeading(player->GetHeading());
#elif GTAVC
2022-01-07 03:18:00 -05:00
float x,y,z;
player->m_placement.GetOrientation(x, y, z);
veh->m_placement.SetOrientation(x, y, z);
#else
float x,y,z;
player->GetOrientation(x, y, z);
veh->SetOrientation(x, y, z);
#endif
2022-01-07 03:18:00 -05:00
Command<Commands::WARP_CHAR_INTO_CAR>(hplayer, hveh);
Util::SetCarForwardSpeed(veh, speed);
2022-01-07 03:18:00 -05:00
}
else
{
#ifdef GTASA
2022-01-07 03:18:00 -05:00
player->TransformFromObjectSpace(pos, CVector(0, 10, 0));
#else
player->TransformFromObjectSpace(pos);
#endif
Command<Commands::CREATE_CAR>(imodel, pos.x, pos.y, pos.z + 3.0f, &hveh);
veh = CPools::GetVehicle(hveh);
#ifdef GTASA
2022-01-07 03:18:00 -05:00
veh->SetHeading(player->GetHeading() + 55.0f);
#elif GTAVC
2022-01-07 03:18:00 -05:00
float x,y,z;
player->m_placement.GetOrientation(x, y, z);
veh->m_placement.SetOrientation(x, y, z);
#else
float x,y,z;
player->GetOrientation(x, y, z);
veh->SetOrientation(x, y, z);
#endif
2022-01-07 03:18:00 -05:00
}
2022-05-16 14:42:00 -04:00
veh->m_eDoorLock = DOORLOCK_UNLOCKED;
#ifndef GTA3
BY_GAME(veh->m_nAreaCode, veh->m_nAreaCode, NULL) = interior;
#endif
2022-01-07 03:18:00 -05:00
Command<Commands::MARK_CAR_AS_NO_LONGER_NEEDED>(CPools::GetVehicleRef(veh));
CStreaming::SetModelIsDeletable(imodel);
#ifdef GTASA
2022-01-07 03:18:00 -05:00
}
veh->m_nVehicleFlags.bHasBeenOwnedByPlayer = true;
#else
Command<Commands::RESTORE_CAMERA_JUMPCUT>();
2021-08-09 14:26:49 -04:00
#endif
2020-12-02 16:19:16 -05:00
}
std::string Vehicle::GetNameFromModel(int model)
{
2021-10-23 16:57:34 -04:00
#ifdef GTA3
2022-01-07 03:18:00 -05:00
return std::to_string(model);
#else
2022-01-07 03:18:00 -05:00
return (const char*)CModelInfo::GetModelInfo(model) + 0x32;
#endif
2020-12-02 16:19:16 -05:00
}
2021-10-25 10:03:27 -04:00
int Vehicle::GetModelFromName(const char* name)
{
2022-01-07 03:18:00 -05:00
int model = 0;
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo((char*)name, &model);
if (model > 0 && model < 1000000 && GetNameFromModel(model) != "")
{
return model;
}
else
{
return 0;
}
}
2022-07-17 18:07:30 -04:00
static void StartAutoDrive(CVehicle *pVeh, const char *buf = nullptr)
{
int hVeh = CPools::GetVehicleRef(pVeh);
CVector pos;
if (buf == nullptr)
{
2022-07-17 18:09:08 -04:00
#ifdef GTASA
2022-07-17 18:07:30 -04:00
tRadarTrace targetBlip = CRadar::ms_RadarTrace[LOWORD(FrontEndMenuManager.m_nTargetBlipIndex)];
pos = targetBlip.m_vecPos;
if (targetBlip.m_nRadarSprite != RADAR_SPRITE_WAYPOINT)
{
SetHelpMessage(TEXT("Teleport.TargetBlipText"));
return;
}
#else
return;
#endif
}
else
{
if (sscanf(buf, "%f,%f,%f", &pos.x, &pos.y, &pos.z) != 3)
{
int dim;
sscanf(buf, "%d,%f,%f,%f", &dim, &pos.x, &pos.y, &pos.z);
}
}
int model = pVeh->m_nModelIndex;
if (CModelInfo::IsBoatModel(model))
{
Command<Commands::BOAT_GOTO_COORDS>(hVeh, pos.x, pos.y, pos.z);
}
else if (CModelInfo::IsPlaneModel(model))
{
CVector p = pVeh->GetPosition();
p.z = 300.0f;
#ifdef GTASA
pVeh->SetPosn(p);
#elif GTAVC
pVeh->SetPosition(p);
#else
pVeh->SetPos(p);
#endif
Command<Commands::PLANE_GOTO_COORDS>(hVeh, pos.x, pos.y, 300.0f, 30, 200);
}
else if (CModelInfo::IsHeliModel(model))
{
CVector p = pVeh->GetPosition();
p.z = 300.0f;
#ifdef GTASA
pVeh->SetPosn(p);
#elif GTAVC
pVeh->SetPosition(p);
#else
pVeh->SetPos(p);
#endif
Command<Commands::HELI_GOTO_COORDS>(hVeh, pos.x, pos.y, 300.0f, 30, 200);
}
#ifdef GTASA
else if (CModelInfo::IsTrainModel(model))
{
return;
}
#endif
else
{
Command<Commands::CAR_GOTO_COORDINATES>(hVeh, pos.x, pos.y, pos.z);
}
}
2022-01-20 02:04:45 -05:00
void Vehicle::ShowPage()
2020-12-02 16:19:16 -05:00
{
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
CPlayerPed* pPlayer = FindPlayerPed();
int hplayer = CPools::GetPedRef(pPlayer);
2022-07-17 18:07:30 -04:00
bool bPlayerInCar = Command<Commands::IS_CHAR_IN_ANY_CAR>(hplayer);
2022-01-07 03:18:00 -05:00
CVehicle *pVeh = pPlayer->m_pVehicle;
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.BlowCar"), ImVec2(Widget::CalcSize(3))))
2022-01-07 03:18:00 -05:00
{
for (CVehicle *pVeh : CPools::ms_pVehiclePool)
{
BY_GAME(pVeh->BlowUpCar(pPlayer, false), pVeh->BlowUpCar(pPlayer), pVeh->BlowUpCar(pPlayer));
}
}
ImGui::SameLine();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.FixCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInVehicle())
2022-01-07 03:18:00 -05:00
{
Util::FixVehicle(pVeh);
2022-01-07 03:18:00 -05:00
}
ImGui::SameLine();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.FlipCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInVehicle())
2022-01-07 03:18:00 -05:00
{
2022-07-16 14:29:32 -04:00
Util::UnFlipVehicle(pVeh);
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
2022-07-16 14:29:32 -04:00
2022-01-07 03:18:00 -05:00
if (ImGui::BeginTabBar("Vehicle", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll))
2022-07-16 14:29:32 -04:00
{
2022-01-07 03:18:00 -05:00
CVehicle* pVeh = pPlayer->m_pVehicle;
bool is_driver = pVeh && (pPlayer->m_pVehicle->m_pDriver == pPlayer);
ImGui::Spacing();
if (ImGui::BeginTabItem(TEXT("Window.CheckboxTab")))
2022-01-07 03:18:00 -05:00
{
ImGui::Spacing();
ImGui::BeginChild("CheckboxesChild");
ImGui::Columns(2, 0, false);
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.AimDrive"), 0x969179);
Widget::CheckboxAddr(TEXT("Vehicle.AllNitro"), 0x969165);
#endif
2022-07-16 14:29:32 -04:00
Widget::Checkbox(TEXT("Vehicle.AutoUnflip"), &m_bAutoUnflip);
2021-10-30 16:30:28 -04:00
#ifndef GTA3
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.AggroDriver"), BY_GAME(0x96914F,0xA10B47, NULL));
Widget::CheckboxAddr(TEXT("Vehicle.AllTaxiNitro"), BY_GAME(0x96918B,0xA10B3A, NULL));
Widget::Checkbox(TEXT("Vehicle.BikeFly"), &m_bBikeFly);
Widget::CheckboxAddr(TEXT("Vehicle.BoatFly"), BY_GAME(0x969153, 0xA10B11, NULL));
#endif
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.CarFly"), BY_GAME(0x969160, 0xA10B28, 0x95CD75));
Widget::Checkbox(TEXT("Vehicle.CarHeavy"), &m_bVehHeavy);
if (Widget::Checkbox(TEXT("Vehicle.DmgProof"), &m_bNoDamage, TEXT("Vehicle.DmgProofTip")))
2022-01-07 03:18:00 -05:00
{
if (pVeh && !m_bNoDamage)
{
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
pVeh->m_nPhysicalFlags.bBulletProof = false;
pVeh->m_nPhysicalFlags.bExplosionProof = false;
pVeh->m_nPhysicalFlags.bFireProof = false;
pVeh->m_nPhysicalFlags.bCollisionProof = false;
pVeh->m_nPhysicalFlags.bMeleeProof = false;
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bCanBeDamaged = false;
2021-08-09 14:26:49 -04:00
#elif GTAVC
2022-01-07 03:18:00 -05:00
pVeh->m_nFlags.bBulletProof = false;
pVeh->m_nFlags.bExplosionProof = false;
pVeh->m_nFlags.bFireProof = false;
pVeh->m_nFlags.bCollisionProof = false;
pVeh->m_nFlags.bMeleeProof = false;
2022-02-20 12:00:35 -05:00
pVeh->m_nFlags.bImmuneToNonPlayerDamage = false;
2022-01-07 03:18:00 -05:00
#else
pVeh->m_nFlags.bBulletProof = false;
pVeh->m_nFlags.bExplosionProof = false;
pVeh->m_nFlags.bFireProof = false;
pVeh->m_nFlags.bCollisionProof = false;
pVeh->m_nFlags.bMeleeProof = false;
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
}
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddrRaw(TEXT("Vehicle.LockTrainCam"), 0x52A52F, 1, "\xAB", "\x06");
Widget::CheckboxAddr(TEXT("Vehicle.LessTraffic"), 0x96917A);
if (Widget::Checkbox(TEXT("Vehicle.NoDerail"), &m_bNoDerail))
2022-06-24 13:32:43 -04:00
{
if (m_bNoDerail)
{
patch::Set<uint32_t>(0x6F8C2A, 0x00441F0F, true); // nop dword ptr [eax+eax*1+00h]
patch::Set<uint8_t>(0x6F8C2E, 0x00, true);
patch::Set<uint16_t>(0x6F8C41, 0xE990, true); // jmp near
}
else
{
patch::SetRaw(0x6F8C2A, (void*)"\x8A\x46\x36\xA8\xF8\xD8\x8E", 7);
}
}
2022-07-01 04:06:34 -04:00
// if (Widget::Checkbox(TEXT("Vehicle.NoColl"), &m_bDisableColDetection))
2022-01-07 03:18:00 -05:00
// {
// if (m_bDisableColDetection)
// {
// patch::SetUChar(0x56717B, 0x7D);
// patch::SetUChar(0x56725D, 0x7D);
// }
// // update flags for exising vehicles
// for (auto veh : CPools::ms_pVehiclePool)
// {
// if (veh == FindPlayerVehicle(-1, false))
// {
// continue;
// }
// if (m_bDisableColDetection)
// {
// CCollisionData* pColData = veh->GetColModel()->m_pColData;
// // pColData->m_nNumSpheres = 0;
// pColData->m_nNumBoxes = 0;
// pColData->m_nNumTriangles = 0;
// }
// }
// }
#endif
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
2022-02-19 13:32:25 -05:00
#ifndef GTA3
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.StayOnBike"), &m_bDontFallBike))
2022-02-19 13:32:25 -05:00
{
if (m_bDontFallBike)
{
#ifdef GTASA
2022-02-19 13:32:25 -05:00
pPlayer->m_nPedFlags.CantBeKnockedOffBike = 1;
#elif GTAVC
patch::SetRaw(0x614C4E, (void*)"\x8B\x8D\x00\x00\x00\x00", 6);
patch::SetRaw(0x614CC5, (void*)"\x8B\x85\x00\x00\x00\x00", 6);
#endif
2022-02-19 13:32:25 -05:00
}
else
{
#ifdef GTASA
pPlayer->m_nPedFlags.CantBeKnockedOffBike = 2;
#elif GTAVC
patch::SetRaw(0x614C4E, (void*)"\x8B\x8D\xA8\x01\x00\x00", 6);
patch::SetRaw(0x614CC5, (void*)"\x8B\x85\xAC\x01\x00\x00", 6);
#endif
}
}
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.DriveWater"), BY_GAME(0x969152, 0xA10B81, NULL));
#endif
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.FloatOnHit"), 0x969166);
#endif
#ifndef GTA3
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.GreenLights"), BY_GAME(0x96914E, 0xA10ADC, NULL));
#endif
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.PerfectHandling"), 0x96914C);
Widget::CheckboxAddr(TEXT("Vehicle.TankMode"), 0x969164);
2022-07-01 04:06:34 -04:00
Widget::Checkbox(TEXT("Vehicle.InfNitro"), &UnlimitedNitro::m_bEnabled, TEXT("Vehicle.InfNitroTip"));
if (Widget::Checkbox(TEXT("Vehicle.FlipNoBurn"), &m_bVehFlipNoBurn, TEXT("Vehicle.FlipNoBurnTip")))
2022-06-24 13:32:43 -04:00
{
// MixSets (Link2012)
if (m_bVehFlipNoBurn)
{
// Patch ped vehicles damage when flipped
patch::SetRaw(0x6A776B, (void*)"\xD8\xDD\x00\x00\x00\x00", 6); // fstp st0, nop 4
// Patch player vehicle damage when flipped
patch::SetRaw(0x570E7F, (void*)"\xD8\xDD\x00\x00\x00\x00", 6); // fstp st0, nop 4
}
else
{
// restore patches
patch::SetRaw(0x6A776B, (void*)"\xD9\x9E\xC0\x04\x00\x00", 6);
patch::SetRaw(0x570E7F, (void*)"\xD9\x99\xC0\x04\x00\x00", 6); // fstp dword ptr [ecx+4C0h]
}
}
#elif GTA3
2022-07-01 04:06:34 -04:00
Widget::CheckboxAddr(TEXT("Vehicle.PerfectHandling"), 0x95CD66);
#endif
2022-07-01 04:06:34 -04:00
Widget::Checkbox(TEXT("Vehicle.Watertight"), &m_bVehWatertight, TEXT("Vehicle.WatertightTip"));
Widget::CheckboxAddr(TEXT("Vehicle.OnlyWheels"), BY_GAME(0x96914B, 0xA10B70, 0x95CD78));
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
2020-12-02 16:19:16 -05:00
2022-01-07 03:18:00 -05:00
if (is_driver)
{
ImGui::NewLine();
ImGui::TextWrapped(TEXT("Vehicle.ForCurVeh"));
2022-01-07 03:18:00 -05:00
ImGui::Columns(2, 0, false);
2022-01-07 03:18:00 -05:00
bool state = false;
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
state = pVeh->m_nVehicleFlags.bAlwaysSkidMarks;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.SkidMarks"), &state, nullptr))
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bAlwaysSkidMarks = state;
2021-08-09 14:26:49 -04:00
#endif
state = BY_GAME(pVeh->m_nPhysicalFlags.bBulletProof, pVeh->m_nFlags.bBulletProof, pVeh->m_nFlags.bBulletProof);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.BulletProof"), &state, nullptr, m_bNoDamage))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_nPhysicalFlags.bBulletProof, pVeh->m_nFlags.bBulletProof, pVeh->m_nFlags.bBulletProof) = state;
2022-01-07 03:18:00 -05:00
}
2021-10-25 10:03:27 -04:00
state = BY_GAME(pVeh->m_nPhysicalFlags.bCollisionProof, pVeh->m_nFlags.bCollisionProof, pVeh->m_nFlags.bCollisionProof);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.ColProof"), &state, nullptr, m_bNoDamage))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_nPhysicalFlags.bCollisionProof, pVeh->m_nFlags.bCollisionProof, pVeh->m_nFlags.bCollisionProof) = state;
2022-01-07 03:18:00 -05:00
}
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
state = pVeh->m_nVehicleFlags.bDisableParticles;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.NoParticles"), &state, nullptr))
2022-01-07 03:18:00 -05:00
{
pVeh->m_nVehicleFlags.bDisableParticles = state;
}
state = pVeh->m_nVehicleFlags.bVehicleCanBeTargetted;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.DriverTarget"), &state))
2022-01-07 03:18:00 -05:00
{
pVeh->m_nVehicleFlags.bVehicleCanBeTargetted = state;
}
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
state = BY_GAME(!pVeh->m_nVehicleFlags.bEngineBroken, true, true) || pVeh->m_nVehicleFlags.bEngineOn;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.EngineOn"), &state, nullptr, !is_driver))
2022-01-07 03:18:00 -05:00
{
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bEngineBroken = !state;
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bEngineOn = state;
}
state = BY_GAME(pVeh->m_nPhysicalFlags.bExplosionProof, pVeh->m_nFlags.bExplosionProof, pVeh->m_nFlags.bExplosionProof);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.ExplosionProof"), &state, nullptr, m_bNoDamage))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_nPhysicalFlags.bExplosionProof, pVeh->m_nFlags.bExplosionProof, pVeh->m_nFlags.bExplosionProof) = state;
2022-01-07 03:18:00 -05:00
}
state = BY_GAME(pVeh->m_nPhysicalFlags.bFireProof, pVeh->m_nFlags.bFireProof, pVeh->m_nFlags.bFireProof);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.FireProof"), &state, nullptr, m_bNoDamage))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_nPhysicalFlags.bFireProof, pVeh->m_nFlags.bFireProof, pVeh->m_nFlags.bFireProof) = state;
2022-01-07 03:18:00 -05:00
}
ImGui::NextColumn();
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
state = pVeh->m_nVehicleFlags.bVehicleCanBeTargettedByHS;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.HSTarget"), &state, TEXT("Vehicle.HSTargetTip")))
2022-01-07 03:18:00 -05:00
{
pVeh->m_nVehicleFlags.bVehicleCanBeTargettedByHS = state;
}
2021-08-09 14:26:49 -04:00
#endif
state = !BY_GAME(pVeh->m_bIsVisible, pVeh->m_nFlags.bIsVisible, pVeh->m_nFlags.bIsVisible);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.InvisCar"), &state, nullptr, !is_driver))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_bIsVisible, pVeh->m_nFlags.bIsVisible, pVeh->m_nFlags.bIsVisible) = !state;
2022-01-07 03:18:00 -05:00
}
state = BY_GAME(!pVeh->ms_forceVehicleLightsOff, pVeh->m_nVehicleFlags.bLightsOn, pVeh->m_nVehicleFlags.bLightsOn);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.LightsOn"), &state, nullptr, !is_driver))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->ms_forceVehicleLightsOff, pVeh->m_nVehicleFlags.bLightsOn, pVeh->m_nVehicleFlags.bLightsOn) = state;
}
2022-05-16 14:42:00 -04:00
state = pVeh->m_eDoorLock == DOORLOCK_LOCKED_PLAYER_INSIDE;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.LockDoor"), &state, nullptr, !is_driver))
2022-01-07 03:18:00 -05:00
{
2022-05-16 14:42:00 -04:00
pVeh->m_eDoorLock = state ? DOORLOCK_LOCKED_PLAYER_INSIDE : DOORLOCK_UNLOCKED;
2022-01-07 03:18:00 -05:00
}
state = BY_GAME(pVeh->m_nPhysicalFlags.bMeleeProof, pVeh->m_nFlags.bMeleeProof, pVeh->m_nFlags.bMeleeProof);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.MeleeProof"), &state, nullptr, m_bNoDamage))
2022-01-07 03:18:00 -05:00
{
BY_GAME(pVeh->m_nPhysicalFlags.bMeleeProof, pVeh->m_nFlags.bMeleeProof, pVeh->m_nFlags.bMeleeProof) = state;
2022-01-07 03:18:00 -05:00
}
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-01-07 03:18:00 -05:00
state = pVeh->m_nVehicleFlags.bPetrolTankIsWeakPoint;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.PentrolTank"), &state, TEXT("Vehicle.PetrolTankTip")))
2022-01-07 03:18:00 -05:00
{
pVeh->m_nVehicleFlags.bPetrolTankIsWeakPoint = state;
}
state = pVeh->m_nVehicleFlags.bSirenOrAlarm;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.Siren"), &state))
2022-01-07 03:18:00 -05:00
{
pVeh->m_nVehicleFlags.bSirenOrAlarm = state;
}
state = pVeh->m_nVehicleFlags.bTakeLessDamage;
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.LessDmg"), &state, nullptr))
{
2022-01-07 03:18:00 -05:00
pVeh->m_nVehicleFlags.bTakeLessDamage = state;
}
2021-08-09 14:26:49 -04:00
#endif
2021-02-24 16:54:45 -05:00
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Window.MenusTab")))
2022-01-07 03:18:00 -05:00
{
ImGui::Spacing();
ImGui::BeginChild("MenusChild");
2021-10-23 16:57:34 -04:00
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::EditAddr<float>(TEXT("Vehicle.DensityMul"), 0x8A5B20, 0, 1, 10);
2021-10-23 16:57:34 -04:00
#endif
2022-07-17 18:07:30 -04:00
if (ImGui::CollapsingHeader(TEXT(bPlayerInCar ? "Vehicle.SwitchSeats" : "Vehicle.EnterNearVeh")))
2022-01-07 03:18:00 -05:00
{
2022-07-17 18:07:30 -04:00
CVehicle* pTargetVeh = bPlayerInCar ? pVeh : Util::GetClosestVehicle();
2020-12-02 16:19:16 -05:00
2022-07-17 18:07:30 -04:00
if (pTargetVeh)
2022-01-07 03:18:00 -05:00
{
2022-07-17 18:07:30 -04:00
int seats = pTargetVeh->m_nMaxPassengers;
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
ImGui::Columns(2, 0, false);
2020-12-02 16:19:16 -05:00
2022-07-17 18:07:30 -04:00
ImGui::Text(GetNameFromModel(pTargetVeh->m_nModelIndex).c_str());
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
ImGui::Text(TEXT("Vehicle.TotalSeats"), (seats + 1));
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
2020-12-02 16:19:16 -05:00
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.Driver"), ImVec2(Widget::CalcSize(2))))
2022-01-07 03:18:00 -05:00
{
2022-07-17 18:07:30 -04:00
Command<Commands::WARP_CHAR_INTO_CAR>(hplayer, pTargetVeh);
2022-01-07 03:18:00 -05:00
}
2020-12-02 16:19:16 -05:00
2021-10-23 16:57:34 -04:00
#ifndef GTA3
2022-01-07 03:18:00 -05:00
for (int i = 0; i < seats; ++i)
{
if (i % 2 != 1)
{
ImGui::SameLine();
}
2022-07-17 18:07:30 -04:00
if (ImGui::Button(std::format("{} {}", TEXT("Vehicle.Passenger"), i+1).c_str(),
2022-06-29 19:56:53 -04:00
ImVec2(Widget::CalcSize(2))))
2022-01-07 03:18:00 -05:00
{
2021-10-07 08:30:44 -04:00
#ifdef GTASA
2022-07-17 18:07:30 -04:00
Command<Commands::WARP_CHAR_INTO_CAR_AS_PASSENGER>(hplayer, pTargetVeh, i);
#elif GTAVC
2022-07-17 18:07:30 -04:00
WarpPlayerIntoVehicle(pTargetVeh, i);
#endif
2022-01-07 03:18:00 -05:00
}
}
2021-10-23 16:57:34 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
else
{
2022-07-17 18:07:30 -04:00
ImGui::Spacing();
Widget::TextCentered(TEXT("Vehicle.NoNearVeh"));
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
ImGui::Separator();
}
if (ImGui::CollapsingHeader(TEXT("Vehicle.RemoveVehRadius")))
2022-01-07 03:18:00 -05:00
{
ImGui::InputInt(TEXT("Vehicle.Radius"), &m_nVehRemoveRadius);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.RemoveVeh"), Widget::CalcSize(1)))
2022-01-07 03:18:00 -05:00
{
CPlayerPed* player = FindPlayerPed();
for (CVehicle* pVeh : CPools::ms_pVehiclePool)
{
if (DistanceBetweenPoints(pVeh->GetPosition(), player->GetPosition()) < m_nVehRemoveRadius
&& player->m_pVehicle != pVeh)
{
Command<Commands::DELETE_CAR>(CPools::GetVehicleRef(pVeh));
}
}
}
ImGui::Spacing();
ImGui::Separator();
}
2021-10-23 16:57:34 -04:00
#ifndef GTA3
2022-07-01 04:27:11 -04:00
std::vector<Widget::BindInfo> color
2022-01-07 03:18:00 -05:00
{
2022-07-01 04:27:11 -04:00
{TEXT("Vehicle.Black"), BY_GAME(0x969151, 0xA10B82, NULL)},
{TEXT("Vehicle.Pink"), BY_GAME(0x969150, 0xA10B26, NULL)}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.TrafficColor"), color);
2021-08-17 01:46:41 -04:00
#endif
2022-07-01 04:27:11 -04:00
#ifdef GTASA
std::vector<Widget::BindInfo> type
{
{TEXT("Vehicle.Cheap"), 0x96915E}, {TEXT("Vehicle.Country"), 0x96917B},
{TEXT("Vehicle.Fast"), 0x96915F}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.TrafficType"), type);
2021-10-23 16:57:34 -04:00
#endif
2022-01-07 03:18:00 -05:00
if (pPlayer && pPlayer->m_pVehicle)
{
CVehicle* pVeh = pPlayer->m_pVehicle;
int hVeh = CPools::GetVehicleRef(pVeh);
2020-12-02 16:19:16 -05:00
2021-08-09 14:26:49 -04:00
#ifdef GTASA
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.DirtLvl"), (int)pVeh + 0x4B0, 0, 7.5, 15);
if (pVeh->m_nVehicleClass == VEHICLE_AUTOMOBILE && ImGui::CollapsingHeader(TEXT("Vehicle.Doors")))
2022-01-07 03:18:00 -05:00
{
ImGui::Columns(2, 0, false);
ImGui::RadioButton(TEXT("Vehicle.Damage"), &m_nDoorMenuButton, 0);
ImGui::RadioButton(TEXT("Vehicle.Fix"), &m_nDoorMenuButton, 1);
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
ImGui::RadioButton(TEXT("Vehicle.Open"), &m_nDoorMenuButton, 2);
ImGui::RadioButton(TEXT("Vehicle.Pop"), &m_nDoorMenuButton, 3);
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
ImGui::Spacing();
int seats = pVeh->m_nMaxPassengers + 1; // passenger + driver
int doors = seats == 4 ? 6 : 4;
int hveh = CPools::GetVehicleRef(pVeh);
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.All"), ImVec2(Widget::CalcSize())))
2022-01-07 03:18:00 -05:00
{
for (int i = 0; i < doors; ++i)
{
switch (m_nDoorMenuButton)
{
case 0:
Command<Commands::DAMAGE_CAR_DOOR>(hveh, i);
break;
case 1:
Command<Commands::FIX_CAR_DOOR>(hveh, i);
break;
case 2:
Command<Commands::OPEN_CAR_DOOR>(hveh, i);
break;
case 3:
Command<Commands::POP_CAR_DOOR>(hveh, i);
break;
default:
break;
}
}
}
for (int i = 0; i != doors; ++i)
{
2022-06-29 19:56:53 -04:00
if (ImGui::Button(m_DoorNames[i].c_str(), ImVec2(Widget::CalcSize(2))))
2022-01-07 03:18:00 -05:00
{
switch (m_nDoorMenuButton)
{
case 0:
Command<Commands::DAMAGE_CAR_DOOR>(hveh, i);
break;
case 1:
Command<Commands::FIX_CAR_DOOR>(hveh, i);
break;
case 2:
Command<Commands::OPEN_CAR_DOOR>(hveh, i);
break;
case 3:
Command<Commands::POP_CAR_DOOR>(hveh, i);
break;
default:
break;
}
}
if (i % 2 != 1)
{
ImGui::SameLine();
}
}
ImGui::Spacing();
ImGui::Separator();
}
2022-07-12 23:51:21 -04:00
#endif
Widget::EditAddr<float>(TEXT("Menu.VehHealth"), (int)&pVeh->m_fHealth, 0, 0, 1000);
if (ImGui::CollapsingHeader(TEXT("Vehicle.SetSpeed")))
2022-01-07 03:18:00 -05:00
{
2022-07-01 04:06:34 -04:00
Widget::Checkbox(TEXT("Vehicle.LockSpeed"), &m_bLockSpeed);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
ImGui::InputFloat(TEXT("Vehicle.Set"), &m_fLockSpeed);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
m_fLockSpeed = m_fLockSpeed > 100 ? 100 : m_fLockSpeed;
m_fLockSpeed = m_fLockSpeed < 0 ? 0 : m_fLockSpeed;
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.Set"), ImVec2(Widget::CalcSize(2))))
2022-01-07 03:18:00 -05:00
{
Util::SetCarForwardSpeed(pVeh, m_fLockSpeed);
2022-01-07 03:18:00 -05:00
}
ImGui::SameLine();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.InstantStop"), ImVec2(Widget::CalcSize(2))))
2022-01-07 03:18:00 -05:00
{
Util::SetCarForwardSpeed(pVeh, 0.0f);
2022-01-07 03:18:00 -05:00
}
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Window.SpawnTab")))
2022-01-07 03:18:00 -05:00
{
ImGui::Spacing();
ImGui::Columns(2, 0, false);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.SpawnInside"), &Spawner::m_bSpawnInside))
2022-06-24 13:32:43 -04:00
{
2022-06-26 08:08:55 -04:00
gConfig.Set("Features.SpawnInsideVehicle", Spawner::m_bSpawnInside);
2022-06-24 13:32:43 -04:00
}
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
2022-07-01 04:06:34 -04:00
if( Widget::Checkbox(TEXT("Vehicle.SpawnInAir"), &Spawner::m_bSpawnInAir))
2022-06-24 13:32:43 -04:00
{
2022-06-26 08:08:55 -04:00
gConfig.Set("Features.SpawnAircraftInAir", Spawner::m_bSpawnInAir);
2022-06-24 13:32:43 -04:00
}
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
ImGui::Spacing();
2022-04-17 07:46:28 -04:00
2022-04-17 07:52:18 -04:00
int width = ImGui::GetWindowContentRegionWidth() - ImGui::GetStyle().ItemSpacing.x;
2022-04-17 07:46:28 -04:00
#ifdef GTASA
2022-04-17 07:52:18 -04:00
width /= 2;
2022-04-17 07:46:28 -04:00
#endif
2022-04-17 07:52:18 -04:00
ImGui::SetNextItemWidth(width);
2022-04-17 07:46:28 -04:00
static char smodel[8];
if (ImGui::InputTextWithHint("##SpawnID", TEXT("Vehicle.IDSpawnText"), smodel, 8, ImGuiInputTextFlags_EnterReturnsTrue))
{
try{
int model = std::stoi(smodel);
if (CModelInfo::IsCarModel(model))
{
std::string str = std::string(smodel);
2022-04-17 07:52:18 -04:00
#ifdef GTASA
2022-04-17 07:46:28 -04:00
SpawnVehicle(str);
2022-04-17 07:52:18 -04:00
#else
2022-07-01 04:27:11 -04:00
std::string temp = "";
SpawnVehicle(temp, temp, str);
2022-04-17 07:52:18 -04:00
#endif
2022-04-17 07:46:28 -04:00
}
else
{
SetHelpMessage(TEXT("Vehicle.InvalidID"));
}
}
catch(...)
{
SetHelpMessage(TEXT("Vehicle.InvalidID"));
}
}
#ifdef GTASA
2022-04-17 07:46:28 -04:00
ImGui::SameLine();
ImGui::SetNextItemWidth(width);
2022-06-26 08:08:55 -04:00
ImGui::InputTextWithHint("##LicenseText", TEXT("Vehicle.PlateText"), Spawner::m_nLicenseText, 9);
2022-01-07 03:18:00 -05:00
Widget::ImageList(Spawner::m_VehData, SpawnVehicle,
[](std::string& str)
2022-01-07 03:18:00 -05:00
{
return GetNameFromModel(std::stoi(str));
});
#else
2022-06-29 19:56:53 -04:00
Widget::DataList(Spawner::m_VehData, SpawnVehicle, nullptr);
#endif
2022-01-07 03:18:00 -05:00
ImGui::EndTabItem();
}
2022-07-17 18:07:30 -04:00
if (pPlayer->m_pVehicle && bPlayerInCar)
2022-01-07 03:18:00 -05:00
{
CVehicle* veh = FindPlayerPed()->m_pVehicle;
int hveh = CPools::GetVehicleRef(veh);
2022-07-17 18:07:30 -04:00
if (ImGui::BeginTabItem(TEXT("Vehicle.AutoDrive")))
{
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.AutoDriveStop"), Widget::CalcSize(1)))
{
}
ImGui::Spacing();
if (ImGui::BeginTabBar("PassTabaBar"))
{
if (ImGui::BeginTabItem(TEXT("Teleport.Coordinates")))
{
static char buf[INPUT_BUFFER_SIZE];
ImGui::Spacing();
ImGui::TextWrapped(TEXT("Vehicle.AutoDriveInfo"));
ImGui::Spacing();
ImGui::InputTextWithHint(TEXT("Teleport.Coordinates"), "x, y, z", buf, IM_ARRAYSIZE(buf));
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.AutoDriveCoord"), Widget::CalcSize(BY_GAME(2,1,1))))
{
StartAutoDrive(pVeh, buf);
}
#ifdef GTASA
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.AutoDriveMarker"), Widget::CalcSize(2)))
{
StartAutoDrive(pVeh);
}
#endif
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Teleport.Location")))
{
ImGui::Spacing();
Widget::DataList(Teleport::m_locData,
[](std::string& rootkey, std::string& bLocName, std::string& loc)
{
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
StartAutoDrive(pVeh, loc.c_str());
}, nullptr);
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.Color")))
2022-01-07 03:18:00 -05:00
{
#ifdef GTASA
2022-06-26 08:08:55 -04:00
Paint::GenerateNodeList(veh, PaintData::m_vecNames, PaintData::m_Selected);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.ResetColor"), ImVec2(Widget::CalcSize())))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
Paint::ResetNodeColor(veh, PaintData::m_Selected);
2022-03-18 03:23:43 -04:00
SetHelpMessage(TEXT("Vehicle.ResetColorMSG"));
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
2022-07-01 04:06:34 -04:00
Widget::ListBox(TEXT("Vehicle.Component"), PaintData::m_vecNames, PaintData::m_Selected);
2022-01-07 03:18:00 -05:00
2022-06-26 08:08:55 -04:00
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), PaintData::m_fColorPicker))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
uchar r = PaintData::m_fColorPicker[0] * 255;
uchar g = PaintData::m_fColorPicker[1] * 255;
uchar b = PaintData::m_fColorPicker[2] * 255;
Paint::SetNodeColor(veh, PaintData::m_Selected, { r, g, b, 255 }, PaintData::m_bMatFilter);
2022-01-07 03:18:00 -05:00
}
#endif
2021-08-12 23:51:00 -04:00
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
2021-08-12 23:51:00 -04:00
#ifdef GTASA
2022-06-26 08:08:55 -04:00
ImGui::Checkbox(TEXT("Vehicle.MatFilter"), &PaintData::m_bMatFilter);
ImGui::RadioButton(TEXT("Vehicle.Primary"), &PaintData::m_nRadioButton, 1);
ImGui::RadioButton(TEXT("Vehicle.Secondary"), &PaintData::m_nRadioButton, 2);
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
ImGui::NewLine();
2022-06-26 08:08:55 -04:00
ImGui::RadioButton(TEXT("Vehicle.Tertiary"), &PaintData::m_nRadioButton, 3);
ImGui::RadioButton(TEXT("Vehicle.Quaternary"), &PaintData::m_nRadioButton, 4);
2022-01-07 03:18:00 -05:00
#else
2022-06-26 08:21:28 -04:00
ImGui::RadioButton(TEXT("Vehicle.Primary"), &PaintData::m_nRadioButton, 1);
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
2022-06-26 08:21:28 -04:00
ImGui::RadioButton(TEXT("Vehicle.Secondary"), &PaintData::m_nRadioButton, 2);
2022-01-07 03:18:00 -05:00
#endif
ImGui::Spacing();
ImGui::Columns(1);
ImGui::Text(TEXT("Vehicle.SelectPreset"));
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
int count = (int)m_CarcolsColorData.size();
2022-06-29 19:56:53 -04:00
ImVec2 size = Widget::CalcSize();
2022-01-07 03:18:00 -05:00
int btnsInRow = ImGui::GetWindowContentRegionWidth() / (size.y * 2);
int btnSize = (ImGui::GetWindowContentRegionWidth() - int(ImGuiStyleVar_ItemSpacing) * (btnsInRow -
0.6 * btnsInRow)) / btnsInRow;
ImGui::BeginChild("Colorss");
for (int colorId = 0; colorId < count; ++colorId)
{
2022-07-01 04:06:34 -04:00
if (Widget::ColorBtn(colorId, m_CarcolsColorData[colorId], ImVec2(btnSize, btnSize)))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
*(uint8_replacement*)(int(veh) + BY_GAME(0x433, 0x19F, 0x19B) + PaintData::m_nRadioButton) = colorId;
2022-01-07 03:18:00 -05:00
}
if ((colorId + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
#ifdef GTASA
2022-01-07 03:18:00 -05:00
if (gRenderer != Render_DirectX11)
{
if (ImGui::BeginTabItem(TEXT("Vehicle.NeonsTab")))
2022-01-07 03:18:00 -05:00
{
2022-06-22 07:35:03 -04:00
int model = veh->m_nModelIndex;
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.RemoveNeon"), ImVec2(Widget::CalcSize())))
2022-01-07 03:18:00 -05:00
{
Neon::Remove(veh);
2022-03-18 03:23:43 -04:00
SetHelpMessage(TEXT("Vehicle.RemoveNeonMSG"));
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
bool pulsing = Neon::IsPulsingEnabled(veh);
2022-07-01 04:06:34 -04:00
if (Widget::Checkbox(TEXT("Vehicle.PulsingNeon"), &pulsing))
2022-01-07 03:18:00 -05:00
{
Neon::SetPulsing(veh, pulsing);
}
2022-07-01 04:06:34 -04:00
Widget::Checkbox(TEXT("Vehicle.RainbowNeon"), &NeonData::m_bRainbowEffect, TEXT("Vehicle.RainbowNeonMSG"));
2022-01-07 03:18:00 -05:00
ImGui::NextColumn();
2022-07-01 04:06:34 -04:00
Widget::Checkbox(TEXT("Vehicle.TrafficNeon"), &NeonData::m_bApplyOnTraffic, TEXT("Vehicle.TrafficNeonMSG"));
2022-01-07 03:18:00 -05:00
ImGui::Columns(1);
ImGui::Spacing();
2022-06-26 08:08:55 -04:00
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), NeonData::m_fColorPicker))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
int r = static_cast<int>(NeonData::m_fColorPicker[0] * 255);
int g = static_cast<int>(NeonData::m_fColorPicker[1] * 255);
int b = static_cast<int>(NeonData::m_fColorPicker[2] * 255);
2022-06-22 07:35:03 -04:00
Neon::Install(veh, r, g, b);
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
ImGui::Text(TEXT("Vehicle.SelectPreset"));
2022-01-07 03:18:00 -05:00
int count = (int)m_CarcolsColorData.size();
2022-06-29 19:56:53 -04:00
ImVec2 size = Widget::CalcSize();
2022-01-07 03:18:00 -05:00
int btnsInRow = ImGui::GetWindowContentRegionWidth() / (size.y * 2);
int btnSize = (ImGui::GetWindowContentRegionWidth() - int(ImGuiStyleVar_ItemSpacing) * (btnsInRow -
0.6 * btnsInRow)) / btnsInRow;
ImGui::BeginChild("Neonss");
for (int color_id = 0; color_id < count; ++color_id)
{
2022-06-22 07:35:03 -04:00
auto& color = m_CarcolsColorData[color_id];
2022-07-01 04:06:34 -04:00
if (Widget::ColorBtn(color_id, color, ImVec2(btnSize, btnSize)))
2022-01-07 03:18:00 -05:00
{
2022-06-22 07:35:03 -04:00
int r = static_cast<int>(color[0] * 255);
int g = static_cast<int>(color[1] * 255);
int b = static_cast<int>(color[2] * 255);
Neon::Install(veh, r, g, b);
2022-01-07 03:18:00 -05:00
}
if ((color_id + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.TextureTab")))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
Paint::GenerateNodeList(veh, PaintData::m_vecNames, PaintData::m_Selected);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.ResetTexture"), ImVec2(Widget::CalcSize())))
2022-01-07 03:18:00 -05:00
{
2022-06-26 08:08:55 -04:00
Paint::ResetNodeTexture(veh, PaintData::m_Selected);
2022-03-18 03:23:43 -04:00
SetHelpMessage(TEXT("Vehicle.ResetTextureMSG"));
2022-01-07 03:18:00 -05:00
}
ImGui::Spacing();
2022-07-01 04:06:34 -04:00
Widget::ListBox(TEXT("Vehicle.Component"), PaintData::m_vecNames, PaintData::m_Selected);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-22 07:35:03 -04:00
ImGui::Columns(2, NULL, false);
2022-06-26 08:08:55 -04:00
ImGui::Checkbox(TEXT("Vehicle.MatFilter"), &PaintData::m_bMatFilter);
2022-06-22 07:35:03 -04:00
ImGui::NextColumn();
2022-01-07 03:18:00 -05:00
int maxpjob, curpjob;
Command<Commands::GET_NUM_AVAILABLE_PAINTJOBS>(hveh, &maxpjob);
if (maxpjob > 0)
{
Command<Commands::GET_CURRENT_VEHICLE_PAINTJOB>(hveh, &curpjob);
2022-06-22 07:35:03 -04:00
if (ImGui::ArrowButton("Left", ImGuiDir_Left))
2022-01-07 03:18:00 -05:00
{
2022-06-22 07:35:03 -04:00
curpjob -= 1;
2022-01-07 03:18:00 -05:00
if (curpjob < -1)
2022-06-22 07:35:03 -04:00
{
curpjob = maxpjob - 1;
}
Command<Commands::GIVE_VEHICLE_PAINTJOB>(hveh, curpjob);
}
ImGui::SameLine();
ImGui::Text("%s: %d",TEXT("Vehicle.Paintjob"), curpjob+2);
ImGui::SameLine();
if (ImGui::ArrowButton("Right", ImGuiDir_Right))
{
curpjob += 1;
if (curpjob > maxpjob)
{
curpjob = -1;
}
2022-01-07 03:18:00 -05:00
Command<Commands::GIVE_VEHICLE_PAINTJOB>(hveh, curpjob);
}
ImGui::Spacing();
}
2022-06-22 07:35:03 -04:00
ImGui::Columns(1);
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
Widget::ImageList(Paint::m_TextureData,
2022-01-07 03:18:00 -05:00
[](std::string& str)
{
2022-06-26 08:08:55 -04:00
Paint::SetNodeTexture(FindPlayerPed()->m_pVehicle, PaintData::m_Selected, str,
PaintData::m_bMatFilter);
2022-01-07 03:18:00 -05:00
},
[](std::string& str)
{
return str;
});
ImGui::EndTabItem();
}
}
if (ImGui::BeginTabItem(TEXT("Vehicle.TuneTab")))
2022-01-07 03:18:00 -05:00
{
ImGui::Spacing();
2022-06-29 19:56:53 -04:00
Widget::ImageList(m_TuneData,
2022-01-07 03:18:00 -05:00
[](std::string& str)
{
AddComponent(str);
},
// [](std::string& str)
// {
// RemoveComponent(str);
// },
2022-01-07 03:18:00 -05:00
[](std::string& str)
{
return str;
},
2022-06-29 19:56:53 -04:00
[](std::string& str)
2022-01-07 03:18:00 -05:00
{
2022-06-29 19:56:53 -04:00
return ((bool(*)(int, CVehicle*))0x49B010)(std::stoi(str), FindPlayerPed()->m_pVehicle);
});
2022-01-07 03:18:00 -05:00
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.HandlingTab")))
2022-01-07 03:18:00 -05:00
{
ImGui::Spacing();
// https://github.com/multitheftauto/mtasa-blue/blob/16769b8d1c94e2b9fe6323dcba46d1305f87a190/Client/game_sa/CModelInfoSA.h#L213
CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(pPlayer->m_pVehicle->m_nModelIndex);
int handlingID = patch::Get<WORD>((int)pInfo + 74, false); // CBaseModelInfo + 74 = handlingID
tHandlingData *pHandlingData = reinterpret_cast<tHandlingData*>(0xC2B9DC + (handlingID * 224)); // sizeof(tHandlingData) = 224
2022-01-07 03:18:00 -05:00
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.ResetHandling"), ImVec2(Widget::CalcSize(3))))
2022-01-07 03:18:00 -05:00
{
gHandlingDataMgr.LoadHandlingData();
2022-03-18 03:23:43 -04:00
SetHelpMessage(TEXT("Vehicle.ResetHandlingMSG"));
2022-01-07 03:18:00 -05:00
}
ImGui::SameLine();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.SaveFile"), ImVec2(Widget::CalcSize(3))))
2022-01-07 03:18:00 -05:00
{
FileHandler::GenerateHandlingFile(pHandlingData, m_VehicleIDE);
2022-03-18 03:23:43 -04:00
SetHelpMessage(TEXT("Vehicle.SaveFileMSG"));
2022-01-07 03:18:00 -05:00
}
ImGui::SameLine();
2022-06-29 19:56:53 -04:00
if (ImGui::Button(TEXT("Vehicle.ReadMore"), ImVec2(Widget::CalcSize(3))))
{
2022-01-07 03:18:00 -05:00
ShellExecute(NULL, "open", "https://projectcerbera.com/gta/sa/tutorials/handling", NULL, NULL,
SW_SHOWNORMAL);
}
2022-01-07 03:18:00 -05:00
ImGui::Spacing();
ImGui::BeginChild("HandlingChild");
2022-07-01 04:06:34 -04:00
std::vector<Widget::BindInfo> abs{ {TEXT("Vehicle.On"), 1}, {TEXT("Vehicle.Off"), 0} };
Widget::EditRadioBtnAddr(TEXT("Vehicle.Abs"), (int)&pHandlingData->m_bABS, abs);
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.ADM"), (int)&pHandlingData->m_fSuspensionAntiDiveMultiplier, 0.0f, 0.0f, 1.0f);
Widget::EditAddr<BYTE>(TEXT("Vehicle.AnimGroup"), (int)&pHandlingData->m_nAnimGroup, 0, 0, 20);
Widget::EditAddr(TEXT("Vehicle.BrakeBias"), (int)&pHandlingData->m_fBrakeBias, 0.0f, 0.0f, 1.0f);
// Brake deceleration calculation
float BrakeDeceleration = pHandlingData->m_fBrakeDeceleration * 2500;
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.BrakeDecel"), (int)&pHandlingData->m_fBrakeDeceleration, 0.0f, 0.0f, 20.0f, 2500.0f);
pHandlingData->m_fBrakeDeceleration = BrakeDeceleration / 2500;
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.CemterMassX"), (int)&pHandlingData->m_vecCentreOfMass.x, -10.0f, -10.0f, 10.0f);
Widget::EditAddr(TEXT("Vehicle.CemterMassY"), (int)&pHandlingData->m_vecCentreOfMass.y, -10.0f, -10.0f, 10.0f);
Widget::EditAddr(TEXT("Vehicle.CemterMassZ"), (int)&pHandlingData->m_vecCentreOfMass.z, -10.0f, -10.0f, 10.0f);
// CDM calculations
float factor = (1.0 / pHandlingData->m_fMass);
float fCDM = pHandlingData->m_fCollisionDamageMultiplier / (2000.0f * factor);
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.CDM"), (int)&fCDM, 0.0f, 0.0f, 1.0f, 0.3381f);
pHandlingData->m_fCollisionDamageMultiplier = factor * fCDM * 2000.0f;
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.DampingLvl"), (int)&pHandlingData->m_fSuspensionDampingLevel, -10.0f, -10.0f, 10.0f); // test later
Widget::EditAddr(TEXT("Vehicle.DragMult"), (int)&pHandlingData->m_fDragMult, 0.0f, 0.0f, 30.0f);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
std::vector<Widget::BindInfo> drive_type
2022-01-07 03:18:00 -05:00
{
2022-03-03 00:44:32 -05:00
{TEXT("Vehicle.FrontWheelDrive"), 70},
{TEXT("Vehicle.RearWheelDrive"), 82},
{TEXT("Vehicle.FourWheelDrive"), 52}
2022-01-07 03:18:00 -05:00
};
2022-07-01 04:06:34 -04:00
Widget::EditRadioBtnAddr(TEXT("Vehicle.DriveType"), (int)&pHandlingData->m_transmissionData.m_nDriveType, drive_type);
// Engine acceleration calculation
float fEngineAcceleration = pHandlingData->m_transmissionData.m_fEngineAcceleration * 12500;
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.EngineAccel"), (int)&fEngineAcceleration, 0.0f, 0.0f, 49.0f, 12500.0f);
pHandlingData->m_transmissionData.m_fEngineAcceleration = fEngineAcceleration / 12500;
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.EngineInertia"), (int)&pHandlingData->m_transmissionData.m_fEngineInertia, 0.1f, 0.1f, 400.0f);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
std::vector<Widget::BindInfo> engine_type
2022-03-03 00:44:32 -05:00
{
{TEXT("Vehicle.Petrol"), 80}, {TEXT("Vehicle.Diseal"), 68}, {TEXT("Vehicle.Electric"), 69}
};
2022-07-01 04:06:34 -04:00
Widget::EditRadioBtnAddr(TEXT("Vehicle.EngineType"), (int)&pHandlingData->m_transmissionData.m_nEngineType, engine_type);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
std::vector<Widget::BindInfo> lights
2022-03-03 00:44:32 -05:00
{
{TEXT("Vehicle.Long"), 0}, {TEXT("Vehicle.Small"), 1},
{TEXT("Vehicle.Big"), 2}, {TEXT("Vehicle.Tall"), 3}
};
2022-07-01 04:06:34 -04:00
Widget::EditRadioBtnAddr(TEXT("Vehicle.FrontLights"), (int)&pHandlingData->m_nFrontLights, lights);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.ForceLevel"), (int)&pHandlingData->m_fSuspensionForceLevel, -10.0f, -10.0f, 10.0f); // test later
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditBits(TEXT("Vehicle.HandlingFlags"), (int)&pHandlingData->m_nHandlingFlags, m_HandlingFlagNames);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.HighSpeedDamping"), (int)&pHandlingData->m_fSuspensionDampingLevel, -10.0f, -10.0f, 10.0f); // test later
Widget::EditAddr(TEXT("Vehicle.LowerKimit"), (int)&pHandlingData->m_fSuspensionLowerLimit, -10.0f, -10.0f, 10.0f); // test later
Widget::EditAddr(TEXT("Vehicle.Mass"), (int)&pHandlingData->m_fMass, 1.0f, 1.0f, 50000.0f);
2022-01-07 03:18:00 -05:00
// Max Velocity calculation
int MaxVelocity = pHandlingData->m_transmissionData.m_fMaxGearVelocity / *(float*)0xC2B9BC;
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.MaxVelocity"), (int)&MaxVelocity, 1.0f, 1.0f, 1000.0f);
pHandlingData->m_transmissionData.m_fMaxGearVelocity = MaxVelocity * (*(float*)0xC2B9BC);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditBits(TEXT("Vehicle.ModelFlags"), (int)&pHandlingData->m_nModelFlags, m_ModelFlagNames);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditAddr<int>(TEXT("Vehicle.MonValue"), (int)&pHandlingData->m_nMonetaryValue, 1, 1, 100000);
Widget::EditAddr<BYTE>(TEXT("Vehicle.NumGears"), (int)&pHandlingData->m_transmissionData.m_nNumberOfGears, 1, 1, 10);
Widget::EditAddr<BYTE>(TEXT("Vehicle.PercentSubmerged"), (int)&pHandlingData->m_nPercentSubmerged, 10, 10, 120);
2022-01-07 03:18:00 -05:00
2022-07-01 04:06:34 -04:00
Widget::EditRadioBtnAddr(TEXT("Vehicle.RearLights"), (int)&pHandlingData->m_nRearLights, lights);
2022-07-01 04:06:34 -04:00
Widget::EditAddr(TEXT("Vehicle.SeatOffset"), (int)&pHandlingData->m_fSeatOffsetDistance, 0.0f, 0.0f, 1.0f);
Widget::EditAddr(TEXT("Vehicle.SteeringLock"), (int)&pHandlingData->m_fSteeringLock, 10.0f, 10.0f, 50.0f);
Widget::EditAddr(TEXT("Vehicle.SuspensionBias"), (int)&pHandlingData->m_fSuspensionBiasBetweenFrontAndRear, 0.0f, 0.0f, 1.0f);
Widget::EditAddr(TEXT("Vehicle.TractionBias"), (int)&pHandlingData->m_fTractionBias, 0.0f, 0.0f, 1.0f);
Widget::EditAddr(TEXT("Vehicle.TractionLoss"), (int)&pHandlingData->m_fTractionLoss, 0.0f, 0.0f, 1.0f);
Widget::EditAddr(TEXT("Vehicle.TractionMul"), (int)&pHandlingData->m_fTractionMultiplier, 0.5f, 0.5f, 2.0f);
Widget::EditAddr(TEXT("Vehicle.TurnMass"), (int)&pHandlingData->m_fTurnMass, 20.0f, 20.0f, 1000.0f); // test later
Widget::EditAddr(TEXT("Vehicle.UpperLimit"), (int)&pHandlingData->m_fSuspensionUpperLimit, -1.0f, -1.0f, 1.0f);
2022-01-07 03:18:00 -05:00
ImGui::EndChild();
2021-02-24 16:54:45 -05:00
2022-01-07 03:18:00 -05:00
ImGui::EndTabItem();
}
2021-08-09 14:26:49 -04:00
#endif
2022-01-07 03:18:00 -05:00
}
ImGui::EndTabBar();
}
2021-08-28 01:13:18 -04:00
}