From b778390a765c2e91d827b86d8b7f015516e52207 Mon Sep 17 00:00:00 2001 From: FileEX Date: Thu, 7 Nov 2024 18:34:48 +0100 Subject: [PATCH 1/6] Add new glitch --- Client/mods/deathmatch/logic/CClientGame.cpp | 8 +++++- Client/mods/deathmatch/logic/CClientGame.h | 1 + .../mods/deathmatch/logic/CPacketHandler.cpp | 1 + Client/multiplayer_sa/CMultiplayerSA.cpp | 25 +++++++++++++++++++ Client/multiplayer_sa/CMultiplayerSA.h | 1 + Client/sdk/multiplayer/CMultiplayer.h | 1 + Server/mods/deathmatch/logic/CGame.cpp | 2 ++ Server/mods/deathmatch/logic/CGame.h | 1 + .../logic/packets/CMapInfoPacket.cpp | 1 + Shared/sdk/net/SyncStructures.h | 17 +++++++++++++ Shared/sdk/net/bitstream.h | 4 +++ 11 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 429bafb3659..656aa434625 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -135,6 +135,9 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false; m_Glitches[GLITCH_QUICKSTAND] = false; m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false; + m_Glitches[GLITCH_IGNOREFIRESTATE] = false; + g_pMultiplayer->SetIgnoreFireState(false); + g_pMultiplayer->DisableBadDrivebyHitboxes(true); // Remove Night & Thermal vision view (if enabled). @@ -5971,6 +5974,9 @@ bool CClientGame::SetGlitchEnabled(unsigned char ucGlitch, bool bEnabled) g_pMultiplayer->DisableQuickReload(!bEnabled); if (ucGlitch == GLITCH_CLOSEDAMAGE) g_pMultiplayer->DisableCloseRangeDamage(!bEnabled); + if (ucGlitch == GLITCH_IGNOREFIRESTATE) + g_pMultiplayer->SetIgnoreFireState(bEnabled); + return true; } return false; @@ -6475,7 +6481,7 @@ void CClientGame::OutputServerInfo() { SString strEnabledGlitches; const char* szGlitchNames[] = {"Quick reload", "Fast fire", "Fast move", "Crouch bug", "Close damage", "Hit anim", "Fast sprint", - "Bad driveby hitboxes", "Quick stand"}; + "Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace", "Ignore fire state"}; for (uint i = 0; i < NUM_GLITCHES; i++) { if (IsGlitchEnabled(i)) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index ba6bc29334f..160977d7355 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -200,6 +200,7 @@ class CClientGame GLITCH_BADDRIVEBYHITBOX, GLITCH_QUICKSTAND, GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE, + GLITCH_IGNOREFIRESTATE, NUM_GLITCHES }; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index ebf2ba5140f..49e59ea0045 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -2372,6 +2372,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_FASTSPRINT, funBugs.data3.bFastSprint); g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_BADDRIVEBYHITBOX, funBugs.data4.bBadDrivebyHitboxes); g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_QUICKSTAND, funBugs.data5.bQuickStand); + g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_IGNOREFIRESTATE, funBugs.data6.bIgnoreFireState); SWorldSpecialPropertiesStateSync wsProps; if (bitStream.Can(eBitStreamVersion::WorldSpecialProperties)) diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 1b21f79a238..bd07e46a9c4 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1861,6 +1861,31 @@ void CMultiplayerSA::DisableCloseRangeDamage(bool bDisabled) MemPut(0x73BA00, 0x86); } } + +void CMultiplayerSA::SetIgnoreFireState(bool ignore) +{ + if (ignore) + { + MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable + MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask + MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask + MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter + + // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon + MemSet((void*)0x685A7F, 0x90, 14); + } + else + { + // Restore original bytes + MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10); + MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14); + MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14); + MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14); + + MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14); + } +} + bool CMultiplayerSA::GetInteriorSoundsEnabled() { return bInteriorSoundsEnabled; diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 802b9b56eac..96d1bda21bc 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -99,6 +99,7 @@ class CMultiplayerSA : public CMultiplayer void DisableQuickReload(bool bDisable); void DisableCloseRangeDamage(bool bDisable); void DisableBadDrivebyHitboxes(bool bDisable) { m_bBadDrivebyHitboxesDisabled = bDisable; } + void SetIgnoreFireState(bool ignore) override; bool GetExplosionsDisabled(); void DisableExplosions(bool bDisabled); diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 02c932cf574..35458b69de2 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -216,6 +216,7 @@ class CMultiplayer virtual void DisableQuickReload(bool bDisable) = 0; virtual void DisableCloseRangeDamage(bool bDisable) = 0; virtual void DisableBadDrivebyHitboxes(bool bDisable) = 0; + virtual void SetIgnoreFireState(bool ignore) = 0; virtual bool GetExplosionsDisabled() = 0; virtual void DisableExplosions(bool bDisabled) = 0; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index d4efea393f4..65507ac056d 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -238,6 +238,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false; m_Glitches[GLITCH_QUICKSTAND] = false; m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false; + m_Glitches[GLITCH_IGNOREFIRESTATE] = false; for (int i = 0; i < WEAPONTYPE_LAST_WEAPONTYPE; i++) m_JetpackWeapons[i] = false; @@ -273,6 +274,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_GlitchNames["baddrivebyhitbox"] = GLITCH_BADDRIVEBYHITBOX; m_GlitchNames["quickstand"] = GLITCH_QUICKSTAND; m_GlitchNames["kickoutofvehicle_onmodelreplace"] = GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE; + m_GlitchNames["ignorefirestate"] = GLITCH_IGNOREFIRESTATE; m_bCloudsEnabled = true; diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index d865e858ec9..c47a4ea0678 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -194,6 +194,7 @@ class CGame GLITCH_BADDRIVEBYHITBOX, GLITCH_QUICKSTAND, GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE, + GLITCH_IGNOREFIRESTATE, NUM_GLITCHES }; diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index e62547b3fb9..e8280b5043f 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -170,6 +170,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const funBugs.data3.bFastSprint = g_pGame->IsGlitchEnabled(CGame::GLITCH_FASTSPRINT); funBugs.data4.bBadDrivebyHitboxes = g_pGame->IsGlitchEnabled(CGame::GLITCH_BADDRIVEBYHITBOX); funBugs.data5.bQuickStand = g_pGame->IsGlitchEnabled(CGame::GLITCH_QUICKSTAND); + funBugs.data6.bIgnoreFireState = g_pGame->IsGlitchEnabled(CGame::GLITCH_IGNOREFIRESTATE); BitStream.Write(&funBugs); // Write world special properties states diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 1e9b8215b3e..223b9f537c8 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -1937,6 +1937,10 @@ struct SFunBugsStateSync : public ISyncStructure { BITCOUNT5 = 1 }; + enum + { + BITCOUNT6 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -1958,6 +1962,11 @@ struct SFunBugsStateSync : public ISyncStructure else data5.bQuickStand = 0; + if (bitStream.Can(eBitStreamVersion::Glitch_IgnoreFireState)) + bOk &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); + else + data6.bIgnoreFireState = 0; + //// Example for adding item: // if ( bitStream.Version() >= 0x999 ) // bOk &= bitStream.ReadBits ( reinterpret_cast < char* > ( &data9 ), BITCOUNT9 ); @@ -1977,6 +1986,8 @@ struct SFunBugsStateSync : public ISyncStructure bitStream.WriteBits(reinterpret_cast(&data4), BITCOUNT4); if (bitStream.Can(eBitStreamVersion::QuickStandGlitch)) bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); + if (bitStream.Can(eBitStreamVersion::Glitch_IgnoreFireState)) + bitStream.WriteBits(reinterpret_cast(&data6), BITCOUNT6); //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourGlitch)) @@ -2015,6 +2026,12 @@ struct SFunBugsStateSync : public ISyncStructure { bool bQuickStand : 1; } data5; + + // Add new ones in separate structs + struct + { + bool bIgnoreFireState : 1; + } data6; }; ////////////////////////////////////////// diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index c29f739ff19..acea8294673 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -572,6 +572,10 @@ enum class eBitStreamVersion : unsigned short // 2024-09-04 RespawnObject_Serverside, + // Add ignorefirestate glitch + // 2024-11-07 + Glitch_IgnoreFireState, + // 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 e2fafa048f2c29878304eb91cfb632aa9bb6c41b Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 19 Nov 2024 13:09:55 +0100 Subject: [PATCH 2/6] Move to special world property --- Client/game_sa/CGameSA.cpp | 28 +++++++++++++++ Client/game_sa/CGameSA.h | 3 ++ Client/mods/deathmatch/logic/CClientGame.cpp | 12 +++---- Client/mods/deathmatch/logic/CClientGame.h | 1 - .../mods/deathmatch/logic/CPacketHandler.cpp | 2 +- Client/multiplayer_sa/CMultiplayerSA.cpp | 24 ------------- Client/multiplayer_sa/CMultiplayerSA.h | 1 - Client/sdk/game/CGame.h | 3 ++ Client/sdk/multiplayer/CMultiplayer.h | 1 - Server/mods/deathmatch/logic/CGame.cpp | 3 +- Server/mods/deathmatch/logic/CGame.h | 1 - .../logic/packets/CMapInfoPacket.cpp | 2 +- Shared/mods/deathmatch/logic/Enums.cpp | 1 + Shared/mods/deathmatch/logic/Enums.h | 1 + Shared/sdk/net/SyncStructures.h | 35 ++++++++++--------- Shared/sdk/net/bitstream.h | 4 +-- 16 files changed, 65 insertions(+), 57 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 07ac611c09a..918091d4823 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -848,6 +848,34 @@ void CGameSA::SetRoadSignsTextEnabled(bool isEnabled) m_isRoadSignsTextEnabled = isEnabled; } +void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled) +{ + if (isEnabled == m_isIgnoreFireStateEnabled) + return; + + if (isEnabled) + { + MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable + MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask + MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask + MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter + + MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon + } + else + { + // Restore original bytes + MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10); + MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14); + MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14); + MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14); + + MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14); + } + + m_isIgnoreFireStateEnabled = isEnabled; +} + bool CGameSA::PerformChecks() { std::map::iterator it; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index cf4788d9539..33731af8581 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -249,6 +249,8 @@ class CGameSA : public CGame bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; } void SetTunnelWeatherBlendEnabled(bool isEnabled) override; + bool IsIgnoreFireStateEnabled() const noexcept override { return m_isIgnoreFireStateEnabled; } + void SetIgnoreFireStateEnabled(bool isEnabled) override; unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -378,6 +380,7 @@ class CGameSA : public CGame bool m_isRoadSignsTextEnabled{true}; bool m_isBuildingsRemoved{false}; bool m_isExtendedWaterCannonsEnabled{false}; + bool m_isIgnoreFireStateEnabled{false}; static unsigned int& ClumpOffset; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 656aa434625..a0b459c0427 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -135,8 +135,6 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false; m_Glitches[GLITCH_QUICKSTAND] = false; m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false; - m_Glitches[GLITCH_IGNOREFIRESTATE] = false; - g_pMultiplayer->SetIgnoreFireState(false); g_pMultiplayer->DisableBadDrivebyHitboxes(true); @@ -5974,9 +5972,6 @@ bool CClientGame::SetGlitchEnabled(unsigned char ucGlitch, bool bEnabled) g_pMultiplayer->DisableQuickReload(!bEnabled); if (ucGlitch == GLITCH_CLOSEDAMAGE) g_pMultiplayer->DisableCloseRangeDamage(!bEnabled); - if (ucGlitch == GLITCH_IGNOREFIRESTATE) - g_pMultiplayer->SetIgnoreFireState(bEnabled); - return true; } return false; @@ -6031,6 +6026,9 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is case WorldSpecialProperty::TUNNELWEATHERBLEND: g_pGame->SetTunnelWeatherBlendEnabled(isEnabled); return true; + case WorldSpecialProperty::IGNOREFIRESTATE: + g_pGame->SetIgnoreFireStateEnabled(isEnabled); + return true; } return false; } @@ -6068,6 +6066,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) return g_pGame->IsRoadSignsTextEnabled(); case WorldSpecialProperty::TUNNELWEATHERBLEND: return g_pGame->IsTunnelWeatherBlendEnabled(); + case WorldSpecialProperty::IGNOREFIRESTATE: + return g_pGame->IsIgnoreFireStateEnabled(); } return false; } @@ -6481,7 +6481,7 @@ void CClientGame::OutputServerInfo() { SString strEnabledGlitches; const char* szGlitchNames[] = {"Quick reload", "Fast fire", "Fast move", "Crouch bug", "Close damage", "Hit anim", "Fast sprint", - "Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace", "Ignore fire state"}; + "Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace"}; for (uint i = 0; i < NUM_GLITCHES; i++) { if (IsGlitchEnabled(i)) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 160977d7355..ba6bc29334f 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -200,7 +200,6 @@ class CClientGame GLITCH_BADDRIVEBYHITBOX, GLITCH_QUICKSTAND, GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE, - GLITCH_IGNOREFIRESTATE, NUM_GLITCHES }; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index 49e59ea0045..029b16c8c31 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -2372,7 +2372,6 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_FASTSPRINT, funBugs.data3.bFastSprint); g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_BADDRIVEBYHITBOX, funBugs.data4.bBadDrivebyHitboxes); g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_QUICKSTAND, funBugs.data5.bQuickStand); - g_pClientGame->SetGlitchEnabled(CClientGame::GLITCH_IGNOREFIRESTATE, funBugs.data6.bIgnoreFireState); SWorldSpecialPropertiesStateSync wsProps; if (bitStream.Can(eBitStreamVersion::WorldSpecialProperties)) @@ -2394,6 +2393,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index bd07e46a9c4..a7b8564fa41 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1862,30 +1862,6 @@ void CMultiplayerSA::DisableCloseRangeDamage(bool bDisabled) } } -void CMultiplayerSA::SetIgnoreFireState(bool ignore) -{ - if (ignore) - { - MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable - MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask - MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask - MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter - - // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon - MemSet((void*)0x685A7F, 0x90, 14); - } - else - { - // Restore original bytes - MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10); - MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14); - MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14); - MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14); - - MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14); - } -} - bool CMultiplayerSA::GetInteriorSoundsEnabled() { return bInteriorSoundsEnabled; diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 96d1bda21bc..802b9b56eac 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -99,7 +99,6 @@ class CMultiplayerSA : public CMultiplayer void DisableQuickReload(bool bDisable); void DisableCloseRangeDamage(bool bDisable); void DisableBadDrivebyHitboxes(bool bDisable) { m_bBadDrivebyHitboxesDisabled = bDisable; } - void SetIgnoreFireState(bool ignore) override; bool GetExplosionsDisabled(); void DisableExplosions(bool bDisabled); diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 2314fdad0e2..06866e06ce9 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -230,6 +230,9 @@ class __declspec(novtable) CGame virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0; virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0; + virtual bool IsIgnoreFireStateEnabled() const noexcept = 0; + virtual void SetIgnoreFireStateEnabled(bool isEnabled) = 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 35458b69de2..02c932cf574 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -216,7 +216,6 @@ class CMultiplayer virtual void DisableQuickReload(bool bDisable) = 0; virtual void DisableCloseRangeDamage(bool bDisable) = 0; virtual void DisableBadDrivebyHitboxes(bool bDisable) = 0; - virtual void SetIgnoreFireState(bool ignore) = 0; virtual bool GetExplosionsDisabled() = 0; virtual void DisableExplosions(bool bDisabled) = 0; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 65507ac056d..d15b2600767 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -238,7 +238,6 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false; m_Glitches[GLITCH_QUICKSTAND] = false; m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false; - m_Glitches[GLITCH_IGNOREFIRESTATE] = false; for (int i = 0; i < WEAPONTYPE_LAST_WEAPONTYPE; i++) m_JetpackWeapons[i] = false; @@ -259,6 +258,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::EXTENDEDWATERCANNONS] = true; m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true; m_WorldSpecialProps[WorldSpecialProperty::TUNNELWEATHERBLEND] = true; + m_WorldSpecialProps[WorldSpecialProperty::IGNOREFIRESTATE] = false; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; @@ -274,7 +274,6 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_GlitchNames["baddrivebyhitbox"] = GLITCH_BADDRIVEBYHITBOX; m_GlitchNames["quickstand"] = GLITCH_QUICKSTAND; m_GlitchNames["kickoutofvehicle_onmodelreplace"] = GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE; - m_GlitchNames["ignorefirestate"] = GLITCH_IGNOREFIRESTATE; m_bCloudsEnabled = true; diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index c47a4ea0678..d865e858ec9 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -194,7 +194,6 @@ class CGame GLITCH_BADDRIVEBYHITBOX, GLITCH_QUICKSTAND, GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE, - GLITCH_IGNOREFIRESTATE, NUM_GLITCHES }; diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index e8280b5043f..e2adf9a5bce 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -170,7 +170,6 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const funBugs.data3.bFastSprint = g_pGame->IsGlitchEnabled(CGame::GLITCH_FASTSPRINT); funBugs.data4.bBadDrivebyHitboxes = g_pGame->IsGlitchEnabled(CGame::GLITCH_BADDRIVEBYHITBOX); funBugs.data5.bQuickStand = g_pGame->IsGlitchEnabled(CGame::GLITCH_QUICKSTAND); - funBugs.data6.bIgnoreFireState = g_pGame->IsGlitchEnabled(CGame::GLITCH_IGNOREFIRESTATE); BitStream.Write(&funBugs); // Write world special properties states @@ -193,6 +192,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data3.roadsignstext = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT); wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS); wsProps.data5.tunnelweatherblend = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND); + wsProps.data6.ignoreFireState = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE); BitStream.Write(&wsProps); } diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index 1e3d0b20031..20be17719d6 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -101,6 +101,7 @@ ADD_ENUM(WorldSpecialProperty::FIREBALLDESTRUCT, "fireballdestruct") ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons") ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext") ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") +ADD_ENUM(WorldSpecialProperty::IGNOREFIRESTATE, "ignorefirestate") 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 e975d0d9074..31251797143 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -91,6 +91,7 @@ enum class WorldSpecialProperty ROADSIGNSTEXT, EXTENDEDWATERCANNONS, TUNNELWEATHERBLEND, + IGNOREFIRESTATE, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 223b9f537c8..0e42407aaee 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -1937,10 +1937,6 @@ struct SFunBugsStateSync : public ISyncStructure { BITCOUNT5 = 1 }; - enum - { - BITCOUNT6 = 1 - }; bool Read(NetBitStreamInterface& bitStream) { @@ -1962,11 +1958,6 @@ struct SFunBugsStateSync : public ISyncStructure else data5.bQuickStand = 0; - if (bitStream.Can(eBitStreamVersion::Glitch_IgnoreFireState)) - bOk &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); - else - data6.bIgnoreFireState = 0; - //// Example for adding item: // if ( bitStream.Version() >= 0x999 ) // bOk &= bitStream.ReadBits ( reinterpret_cast < char* > ( &data9 ), BITCOUNT9 ); @@ -1986,8 +1977,6 @@ struct SFunBugsStateSync : public ISyncStructure bitStream.WriteBits(reinterpret_cast(&data4), BITCOUNT4); if (bitStream.Can(eBitStreamVersion::QuickStandGlitch)) bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); - if (bitStream.Can(eBitStreamVersion::Glitch_IgnoreFireState)) - bitStream.WriteBits(reinterpret_cast(&data6), BITCOUNT6); //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourGlitch)) @@ -2026,12 +2015,6 @@ struct SFunBugsStateSync : public ISyncStructure { bool bQuickStand : 1; } data5; - - // Add new ones in separate structs - struct - { - bool bIgnoreFireState : 1; - } data6; }; ////////////////////////////////////////// @@ -2061,6 +2044,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT5 = 1 }; + enum + { + BITCOUNT6 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2085,6 +2072,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure else data5.tunnelweatherblend = true; + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); + else + data6.ignoreFireState = false; + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2108,6 +2100,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) + bitStream.WriteBits(reinterpret_cast(&data6), BITCOUNT6); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2149,6 +2144,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { bool tunnelweatherblend : 1; } data5; + + struct + { + bool ignoreFireState : 1; + } data6; SWorldSpecialPropertiesStateSync() { @@ -2169,6 +2169,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data3.roadsignstext = true; data4.extendedwatercannons = true; data5.tunnelweatherblend = true; + data6.ignoreFireState = false; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index acea8294673..d1cafb61020 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -572,9 +572,9 @@ enum class eBitStreamVersion : unsigned short // 2024-09-04 RespawnObject_Serverside, - // Add ignorefirestate glitch + // Add ignorefirestate special world property // 2024-11-07 - Glitch_IgnoreFireState, + WorldSpecialProperty_IgnoreFireState, // 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 dc89360e038365299e307d96df4cfaf2587d1b20 Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 2 May 2025 18:31:40 +0200 Subject: [PATCH 3/6] Update CGameSA.cpp --- Client/game_sa/CGameSA.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 918091d4823..55b43121275 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -861,6 +861,8 @@ void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled) MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon + MemSet((void*)0x53A899, 0x90, 5); // CFire::ProcessFire + MemSet((void*)0x53A990, 0x90, 5); // CFire::ProcessFire } else { @@ -871,6 +873,9 @@ void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled) MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14); MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14); + + MemCpy((void*)0x53A899, "\xE8\x82\xF7\x0C\x00", 5); + MemCpy((void*)0x53A990, "\xE8\x8B\xF6\x0C\x00", 5); } m_isIgnoreFireStateEnabled = isEnabled; From a785ff1921db19ec446bddfc1d2c1ffd55c4d833 Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 2 May 2025 18:39:46 +0200 Subject: [PATCH 4/6] Update SyncStructures.h --- Shared/sdk/net/SyncStructures.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 527cd23d9b6..4260a3e74c5 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2106,7 +2106,8 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) isOK &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); else - data6.ignoreFireState = false; + data6.ignoreFireState = false; + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_FlyingComponents)) isOK &= bitStream.ReadBits(reinterpret_cast(&data7), BITCOUNT7); else From 18a6f32ee54192a33a7f09c9b3921b14ce2a0a6c Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 2 May 2025 18:40:39 +0200 Subject: [PATCH 5/6] Update SyncStructures.h --- Shared/sdk/net/SyncStructures.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 4260a3e74c5..5c51b013d4f 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2107,7 +2107,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure isOK &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); else data6.ignoreFireState = false; - + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_FlyingComponents)) isOK &= bitStream.ReadBits(reinterpret_cast(&data7), BITCOUNT7); else From aca64fc21b3a6b1b617271130c1c30e731a1993c Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 4 May 2025 23:21:32 +0200 Subject: [PATCH 6/6] Fix bug --- Client/multiplayer_sa/CMultiplayerSA.cpp | 2 + Client/multiplayer_sa/CMultiplayerSA.h | 1 + .../multiplayer_sa/CMultiplayerSA_Tasks.cpp | 71 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 Client/multiplayer_sa/CMultiplayerSA_Tasks.cpp diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 33f22545419..de710fdc36c 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1595,6 +1595,8 @@ void CMultiplayerSA::InitHooks() InitHooks_ObjectStreamerOptimization(); InitHooks_Postprocess(); + + InitHooks_Tasks(); } // Used to store copied pointers for explosions in the FxSystem diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 73bd1ef24eb..072e0a98f9f 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -81,6 +81,7 @@ class CMultiplayerSA : public CMultiplayer void InitHooks_ObjectStreamerOptimization(); void InitHooks_Postprocess(); void InitHooks_DeviceSelection(); + void InitHooks_Tasks(); CRemoteDataStorage* CreateRemoteDataStorage(); void DestroyRemoteDataStorage(CRemoteDataStorage* pData); void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData); diff --git a/Client/multiplayer_sa/CMultiplayerSA_Tasks.cpp b/Client/multiplayer_sa/CMultiplayerSA_Tasks.cpp new file mode 100644 index 00000000000..69cce9ab046 --- /dev/null +++ b/Client/multiplayer_sa/CMultiplayerSA_Tasks.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: multiplayer_sa/CMultiplayerSA_Tasks.cpp + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ +#include "StdInc.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// +// CTaskSimplePlayerOnFoot::MakeAbortable +// +// If ignorefirestate is enabled, we need this hook to avoid tweaking the aiming animation +// and the chainsaw turning off when entering fire +// +////////////////////////////////////////////////////////////////////////////////////////// +static bool __IsIgnoreFireStateEnabled() +{ + return pGameInterface->IsIgnoreFireStateEnabled(); +} + +#define HOOKPOS_CTaskSimplePlayerOnFoot__MakeAbortable 0x68584D +#define HOOKSIZE_CTaskSimplePlayerOnFoot__MakeAbortable 6 +static constexpr std::uintptr_t RETURN_CTaskSimplePlayerOnFoot__MakeAbortable = 0x68585F; +static constexpr std::uintptr_t SKIP_CTaskSimplePlayerOnFoot__MakeAbortable = 0x685855; +static void _declspec(naked) HOOK_CTaskSimplePlayerOnFoot__MakeAbortable() +{ + _asm + { + // return false and keep task alive + call dword ptr [eax+8] + cmp eax, 3Dh + jl skip + + // if eventPriority == 66 (EventOnFire) && IsIgnoreFireStateEnabled() + cmp eax, 42h + jne continue_logic + + call __IsIgnoreFireStateEnabled + test al, al + jz continue_logic + + // return true but keep task alive + pop edi + pop esi + pop ebx + mov al, 1 + retn 0Ch + + continue_logic: + jmp RETURN_CTaskSimplePlayerOnFoot__MakeAbortable + + skip: + jmp SKIP_CTaskSimplePlayerOnFoot__MakeAbortable + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +// CMultiplayerSA::InitHooks_Tasks +// +// Setup hooks +// +////////////////////////////////////////////////////////////////////////////////////////// +void CMultiplayerSA::InitHooks_Tasks() +{ + EZHookInstall(CTaskSimplePlayerOnFoot__MakeAbortable); +}