Skip to content

Commit 049daca

Browse files
committed
setVehicleSpecialFeatureEnabled
1 parent 8b199c4 commit 049daca

21 files changed

+514
-162
lines changed

Client/game_sa/CAutomobileSA.cpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void CAutomobileSAInterface::SetPanelDamage(std::uint8_t panelId, bool breakGlas
2727
if (nodeId < 0)
2828
return;
2929

30-
eCarNodes node = static_cast<eCarNodes>(nodeId);
30+
CarNodes::Enum node = static_cast<CarNodes::Enum>(nodeId);
3131

3232
RwFrame* frame = m_aCarNodes[nodeId];
3333
if (!frame)
@@ -47,7 +47,7 @@ void CAutomobileSAInterface::SetPanelDamage(std::uint8_t panelId, bool breakGlas
4747
if ((pHandlingData->uiModelFlags & 0x10000000) != 0) // check bouncePanels flag
4848
return;
4949

50-
if (node != eCarNodes::WINDSCREEN && node != eCarNodes::WING_LF && node != eCarNodes::WING_RF)
50+
if (node != CarNodes::Enum::WINDSCREEN && node != CarNodes::Enum::WING_LF && node != CarNodes::Enum::WING_RF)
5151
{
5252
// Get free bouncing panel
5353
for (auto& panel : m_panels)
@@ -87,3 +87,79 @@ void CAutomobileSAInterface::SetPanelDamage(std::uint8_t panelId, bool breakGlas
8787
}
8888
}
8989
}
90+
91+
void CAutomobileSA::PreRender_End(CAutomobileSAInterface* vehicleInterface)
92+
{
93+
auto* vehicle = pGame->GetPools()->GetVehicle(reinterpret_cast<DWORD*>(vehicleInterface));
94+
if (!vehicle || !vehicle->pEntity)
95+
return;
96+
97+
// Support for default vehicles is still in the GTA code, so we don't need to do it again
98+
if (vehicleInterface->m_nModelIndex == 407 || vehicleInterface->m_nModelIndex == 601)
99+
return;
100+
101+
// Simple turret like in fire truck
102+
if (vehicle->pEntity->IsSpecialFeatureEnabled(VehicleFeatures::Enum::WATER_CANNON) && !vehicle->pEntity->IsSpecialFeatureEnabled(VehicleFeatures::Enum::TURRET))
103+
{
104+
CVehicleSA::SetComponentRotation(vehicleInterface->m_aCarNodes[CarNodes::MISC_A], eComponentRotationAxis::AXIS_X, vehicleInterface->m_fDoomHorizontalRotation, true);
105+
CVehicleSA::SetComponentRotation(vehicleInterface->m_aCarNodes[CarNodes::MISC_A], eComponentRotationAxis::AXIS_Z, vehicleInterface->m_fDoomVerticalRotation, false);
106+
}
107+
108+
// Turret like rhino or swat van
109+
if (vehicle->pEntity->IsSpecialFeatureEnabled(VehicleFeatures::Enum::TURRET))
110+
{
111+
CVehicleSA::SetComponentRotation(vehicleInterface->m_aCarNodes[CarNodes::MISC_A], eComponentRotationAxis::AXIS_Z, vehicleInterface->m_fDoomVerticalRotation, true);
112+
CVehicleSA::SetComponentRotation(vehicleInterface->m_aCarNodes[CarNodes::MISC_B], eComponentRotationAxis::AXIS_X, vehicleInterface->m_fDoomHorizontalRotation, true);
113+
}
114+
}
115+
116+
bool CAutomobileSA::HasFeatureEnabled(CAutomobileSAInterface* vehicleInterface, VehicleFeatures::Enum feature)
117+
{
118+
auto* vehicle = pGame->GetPools()->GetVehicle(reinterpret_cast<DWORD*>(vehicleInterface));
119+
if (!vehicle || !vehicle->pEntity) // This really shouldn't happen
120+
return true;
121+
122+
return vehicle->pEntity->IsSpecialFeatureEnabled(feature);
123+
}
124+
125+
static constexpr std::uintptr_t SKIIP_FIRE_TRUCK = 0x6B1F77;
126+
static constexpr std::uintptr_t CONTINUE_FIRE_TRUCK = 0x6B1F5B;
127+
static constexpr VehicleFeatures::Enum WATER_CANNON_ID = VehicleFeatures::Enum::WATER_CANNON;
128+
static void _declspec(naked) HOOK_CAutomobile_ProcessControl_FireTruckCheck()
129+
{
130+
_asm
131+
{
132+
push WATER_CANNON_ID
133+
push esi
134+
call CAutomobileSA::HasFeatureEnabled
135+
add esp, 8
136+
137+
test al, al
138+
jz skip
139+
140+
jmp CONTINUE_FIRE_TRUCK
141+
142+
skip:
143+
jmp SKIIP_FIRE_TRUCK
144+
}
145+
}
146+
147+
static constexpr std::uintptr_t FINISH_PRE_RENDER = 0x6ACC92;
148+
static void _declspec(naked) HOOK_CAutomobile_PreRender_End()
149+
{
150+
_asm
151+
{
152+
push esi
153+
call CAutomobileSA::PreRender_End
154+
add esp, 4
155+
156+
lea ecx, [esp+94h]
157+
jmp FINISH_PRE_RENDER
158+
}
159+
}
160+
161+
void CAutomobileSA::StaticSetHooks()
162+
{
163+
HookInstall(0x6B1F4B, (DWORD)HOOK_CAutomobile_ProcessControl_FireTruckCheck, 8); // Model check in CAutomobile::ProcessControl
164+
HookInstall(0x6ACC8B, (DWORD)HOOK_CAutomobile_PreRender_End, 7); // The end of the CAutomobile::PreRender function
165+
}

Client/game_sa/CAutomobileSA.h

Lines changed: 95 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -42,97 +42,97 @@ class CAutomobileSAInterface : public CVehicleSAInterface
4242
public:
4343
void SetPanelDamage(std::uint8_t panelId, bool breakGlass, bool spawnFlyingComponent = true);
4444

45-
CObjectSAInterface* SpawnFlyingComponent(const eCarNodes& nodeId, const eCarComponentCollisionTypes& collType)
45+
CObjectSAInterface* SpawnFlyingComponent(const CarNodes::Enum& nodeId, const eCarComponentCollisionTypes& collType)
4646
{
47-
return ((CObjectSAInterface*(__thiscall*)(CAutomobileSAInterface*, eCarNodes, eCarComponentCollisionTypes))0x6a8580)(this, nodeId, collType);
47+
return ((CObjectSAInterface * (__thiscall*)(CAutomobileSAInterface*, CarNodes::Enum, eCarComponentCollisionTypes))0x6a8580)(this, nodeId, collType);
4848
}
4949

50-
CDamageManagerSAInterface m_damageManager;
51-
CDoorSAInterface m_doors[MAX_DOORS];
52-
RwFrame* m_aCarNodes[static_cast<std::size_t>(eCarNodes::NUM_NODES)];
53-
CBouncingPanelSAInterface m_panels[3];
54-
CDoorSAInterface m_swingingChassis;
55-
CColPointSAInterface m_wheelColPoint[MAX_WHEELS];
56-
float m_wheelsDistancesToGround1[4];
57-
float m_wheelsDistancesToGround2[4];
58-
float m_wheelCollisionState[4];
59-
float field_800;
60-
float field_804;
61-
float field_80C;
62-
int m_wheelSkidmarkType[4];
63-
bool m_wheelSkidmarkBloodState[4];
64-
bool m_wheelSkidmarkSomeBool[4];
65-
float m_wheelRotation[4];
66-
float m_wheelPosition[4];
67-
float m_wheelSpeed[4];
68-
int field_858[4];
69-
char taxiAvaliable;
70-
char field_869;
71-
short field_86A;
72-
unsigned short m_wMiscComponentAngle;
73-
unsigned short m_wVoodooSuspension;
74-
int m_dwBusDoorTimerEnd;
75-
int m_dwBusDoorTimerStart;
76-
float field_878;
77-
float wheelOffsetZ[4];
78-
int field_88C[3];
79-
float m_fFrontHeightAboveRoad;
80-
float m_fRearHeightAboveRoad;
81-
float m_fCarTraction;
82-
float m_fNitroValue;
83-
int field_8A4;
84-
int m_fRotationBalance; // used in CHeli::TestSniperCollision
85-
float m_fMoveDirection;
86-
int field_8B4[6];
87-
int field_8C8[6];
88-
float m_fBurningTime;
89-
CEntitySAInterface* m_pWheelCollisionEntity[4];
90-
CVector m_vWheelCollisionPos[4];
91-
char field_924;
92-
char field_925;
93-
char field_926;
94-
char field_927;
95-
char field_928;
96-
char field_929;
97-
char field_92A;
98-
char field_92B;
99-
char field_92C;
100-
char field_92D;
101-
char field_92E;
102-
char field_92F;
103-
char field_930;
104-
char field_931;
105-
char field_932;
106-
char field_933;
107-
char field_934;
108-
char field_935;
109-
char field_936;
110-
char field_937;
111-
char field_938;
112-
char field_939;
113-
char field_93A;
114-
char field_93B;
115-
char field_93C;
116-
char field_93D;
117-
char field_93E;
118-
char field_93F;
119-
int field_940;
120-
int field_944;
121-
float m_fDoomVerticalRotation;
122-
float m_fDoomHorizontalRotation;
123-
float m_fForcedOrientation;
124-
float m_fUpDownLightAngle[2];
125-
unsigned char m_nNumContactWheels;
126-
unsigned char m_nWheelsOnGround;
127-
char field_962;
128-
char field_963;
129-
float field_964;
130-
int m_wheelFrictionState[4];
131-
CFxSystemSAInterface* pNitroParticle[2];
132-
char field_980;
133-
char field_981;
134-
short field_982;
135-
float field_984;
50+
CDamageManagerSAInterface m_damageManager;
51+
CDoorSAInterface m_doors[MAX_DOORS];
52+
std::array<RwFrame*, CarNodes::Enum::NUM_NODES> m_aCarNodes;
53+
CBouncingPanelSAInterface m_panels[3];
54+
CDoorSAInterface m_swingingChassis;
55+
CColPointSAInterface m_wheelColPoint[MAX_WHEELS];
56+
float m_wheelsDistancesToGround1[4];
57+
float m_wheelsDistancesToGround2[4];
58+
float m_wheelCollisionState[4];
59+
float field_800;
60+
float field_804;
61+
float field_80C;
62+
int m_wheelSkidmarkType[4];
63+
bool m_wheelSkidmarkBloodState[4];
64+
bool m_wheelSkidmarkSomeBool[4];
65+
float m_wheelRotation[4];
66+
float m_wheelPosition[4];
67+
float m_wheelSpeed[4];
68+
int field_858[4];
69+
char taxiAvaliable;
70+
char field_869;
71+
short field_86A;
72+
unsigned short m_wMiscComponentAngle;
73+
unsigned short m_wVoodooSuspension;
74+
int m_dwBusDoorTimerEnd;
75+
int m_dwBusDoorTimerStart;
76+
float field_878;
77+
float wheelOffsetZ[4];
78+
int field_88C[3];
79+
float m_fFrontHeightAboveRoad;
80+
float m_fRearHeightAboveRoad;
81+
float m_fCarTraction;
82+
float m_fNitroValue;
83+
int field_8A4;
84+
int m_fRotationBalance; // used in CHeli::TestSniperCollision
85+
float m_fMoveDirection;
86+
int field_8B4[6];
87+
int field_8C8[6];
88+
float m_fBurningTime;
89+
CEntitySAInterface* m_pWheelCollisionEntity[4];
90+
CVector m_vWheelCollisionPos[4];
91+
char field_924;
92+
char field_925;
93+
char field_926;
94+
char field_927;
95+
char field_928;
96+
char field_929;
97+
char field_92A;
98+
char field_92B;
99+
char field_92C;
100+
char field_92D;
101+
char field_92E;
102+
char field_92F;
103+
char field_930;
104+
char field_931;
105+
char field_932;
106+
char field_933;
107+
char field_934;
108+
char field_935;
109+
char field_936;
110+
char field_937;
111+
char field_938;
112+
char field_939;
113+
char field_93A;
114+
char field_93B;
115+
char field_93C;
116+
char field_93D;
117+
char field_93E;
118+
char field_93F;
119+
int field_940;
120+
int field_944;
121+
float m_fDoomVerticalRotation;
122+
float m_fDoomHorizontalRotation;
123+
float m_fForcedOrientation;
124+
float m_fUpDownLightAngle[2];
125+
unsigned char m_nNumContactWheels;
126+
unsigned char m_nWheelsOnGround;
127+
char field_962;
128+
char field_963;
129+
float field_964;
130+
int m_wheelFrictionState[4];
131+
CFxSystemSAInterface* pNitroParticle[2];
132+
char field_980;
133+
char field_981;
134+
short field_982;
135+
float field_984;
136136
};
137137
static_assert(sizeof(CAutomobileSAInterface) == 0x988, "Invalid size for CAutomobileSAInterface");
138138

@@ -143,4 +143,11 @@ class CAutomobileSA : public virtual CAutomobile, public virtual CVehicleSA
143143
CAutomobileSA(CAutomobileSAInterface* pInterface);
144144

145145
CAutomobileSAInterface* GetAutomobileInterface() { return reinterpret_cast<CAutomobileSAInterface*>(GetInterface()); }
146+
147+
static void StaticSetHooks();
148+
149+
private:
150+
static void PreRender_End(CAutomobileSAInterface* vehicleInterface);
151+
152+
static bool HasFeatureEnabled(CAutomobileSAInterface* vehicleInterface, VehicleFeatures::Enum feature);
146153
};

Client/game_sa/CGameSA.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ CGameSA::CGameSA()
250250
CFireSA::StaticSetHooks();
251251
CPtrNodeSingleLinkPoolSA::StaticSetHooks();
252252
CVehicleAudioSettingsManagerSA::StaticSetHooks();
253+
CAutomobileSA::StaticSetHooks();
253254
}
254255
catch (const std::bad_alloc& e)
255256
{

Client/game_sa/CGameSA.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "CPlantManagerSA.h"
2020
#include "CRendererSA.h"
2121
#include "CVehicleAudioSettingsManagerSA.h"
22+
#include "CVehicleSA.h"
2223

2324
class CAnimBlendClumpDataSAInterface;
2425
class CObjectGroupPhysicalPropertiesSA;
@@ -322,6 +323,13 @@ class CGameSA : public CGame
322323

323324
bool SetBuildingPoolSize(size_t size);
324325

326+
bool SetVehicleModelSpecialFeatureEnabled(std::uint16_t model, const VehicleFeatures::Enum& feature, bool enabled) override { return CVehicleSA::SetModelSpecialFeatureEnabled(model, feature, enabled); };
327+
bool IsVehicleModelSpecialFeatureEnabled(std::uint16_t model, const VehicleFeatures::Enum& feature) const override { return CVehicleSA::IsModelSpecialFeatureEnabled(model, feature); };
328+
329+
ModelFeaturesArray GetModelSpecialFeatures(std::uint16_t model) const noexcept override { return CVehicleSA::GetModelSpecialFeatures(model); }
330+
331+
void ResetVehicleModelsSpecialFeatures() const noexcept override { CVehicleSA::ResetVehicleModelsSpecialFeatures(); };
332+
325333
private:
326334
std::unique_ptr<CPools> m_Pools;
327335
CPlayerInfo* m_pPlayerInfo;

0 commit comments

Comments
 (0)