From c00cdcde3f9c3c31173b0ad620a46b917b79e3de Mon Sep 17 00:00:00 2001 From: FileEX Date: Mon, 6 Jan 2025 17:14:39 +0100 Subject: [PATCH 1/4] Fix bug --- Client/game_sa/CPedSA.cpp | 14 ++++++++++---- .../logic/CStaticFunctionDefinitions.cpp | 2 +- .../deathmatch/logic/luadefs/CLuaElementDefs.cpp | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 3818e0cb4d1..7e8f47440b4 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -854,7 +854,7 @@ void CPedSA::SetBleeding(bool bBleeding) bool CPedSA::SetOnFire(bool onFire) { CPedSAInterface* pInterface = GetPedInterface(); - if (onFire == !!pInterface->pFireOnPed) + if (onFire && pInterface->pFireOnPed) return false; auto* fireManager = static_cast(pGame->GetFireManager()); @@ -877,10 +877,16 @@ bool CPedSA::SetOnFire(bool onFire) else { CFire* fire = fireManager->GetFire(static_cast(pInterface->pFireOnPed)); - if (!fire) - return false; + if (fire) + fire->Extinguish(); - fire->Extinguish(); + CTaskManager* taskManager = m_pPedIntelligence->GetTaskManager(); + if (taskManager) + { + CTask* task = taskManager->GetTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM); + if (task && task->GetTaskType() == TASK_SIMPLE_PLAYER_ON_FIRE) + taskManager->RemoveTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM); + } } return true; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index fdb7a897a88..1688bd72196 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2594,7 +2594,7 @@ bool CStaticFunctionDefinitions::SetPedOnFire(CClientEntity& Entity, bool bOnFir { if (IS_PED(&Entity)) { - if (!Entity.IsLocalEntity()) + if (!Entity.IsLocalEntity() && &Entity != GetLocalPlayer()) return false; CClientPed& Ped = static_cast(Entity); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index daea88e46f8..436e03d8122 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -2520,7 +2520,7 @@ bool CLuaElementDefs::SetLowLodElement(lua_State* luaVM, CClientEntity* pEntity, bool CLuaElementDefs::SetElementOnFire(CClientEntity* entity, bool onFire) noexcept { - if (!entity->IsLocalEntity()) + if (!entity->IsLocalEntity() && entity != CStaticFunctionDefinitions::GetLocalPlayer()) return false; return entity->SetOnFire(onFire); From ec5a337e746de4d2414ffa0da6ad2c099679f6d3 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 11 Jan 2025 14:43:29 +0100 Subject: [PATCH 2/4] Review --- Client/game_sa/CPedSA.cpp | 12 ++++++------ Client/game_sa/CTaskManagerSA.cpp | 12 ++++++++++++ Client/game_sa/CTaskManagerSA.h | 1 + Client/sdk/game/CTaskManager.h | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 7e8f47440b4..c27efabed62 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -876,17 +876,17 @@ bool CPedSA::SetOnFire(bool onFire) } else { + bool wasFire = false; + CFire* fire = fireManager->GetFire(static_cast(pInterface->pFireOnPed)); if (fire) + { fire->Extinguish(); + wasFire = true; + } CTaskManager* taskManager = m_pPedIntelligence->GetTaskManager(); - if (taskManager) - { - CTask* task = taskManager->GetTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM); - if (task && task->GetTaskType() == TASK_SIMPLE_PLAYER_ON_FIRE) - taskManager->RemoveTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM); - } + return wasFire || (taskManager && taskManager->RemoveTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM, TASK_SIMPLE_PLAYER_ON_FIRE)); } return true; diff --git a/Client/game_sa/CTaskManagerSA.cpp b/Client/game_sa/CTaskManagerSA.cpp index 15589de95f4..c8873c35528 100644 --- a/Client/game_sa/CTaskManagerSA.cpp +++ b/Client/game_sa/CTaskManagerSA.cpp @@ -151,6 +151,18 @@ void CTaskManagerSA::RemoveTaskSecondary(const int iTaskPriority) SetTaskSecondary(NULL, iTaskPriority); } +bool CTaskManagerSA::RemoveTaskSecondary(const int taskPriority, const int taskType) +{ + CTask* task = GetTaskSecondary(taskPriority); + if (task && task->GetTaskType() == taskType) + { + RemoveTaskSecondary(taskPriority); + return true; + } + + return false; +} + void CTaskManagerSA::SetTaskSecondary(CTaskSA* pTaskSecondary, const int iType) { DWORD dwFunc = FUNC_SetTaskSecondary; diff --git a/Client/game_sa/CTaskManagerSA.h b/Client/game_sa/CTaskManagerSA.h index bb993666216..946f3d4a1ed 100644 --- a/Client/game_sa/CTaskManagerSA.h +++ b/Client/game_sa/CTaskManagerSA.h @@ -57,6 +57,7 @@ class CTaskManagerSA : public CTaskManager CTask* FindActiveTaskByType(const int iTaskType); CTask* FindTaskByType(const int iPriority, const int iTaskType); void RemoveTaskSecondary(const int iTaskPriority); + bool RemoveTaskSecondary(const int taskPriority, const int taskType); void SetTaskSecondary(CTaskSA* pTaskSecondary, const int iType); CTask* GetTaskSecondary(const int iType); // code it bool HasTaskSecondary(const CTask* pTaskSecondary); // code it diff --git a/Client/sdk/game/CTaskManager.h b/Client/sdk/game/CTaskManager.h index f89d145dd4c..edf794ce44d 100644 --- a/Client/sdk/game/CTaskManager.h +++ b/Client/sdk/game/CTaskManager.h @@ -60,6 +60,7 @@ class CTaskManager virtual CTask* FindActiveTaskByType(const int iTaskType) = 0; virtual CTask* FindTaskByType(const int iPriority, const int iTaskType) = 0; virtual void RemoveTaskSecondary(const int iTaskPriority) = 0; + virtual bool RemoveTaskSecondary(const int taskPriority, const int taskType) = 0; // virtual void SetTaskSecondary(CTask* pTaskSecondary, const int iType)=0; virtual CTask* GetTaskSecondary(const int iType) = 0; virtual bool HasTaskSecondary(const CTask* pTaskSecondary) = 0; From 7fed8edfdde4846f0e23d339b2ce8cdae0d74007 Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 29 Jan 2025 17:07:53 +0100 Subject: [PATCH 3/4] Fix bug --- Client/game_sa/CFireSA.cpp | 45 ++++++++++++++++++++++++++++++++++++++ Client/game_sa/CFireSA.h | 2 ++ Client/game_sa/CGameSA.cpp | 1 + Client/game_sa/CPedSA.cpp | 14 ++++-------- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Client/game_sa/CFireSA.cpp b/Client/game_sa/CFireSA.cpp index a3920fa77dc..33f35c749d9 100644 --- a/Client/game_sa/CFireSA.cpp +++ b/Client/game_sa/CFireSA.cpp @@ -14,6 +14,8 @@ #include "CFireSA.h" #include "CGameSA.h" #include "CPoolsSA.h" +#include +#include extern CGameSA* pGame; @@ -209,3 +211,46 @@ void CFireSA::SetNumGenerationsAllowed(char generations) { internalInterface->nNumGenerationsAllowed = generations; } + +//////////////////////////////////////////////////////////////////////// +// CFire::Extinguish +// +// Fix GH #3249 (PLAYER_ON_FIRE task is not aborted after the fire is extinguished) +//////////////////////////////////////////////////////////////////////// +static void AbortFireTask(CEntitySAInterface* entityOnFire) +{ + if (!entityOnFire) + return; + + auto ped = pGame->GetPools()->GetPed(reinterpret_cast(entityOnFire)); + if (!ped || !ped->pEntity) + return; + + CTaskManager* taskManager = ped->pEntity->GetPedIntelligence()->GetTaskManager(); + if (!taskManager) + return; + + taskManager->RemoveTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM, TASK_SIMPLE_PLAYER_ON_FIRE); +} + +#define HOOKPOS_CFire_Extinguish 0x539429 +#define HOOKSIZE_CFire_Extinguish 6 +static constexpr std::uintptr_t CONTINUE_CFire_Extinguish = 0x53942F; +static void _declspec(naked) HOOK_CFire_Extinguish() +{ + _asm + { + mov [eax+730h], edi + + push eax + call AbortFireTask + add esp, 4 + + jmp CONTINUE_CFire_Extinguish + } +} + +void CFireSA::StaticSetHooks() +{ + EZHookInstall(CFire_Extinguish); +} diff --git a/Client/game_sa/CFireSA.h b/Client/game_sa/CFireSA.h index 06a2b426d71..7e3c802151a 100644 --- a/Client/game_sa/CFireSA.h +++ b/Client/game_sa/CFireSA.h @@ -64,4 +64,6 @@ class CFireSA : public CFire void SetStrength(float fStrength); void SetNumGenerationsAllowed(char generations); CFireSAInterface* GetInterface() { return internalInterface; } + + static void StaticSetHooks(); }; diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index bbcea89897a..9a7ca0f88ba 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -245,6 +245,7 @@ CGameSA::CGameSA() CVehicleSA::StaticSetHooks(); CCheckpointSA::StaticSetHooks(); CHudSA::StaticSetHooks(); + CFireSA::StaticSetHooks(); } catch (const std::bad_alloc& e) { diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index c27efabed62..3818e0cb4d1 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -854,7 +854,7 @@ void CPedSA::SetBleeding(bool bBleeding) bool CPedSA::SetOnFire(bool onFire) { CPedSAInterface* pInterface = GetPedInterface(); - if (onFire && pInterface->pFireOnPed) + if (onFire == !!pInterface->pFireOnPed) return false; auto* fireManager = static_cast(pGame->GetFireManager()); @@ -876,17 +876,11 @@ bool CPedSA::SetOnFire(bool onFire) } else { - bool wasFire = false; - CFire* fire = fireManager->GetFire(static_cast(pInterface->pFireOnPed)); - if (fire) - { - fire->Extinguish(); - wasFire = true; - } + if (!fire) + return false; - CTaskManager* taskManager = m_pPedIntelligence->GetTaskManager(); - return wasFire || (taskManager && taskManager->RemoveTaskSecondary(TASK_SECONDARY_PARTIAL_ANIM, TASK_SIMPLE_PLAYER_ON_FIRE)); + fire->Extinguish(); } return true; From e882c0eff0081f4e9eedf67a69df1f059c8aea5f Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 29 Jan 2025 19:49:39 +0100 Subject: [PATCH 4/4] Update Client/game_sa/CFireSA.cpp Co-authored-by: Uladzislau Nikalayevich --- Client/game_sa/CFireSA.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Client/game_sa/CFireSA.cpp b/Client/game_sa/CFireSA.cpp index 33f35c749d9..94d6abbafe0 100644 --- a/Client/game_sa/CFireSA.cpp +++ b/Client/game_sa/CFireSA.cpp @@ -219,9 +219,6 @@ void CFireSA::SetNumGenerationsAllowed(char generations) //////////////////////////////////////////////////////////////////////// static void AbortFireTask(CEntitySAInterface* entityOnFire) { - if (!entityOnFire) - return; - auto ped = pGame->GetPools()->GetPed(reinterpret_cast(entityOnFire)); if (!ped || !ped->pEntity) return;