Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #552 Impossible to stop helicopter rotor if it has a driver #3621

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
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
56 changes: 56 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()
FileEX marked this conversation as resolved.
Show resolved Hide resolved
{
_asm
{
mov esi, ecx
mov al, [esi+36h]

pushad
push ecx
call CanProcessFlyingCarStuff
add esp, 4
FileEX marked this conversation as resolved.
Show resolved Hide resolved

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,24 @@ void CVehicleSA::SetTrainSpeed(float fSpeed)
pInterface->m_fTrainSpeed = fSpeed;
}

float CVehicleSA::GetHeliRotorSpeed() const
{
return static_cast<CHeliSAInterface*>(m_pInterface)->m_wheelSpeed[1];
}

void CVehicleSA::SetHeliRotorSpeed(float speed)
FileEX marked this conversation as resolved.
Show resolved Hide resolved
{
static_cast<CHeliSAInterface*>(GetInterface())->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 +1827,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;

FileEX marked this conversation as resolved.
Show resolved Hide resolved
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() const;
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) noexcept
{
if (vehicle->GetVehicleType() != eClientVehicleType::CLIENTVEHICLE_HELI)
return false;

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

bool CLuaVehicleDefs::GetHeliRotorState(CClientVehicle* vehicle) noexcept
{
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) noexcept;
static bool GetHeliRotorState(CClientVehicle* const vehicle) noexcept;

// Components
LUA_DECLARE(SetVehicleComponentPosition);
LUA_DECLARE_OOP(GetVehicleComponentPosition);
Expand Down
4 changes: 3 additions & 1 deletion Client/sdk/game/CVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ class CVehicle : public virtual CPhysical
virtual bool GetTakeLessDamage() = 0;
virtual bool GetTyresDontBurst() = 0;
virtual unsigned short GetAdjustablePropertyValue() = 0;
virtual float GetHeliRotorSpeed() = 0;
virtual float GetHeliRotorSpeed() const = 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
Loading