Refactor code more & fix issue with clothes

This commit is contained in:
Grinch_ 2022-08-20 08:56:05 +06:00
parent 5e4b7a9420
commit 6495b36952
48 changed files with 1353 additions and 1142 deletions

View File

@ -127,14 +127,6 @@ void CheatMenu::Init()
ApplyStyle();
Locale::Init(FILE_NAME "/locale/", "English", "English");
// GenHeaderList();
// Init menu parts
Player::Init();
Ped::Init();
Vehicle::Init();
Visual::Init();
WeaponPage::Init();
Overlay::Init();
Events::processScriptsEvent += []()

View File

@ -11,7 +11,7 @@ class AnimationMgr : public ICheat<AnimationMgr>
private:
CPed *m_pTarget = nullptr; // target ped pointer
friend class ICheat;
friend class IFeature;
AnimationMgr();
AnimationMgr(const AnimationMgr&);

126
src/custom/autodrive.cpp Normal file
View File

@ -0,0 +1,126 @@
#include "pch.h"
#include "autodrive.h"
#include "utils/widget.h"
#include "pages/teleport.h"
AutoDriveMgr& AutoDrive = AutoDriveMgr::Get();
void AutoDriveMgr::StartDrive(CVehicle *pVeh, const char *buf)
{
int hVeh = CPools::GetVehicleRef(pVeh);
CVector pos;
if (buf == nullptr)
{
#ifdef GTASA
tRadarTrace targetBlip = CRadar::ms_RadarTrace[LOWORD(FrontEndMenuManager.m_nTargetBlipIndex)];
pos = targetBlip.m_vecPos;
if (targetBlip.m_nRadarSprite != RADAR_SPRITE_WAYPOINT)
{
Util::SetMessage(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);
}
}
void AutoDriveMgr::Draw()
{
CPlayerPed* pPlay = FindPlayerPed();
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());;
int hPlayer = CPools::GetPedRef(pPlay);
int hVeh = CPools::GetVehicleRef(pVeh);
if (ImGui::Button(TEXT("Vehicle.AutoDriveStop"), Widget::CalcSize(1)))
{
Command<Commands::WARP_CHAR_INTO_CAR>(hPlayer, hVeh);
}
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))))
{
StartDrive(pVeh, buf);
}
#ifdef GTASA
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.AutoDriveMarker"), Widget::CalcSize(2)))
{
StartDrive(pVeh);
}
#endif
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Teleport.Location")))
{
ImGui::Spacing();
Widget::DataList(teleportPage.m_locData,
[this, pVeh](std::string& rootkey, std::string& bLocName, std::string& loc)
{
StartDrive(pVeh, loc.c_str());
});
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}

26
src/custom/autodrive.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include "utils/resourcestore.h"
#include "interface/icheat.hpp"
/*
AutoDriveMgr Class
Automatically drives vehicle to marker/ coord
*/
class AutoDriveMgr : public ICheat<AutoDriveMgr>
{
private:
friend class IFeature;
AutoDriveMgr(){};
AutoDriveMgr(const AutoDriveMgr&);
void StartDrive(CVehicle *pVeh, const char *buf = nullptr);
public:
// Draw custom skins handler code
void Draw();
};
extern AutoDriveMgr& AutoDrive;

View File

