From 8af571754c112fce5f2aa8441b64269c8d76eaaa Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 31 Dec 2024 08:15:05 +0100 Subject: [PATCH 1/3] Fix bug --- Client/mods/deathmatch/logic/CClientGame.cpp | 11 ++++--- Client/mods/deathmatch/logic/CClientGame.h | 4 +-- .../CMultiplayerSA_Rendering.cpp | 32 +++++++++++++++++++ .../multiplayer_sa/multiplayer_shotsync.cpp | 7 ++-- Client/sdk/multiplayer/CMultiplayer.h | 2 +- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 99eb78de34a..1f5dc4ebc58 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3528,9 +3528,9 @@ void CClientGame::StaticDrawRadarAreasHandler() g_pClientGame->DrawRadarAreasHandler(); } -bool CClientGame::StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent) +bool CClientGame::StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface) { - return g_pClientGame->DamageHandler(pDamagePed, pEvent); + return g_pClientGame->DamageHandler(pDamagePed, pEvent, pedInterface); } void CClientGame::StaticDeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart) @@ -4183,7 +4183,7 @@ void GetDeathAnim(CClientPed* pDamagedPed, CEventDamage* pEvent, AssocGroupId& o // returning false ?? // returning true ?? // -bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent) +bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface) { // CEventDamage::AffectsPed: This is/can be called more than once for each bit of damage (and may not actually take any more health (even if we return // true)) @@ -4220,6 +4220,9 @@ bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent) if (pPedClientEntity->pClientEntity && pPedClientEntity->pClientEntity->GetGameEntity() != nullptr) { pDamagedPed = reinterpret_cast(pPedClientEntity->pClientEntity); + + // Update the damaged ped, because it might have been invalidated in onClientPedDamage/onClientPlayerDamage using setElementHealth + pedInterface = reinterpret_cast(pDamagedPed->GetGameEntity()->GetInterface()); } } } @@ -4356,8 +4359,8 @@ bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent) bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, uchar hitZone, CClientPed* pDamagedPed, CClientEntity* pInflictingEntity, CEventDamage* pEvent) { - float fPreviousHealth = pDamagedPed->m_fHealth; float fCurrentHealth = pDamagedPed->GetGamePlayer()->GetHealth(); + float fPreviousHealth = fCurrentHealth + fDamage; float fPreviousArmor = pDamagedPed->m_fArmor; float fCurrentArmor = pDamagedPed->GetGamePlayer()->GetArmor(); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index e887199fcd8..f8fe21bcf72 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -509,7 +509,7 @@ class CClientGame void SetupGlobalLuaEvents(); - static bool StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent); + static bool StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface); static void StaticDeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); static void StaticFireHandler(CFire* pFire); static bool StaticBreakTowLinkHandler(CVehicle* pTowedVehicle); @@ -560,7 +560,7 @@ class CClientGame static AnimationId StaticDrivebyAnimationHandler(AnimationId animGroup, AssocGroupId animId); static void StaticAudioZoneRadioSwitchHandler(DWORD dwStationID); - bool DamageHandler(CPed* pDamagePed, CEventDamage* pEvent); + bool DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface); void DeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); void FireHandler(CFire* pFire); bool BreakTowLinkHandler(CVehicle* pTowedVehicle); diff --git a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp index b346f258740..81ce33e3b74 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp @@ -739,6 +739,37 @@ void _declspec(naked) HOOK_CRenderer_EverythingBarRoads() } } + +////////////////////////////////////////////////////////////////////////////////////////// +// +// CRenderer::RenderEverythingBarRoads +// +// m_pRwObject can be nullptr and crash +// Fix for a crash caused by frequent re-creation of entities. +// +////////////////////////////////////////////////////////////////////////////////////////// +#define HOOKPOS_CRender_EverythingBarRoads_Loop 0x553B07 +#define HOOKSIZE_CRender_EverythingBarRoads_Loop 5 +static constexpr std::uintptr_t CONTINUE_CRender_EverythingBarRoads_Loop = 0x553C5A; +static constexpr std::uintptr_t RETURN_CRender_EverythingBarRoads_Loop = 0x553B0C; +static void _declspec(naked) HOOK_CRender_EverythingBarRoads_Loop() +{ + _asm + { + // check entity->object.m_pRwObject + mov ecx, [esi+18h] + test ecx, ecx + jz skip + + mov al, [esi+36h] + and al, 7 + jmp RETURN_CRender_EverythingBarRoads_Loop + + skip: + jmp CONTINUE_CRender_EverythingBarRoads_Loop + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::InitHooks_Rendering @@ -763,4 +794,5 @@ void CMultiplayerSA::InitHooks_Rendering() EZHookInstallChecked(RwCameraSetNearClipPlane); EZHookInstall(RenderEffects_HeliLight); EZHookInstall(CRenderer_EverythingBarRoads); + EZHookInstall(CRender_EverythingBarRoads_Loop); } diff --git a/Client/multiplayer_sa/multiplayer_shotsync.cpp b/Client/multiplayer_sa/multiplayer_shotsync.cpp index 7324cafcdf7..e8a30eff99b 100644 --- a/Client/multiplayer_sa/multiplayer_shotsync.cpp +++ b/Client/multiplayer_sa/multiplayer_shotsync.cpp @@ -760,7 +760,7 @@ void _declspec(naked) HOOK_CWeapon__Fire_Sniper() } } -bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface* affectsPed) +bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface*& affectsPed) { if (m_pDamageHandler && event) { @@ -775,7 +775,7 @@ bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface* affects CEventDamage* pEvent = pGameInterface->GetEventList()->GetEventDamage(event); pEvent->SetDamageReason(g_GenerateDamageEventReason); // Call the event - bool bReturn = m_pDamageHandler(pPed, pEvent); + bool bReturn = m_pDamageHandler(pPed, pEvent, affectsPed); // Destroy the CEventDamageSA (so we dont get a leak) pEvent->Destroy(); // Finally, return @@ -819,6 +819,9 @@ void _declspec(naked) HOOK_CEventDamage__AffectsPed() push esi mov esi, ecx + mov ecx, affectsPed + mov [esp+14h], ecx + mov ecx, HOOKPOS_CEventDamage__AffectsPed add ecx, 6 jmp ecx diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 33e349ea71a..3b9bceacc26 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -83,7 +83,7 @@ typedef bool(PreWeaponFireHandler)(class CPlayerPed* pPlayer, bool bStopIfUsingB typedef void(PostWeaponFireHandler)(); typedef void(BulletImpactHandler)(class CPed* pInitiator, class CEntity* pVictim, const CVector* pvecStartPosition, const CVector* pvecEndPosition); typedef void(BulletFireHandler)(class CPed* pInitiator, const CVector* pvecStartPosition, const CVector* pvecEndPosition); -typedef bool(DamageHandler)(class CPed* pDamagePed, class CEventDamage* pEvent); +typedef bool(DamageHandler)(class CPed* pDamagePed, class CEventDamage* pEvent, class CPedSAInterface*& pedInterface); typedef void(DeathHandler)(class CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); typedef void(FireHandler)(class CFire* pFire); typedef bool(ProjectileStopHandler)(class CEntity* owner, enum eWeaponType weaponType, class CVector* origin, float fForce, class CVector* target, From 4007710a9ba31f28d60bbacc34e17163a3711732 Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 1 Jan 2025 16:50:02 +0100 Subject: [PATCH 2/3] Cleanup --- Client/mods/deathmatch/logic/CClientGame.cpp | 23 ++++++------- Client/mods/deathmatch/logic/CClientGame.h | 4 +-- Client/mods/deathmatch/logic/CClientPed.cpp | 30 +++++++++++------ Client/mods/deathmatch/logic/CClientPed.h | 2 ++ .../CMultiplayerSA_Rendering.cpp | 32 ------------------- .../multiplayer_sa/multiplayer_shotsync.cpp | 7 ++-- Client/sdk/multiplayer/CMultiplayer.h | 2 +- 7 files changed, 37 insertions(+), 63 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 1f5dc4ebc58..b52270e22c4 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3428,6 +3428,9 @@ void CClientGame::Event_OnIngame() pHud->SetComponentVisible(HUD_VITAL_STATS, false); pHud->SetComponentVisible(HUD_AREA_NAME, false); + // Reset properties + CLuaPlayerDefs::ResetPlayerHudComponentProperty(HUD_ALL, eHudComponentProperty::ALL_PROPERTIES); + g_pMultiplayer->DeleteAndDisableGangTags(); g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(); @@ -3528,9 +3531,9 @@ void CClientGame::StaticDrawRadarAreasHandler() g_pClientGame->DrawRadarAreasHandler(); } -bool CClientGame::StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface) +bool CClientGame::StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent) { - return g_pClientGame->DamageHandler(pDamagePed, pEvent, pedInterface); + return g_pClientGame->DamageHandler(pDamagePed, pEvent); } void CClientGame::StaticDeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart) @@ -4183,7 +4186,7 @@ void GetDeathAnim(CClientPed* pDamagedPed, CEventDamage* pEvent, AssocGroupId& o // returning false ?? // returning true ?? // -bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface) +bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent) { // CEventDamage::AffectsPed: This is/can be called more than once for each bit of damage (and may not actually take any more health (even if we return // true)) @@ -4220,9 +4223,6 @@ bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAIn if (pPedClientEntity->pClientEntity && pPedClientEntity->pClientEntity->GetGameEntity() != nullptr) { pDamagedPed = reinterpret_cast(pPedClientEntity->pClientEntity); - - // Update the damaged ped, because it might have been invalidated in onClientPedDamage/onClientPlayerDamage using setElementHealth - pedInterface = reinterpret_cast(pDamagedPed->GetGameEntity()->GetInterface()); } } } @@ -4359,8 +4359,8 @@ bool CClientGame::DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAIn bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, uchar hitZone, CClientPed* pDamagedPed, CClientEntity* pInflictingEntity, CEventDamage* pEvent) { + float fPreviousHealth = pDamagedPed->m_fHealth; float fCurrentHealth = pDamagedPed->GetGamePlayer()->GetHealth(); - float fPreviousHealth = fCurrentHealth + fDamage; float fPreviousArmor = pDamagedPed->m_fArmor; float fCurrentArmor = pDamagedPed->GetGamePlayer()->GetArmor(); @@ -4404,12 +4404,9 @@ bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, return false; } - if (pDamagedPed->IsLocalPlayer()) - { - // Reget values in case they have been changed during onClientPlayerDamage event (Avoid AC#1 kick) - fCurrentHealth = pDamagedPed->GetGamePlayer()->GetHealth(); - fCurrentArmor = pDamagedPed->GetGamePlayer()->GetArmor(); - } + // Reget values in case they have been changed during onClientPlayerDamage/onClientPedDamage event (Avoid AC#1 kick) + fCurrentHealth = pDamagedPed->GetGamePlayer()->GetHealth(); + fCurrentArmor = pDamagedPed->GetGamePlayer()->GetArmor(); bool bIsBeingShotWhilstAiming = (weaponUsed >= WEAPONTYPE_PISTOL && weaponUsed <= WEAPONTYPE_MINIGUN && pDamagedPed->IsUsingGun()); bool bOldBehaviour = !IsGlitchEnabled(GLITCH_HITANIM); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index f8fe21bcf72..e887199fcd8 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -509,7 +509,7 @@ class CClientGame void SetupGlobalLuaEvents(); - static bool StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface); + static bool StaticDamageHandler(CPed* pDamagePed, CEventDamage* pEvent); static void StaticDeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); static void StaticFireHandler(CFire* pFire); static bool StaticBreakTowLinkHandler(CVehicle* pTowedVehicle); @@ -560,7 +560,7 @@ class CClientGame static AnimationId StaticDrivebyAnimationHandler(AnimationId animGroup, AssocGroupId animId); static void StaticAudioZoneRadioSwitchHandler(DWORD dwStationID); - bool DamageHandler(CPed* pDamagePed, CEventDamage* pEvent, CPedSAInterface*& pedInterface); + bool DamageHandler(CPed* pDamagePed, CEventDamage* pEvent); void DeathHandler(CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); void FireHandler(CFire* pFire); bool BreakTowLinkHandler(CVehicle* pTowedVehicle); diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index c3d2f27f918..c7508327327 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -2705,6 +2705,10 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) return; } + // Re-create ped + if (m_shouldRecreate) + ReCreateGameEntity(); + // Grab some vars here, saves getting them twice CClientVehicle* pVehicle = GetOccupiedVehicle(); @@ -3974,11 +3978,7 @@ void CClientPed::_ChangeModel() { // ChrML: Changing the skin in certain cases causes player sliding. So we recreate instead. - // Kill the old player - _DestroyModel(); - - // Create the new with the new skin - _CreateModel(); + m_shouldRecreate = true; } // ReAttach satchels @@ -4012,11 +4012,7 @@ void CClientPed::ReCreateModel() m_pLoadedModelInfo->ModelAddRef(BLOCKING, "CClientPed::ReCreateModel"); } - // Destroy the old model - _DestroyModel(); - - // Create the new model - _CreateModel(); + m_shouldRecreate = true; // Remove the reference we temporarily added again if (bSameModel) @@ -4026,6 +4022,20 @@ void CClientPed::ReCreateModel() } } +void CClientPed::ReCreateGameEntity() +{ + if (!m_shouldRecreate) + return; + + // Destroy current game entity + _DestroyModel(); + + // Create the new game entity + _CreateModel(); + + m_shouldRecreate = false; +} + void CClientPed::ModelRequestCallback(CModelInfo* pModelInfo) { // If we have a player loaded diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 5c7b2cb4a6e..2934990e059 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -566,6 +566,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule // Used to destroy the current game ped and create a new one in the same state. void ReCreateModel(); + void ReCreateGameEntity(); void _CreateModel(); void _CreateLocalModel(); @@ -725,6 +726,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool m_bPendingRebuildPlayer; uint m_uiFrameLastRebuildPlayer; bool m_bIsSyncing; + bool m_shouldRecreate{false}; bool m_bBulletImpactData; CClientEntityPtr m_pBulletImpactEntity; diff --git a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp index 81ce33e3b74..b346f258740 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp @@ -739,37 +739,6 @@ void _declspec(naked) HOOK_CRenderer_EverythingBarRoads() } } - -////////////////////////////////////////////////////////////////////////////////////////// -// -// CRenderer::RenderEverythingBarRoads -// -// m_pRwObject can be nullptr and crash -// Fix for a crash caused by frequent re-creation of entities. -// -////////////////////////////////////////////////////////////////////////////////////////// -#define HOOKPOS_CRender_EverythingBarRoads_Loop 0x553B07 -#define HOOKSIZE_CRender_EverythingBarRoads_Loop 5 -static constexpr std::uintptr_t CONTINUE_CRender_EverythingBarRoads_Loop = 0x553C5A; -static constexpr std::uintptr_t RETURN_CRender_EverythingBarRoads_Loop = 0x553B0C; -static void _declspec(naked) HOOK_CRender_EverythingBarRoads_Loop() -{ - _asm - { - // check entity->object.m_pRwObject - mov ecx, [esi+18h] - test ecx, ecx - jz skip - - mov al, [esi+36h] - and al, 7 - jmp RETURN_CRender_EverythingBarRoads_Loop - - skip: - jmp CONTINUE_CRender_EverythingBarRoads_Loop - } -} - ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::InitHooks_Rendering @@ -794,5 +763,4 @@ void CMultiplayerSA::InitHooks_Rendering() EZHookInstallChecked(RwCameraSetNearClipPlane); EZHookInstall(RenderEffects_HeliLight); EZHookInstall(CRenderer_EverythingBarRoads); - EZHookInstall(CRender_EverythingBarRoads_Loop); } diff --git a/Client/multiplayer_sa/multiplayer_shotsync.cpp b/Client/multiplayer_sa/multiplayer_shotsync.cpp index e8a30eff99b..7324cafcdf7 100644 --- a/Client/multiplayer_sa/multiplayer_shotsync.cpp +++ b/Client/multiplayer_sa/multiplayer_shotsync.cpp @@ -760,7 +760,7 @@ void _declspec(naked) HOOK_CWeapon__Fire_Sniper() } } -bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface*& affectsPed) +bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface* affectsPed) { if (m_pDamageHandler && event) { @@ -775,7 +775,7 @@ bool ProcessDamageEvent(CEventDamageSAInterface* event, CPedSAInterface*& affect CEventDamage* pEvent = pGameInterface->GetEventList()->GetEventDamage(event); pEvent->SetDamageReason(g_GenerateDamageEventReason); // Call the event - bool bReturn = m_pDamageHandler(pPed, pEvent, affectsPed); + bool bReturn = m_pDamageHandler(pPed, pEvent); // Destroy the CEventDamageSA (so we dont get a leak) pEvent->Destroy(); // Finally, return @@ -819,9 +819,6 @@ void _declspec(naked) HOOK_CEventDamage__AffectsPed() push esi mov esi, ecx - mov ecx, affectsPed - mov [esp+14h], ecx - mov ecx, HOOKPOS_CEventDamage__AffectsPed add ecx, 6 jmp ecx diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 3b9bceacc26..33e349ea71a 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -83,7 +83,7 @@ typedef bool(PreWeaponFireHandler)(class CPlayerPed* pPlayer, bool bStopIfUsingB typedef void(PostWeaponFireHandler)(); typedef void(BulletImpactHandler)(class CPed* pInitiator, class CEntity* pVictim, const CVector* pvecStartPosition, const CVector* pvecEndPosition); typedef void(BulletFireHandler)(class CPed* pInitiator, const CVector* pvecStartPosition, const CVector* pvecEndPosition); -typedef bool(DamageHandler)(class CPed* pDamagePed, class CEventDamage* pEvent, class CPedSAInterface*& pedInterface); +typedef bool(DamageHandler)(class CPed* pDamagePed, class CEventDamage* pEvent); typedef void(DeathHandler)(class CPed* pKilledPed, unsigned char ucDeathReason, unsigned char ucBodyPart); typedef void(FireHandler)(class CFire* pFire); typedef bool(ProjectileStopHandler)(class CEntity* owner, enum eWeaponType weaponType, class CVector* origin, float fForce, class CVector* target, From 632dcc2a09402e442955478acc43977dfcef6898 Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 1 Jan 2025 18:51:20 +0100 Subject: [PATCH 3/3] Update CClientPed.cpp --- Client/mods/deathmatch/logic/CClientPed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index c7508327327..74ff777d3bc 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -4024,7 +4024,7 @@ void CClientPed::ReCreateModel() void CClientPed::ReCreateGameEntity() { - if (!m_shouldRecreate) + if (!m_shouldRecreate || !m_pPlayerPed) return; // Destroy current game entity