From c3eb37ed0a0625edd46ef4ad0bc4981b2c4437ce Mon Sep 17 00:00:00 2001 From: samr46 Date: Thu, 29 May 2025 13:19:22 +0300 Subject: [PATCH 1/7] Add new world special property (vehenginemanualmode) --- Client/game_sa/CGameSA.cpp | 14 ++++++++++ Client/game_sa/CGameSA.h | 2 ++ Client/game_sa/CVehicleSA.cpp | 28 ++++++++++++++++++- Client/mods/deathmatch/logic/CClientGame.cpp | 17 +++++++++++ Client/mods/deathmatch/logic/CClientGame.h | 5 ++++ .../logic/CClientVehicleManager.cpp | 17 +++++++++++ .../deathmatch/logic/CClientVehicleManager.h | 2 ++ .../mods/deathmatch/logic/CPacketHandler.cpp | 1 + Client/sdk/game/CGame.h | 2 ++ Server/mods/deathmatch/logic/CGame.cpp | 5 +++- .../logic/CStaticFunctionDefinitions.cpp | 2 +- .../logic/packets/CMapInfoPacket.cpp | 1 + Shared/mods/deathmatch/logic/Enums.cpp | 1 + Shared/mods/deathmatch/logic/Enums.h | 1 + Shared/sdk/net/SyncStructures.h | 18 ++++++++++++ Shared/sdk/net/bitstream.h | 4 +++ 16 files changed, 117 insertions(+), 3 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 7cac177f422..ef8d9cf687b 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -930,6 +930,20 @@ void CGameSA::SetVehicleBurnExplosionsEnabled(bool isEnabled) m_isVehicleBurnExplosionsEnabled = isEnabled; } +void CGameSA::SetVehicleEngineManualModeEnabled(bool isEnabled) +{ + if (isEnabled) + { + MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) + MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) + } + else + { + MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); + MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); + } +} + bool CGameSA::PerformChecks() { std::map::iterator it; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 9ed552b92d8..a97b6011a9e 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -262,6 +262,8 @@ class CGameSA : public CGame bool IsVehicleBurnExplosionsEnabled() const noexcept override { return m_isVehicleBurnExplosionsEnabled; } void SetVehicleBurnExplosionsEnabled(bool isEnabled) override; + void SetVehicleEngineManualModeEnabled(bool isEnabled) override; + unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 761ae58535a..b73e5704e18 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -54,13 +54,39 @@ void _declspec(naked) HOOK_Vehicle_PreRender(void) } } +float& fTimeStep = *(float*)(0xB7CB5C); static bool __fastcall CanProcessFlyingCarStuff(CAutomobileSAInterface* vehicleInterface) { SClientEntity* vehicle = pGame->GetPools()->GetVehicle((DWORD*)vehicleInterface); if (!vehicle || !vehicle->pEntity) return true; - return vehicle->pEntity->GetVehicleRotorState(); + if (vehicle->pEntity->GetVehicleRotorState()) + { + if (*(unsigned char*)0x64BC03 == 0x75) // keep default behavior + return true; + + if (vehicle->pEntity->GetEntityStatus() != eEntityStatus::STATUS_PHYSICS && !vehicle->pEntity->IsBeingDriven()) + { + vehicle->pEntity->SetEntityStatus(eEntityStatus::STATUS_PHYSICS); // this will make rotors spin without driver when engine is on + return false; + } + if (!vehicle->pEntity->IsEngineOn()) + { + // Smoothly change rotors speed to 0 + float speed = vehicle->pEntity->GetHeliRotorSpeed(); + if (speed > 0) + vehicle->pEntity->SetHeliRotorSpeed(std::max(0.0f, speed - fTimeStep * 0.00055f)); // 0x6C4EB7 + + speed = vehicle->pEntity->GetPlaneRotorSpeed(); + if (speed > 0) + vehicle->pEntity->SetPlaneRotorSpeed(std::max(0.0f, speed - fTimeStep * 0.003f)); // 0x6CC145 + + return false; + } + return true; + } + return false; } static constexpr DWORD CONTINUE_CHeli_ProcessFlyingCarStuff = 0x6C4E82; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index a83905d473a..cb3cf3e1a84 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6057,6 +6057,9 @@ bool CClientGame::SetWorldSpecialProperty(const WorldSpecialProperty property, c case WorldSpecialProperty::VEHICLEBURNEXPLOSIONS: g_pGame->SetVehicleBurnExplosionsEnabled(enabled); break; + case WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE: + SetVehicleEngineManualModeEnabled(enabled); + break; default: return false; } @@ -6103,6 +6106,8 @@ bool CClientGame::IsWorldSpecialProperty(const WorldSpecialProperty property) return m_pVehicleManager->IsSpawnFlyingComponentEnabled(); case WorldSpecialProperty::VEHICLEBURNEXPLOSIONS: return g_pGame->IsVehicleBurnExplosionsEnabled(); + case WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE: + return IsVehicleEngineManualModeEnabled(); } return false; @@ -6138,6 +6143,17 @@ bool CClientGame::IsWeaponRenderEnabled() const return g_pGame->IsWeaponRenderEnabled(); } +void CClientGame::SetVehicleEngineManualModeEnabled(bool isEnabled) +{ + if (isEnabled == m_isVehEngineManualModeEnabled) + return; + + g_pGame->SetVehicleEngineManualModeEnabled(isEnabled); + m_pVehicleManager->ResetNotControlledRotors(isEnabled); + + m_isVehEngineManualModeEnabled = isEnabled; +} + #pragma code_seg(".text") bool CClientGame::VerifySADataFiles(int iEnableClientChecks) { @@ -6823,6 +6839,7 @@ void CClientGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo g_pGame->SetIgnoreFireStateEnabled(false); m_pVehicleManager->SetSpawnFlyingComponentEnabled(true); g_pGame->SetVehicleBurnExplosionsEnabled(true); + SetVehicleEngineManualModeEnabled(false); } // Reset all setWorldProperty to default diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 9780a185c26..b0b9a47e5c6 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -426,6 +426,9 @@ class CClientGame void SetWeaponRenderEnabled(bool enabled); bool IsWeaponRenderEnabled() const; + bool IsVehicleEngineManualModeEnabled() const noexcept { return m_isVehEngineManualModeEnabled; } + void SetVehicleEngineManualModeEnabled(bool isEnabled); + void ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo); CTransferBox* GetTransferBox() { return m_pTransferBox; }; @@ -784,6 +787,8 @@ class CClientGame // Birds Enabled bool m_bBirdsEnabled; + bool m_isVehEngineManualModeEnabled{false}; + unsigned long m_ulMinuteDuration; CClientGUIElement* m_pClickedGUIElement; diff --git a/Client/mods/deathmatch/logic/CClientVehicleManager.cpp b/Client/mods/deathmatch/logic/CClientVehicleManager.cpp index 3a9494def90..6209b9a43b5 100644 --- a/Client/mods/deathmatch/logic/CClientVehicleManager.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicleManager.cpp @@ -791,3 +791,20 @@ void CClientVehicleManager::RestreamVehicleUpgrades(unsigned short usModel) pVehicle->GetUpgrades()->RestreamVehicleUpgrades(usModel); } } + +void CClientVehicleManager::ResetNotControlledRotors(bool isManualMode) +{ + // Reset rotors to custom or original state for loaded vehicles without controller + // Custom state allows rotors to spin without driver inside (if engine is on) + eEntityStatus status = isManualMode ? eEntityStatus::STATUS_PHYSICS : eEntityStatus::STATUS_ABANDONED; + for (auto& pVehicle : m_List) + { + if (pVehicle->GetGameEntity() && pVehicle->GetVehicleRotorState() && !pVehicle->IsDriven()) + { + float speed = (isManualMode && pVehicle->IsEngineOn()) ? 0.001f : 0.0f; + pVehicle->GetGameEntity()->SetEntityStatus(status); + pVehicle->SetHeliRotorSpeed(speed); + pVehicle->SetPlaneRotorSpeed(speed); + } + } +} diff --git a/Client/mods/deathmatch/logic/CClientVehicleManager.h b/Client/mods/deathmatch/logic/CClientVehicleManager.h index 5f0ad55f615..567870d7524 100644 --- a/Client/mods/deathmatch/logic/CClientVehicleManager.h +++ b/Client/mods/deathmatch/logic/CClientVehicleManager.h @@ -73,6 +73,8 @@ class CClientVehicleManager bool IsSpawnFlyingComponentEnabled() const noexcept { return m_spawnFlyingComponentsDuringRecreate; } void SetSpawnFlyingComponentEnabled(bool isEnabled) noexcept { m_spawnFlyingComponentsDuringRecreate = isEnabled; } + void ResetNotControlledRotors(bool isManualMode); + protected: CClientManager* m_pManager; bool m_bCanRemoveFromList; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index f14c2819788..94147e9047c 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -2402,6 +2402,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FLYINGCOMPONENTS, wsProps.data7.flyingcomponents); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, wsProps.data8.vehicleburnexplosions); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, wsProps.data9.vehEngineManualMode); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index baa6103e100..7bca36be21c 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -241,6 +241,8 @@ class __declspec(novtable) CGame virtual bool IsVehicleBurnExplosionsEnabled() const noexcept = 0; virtual void SetVehicleBurnExplosionsEnabled(bool isEnabled) = 0; + virtual void SetVehicleEngineManualModeEnabled(bool isEnabled) = 0; + virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 442f12b22bc..25bcfbc5011 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -263,6 +263,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::IGNOREFIRESTATE] = false; m_WorldSpecialProps[WorldSpecialProperty::FLYINGCOMPONENTS] = true; m_WorldSpecialProps[WorldSpecialProperty::VEHICLEBURNEXPLOSIONS] = true; + m_WorldSpecialProps[WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE] = false; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; @@ -3405,7 +3406,8 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); // Update our engine State - pVehicle->SetEngineOn(true); + if (!g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE)) + pVehicle->SetEngineOn(true); // Tell everyone he's in (they should warp him in) CVehicleInOutPacket Reply(PedID, VehicleID, ucOccupiedSeat, VEHICLE_NOTIFY_IN_RETURN); @@ -4524,6 +4526,7 @@ void CGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo) g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE, false); g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::FLYINGCOMPONENTS, true); g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, false); } // Reset all weather stuff like heat haze, wind velocity etc diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index ad64816a6dd..61fab6c6f30 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -4262,7 +4262,7 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CPed* pPed, CVehicle* pVehic pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); // If he's the driver, switch on the engine - if (uiSeat == 0) + if (uiSeat == 0 && !g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE)) pVehicle->SetEngineOn(true); // Tell all the players diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index 08db7a8dc38..2d3d4c2bf53 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -195,6 +195,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data6.ignoreFireState = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE); wsProps.data7.flyingcomponents = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FLYINGCOMPONENTS); wsProps.data8.vehicleburnexplosions = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS); + wsProps.data9.vehEngineManualMode = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE); BitStream.Write(&wsProps); } diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index a531fdb8425..2a0aa3a7f1a 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -119,6 +119,7 @@ ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") ADD_ENUM(WorldSpecialProperty::IGNOREFIRESTATE, "ignorefirestate") ADD_ENUM(WorldSpecialProperty::FLYINGCOMPONENTS, "flyingcomponents") ADD_ENUM(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, "vehicleburnexplosions") +ADD_ENUM(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, "vehenginemanualmode") IMPLEMENT_ENUM_CLASS_END("world-special-property") IMPLEMENT_ENUM_BEGIN(ePacketID) diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index 2b845f25a67..2c266559f70 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -96,6 +96,7 @@ enum class WorldSpecialProperty IGNOREFIRESTATE, FLYINGCOMPONENTS, VEHICLEBURNEXPLOSIONS, + VEHICLE_ENGINE_MANUAL_MODE, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 55887dd42c8..14db97bd3c2 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2083,6 +2083,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT8 = 1 }; + enum + { + BITCOUNT9 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2121,6 +2125,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure isOK &= bitStream.ReadBits(reinterpret_cast(&data8), BITCOUNT8); else data8.vehicleburnexplosions = true; + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineManualMode)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); + else + data9.vehEngineManualMode = false; //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) @@ -2154,6 +2163,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleBurnExplosions)) bitStream.WriteBits(reinterpret_cast(&data8), BITCOUNT8); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineManualMode)) + bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2210,6 +2222,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { bool vehicleburnexplosions : 1; } data8; + + struct + { + bool vehEngineManualMode : 1; + } data9; SWorldSpecialPropertiesStateSync() { @@ -2233,6 +2250,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data6.ignoreFireState = false; data7.flyingcomponents = true; data8.vehicleburnexplosions = true; + data9.vehEngineManualMode = false; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index f8a4058f572..fd8494723d7 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -620,6 +620,10 @@ enum class eBitStreamVersion : unsigned short // 2025-05-26 ServersideBuildingElement, + // Add "vehenginemanualmode" to setWorldSpecialPropertyEnabled + // 2025-05-29 + WorldSpecialProperty_VehicleEngineManualMode, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next, From 8e999e386aaddbed8d6c727b53dfffe8927e78cb Mon Sep 17 00:00:00 2001 From: samr46 Date: Thu, 29 May 2025 17:15:46 +0300 Subject: [PATCH 2/7] Move SetVehicleEngineManualModeEnabled() to appropriate module --- Client/game_sa/CGameSA.cpp | 14 -------------- Client/game_sa/CGameSA.h | 2 +- Client/game_sa/CVehicleSA.cpp | 2 +- Client/mods/deathmatch/logic/CClientGame.cpp | 13 ++++++++----- Client/mods/deathmatch/logic/CClientGame.h | 6 ++---- Client/multiplayer_sa/CMultiplayerSA.cpp | 14 ++++++++++++++ Client/multiplayer_sa/CMultiplayerSA.h | 2 ++ Client/sdk/game/CGame.h | 2 +- Client/sdk/multiplayer/CMultiplayer.h | 2 ++ 9 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index ef8d9cf687b..7cac177f422 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -930,20 +930,6 @@ void CGameSA::SetVehicleBurnExplosionsEnabled(bool isEnabled) m_isVehicleBurnExplosionsEnabled = isEnabled; } -void CGameSA::SetVehicleEngineManualModeEnabled(bool isEnabled) -{ - if (isEnabled) - { - MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) - MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) - } - else - { - MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); - MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); - } -} - bool CGameSA::PerformChecks() { std::map::iterator it; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index a97b6011a9e..481fc35ec02 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -262,7 +262,7 @@ class CGameSA : public CGame bool IsVehicleBurnExplosionsEnabled() const noexcept override { return m_isVehicleBurnExplosionsEnabled; } void SetVehicleBurnExplosionsEnabled(bool isEnabled) override; - void SetVehicleEngineManualModeEnabled(bool isEnabled) override; + bool IsVehicleEngineManualModeEnabled() const noexcept override { return *(unsigned char*)0x64BC03 == 0x90; } unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index b73e5704e18..6a2d88c28b6 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -63,7 +63,7 @@ static bool __fastcall CanProcessFlyingCarStuff(CAutomobileSAInterface* vehicleI if (vehicle->pEntity->GetVehicleRotorState()) { - if (*(unsigned char*)0x64BC03 == 0x75) // keep default behavior + if (!pGame->IsVehicleEngineManualModeEnabled()) // keep default behavior return true; if (vehicle->pEntity->GetEntityStatus() != eEntityStatus::STATUS_PHYSICS && !vehicle->pEntity->IsBeingDriven()) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index cb3cf3e1a84..5ec64406ee1 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6143,15 +6143,18 @@ bool CClientGame::IsWeaponRenderEnabled() const return g_pGame->IsWeaponRenderEnabled(); } -void CClientGame::SetVehicleEngineManualModeEnabled(bool isEnabled) +void CClientGame::SetVehicleEngineManualModeEnabled(bool enabled) { - if (isEnabled == m_isVehEngineManualModeEnabled) + if (enabled == g_pGame->IsVehicleEngineManualModeEnabled()) return; - g_pGame->SetVehicleEngineManualModeEnabled(isEnabled); - m_pVehicleManager->ResetNotControlledRotors(isEnabled); + g_pMultiplayer->SetVehicleEngineManualModeEnabled(enabled); + m_pVehicleManager->ResetNotControlledRotors(enabled); +} - m_isVehEngineManualModeEnabled = isEnabled; +bool CClientGame::IsVehicleEngineManualModeEnabled() const +{ + return g_pGame->IsVehicleEngineManualModeEnabled(); } #pragma code_seg(".text") diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index b0b9a47e5c6..99d47ffdb4c 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -426,8 +426,8 @@ class CClientGame void SetWeaponRenderEnabled(bool enabled); bool IsWeaponRenderEnabled() const; - bool IsVehicleEngineManualModeEnabled() const noexcept { return m_isVehEngineManualModeEnabled; } - void SetVehicleEngineManualModeEnabled(bool isEnabled); + void SetVehicleEngineManualModeEnabled(bool enabled); + bool IsVehicleEngineManualModeEnabled() const; void ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo); @@ -787,8 +787,6 @@ class CClientGame // Birds Enabled bool m_bBirdsEnabled; - bool m_isVehEngineManualModeEnabled{false}; - unsigned long m_ulMinuteDuration; CClientGUIElement* m_pClickedGUIElement; diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 8ac305efca0..afc41f502eb 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -6634,6 +6634,20 @@ void CMultiplayerSA::SetAutomaticVehicleStartupOnPedEnter(bool bSet) MemSet((char*)0x64BC0D, 0x90, 6); } +void CMultiplayerSA::SetVehicleEngineManualModeEnabled(bool enabled) +{ + if (enabled) + { + MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) + MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) + } + else + { + MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); + MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); + } +} + // Storage CVehicleSAInterface* pHeliKiller = NULL; CEntitySAInterface* pHitByHeli = NULL; diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 7a48e561061..9d1091938aa 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -333,6 +333,8 @@ class CMultiplayerSA : public CMultiplayer void SetAutomaticVehicleStartupOnPedEnter(bool bSet); + void SetVehicleEngineManualModeEnabled(bool enabled) override; + void SetPedTargetingMarkerEnabled(bool bEnable); bool IsPedTargetingMarkerEnabled(); bool IsConnected(); diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 7bca36be21c..257a66fafa7 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -241,7 +241,7 @@ class __declspec(novtable) CGame virtual bool IsVehicleBurnExplosionsEnabled() const noexcept = 0; virtual void SetVehicleBurnExplosionsEnabled(bool isEnabled) = 0; - virtual void SetVehicleEngineManualModeEnabled(bool isEnabled) = 0; + virtual bool IsVehicleEngineManualModeEnabled() const noexcept = 0; virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 8895234df23..c1524d7bd95 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -444,6 +444,8 @@ class CMultiplayer virtual void SetAutomaticVehicleStartupOnPedEnter(bool bSet) = 0; + virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; + virtual void SetPedTargetingMarkerEnabled(bool bEnabled) = 0; virtual bool IsPedTargetingMarkerEnabled() = 0; From 79f53bd8fca444ff732587de61509e7117521174 Mon Sep 17 00:00:00 2001 From: samr46 Date: Fri, 30 May 2025 13:17:52 +0300 Subject: [PATCH 3/7] Restore original implementation of SetVehicleEngineManualModeEnabled() --- Client/game_sa/CGameSA.cpp | 19 +++++++++++++++++++ Client/game_sa/CGameSA.h | 4 +++- Client/mods/deathmatch/logic/CClientGame.cpp | 2 +- Client/multiplayer_sa/CMultiplayerSA.cpp | 14 -------------- Client/multiplayer_sa/CMultiplayerSA.h | 2 -- Client/sdk/game/CGame.h | 1 + Client/sdk/multiplayer/CMultiplayer.h | 2 -- 7 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 7cac177f422..7ea533ae674 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -930,6 +930,25 @@ void CGameSA::SetVehicleBurnExplosionsEnabled(bool isEnabled) m_isVehicleBurnExplosionsEnabled = isEnabled; } +void CGameSA::SetVehicleEngineManualModeEnabled(bool enabled) +{ + if (enabled == m_isVehicleEngineManualModeEnabled) + return; + + if (enabled) + { + MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) + MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) + } + else + { + MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); + MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); + } + + m_isVehicleEngineManualModeEnabled = enabled; +} + bool CGameSA::PerformChecks() { std::map::iterator it; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 481fc35ec02..666608e0147 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -262,7 +262,8 @@ class CGameSA : public CGame bool IsVehicleBurnExplosionsEnabled() const noexcept override { return m_isVehicleBurnExplosionsEnabled; } void SetVehicleBurnExplosionsEnabled(bool isEnabled) override; - bool IsVehicleEngineManualModeEnabled() const noexcept override { return *(unsigned char*)0x64BC03 == 0x90; } + bool IsVehicleEngineManualModeEnabled() const noexcept override { return m_isVehicleEngineManualModeEnabled; } + void SetVehicleEngineManualModeEnabled(bool enabled) override; unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -396,6 +397,7 @@ class CGameSA : public CGame bool m_isExtendedWaterCannonsEnabled{false}; bool m_isIgnoreFireStateEnabled{false}; bool m_isVehicleBurnExplosionsEnabled{true}; + bool m_isVehicleEngineManualModeEnabled{false}; static unsigned int& ClumpOffset; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 5ec64406ee1..dfe203b4366 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6148,7 +6148,7 @@ void CClientGame::SetVehicleEngineManualModeEnabled(bool enabled) if (enabled == g_pGame->IsVehicleEngineManualModeEnabled()) return; - g_pMultiplayer->SetVehicleEngineManualModeEnabled(enabled); + g_pGame->SetVehicleEngineManualModeEnabled(enabled); m_pVehicleManager->ResetNotControlledRotors(enabled); } diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index afc41f502eb..8ac305efca0 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -6634,20 +6634,6 @@ void CMultiplayerSA::SetAutomaticVehicleStartupOnPedEnter(bool bSet) MemSet((char*)0x64BC0D, 0x90, 6); } -void CMultiplayerSA::SetVehicleEngineManualModeEnabled(bool enabled) -{ - if (enabled) - { - MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) - MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) - } - else - { - MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); - MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); - } -} - // Storage CVehicleSAInterface* pHeliKiller = NULL; CEntitySAInterface* pHitByHeli = NULL; diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 9d1091938aa..7a48e561061 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -333,8 +333,6 @@ class CMultiplayerSA : public CMultiplayer void SetAutomaticVehicleStartupOnPedEnter(bool bSet); - void SetVehicleEngineManualModeEnabled(bool enabled) override; - void SetPedTargetingMarkerEnabled(bool bEnable); bool IsPedTargetingMarkerEnabled(); bool IsConnected(); diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 257a66fafa7..4941af690e4 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -241,6 +241,7 @@ class __declspec(novtable) CGame virtual bool IsVehicleBurnExplosionsEnabled() const noexcept = 0; virtual void SetVehicleBurnExplosionsEnabled(bool isEnabled) = 0; + virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; virtual bool IsVehicleEngineManualModeEnabled() const noexcept = 0; virtual CWeapon* CreateWeapon() = 0; diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index c1524d7bd95..8895234df23 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -444,8 +444,6 @@ class CMultiplayer virtual void SetAutomaticVehicleStartupOnPedEnter(bool bSet) = 0; - virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; - virtual void SetPedTargetingMarkerEnabled(bool bEnabled) = 0; virtual bool IsPedTargetingMarkerEnabled() = 0; From 0a6e8ea531bc0817f4b8ad8bfff1bac46628dd0c Mon Sep 17 00:00:00 2001 From: samr46 Date: Fri, 30 May 2025 13:28:21 +0300 Subject: [PATCH 4/7] Use direct memory check instead of new variable --- Client/game_sa/CGameSA.cpp | 8 ++++---- Client/game_sa/CGameSA.h | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 7ea533ae674..abc36574d0b 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -932,9 +932,6 @@ void CGameSA::SetVehicleBurnExplosionsEnabled(bool isEnabled) void CGameSA::SetVehicleEngineManualModeEnabled(bool enabled) { - if (enabled == m_isVehicleEngineManualModeEnabled) - return; - if (enabled) { MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) @@ -945,8 +942,11 @@ void CGameSA::SetVehicleEngineManualModeEnabled(bool enabled) MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); } +} - m_isVehicleEngineManualModeEnabled = enabled; +bool CGameSA::IsVehicleEngineManualModeEnabled() const noexcept +{ + return *(unsigned char*)0x64BC03 == 0x90; } bool CGameSA::PerformChecks() diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 666608e0147..c877061a4b0 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -262,8 +262,8 @@ class CGameSA : public CGame bool IsVehicleBurnExplosionsEnabled() const noexcept override { return m_isVehicleBurnExplosionsEnabled; } void SetVehicleBurnExplosionsEnabled(bool isEnabled) override; - bool IsVehicleEngineManualModeEnabled() const noexcept override { return m_isVehicleEngineManualModeEnabled; } void SetVehicleEngineManualModeEnabled(bool enabled) override; + bool IsVehicleEngineManualModeEnabled() const noexcept override; unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -397,7 +397,6 @@ class CGameSA : public CGame bool m_isExtendedWaterCannonsEnabled{false}; bool m_isIgnoreFireStateEnabled{false}; bool m_isVehicleBurnExplosionsEnabled{true}; - bool m_isVehicleEngineManualModeEnabled{false}; static unsigned int& ClumpOffset; From 4fcf7487f275a73480fdbcf34422361acb50cd2e Mon Sep 17 00:00:00 2001 From: samr46 Date: Sun, 1 Jun 2025 14:00:00 +0300 Subject: [PATCH 5/7] Move Is/SetVehicleEngineManualModeEnabled back to MultiplayerSA --- Client/game_sa/CGameSA.cpp | 19 ------------------- Client/game_sa/CGameSA.h | 3 --- Client/game_sa/CVehicleSA.cpp | 7 +++++-- Client/mods/deathmatch/logic/CClientGame.cpp | 6 +++--- Client/multiplayer_sa/CMultiplayerSA.cpp | 19 +++++++++++++++++++ Client/multiplayer_sa/CMultiplayerSA.h | 3 +++ Client/sdk/game/CGame.h | 3 --- Client/sdk/multiplayer/CMultiplayer.h | 3 +++ 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index abc36574d0b..7cac177f422 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -930,25 +930,6 @@ void CGameSA::SetVehicleBurnExplosionsEnabled(bool isEnabled) m_isVehicleBurnExplosionsEnabled = isEnabled; } -void CGameSA::SetVehicleEngineManualModeEnabled(bool enabled) -{ - if (enabled) - { - MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) - MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) - } - else - { - MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); - MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); - } -} - -bool CGameSA::IsVehicleEngineManualModeEnabled() const noexcept -{ - return *(unsigned char*)0x64BC03 == 0x90; -} - bool CGameSA::PerformChecks() { std::map::iterator it; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index c877061a4b0..9ed552b92d8 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -262,9 +262,6 @@ class CGameSA : public CGame bool IsVehicleBurnExplosionsEnabled() const noexcept override { return m_isVehicleBurnExplosionsEnabled; } void SetVehicleBurnExplosionsEnabled(bool isEnabled) override; - void SetVehicleEngineManualModeEnabled(bool enabled) override; - bool IsVehicleEngineManualModeEnabled() const noexcept override; - unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 6a2d88c28b6..a8cc227cc70 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -10,6 +10,8 @@ *****************************************************************************/ #include "StdInc.h" +#include +#include #include "CAutomobileSA.h" #include "CBikeSA.h" #include "CCameraSA.h" @@ -28,7 +30,8 @@ #include "gamesa_renderware.h" #include "CFireManagerSA.h" -extern CGameSA* pGame; +extern CCoreInterface* g_pCore; +extern CGameSA* pGame; static BOOL m_bVehicleSunGlare = false; _declspec(naked) void DoVehicleSunGlare(void* this_) @@ -63,7 +66,7 @@ static bool __fastcall CanProcessFlyingCarStuff(CAutomobileSAInterface* vehicleI if (vehicle->pEntity->GetVehicleRotorState()) { - if (!pGame->IsVehicleEngineManualModeEnabled()) // keep default behavior + if (!g_pCore->GetMultiplayer()->IsVehicleEngineManualModeEnabled()) // keep default behavior return true; if (vehicle->pEntity->GetEntityStatus() != eEntityStatus::STATUS_PHYSICS && !vehicle->pEntity->IsBeingDriven()) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index dfe203b4366..5bc0b9146c0 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6145,16 +6145,16 @@ bool CClientGame::IsWeaponRenderEnabled() const void CClientGame::SetVehicleEngineManualModeEnabled(bool enabled) { - if (enabled == g_pGame->IsVehicleEngineManualModeEnabled()) + if (enabled == g_pMultiplayer->IsVehicleEngineManualModeEnabled()) return; - g_pGame->SetVehicleEngineManualModeEnabled(enabled); + g_pMultiplayer->SetVehicleEngineManualModeEnabled(enabled); m_pVehicleManager->ResetNotControlledRotors(enabled); } bool CClientGame::IsVehicleEngineManualModeEnabled() const { - return g_pGame->IsVehicleEngineManualModeEnabled(); + return g_pMultiplayer->IsVehicleEngineManualModeEnabled(); } #pragma code_seg(".text") diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 8ac305efca0..b9235af715f 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -6634,6 +6634,25 @@ void CMultiplayerSA::SetAutomaticVehicleStartupOnPedEnter(bool bSet) MemSet((char*)0x64BC0D, 0x90, 6); } +bool CMultiplayerSA::IsVehicleEngineManualModeEnabled() const noexcept +{ + return *(unsigned char*)0x64BC03 == 0x90; +} + +void CMultiplayerSA::SetVehicleEngineManualModeEnabled(bool enabled) +{ + if (enabled) + { + MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) + MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) + } + else + { + MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); + MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); + } +} + // Storage CVehicleSAInterface* pHeliKiller = NULL; CEntitySAInterface* pHitByHeli = NULL; diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 7a48e561061..230807cfad6 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -333,6 +333,9 @@ class CMultiplayerSA : public CMultiplayer void SetAutomaticVehicleStartupOnPedEnter(bool bSet); + bool IsVehicleEngineManualModeEnabled() const noexcept override; + void SetVehicleEngineManualModeEnabled(bool enabled) override; + void SetPedTargetingMarkerEnabled(bool bEnable); bool IsPedTargetingMarkerEnabled(); bool IsConnected(); diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 4941af690e4..baa6103e100 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -241,9 +241,6 @@ class __declspec(novtable) CGame virtual bool IsVehicleBurnExplosionsEnabled() const noexcept = 0; virtual void SetVehicleBurnExplosionsEnabled(bool isEnabled) = 0; - virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; - virtual bool IsVehicleEngineManualModeEnabled() const noexcept = 0; - virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 8895234df23..f312280c5f9 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -444,6 +444,9 @@ class CMultiplayer virtual void SetAutomaticVehicleStartupOnPedEnter(bool bSet) = 0; + virtual bool IsVehicleEngineManualModeEnabled() const noexcept = 0; + virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; + virtual void SetPedTargetingMarkerEnabled(bool bEnabled) = 0; virtual bool IsPedTargetingMarkerEnabled() = 0; From 1aef5e986a3a15aa38d6aeb49c92bc2932ffd461 Mon Sep 17 00:00:00 2001 From: samr46 Date: Mon, 2 Jun 2025 16:11:32 +0300 Subject: [PATCH 6/7] Rename property to vehicle_engine_autostart --- Client/game_sa/CVehicleSA.cpp | 4 ++-- Client/mods/deathmatch/logic/CClientGame.cpp | 20 +++++++++---------- Client/mods/deathmatch/logic/CClientGame.h | 4 ++-- .../logic/CClientVehicleManager.cpp | 8 ++++---- .../mods/deathmatch/logic/CPacketHandler.cpp | 2 +- Client/multiplayer_sa/CMultiplayerSA.cpp | 14 ++++++------- Client/multiplayer_sa/CMultiplayerSA.h | 4 ++-- Client/sdk/multiplayer/CMultiplayer.h | 4 ++-- Server/mods/deathmatch/logic/CGame.cpp | 6 +++--- .../logic/CStaticFunctionDefinitions.cpp | 2 +- .../logic/packets/CMapInfoPacket.cpp | 2 +- Shared/mods/deathmatch/logic/Enums.cpp | 2 +- Shared/mods/deathmatch/logic/Enums.h | 2 +- Shared/sdk/net/SyncStructures.h | 10 +++++----- Shared/sdk/net/bitstream.h | 4 ++-- 15 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index a8cc227cc70..f143c1784eb 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -57,7 +57,7 @@ void _declspec(naked) HOOK_Vehicle_PreRender(void) } } -float& fTimeStep = *(float*)(0xB7CB5C); +static float& fTimeStep = *(float*)(0xB7CB5C); static bool __fastcall CanProcessFlyingCarStuff(CAutomobileSAInterface* vehicleInterface) { SClientEntity* vehicle = pGame->GetPools()->GetVehicle((DWORD*)vehicleInterface); @@ -66,7 +66,7 @@ static bool __fastcall CanProcessFlyingCarStuff(CAutomobileSAInterface* vehicleI if (vehicle->pEntity->GetVehicleRotorState()) { - if (!g_pCore->GetMultiplayer()->IsVehicleEngineManualModeEnabled()) // keep default behavior + if (g_pCore->GetMultiplayer()->IsVehicleEngineAutoStartEnabled()) // keep default behavior return true; if (vehicle->pEntity->GetEntityStatus() != eEntityStatus::STATUS_PHYSICS && !vehicle->pEntity->IsBeingDriven()) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 5bc0b9146c0..25f440fab5e 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6057,8 +6057,8 @@ bool CClientGame::SetWorldSpecialProperty(const WorldSpecialProperty property, c case WorldSpecialProperty::VEHICLEBURNEXPLOSIONS: g_pGame->SetVehicleBurnExplosionsEnabled(enabled); break; - case WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE: - SetVehicleEngineManualModeEnabled(enabled); + case WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART: + SetVehicleEngineAutoStartEnabled(enabled); break; default: return false; @@ -6106,8 +6106,8 @@ bool CClientGame::IsWorldSpecialProperty(const WorldSpecialProperty property) return m_pVehicleManager->IsSpawnFlyingComponentEnabled(); case WorldSpecialProperty::VEHICLEBURNEXPLOSIONS: return g_pGame->IsVehicleBurnExplosionsEnabled(); - case WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE: - return IsVehicleEngineManualModeEnabled(); + case WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART: + return IsVehicleEngineAutoStartEnabled(); } return false; @@ -6143,18 +6143,18 @@ bool CClientGame::IsWeaponRenderEnabled() const return g_pGame->IsWeaponRenderEnabled(); } -void CClientGame::SetVehicleEngineManualModeEnabled(bool enabled) +void CClientGame::SetVehicleEngineAutoStartEnabled(bool enabled) { - if (enabled == g_pMultiplayer->IsVehicleEngineManualModeEnabled()) + if (enabled == g_pMultiplayer->IsVehicleEngineAutoStartEnabled()) return; - g_pMultiplayer->SetVehicleEngineManualModeEnabled(enabled); + g_pMultiplayer->SetVehicleEngineAutoStartEnabled(enabled); m_pVehicleManager->ResetNotControlledRotors(enabled); } -bool CClientGame::IsVehicleEngineManualModeEnabled() const +bool CClientGame::IsVehicleEngineAutoStartEnabled() const { - return g_pMultiplayer->IsVehicleEngineManualModeEnabled(); + return g_pMultiplayer->IsVehicleEngineAutoStartEnabled(); } #pragma code_seg(".text") @@ -6842,7 +6842,7 @@ void CClientGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo g_pGame->SetIgnoreFireStateEnabled(false); m_pVehicleManager->SetSpawnFlyingComponentEnabled(true); g_pGame->SetVehicleBurnExplosionsEnabled(true); - SetVehicleEngineManualModeEnabled(false); + SetVehicleEngineAutoStartEnabled(true); } // Reset all setWorldProperty to default diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 99d47ffdb4c..d21de68f067 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -426,8 +426,8 @@ class CClientGame void SetWeaponRenderEnabled(bool enabled); bool IsWeaponRenderEnabled() const; - void SetVehicleEngineManualModeEnabled(bool enabled); - bool IsVehicleEngineManualModeEnabled() const; + void SetVehicleEngineAutoStartEnabled(bool enabled); + bool IsVehicleEngineAutoStartEnabled() const; void ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo); diff --git a/Client/mods/deathmatch/logic/CClientVehicleManager.cpp b/Client/mods/deathmatch/logic/CClientVehicleManager.cpp index 6209b9a43b5..f1d32978c6b 100644 --- a/Client/mods/deathmatch/logic/CClientVehicleManager.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicleManager.cpp @@ -792,16 +792,16 @@ void CClientVehicleManager::RestreamVehicleUpgrades(unsigned short usModel) } } -void CClientVehicleManager::ResetNotControlledRotors(bool isManualMode) +void CClientVehicleManager::ResetNotControlledRotors(bool engineAutoStart) { - // Reset rotors to custom or original state for loaded vehicles without controller + // Reset rotors to original or custom state for loaded vehicles without controller // Custom state allows rotors to spin without driver inside (if engine is on) - eEntityStatus status = isManualMode ? eEntityStatus::STATUS_PHYSICS : eEntityStatus::STATUS_ABANDONED; + eEntityStatus status = engineAutoStart ? eEntityStatus::STATUS_ABANDONED : eEntityStatus::STATUS_PHYSICS; for (auto& pVehicle : m_List) { if (pVehicle->GetGameEntity() && pVehicle->GetVehicleRotorState() && !pVehicle->IsDriven()) { - float speed = (isManualMode && pVehicle->IsEngineOn()) ? 0.001f : 0.0f; + float speed = (!engineAutoStart && pVehicle->IsEngineOn()) ? 0.001f : 0.0f; pVehicle->GetGameEntity()->SetEntityStatus(status); pVehicle->SetHeliRotorSpeed(speed); pVehicle->SetPlaneRotorSpeed(speed); diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index 94147e9047c..1f50f7ac679 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -2402,7 +2402,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FLYINGCOMPONENTS, wsProps.data7.flyingcomponents); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, wsProps.data8.vehicleburnexplosions); - g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, wsProps.data9.vehEngineManualMode); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART, wsProps.data9.vehicleEngineAutoStart); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index b9235af715f..2389110fbf9 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -6634,22 +6634,22 @@ void CMultiplayerSA::SetAutomaticVehicleStartupOnPedEnter(bool bSet) MemSet((char*)0x64BC0D, 0x90, 6); } -bool CMultiplayerSA::IsVehicleEngineManualModeEnabled() const noexcept +bool CMultiplayerSA::IsVehicleEngineAutoStartEnabled() const noexcept { - return *(unsigned char*)0x64BC03 == 0x90; + return *(unsigned char*)0x64BC03 == 0x75; } -void CMultiplayerSA::SetVehicleEngineManualModeEnabled(bool enabled) +void CMultiplayerSA::SetVehicleEngineAutoStartEnabled(bool enabled) { if (enabled) { - MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) - MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) + MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); + MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); } else { - MemCpy((void*)0x64BC03, "\x75\x05\x80\xC9\x10", 5); - MemCpy((void*)0x6C4EA9, "\x8A\x86\x28\x04", 4); + MemSet((void*)0x64BC03, 0x90, 5); // prevent vehicle engine from turning on (driver enter) + MemCpy((void*)0x6C4EA9, "\xE9\x15\x03\x00", 4); // prevent aircraft engine from turning off (driver exit) } } diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 230807cfad6..f4c79ce9b6d 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -333,8 +333,8 @@ class CMultiplayerSA : public CMultiplayer void SetAutomaticVehicleStartupOnPedEnter(bool bSet); - bool IsVehicleEngineManualModeEnabled() const noexcept override; - void SetVehicleEngineManualModeEnabled(bool enabled) override; + bool IsVehicleEngineAutoStartEnabled() const noexcept override; + void SetVehicleEngineAutoStartEnabled(bool enabled) override; void SetPedTargetingMarkerEnabled(bool bEnable); bool IsPedTargetingMarkerEnabled(); diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index f312280c5f9..555de9e5264 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -444,8 +444,8 @@ class CMultiplayer virtual void SetAutomaticVehicleStartupOnPedEnter(bool bSet) = 0; - virtual bool IsVehicleEngineManualModeEnabled() const noexcept = 0; - virtual void SetVehicleEngineManualModeEnabled(bool enabled) = 0; + virtual bool IsVehicleEngineAutoStartEnabled() const noexcept = 0; + virtual void SetVehicleEngineAutoStartEnabled(bool enabled) = 0; virtual void SetPedTargetingMarkerEnabled(bool bEnabled) = 0; virtual bool IsPedTargetingMarkerEnabled() = 0; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 25bcfbc5011..16e7b7312bd 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -263,7 +263,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::IGNOREFIRESTATE] = false; m_WorldSpecialProps[WorldSpecialProperty::FLYINGCOMPONENTS] = true; m_WorldSpecialProps[WorldSpecialProperty::VEHICLEBURNEXPLOSIONS] = true; - m_WorldSpecialProps[WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE] = false; + m_WorldSpecialProps[WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART] = true; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; @@ -3406,7 +3406,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); // Update our engine State - if (!g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE)) + if (g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART)) pVehicle->SetEngineOn(true); // Tell everyone he's in (they should warp him in) @@ -4526,7 +4526,7 @@ void CGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo) g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE, false); g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::FLYINGCOMPONENTS, true); g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, true); - g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART, true); } // Reset all weather stuff like heat haze, wind velocity etc diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 61fab6c6f30..f8bfad986a3 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -4262,7 +4262,7 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CPed* pPed, CVehicle* pVehic pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); // If he's the driver, switch on the engine - if (uiSeat == 0 && !g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE)) + if (uiSeat == 0 && g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART)) pVehicle->SetEngineOn(true); // Tell all the players diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index 2d3d4c2bf53..0fd78c8bd37 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -195,7 +195,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data6.ignoreFireState = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE); wsProps.data7.flyingcomponents = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FLYINGCOMPONENTS); wsProps.data8.vehicleburnexplosions = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS); - wsProps.data9.vehEngineManualMode = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE); + wsProps.data9.vehicleEngineAutoStart = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART); BitStream.Write(&wsProps); } diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index 2a0aa3a7f1a..8bb99db974f 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -119,7 +119,7 @@ ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") ADD_ENUM(WorldSpecialProperty::IGNOREFIRESTATE, "ignorefirestate") ADD_ENUM(WorldSpecialProperty::FLYINGCOMPONENTS, "flyingcomponents") ADD_ENUM(WorldSpecialProperty::VEHICLEBURNEXPLOSIONS, "vehicleburnexplosions") -ADD_ENUM(WorldSpecialProperty::VEHICLE_ENGINE_MANUAL_MODE, "vehenginemanualmode") +ADD_ENUM(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART, "vehicle_engine_autostart") IMPLEMENT_ENUM_CLASS_END("world-special-property") IMPLEMENT_ENUM_BEGIN(ePacketID) diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index 2c266559f70..884bb559f5c 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -96,7 +96,7 @@ enum class WorldSpecialProperty IGNOREFIRESTATE, FLYINGCOMPONENTS, VEHICLEBURNEXPLOSIONS, - VEHICLE_ENGINE_MANUAL_MODE, + VEHICLE_ENGINE_AUTOSTART, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 14db97bd3c2..c9d4a980751 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2126,10 +2126,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure else data8.vehicleburnexplosions = true; - if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineManualMode)) + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineAutoStart)) isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); else - data9.vehEngineManualMode = false; + data9.vehicleEngineAutoStart = true; //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) @@ -2163,7 +2163,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleBurnExplosions)) bitStream.WriteBits(reinterpret_cast(&data8), BITCOUNT8); - if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineManualMode)) + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_VehicleEngineAutoStart)) bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); //// Example for adding item: @@ -2225,7 +2225,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure struct { - bool vehEngineManualMode : 1; + bool vehicleEngineAutoStart : 1; } data9; SWorldSpecialPropertiesStateSync() @@ -2250,7 +2250,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data6.ignoreFireState = false; data7.flyingcomponents = true; data8.vehicleburnexplosions = true; - data9.vehEngineManualMode = false; + data9.vehicleEngineAutoStart = true; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index fd8494723d7..160077ec357 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -621,8 +621,8 @@ enum class eBitStreamVersion : unsigned short ServersideBuildingElement, // Add "vehenginemanualmode" to setWorldSpecialPropertyEnabled - // 2025-05-29 - WorldSpecialProperty_VehicleEngineManualMode, + // 2025-06-02 + WorldSpecialProperty_VehicleEngineAutoStart, // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. From 656400d32bd196baed9b9aee5b4b55f026a78298 Mon Sep 17 00:00:00 2001 From: samr46 Date: Mon, 2 Jun 2025 16:19:30 +0300 Subject: [PATCH 7/7] Fix typo --- Client/mods/deathmatch/logic/CClientVehicleManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientVehicleManager.h b/Client/mods/deathmatch/logic/CClientVehicleManager.h index 567870d7524..c9d14d848d4 100644 --- a/Client/mods/deathmatch/logic/CClientVehicleManager.h +++ b/Client/mods/deathmatch/logic/CClientVehicleManager.h @@ -73,7 +73,7 @@ class CClientVehicleManager bool IsSpawnFlyingComponentEnabled() const noexcept { return m_spawnFlyingComponentsDuringRecreate; } void SetSpawnFlyingComponentEnabled(bool isEnabled) noexcept { m_spawnFlyingComponentsDuringRecreate = isEnabled; } - void ResetNotControlledRotors(bool isManualMode); + void ResetNotControlledRotors(bool engineAutoStart); protected: CClientManager* m_pManager;