@ -0,0 +1,76 @@
#include "pch.h"
#include "customskins_sa.h"
#include "utils/widget.h"
CustomSkinsMgr& CustomSkins = CustomSkinsMgr::Get();
CustomSkinsMgr::CustomSkinsMgr()
{
std::string path = GAME_PATH((char*)"modloader/");
if (GetModuleHandle("modloader.asi") && std::filesystem::is_directory(path))
{
path += "CustomSkins/";
if (std::filesystem::is_directory(path))
{
for (auto& p : std::filesystem::recursive_directory_iterator(path))
{
if (p.path().extension() == ".dff")
{
std::string file_name = p.path().stem().string();
if (file_name.size() < 9)
{
m_List.push_back(file_name);
}
else
{
Log::Print<eLogLevel::Error>("Custom Skin longer than 8 characters {}", file_name);
}
}
}
}
else
{
std::filesystem::create_directory(path);
}
m_bInit = true;
}
}
void CustomSkinsMgr::SetSkin(const std::string& name)
{
CStreaming::RequestSpecialChar(1, name.c_str(), PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(true);
FindPlayerPed()->SetModelIndex(291);
CStreaming::SetSpecialCharIsDeletable(291);
}
void CustomSkinsMgr::Draw()
{
if (m_bInit)
{
Widget::Filter(TEXT("Window.Search"), m_Filter, std::format("{}{}", TEXT("Player.TotalSkins"), m_List.size()).c_str());
Widget::Tooltip(TEXT("Player.CustomSkinsDirTip"));
ImGui::Spacing();
ImGui::TextWrapped(TEXT("Player.CustomSkinsTip"));
ImGui::Spacing();
for (std::string name : m_List)
{
if (m_Filter.PassFilter(name.c_str()))
{
if (ImGui::MenuItem(name.c_str()))
{
SetSkin(name);
}
}
}
}
else
{
ImGui::TextWrapped(TEXT("Player.CustomSkinTutorial"));
ImGui::Spacing();
if (ImGui::Button(TEXT("Player.DownloadModloader"), ImVec2(Widget::CalcSize(1))))
{
OPEN_LINK("https://gtaforums.com/topic/669520-mod-loader/");
}
}
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "utils/resourcestore.h"
#include "interface/icheat.hpp"
/*
CustomSkins Class for SA
Adds ability to use skins without replacing
Requires modloader installed
There are certain limitations,
1. Skin names can't be longer than 8 chars
2. Skins can't be removed while the game is running
*/
class CustomSkinsMgr : public ICheat<CustomSkinsMgr>
{
private:
ImGuiTextFilter m_Filter;
std::vector<std::string> m_List;
bool m_bInit;
friend class IFeature;
CustomSkinsMgr();
CustomSkinsMgr(const CustomSkinsMgr&);
// Change player to custom skin
void SetSkin(const std::string& name);
public:
// Draw custom skins handler code
void Draw();
};
extern CustomSkinsMgr& CustomSkins;

View File

@ -17,7 +17,7 @@ private:
CVehicle *m_pLastVeh; // vehicle player was in
int m_nVehSeat; // seat id of player vehicle
friend class ICheat;
friend class IFeature;
CutsceneMgr();
CutsceneMgr(const CutsceneMgr&);

View File

@ -14,7 +14,7 @@ private:
bool m_bHudState; // backup of the prev game hud state
bool m_bRadarState; // backup of the prev game radar state
friend ICheat;
friend class IFeature;
FreecamMgr();
FreecamMgr(const FreecamMgr&);

View File

@ -31,7 +31,7 @@ private:
RwTexture* m_pNeonTexture = nullptr; // pointer to the neon mask texture
VehicleExtendedData<NeonData> m_VehNeon;
friend ICheat;
friend class IFeature;
NeonMgr();
NeonMgr(NeonMgr&);
~NeonMgr();

View File

@ -11,7 +11,7 @@ class ParticleMgr : public ICheat<ParticleMgr>
private:
std::vector<int> m_nList;
friend class ICheat;
friend class IFeature;
ParticleMgr(){};
ParticleMgr(const ParticleMgr&);

View File

@ -12,7 +12,7 @@ private:
std::string m_EnabledCheats[92][2];
DataStore m_pData {"cheats"};
friend ICheat;
friend class IFeature;
RandomCheatsMgr();
RandomCheatsMgr(const RandomCheatsMgr&);

View File

@ -9,7 +9,7 @@ class TopDownCamera : public ICheat<TopDownCamera>
{
private:
friend ICheat;
friend class IFeature;
TopDownCamera();
TopDownCamera(const TopDownCamera&);

255
src/custom/vehmod_sa.cpp Normal file
View File

@ -0,0 +1,255 @@
#include "pch.h"
#include "vehmod_sa.h"
#include "utils/widget.h"
#include "filehandler.h"
static std::vector<std::string> m_HandlingFlagNames = // 32 flags
{
"1G_BOOST", "2G_BOOST", "NPC_ANTI_ROLL", "NPC_NEUTRAL_HANDL", "NO_HANDBRAKE", "STEER_REARWHEELS",
"HB_REARWHEEL_STEER", "ALT_STEER_OPT",
"WHEEL_F_NARROW2", "WHEEL_F_NARROW", "WHEEL_F_WIDE", "WHEEL_F_WIDE2", "WHEEL_R_NARROW2", "WHEEL_R_NARROW",
"WHEEL_R_WIDE", "WHEEL_R_WIDE2",
"HYDRAULIC_GEOM", "HYDRAULIC_INST", "HYDRAULIC_NONE", "NOS_INST", "OFFROAD_ABILITY", "OFFROAD_ABILITY2",
"HALOGEN_LIGHTS", "PROC_REARWHEEL_1ST",
"USE_MAXSP_LIMIT", "LOW_RIDER", "STREET_RACER", "SWINGING_CHASSIS", "Unused 1", "Unused 2", "Unused 3",
"Unused 4"
};
static std::vector<std::string> m_ModelFlagNames = // 32 flags
{
"IS_VAN", "IS_BUS", "IS_LOW", "IS_BIG", "REVERSE_BONNET", "HANGING_BOOT", "TAILGATE_BOOT", "NOSWING_BOOT",
"NO_DOORS", "TANDEM_SEATS",
"SIT_IN_BOAT", "CONVERTIBLE", "NO_EXHAUST", "DOUBLE_EXHAUST", "NO1FPS_LOOK_BEHIND", "FORCE_DOOR_CHECK",
"AXLE_F_NOTILT", "AXLE_F_SOLID", "AXLE_F_MCPHERSON",
"AXLE_F_REVERSE", "AXLE_R_NOTILT", "AXLE_R_SOLID", "AXLE_R_MCPHERSON", "AXLE_R_REVERSE", "IS_BIKE", "IS_HELI",
"IS_PLANE", "IS_BOAT", "BOUNCE_PANELS",
"DOUBLE_RWHEELS", "FORCE_GROUND_CLEARANCE", "IS_HATCHBAC1K"
};
VehModMgr& VehMod = VehModMgr::Get();
VehModMgr::VehModMgr()
{
FileHandler::FetchHandlingID(m_VehicleIDE);
Events::processScriptsEvent += [this]()
{
if (m_Nitro.m_bEnabled && FindPlayerVehicle(-1, false)->m_nVehicleSubClass == VEHICLE_AUTOMOBILE)
{
patch::Set<BYTE>(0x969165, 0, true); // All cars have nitro
patch::Set<BYTE>(0x96918B, 0, true); // All taxis have nitro
if (KeyPressed(VK_LBUTTON))
{
if (!m_Nitro.m_bCompAdded)
{
AddComponent("1010", false);
m_Nitro.m_bCompAdded = true;
}
}
else
{
if (m_Nitro.m_bCompAdded)
{
RemoveComponent("1010", false);
m_Nitro.m_bCompAdded = false;
}
}
}
};
}
void VehModMgr::AddComponent(const std::string& component, const bool display_message)
{
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)
{
Util::SetMessage("Component added");
}
}
catch (...)
{
Log::Print<eLogLevel::Warn>("Failed to add component to vehicle {}", component);
}
}
void VehModMgr::RemoveComponent(const std::string& component, const bool display_message)
{
try
{
CPlayerPed* player = FindPlayerPed();
int icomp = std::stoi(component);
int hveh = CPools::GetVehicleRef(player->m_pVehicle);
player->m_pVehicle->RemoveVehicleUpgrade(icomp);
if (display_message)
{
Util::SetMessage("Component removed");
}
}
catch (...)
{
Log::Print<eLogLevel::Warn>("Failed to remove component from vehicle {}", component);
}
}
void VehModMgr::Draw()
{
if (ImGui::BeginTabItem(TEXT("Vehicle.TuneTab")))
{
ImGui::Spacing();
Widget::ImageList(m_TuneData,
[this](std::string& str)
{
AddComponent(str);
},
// [](std::string& str)
// {
// RemoveComponent(str);
// },
[](std::string& str)
{
return str;
},
[](std::string& str)
{
return ((bool(*)(int, CVehicle*))0x49B010)(std::stoi(str), FindPlayerPed()->m_pVehicle);
});
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.HandlingTab")))
{
ImGui::Spacing();
// https://github.com/multitheftauto/mtasa-blue/blob/16769b8d1c94e2b9fe6323dcba46d1305f87a190/Client/game_sa/CModelInfoSA.h#L213
CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(FindPlayerVehicle(-1, false)->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
if (ImGui::Button(TEXT("Vehicle.ResetHandling"), ImVec2(Widget::CalcSize(3))))
{
gHandlingDataMgr.LoadHandlingData();
Util::SetMessage(TEXT("Vehicle.ResetHandlingMSG"));
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.SaveFile"), ImVec2(Widget::CalcSize(3))))
{
FileHandler::GenerateHandlingFile(pHandlingData, m_VehicleIDE);
Util::SetMessage(TEXT("Vehicle.SaveFileMSG"));
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.ReadMore"), ImVec2(Widget::CalcSize(3))))
{
ShellExecute(NULL, "open", "https://projectcerbera.com/gta/sa/tutorials/handling", NULL, NULL,
SW_SHOWNORMAL);
}
ImGui::Spacing();
ImGui::BeginChild("HandlingChild");
std::vector<Widget::BindInfo> abs{ {TEXT("Vehicle.On"), 1}, {TEXT("Vehicle.Off"), 0} };
Widget::EditRadioBtnAddr(TEXT("Vehicle.Abs"), (int)&pHandlingData->m_bABS, abs);
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;
Widget::EditAddr(TEXT("Vehicle.BrakeDecel"), (int)&pHandlingData->m_fBrakeDeceleration, 0.0f, 0.0f, 20.0f, 2500.0f);
pHandlingData->m_fBrakeDeceleration = BrakeDeceleration / 2500;
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);
Widget::EditAddr(TEXT("Vehicle.CDM"), (int)&fCDM, 0.0f, 0.0f, 1.0f, 0.3381f);
pHandlingData->m_fCollisionDamageMultiplier = factor * fCDM * 2000.0f;
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);
std::vector<Widget::BindInfo> drive_type
{
{TEXT("Vehicle.FrontWheelDrive"), 70},
{TEXT("Vehicle.RearWheelDrive"), 82},
{TEXT("Vehicle.FourWheelDrive"), 52}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.DriveType"), (int)&pHandlingData->m_transmissionData.m_nDriveType, drive_type);
// Engine acceleration calculation
float fEngineAcceleration = pHandlingData->m_transmissionData.m_fEngineAcceleration * 12500;
Widget::EditAddr(TEXT("Vehicle.EngineAccel"), (int)&fEngineAcceleration, 0.0f, 0.0f, 49.0f, 12500.0f);
pHandlingData->m_transmissionData.m_fEngineAcceleration = fEngineAcceleration / 12500;
Widget::EditAddr(TEXT("Vehicle.EngineInertia"), (int)&pHandlingData->m_transmissionData.m_fEngineInertia, 0.1f, 0.1f, 400.0f);
std::vector<Widget::BindInfo> engine_type
{
{TEXT("Vehicle.Petrol"), 80}, {TEXT("Vehicle.Diseal"), 68}, {TEXT("Vehicle.Electric"), 69}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.EngineType"), (int)&pHandlingData->m_transmissionData.m_nEngineType, engine_type);
std::vector<Widget::BindInfo> lights
{
{TEXT("Vehicle.Long"), 0}, {TEXT("Vehicle.Small"), 1},
{TEXT("Vehicle.Big"), 2}, {TEXT("Vehicle.Tall"), 3}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.FrontLights"), (int)&pHandlingData->m_nFrontLights, lights);
Widget::EditAddr(TEXT("Vehicle.ForceLevel"), (int)&pHandlingData->m_fSuspensionForceLevel, -10.0f, -10.0f, 10.0f); // test later
Widget::EditBits(TEXT("Vehicle.HandlingFlags"), (int)&pHandlingData->m_nHandlingFlags, m_HandlingFlagNames);
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);
// Max Velocity calculation
int MaxVelocity = pHandlingData->m_transmissionData.m_fMaxGearVelocity / *(float*)0xC2B9BC;
Widget::EditAddr(TEXT("Vehicle.MaxVelocity"), (int)&MaxVelocity, 1.0f, 1.0f, 1000.0f);
pHandlingData->m_transmissionData.m_fMaxGearVelocity = MaxVelocity * (*(float*)0xC2B9BC);
Widget::EditBits(TEXT("Vehicle.ModelFlags"), (int)&pHandlingData->m_nModelFlags, m_ModelFlagNames);
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);
Widget::EditRadioBtnAddr(TEXT("Vehicle.RearLights"), (int)&pHandlingData->m_nRearLights, lights);
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);
ImGui::EndChild();
ImGui::EndTabItem();
}
}

34
src/custom/vehmod_sa.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "pch.h"
#include "interface/ifeature.hpp"
/*
VehModMgr Class
Handles tunes & handling
*/
class VehModMgr : public IFeature<VehModMgr>
{
private:
ResourceStore m_TuneData { "components", eResourceType::TYPE_IMAGE_TEXT, ImVec2(100, 80) };
std::map<int, std::string> m_VehicleIDE;
// Add/ Remove vehicle mod
void AddComponent(const std::string& component, bool displayMessage = true);
void RemoveComponent(const std::string& component, bool displayMessage = true);
friend class IFeature;
VehModMgr();
VehModMgr(const VehModMgr&);
public:
struct
{
bool m_bEnabled;
bool m_bCompAdded;
} m_Nitro;
// Draw custom skins handler code
void Draw();
};
extern VehModMgr& VehMod;

287
src/custom/vehpaint.cpp Normal file
View File

@ -0,0 +1,287 @@
#include "pch.h"
#include "vehpaint.h"
#include "utils/widget.h"
#include "custom/filehandler.h"
#ifdef GTASA
#include "custom/neon_sa.h"
#include "custom/paint_sa.h"
#endif
VehPaintMgr& VehPaint = VehPaintMgr::Get();
VehPaintMgr::VehPaintMgr()
{
FileHandler::FetchColorData(m_ColorData);
#ifdef GTASA
Paint::InjectHooks();
Events::processScriptsEvent += [this]
{
uint timer = CTimer::m_snTimeInMilliseconds;
CPlayerPed* pPlayer = FindPlayerPed();
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
if (pPlayer && Util::IsInCar())
{
if (m_Neon.m_bRainbowEffect && timer - m_Neon.m_nRainbowTimer > 50)
{
int red, green, blue;
Util::RainbowValues(red, green, blue, 0.25);
Neon.Install(pVeh, red, green, blue);
m_Neon.m_nRainbowTimer = timer;
}
}
// Traffic neons
if (m_Neon.m_bApplyOnTraffic && timer - m_Neon.m_nTrafficTimer > 1000)
{
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));
}
}
m_Neon.m_nTrafficTimer = timer;
}
};
#endif
}
void VehPaintMgr::Draw()
{
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
int hVeh = CPools::GetVehicleRef(pVeh);
if (ImGui::BeginTabItem(TEXT("Vehicle.Color")))
{
#ifdef GTASA
Paint::GenerateNodeList(pVeh, m_Paint.m_vecNames, m_Paint.m_Selected);
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.ResetColor"), ImVec2(Widget::CalcSize())))
{
Paint::ResetNodeColor(pVeh, m_Paint.m_Selected);
Util::SetMessage(TEXT("Vehicle.ResetColorMSG"));
}
ImGui::Spacing();
Widget::ListBox(TEXT("Vehicle.Component"), m_Paint.m_vecNames, m_Paint.m_Selected);
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), m_Paint.m_fColorPicker))
{
uchar r = m_Paint.m_fColorPicker[0] * 255;
uchar g = m_Paint.m_fColorPicker[1] * 255;
uchar b = m_Paint.m_fColorPicker[2] * 255;
Paint::SetNodeColor(pVeh, m_Paint.m_Selected, { r, g, b, 255 }, m_Paint.m_bMatFilter);
}
#endif
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
#ifdef GTASA
ImGui::Checkbox(TEXT("Vehicle.MatFilter"), &m_Paint.m_bMatFilter);
ImGui::RadioButton(TEXT("Vehicle.Primary"), &m_Paint.m_nRadioButton, 1);
ImGui::RadioButton(TEXT("Vehicle.Secondary"), &m_Paint.m_nRadioButton, 2);
ImGui::NextColumn();
ImGui::NewLine();
ImGui::RadioButton(TEXT("Vehicle.Tertiary"), &m_Paint.m_nRadioButton, 3);
ImGui::RadioButton(TEXT("Vehicle.Quaternary"), &m_Paint.m_nRadioButton, 4);
#else
ImGui::RadioButton(TEXT("Vehicle.Primary"), &m_Paint.m_nRadioButton, 1);
ImGui::NextColumn();
ImGui::RadioButton(TEXT("Vehicle.Secondary"), &m_Paint.m_nRadioButton, 2);
#endif
ImGui::Spacing();
ImGui::Columns(1);
ImGui::Text(TEXT("Vehicle.SelectPreset"));
ImGui::Spacing();
int count = (int)m_ColorData.size();
ImVec2 size = Widget::CalcSize();
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)
{
if (Widget::ColorBtn(colorId, m_ColorData[colorId], ImVec2(btnSize, btnSize)))
{
*(uint8_replacement*)(int(pVeh) + BY_GAME(0x433, 0x19F, 0x19B) + m_Paint.m_nRadioButton) = colorId;
}
if ((colorId + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
#ifdef GTASA
if (gRenderer != eRenderer::DirectX11)
{
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
if (ImGui::BeginTabItem(TEXT("Vehicle.NeonsTab")))
{
int model = pVeh->m_nModelIndex;
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.RemoveNeon"), ImVec2(Widget::CalcSize())))
{
Neon.Remove(pVeh);
Util::SetMessage(TEXT("Vehicle.RemoveNeonMSG"));
}
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
bool pulsing = Neon.IsPulsingEnabled(pVeh);
if (Widget::Checkbox(TEXT("Vehicle.PulsingNeon"), &pulsing))
{
Neon.SetPulsing(pVeh, pulsing);
}
Widget::Checkbox(TEXT("Vehicle.RainbowNeon"), &m_Neon.m_bRainbowEffect, TEXT("Vehicle.RainbowNeonMSG"));
ImGui::NextColumn();
Widget::Checkbox(TEXT("Vehicle.TrafficNeon"), &m_Neon.m_bApplyOnTraffic, TEXT("Vehicle.TrafficNeonMSG"));
ImGui::Columns(1);
ImGui::Spacing();
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), m_Neon.m_fColorPicker))
{
int r = static_cast<int>(m_Neon.m_fColorPicker[0] * 255);
int g = static_cast<int>(m_Neon.m_fColorPicker[1] * 255);
int b = static_cast<int>(m_Neon.m_fColorPicker[2] * 255);
Neon.Install(pVeh, r, g, b);
}
ImGui::Spacing();
ImGui::Text(TEXT("Vehicle.SelectPreset"));
int count = (int)m_ColorData.size();
ImVec2 size = Widget::CalcSize();
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)
{
auto& color = m_ColorData[color_id];
if (Widget::ColorBtn(color_id, color, ImVec2(btnSize, btnSize)))
{
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(pVeh, r, g, b);
}
if ((color_id + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.TextureTab")))
{
Paint::GenerateNodeList(pVeh, m_Paint.m_vecNames, m_Paint.m_Selected);
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.ResetTexture"), ImVec2(Widget::CalcSize())))
{
Paint::ResetNodeTexture(pVeh, m_Paint.m_Selected);
Util::SetMessage(TEXT("Vehicle.ResetTextureMSG"));
}
ImGui::Spacing();
Widget::ListBox(TEXT("Vehicle.Component"), m_Paint.m_vecNames, m_Paint.m_Selected);
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
ImGui::Checkbox(TEXT("Vehicle.MatFilter"), &m_Paint.m_bMatFilter);
ImGui::NextColumn();
int maxpjob, curpjob;
Command<Commands::GET_NUM_AVAILABLE_PAINTJOBS>(hVeh, &maxpjob);
if (maxpjob > 0)
{
Command<Commands::GET_CURRENT_VEHICLE_PAINTJOB>(hVeh, &curpjob);
if (ImGui::ArrowButton("Left", ImGuiDir_Left))
{
curpjob -= 1;
if (curpjob < -1)
{
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;
}
Command<Commands::GIVE_VEHICLE_PAINTJOB>(hVeh, curpjob);
}
ImGui::Spacing();
}
ImGui::Columns(1);
ImGui::Spacing();
Widget::ImageList(Paint::m_TextureData,
[this](std::string& str)
{
Paint::SetNodeTexture(FindPlayerPed()->m_pVehicle, m_Paint.m_Selected, str,
m_Paint.m_bMatFilter);
},
[](std::string& str)
{
return str;
}, nullptr, [](){});
ImGui::EndTabItem();
}
}
#endif
}

42
src/custom/vehpaint.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include "interface/ifeature.hpp"
/*
VehPaintMgr Class
Handles neon, textures for vehicle
*/
class VehPaintMgr : public IFeature<VehPaintMgr>
{
private:
std::vector<std::vector<float>> m_ColorData; // vehicle color data from carcols.dat
struct
{
float m_fColorPicker[3] { 0, 0, 0 };
bool m_bRainbowEffect;
unsigned int m_nRainbowTimer;
bool m_bApplyOnTraffic;
unsigned int m_nTrafficTimer;
} m_Neon;
struct
{
bool m_bMatFilter = true;
int m_nRadioButton = 1;
float m_fColorPicker[3] { 0, 0, 0 };
std::vector<std::string> m_vecNames{"Default"};
std::string m_Selected = "Default";
} m_Paint;
friend class IFeature;
VehPaintMgr();
VehPaintMgr(const VehPaintMgr&);
public:
// Draw color, neon & texture tabs
void Draw();
};
extern VehPaintMgr& VehPaint;

View File

@ -10,7 +10,7 @@
#define MENU_NAME "Cheat Menu"
#define MENU_VERSION_NUMBER "3.3"
#define MENU_VERSION MENU_VERSION_NUMBER"-beta"
#define BUILD_NUMBER "20220810"
#define BUILD_NUMBER "20220820"
#define MENU_TITLE MENU_NAME " v" MENU_VERSION
#ifdef GTASA

View File

@ -1,7 +1,8 @@
#pragma once
#include "ifeature.hpp"
template<typename T>
class ICheat
class ICheat : public IFeature<T>
{
protected:
bool m_bEnabled = false;
@ -20,12 +21,6 @@ public:
m_bEnabled = true;
}
static T &Get()
{
static T _instance;
return _instance;
}
// Returns the current stae of the cheat
virtual const bool GetState() final
{

View File

@ -0,0 +1,12 @@
#pragma once
template<typename T>
class IFeature
{
public:
static T &Get()
{
static T _instance;
return _instance;
}
};

View File

@ -5,9 +5,17 @@
#include "imgui/imgui_internal.h"
#include "pages/welcome.h"
void PageHandler::AddPage(PagePtr page)
void PageHandler::AddPage(PagePtr page, size_t index)
{
m_PageList.push_back(page);
static size_t size = static_cast<size_t>(ePageID::None);
if (index <= size)
{
if (m_PageList.size() < size)
{
m_PageList.resize(size);
}
m_PageList[index] = page;
}
}
void PageHandler::SetCurrentPage(PagePtr page)

View File

@ -1,21 +1,24 @@
#pragma once
#include <vector>
#include "ifeature.hpp"
enum class ePageID
{
Anniversary,
Game,
Menu,
None,
Ped,
Player,
Scene,
Teleport,
Update,
Player,
Ped,
Scene,
Vehicle,
Visual,
Weapon,
Welcome
Game,
Visual,
Menu,
// Pages without headers
None,
Anniversary,
Update,
Welcome,
};
/*
@ -38,7 +41,7 @@ public:
static void DrawPages();
// Add a new page
static void AddPage(PagePtr page);
static void AddPage(PagePtr page, size_t index);
static void SetCurrentPage(PagePtr page);
};
@ -47,7 +50,7 @@ public:
Every page must inherit this
*/
template<typename T>
class IPage
class IPage : public IFeature<T>
{
private:
ePageID m_eID; // Menu page ID
@ -58,18 +61,12 @@ public:
IPage(ePageID page, const std::string& key, bool header)
: m_eID(page), m_NameKey(key), m_bHasHeader(header)
{
PageHandler::AddPage(reinterpret_cast<PagePtr>(this));
PageHandler::AddPage(reinterpret_cast<PagePtr>(this), static_cast<size_t>(m_eID));
}
// Page drawing code goes here
virtual void Draw() = 0;
static T &Get()
{
static T _instance;
return _instance;
}
// Returns the ID of the page
virtual ePageID GetPageID() final
{

View File

@ -5,7 +5,7 @@
class AnniversaryPage : public IPage<AnniversaryPage>
{
private:
friend IPage;
friend class IFeature;
AnniversaryPage() : IPage<AnniversaryPage>(ePageID::Anniversary, "Anniversary", false){}
AnniversaryPage(const AnniversaryPage&);

View File

@ -175,7 +175,6 @@ void SetPlayerMission(std::string& rootkey, std::string& name, std::string& id)
void GamePage::Draw()
{
ImGui::Spacing();
CPlayerPed* pPlayer = FindPlayerPed();
int hplayer = CPools::GetPedRef(pPlayer);

View File

@ -28,7 +28,7 @@ private:
ResourceStore m_StatData{ "stats", eResourceType::TYPE_TEXT };
#endif
friend IPage;
friend class IFeature;
GamePage();
GamePage(const GamePage&);

View File

@ -104,7 +104,7 @@ void MenuPage::Draw()
}
ImGui::NextColumn();
if (gRenderer == Render_DirectX9
if (gRenderer == eRenderer::DirectX9
&& Widget::Checkbox(TEXT("Menu.TextOnlyMode"), &m_bTextOnlyMode, TEXT("Menu.TextOnlyModeHint")))
{
gConfig.Set("Menu.TextOnlyMode", m_bTextOnlyMode);
@ -380,6 +380,12 @@ void MenuPage::Draw()
ImGui::TableNextColumn();
ImGui::Text("MinHook");
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("_AG & jeremii");
ImGui::TableNextColumn();
ImGui::Text("Radar code");
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text(TEXT("Main.TranslatorName"));

View File

@ -8,7 +8,7 @@ public:
bool m_bDiscordRPC; // Is the discord rich presence enabled
bool m_bTextOnlyMode; // Hide all menu images mode
friend IPage;
friend class IFeature;
MenuPage();
MenuPage(const MenuPage&);

View File

@ -23,14 +23,17 @@ static const char* pedTypeList = "Civ Male\0Civ Female\0Cop\0Leones\0Triads\0Dia
#endif
void Ped::Init()
PedPage &pedPage = PedPage::Get();
PedPage::PedPage()
: IPage<PedPage>(ePageID::Ped, "Window.PedPage", true)
{
/*
Taken from gta chaos mod by Lordmau5 & _AG
TODO: Implement in VC too
*/
#ifdef GTASA
Events::pedRenderEvent += [](CPed *ped)
Events::pedRenderEvent += [this](CPed *ped)
{
if (m_bBigHead)// || m_bThinBody)
@ -86,7 +89,7 @@ void Ped::Init()
#endif
}
void Ped::AddNewPed()
void PedPage::AddNewPed()
{
static char name[8];
static int model = 0;
@ -118,12 +121,12 @@ void Ped::AddNewPed()
}
}
#ifdef GTASA
void Ped::SpawnPed(std::string& model)
void PedPage::SpawnPed(std::string& model)
#else
void Ped::SpawnPed(std::string& cat, std::string& name, std::string& model)
void PedPage::SpawnPed(std::string& cat, std::string& name, std::string& model)
#endif
{
if (Spawner::m_List.size() == SPAWN_PED_LIMIT)
if (m_Spawner.m_List.size() == SPAWN_PED_LIMIT)
{
Util::SetMessage(TEXT("Ped.MaxLimit"));
return;
@ -155,7 +158,7 @@ void Ped::SpawnPed(std::string& cat, std::string& name, std::string& model)
CStreaming::RequestSpecialChar(currentSlot, name.c_str(), PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(true);
Command<Commands::CREATE_CHAR>(Spawner::m_nSelectedPedType + 4, 290 + currentSlot, pos.x, pos.y, pos.z + 1, &hplayer);
Command<Commands::CREATE_CHAR>(m_Spawner.m_nSelectedPedType + 4, 290 + currentSlot, pos.x, pos.y, pos.z + 1, &hplayer);
CStreaming::SetSpecialCharIsDeletable(290 + currentSlot);
// SA has 10 slots
@ -175,7 +178,7 @@ void Ped::SpawnPed(std::string& cat, std::string& name, std::string& model)
Command<Commands::LOAD_SPECIAL_CHARACTER>(currentSlot, model.c_str());
Command<Commands::LOAD_ALL_MODELS_NOW>();
Command<Commands::CREATE_CHAR>(Spawner::m_nSelectedPedType + 4, 108+currentSlot, pos.x, pos.y, pos.z + 1, &hplayer);
Command<Commands::CREATE_CHAR>(m_Spawner.m_nSelectedPedType + 4, 108+currentSlot, pos.x, pos.y, pos.z + 1, &hplayer);
Command<Commands::UNLOAD_SPECIAL_CHARACTER>(currentSlot);
++currentSlot;
@ -192,37 +195,37 @@ void Ped::SpawnPed(std::string& cat, std::string& name, std::string& model)
CStreaming::RequestModel(iModel, eStreamingFlags::PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
Command<Commands::CREATE_CHAR>(Spawner::m_nSelectedPedType + 4, iModel, pos.x, pos.y, pos.z + 1, &hplayer);
Command<Commands::CREATE_CHAR>(m_Spawner.m_nSelectedPedType + 4, iModel, pos.x, pos.y, pos.z + 1, &hplayer);
CStreaming::SetModelIsDeletable(iModel);
}
ped = CPools::GetPed(hplayer);
if (Spawner::m_bPedMove)
if (m_Spawner.m_bPedMove)
{
Spawner::m_List.push_back(ped);
m_Spawner.m_List.push_back(ped);
}
else
{
Command<Commands::MARK_CHAR_AS_NO_LONGER_NEEDED>(hplayer);
}
ped->m_nPedFlags.bPedIsBleeding = Spawner::m_bPedBleed;
ped->m_nWeaponAccuracy = Spawner::m_nAccuracy;
ped->m_fHealth = Spawner::m_nPedHealth;
ped->m_nPedFlags.bPedIsBleeding = m_Spawner.m_bPedBleed;
ped->m_nWeaponAccuracy = m_Spawner.m_nAccuracy;
ped->m_fHealth = m_Spawner.m_nPedHealth;
#ifdef GTASA
if (Spawner::m_nWeaponId != 0)
if (m_Spawner.m_nWeaponId != 0)
{
int model = 0;
Command<Commands::GET_WEAPONTYPE_MODEL>(Spawner::m_nWeaponId, &model);
Command<Commands::GET_WEAPONTYPE_MODEL>(m_Spawner.m_nWeaponId, &model);
CStreaming::RequestModel(model, PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
Command<Commands::GIVE_WEAPON_TO_CHAR>(hplayer, Spawner::m_nWeaponId, 999);
Command<Commands::GIVE_WEAPON_TO_CHAR>(hplayer, m_Spawner.m_nWeaponId, 999);
}
#endif
}
}
void Ped::ShowPage()
void PedPage::Draw()
{
if (ImGui::BeginTabBar("Ped", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll))
{
@ -320,12 +323,12 @@ void Ped::ShowPage()
ImGui::Spacing();
if (ImGui::Button(TEXT("Ped.RemoveFrozen"), Widget::CalcSize(1)))
{
for (CPed* ped : Spawner::m_List)
for (CPed* ped : m_Spawner.m_List)
{
CWorld::Remove(ped);
ped->Remove();
}
Spawner::m_List.clear();
m_Spawner.m_List.clear();
}
ImGui::Spacing();
if (ImGui::BeginTabBar("SpawnPedBar"))
@ -336,12 +339,14 @@ void Ped::ShowPage()
{
ImGui::Spacing();
#ifdef GTASA
Widget::ImageList(m_PedData, SpawnPed,
[](std::string& str){
return m_PedData.m_pData->Get(str.c_str(), "Unknown");
}, nullptr, AddNewPed);
Widget::ImageList(m_PedData, fArgWrapper(pedPage.SpawnPed),
[this](str &text)
{
return m_PedData.m_pData->Get(text.c_str(), "Unknown");
},
nullptr, fArgNoneWrapper(pedPage.AddNewPed));
#else
Widget::DataList(m_PedData, SpawnPed, AddNewPed);
Widget::DataList(m_PedData, fArg3Wrapper(pedPage.SpawnPed), fArgNoneWrapper(pedPage.AddNewPed));
#endif
ImGui::EndTabItem();
}
@ -350,26 +355,26 @@ void Ped::ShowPage()
ImGui::Spacing();
ImGui::BeginChild("PedCOnfig");
ImGui::Columns(2, 0, false);
Widget::Checkbox(TEXT("Ped.NoMove"), &Spawner::m_bPedMove);
Widget::Checkbox(TEXT("Ped.NoMove"), &m_Spawner.m_bPedMove);
ImGui::NextColumn();
Widget::Checkbox(TEXT("Ped.PedBleed"), &Spawner::m_bPedBleed);
Widget::Checkbox(TEXT("Ped.PedBleed"), &m_Spawner.m_bPedBleed);
ImGui::Columns(1);
ImGui::Spacing();
ImGui::SliderInt(TEXT("Ped.Accuracy"), &Spawner::m_nAccuracy, 0.0, 100.0);
if (ImGui::InputInt(TEXT("Ped.Health"), &Spawner::m_nPedHealth))
ImGui::SliderInt(TEXT("Ped.Accuracy"), &m_Spawner.m_nAccuracy, 0.0, 100.0);
if (ImGui::InputInt(TEXT("Ped.Health"), &m_Spawner.m_nPedHealth))
{
if (Spawner::m_nPedHealth > 1000)
if (m_Spawner.m_nPedHealth > 1000)
{
Spawner::m_nPedHealth = 1000;
m_Spawner.m_nPedHealth = 1000;
}
if (Spawner::m_nPedHealth < 0)
if (m_Spawner.m_nPedHealth < 0)
{
Spawner::m_nPedHealth = 0;
m_Spawner.m_nPedHealth = 0;
}
}
ImGui::Combo(TEXT("Ped.PedType"), &Spawner::m_nSelectedPedType, pedTypeList);
ImGui::Combo(TEXT("Ped.PedType"), &m_Spawner.m_nSelectedPedType, pedTypeList);
ImGui::EndChild();
ImGui::EndTabItem();
}
@ -380,25 +385,25 @@ void Ped::ShowPage()
ImGui::Text(TEXT("Ped.SelectedWeapon"), weaponName.c_str());
ImGui::Spacing();
#ifdef GTASA
Widget::ImageList(WeaponPage::m_WeaponData,
[](std::string& str)
Widget::ImageList(weaponPage.m_WeaponData,
[this](std::string& str)
{
Spawner::m_nWeaponId = std::stoi(str);
weaponName = WeaponPage::m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
m_Spawner.m_nWeaponId = std::stoi(str);
weaponName = weaponPage.m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
},
[](std::string& str)
{
return WeaponPage::m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
return weaponPage.m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
},
[](std::string& str)
{
return str != "-1"; /*Jetpack*/
});
#else
Widget::DataList(Weapon::m_WeaponData,
[](std::string& root, std::string& key, std::string& id)
Widget::DataList(weaponPage.m_WeaponData,
[this](std::string& root, std::string& key, std::string& id)
{
Spawner::m_nWeaponId = std::stoi(id);
m_Spawner.m_nWeaponId = std::stoi(id);
weaponName = key;
});
#endif
@ -462,8 +467,7 @@ void Ped::ShowPage()
ImGui::Spacing();
if (ImGui::Button(TEXT("Ped.DownloadExGangWars"), Widget::CalcSize(1)))
{
ShellExecute(NULL, "open", "https://gtaforums.com/topic/682194-extended-gang-wars/", NULL, NULL,
SW_SHOWNORMAL);
OPEN_LINK("https://gtaforums.com/topic/682194-extended-gang-wars/");
}
}

View File

@ -1,41 +1,47 @@
#pragma once
#include "pch.h"
#include "interface/ipage.h"
class Ped
class PedPage : public IPage<PedPage>
{
private:
static inline bool m_bBigHead;
static inline bool m_bThinBody;
struct Spawner
bool m_bBigHead;
bool m_bThinBody;
struct
{
static inline std::vector<CPed*> m_List;
static inline int m_nAccuracy = 50;
static inline int m_nPedHealth = 100;
static inline bool m_bPedMove;
static inline bool m_bPedBleed;
static inline int m_nSelectedPedType;
static inline int m_nWeaponId;
};
std::vector<CPed*> m_List;
int m_nAccuracy = 50;
int m_nPedHealth = 100;
bool m_bPedMove;
bool m_bPedBleed;
int m_nSelectedPedType;
int m_nWeaponId;
} m_Spawner;
static void AddNewPed();
friend class IFeature;
PedPage();
PedPage(const PedPage&);
// Add new ped to data file
void AddNewPed();
// Spawn a ped with specified model
#ifdef GTASA
static void SpawnPed(std::string& model);
void SpawnPed(str& model);
#else
static void SpawnPed(std::string& cat, std::string& name, std::string& model);
void SpawnPed(str& cat, str& name, str& model);
#endif
public:
#ifdef GTASA
static inline DataStore m_SpecialPedData {"special_peds"};
static inline ResourceStore m_PedData{"peds", eResourceType::TYPE_IMAGE_TEXT, ImVec2(65, 110)};
DataStore m_SpecialPedData {"special_peds"};
ResourceStore m_PedData{"peds", eResourceType::TYPE_IMAGE_TEXT, ImVec2(65, 110)};
#else
static inline ResourceStore m_PedData {"peds", eResourceType::TYPE_TEXT};
ResourceStore m_PedData {"peds", eResourceType::TYPE_TEXT};
#endif
Ped() = delete;
Ped(const Ped&) = delete;
static void Init();
static void ShowPage();
void Draw();
};
extern PedPage &pedPage;

View File

@ -8,6 +8,7 @@
#ifdef GTASA
#include "ped.h"
#include "custom/topdowncam_sa.h"
#include "custom/customskins_sa.h"
static inline const char* clothNameList[18] =
{
@ -28,7 +29,9 @@ static inline void PlayerModelBrokenFix()
}
#endif
void Player::Init()
PlayerPage &playerPage = PlayerPage::Get();
PlayerPage::PlayerPage()
: IPage<PlayerPage>(ePageID::Player, "Window.PlayerPage", true)
{
#ifdef GTASA
// Fix player model being broken after rebuild
@ -36,42 +39,7 @@ void Player::Init()
m_bAimSkinChanger = gConfig.Get("Features.AimSkinChanger", false);
#endif
// Custom skins setup
std::string path = GAME_PATH((char*)"modloader/");
if (GetModuleHandle("modloader.asi") && std::filesystem::is_directory(path))
{
#ifdef GTASA
path += "CustomSkins/";
if (std::filesystem::is_directory(path))
{
for (auto& p : std::filesystem::recursive_directory_iterator(path))
{
if (p.path().extension() == ".dff")
{
std::string file_name = p.path().stem().string();
if (file_name.size() < 9)
{
CustomSkins::m_List.push_back(file_name);
}
else
{
Log::Print<eLogLevel::Error>("Custom Skin longer than 8 characters {}", file_name);
}
}
}
}
else
{
std::filesystem::create_directory(path);
}
#endif
m_bModloaderInstalled = true;
}
Events::processScriptsEvent += []
Events::processScriptsEvent += [this]
{
uint timer = CTimer::m_snTimeInMilliseconds;
CPlayerPed* player = FindPlayerPed();
@ -123,22 +91,22 @@ void Player::Init()
}
}
if (KeepPosition::m_bEnabled)
if (m_RespawnDieLoc.m_bEnabled)
{
if (Command<Commands::IS_CHAR_DEAD>(hplayer))
{
KeepPosition::m_fPos = player->GetPosition();
m_RespawnDieLoc.m_fPos = player->GetPosition();
}
else
{
CVector cur_pos = player->GetPosition();
if (KeepPosition::m_fPos.x != 0 && KeepPosition::m_fPos.x != cur_pos.x
&& KeepPosition::m_fPos.y != 0 && KeepPosition::m_fPos.y != cur_pos.y)
if (m_RespawnDieLoc.m_fPos.x != 0 && m_RespawnDieLoc.m_fPos.x != cur_pos.x
&& m_RespawnDieLoc.m_fPos.y != 0 && m_RespawnDieLoc.m_fPos.y != cur_pos.y)
{
BY_GAME(player->Teleport(KeepPosition::m_fPos, false)
, player->Teleport(KeepPosition::m_fPos), player->Teleport(KeepPosition::m_fPos));
KeepPosition::m_fPos = CVector(0, 0, 0);
BY_GAME(player->Teleport(m_RespawnDieLoc.m_fPos, false)
, player->Teleport(m_RespawnDieLoc.m_fPos), player->Teleport(m_RespawnDieLoc.m_fPos));
m_RespawnDieLoc.m_fPos = CVector(0, 0, 0);
}
}
}
@ -179,7 +147,7 @@ void Player::Init()
if (targetPed)
{
player->SetModelIndex(targetPed->m_nModelIndex);
Util::ClearCharTasksVehCheck(player);
Util::ClearCharTasksCarCheck(player);
}
}
#endif
@ -221,7 +189,7 @@ void Player::Init()
}
#ifdef GTASA
void Player::ChangePlayerCloth(std::string& name)
void PlayerPage::SetCloth(std::string& name)
{
int bodyPart;
char model[16], tex[16];
@ -259,47 +227,32 @@ void Player::ChangePlayerCloth(std::string& name)
#endif
#ifdef GTASA
void Player::ChangePlayerModel(std::string& model)
void PlayerPage::SetModel(std::string& model)
{
bool custom_skin = std::find(CustomSkins::m_List.begin(), CustomSkins::m_List.end(), model) !=
CustomSkins::m_List.end();
if (Ped::m_PedData.m_pData->Contains(model.c_str()) || custom_skin)
if (pedPage.m_PedData.m_pData->Contains(model.c_str()))
{
CPlayerPed* player = FindPlayerPed();
if (Ped::m_SpecialPedData.Contains(model.c_str()) || custom_skin)
if (pedPage.m_SpecialPedData.Contains(model.c_str()))
{
std::string name;
if (Ped::m_SpecialPedData.Contains(model.c_str()))
{
name = Ped::m_SpecialPedData.Get(model.c_str(), "Unknown");
}
else
{
name = model;
}
std::string name = pedPage.m_SpecialPedData.Get(model.c_str(), "Unknown");
CStreaming::RequestSpecialChar(1, name.c_str(), PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(true);
player->SetModelIndex(291);
CStreaming::SetSpecialCharIsDeletable(291);
}
else
{
int imodel = std::stoi(model);
CStreaming::RequestModel(imodel, eStreamingFlags::PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
player->SetModelIndex(imodel);
CStreaming::SetModelIsDeletable(imodel);
}
Util::ClearCharTasksVehCheck(player);
Util::ClearCharTasksCarCheck(player);
}
}
#else
void Player::ChangePlayerModel(std::string& cat, std::string& key, std::string& val)
void PlayerPage::ChangePlayerModel(std::string& cat, std::string& key, std::string& val)
{
CPlayerPed* player = FindPlayerPed();
@ -329,7 +282,7 @@ void Player::ChangePlayerModel(std::string& cat, std::string& key, std::string&
}
#endif
void Player::ShowPage()
void PlayerPage::Draw()
{
CPlayerPed* pPlayer = FindPlayerPed();
int hplayer = CPools::GetPedRef(pPlayer);
@ -574,7 +527,7 @@ void Player::ShowPage()
#endif
Widget::CheckboxAddr(TEXT("Player.NoFee"), (int)&pInfo->m_bGetOutOfJailFree);
Widget::Checkbox(TEXT("Player.RespawnDieLoc"), &KeepPosition::m_bEnabled, TEXT("Player.RespawnDieLocTip"));
Widget::Checkbox(TEXT("Player.RespawnDieLoc"), &m_RespawnDieLoc.m_bEnabled, TEXT("Player.RespawnDieLocTip"));
Widget::Checkbox(TEXT("Player.PlayerRegen"), &m_bPlayerRegen, TEXT("Player.PlayerRegenTip"));
#ifdef GTASA
static bool sprintInt = false;
@ -684,7 +637,7 @@ void Player::ShowPage()
if (ImGui::Button(TEXT("Player.ChangeToCJ"), ImVec2(Widget::CalcSize(1))))
{
pPlayer->SetModelIndex(0);
Util::ClearCharTasksVehCheck(pPlayer);
Util::ClearCharTasksCarCheck(pPlayer);
}
}
ImGui::Spacing();
@ -806,7 +759,8 @@ void Player::ShowPage()
{
if (pPlayer->m_nModelIndex == 0)
{
Widget::ImageList(m_ClothData, ChangePlayerCloth, [](std::string& str)
Widget::ImageList(m_ClothData, fArgWrapper(playerPage.SetCloth),
[](std::string& str)
{
std::stringstream ss(str);
std::string temp;
@ -825,7 +779,7 @@ void Player::ShowPage()
if (ImGui::Button(TEXT("Player.ChangeToCJ"), ImVec2(Widget::CalcSize(1))))
{
pPlayer->SetModelIndex(0);
Util::ClearCharTasksVehCheck(pPlayer);
Util::ClearCharTasksCarCheck(pPlayer);
}
}
ImGui::EndTabItem();
@ -837,7 +791,6 @@ void Player::ShowPage()
ImGui::Spacing();
ImGui::BeginChild("ClothesRemove");
size_t count = 0;
if (ImGui::Button(TEXT("Player.RemoveAll"), ImVec2(Widget::CalcSize(2))))
{
CPlayerPed* player = FindPlayerPed();
@ -848,12 +801,13 @@ void Player::ShowPage()
CClothes::RebuildPlayer(player, false);
}
ImGui::SameLine();
size_t count = 0;
for (auto [k, v] : m_ClothData.m_pData->Items())
{
if (ImGui::Button(std::string(k.str()).c_str(), ImVec2(Widget::CalcSize(2))))
{
CPlayerPed* player = FindPlayerPed();
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(0u, 0u, count);
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(0u, 0u, std::stoi(v.value_or<std::string>("0")));
CClothes::RebuildPlayer(player, false);
}
@ -869,45 +823,17 @@ void Player::ShowPage()
}
if (ImGui::BeginTabItem(TEXT("Player.PedSkinsTab")))
{
Widget::ImageList(Ped::m_PedData, ChangePlayerModel,
Widget::ImageList(pedPage.m_PedData, fArgWrapper(playerPage.SetModel),
[](std::string& str)
{
return Ped::m_PedData.m_pData->Get(str.c_str(), "Unknown");
return pedPage.m_PedData.m_pData->Get(str.c_str(), "Unknown");
});
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Player.CustomSkinsTab")))
{
ImGui::Spacing();
if (m_bModloaderInstalled)
{
Widget::Filter(TEXT("Window.Search"), m_ClothData.m_Filter,
std::string(TEXT("Player.TotalSkins") + std::to_string(CustomSkins::m_List.size()))
.c_str());
Widget::Tooltip(TEXT("Player.CustomSkinsDirTip"));
ImGui::Spacing();
ImGui::TextWrapped(TEXT("Player.CustomSkinsTip"));
ImGui::Spacing();
for (std::string name : CustomSkins::m_List)
{
if (CustomSkins::m_Filter.PassFilter(name.c_str()))
{
if (ImGui::MenuItem(name.c_str()))
{
ChangePlayerModel(name);
}
}
}
}
else
{
ImGui::TextWrapped(TEXT("Player.CustomSkinTutorial"));
ImGui::Spacing();
if (ImGui::Button(TEXT("Player.DownloadModloader"), ImVec2(Widget::CalcSize(1))))
ShellExecute(NULL, "open", "https://gtaforums.com/topic/669520-mod-loader/", NULL, NULL,
SW_SHOWNORMAL);
}
CustomSkins.Draw();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
@ -924,7 +850,7 @@ void Player::ShowPage()
#else
ImGui::TextWrapped(TEXT("Player.WorkSkinOnly"));
#endif
Widget::DataList(skinData, ChangePlayerModel);
Widget::DataList(skinData, fArg3Wrapper(playerPage.ChangePlayerModel));
ImGui::EndTabItem();
}
#endif

View File

@ -1,47 +1,44 @@
#pragma once
#include "pch.h"
#include "interface/ipage.h"
class Player
class PlayerPage : public IPage<PlayerPage>
{
private:
static inline bool m_bGodMode;
static inline bool m_bPlayerRegen;
static inline bool m_bModloaderInstalled;
struct KeepPosition
bool m_bGodMode;
bool m_bPlayerRegen;
struct
{
static inline bool m_bEnabled = false;
static inline CVector m_fPos;
};
static inline bool m_bKeepStuff;
static inline bool m_bFreezeWantedLevel;
bool m_bEnabled = false;
CVector m_fPos;
} m_RespawnDieLoc;
bool m_bKeepStuff;
bool m_bFreezeWantedLevel;
#ifdef GTAVC
static inline bool m_bNoUndress;
bool m_bNoUndress; // Tommy won't lose clothes after busted/ wasted
#endif
#ifdef GTASA
static inline bool m_bAimSkinChanger;
static inline bool m_bDrunkEffect;
static inline bool m_bFastSprint;
static inline ResourceStore m_ClothData { "clothes", eResourceType::TYPE_TEXT_IMAGE, ImVec2(70, 100)};
struct CustomSkins
{
static inline ImGuiTextFilter m_Filter;
static inline std::vector<std::string> m_List;
};
bool m_bAimSkinChanger;
bool m_bDrunkEffect;
bool m_bFastSprint;
ResourceStore m_ClothData { "clothes", eResourceType::TYPE_TEXT_IMAGE, ImVec2(70, 100)};
static void ChangePlayerModel(std::string& model);
static void ChangePlayerCloth(std::string& model);
void SetCloth(str& id);
void SetModel(str& id);
#else
static inline ResourceStore skinData { BY_GAME(NULL, "skins", "peds"), eResourceType::TYPE_TEXT };
static void ChangePlayerModel(std::string& cat, std::string& name, std::string& id);
ResourceStore skinData { BY_GAME(NULL, "skins", "peds"), eResourceType::TYPE_TEXT };
void ChangePlayerModel(str& cat, str& name, str& id);
#endif
friend class IFeature;
PlayerPage();
PlayerPage(const PlayerPage&);
public:
Player() = delete;
Player(const Player&) = delete;
static void Init();
static void ShowPage();
void Draw();
};
extern PlayerPage &playerPage;

View File

@ -8,7 +8,7 @@
class ScenePage : public IPage<ScenePage>
{
private:
friend IPage;
friend class IFeature;
ScenePage() : IPage<ScenePage>(ePageID::Scene, "Window.ScenePage", true){}
ScenePage(const ScenePage&);

View File

@ -31,7 +31,7 @@ private:
public:
ResourceStore m_locData{"locations", eResourceType::TYPE_TEXT};
friend IPage;
friend class IFeature;
TeleportPage();
TeleportPage(const TeleportPage&);

View File

@ -5,7 +5,7 @@
class UpdatePage : public IPage<UpdatePage>
{
private:
friend IPage;
friend class IFeature;
UpdatePage() : IPage<UpdatePage>(ePageID::Update, "Update", false){}
UpdatePage(const UpdatePage&);

View File

@ -7,49 +7,45 @@
#include "utils/widget.h"
#include "utils/util.h"
#include "custom/filehandler.h"
#include "custom/vehpaint.h"
#include "custom/autodrive.h"
#ifdef GTASA
#include <tHandlingData.h>
#include "custom/neon_sa.h"
#include "custom/paint_sa.h"
#include "custom/vehmod_sa.h"
#endif
void Vehicle::Init()
VehiclePage& vehiclePage = VehiclePage::Get();
VehiclePage::VehiclePage()
: IPage<VehiclePage>(ePageID::Vehicle, "Window.VehiclePage", true)
{
#ifdef GTASA
FileHandler::FetchHandlingID(m_VehicleIDE);
Paint::InjectHooks();
#endif
FileHandler::FetchColorData(m_CarcolsColorData);
// Get config data
Spawner::m_bSpawnInAir = gConfig.Get("Features.SpawnAircraftInAir", true);
Spawner::m_bSpawnInside = gConfig.Get("Features.SpawnInsideVehicle", true);
m_Spawner.m_bInAir = gConfig.Get("Features.SpawnAircraftInAir", true);
m_Spawner.m_bAsDriver = gConfig.Get("Features.SpawnInsideVehicle", true);
Events::processScriptsEvent += []
Events::processScriptsEvent += [this]
{
uint timer = CTimer::m_snTimeInMilliseconds;
CPlayerPed* pPlayer = FindPlayerPed();
CVehicle* pVeh = BY_GAME(FindPlayerVehicle(-1, false), FindPlayerVehicle(), FindPlayerVehicle());
if (pPlayer && Util::IsInVehicle())
if (pPlayer && Util::IsInCar())
{
int hveh = CPools::GetVehicleRef(pVeh);
float speed = pVeh->m_vecMoveSpeed.Magnitude() * 50.0f;
if (m_bAutoUnflip && pVeh->IsUpsideDown() && speed < 2.0f)
{
Util::UnFlipVehicle(pVeh);
Util::UnFlipCar(pVeh);
}
if (unflipVeh.Pressed())
{
Util::UnFlipVehicle(pVeh);
Util::UnFlipCar(pVeh);
}
if (fixVeh.Pressed())
{
Util::FixVehicle(pVeh);
Util::FixCar(pVeh);
Util::SetMessage("Vehicle fixed");
}
@ -121,72 +117,9 @@ void Vehicle::Init()
{
Util::SetCarForwardSpeed(pVeh, m_fLockSpeed);
}
#ifdef GTASA
if (UnlimitedNitro::m_bEnabled && pVeh->m_nVehicleSubClass == VEHICLE_AUTOMOBILE)
{
patch::Set<BYTE>(0x969165, 0, true); // All cars have nitro
patch::Set<BYTE>(0x96918B, 0, true); // All taxis have nitro
if (KeyPressed(VK_LBUTTON))
{
if (!UnlimitedNitro::m_bCompAdded)
{
AddComponent("1010", false);
UnlimitedNitro::m_bCompAdded = true;
}
}
else
{
if (UnlimitedNitro::m_bCompAdded)
{
RemoveComponent("1010", false);
UnlimitedNitro::m_bCompAdded = false;
}
}
}
if (NeonData::m_bRainbowEffect && timer - NeonData::m_nRainbowTimer > 50)
{
int red, green, blue;
Util::RainbowValues(red, green, blue, 0.25);
Neon.Install(pVeh, red, green, blue);
NeonData::m_nRainbowTimer = timer;
}
#endif
}
#ifdef GTASA
// Traffic neons
if (NeonData::m_bApplyOnTraffic && timer - NeonData::m_bTrafficTimer > 1000)
{
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));
}
}
NeonData::m_bTrafficTimer = timer;
}
if (m_bBikeFly && pVeh && pVeh->IsDriver(pPlayer))
{
@ -207,54 +140,8 @@ void Vehicle::Init()
}
#ifdef GTASA
void Vehicle::AddComponent(const std::string& component, const bool display_message)
{
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)
{
Util::SetMessage("Component added");
}
}
catch (...)
{
Log::Print<eLogLevel::Warn>("Failed to add component to vehicle {}", component);
}
}
void Vehicle::RemoveComponent(const std::string& component, const bool display_message)
{
try
{
CPlayerPed* player = FindPlayerPed();
int icomp = std::stoi(component);
int hveh = CPools::GetVehicleRef(player->m_pVehicle);
player->m_pVehicle->RemoveVehicleUpgrade(icomp);
if (display_message)
{
Util::SetMessage("Component removed");
}
}
catch (...)
{
Log::Print<eLogLevel::Warn>("Failed to remove component from vehicle {}", component);
}
}
// hardcoded for now
int Vehicle::GetRandomTrainIdForModel(int model)
int VehiclePage::GetRandomTrainIdForModel(int model)
{
static int train_ids[] =
{
@ -322,7 +209,7 @@ void WarpPlayerIntoVehicle(CVehicle *pVeh, int seatId)
}
#endif
void Vehicle::AddNewVehicle()
void VehiclePage::AddNew()
{
static char name[INPUT_BUFFER_SIZE];
static int model = 0;
@ -335,8 +222,8 @@ void Vehicle::AddNewVehicle()
if (CModelInfo::IsCarModel(model))
{
std::string key = std::format("Custom.{} (Added)", name);
Spawner::m_VehData.m_pData->Set(key.c_str(), std::to_string(model));
Spawner::m_VehData.m_pData->Save();
m_Spawner.m_VehData.m_pData->Set(key.c_str(), std::to_string(model));
m_Spawner.m_VehData.m_pData->Save();
Util::SetMessage(TEXT("Window.AddEntryMSG"));
}
else
@ -352,7 +239,7 @@ void Vehicle::AddNewVehicle()
if (Command<Commands::IS_CHAR_IN_ANY_CAR>(hPlayer))
{
model = pPlayer->m_pVehicle->m_nModelIndex;
std::string str = Vehicle::GetNameFromModel(model);
std::string str = Util::GetCarName(model);
strcpy(name, str.c_str());
}
else
@ -363,9 +250,9 @@ void Vehicle::AddNewVehicle()
}
#ifdef GTASA
void Vehicle::SpawnVehicle(std::string& smodel)
void VehiclePage::SpawnVehicle(std::string& smodel)
#else
void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::string& smodel)
void VehiclePage::SpawnVehicle(std::string& rootkey, std::string& vehName, std::string& smodel)
#endif
{
CPlayerPed* player = FindPlayerPed();
@ -378,7 +265,7 @@ void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::stri
float speed = 0;
bool bInVehicle = Command<Commands::IS_CHAR_IN_ANY_CAR>(hplayer);
if (bInVehicle && Spawner::m_bSpawnInside)
if (bInVehicle && m_Spawner.m_bAsDriver)
{
CVehicle* pveh = player->m_pVehicle;
int hveh = CPools::GetVehicleRef(pveh);
@ -404,7 +291,7 @@ void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::stri
if (interior == 0)
{
if (Spawner::m_bSpawnInAir && (CModelInfo::IsHeliModel(imodel) || CModelInfo::IsPlaneModel(imodel)))
if (m_Spawner.m_bInAir && (CModelInfo::IsHeliModel(imodel) || CModelInfo::IsPlaneModel(imodel)))
{
pos.z = 400;
}
@ -446,7 +333,7 @@ void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::stri
if (veh->m_pDriver)
Command<Commands::DELETE_CHAR>(CPools::GetPedRef(veh->m_pDriver));
if (Spawner::m_bSpawnInside)
if (m_Spawner.m_bAsDriver)
{
Command<Commands::WARP_CHAR_INTO_CAR>(hplayer, hveh);
Util::SetCarForwardSpeed(veh, speed);
@ -466,13 +353,13 @@ void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::stri
CStreaming::RequestModel(imodel, PRIORITY_REQUEST);
CStreaming::LoadAllRequestedModels(false);
#ifdef GTASA
if (Spawner::m_nLicenseText[0] != '\0')
if (m_Spawner.m_nLicenseText[0] != '\0')
{
Command<Commands::CUSTOM_PLATE_FOR_NEXT_CAR>(imodel, Spawner::m_nLicenseText);
Command<Commands::CUSTOM_PLATE_FOR_NEXT_CAR>(imodel, m_Spawner.m_nLicenseText);
}
#endif
int hveh = 0;
if (Spawner::m_bSpawnInside)
if (m_Spawner.m_bAsDriver)
{
Command<Commands::CREATE_CAR>(imodel, pos.x, pos.y, pos.z + 4.0f, &hveh);
veh = CPools::GetVehicle(hveh);
@ -526,102 +413,7 @@ void Vehicle::SpawnVehicle(std::string& rootkey, std::string& vehName, std::stri
#endif
}
std::string Vehicle::GetNameFromModel(int model)
{
#ifdef GTA3
return std::to_string(model);
#else
return (const char*)CModelInfo::GetModelInfo(model) + 0x32;
#endif
}
int Vehicle::GetModelFromName(const char* name)
{
int model = 0;
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo((char*)name, &model);
if (model > 0 && model < 1000000 && GetNameFromModel(model) != "")
{
return model;
}
else
{
return 0;
}
}
static void StartAutoDrive(CVehicle *pVeh, const char *buf = nullptr)
{
int hVeh = CPools::GetVehicleRef(pVeh);
CVector pos;
if (buf == nullptr)
{
#ifdef GTASA
tRadarTrace targetBlip = CRadar::ms_RadarTrace[LOWORD(FrontEndMenuManager.m_nTargetBlipIndex)];
pos = targetBlip.m_vecPos;
if (targetBlip.m_nRadarSprite != RADAR_SPRITE_WAYPOINT)
{
Util::SetMessage(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);
}
}
void Vehicle::ShowPage()
void VehiclePage::Draw()
{
ImGui::Spacing();
CPlayerPed* pPlayer = FindPlayerPed();
@ -639,16 +431,16 @@ void Vehicle::ShowPage()
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.FixCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInVehicle())
if (ImGui::Button(TEXT("Vehicle.FixCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInCar())
{
Util::FixVehicle(pVeh);
Util::FixCar(pVeh);
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.FlipCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInVehicle())
if (ImGui::Button(TEXT("Vehicle.FlipCar"), ImVec2(Widget::CalcSize(3))) && Util::IsInCar())
{
Util::UnFlipVehicle(pVeh);
Util::UnFlipCar(pVeh);
}
ImGui::Spacing();
@ -790,7 +582,7 @@ void Vehicle::ShowPage()
Widget::CheckboxAddr(TEXT("Vehicle.PerfectHandling"), 0x96914C);
Widget::CheckboxAddr(TEXT("Vehicle.TankMode"), 0x969164);
Widget::Checkbox(TEXT("Vehicle.InfNitro"), &UnlimitedNitro::m_bEnabled, TEXT("Vehicle.InfNitroTip"));
Widget::Checkbox(TEXT("Vehicle.InfNitro"), &VehMod.m_Nitro.m_bEnabled, TEXT("Vehicle.InfNitroTip"));
if (Widget::Checkbox(TEXT("Vehicle.FlipNoBurn"), &m_bVehFlipNoBurn, TEXT("Vehicle.FlipNoBurnTip")))
{
// MixSets (Link2012)
@ -948,7 +740,7 @@ void Vehicle::ShowPage()
#endif
if (ImGui::CollapsingHeader(TEXT(bPlayerInCar ? "Vehicle.SwitchSeats" : "Vehicle.EnterNearVeh")))
{
CVehicle* pTargetVeh = bPlayerInCar ? pVeh : Util::GetClosestVehicle();
CVehicle* pTargetVeh = bPlayerInCar ? pVeh : Util::GetClosestCar();
if (pTargetVeh)
{
@ -957,7 +749,7 @@ void Vehicle::ShowPage()
ImGui::Spacing();
ImGui::Columns(2, 0, false);
ImGui::Text(GetNameFromModel(pTargetVeh->m_nModelIndex).c_str());
ImGui::Text(Util::GetCarName(pTargetVeh->m_nModelIndex).c_str());
ImGui::NextColumn();
ImGui::Text(TEXT("Vehicle.TotalSeats"), (seats + 1));
ImGui::Columns(1);
@ -999,14 +791,15 @@ void Vehicle::ShowPage()
}
if (ImGui::CollapsingHeader(TEXT("Vehicle.RemoveVehRadius")))
{
ImGui::InputInt(TEXT("Vehicle.Radius"), &m_nVehRemoveRadius);
static int removeRadius;
ImGui::InputInt(TEXT("Vehicle.Radius"), &removeRadius);
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.RemoveVeh"), Widget::CalcSize(1)))
{
CPlayerPed* player = FindPlayerPed();
for (CVehicle* pVeh : CPools::ms_pVehiclePool)
{
if (DistanceBetweenPoints(pVeh->GetPosition(), player->GetPosition()) < m_nVehRemoveRadius
if (DistanceBetweenPoints(pVeh->GetPosition(), player->GetPosition()) < removeRadius
&& player->m_pVehicle != pVeh)
{
Command<Commands::DELETE_CAR>(CPools::GetVehicleRef(pVeh));
@ -1042,6 +835,7 @@ void Vehicle::ShowPage()
Widget::EditAddr(TEXT("Vehicle.DirtLvl"), (int)pVeh + 0x4B0, 0, 7.5, 15);
if (pVeh->m_nVehicleClass == VEHICLE_AUTOMOBILE && ImGui::CollapsingHeader(TEXT("Vehicle.Doors")))
{
static int m_nDoorMenuButton;
ImGui::Columns(2, 0, false);
ImGui::RadioButton(TEXT("Vehicle.Damage"), &m_nDoorMenuButton, 0);
ImGui::RadioButton(TEXT("Vehicle.Fix"), &m_nDoorMenuButton, 1);
@ -1141,14 +935,14 @@ void Vehicle::ShowPage()
{
ImGui::Spacing();
ImGui::Columns(2, 0, false);
if (Widget::Checkbox(TEXT("Vehicle.SpawnInside"), &Spawner::m_bSpawnInside))
if (Widget::Checkbox(TEXT("Vehicle.SpawnInside"), &m_Spawner.m_bAsDriver))
{
gConfig.Set("Features.SpawnInsideVehicle", Spawner::m_bSpawnInside);
gConfig.Set("Features.SpawnInsideVehicle", m_Spawner.m_bAsDriver);
}
ImGui::NextColumn();
if( Widget::Checkbox(TEXT("Vehicle.SpawnInAir"), &Spawner::m_bSpawnInAir))
if( Widget::Checkbox(TEXT("Vehicle.SpawnInAir"), &m_Spawner.m_bInAir))
{
gConfig.Set("Features.SpawnAircraftInAir", Spawner::m_bSpawnInAir);
gConfig.Set("Features.SpawnAircraftInAir", m_Spawner.m_bInAir);
}
ImGui::Columns(1);
@ -1189,14 +983,14 @@ void Vehicle::ShowPage()
#ifdef GTASA
ImGui::SameLine();
ImGui::SetNextItemWidth(width);
ImGui::InputTextWithHint("##LicenseText", TEXT("Vehicle.PlateText"), Spawner::m_nLicenseText, 9);
ImGui::InputTextWithHint("##LicenseText", TEXT("Vehicle.PlateText"), m_Spawner.m_nLicenseText, 9);
Widget::ImageList(Spawner::m_VehData, SpawnVehicle,
Widget::ImageList(m_Spawner.m_VehData, fArgWrapper(vehiclePage.SpawnVehicle),
[](std::string& str){
return GetNameFromModel(std::stoi(str));
}, nullptr, AddNewVehicle);
return Util::GetCarName(std::stoi(str));
}, nullptr, fArgNoneWrapper(vehiclePage.AddNew));
#else
Widget::DataList(Spawner::m_VehData, SpawnVehicle, AddNewVehicle);
Widget::DataList(m_Spawner.m_VehData, fArg3Wrapper(vehiclePage.SpawnVehicle), fArgNoneWrapper(vehiclePage.AddNew));
#endif
ImGui::EndTabItem();
}
@ -1207,401 +1001,13 @@ void Vehicle::ShowPage()
if (ImGui::BeginTabItem(TEXT("Vehicle.AutoDrive")))
{
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.AutoDriveStop"), Widget::CalcSize(1)))
{
Command<Commands::WARP_CHAR_INTO_CAR>(hplayer, hveh);
}
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(teleportPage.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());
});
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
AutoDrive.Draw();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.Color")))
{
VehPaint.Draw();
#ifdef GTASA
Paint::GenerateNodeList(veh, PaintData::m_vecNames, PaintData::m_Selected);
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.ResetColor"), ImVec2(Widget::CalcSize())))
{
Paint::ResetNodeColor(veh, PaintData::m_Selected);
Util::SetMessage(TEXT("Vehicle.ResetColorMSG"));
}
ImGui::Spacing();
Widget::ListBox(TEXT("Vehicle.Component"), PaintData::m_vecNames, PaintData::m_Selected);
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), PaintData::m_fColorPicker))
{
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);
}
#endif
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
#ifdef GTASA
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);
ImGui::NextColumn();
ImGui::NewLine();
ImGui::RadioButton(TEXT("Vehicle.Tertiary"), &PaintData::m_nRadioButton, 3);
ImGui::RadioButton(TEXT("Vehicle.Quaternary"), &PaintData::m_nRadioButton, 4);
#else
ImGui::RadioButton(TEXT("Vehicle.Primary"), &PaintData::m_nRadioButton, 1);
ImGui::NextColumn();
ImGui::RadioButton(TEXT("Vehicle.Secondary"), &PaintData::m_nRadioButton, 2);
#endif
ImGui::Spacing();
ImGui::Columns(1);
ImGui::Text(TEXT("Vehicle.SelectPreset"));
ImGui::Spacing();
int count = (int)m_CarcolsColorData.size();
ImVec2 size = Widget::CalcSize();
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)
{
if (Widget::ColorBtn(colorId, m_CarcolsColorData[colorId], ImVec2(btnSize, btnSize)))
{
*(uint8_replacement*)(int(veh) + BY_GAME(0x433, 0x19F, 0x19B) + PaintData::m_nRadioButton) = colorId;
}
if ((colorId + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
#ifdef GTASA
if (gRenderer != Render_DirectX11)
{
if (ImGui::BeginTabItem(TEXT("Vehicle.NeonsTab")))
{
int model = veh->m_nModelIndex;
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.RemoveNeon"), ImVec2(Widget::CalcSize())))
{
Neon.Remove(veh);
Util::SetMessage(TEXT("Vehicle.RemoveNeonMSG"));
}
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
bool pulsing = Neon.IsPulsingEnabled(veh);
if (Widget::Checkbox(TEXT("Vehicle.PulsingNeon"), &pulsing))
{
Neon.SetPulsing(veh, pulsing);
}
Widget::Checkbox(TEXT("Vehicle.RainbowNeon"), &NeonData::m_bRainbowEffect, TEXT("Vehicle.RainbowNeonMSG"));
ImGui::NextColumn();
Widget::Checkbox(TEXT("Vehicle.TrafficNeon"), &NeonData::m_bApplyOnTraffic, TEXT("Vehicle.TrafficNeonMSG"));
ImGui::Columns(1);
ImGui::Spacing();
if (ImGui::ColorEdit3(TEXT("Vehicle.ColorPicker"), NeonData::m_fColorPicker))
{
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);
Neon.Install(veh, r, g, b);
}
ImGui::Spacing();
ImGui::Text(TEXT("Vehicle.SelectPreset"));
int count = (int)m_CarcolsColorData.size();
ImVec2 size = Widget::CalcSize();
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)
{
auto& color = m_CarcolsColorData[color_id];
if (Widget::ColorBtn(color_id, color, ImVec2(btnSize, btnSize)))
{
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);
}
if ((color_id + 1) % btnsInRow != 0)
{
ImGui::SameLine(0.0, 4.0);
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.TextureTab")))
{
Paint::GenerateNodeList(veh, PaintData::m_vecNames, PaintData::m_Selected);
ImGui::Spacing();
if (ImGui::Button(TEXT("Vehicle.ResetTexture"), ImVec2(Widget::CalcSize())))
{
Paint::ResetNodeTexture(veh, PaintData::m_Selected);
Util::SetMessage(TEXT("Vehicle.ResetTextureMSG"));
}
ImGui::Spacing();
Widget::ListBox(TEXT("Vehicle.Component"), PaintData::m_vecNames, PaintData::m_Selected);
ImGui::Spacing();
ImGui::Columns(2, NULL, false);
ImGui::Checkbox(TEXT("Vehicle.MatFilter"), &PaintData::m_bMatFilter);
ImGui::NextColumn();
int maxpjob, curpjob;
Command<Commands::GET_NUM_AVAILABLE_PAINTJOBS>(hveh, &maxpjob);
if (maxpjob > 0)
{
Command<Commands::GET_CURRENT_VEHICLE_PAINTJOB>(hveh, &curpjob);
if (ImGui::ArrowButton("Left", ImGuiDir_Left))
{
curpjob -= 1;
if (curpjob < -1)
{
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;
}
Command<Commands::GIVE_VEHICLE_PAINTJOB>(hveh, curpjob);
}
ImGui::Spacing();
}
ImGui::Columns(1);
ImGui::Spacing();
Widget::ImageList(Paint::m_TextureData,
[](std::string& str)
{
Paint::SetNodeTexture(FindPlayerPed()->m_pVehicle, PaintData::m_Selected, str,
PaintData::m_bMatFilter);
},
[](std::string& str)
{
return str;
}, nullptr, [](){});
ImGui::EndTabItem();
}
}
if (ImGui::BeginTabItem(TEXT("Vehicle.TuneTab")))
{
ImGui::Spacing();
Widget::ImageList(m_TuneData,
[](std::string& str)
{
AddComponent(str);
},
// [](std::string& str)
// {
// RemoveComponent(str);
// },
[](std::string& str)
{
return str;
},
[](std::string& str)
{
return ((bool(*)(int, CVehicle*))0x49B010)(std::stoi(str), FindPlayerPed()->m_pVehicle);
});
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(TEXT("Vehicle.HandlingTab")))
{
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
if (ImGui::Button(TEXT("Vehicle.ResetHandling"), ImVec2(Widget::CalcSize(3))))
{
gHandlingDataMgr.LoadHandlingData();
Util::SetMessage(TEXT("Vehicle.ResetHandlingMSG"));
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.SaveFile"), ImVec2(Widget::CalcSize(3))))
{
FileHandler::GenerateHandlingFile(pHandlingData, m_VehicleIDE);
Util::SetMessage(TEXT("Vehicle.SaveFileMSG"));
}
ImGui::SameLine();
if (ImGui::Button(TEXT("Vehicle.ReadMore"), ImVec2(Widget::CalcSize(3))))
{
ShellExecute(NULL, "open", "https://projectcerbera.com/gta/sa/tutorials/handling", NULL, NULL,
SW_SHOWNORMAL);
}
ImGui::Spacing();
ImGui::BeginChild("HandlingChild");
std::vector<Widget::BindInfo> abs{ {TEXT("Vehicle.On"), 1}, {TEXT("Vehicle.Off"), 0} };
Widget::EditRadioBtnAddr(TEXT("Vehicle.Abs"), (int)&pHandlingData->m_bABS, abs);
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;
Widget::EditAddr(TEXT("Vehicle.BrakeDecel"), (int)&pHandlingData->m_fBrakeDeceleration, 0.0f, 0.0f, 20.0f, 2500.0f);
pHandlingData->m_fBrakeDeceleration = BrakeDeceleration / 2500;
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);
Widget::EditAddr(TEXT("Vehicle.CDM"), (int)&fCDM, 0.0f, 0.0f, 1.0f, 0.3381f);
pHandlingData->m_fCollisionDamageMultiplier = factor * fCDM * 2000.0f;
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);
std::vector<Widget::BindInfo> drive_type
{
{TEXT("Vehicle.FrontWheelDrive"), 70},
{TEXT("Vehicle.RearWheelDrive"), 82},
{TEXT("Vehicle.FourWheelDrive"), 52}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.DriveType"), (int)&pHandlingData->m_transmissionData.m_nDriveType, drive_type);
// Engine acceleration calculation
float fEngineAcceleration = pHandlingData->m_transmissionData.m_fEngineAcceleration * 12500;
Widget::EditAddr(TEXT("Vehicle.EngineAccel"), (int)&fEngineAcceleration, 0.0f, 0.0f, 49.0f, 12500.0f);
pHandlingData->m_transmissionData.m_fEngineAcceleration = fEngineAcceleration / 12500;
Widget::EditAddr(TEXT("Vehicle.EngineInertia"), (int)&pHandlingData->m_transmissionData.m_fEngineInertia, 0.1f, 0.1f, 400.0f);
std::vector<Widget::BindInfo> engine_type
{
{TEXT("Vehicle.Petrol"), 80}, {TEXT("Vehicle.Diseal"), 68}, {TEXT("Vehicle.Electric"), 69}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.EngineType"), (int)&pHandlingData->m_transmissionData.m_nEngineType, engine_type);
std::vector<Widget::BindInfo> lights
{
{TEXT("Vehicle.Long"), 0}, {TEXT("Vehicle.Small"), 1},
{TEXT("Vehicle.Big"), 2}, {TEXT("Vehicle.Tall"), 3}
};
Widget::EditRadioBtnAddr(TEXT("Vehicle.FrontLights"), (int)&pHandlingData->m_nFrontLights, lights);
Widget::EditAddr(TEXT("Vehicle.ForceLevel"), (int)&pHandlingData->m_fSuspensionForceLevel, -10.0f, -10.0f, 10.0f); // test later
Widget::EditBits(TEXT("Vehicle.HandlingFlags"), (int)&pHandlingData->m_nHandlingFlags, m_HandlingFlagNames);
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);
// Max Velocity calculation
int MaxVelocity = pHandlingData->m_transmissionData.m_fMaxGearVelocity / *(float*)0xC2B9BC;
Widget::EditAddr(TEXT("Vehicle.MaxVelocity"), (int)&MaxVelocity, 1.0f, 1.0f, 1000.0f);
pHandlingData->m_transmissionData.m_fMaxGearVelocity = MaxVelocity * (*(float*)0xC2B9BC);
Widget::EditBits(TEXT("Vehicle.ModelFlags"), (int)&pHandlingData->m_nModelFlags, m_ModelFlagNames);
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);
Widget::EditRadioBtnAddr(TEXT("Vehicle.RearLights"), (int)&pHandlingData->m_nRearLights, lights);
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);
ImGui::EndChild();
ImGui::EndTabItem();
}
VehMod.Draw();
#endif
}
ImGui::EndTabBar();

View File

@ -1,111 +1,50 @@
#pragma once
#include "pch.h"
#include "interface/ipage.h"
class Vehicle
class VehiclePage : public IPage<VehiclePage>
{
private:
static inline bool m_bAutoUnflip;
static inline bool m_bBikeFly;
static inline bool m_bDontFallBike;
static inline bool m_bVehHeavy;
static inline bool m_bVehWatertight;
static inline bool m_bNoDamage;
static inline int m_nDoorMenuButton;
static inline std::string m_DoorNames[6] =
bool m_bAutoUnflip;
bool m_bBikeFly;
bool m_bDontFallBike;
bool m_bVehHeavy;
bool m_bVehWatertight;
bool m_bNoDamage;
std::string m_DoorNames[6] =
{ "Hood", "Boot", "Front left door", "Front right door", "Rear left door", "Rear right door" };
static inline int m_nVehRemoveRadius;
static inline bool m_bLockSpeed;
static inline float m_fLockSpeed;
static inline std::vector<std::vector<float>> m_CarcolsColorData;
struct PaintData
{
static inline bool m_bMatFilter = true;
static inline int m_nRadioButton = 1;
static inline float m_fColorPicker[3] { 0, 0, 0 };
static inline std::vector<std::string> m_vecNames{"Default"};
static inline std::string m_Selected = "Default";
};
bool m_bLockSpeed;
float m_fLockSpeed;
#ifdef GTASA
static inline bool m_bDisableColDetection;
static inline bool m_bVehFlipNoBurn;
static inline bool m_bMoreTrainCams;
static inline bool m_bNoDerail;
static inline std::map<int, std::string> m_VehicleIDE;
struct NeonData
{
static inline float m_fColorPicker[3] { 0, 0, 0 };
static inline bool m_bRainbowEffect;
static inline uint m_nRainbowTimer;
static inline bool m_bApplyOnTraffic;
static inline uint m_bTrafficTimer;
};
static inline ResourceStore m_TuneData { "components", eResourceType::TYPE_IMAGE_TEXT, ImVec2(100, 80) };
bool m_bDisableColDetection;
bool m_bVehFlipNoBurn;
bool m_bNoDerail;
#endif
struct Spawner
struct
{
#ifdef GTASA
static inline ResourceStore m_VehData { "vehicles", eResourceType::TYPE_IMAGE_TEXT, ImVec2(100, 75)};
#else
static inline ResourceStore m_VehData {"vehicles", eResourceType::TYPE_TEXT};
#endif
static inline bool m_bSpawnInside = true;
static inline bool m_bSpawnInAir = true;
static inline char m_nLicenseText[9];
};
struct UnlimitedNitro
{
static inline bool m_bEnabled;
static inline bool m_bCompAdded;
};
ResourceStore m_VehData { "vehicles", BY_GAME(eResourceType::TYPE_IMAGE_TEXT, eResourceType::TYPE_TEXT,
eResourceType::TYPE_TEXT), ImVec2(100, 75)};
bool m_bAsDriver = true;
bool m_bInAir = true;
char m_nLicenseText[9];
} m_Spawner;
#ifdef GTASA
static inline std::vector<std::string> m_HandlingFlagNames = // 32 flags
{
"1G_BOOST", "2G_BOOST", "NPC_ANTI_ROLL", "NPC_NEUTRAL_HANDL", "NO_HANDBRAKE", "STEER_REARWHEELS",
"HB_REARWHEEL_STEER", "ALT_STEER_OPT",
"WHEEL_F_NARROW2", "WHEEL_F_NARROW", "WHEEL_F_WIDE", "WHEEL_F_WIDE2", "WHEEL_R_NARROW2", "WHEEL_R_NARROW",
"WHEEL_R_WIDE", "WHEEL_R_WIDE2",
"HYDRAULIC_GEOM", "HYDRAULIC_INST", "HYDRAULIC_NONE", "NOS_INST", "OFFROAD_ABILITY", "OFFROAD_ABILITY2",
"HALOGEN_LIGHTS", "PROC_REARWHEEL_1ST",
"USE_MAXSP_LIMIT", "LOW_RIDER", "STREET_RACER", "SWINGING_CHASSIS", "Unused 1", "Unused 2", "Unused 3",
"Unused 4"
};
static inline std::vector<std::string> m_ModelFlagNames = // 32 flags
{
"IS_VAN", "IS_BUS", "IS_LOW", "IS_BIG", "REVERSE_BONNET", "HANGING_BOOT", "TAILGATE_BOOT", "NOSWING_BOOT",
"NO_DOORS", "TANDEM_SEATS",
"SIT_IN_BOAT", "CONVERTIBLE", "NO_EXHAUST", "DOUBLE_EXHAUST", "NO1FPS_LOOK_BEHIND", "FORCE_DOOR_CHECK",
"AXLE_F_NOTILT", "AXLE_F_SOLID", "AXLE_F_MCPHERSON",
"AXLE_F_REVERSE", "AXLE_R_NOTILT", "AXLE_R_SOLID", "AXLE_R_MCPHERSON", "AXLE_R_REVERSE", "IS_BIKE", "IS_HELI",
"IS_PLANE", "IS_BOAT", "BOUNCE_PANELS",
"DOUBLE_RWHEELS", "FORCE_GROUND_CLEARANCE", "IS_HATCHBAC1K"
};
#endif
private:
#ifdef GTASA
static void AddComponent(const std::string& component, bool display_message = true);
static void RemoveComponent(const std::string& component, bool display_message = true);
static int GetRandomTrainIdForModel(int model);
#endif
friend class IFeature;
VehiclePage();
VehiclePage(const VehiclePage&);
public:
Vehicle() = delete;
Vehicle(const Vehicle&) = delete;
void AddNew();
void Draw();
static void AddNewVehicle();
#ifdef GTASA
static void SpawnVehicle(std::string& name);
int GetRandomTrainIdForModel(int model);
void SpawnVehicle(std::string& name);
#else
static void SpawnVehicle(std::string& rootkey, std::string& vehName, std::string& model);
void SpawnVehicle(std::string& rootkey, std::string& vehName, std::string& model);
#endif
static void Init();
static std::string GetNameFromModel(int model);
static int GetModelFromName(const char* name);
static void ShowPage();
};
extern VehiclePage& vehiclePage;

View File

@ -133,7 +133,9 @@ static std::vector<std::string> m_WeatherNames
#endif
};
void Visual::Init()
VisualPage& visualPage = VisualPage::Get();
VisualPage::VisualPage()
: IPage<VisualPage>(ePageID::Visual, "Window.VisualPage", true)
{
#ifdef GTASA
if (GetModuleHandle("timecycle24.asi"))
@ -142,7 +144,7 @@ void Visual::Init()
}
#endif
Events::processScriptsEvent += []
Events::processScriptsEvent += [this]
{
// TODO: Needs improvement
static short m_nBacWeatherType;
@ -401,7 +403,7 @@ void TimecycSlider(const char* label, T* ptr, int min, int max)
}
template<typename T>
bool Visual::TimeCycColorEdit3(const char* label, T* r, T* g, T* b, ImGuiColorEditFlags flags)
bool VisualPage::TimeCycColorEdit3(const char* label, T* r, T* g, T* b, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
@ -430,7 +432,7 @@ bool Visual::TimeCycColorEdit3(const char* label, T* r, T* g, T* b, ImGuiColorEd
}
template <typename T>
void Visual::TimecycSlider(const char* label, T* ptr, int min, int max)
void VisualPage::TimecycSlider(const char* label, T* ptr, int min, int max)
{
int val = CalcArrayIndex();
#ifdef GTASA
@ -446,7 +448,7 @@ void Visual::TimecycSlider(const char* label, T* ptr, int min, int max)
}
template <typename T>
bool Visual::TimeCycColorEdit4(const char* label, T* r, T* g, T* b, T* a, ImGuiColorEditFlags flags)
bool VisualPage::TimeCycColorEdit4(const char* label, T* r, T* g, T* b, T* a, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
@ -522,7 +524,7 @@ static void ColorPickerAddr(const char* label, int addr, ImVec4&& default_color)
}
}
void Visual::PatchRadar()
void VisualPage::PatchRadar()
{
#ifdef GTASA
static float clockPosX = *(float*)*(int*)0x58EC16;
@ -598,7 +600,7 @@ void Visual::PatchRadar()
#endif
}
void Visual::ShowPage()
void VisualPage::Draw()
{
if (ImGui::BeginTabBar("Visual", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll))
{
@ -619,11 +621,11 @@ void Visual::ShowPage()
if (m_bDisableHydrant)
{
// don't call Fx_c::TriggerWaterHydrant
plugin::patch::Nop(0x4A0D70, 5);
patch::Nop(0x4A0D70, 5);
}
else
{
plugin::patch::SetRaw(0x4A0D70, (char*)"\xE9\x94\x3F\xF6\xFF", 5);
patch::SetRaw(0x4A0D70, (char*)"\xE9\x94\x3F\xF6\xFF", 5);
}
}
Widget::CheckboxAddr(TEXT("Visual.FogEffect"), 0xC402C6);
@ -650,18 +652,18 @@ void Visual::ShowPage()
else
{
// restore
plugin::patch::SetRaw(0x575BF6, (char*)"\xE8\x65\x1F\x1B\x00", 5);
plugin::patch::SetRaw(0x575C40, (char*)"\xE8\x1B\x1F\x1B\x00", 5);
plugin::patch::SetRaw(0x575C84, (char*)"\xE8\xD7\x1E\x1B\x00", 5);
plugin::patch::SetRaw(0x575CCE, (char*)"\xE8\x8D\x1E\x1B\x00", 5);
plugin::patch::SetRaw(0x575D1F, (char*)"\xE8\x3C\x1E\x1B\x00", 5);
plugin::patch::SetRaw(0x575D6F, (char*)"\xE8\xEC\x1D\x1B\x00", 5);
plugin::patch::SetRaw(0x575DC2, (char*)"\xE8\x99\x1D\x1B\x00", 5);
plugin::patch::SetRaw(0x575E12, (char*)"\xE8\x49\x1D\x1B\x00", 5);
plugin::patch::SetRaw(0x5754EC, (char*)"\xD8\x0D\x20\x95\x85\x00", 6);
plugin::patch::SetRaw(0x575537, (char*)"\xD8\x0D\x24\x95\x85\x00", 6);
plugin::patch::SetRaw(0x575311, (char*)"\xD8\x0D\x70\x53\x86\x00", 6);
plugin::patch::SetRaw(0x575361, (char*)"\xD8\x0D\x6C\x53\x86\x00", 6);
patch::SetRaw(0x575BF6, (char*)"\xE8\x65\x1F\x1B\x00", 5);
patch::SetRaw(0x575C40, (char*)"\xE8\x1B\x1F\x1B\x00", 5);
patch::SetRaw(0x575C84, (char*)"\xE8\xD7\x1E\x1B\x00", 5);
patch::SetRaw(0x575CCE, (char*)"\xE8\x8D\x1E\x1B\x00", 5);
patch::SetRaw(0x575D1F, (char*)"\xE8\x3C\x1E\x1B\x00", 5);
patch::SetRaw(0x575D6F, (char*)"\xE8\xEC\x1D\x1B\x00", 5);
patch::SetRaw(0x575DC2, (char*)"\xE8\x99\x1D\x1B\x00", 5);
patch::SetRaw(0x575E12, (char*)"\xE8\x49\x1D\x1B\x00", 5);
patch::SetRaw(0x5754EC, (char*)"\xD8\x0D\x20\x95\x85\x00", 6);
patch::SetRaw(0x575537, (char*)"\xD8\x0D\x24\x95\x85\x00", 6);
patch::SetRaw(0x575311, (char*)"\xD8\x0D\x70\x53\x86\x00", 6);
patch::SetRaw(0x575361, (char*)"\xD8\x0D\x6C\x53\x86\x00", 6);
}
}
Widget::CheckboxAddr(TEXT("Visual.GrainEffect"), 0xC402B4);
@ -692,14 +694,14 @@ void Visual::ShowPage()
if (m_bInvisibleWater)
{
// don't call CWaterLevel::RenderWater()
plugin::patch::Nop(0x53E004, 5);
plugin::patch::Nop(0x53E142, 5);
patch::Nop(0x53E004, 5);
patch::Nop(0x53E142, 5);
}
else
{
// restore call CWaterLevel::RenderWater()
plugin::patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
plugin::patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
}
}
}
@ -740,7 +742,7 @@ void Visual::ShowPage()
patch::Set<float>(0xBA830C, 0.0);
patch::Set<float>(0xBA8308, 1.0);
// stop map rotaiton
// stop map rotation
patch::Nop(0x5837FB, 6);
patch::Nop(0x583805, 6);
patch::Nop(0x58380D, 6);
@ -763,20 +765,20 @@ void Visual::ShowPage()
if (m_bNoWater)
{
// don't call CWaterLevel::RenderWater()
plugin::patch::Nop(0x53E004, 5);
plugin::patch::Nop(0x53E142, 5);
patch::Nop(0x53E004, 5);
patch::Nop(0x53E142, 5);
// rtn CWaterLevel::GetWaterLevelNoWaves
plugin::patch::SetRaw(0x6E8580, (char*)"\x32\xC0\xC3", 3);
patch::SetRaw(0x6E8580, (char*)"\x32\xC0\xC3", 3);
}
else
{
// restore call CWaterLevel::RenderWater()
plugin::patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
plugin::patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
// restore CWaterLevel::GetWaterLevelNoWaves
plugin::patch::SetRaw(0x6E8580, (char*)"\x51\xD9\x44", 3);
patch::SetRaw(0x6E8580, (char*)"\x51\xD9\x44", 3);
}
}
bool radar_state = (patch::Get<BYTE>(0xBA676C) != 2);

View File

@ -1,38 +1,41 @@
#pragma once
#include "pch.h"
#include "interface/ipage.h"
class Visual
class VisualPage : public IPage<VisualPage>
{
private:
static inline bool m_bLockWeather;
bool m_bLockWeather;
#ifdef GTASA
static inline bool m_bInvisibleWater;
static inline bool m_bNoWater;
static inline bool m_bDisableHydrant;
static inline bool m_bNoMoneyZeros;
static inline bool m_bNoPartciles;
static inline bool m_bNoPostFX;
static inline bool m_bNoTextures;
static inline bool m_bFullScreenMap;
static inline bool m_bSquareRadar;
static inline bool m_bNoRadarRot;
bool m_bInvisibleWater;
bool m_bNoWater;
bool m_bDisableHydrant;
bool m_bNoMoneyZeros;
bool m_bNoPartciles;
bool m_bNoPostFX;
bool m_bNoTextures;
bool m_bFullScreenMap;
bool m_bSquareRadar;
bool m_bNoRadarRot;
#endif
friend class IFeature;
VisualPage();
VisualPage(const VisualPage&);
template<typename T>
static bool TimeCycColorEdit3(const char* label, T* r, T* g, T* b, ImGuiColorEditFlags flags = 0);
bool TimeCycColorEdit3(const char* label, T* r, T* g, T* b, ImGuiColorEditFlags flags = 0);
template <typename T>
static bool TimeCycColorEdit4(const char* label, T* r, T* g, T* b, T* a, ImGuiColorEditFlags flags = 0);
bool TimeCycColorEdit4(const char* label, T* r, T* g, T* b, T* a, ImGuiColorEditFlags flags = 0);
template <typename T>
static void TimecycSlider(const char* label, T* data, int min, int max);
void TimecycSlider(const char* label, T* data, int min, int max);
public:
Visual() = delete;
Visual(const Visual&) = delete;
static void Init();
static void ShowPage();
void Draw();
// Patches the radar for visual changes
static void PatchRadar();
void PatchRadar();
};
extern VisualPage& visualPage;

View File

@ -4,9 +4,11 @@
#include "utils/util.h"
#include <CWeaponInfo.h>
void WeaponPage::Init()
WeaponPage& weaponPage = WeaponPage::Get();
WeaponPage::WeaponPage()
: IPage<WeaponPage>(ePageID::Weapon, "Window.WeaponPage", true)
{
Events::processScriptsEvent += []
Events::processScriptsEvent += [this]
{
CPlayerPed* player = FindPlayerPed();
@ -94,11 +96,11 @@ void WeaponPage::Init()
}
#ifdef GTASA
void WeaponPage::SetGangWeapon(std::string& weapon_type)
void WeaponPage::GangStruct::SetWeapon(std::string& weaponType)
{
m_nGangWeaponList[m_nSelectedGang][m_nSelectedWeapon] = std::stoi(weapon_type);
CGangs::SetGangWeapons(m_nSelectedGang, m_nGangWeaponList[m_nSelectedGang][0], m_nGangWeaponList[m_nSelectedGang][1],
m_nGangWeaponList[m_nSelectedGang][2]);
m_WeaponList[m_nSelected][m_nSelectedWeapon] = std::stoi(weaponType);
CGangs::SetGangWeapons(m_nSelected, m_WeaponList[m_nSelected][0], m_WeaponList[m_nSelected][1],
m_WeaponList[m_nSelected][2]);
}
#else
// Implementation of SA opcode 0x555
@ -206,7 +208,7 @@ void WeaponPage::GiveWeaponToPlayer(std::string& weapon_type)
}
}
#else
void Weapon::GiveWeaponToPlayer(std::string& rootkey, std::string& name, std::string& model)
void WeaponPage::GiveWeaponToPlayer(std::string& rootkey, std::string& name, std::string& model)
{
CPlayerPed* player = FindPlayerPed();
int hplayer = CPools::GetPedRef(player);
@ -376,17 +378,17 @@ void WeaponPage::Draw()
m_nAmmoCount = (m_nAmmoCount > 99999) ? 99999 : m_nAmmoCount;
}
#ifdef GTASA
Widget::ImageList(m_WeaponData, GiveWeaponToPlayer,
[](std::string& str)
Widget::ImageList(m_WeaponData, fArgWrapper(weaponPage.GiveWeaponToPlayer),
[this](std::string& str)
{
return m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
},
[](std::string& str)
{
return str != "0"; /*Unarmed*/
}, AddNew);
}, fArgNoneWrapper(weaponPage.AddNew));
#else
Widget::DataList(m_WeaponData, GiveWeaponToPlayer, AddWeapon);
Widget::DataList(m_WeaponData, fArg3Wrapper(weaponPage.GiveWeaponToPlayer), fArgNoneWrapper(weaponPage.AddNew));
#endif
ImGui::EndTabItem();
}
@ -399,15 +401,15 @@ void WeaponPage::Draw()
"Ballas\0Grove street families\0Los santos vagos\0San fierro rifa\0Da nang boys\0"
"Mafia\0Mountain cloud triad\0Varrio los aztecas\0Gang9\0Gang10\0"
};
ImGui::Combo(TEXT("Weapon.SelectGang"), &m_nSelectedGang, gangList);
ImGui::Combo(TEXT("Ped.SelectWeapon"), &m_nSelectedWeapon, "Weapon 1\0Weapon 2\0Weapon 3\0");
ImGui::Combo(TEXT("Weapon.SelectGang"), &m_Gang.m_nSelected, gangList);
ImGui::Combo(TEXT("Ped.SelectWeapon"), &m_Gang.m_nSelectedWeapon, "Weapon 1\0Weapon 2\0Weapon 3\0");
ImGui::Spacing();
std::string key = std::to_string(m_nGangWeaponList[m_nSelectedGang][m_nSelectedWeapon]);
std::string key = std::to_string(m_Gang.m_WeaponList[m_Gang.m_nSelected][m_Gang.m_nSelectedWeapon]);
ImGui::Text(TEXT("Weapon.CurrentWeapon"), m_WeaponData.m_pData->Get(key.c_str(), "Unknown").c_str());
ImGui::Spacing();
Widget::ImageList(m_WeaponData, SetGangWeapon,
[](std::string& str){
Widget::ImageList(m_WeaponData, fArgWrapper(weaponPage.m_Gang.SetWeapon),
[this](std::string& str){
return m_WeaponData.m_pData->Get(str.c_str(), "Unknown");
},
[](std::string& str){

View File

@ -1,59 +1,65 @@
#pragma once
#include "pch.h"
#include "interface/ipage.h"
class WeaponPage
class WeaponPage : public IPage<WeaponPage>
{
private:
static inline bool m_bFastReload;
static inline bool m_bHugeDamage;
static inline bool m_bLongRange;
static inline int m_nAmmoCount = 99999;
static inline int m_nSelectedWeapon;
bool m_bFastReload;
bool m_bHugeDamage;
bool m_bLongRange;
int m_nAmmoCount = 99999;
#ifdef GTASA
static inline bool m_bAutoAim;
static inline bool m_bRapidFire;
static inline bool m_bDualWeild;
static inline bool m_bMoveAim;
static inline bool m_bMoveFire;
static inline bool m_bNoSpread;
static inline int m_nSelectedGang;
static inline int m_nGangWeaponList[10][3] =
bool m_bAutoAim;
bool m_bRapidFire;
bool m_bDualWeild;
bool m_bMoveAim;
bool m_bMoveFire;
bool m_bNoSpread;
struct GangStruct
{
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // Ballas
{WEAPON_PISTOL, WEAPON_UNARMED, WEAPON_UNARMED}, // Grove
{WEAPON_PISTOL, WEAPON_UNARMED, WEAPON_UNARMED}, // Vagos
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // SF Rifa
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // Da Nang Boys
{WEAPON_DESERT_EAGLE, WEAPON_UNARMED, WEAPON_UNARMED}, // Mafia
{WEAPON_PISTOL, WEAPON_AK47, WEAPON_UNARMED}, // Triads
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // VLA
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // Gang 9
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // Gang 10
};
int m_nSelected;
int m_nSelectedWeapon;
int m_WeaponList[10][3] =
{
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // Ballas
{WEAPON_PISTOL, WEAPON_UNARMED, WEAPON_UNARMED}, // Grove
{WEAPON_PISTOL, WEAPON_UNARMED, WEAPON_UNARMED}, // Vagos
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // SF Rifa
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // Da Nang Boys
{WEAPON_DESERT_EAGLE, WEAPON_UNARMED, WEAPON_UNARMED}, // Mafia
{WEAPON_PISTOL, WEAPON_AK47, WEAPON_UNARMED}, // Triads
{WEAPON_PISTOL, WEAPON_MICRO_UZI, WEAPON_UNARMED}, // VLA
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // Gang 9
{WEAPON_UNARMED, WEAPON_UNARMED, WEAPON_UNARMED}, // Gang 10
};
void SetWeapon(std::string& weaponType);
} m_Gang;
#else
static inline bool m_bInfiniteAmmo;
bool m_bInfiniteAmmo;
#endif
friend class IFeature;
WeaponPage();
WeaponPage(const WeaponPage&);
public:
WeaponPage() = delete;
WeaponPage(const WeaponPage&) = delete;
ResourceStore m_WeaponData { "weapons", BY_GAME(eResourceType::TYPE_IMAGE_TEXT, eResourceType::TYPE_TEXT,
eResourceType::TYPE_TEXT), ImVec2(65, 65) };
static void Init();
// Add new weapon entry
void AddNew();
void Draw();
static void Draw();
static void AddNew();
#ifdef GTASA
static inline ResourceStore m_WeaponData { "weapons", eResourceType::TYPE_IMAGE_TEXT, ImVec2(65, 65) };
static void GiveWeaponToPlayer(std::string& weapon_type);
static void SetGangWeapon(std::string& weapon_type);
void GiveWeaponToPlayer(std::string& weaponType);
#else
static inline ResourceStore m_WeaponData { "weapons", eResourceType::TYPE_TEXT };
static void GiveWeaponToPlayer(std::string& rootkey, std::string& model, std::string& name);
void GiveWeaponToPlayer(std::string& rootkey, std::string& model, std::string& name);
#endif
};
extern WeaponPage& weaponPage;

View File

@ -5,7 +5,7 @@
class WelcomePage : public IPage<WelcomePage>
{
private:
friend IPage;
friend class IFeature;
WelcomePage() : IPage<WelcomePage>(ePageID::Welcome, "Welcome", false)
{
PageHandler::SetCurrentPage(this);

View File

@ -1,5 +1,5 @@
#include "pch.h"
eRenderer gRenderer = Render_Unknown;
eRenderer gRenderer = eRenderer::Unknown;
DataStore gConfig = DataStore(FILE_NAME, true);
ResourceStore gTextureList { "misc", eResourceType::TYPE_IMAGE, ImVec2(100, 80) };

View File

@ -6,6 +6,7 @@
#include <d3d11Shader.h>
#include <filesystem>
#include <fstream>
#include <functional>
#include <memory>
#include <iostream>
#include <sstream>
@ -67,25 +68,26 @@
using namespace plugin;
enum eRenderer
enum class eRenderer
{
Render_DirectX9,
Render_DirectX11,
Render_Unknown
DirectX9,
DirectX11,
Unknown
};
extern eRenderer gRenderer;
extern DataStore gConfig;
typedef std::string str;
typedef void(*fArg3_t)(str&, str&, str&);
typedef void(*fArg1_t)(str&);
typedef void(*fArgNone_t)();
typedef std::string(*fRtnArg1_t)(str&);
typedef bool(*fRtnBoolArg1_t)(str&);
using str = std::string;
using fArgNone_t = std::function<void()>;
using fArg1_t = std::function<void(str&)>;
using fArg3_t = std::function<void(str&, str&, str&)>;
using fRtnArg1_t = std::function<std::string(str&)>;
using fRtnBoolArg1_t = std::function<bool(str&)>;
#define fArg3Wrapper(x) [](str& a, str& b, str& c){x(a, b, c);}
#define fArgWrapper(x) [](str& a){x(a);}
#define fRtnArgWrapper(x) [](str& a){return x(a);}
#define fArgNoneWrapper(x) [](){x();}
#ifdef GTASA

View File

@ -62,7 +62,7 @@ void D3dHook::ProcessFrame(void* ptr)
{
FontMgr::ReloadAll();
if (gRenderer == Render_DirectX9)
if (gRenderer == eRenderer::DirectX9)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
}
@ -85,7 +85,7 @@ void D3dHook::ProcessFrame(void* ptr)
}
ImGui_ImplWin32_NewFrame();
if (gRenderer == Render_DirectX9)
if (gRenderer == eRenderer::DirectX9)
{
ImGui_ImplDX9_NewFrame();
}
@ -104,7 +104,7 @@ void D3dHook::ProcessFrame(void* ptr)
ImGui::EndFrame();
ImGui::Render();
if (gRenderer == Render_DirectX9)
if (gRenderer == eRenderer::DirectX9)
{
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
}
@ -116,7 +116,7 @@ void D3dHook::ProcessFrame(void* ptr)
if (FontMgr::IsFontReloadRequired())
{
FontMgr::ReloadAll();
if (gRenderer == Render_DirectX9)
if (gRenderer == eRenderer::DirectX9)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
}
@ -135,7 +135,7 @@ void D3dHook::ProcessFrame(void* ptr)
patch::Nop(0x00531155, 5); // shift trigger fix
#endif
if (gRenderer == Render_DirectX9)
if (gRenderer == eRenderer::DirectX9)
{
ImGui_ImplDX9_Init(reinterpret_cast<IDirect3DDevice9*>(ptr));
}
@ -270,7 +270,7 @@ bool D3dHook::Init(void *pCallback)
*/
if (init(kiero::RenderType::D3D9) == kiero::Status::Success)
{
gRenderer = Render_DirectX9;
gRenderer = eRenderer::DirectX9;
kiero::bind(16, (void**)&oReset, hkReset);
kiero::bind(42, (void**)&oEndScene, hkEndScene);
pCallbackFunc = pCallback;
@ -281,7 +281,7 @@ bool D3dHook::Init(void *pCallback)
if (init(kiero::RenderType::D3D11) == kiero::Status::Success)
{
gRenderer = Render_DirectX11;
gRenderer = eRenderer::DirectX11;
kiero::bind(8, (void**)&oPresent, hkPresent);
pCallbackFunc = pCallback;
hookInjected = true;

View File

@ -102,7 +102,7 @@ void Overlay::ProcessModelInfo()
#ifdef GTASA
if (pEnt->m_nType == ENTITY_TYPE_VEHICLE)
{
text = std::format("{}\n{}", model, Vehicle::GetNameFromModel(model));
text = std::format("{}\n{}", model, Util::GetCarName(model));
}
else if (pEnt->m_nType == ENTITY_TYPE_PED)
{
@ -326,7 +326,7 @@ void Overlay::ProcessCommands(std::string&& str)
if (wep_name == "jetpack")
{
std::string weapon = "-1";
WeaponPage::GiveWeaponToPlayer(weapon);
weaponPage.GiveWeaponToPlayer(weapon);
Util::SetMessage(TEXT("Menu.WeaponSpawned"));
}
else
@ -337,7 +337,7 @@ void Overlay::ProcessCommands(std::string&& str)
if (wep_name != "" && pweaponinfo->m_nModelId1 != -1)
{
WeaponPage::GiveWeaponToPlayer(weapon_name);
weaponPage.GiveWeaponToPlayer(weapon_name);
Util::SetMessage(TEXT("Menu.WeaponSpawned"));
}
else
@ -351,11 +351,11 @@ void Overlay::ProcessCommands(std::string&& str)
std::string veh_name;
ss >> veh_name;
int model = Vehicle::GetModelFromName(veh_name.c_str());
int model = Util::GetCarModel(veh_name.c_str());
if (model != 0)
{
std::string smodel = std::to_string(model);
Vehicle::SpawnVehicle(smodel);
vehiclePage.SpawnVehicle(smodel);
Util::SetMessage(TEXT("Menu.VehicleSpawned"));
}
else

View File

@ -121,7 +121,7 @@ void RPC::DrawPages()
if (BY_GAME(pPed->m_nPedFlags.bInVehicle, pPed->m_bInVehicle, pPed->m_bInVehicle))
{
std::string name = Vehicle::GetNameFromModel(pPed->m_pVehicle->m_nModelIndex);
std::string name = Util::GetCarName(pPed->m_pVehicle->m_nModelIndex);
std::transform(name.begin(), name.end(), name.begin(), asciitolower);
smallImgText = std::format("{} {} {} {}", TEXT("RPC.Driving"), name, TEXT("RPC.In"), Util::GetLocationName(&pPed->GetPosition()));
smallImg = "drive";

View File

@ -37,6 +37,30 @@ ImVec2 Util::ConvertMapToScreen(ImVec2 pos, ImVec2 mapSz, ImVec2 screenSz)
return pos;
}
std::string Util::GetCarName(int model)
{
#ifdef GTA3
return std::to_string(model);
#else
return (const char*)CModelInfo::GetModelInfo(model) + 0x32;
#endif
}
int Util::GetCarModel(const char* name)
{
int model = 0;
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo((char*)name, &model);
if (model > 0 && model < 1000000 && GetCarName(model) != "")
{
return model;
}
else
{
return 0;
}
}
void Util::SetMessage(const char *message, bool b1, bool b2, bool b3)
{
#if GTASA
@ -57,7 +81,7 @@ float Util::RoundFloat(float val)
return roundf(val * 100) / 100;
}
bool Util::IsInVehicle(CPed *pPed)
bool Util::IsInCar(CPed *pPed)
{
if (!pPed)
{
@ -67,7 +91,7 @@ bool Util::IsInVehicle(CPed *pPed)
return BY_GAME(pPed->m_nPedFlags.bInVehicle, pPed->m_bInVehicle, pPed->m_bInVehicle);
}
void Util::FixVehicle(CVehicle *pVeh)
void Util::FixCar(CVehicle *pVeh)
{
#ifdef GTASA
pVeh->Fix();
@ -91,7 +115,7 @@ void Util::FixVehicle(CVehicle *pVeh)
pVeh->m_fHealth = 1000.0f;
}
void Util::UnFlipVehicle(CVehicle *pVeh)
void Util::UnFlipCar(CVehicle *pVeh)
{
#ifdef GTASA
int hveh = CPools::GetVehicleRef(pVeh);
@ -170,14 +194,14 @@ std::string Util::GetLocationName(CVector* pos)
}
#ifdef GTASA
void Util::ClearCharTasksVehCheck(CPed* pPed)
void Util::ClearCharTasksCarCheck(CPed* pPed)
{
uint hped = CPools::GetPedRef(pPed);
uint hveh = NULL;
bool veh_engine = true;
float speed;
if (IsInVehicle(pPed))
if (IsInCar(pPed))
{
hveh = CPools::GetVehicleRef(pPed->m_pVehicle);
veh_engine = pPed->m_pVehicle->m_nVehicleFlags.bEngineOn;
@ -223,7 +247,7 @@ int Util::GetLargestGangInZone()
// implemention of opcode 0AB5 (STORE_CLOSEST_ENTITIES)
// https://github.com/cleolibrary/CLEO4/blob/916d400f4a731ba1dd0ff16e52bdb056f42b7038/source/CCustomOpcodeSystem.cpp#L1671
CVehicle* Util::GetClosestVehicle()
CVehicle* Util::GetClosestCar()
{
CPlayerPed* player = FindPlayerPed();

View File

@ -19,24 +19,29 @@ public:
Util(Util&) = delete;
#ifdef GTASA
static void ClearCharTasksCarCheck(CPed* ped);
static int GetLargestGangInZone();
static void ClearCharTasksVehCheck(CPed* ped);
static bool IsOnMission();
#endif
static ImVec2 ConvertScreenToMap(ImVec2 pos, ImVec2 mapSz, ImVec2 screenSz);
static ImVec2 ConvertMapToScreen(ImVec2 pos, ImVec2 mapSz, ImVec2 screenSz);
static void UnFlipVehicle(CVehicle *pVeh);
static void FixVehicle(CVehicle *pVeh);
static CPed* GetClosestPed();
static CVehicle* GetClosestVehicle();
static void FixCar(CVehicle *pVeh);
static void SetCarForwardSpeed(CVehicle *pVeh, float speed);
static CVehicle* GetClosestCar();
static int GetCarModel(const char* name);
static std::string GetCarName(int model);
static bool IsInCar(CPed *pPed = FindPlayerPed());
static void UnFlipCar(CVehicle *pVeh);
static void GetCPUUsageInit();
static double GetCurrentCPUUsage();
static float RoundFloat(float val);
static CPed* GetClosestPed();
static std::string GetLocationName(CVector* pos);
static bool IsOnCutscene();
static bool IsInVehicle(CPed *pPed = FindPlayerPed());
static void RainbowValues(int& r, int& g, int& b, float speed);
static void SetCarForwardSpeed(CVehicle *pVeh, float speed);
static void SetMessage(const char *message, bool b1 = false, bool b2 = false, bool b3 = false);
static float RoundFloat(float val);
};

View File

@ -324,7 +324,7 @@ void Widget::ImageList(ResourceStore &store, fArg1_t clickFunc, fRtnArg1_t getNa
m_ImageSize.x /= imagesInRow;
bool showImages = !menuPage.m_bTextOnlyMode;
if (gRenderer == Render_DirectX11)
if (gRenderer == eRenderer::DirectX11)
{
showImages = false;
}