From 5f21c32fb0725140d6d03476e08de330d429b55a Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 2 Oct 2024 15:04:49 +0200 Subject: [PATCH 1/2] Fix #3760 isPlayerCrosshairVisible returns true at the start of aiming (#3762) --- Client/game_sa/CCameraSA.cpp | 5 +++ Client/game_sa/CCameraSA.h | 13 ++---- Client/game_sa/CEntitySA.h | 2 +- Client/game_sa/CHudSA.cpp | 62 +++++++++++++++++---------- Client/game_sa/CPedIntelligenceSA.cpp | 14 ++++++ Client/game_sa/CPedIntelligenceSA.h | 1 + Client/game_sa/CPedSA.h | 13 +++++- Client/game_sa/CPlayerInfoSA.h | 7 ++- Client/sdk/game/CCamera.h | 2 + Client/sdk/game/CPed.h | 3 ++ Client/sdk/game/CPedIntelligence.h | 2 + Client/sdk/game/TaskAttack.h | 2 + 12 files changed, 87 insertions(+), 39 deletions(-) diff --git a/Client/game_sa/CCameraSA.cpp b/Client/game_sa/CCameraSA.cpp index 960ec7cfa7..2e8f6b6eb8 100644 --- a/Client/game_sa/CCameraSA.cpp +++ b/Client/game_sa/CCameraSA.cpp @@ -458,3 +458,8 @@ void CCameraSA::ResetShakeCamera() noexcept { GetInterface()->m_fCamShakeForce = 0.0f; } + +std::uint8_t CCameraSA::GetTransitionState() +{ + return GetInterface()->m_uiTransitionState; +} diff --git a/Client/game_sa/CCameraSA.h b/Client/game_sa/CCameraSA.h index 246f3362d8..6ccf5fe471 100644 --- a/Client/game_sa/CCameraSA.h +++ b/Client/game_sa/CCameraSA.h @@ -82,6 +82,7 @@ class CCameraSAInterface public: // CPlaceable CPlaceableSAInterface Placeable; + std::uint8_t specialPadding[4]; // Temporary padding due to incorrect CPlaceableSAInterface class // End CPlaceable // move these out the class, have decided to set up a mirrored enumerated type thingy at the top @@ -131,16 +132,6 @@ class CCameraSAInterface bool m_bCooperativeCamMode; bool m_bAllowShootingWith2PlayersInCar; bool m_bDisableFirstPersonInCar; - static bool m_bUseMouse3rdPerson; -#ifndef FINALBUILD - bool bStaticFrustum; -#endif - - // for debug keyboard stuff -#ifndef MASTER - unsigned char display_kbd_debug; - float kbd_fov_value; -#endif // MASTER // The following fields allow the level designers to specify the camera for 2 player games. short m_ModeForTwoPlayersSeparateCars; @@ -430,4 +421,6 @@ class CCameraSA : public CCamera void ShakeCamera(float radius, float x, float y, float z) noexcept override; void ResetShakeCamera() noexcept override; + + std::uint8_t GetTransitionState(); }; diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index 548cb657f6..fe0f2d77ae 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -123,7 +123,7 @@ class CPlaceableSAInterface // 20 bytes class CEntitySAInterface { public: - CEntitySAInterfaceVTBL* vtbl; // the virtual table + CEntitySAInterfaceVTBL* vtbl; // the virtual table it should be in the CPlaceableSAInterface CPlaceableSAInterface Placeable; // 4 diff --git a/Client/game_sa/CHudSA.cpp b/Client/game_sa/CHudSA.cpp index a63f470349..6b9c2ff770 100644 --- a/Client/game_sa/CHudSA.cpp +++ b/Client/game_sa/CHudSA.cpp @@ -13,6 +13,8 @@ #include "CHudSA.h" #include "CGameSA.h" #include "CCameraSA.h" +#include "CPlayerInfoSA.h" +#include "TaskAttackSA.h" extern CGameSA* pGame; @@ -178,35 +180,51 @@ void CHudSA::ResetComponentAdjustment() bool CHudSA::IsCrosshairVisible() { - if (!IsComponentVisible(HUD_CROSSHAIR)) - return false; + bool specialAiming = false; + bool simpleAiming = false; + // Get camera view mode CCamera* camera = pGame->GetCamera(); eCamMode cameraViewMode = static_cast(camera->GetCam(camera->GetActiveCam())->GetMode()); - switch (cameraViewMode) + // Get player + CPed* playerPed = pGame->GetPedContext(); + CWeapon* weapon = nullptr; + eWeaponType weaponType; + + // Get player current weapon + if (playerPed) + { + weapon = playerPed->GetWeapon(playerPed->GetCurrentWeaponSlot()); + if (weapon) + weaponType = weapon->GetType(); + } + + // Special aiming + if (cameraViewMode == MODE_SNIPER || cameraViewMode == MODE_1STPERSON || cameraViewMode == MODE_ROCKETLAUNCHER || cameraViewMode == MODE_ROCKETLAUNCHER_HS || cameraViewMode == MODE_M16_1STPERSON || cameraViewMode == MODE_HELICANNON_1STPERSON || cameraViewMode == MODE_CAMERA) + { + if (weapon && cameraViewMode != MODE_1STPERSON && pGame->GetWeaponInfo(weaponType, WEAPONSKILL_STD)->GetFireType() != FIRETYPE_MELEE) + specialAiming = true; + } + + // Simple aiming + if (cameraViewMode == MODE_M16_1STPERSON_RUNABOUT || cameraViewMode == MODE_ROCKETLAUNCHER_RUNABOUT || cameraViewMode == MODE_ROCKETLAUNCHER_RUNABOUT_HS || cameraViewMode == MODE_SNIPER_RUNABOUT) + simpleAiming = true; + + if ((playerPed && weapon) && !playerPed->GetTargetedObject() && playerPed->GetPedInterface()->pPlayerData->m_bFreeAiming) { - case MODE_SNIPER_RUNABOUT: - case MODE_ROCKETLAUNCHER_RUNABOUT: - case MODE_ROCKETLAUNCHER_RUNABOUT_HS: - case MODE_M16_1STPERSON_RUNABOUT: - case MODE_1STPERSON_RUNABOUT: - case MODE_AIMWEAPON: - case MODE_AIMWEAPON_ATTACHED: - case MODE_AIMWEAPON_FROMCAR: - case MODE_M16_1STPERSON: - case MODE_HELICANNON_1STPERSON: - case MODE_SNIPER: - case MODE_ROCKETLAUNCHER: - case MODE_ROCKETLAUNCHER_HS: - case MODE_AIMING: - case MODE_CAMERA: - return true; - default: - break; + CTaskSimpleUseGun* taskUseGun = playerPed->GetPedIntelligence()->GetTaskUseGun(); + if ((!taskUseGun || !taskUseGun->GetSkipAim()) && (cameraViewMode == MODE_AIMWEAPON || cameraViewMode == MODE_AIMWEAPON_FROMCAR || cameraViewMode == MODE_AIMWEAPON_ATTACHED)) + { + if (playerPed->GetPedState() != PED_ENTER_CAR && playerPed->GetPedState() != PED_CARJACK) + { + if ((weaponType >= WEAPONTYPE_PISTOL && weaponType <= WEAPONTYPE_M4) || weaponType == WEAPONTYPE_TEC9 || weaponType == WEAPONTYPE_COUNTRYRIFLE || weaponType == WEAPONTYPE_MINIGUN || weaponType == WEAPONTYPE_FLAMETHROWER) + simpleAiming = cameraViewMode != MODE_AIMWEAPON || camera->GetTransitionState() == 0; + } + } } // Check CTheScripts::bDrawCrossHair std::uint8_t crossHairType = *reinterpret_cast(VAR_CTheScripts_bDrawCrossHair); - return crossHairType > 0; + return specialAiming || simpleAiming || crossHairType > 0; } diff --git a/Client/game_sa/CPedIntelligenceSA.cpp b/Client/game_sa/CPedIntelligenceSA.cpp index 3c5b1359d0..e6752a96da 100644 --- a/Client/game_sa/CPedIntelligenceSA.cpp +++ b/Client/game_sa/CPedIntelligenceSA.cpp @@ -14,6 +14,7 @@ #include "CPedSA.h" #include "CTaskManagementSystemSA.h" #include "CTaskManagerSA.h" +#include "TaskAttackSA.h" CPedIntelligenceSA::CPedIntelligenceSA(CPedIntelligenceSAInterface* pedIntelligenceSAInterface, CPed* ped) { @@ -55,3 +56,16 @@ CTaskSAInterface* CPedIntelligenceSA::SetTaskDuckSecondary(unsigned short nLengt auto SetTaskDuckSecondary = (CTaskSAInterface * (__thiscall*)(CPedIntelligenceSAInterface*, unsigned short))0x601230; return SetTaskDuckSecondary(internalInterface, nLengthOfDuck); } + +CTaskSimpleUseGun* CPedIntelligenceSA::GetTaskUseGun() +{ + CTaskManager* taskMgr = GetTaskManager(); + if (!taskMgr) + return nullptr; + + CTask* secondaryTask = taskMgr->GetTaskSecondary(TASK_SECONDARY_ATTACK); + if (secondaryTask && secondaryTask->GetTaskType() == TASK_SIMPLE_USE_GUN) + return dynamic_cast(secondaryTask); + + return nullptr; +} diff --git a/Client/game_sa/CPedIntelligenceSA.h b/Client/game_sa/CPedIntelligenceSA.h index 7e813193c0..10cfe322ce 100644 --- a/Client/game_sa/CPedIntelligenceSA.h +++ b/Client/game_sa/CPedIntelligenceSA.h @@ -54,4 +54,5 @@ class CPedIntelligenceSA : public CPedIntelligence CTaskManager* GetTaskManager(); bool TestForStealthKill(CPed* pPed, bool bUnk); CTaskSAInterface* SetTaskDuckSecondary(unsigned short nLengthOfDuck); + CTaskSimpleUseGun* GetTaskUseGun(); }; diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index fee84fd651..668d2367c7 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -230,7 +230,12 @@ class CPedSAInterface : public CPhysicalSAInterface // +1420 = curre int iMoveAnimGroup; // 1236 BYTE bPad4b[52]; CPedIKSAInterface pedIK; // 1292 (length 32 bytes) - int bPad5[5]; + + std::uint32_t field_52C; + ePedState pedState; + eMoveState moveState; + eMoveState swimmingMoveState; + std::uint32_t field_53C; float fHealth; int iUnknown121; @@ -258,7 +263,8 @@ class CPedSAInterface : public CPhysicalSAInterface // +1420 = curre // weapons at +1440 ends at +1804 BYTE bPad4[12]; BYTE bCurrentWeaponSlot; // is actually here - BYTE bPad6[20]; + BYTE bPad6[3]; + CEntitySAInterface* pTargetedObject; BYTE bFightingStyle; // 1837 BYTE bFightingStyleExtra; BYTE bPad7[1]; @@ -408,5 +414,8 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA std::unique_ptr GetPedIK() { return std::make_unique(GetPedIKInterface()); } static void StaticSetHooks(); + CEntitySAInterface* GetTargetedObject() { return GetPedInterface()->pTargetedObject; } + ePedState GetPedState() { return GetPedInterface()->pedState; } + void GetAttachedSatchels(std::vector &satchelsList) const override; }; diff --git a/Client/game_sa/CPlayerInfoSA.h b/Client/game_sa/CPlayerInfoSA.h index a8b3a84f44..fd73385f05 100644 --- a/Client/game_sa/CPlayerInfoSA.h +++ b/Client/game_sa/CPlayerInfoSA.h @@ -41,8 +41,9 @@ class CPlayerPedDataSAInterface CVector2D m_vecFightMovement; // 12 float m_moveBlendRatio; // 20 - float m_fSprintEnergy; // 24 - // FLOAT m_fSprintControlCounter; // Removed arbitatrily to aligned next byte, should be here really + float m_fTimeCanRun; + float m_fSprintEnergy; + BYTE m_nChosenWeapon; // 28 BYTE m_nCarDangerCounter; // 29 BYTE m_pad0; // 30 @@ -68,8 +69,6 @@ class CPlayerPedDataSAInterface DWORD m_bInVehicleDontAllowWeaponChange : 1; // stop weapon change once driveby weapon has been given DWORD m_bRenderWeapon : 1; // set to false during cutscenes so that knuckledusters are not rendered - DWORD m_pad2; // 56 - long m_PlayerGroup; // 60 DWORD m_AdrenalineEndTime; // 64 diff --git a/Client/sdk/game/CCamera.h b/Client/sdk/game/CCamera.h index 7dc104e3c0..57ede01f01 100644 --- a/Client/sdk/game/CCamera.h +++ b/Client/sdk/game/CCamera.h @@ -146,4 +146,6 @@ class CCamera virtual void ShakeCamera(float radius, float x, float y, float z) noexcept = 0; virtual void ResetShakeCamera() noexcept = 0; + + virtual std::uint8_t GetTransitionState() = 0; }; diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 4e91cdb8b4..22fb276923 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -285,5 +285,8 @@ class CPed : public virtual CPhysical virtual void* GetPedNodeInterface(std::int32_t nodeId) = 0; virtual std::unique_ptr GetPedIK() = 0; + virtual CEntitySAInterface* GetTargetedObject() = 0; + virtual ePedState GetPedState() = 0; + virtual void GetAttachedSatchels(std::vector &satchelsList) const = 0; }; diff --git a/Client/sdk/game/CPedIntelligence.h b/Client/sdk/game/CPedIntelligence.h index 37704ed893..f9d662e94d 100644 --- a/Client/sdk/game/CPedIntelligence.h +++ b/Client/sdk/game/CPedIntelligence.h @@ -14,6 +14,7 @@ class CPed; class CTaskSAInterface; class CTaskManager; +class CTaskSimpleUseGun; class CPedIntelligence { @@ -21,4 +22,5 @@ class CPedIntelligence virtual CTaskManager* GetTaskManager() = 0; virtual bool TestForStealthKill(CPed* pPed, bool bUnk) = 0; virtual CTaskSAInterface* SetTaskDuckSecondary(unsigned short nLengthOfDuck) = 0; + virtual CTaskSimpleUseGun* GetTaskUseGun() = 0; }; diff --git a/Client/sdk/game/TaskAttack.h b/Client/sdk/game/TaskAttack.h index 9a63e8da20..c98d062848 100644 --- a/Client/sdk/game/TaskAttack.h +++ b/Client/sdk/game/TaskAttack.h @@ -44,6 +44,8 @@ class CTaskSimpleUseGun : public virtual CTaskSimple virtual bool ControlGun(CPed* pPed, CEntity* pTargetEntity, char nCommand) = 0; virtual bool ControlGunMove(CVector2D* pMoveVec) = 0; virtual void Reset(CPed* pPed, CEntity* pTargetEntity, CVector vecTarget, char nCommand, short nBurstLength = 1) = 0; + + virtual bool GetSkipAim() = 0; }; class CTaskSimpleFight : public virtual CTaskSimple From a550bbfff308eea5a41950a3342d11a55814663f Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 2 Oct 2024 23:59:55 +0300 Subject: [PATCH 2/2] Fix building crash (PR #3753) --- Client/game_sa/CBuildingsPoolSA.cpp | 3 +++ Client/game_sa/CEntitySA.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index caa392c132..50ae14bb3c 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -151,6 +151,9 @@ void CBuildingsPoolSA::RemoveAllBuildings() RemoveBuildingFromWorld(building); + if (building->HasMatrix()) + building->RemoveMatrix(); + pBuildsingsPool->Release(i); (*m_pOriginalBuildingsBackup)[i].first = true; diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index fe0f2d77ae..205d5415f7 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -242,6 +242,10 @@ class CEntitySAInterface using vtbl_DeleteRwObject = void(__thiscall*)(CEntitySAInterface * pEntity); ((vtbl_DeleteRwObject)this->vtbl->DeleteRwObject)(this); }; + + bool HasMatrix() const noexcept { return Placeable.matrix != nullptr; } + + void RemoveMatrix() { ((void(__thiscall*)(void*))0x54F3B0)(this); } }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface");