Skip to content
32 changes: 32 additions & 0 deletions Client/game_sa/CHeliSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,38 @@

class CHeliSAInterface : public CAutomobileSAInterface
{
public:
std::uint8_t m_nHeliFlags; // 0x988
std::uint8_t ___pad1[3]; // 0x989
float m_fLeftRightSkid; // 0x98C
float m_fSteeringUpDown; // 0x990
float m_fSteeringLeftRight; // 0x994
float m_fAccelerationBreakStatus; // 0x998
std::int32_t field_99C; // 0x99C
float m_fRotorZ; // 0x9A0
float m_fSecondRotorZ; // 0x9A4
float m_fMaxAltitude; // 0x9A8
std::int32_t field_9AC; // 0x9AC
float m_fMinAltitude; // 0x9B0
std::int32_t field_9B4; // 0x9B4
std::uint8_t field_9B8; // 0x9B8
std::uint8_t m_nNumSwatOccupants; // 0x9B9
std::uint8_t m_anSwatIDs[4]; // 0x9BA
std::uint8_t ___pad2[2]; // 0x9BE
std::uint32_t field_9C0[4]; // 0x9C0
std::int32_t field_9D0; // 0x9D0
FxSystem_c** m_pParticlesList; // 0x9D4
std::uint8_t field_9D8[24]; // 0x9D8
std::int32_t field_9F0; // 0x9F0
CVector m_vecSearchLightTarget; // 0x9F4
float m_fSearchLightIntensity; // 0xA00
std::int32_t field_A04; // 0xA04
std::int32_t field_A08; // 0xA08
FxSystem_c** m_ppGunflashFx; // 0xA0C
std::uint8_t m_nFiringMultiplier; // 0xA10
bool m_bSearchLightEnabled; // 0xA11
std::uint8_t ___pad3[2]; // 0xA12
std::int32_t field_A14; // 0xA14
};

class CHeliSA final : public virtual CHeli, public virtual CAutomobileSA
Expand Down
58 changes: 58 additions & 0 deletions Client/game_sa/CVehicleSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "CProjectileInfoSA.h"
#include "CTrainSA.h"
#include "CPlaneSA.h"
#include "CHeliSA.h"
#include "CVehicleSA.h"
#include "CVisibilityPluginsSA.h"
#include "CWorldSA.h"
Expand Down Expand Up @@ -51,6 +52,40 @@ void _declspec(naked) HOOK_Vehicle_PreRender(void)
}
}

bool CanProcessFlyingCarStuff(CHeliSAInterface* heliInterface)
{
SClientEntity<CVehicleSA>* vehicle = pGame->GetPools()->GetVehicle((DWORD*)heliInterface);
if (!vehicle || !vehicle->pEntity)
return true;

return vehicle->pEntity->GetHeliRotorState();
}

void _declspec(naked) HOOK_CHeli_ProcessFlyingCarStuff()
{
_asm
{
mov esi, ecx
mov al, [esi+36h]

pushad
push ecx
call CanProcessFlyingCarStuff
add esp, 4

movzx eax, al
test eax, eax
jz skip

popad
jmp CONTINUE_CHeli_ProcessFlyingCarStuff

skip:
popad
jmp RETURN_CHeli_ProcessFlyingCarStuff
}
}

namespace
{
bool ClumpDumpCB(RpAtomic* pAtomic, void* data)
Expand Down Expand Up @@ -489,6 +524,26 @@ void CVehicleSA::SetTrainSpeed(float fSpeed)
pInterface->m_fTrainSpeed = fSpeed;
}

float CVehicleSA::GetHeliRotorSpeed()
{
auto* heliInterface = static_cast<CHeliSAInterface*>(GetInterface());
return heliInterface->m_wheelSpeed[1];
}

void CVehicleSA::SetHeliRotorSpeed(float speed)
{
auto* heliInterface = static_cast<CHeliSAInterface*>(GetInterface());
heliInterface->m_wheelSpeed[1] = speed;
}

void CVehicleSA::SetHeliRotorState(bool state, bool stopRotor) noexcept
{
m_heliRotorState = state;

if (!state && stopRotor)
SetHeliRotorSpeed(0.0f);
}

void CVehicleSA::SetPlaneRotorSpeed(float fSpeed)
{
auto pInterface = static_cast<CPlaneSAInterface*>(GetInterface());
Expand Down Expand Up @@ -1774,6 +1829,9 @@ void CVehicleSA::StaticSetHooks()
{
// Setup vehicle sun glare hook
HookInstall(FUNC_CAutomobile_OnVehiclePreRender, (DWORD)HOOK_Vehicle_PreRender, 5);

// Setup hook to handle setHelicopterRotorState function
HookInstall(FUNC_CHeli_ProcessFlyingCarStuff, (DWORD)HOOK_CHeli_ProcessFlyingCarStuff, 5);
}

void CVehicleSA::SetVehiclesSunGlareEnabled(bool bEnabled)
Expand Down
12 changes: 10 additions & 2 deletions Client/game_sa/CVehicleSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ struct RwTexture;
#define FUNC_CAutomobile_OnVehiclePreRender 0x6ABCFD
#define FUNC_CVehicle_DoSunGlare 0x6DD6F0

#define FUNC_CHeli_ProcessFlyingCarStuff 0x6C4E7D

static constexpr DWORD CONTINUE_CHeli_ProcessFlyingCarStuff = 0x6C4E82;
static constexpr DWORD RETURN_CHeli_ProcessFlyingCarStuff = 0x6C5404;

struct SRailNodeSA
{
short sX; // x coordinate times 8
Expand Down Expand Up @@ -410,6 +415,7 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA
unsigned char m_ucVariant2;
unsigned char m_ucVariantCount{0};
bool m_doorsUndamageable{false};
bool m_heliRotorState{true};

std::array<CVector, VEHICLE_DUMMY_COUNT> m_dummyPositions;

Expand Down Expand Up @@ -540,7 +546,8 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA
bool GetTakeLessDamage() { return GetVehicleInterface()->m_nVehicleFlags.bTakeLessDamage; };
bool GetTyresDontBurst() { return GetVehicleInterface()->m_nVehicleFlags.bTyresDontBurst; };
unsigned short GetAdjustablePropertyValue() { return *reinterpret_cast<unsigned short*>(reinterpret_cast<unsigned long>(m_pInterface) + 2156); };
float GetHeliRotorSpeed() { return *reinterpret_cast<float*>(reinterpret_cast<unsigned int>(m_pInterface) + 2124); };
float GetHeliRotorSpeed();
bool GetHeliRotorState() const noexcept override { return m_heliRotorState; }
float GetPlaneRotorSpeed();

unsigned long GetExplodeTime() { return *reinterpret_cast<unsigned long*>(reinterpret_cast<unsigned int>(m_pInterface) + 1240); };
Expand All @@ -566,7 +573,8 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA
{
*reinterpret_cast<unsigned short*>(reinterpret_cast<unsigned int>(m_pInterface) + 2156) = usAdjustableProperty;
};
void SetHeliRotorSpeed(float fSpeed) { *reinterpret_cast<float*>(reinterpret_cast<unsigned int>(m_pInterface) + 2124) = fSpeed; };
void SetHeliRotorSpeed(float speed);
void SetHeliRotorState(bool state, bool stopRotor) noexcept override;
void SetPlaneRotorSpeed(float fSpeed);
bool SetVehicleWheelRotation(float fWheelRot1, float fWheelRot2, float fWheelRot3, float fWheelRot4) noexcept;
void SetExplodeTime(unsigned long ulTime) { *reinterpret_cast<unsigned long*>(reinterpret_cast<unsigned int>(m_pInterface) + 1240) = ulTime; };
Expand Down
13 changes: 13 additions & 0 deletions Client/mods/deathmatch/logic/CClientVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,19 @@ void CClientVehicle::SetHeliRotorSpeed(float fSpeed)
m_fHeliRotorSpeed = fSpeed;
}

bool CClientVehicle::GetHeliRotorState() const noexcept
{
return m_pVehicle && m_eVehicleType == CLIENTVEHICLE_HELI ? m_pVehicle->GetHeliRotorState() : m_heliRotorState;
}

void CClientVehicle::SetHeliRotorState(bool state, bool stopRotor) noexcept
{
if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_HELI)
m_pVehicle->SetHeliRotorState(state, stopRotor);

m_heliRotorState = state;
}

void CClientVehicle::SetPlaneRotorSpeed(float fSpeed)
{
if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_PLANE)
Expand Down
3 changes: 3 additions & 0 deletions Client/mods/deathmatch/logic/CClientVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,12 @@ class CClientVehicle : public CClientStreamElement
// TODO: Make the class remember on virtualization
float GetHeliRotorSpeed();
float GetPlaneRotorSpeed();
bool GetHeliRotorState() const noexcept;

bool GetRotorSpeed(float&);
bool SetRotorSpeed(float);
bool SetWheelsRotation(float fRot1, float fRot2, float fRot3, float fRot4) noexcept;
void SetHeliRotorState(bool state, bool stopRotor) noexcept;
void SetHeliRotorSpeed(float fSpeed);
void SetPlaneRotorSpeed(float fSpeed);
bool IsHeliSearchLightVisible();
Expand Down Expand Up @@ -671,6 +673,7 @@ class CClientVehicle : public CClientStreamElement
uchar m_ucTrackID;
bool m_bJustStreamedIn;
bool m_bWheelScaleChanged;
bool m_heliRotorState{true};

// Time dependent error compensation interpolation
struct
Expand Down
19 changes: 19 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void CLuaVehicleDefs::LoadFunctions()
{"getVehicleModelWheelSize", ArgumentParser<GetVehicleModelWheelSize>},
{"getVehicleWheelFrictionState", ArgumentParser<GetVehicleWheelFrictionState>},
{"getVehicleEntryPoints", ArgumentParser<GetVehicleEntryPoints>},
{"getHelicopterRotorState", ArgumentParser<GetHeliRotorState>},

// Vehicle set funcs
{"createVehicle", CreateVehicle},
Expand Down Expand Up @@ -155,6 +156,7 @@ void CLuaVehicleDefs::LoadFunctions()
{"setVehicleVariant", ArgumentParser<SetVehicleVariant>},
{"setVehicleWheelScale", ArgumentParser<SetVehicleWheelScale>},
{"setVehicleModelWheelSize", ArgumentParser<SetVehicleModelWheelSize>},
{"setHelicopterRotorState", ArgumentParser<SetHeliRotorState>},
};

// Add functions
Expand Down Expand Up @@ -243,6 +245,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM)
lua_classfunction(luaVM, "getModelWheelSize", "getVehicleModelWheelSize");
lua_classfunction(luaVM, "getWheelFrictionState", "getVehicleWheelFrictionState");
lua_classfunction(luaVM, "getEntryPoints", ArgumentParser<OOP_GetVehicleEntryPoints>);
lua_classfunction(luaVM, "getRotorState", "getHelicopterRotorState");

lua_classfunction(luaVM, "setComponentVisible", "setVehicleComponentVisible");
lua_classfunction(luaVM, "setSirensOn", "setVehicleSirensOn");
Expand Down Expand Up @@ -291,6 +294,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM)
lua_classfunction(luaVM, "setVariant", "setVehicleVariant");
lua_classfunction(luaVM, "setWheelScale", "setVehicleWheelScale");
lua_classfunction(luaVM, "setModelWheelSize", "setVehicleModelWheelSize");
lua_classfunction(luaVM, "setRotorState", "setHelicopterRotorState");

lua_classfunction(luaVM, "resetComponentPosition", "resetVehicleComponentPosition");
lua_classfunction(luaVM, "resetComponentRotation", "resetVehicleComponentRotation");
Expand Down Expand Up @@ -347,6 +351,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM)
lua_classvariable(luaVM, "gravity", SetVehicleGravity, OOP_GetVehicleGravity);
lua_classvariable(luaVM, "turnVelocity", SetVehicleTurnVelocity, OOP_GetVehicleTurnVelocity);
lua_classvariable(luaVM, "wheelScale", "setVehicleWheelScale", "getVehicleWheelScale");
lua_classvariable(luaVM, "rotorState", "setHelicopterRotorState", "getHelicopterRotorState");

lua_registerclass(luaVM, "Vehicle", "Element");
}
Expand Down Expand Up @@ -4273,3 +4278,17 @@ std::variant<bool, std::array<CVector, 4>> CLuaVehicleDefs::OOP_GetVehicleEntryP

return entryPoints;
}

bool CLuaVehicleDefs::SetHeliRotorState(CClientVehicle* vehicle, bool state, std::optional<bool> stopRotor)
{
if (vehicle->GetVehicleType() != eClientVehicleType::CLIENTVEHICLE_HELI)
return false;

vehicle->SetHeliRotorState(state, stopRotor.value_or(true));
return true;
}

bool CLuaVehicleDefs::GetHeliRotorState(CClientVehicle* vehicle)
{
return vehicle->GetHeliRotorState();
}
3 changes: 3 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ class CLuaVehicleDefs : public CLuaDefs
static bool SetVehicleModelWheelSize(const unsigned short usModel, const eResizableVehicleWheelGroup eWheelGroup, const float fWheelSize);
static int GetVehicleWheelFrictionState(CClientVehicle* pVehicle, unsigned char wheel);

static bool SetHeliRotorState(CClientVehicle* const vehicle, bool state, std::optional<bool> stopRotor);
static bool GetHeliRotorState(CClientVehicle* const vehicle);

// Components
LUA_DECLARE(SetVehicleComponentPosition);
LUA_DECLARE_OOP(GetVehicleComponentPosition);
Expand Down
2 changes: 2 additions & 0 deletions Client/sdk/game/CVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class CVehicle : public virtual CPhysical
virtual bool GetTyresDontBurst() = 0;
virtual unsigned short GetAdjustablePropertyValue() = 0;
virtual float GetHeliRotorSpeed() = 0;
virtual bool GetHeliRotorState() const noexcept = 0;
virtual float GetPlaneRotorSpeed() = 0;
virtual unsigned long GetExplodeTime() = 0;

Expand All @@ -220,6 +221,7 @@ class CVehicle : public virtual CPhysical
virtual void SetTyresDontBurst(bool bTyresDontBurst) = 0;
virtual void SetAdjustablePropertyValue(unsigned short usAdjustableProperty) = 0;
virtual void SetHeliRotorSpeed(float fSpeed) = 0;
virtual void SetHeliRotorState(bool state, bool stopRotor) noexcept = 0;
virtual void SetPlaneRotorSpeed(float fSpeed) = 0;
virtual bool SetVehicleWheelRotation(float fRot1, float fRot2, float fRot3, float fRot4) noexcept = 0;
virtual void SetTaxiLightOn(bool bLightState) = 0;
Expand Down