From ca22c2aa1e72e1214be7ef6a3cefa98c4b733371 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 17 Aug 2024 14:10:43 +0200 Subject: [PATCH 01/12] Cleanup & optimization --- Client/game_sa/CPedSA.cpp | 1148 +++++++++++----------------------- Client/game_sa/CPedSA.h | 352 ++++++----- Client/game_sa/CPedSoundSA.h | 63 +- Client/sdk/game/CPed.h | 71 ++- 4 files changed, 665 insertions(+), 969 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 009e618e8c6..7b3ad0d1332 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -10,413 +10,270 @@ *****************************************************************************/ #include "StdInc.h" -#include -#include "CFireManagerSA.h" #include "CGameSA.h" -#include "CPedModelInfoSA.h" #include "CPedSA.h" +#include "CPedModelInfoSA.h" #include "CPlayerInfoSA.h" -#include "CProjectileInfoSA.h" #include "CStatsSA.h" #include "CTaskManagerSA.h" #include "CTasksSA.h" -#include "CWeaponInfoSA.h" +#include "CProjectileInfoSA.h" #include "CWeaponStatManagerSA.h" +#include "CFireManagerSA.h" extern CGameSA* pGame; -int g_bOnlyUpdateRotations = false; +int g_onlyUpdateRotations = false; -CPedSA::CPedSA(CPedSAInterface* pPedInterface) noexcept +CPedSA::CPedSA(CPedSAInterface* pPedInterface) : m_pPedInterface(pPedInterface) { MemSetFast(m_pWeapons, 0, sizeof(CWeaponSA*) * WEAPONSLOT_MAX); } -void CPedSA::SetInterface(CEntitySAInterface* intInterface) -{ - m_pInterface = intInterface; -} - CPedSA::~CPedSA() { - if (m_pPedIntelligence) - delete m_pPedIntelligence; - if (m_pPedSound) - delete m_pPedSound; + SAFE_DELETE(m_pPedIntelligence); + SAFE_DELETE(m_pPedSound); - for (int i = 0; i < WEAPONSLOT_MAX; i++) + for (std::uint8_t i = 0; i < WEAPONSLOT_MAX; i++) { - if (m_pWeapons[i]) - delete m_pWeapons[i]; + SAFE_DELETE(m_pWeapons[i]); } // Make sure this ped is not refed in the flame shot info array - CFlameShotInfo* pInfo = (CFlameShotInfo*)ARRAY_CFlameShotInfo; - for (uint i = 0; i < MAX_FLAME_SHOT_INFOS; i++) + CFlameShotInfo* info = (CFlameShotInfo*)ARRAY_CFlameShotInfo; + for (std::uint8_t i = 0; i < MAX_FLAME_SHOT_INFOS; i++) { - if (pInfo->pInstigator == m_pInterface) + if (info->pInstigator == m_pInterface) { - pInfo->pInstigator = NULL; - pInfo->ucFlag1 = 0; + info->pInstigator = nullptr; + info->ucFlag1 = 0; } - pInfo++; + info++; } } // used to init weapons at the moment, called by CPlayerPedSA when its been constructed // can't use constructor as thats called before the interface pointer has been set the the aforementioned constructor -/** - * \todo Reimplement weapons and PedIK for SA - */ +// TODO Reimplement weapons and PedIK for SA void CPedSA::Init() { CPedSAInterface* pedInterface = GetPedInterface(); - DWORD dwPedIntelligence = 0; - DWORD dwFunc = 0x411DE0; - DWORD dwInterface = (DWORD)pedInterface; - _asm - { - mov ecx, dwInterface - call dwFunc - mov dwPedIntelligence, eax - } - CPedIntelligenceSAInterface* m_pPedIntelligenceInterface = (CPedIntelligenceSAInterface*)(dwPedIntelligence); - m_pPedIntelligence = new CPedIntelligenceSA(m_pPedIntelligenceInterface, this); + auto* pedIntelligenceInterface = static_cast(pedInterface->pPedIntelligence); + m_pPedIntelligence = new CPedIntelligenceSA(pedIntelligenceInterface, this); m_pPedSound = new CPedSoundSA(&pedInterface->pedSound); m_sDefaultVoiceType = m_pPedSound->GetVoiceTypeID(); m_sDefaultVoiceID = m_pPedSound->GetVoiceID(); - for (int i = 0; i < WEAPONSLOT_MAX; i++) - m_pWeapons[i] = new CWeaponSA(&(pedInterface->Weapons[i]), this, (eWeaponSlot)i); + for (std::uint8_t i = 0; i < WEAPONSLOT_MAX; i++) + m_pWeapons[i] = new CWeaponSA(&(pedInterface->Weapons[i]), this, static_cast(i)); - // this->m_pPedIK = new Cm_pPedIKSA(&(pedInterface->m_pPedIK)); + #ifdef PedIK_SA + this->m_pPedIK = new Cm_pPedIKSA(&(pedInterface->m_pPedIK)); + #endif } -void CPedSA::SetModelIndex(DWORD dwModelIndex) +void CPedSA::SetModelIndex(DWORD modelIndex) { - DWORD dwFunction = FUNC_SetModelIndex; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - push dwModelIndex - call dwFunction - } + // char __thiscall CPed::SetModelIndex(void *this, int a2) + ((char(__thiscall*)(CEntitySAInterface*, int))FUNC_SetModelIndex)(m_pInterface, modelIndex); // Also set the voice gender - CPedModelInfoSAInterface* pModelInfo = (CPedModelInfoSAInterface*)pGame->GetModelInfo(dwModelIndex)->GetInterface(); - if (pModelInfo) - { - DWORD dwType = pModelInfo->pedType; - GetPedInterface()->pedSound.m_bIsFemale = (dwType == 5 || dwType == 22); - } + CPedModelInfoSAInterface* modelInfo = static_cast(pGame->GetModelInfo(modelIndex)->GetInterface()); + if (!modelInfo) + return; + + DWORD dwType = modelInfo->pedType; + GetPedInterface()->pedSound.m_bIsFemale = (dwType == 5 || dwType == 22); } // Hacky thing done for the local player when changing model void CPedSA::RemoveGeometryRef() { - RpClump* pClump = (RpClump*)GetInterface()->m_pRwObject; - RpAtomic* pAtomic = (RpAtomic*)((pClump->atomics.root.next) - 0x8); - RpGeometry* pGeometry = pAtomic->geometry; - if (pGeometry->refs > 1) - pGeometry->refs--; + RpClump* clump = GetInterface()->m_pRwObject; + if (!clump) + return; + + RpAtomic* atomic = reinterpret_cast((clump->atomics.root.next) - 0x8); + if (!atomic) + return; + + RpGeometry* geometry = atomic->geometry; + if (!geometry || geometry->refs <= 0) + return; + + geometry->refs--; } bool CPedSA::IsInWater() { + if (!m_pPedIntelligence) + return false; + CTask* pTask = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); - return (pTask && (pTask->GetTaskType() == TASK_COMPLEX_IN_WATER)); + if (!pTask) + return false; + + return pTask->GetTaskType() == TASK_COMPLEX_IN_WATER; } -bool CPedSA::AddProjectile(eWeaponType eWeapon, CVector vecOrigin, float fForce, CVector* target, CEntity* targetEntity) +bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) { - return ((CProjectileInfoSA*)pGame->GetProjectileInfo())->AddProjectile((CEntitySA*)this, eWeapon, vecOrigin, fForce, target, targetEntity); + CProjectileInfo* projectileInfo = pGame->GetProjectileInfo(); + if (!projectileInfo) + return false; + + return projectileInfo->AddProjectile(static_cast(this), weaponType, origin, force, target, targetEntity); } void CPedSA::DetachPedFromEntity() { - DWORD dwFunc = FUNC_DetachPedFromEntity; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - call dwFunc - } + // void __thiscall CPed::DettachPedFromEntity(CPed *this) + ((void(__thiscall*)(CEntitySAInterface*))FUNC_DetachPedFromEntity)(m_pInterface); } bool CPedSA::InternalAttachEntityToEntity(DWORD dwEntityInterface, const CVector* vecPosition, const CVector* vecRotation) { - AttachPedToEntity(dwEntityInterface, const_cast(vecPosition), 0, 0.0f, WEAPONTYPE_UNARMED, FALSE); + AttachPedToEntity(dwEntityInterface, const_cast(vecPosition), 0, 0.0f, WEAPONTYPE_UNARMED, false); return true; } -void CPedSA::AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, - bool bChangeCamera) +void CPedSA::AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera) { // sDirection and fRotationLimit only apply to first-person shooting (bChangeCamera) - DWORD dwFunc = FUNC_AttachPedToEntity; - DWORD dwThis = (DWORD)GetInterface(); - float fX = vector->fX; - float fY = vector->fY; - float fZ = vector->fZ; - BYTE bPedType = ((CPedSAInterface*)GetInterface())->bPedType; + CPedSAInterface* pedInterface = GetPedInterface(); + std::uint8_t pedType = pedInterface->bPedType; // Hack the CPed type(?) to non-player so the camera doesn't get changed if (!bChangeCamera) - ((CPedSAInterface*)GetInterface())->bPedType = 2; + pedInterface->bPedType = 2; - _asm - { - push weaponType - push fRotationLimit - movzx ecx, sDirection - push ecx - push fZ - push fY - push fX - push dwEntityInterface - mov ecx, dwThis - call dwFunc - } + // CEntity *__thiscall CPed::AttachPedToEntity(CPed *this, CEntity *a2, float arg4, float a4, float a5, __int16 a6, int a7, eWeaponType a3) + ((CEntitySAInterface*(__thiscall*)(CEntitySAInterface*, CEntitySAInterface*, float, float, float, std::uint16_t, float, std::uint8_t))FUNC_AttachPedToEntity)(m_pInterface, reinterpret_cast(dwEntityInterface), vector->fX, vector->fY, vector->fZ, sDirection, fRotationLimit, static_cast(weaponType)); // Hack the CPed type(?) to whatever it was set to - if (!bChangeCamera)((CPedSAInterface*)GetInterface())->bPedType = bPedType; + if (!bChangeCamera) + pedInterface->bPedType = pedType; } CVehicle* CPedSA::GetVehicle() { - if (((CPedSAInterface*)GetInterface())->pedFlags.bInVehicle) - { - CVehicleSAInterface* vehicle = (CVehicleSAInterface*)(((CPedSAInterface*)GetInterface())->pVehicle); - if (vehicle) - { - SClientEntity* pVehicleClientEntity = pGame->GetPools()->GetVehicle((DWORD*)vehicle); - return pVehicleClientEntity ? pVehicleClientEntity->pEntity : nullptr; - } - } - return NULL; -} - -void CPedSA::Respawn(CVector* position, bool bCameraCut) -{ - CPed* pLocalPlayer = pGame->GetPools()->GetPedFromRef((DWORD)1); - - if (!bCameraCut) - { - // DISABLE call to CCamera__RestoreWithJumpCut when respawning - MemSet((void*)0x4422EA, 0x90, 20); - } - - float fX = position->fX; - float fY = position->fY; - float fZ = position->fZ; - float fUnk = 1.0f; - DWORD dwFunc = FUNC_RestorePlayerStuffDuringResurrection; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - push fUnk - push fZ - push fY - push fX - push dwThis - call dwFunc - add esp, 20 - } -#if 0 // Removed to see if it reduces crashes - dwFunc = 0x441440; // CGameLogic::SortOutStreamingAndMemory - fUnk = 10.0f; - _asm - { - push fUnk - push position - call dwFunc - add esp, 8 - } -#endif - dwFunc = FUNC_RemoveGogglesModel; - _asm - { - mov ecx, dwThis - call dwFunc - } + CPedSAInterface* pedInterface = GetPedInterface(); + if (!pedInterface || !pedInterface->pedFlags.bInVehicle) + return nullptr; - if (!bCameraCut) - { - // B9 28 F0 B6 00 E8 4C 9A 0C 00 B9 28 F0 B6 00 E8 B2 97 0C 00 - unsigned char szCode[] = {0xB9, 0x28, 0xF0, 0xB6, 0x00, 0xE8, 0x4C, 0x9A, 0x0C, 0x00, 0xB9, 0x28, 0xF0, 0xB6, 0x00, 0xE8, 0xB2, 0x97, 0x0C, 0x00}; - // RE-ENABLE call to CCamera__RestoreWithJumpCut when respawning - MemCpy((void*)0x4422EA, szCode, 20); - } - // OutputDebugString ( "Respawn!!!!" ); -} + CVehicleSAInterface* vehicleInterface = pedInterface->pVehicle; + if (!vehicleInterface) + return nullptr; -float CPedSA::GetHealth() -{ - return GetPedInterface()->fHealth; + SClientEntity* vehicleClientEntity = pGame->GetPools()->GetVehicle(reinterpret_cast(vehicleInterface)); + return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; } -void CPedSA::SetHealth(float fHealth) +void CPedSA::Respawn(CVector* position, bool cameraCut) { - GetPedInterface()->fHealth = fHealth; -} - -float CPedSA::GetArmor() -{ - return GetPedInterface()->fArmor; -} + if (!cameraCut) + // DISABLE call to CCamera::RestoreWithJumpCut when respawning + MemSet((void*)0x4422EA, 0x90, 20); -void CPedSA::SetArmor(float fArmor) -{ - GetPedInterface()->fArmor = fArmor; -} + // void __cdecl CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *player, __int128 a2) + ((void(__cdecl*)(CEntitySAInterface*, float, float, float, float))FUNC_RestorePlayerStuffDuringResurrection)(m_pInterface, position->fX, position->fY, position->fZ, 1.0f); -float CPedSA::GetOxygenLevel() -{ - return GetPedInterface()->pPlayerData->m_fBreath; -} + #ifdef SortOutStreamingAndMemory // Disabled to see if it reduces crashes + float angle = 10.0f; // angle for CRenderer::RequestObjectsInDirection -void CPedSA::SetOxygenLevel(float fOxygen) -{ - GetPedInterface()->pPlayerData->m_fBreath = fOxygen; -} + // void __cdecl CGameLogic::SortOutStreamingAndMemory(CVector *translation, float angle) + ((void(__cdecl*)(CVector*, float))FUNC_SortOutStreamingAndMemory)(position, angle); + #endif -void CPedSA::SetIsStanding(bool bStanding) -{ - DWORD dwFunc = FUNC_SetIsStanding; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - push bStanding - call dwFunc - } -} + // BYTE *__thiscall CPed::RemoveGogglesModel(CPed *this) + ((std::uint8_t*(__thiscall*)(CEntitySAInterface*))FUNC_RemoveGogglesModel)(m_pInterface); -DWORD CPedSA::GetType() -{ - return m_dwType; + if (!cameraCut) + // RE-ENABLE call to CCamera::RestoreWithJumpCut when respawning + MemCpy((void*)0x4422EA, "\xB9\x28\xF0\xB6\x00\xE8\x4C\x9A\x0C\x00\xB9\x28\xF0\xB6\x00\xE8\xB2\x97\x0C\x00", 20); } -void CPedSA::SetType(DWORD dwType) +void CPedSA::SetIsStanding(bool standing) { - m_dwType = dwType; + // int __thiscall CPed::SetIsStanding(CPed *this, unsigned __int8 a2) + ((void(__thiscall*)(CEntitySAInterface*, bool))FUNC_SetIsStanding)(m_pInterface, standing); } -void CPedSA::RemoveWeaponModel(int iModel) +void CPedSA::RemoveWeaponModel(int model) { - DWORD dwFunc = FUNC_RemoveWeaponModel; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - push iModel - call dwFunc - } + // void __thiscall CPed::RemoveWeaponModel(CPed *this, int modelID) + ((void(__thiscall*)(CEntitySAInterface*, int))FUNC_RemoveWeaponModel)(m_pInterface, model); } void CPedSA::ClearWeapon(eWeaponType weaponType) { - DWORD dwFunc = FUNC_ClearWeapon; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - push weaponType - call dwFunc - } + // BYTE *__thiscall CPed::ClearWeapon(CPed *this, eWeaponType a2) + ((std::uint8_t*(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_ClearWeapon)(m_pInterface, static_cast(weaponType)); } -CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, unsigned int uiAmmo, eWeaponSkill skill) +CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill) { + // Load weapon model if (weaponType != WEAPONTYPE_UNARMED) { - CWeaponInfo* pInfo = pGame->GetWeaponInfo(weaponType, skill); - if (pInfo) + CWeaponInfo* weaponInfo = pGame->GetWeaponInfo(weaponType, skill); + if (weaponInfo) { - int iModel = pInfo->GetModel(); - - if (iModel) + std::uint16_t model = weaponInfo->GetModel(); + if (model) { - CModelInfo* pWeaponModel = pGame->GetModelInfo(iModel); - if (pWeaponModel) + CModelInfo* modelInfo = pGame->GetModelInfo(model); + if (modelInfo) { - pWeaponModel->Request(BLOCKING, "CPedSA::GiveWeapon"); - pWeaponModel->MakeCustomModel(); + modelInfo->Request(BLOCKING, "CPedSA::GiveWeapon"); + modelInfo->MakeCustomModel(); } } + // If the weapon is satchels, load the detonator too if (weaponType == WEAPONTYPE_REMOTE_SATCHEL_CHARGE) - { - /*int iModel = pGame->GetWeaponInfo ( WEAPONTYPE_DETONATOR )->GetModel(); - if ( iModel ) - { - CModelInfo * pWeaponModel = pGame->GetModelInfo ( iModel ); - if ( pWeaponModel ) - { - pWeaponModel->Request ( true, true ); - } - }*/ - // Load the weapon and give it properly so getPedWeapon shows the weapon is there. GiveWeapon(WEAPONTYPE_DETONATOR, 1, WEAPONSKILL_STD); - } } } - DWORD dwReturn = 0; - DWORD dwFunc = FUNC_GiveWeapon; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - push 1 - push uiAmmo - push weaponType - call dwFunc - mov dwReturn, eax - } - - CWeapon* pWeapon = GetWeapon((eWeaponSlot)dwReturn); + // eWeaponType __thiscall CPed::GiveWeapon(CPed *this, eWeaponType weaponID, signed int ammo, int a4) + // Last argument is unused + eWeaponSlot weaponSlot = ((eWeaponSlot(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint32_t, std::uint8_t))FUNC_GiveWeapon)(m_pInterface, weaponType, ammo, 1); - return pWeapon; + CWeapon* weapon = GetWeapon(weaponSlot); + return weapon; } CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) { - if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE) - { - CWeapon* pWeapon = GetWeapon(pGame->GetWeaponInfo(weaponType)->GetSlot()); - if (pWeapon->GetType() == weaponType) - return pWeapon; - } - return NULL; + if (weaponType >= WEAPONTYPE_LAST_WEAPONTYPE) + return nullptr; + + CWeapon* weapon = GetWeapon(pGame->GetWeaponInfo(weaponType)->GetSlot()); + if (!weapon || weapon->GetType() != weaponType) + return nullptr; + + return weapon; } CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) { - if (weaponSlot < WEAPONSLOT_MAX) - { - return m_pWeapons[weaponSlot]; - } - else - return NULL; + return (weaponSlot >= 0 && weaponSlot < WEAPONSLOT_MAX) ? m_pWeapons[weaponSlot] : nullptr; } void CPedSA::ClearWeapons() { // Remove all the weapons - for (unsigned int i = 0; i < WEAPONSLOT_MAX; i++) + for (CWeaponSA* weapon : m_pWeapons) { - if (m_pWeapons[i]) - { - m_pWeapons[i]->SetAmmoInClip(0); - m_pWeapons[i]->SetAmmoTotal(0); - m_pWeapons[i]->Remove(); - } + weapon->SetAmmoInClip(0); + weapon->SetAmmoTotal(0); + weapon->Remove(); } } @@ -427,136 +284,92 @@ void CPedSA::RestoreLastGoodPhysicsState() SetTargetRotation(0); } -float CPedSA::GetCurrentRotation() -{ - return GetPedInterface()->fCurrentRotation; -} - -float CPedSA::GetTargetRotation() -{ - return GetPedInterface()->fTargetRotation; -} - void CPedSA::SetCurrentRotation(float fRotation) { GetPedInterface()->fCurrentRotation = fRotation; - // char szDebug[255] = {'\0'}; - // sprintf(szDebug,"CurrentRotate Offset: %d", ((DWORD)&((CPedSAInterface *)GetInterface())->CurrentRotate) - (DWORD)GetInterface()); - // OutputDebugString(szDebug); -} - -void CPedSA::SetTargetRotation(float fRotation) -{ - GetPedInterface()->fTargetRotation = fRotation; -} - -eWeaponSlot CPedSA::GetCurrentWeaponSlot() -{ - return (eWeaponSlot)GetPedInterface()->bCurrentWeaponSlot; + #ifdef DEBUG_CurrentRotation + char szDebug[255] = {'\0'}; + sprintf(szDebug,"CurrentRotate Offset: %d", ((DWORD)&((CPedSAInterface *)GetInterface())->CurrentRotate) - (DWORD)GetInterface()); + OutputDebugString(szDebug); + #endif } void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) { - if (weaponSlot < WEAPONSLOT_MAX) - { - eWeaponSlot currentSlot = GetCurrentWeaponSlot(); - if (weaponSlot != GetCurrentWeaponSlot()) - { - CWeapon* weapon = GetWeapon(currentSlot); - if (weapon) - { - CWeaponInfo* weaponInfo = weapon->GetInfo(WEAPONSKILL_STD); + if (weaponSlot >= WEAPONSLOT_MAX) + return; - if (weaponInfo) - RemoveWeaponModel(weaponInfo->GetModel()); - } + eWeaponSlot currentSlot = GetCurrentWeaponSlot(); + if (weaponSlot == currentSlot) + return; - CPedSAInterface* thisPed = (CPedSAInterface*)GetInterface(); + CWeapon* weapon = GetWeapon(currentSlot); + if (weapon) + { + CWeaponInfo* weaponInfo = weapon->GetInfo(WEAPONSKILL_STD); + if (weaponInfo) + RemoveWeaponModel(weaponInfo->GetModel()); + } - // set the new weapon slot - thisPed->bCurrentWeaponSlot = weaponSlot; + CPedSAInterface* pedInterface = GetPedInterface(); - // is the player the local player? - CPed* pPed = pGame->GetPools()->GetPedFromRef((DWORD)1); - // if ( pPed == this && thisPed->pPlayerInfo ) - //{ + // set the new weapon slot + pedInterface->bCurrentWeaponSlot = weaponSlot; - DWORD dwThis = (DWORD)GetInterface(); - if (pPed == this) - { - ((CPlayerInfoSA*)pGame->GetPlayerInfo())->GetInterface()->PlayerPedData.m_nChosenWeapon = weaponSlot; + // is the player the local player? + CPed* localPlayer = pGame->GetPools()->GetPedFromRef(static_cast(1)); + if (localPlayer == this) + { + auto* playerInfo = static_cast(pGame->GetPlayerInfo()); + playerInfo->GetInterface()->PlayerPedData.m_nChosenWeapon = weaponSlot; - DWORD dwFunc = FUNC_MakeChangesForNewWeapon_Slot; - _asm - { - mov ecx, dwThis - push weaponSlot - call dwFunc - } - } - else - { - DWORD dwFunc = FUNC_SetCurrentWeapon; - _asm - { - mov ecx, dwThis - push weaponSlot - call dwFunc - } - } - } + // void __thiscall CPlayerPed::MakeChangesForNewWeapon(CPlayerPed *this, int a3) + ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_MakeChangesForNewWeapon_Slot)(m_pInterface, static_cast(weaponSlot)); + } + else + { + // void __thiscall CPed::SetCurrentWeapon(CPed *this, int slot) + ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_SetCurrentWeapon)(m_pInterface, static_cast(weaponSlot)); } } -CVector* CPedSA::GetBonePosition(eBone bone, CVector* vecPosition) +CVector* CPedSA::GetBonePosition(eBone bone, CVector* position) { ApplySwimAndSlopeRotations(); CEntitySAInterface* entity = GetInterface(); // NOTE(botder): A crash used to occur at 0x749B7B in RpClumpForAllAtomics, because the clump pointer might have been null // for a broken model. - if (entity->m_pRwObject != nullptr) - { - // void __thiscall CPed::GetBonePosition(struct RwV3d &, unsigned int, bool) - using Signature = void(__thiscall*)(CEntitySAInterface*, CVector*, unsigned int, bool); - const auto GameFunction = reinterpret_cast(FUNC_GetBonePosition); - GameFunction(entity, vecPosition, bone, true); - } + if (entity->m_pRwObject) + // int __thiscall CPed::GetBonePosition(CPed *this, CVector *pPoint, int bone_id, bool bDynamic) + ((int(__thiscall*)(CEntitySAInterface*, CVector*, std::uint16_t, bool))FUNC_GetBonePosition)(entity, position, bone, true); // Clamp to a sane range as this function can occasionally return massive values, // which causes ProcessLineOfSight to effectively freeze - if (!IsValidPosition(*vecPosition)) - { - *vecPosition = *GetPosition(); - } + if (!IsValidPosition(*position)) + *position = *GetPosition(); - return vecPosition; + return position; } -CVector* CPedSA::GetTransformedBonePosition(eBone bone, CVector* vecPosition) +CVector* CPedSA::GetTransformedBonePosition(eBone bone, CVector* position) { ApplySwimAndSlopeRotations(); CEntitySAInterface* entity = GetInterface(); // NOTE(botder): A crash used to occur at 0x7C51A8 in RpHAnimIDGetIndex, because the clump pointer might have been null // for a broken model. - if (entity->m_pRwObject != nullptr) - { - // void __thiscall CPed::GetTransformedBonePosition(struct RwV3d &, unsigned int, bool) - using Signature = void(__thiscall*)(CEntitySAInterface*, CVector*, unsigned int, bool); - const auto GameFunction = reinterpret_cast(FUNC_GetTransformedBonePosition); - GameFunction(entity, vecPosition, bone, true); - } + if (entity->m_pRwObject) + // RwV3D *__thiscall CPed::GetTransformedBonePosition(CPed *this, RwV3D *pointsIn, int boneId, char bUpdateBones) + ((RwV3d*(__thiscall*)(CEntitySAInterface*, CVector*, std::uint16_t, bool))FUNC_GetTransformedBonePosition)(entity, position, bone, true); // Clamp to a sane range as this function can occasionally return massive values, // which causes ProcessLineOfSight to effectively freeze - if (!IsValidPosition(*vecPosition)) - { - *vecPosition = *GetPosition(); - } + if (!IsValidPosition(*position)) + *position = *GetPosition(); - return vecPosition; + return position; } // @@ -565,389 +378,210 @@ CVector* CPedSA::GetTransformedBonePosition(eBone bone, CVector* vecPosition) // void CPedSA::ApplySwimAndSlopeRotations() { - CPedSAInterface* pPedInterface = GetPedInterface(); - if (pPedInterface->pedFlags.bCalledPreRender) + CPedSAInterface* pedInterface = GetPedInterface(); + if (pedInterface->pedFlags.bCalledPreRender) return; - g_bOnlyUpdateRotations = true; - - DWORD dwFunc = FUNC_PreRenderAfterTest; - _asm - { - mov ecx, pPedInterface - call dwFunc - } - - g_bOnlyUpdateRotations = false; -} - -bool CPedSA::IsDucking() -{ - return ((CPedSAInterface*)GetInterface())->pedFlags.bIsDucking; -} - -void CPedSA::SetDucking(bool bDuck) -{ - ((CPedSAInterface*)GetInterface())->pedFlags.bIsDucking = bDuck; -} - -int CPedSA::GetCantBeKnockedOffBike() -{ - return ((CPedSAInterface*)GetInterface())->pedFlags.CantBeKnockedOffBike; + // void __thiscall CPed::PreRenderAfterTest(CPed *this) + g_onlyUpdateRotations = true; + ((void(__thiscall*)(CEntitySAInterface*))FUNC_PreRenderAfterTest)(pedInterface); + g_onlyUpdateRotations = false; } -void CPedSA::SetCantBeKnockedOffBike(int iCantBeKnockedOffBike) +void CPedSA::SetGogglesState(bool isWearingThem) { - ((CPedSAInterface*)GetInterface())->pedFlags.CantBeKnockedOffBike = iCantBeKnockedOffBike; + // void __thiscall CPed::PutOnGoggles(CPed *this) + // void __thiscall CPed::TakeOffGoggles(CPed *this) + std::uintptr_t enableGoggleFunc = isWearingThem ? FUNC_PutOnGoggles : FUNC_TakeOffGoggles; + ((void(__thiscall*)(CEntitySAInterface*))enableGoggleFunc)(m_pInterface); } -void CPedSA::QuitEnteringCar(CVehicle* vehicle, int iSeat, bool bUnknown) +void CPedSA::SetClothesTextureAndModel(const char* texture, const char* model, int textureType) { - CVehicleSA* pVehicleSA = dynamic_cast(vehicle); - if (!pVehicleSA) + DWORD* clothes = reinterpret_cast(GetPedInterface()->pPlayerData->m_pClothes); + if (!clothes) return; - DWORD dwFunc = FUNC_QuitEnteringCar; - DWORD dwThis = (DWORD)GetInterface(); - DWORD dwVehicle = (DWORD)pVehicleSA->GetInterface(); - _asm - { - push bUnknown - push iSeat - push dwVehicle - push dwThis - call dwFunc - add esp, 16 - } + // int __fastcall CPedClothesDesc::SetTextureAndModel(DWORD* this, int unknown, char* textureName, char* modelName, eClothesTexturePart texturePart) + // Second argument is unused in CKeyGen::GetUppercaseKey + ((int(__fastcall*)(DWORD*, int, const char*, const char*, std::uint8_t))FUNC_CPedClothesDesc__SetTextureAndModel)(clothes, 0, texture, model, textureType); } -bool CPedSA::IsWearingGoggles() +void CPedSA::RebuildPlayer() { - DWORD dwFunc = FUNC_IsWearingGoggles; - DWORD dwThis = (DWORD)GetInterface(); - bool bReturn = false; - _asm - { - mov ecx, dwThis - call dwFunc - mov bReturn, al - } - return bReturn; + // void __cdecl CClothes::RebuildPlayer(CPed *ped, char bIgnoreFatAndMuscle) + ((void(__cdecl*)(CEntitySAInterface*, bool))FUNC_CClothes__RebuildPlayer)(m_pInterface, false); } -void CPedSA::SetGogglesState(bool bIsWearingThem) +void CPedSA::SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) { - DWORD dwFunc = FUNC_TakeOffGoggles; - if (bIsWearingThem) - dwFunc = FUNC_PutOnGoggles; + CPedSAInterface* pedInterface = GetPedInterface(); + std::uint8_t newStyle = static_cast(style); - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - call dwFunc - } -} + if (newStyle == pedInterface->bFightingStyle) + return; -void CPedSA::SetClothesTextureAndModel(const char* szTexture, const char* szModel, int textureType) -{ - DWORD dwFunc = FUNC_CPedClothesDesc__SetTextureAndModel; - // DWORD dwThis = (DWORD)this->GetInterface()->PlayerPedData.m_pClothes; - DWORD dwThis = (DWORD)((CPedSAInterface*)GetInterface())->pPlayerData->m_pClothes; - _asm - { - mov ecx, dwThis - push textureType - push szModel - push szTexture - call dwFunc - } -} + pedInterface->bFightingStyle = newStyle; -void CPedSA::RebuildPlayer() -{ - DWORD dwFunc = FUNC_CClothes__RebuildPlayer; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - push 0 - push dwThis - call dwFunc - add esp, 8 - } + if (styleExtra > 0 && styleExtra <= 6) + pedInterface->bFightingStyleExtra |= (1 << (styleExtra - 1)); } -eFightingStyle CPedSA::GetFightingStyle() +CEntity* CPedSA::GetContactEntity() { - return (eFightingStyle)((CPedSAInterface*)GetInterface())->bFightingStyle; -} + CEntitySAInterface* contactInterface = GetPedInterface()->pContactEntity; + if (!contactInterface) + return nullptr; -void CPedSA::SetFightingStyle(eFightingStyle style, BYTE bStyleExtra) -{ - BYTE bStyle = (BYTE)style; - BYTE* pFightingStyle = &((CPedSAInterface*)GetInterface())->bFightingStyle; - BYTE* pFightingStyleExtra = &((CPedSAInterface*)GetInterface())->bFightingStyleExtra; - if (bStyle != *pFightingStyle) + CPools* pools = pGame->GetPools(); + switch (contactInterface->nType) { - *pFightingStyle = bStyle; - if (bStyleExtra > 0 && bStyleExtra <= 6) + case ENTITY_TYPE_VEHICLE: { - bStyleExtra--; - BYTE bTemp = *pFightingStyleExtra; - switch (bStyleExtra) - { - case 0: - break; - case 1: - bTemp |= 1; - break; - case 2: - bTemp |= 2; - break; - case 3: - bTemp |= 4; - break; - case 4: - bTemp |= 8; - break; - case 5: - bTemp |= 16; - break; - } - *pFightingStyleExtra = bTemp; + SClientEntity* vehicleClientEntity = pools->GetVehicle(reinterpret_cast(contactInterface)); + return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; } - } -} - -CEntity* CPedSA::GetContactEntity() -{ - CEntitySAInterface* pInterface = ((CPedSAInterface*)GetInterface())->pContactEntity; - if (pInterface) - { - CPools* pPools = pGame->GetPools(); - switch (pInterface->nType) + case ENTITY_TYPE_OBJECT: { - case ENTITY_TYPE_VEHICLE: - { - SClientEntity* pVehicleClientEntity = pPools->GetVehicle((DWORD*)pInterface); - if (pVehicleClientEntity) - { - return pVehicleClientEntity->pEntity; - } - break; - } - case ENTITY_TYPE_OBJECT: - { - SClientEntity* pObjectClientEntity = pPools->GetObject((DWORD*)pInterface); - if (pObjectClientEntity) - { - return pObjectClientEntity->pEntity; - } - break; - } - default: - { - break; - } + SClientEntity* objectClientEntity = pools->GetObject(reinterpret_cast(contactInterface)); + return objectClientEntity ? objectClientEntity->pEntity : nullptr; } + default: + break; } - return nullptr; -} - -unsigned char CPedSA::GetRunState() -{ - return *(unsigned char*)(((DWORD)(GetInterface()) + 1332)); } CEntity* CPedSA::GetTargetedEntity() { - CEntitySAInterface* pInterface = ((CPedSAInterface*)GetInterface())->pTargetedEntity; - if (pInterface) - { - CPools* pPools = pGame->GetPools(); - return pPools->GetEntity((DWORD*)pInterface); - } - return nullptr; + CEntitySAInterface* targetInterface = GetPedInterface()->pTargetedEntity; + if (!targetInterface) + return nullptr; + + return pGame->GetPools()->GetEntity(reinterpret_cast(targetInterface)); } -void CPedSA::SetTargetedEntity(CEntity* pEntity) +void CPedSA::SetTargetedEntity(CEntity* targetEntity) { - CEntitySAInterface* pInterface = NULL; - if (pEntity) + CEntitySAInterface* targetInterface = nullptr; + if (targetEntity) { - CEntitySA* pEntitySA = dynamic_cast(pEntity); - if (pEntitySA) - pInterface = pEntitySA->GetInterface(); + CEntitySA* entity = dynamic_cast(targetEntity); + targetInterface = entity ? entity->GetInterface() : nullptr; } - ((CPedSAInterface*)GetInterface())->pTargetedEntity = pInterface; + GetPedInterface()->pTargetedEntity = targetInterface; } -bool CPedSA::GetCanBeShotInVehicle() +void CPedSA::RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) { - return GetPedInterface()->pedFlags.bCanBeShotInVehicle; + // char __thiscall CPed::RemoveBodyPart(CPed *this, int boneID, int localDir) + // second argument is unused (direction) + ((char(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint8_t))FUNC_CPed_RemoveBodyPart)(m_pInterface, boneID, direction); } -bool CPedSA::GetTestForShotInVehicle() +void CPedSA::SetFootBlood(std::uint32_t footBlood) { - return GetPedInterface()->pedFlags.bTestForShotInVehicle; -} - -void CPedSA::SetCanBeShotInVehicle(bool bShot) -{ - GetPedInterface()->pedFlags.bCanBeShotInVehicle = bShot; -} - -void CPedSA::SetTestForShotInVehicle(bool bTest) -{ - GetPedInterface()->pedFlags.bTestForShotInVehicle = bTest; -} - -void CPedSA::RemoveBodyPart(int i, char c) -{ - DWORD dwThis = (DWORD)GetInterface(); - DWORD dwFunc = FUNC_CPed_RemoveBodyPart; - _asm - { - mov ecx, dwThis - push c - push i - call dwFunc - } -} + CPedSAInterface* pedInterface = GetPedInterface(); -void CPedSA::SetFootBlood(unsigned int uiFootBlood) -{ - DWORD dwThis = (DWORD)GetInterface(); - // Check if the ped is to have foot blood - if (uiFootBlood > 0) - { + if (footBlood > 0) // Make sure the foot blood flag is activated - MemOrFast(dwThis + 0x46F, 16); - } - else if (*(unsigned short*)(dwThis + 0x46F) & 16) - { + pedInterface->pedFlags.bDoBloodyFootprints = true; + else if (pedInterface->pedFlags.bDoBloodyFootprints) // If the foot blood flag is activated, deactivate it - MemSubFast(dwThis + 0x46F, 16); - } - // Set the amount of foot blood - MemPutFast(dwThis + 0x750, uiFootBlood); -} + pedInterface->pedFlags.bDoBloodyFootprints = false; -unsigned int CPedSA::GetFootBlood() -{ - DWORD dwThis = (DWORD)GetInterface(); - // Check if the ped has the foot blood flag - if (*(unsigned short*)(dwThis + 0x46F) & 16) - { - // If the foot blood flag is activated, return the amount of foot blood - return *(unsigned int*)(dwThis + 0x750); - } - // Otherwise, return zero as there is no foot blood - return 0; + // Set the amount of foot blood + pedInterface->dwTimeWhenDead = footBlood; } -bool CPedSA::IsBleeding() +std::uint32_t CPedSA::GetFootBlood() { - return GetPedInterface()->pedFlags.bPedIsBleeding; + CPedSAInterface* pedInterface = GetPedInterface(); + + // If the foot blood flag is activated, return the amount of foot blood + return pedInterface->pedFlags.bDoBloodyFootprints ? pedInterface->dwTimeWhenDead : 0; } -void CPedSA::SetBleeding(bool bBleeding) +void CPedSA::SetOnFire(bool onFire) { - GetPedInterface()->pedFlags.bPedIsBleeding = bBleeding; -} + CPedSAInterface* pedInterface = GetPedInterface(); -bool CPedSA::IsOnFire() -{ - if (GetPedInterface()->pFireOnPed != NULL) - return true; - return false; -} + // If we are already on fire, don't apply a new fire + if ((onFire && pedInterface->pFireOnPed) || (!onFire && !pedInterface->pFireOnPed)) + { + return; + } -void CPedSA::SetOnFire(bool bOnFire) -{ - CPedSAInterface* pInterface = GetPedInterface(); + CFireManagerSA* fireManager = static_cast(pGame->GetFireManager()); + if (!fireManager) + return; - if (bOnFire) + if (onFire) { - // If we are already on fire, don't apply a new fire - if (pInterface->pFireOnPed == NULL) - { - CFireManagerSA* pFireManager = static_cast(pGame->GetFireManager()); - CFire* pFire = pFireManager->StartFire(this, NULL, (float)DEFAULT_FIRE_PARTICLE_SIZE); + CFire* fire = fireManager->StartFire(this, nullptr, static_cast(DEFAULT_FIRE_PARTICLE_SIZE)); + if (!fire) + return; - if (pFire) - { - // Start the fire - pFire->SetTarget(this); - pFire->Ignite(); - pFire->SetStrength(1.0f); - // Attach the fire only to the player, do not let it - // create child fires when moving. - pFire->SetNumGenerationsAllowed(0); - pInterface->pFireOnPed = pFire->GetInterface(); - } - } + fire->SetTarget(this); + fire->Ignite(); + fire->SetStrength(1.0f); + + // Attach the fire only to the player, do not let it + // create child fires when moving. + fire->SetNumGenerationsAllowed(0); + pedInterface->pFireOnPed = fire->GetInterface(); } else { - // Make sure that we have some attached fire - if (pInterface->pFireOnPed != NULL) - { - CFireManagerSA* pFireManager = static_cast(pGame->GetFireManager()); - CFire* pFire = pFireManager->GetFire(static_cast(pInterface->pFireOnPed)); - - if (pFire) - { - pFire->Extinguish(); - } - } + CFire* fire = fireManager->GetFire(pedInterface->pFireOnPed); + if (fire) + fire->Extinguish(); } } -void CPedSA::SetStayInSamePlace(bool bStay) +void CPedSA::GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) { - GetPedInterface()->pedFlags.bStayInSamePlace = bStay; -} + if (!m_pPedSound) + return; -void CPedSA::GetVoice(short* psVoiceType, short* psVoiceID) -{ - if (psVoiceType) - *psVoiceType = m_pPedSound->GetVoiceTypeID(); - if (psVoiceID) - *psVoiceID = m_pPedSound->GetVoiceID(); + if (voiceType) + *voiceType = m_pPedSound->GetVoiceTypeID(); + + if (voiceID) + *voiceID = m_pPedSound->GetVoiceID(); } -void CPedSA::GetVoice(const char** pszVoiceType, const char** pszVoice) +void CPedSA::GetVoice(const char** voiceType, const char** voice) { - short sVoiceType, sVoiceID; + std::int16_t sVoiceType, sVoiceID; GetVoice(&sVoiceType, &sVoiceID); - if (pszVoiceType) - *pszVoiceType = CPedSoundSA::GetVoiceTypeNameFromID(sVoiceType); - if (pszVoice) - *pszVoice = CPedSoundSA::GetVoiceNameFromID(sVoiceType, sVoiceID); + + if (voiceType) + *voiceType = CPedSoundSA::GetVoiceTypeNameFromID(sVoiceType); + if (voice) + *voice = CPedSoundSA::GetVoiceNameFromID(sVoiceType, sVoiceID); } -void CPedSA::SetVoice(short sVoiceType, short sVoiceID) +void CPedSA::SetVoice(std::int16_t voiceType, std::int16_t voiceID) { - m_pPedSound->SetVoiceTypeID(sVoiceType); - m_pPedSound->SetVoiceID(sVoiceID); + if (!m_pPedSound) + return; + + m_pPedSound->SetVoiceTypeID(voiceType); + m_pPedSound->SetVoiceID(voiceID); } -void CPedSA::SetVoice(const char* szVoiceType, const char* szVoice) +void CPedSA::SetVoice(const char* voiceType, const char* voice) { - short sVoiceType = CPedSoundSA::GetVoiceTypeIDFromName(szVoiceType); + std::int16_t sVoiceType = CPedSoundSA::GetVoiceTypeIDFromName(voiceType); if (sVoiceType < 0) return; - short sVoiceID = CPedSoundSA::GetVoiceIDFromName(sVoiceType, szVoice); + + std::int16_t sVoiceID = CPedSoundSA::GetVoiceIDFromName(sVoiceType, voice); if (sVoiceID < 0) return; - SetVoice(sVoiceType, sVoiceID); -} -void CPedSA::ResetVoice() -{ - SetVoice(m_sDefaultVoiceType, m_sDefaultVoiceID); + SetVoice(sVoiceType, sVoiceID); } // GetCurrentWeaponStat will only work if the game ped context is currently set to this ped @@ -956,57 +590,87 @@ CWeaponStat* CPedSA::GetCurrentWeaponStat() if (pGame->GetPedContext() != this) { OutputDebugLine("WARNING: GetCurrentWeaponStat ped context mismatch"); - return NULL; + return nullptr; } - CWeapon* pWeapon = GetWeapon(GetCurrentWeaponSlot()); + CWeapon* weapon = GetWeapon(GetCurrentWeaponSlot()); + if (!weapon) + return nullptr; - if (!pWeapon) - return NULL; + eWeaponType weaponType = weapon->GetType(); + std::uint16_t weaponSkillStat = pGame->GetStats()->GetSkillStatIndex(weaponType); + float skill = pGame->GetStats()->GetStatValue(weaponSkillStat); + CWeaponStat* weaponStat = pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(weaponType, skill); - eWeaponType eWeapon = pWeapon->GetType(); - ushort usStat = pGame->GetStats()->GetSkillStatIndex(eWeapon); - float fSkill = pGame->GetStats()->GetStatValue(usStat); - CWeaponStat* pWeaponStat = pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(eWeapon, fSkill); - return pWeaponStat; + return weaponStat; } float CPedSA::GetCurrentWeaponRange() { - CWeaponStat* pWeaponStat = GetCurrentWeaponStat(); - if (!pWeaponStat) - return 1; + CWeaponStat* weaponStat = GetCurrentWeaponStat(); + if (!weaponStat) + return 1.0f; - return pWeaponStat->GetWeaponRange(); + return weaponStat->GetWeaponRange(); } void CPedSA::AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) { - DWORD dwFunc = FUNC_CAEPedWeaponAudioEntity__AddAudioEvent; - CPedWeaponAudioEntitySAInterface* pThis = &GetPedInterface()->weaponAudioEntity; - _asm - { - mov ecx, pThis - push audioEventType - call dwFunc - } + // void __thiscall CAEPedWeaponAudioEntity::AddAudioEvent(CAEPedWeaponAudioEntity *this, int audioEventId) + ((void(__thiscall*)(CPedWeaponAudioEntitySAInterface*, std::uint16_t))FUNC_CAEPedWeaponAudioEntity__AddAudioEvent)(&GetPedInterface()->weaponAudioEntity, static_cast(audioEventType)); } -int CPedSA::GetCustomMoveAnim() +bool CPedSA::IsDoingGangDriveby() { - return m_iCustomMoveAnim; + if (!m_pPedIntelligence) + return false; + + CTask* task = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_PRIMARY); + if (!task) + return false; + + return task->GetTaskType() == TASK_SIMPLE_GANG_DRIVEBY; } -bool CPedSA::IsDoingGangDriveby() +float CPedSA::GetOxygenLevel() { - auto pTaskManager = m_pPedIntelligence->GetTaskManager(); - CTask* pTask = pTaskManager->GetTask(TASK_PRIORITY_PRIMARY); - if (pTask && pTask->GetTaskType() == TASK_SIMPLE_GANG_DRIVEBY) + return GetPedInterface()->pPlayerData->m_fBreath; +} + +void CPedSA::SetOxygenLevel(float oxygen) +{ + GetPedInterface()->pPlayerData->m_fBreath = oxygen; +} + +void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const +{ + // Array of projectiles objects + CProjectileSAInterface** projectilesArray = (CProjectileSAInterface**)ARRAY_CProjectile; + CProjectileSAInterface* projectileInterface; + + // Array of projectiles infos + CProjectileInfoSAInterface* projectilesInfoArray = (CProjectileInfoSAInterface*)ARRAY_CProjectileInfo; + CProjectileInfoSAInterface* projectileInfoInterface; + + // Loop through all projectiles + for (std::uint8_t i = 0; i < PROJECTILE_COUNT; i++) { - return true; - } + projectileInterface = projectilesArray[i]; + + // is attached to our ped? + if (!projectileInterface || projectileInterface->m_pAttachedEntity != m_pInterface) + continue; + + // index is always the same for both arrays + projectileInfoInterface = &projectilesInfoArray[i]; - return false; + // We are only interested in satchels + if (!projectileInfoInterface || projectileInfoInterface->dwProjectileType != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE) + continue; + + // Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges + satchelsList.push_back({projectileInterface, &projectileInterface->m_vecAttachedOffset, &projectileInterface->m_vecAttachedRotation}); + } } //////////////////////////////////////////////////////////////// @@ -1017,50 +681,35 @@ bool CPedSA::IsDoingGangDriveby() // Check if they have already been applied. // //////////////////////////////////////////////////////////////// -__declspec(noinline) int _cdecl OnCPed_PreRenderAfterTest(CPedSAInterface* pPedInterface) -{ - if (pPedInterface->pedFlags.bCalledPreRender) - return 1; // Skip slope and swim rotations - return 0; -} - -// Hook info -#define HOOKPOS_CPed_PreRenderAfterTest 0x05E65A0 -#define HOOKSIZE_CPed_PreRenderAfterTest 15 -DWORD RETURN_CPed_PreRenderAfterTest = 0x05E65AF; -DWORD RETURN_CPed_PreRenderAfterTestSkip = 0x05E6658; +#define HOOKPOS_CPed_PreRenderAfterTest 0x5E65A0 +#define HOOKSIZE_CPed_PreRenderAfterTest 15 +static constexpr DWORD RETURN_CPed_PreRenderAfterTest = 0x5E65AF; +static constexpr DWORD RETURN_CPed_PreRenderAfterTestSkip = 0x5E6658; void _declspec(naked) HOOK_CPed_PreRenderAfterTest() { _asm { - pushad - push ecx // this - call OnCPed_PreRenderAfterTest - mov [esp+0],eax // Put result temp - add esp, 4*1 - popad - - mov eax,[esp-32-4*1] // Get result temp + mov eax, [ecx+46Ch] // Replaced code - sub esp,70h - push ebx - push ebp - push esi - mov ebp,ecx - mov ecx,dword ptr [ebp+47Ch] - push edi + sub esp,70h + push ebx + push ebp + push esi + mov ebp, ecx + mov ecx, dword ptr [ebp+47Ch] + push edi // Check what to do - cmp eax,0 - jnz skip_rotation_update + test eax, 0x00000400 + jnz skip_rotation_update // Run code at start of CPed::PreRenderAfterTest - jmp RETURN_CPed_PreRenderAfterTest + jmp RETURN_CPed_PreRenderAfterTest skip_rotation_update: // Skip code at start of CPed::PreRenderAfterTest - jmp RETURN_CPed_PreRenderAfterTestSkip + jmp RETURN_CPed_PreRenderAfterTestSkip } } @@ -1072,19 +721,17 @@ void _declspec(naked) HOOK_CPed_PreRenderAfterTest() // Check if it should not be called because we only wanted to do the extra rotations // //////////////////////////////////////////////////////////////// - -// Hook info -#define HOOKPOS_CPed_PreRenderAfterTest_Mid 0x05E6669 -#define HOOKSIZE_CPed_PreRenderAfterTest_Mid 5 -DWORD RETURN_CPed_PreRenderAfterTest_Mid = 0x05E666E; -DWORD RETURN_CPed_PreRenderAfterTest_MidSkip = 0x05E766F; +#define HOOKPOS_CPed_PreRenderAfterTest_Mid 0x5E6669 +#define HOOKSIZE_CPed_PreRenderAfterTest_Mid 5 +static constexpr DWORD RETURN_CPed_PreRenderAfterTest_Mid = 0x5E666E; +static constexpr DWORD RETURN_CPed_PreRenderAfterTest_MidSkip = 0x5E766F; void _declspec(naked) HOOK_CPed_PreRenderAfterTest_Mid() { _asm { // Check what to do - mov eax, g_bOnlyUpdateRotations - cmp eax,0 + mov eax, g_onlyUpdateRotations + cmp eax, 0 jnz skip_tail // Replaced code @@ -1098,44 +745,13 @@ void _declspec(naked) HOOK_CPed_PreRenderAfterTest_Mid() } } -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// // // Setup hooks // -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// void CPedSA::StaticSetHooks() { EZHookInstall(CPed_PreRenderAfterTest); EZHookInstall(CPed_PreRenderAfterTest_Mid); } - -void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const -{ - // Array of projectiles objects - CProjectileSAInterface** projectilesArray = (CProjectileSAInterface**)ARRAY_CProjectile; - CProjectileSAInterface* pProjectileInterface; - - // Array of projectiles infos - CProjectileInfoSAInterface* projectilesInfoArray = (CProjectileInfoSAInterface*)ARRAY_CProjectileInfo; - CProjectileInfoSAInterface* pProjectileInfoInterface; - - // Loop through all projectiles - for (size_t i = 0; i < PROJECTILE_COUNT; i++) - { - pProjectileInterface = projectilesArray[i]; - - // is attached to our ped? - if (!pProjectileInterface || pProjectileInterface->m_pAttachedEntity != m_pInterface) - continue; - - // index is always the same for both arrays - pProjectileInfoInterface = &projectilesInfoArray[i]; - - // We are only interested in satchels - if (!pProjectileInfoInterface || pProjectileInfoInterface->dwProjectileType != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE) - continue; - - // Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges - satchelsList.push_back({pProjectileInterface, &pProjectileInterface->m_vecAttachedOffset, &pProjectileInterface->m_vecAttachedRotation}); - } -} diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index daae4684729..b5492bd4d04 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -20,53 +20,49 @@ class CPedSA; #include "CFireSA.h" #include "CPedIKSA.h" #include "CPhysicalSA.h" - #include "CPedSoundSA.h" #include "CPoolsSA.h" #include "CVehicleSA.h" #include "CWeaponSA.h" +#include "CPedIntelligenceSA.h" -class CPedIntelligenceSA; class CPlayerPedDataSAInterface; -class CPedIntelligenceSAInterface; -#include "CPedIntelligenceSA.h" +// CPed +#define FUNC_AttachPedToEntity 0x5E7CB0 // CPed::AttachPedToEntity +#define FUNC_DetachPedFromEntity 0x5E7EC0 // CPed::DettachPedFromEntity +#define FUNC_SetModelIndex 0x5E4880 // CPed::SetModelIndex +#define FUNC_SetIsStanding 0x4ABBE0 // CPed::SetIsStanding +#define FUNC_SetCurrentWeapon 0x5E61F0 // CPed::SetCurrentWeapon +#define FUNC_GiveWeapon 0x5E6080 // CPed::GiveWeapon +#define FUNC_ClearWeapon 0x5E62B0 // CPed::ClearWeapon +#define FUNC_RemoveWeaponModel 0x5E3990 // CPed::RemoveWeaponModel +#define FUNC_GetBonePosition 0x5E4280 // CPed::GetBonePosition +#define FUNC_GetTransformedBonePosition 0x5E01C0 // CPed::GetTransformedBonePosition +#define FUNC_TakeOffGoggles 0x5E6010 // CPed::TakeOffGoggles +#define FUNC_PutOnGoggles 0x5E3AE0 // CPed::PutOnGoggles +#define FUNC_RemoveGogglesModel 0x5DF170 // CPed::RemoveGogglesModel +#define FUNC_CPed_RemoveBodyPart 0x5F0140 // CPed::RemoveBodyPart +#define FUNC_PreRenderAfterTest 0x5E65A0 // CPed::PreRenderAfterTest + +// CPlayerPed +#define FUNC_MakeChangesForNewWeapon_Slot 0x60D000 // CPlayerPed::MakeChangesForNewWeapon + +// CPedClothesDesc && CClothes +#define FUNC_CPedClothesDesc__SetTextureAndModel 0x5A8080 // CPedClothesDesc::SetTextureAndModel +#define FUNC_CClothes__RebuildPlayer 0x5A82C0 // CClothes::RebuildPlayer + +// CAEPedWeaponAudioEntity +#define FUNC_CAEPedWeaponAudioEntity__AddAudioEvent 0x4E69F0 // CAEPedWeaponAudioEntity::AddAudioEvent + +// CGameLogic +#define FUNC_RestorePlayerStuffDuringResurrection 0x442060 // CGameLogic::RestorePlayerStuffDuringResurrection +#define FUNC_SortOutStreamingAndMemory 0x441440 // CGameLogic::SortOutStreamingAndMemory -#define SIZEOF_CPLAYERPED 1956 - -#define FUNC_SetModelIndex 0x5E4880 -#define FUNC_AttachPedToEntity 0x5E7CB0 -#define FUNC_RestorePlayerStuffDuringResurrection 0x442060 -#define FUNC_SetIsStanding 0x4ABBE0 -#define FUNC_MakeChangesForNewWeapon_Slot 0x60D000 - -#define FUNC_CPedClothesDesc__SetTextureAndModel 0x5A8080 -#define FUNC_CClothes__RebuildPlayer 0x5A82C0 -#define FUNC_CAEPedWeaponAudioEntity__AddAudioEvent 0x4E69F0 - -#define FUNC_QuitEnteringCar 0x650130 // really belongs in CCarEnterExit - -#define FUNC_SetCurrentWeapon 0x5E61F0 -#define FUNC_GiveWeapon 0x5E6080 -#define FUNC_GetBonePosition 0x5E4280 -#define FUNC_GetTransformedBonePosition 0x5E01C0 -#define FUNC_IsWearingGoggles 0x479D10 -#define FUNC_TakeOffGoggles 0x5E6010 -#define FUNC_PutOnGoggles 0x5E3AE0 -#define FUNC_RemoveWeaponModel 0x5E3990 -#define FUNC_RemoveGogglesModel 0x5DF170 -#define FUNC_ClearWeapon 0x5E62B0 -#define FUNC_DetachPedFromEntity 0x5E7EC0 -#define FUNC_CPed_RemoveBodyPart 0x5f0140 -#define FUNC_PreRenderAfterTest 0x5E65A0 - -#define VAR_LocalPlayer 0x94AD28 - -//+1328 = Ped state -//+1344 = ped health class CPedFlags { public: + // m_nPedFlags unsigned int bIsStanding : 1; // is ped standing on something unsigned int bWasStanding : 1; // was ped standing on something unsigned int bIsLooking : 1; // is ped looking at something or in a direction @@ -91,8 +87,7 @@ class CPedFlags unsigned int bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun unsigned int bIsPedDieAnimPlaying : 1; // is ped die animation finished so can dead now unsigned int bStayInSamePlace : 1; // when set, ped stays put - unsigned int - bKindaStayInSamePlace : 1; // when set, ped doesn't seek out opponent or cover large distances. Will still shuffle and look for cover + unsigned int bKindaStayInSamePlace : 1; // when set, ped doesn't seek out opponent or cover large distances. Will still shuffle and look for cover unsigned int bBeingChasedByPolice : 1; // use nodes for routefind unsigned int bNotAllowedToDuck : 1; // Is this ped allowed to duck at all? @@ -104,6 +99,7 @@ class CPedFlags unsigned int bStillOnValidPoly : 1; // set if the polygon the ped is on is still valid for collision unsigned int bAllowMedicsToReviveMe : 1; + // m_nSecondPedFlags unsigned int bResetWalkAnims : 1; unsigned int bOnBoat : 1; // flee but only using nodes unsigned int bBusJacked : 1; // flee but only using nodes @@ -140,6 +136,7 @@ class CPedFlags unsigned int bCrouchWhenScared : 1; unsigned int bKnockedOffBike : 1; + // m_nThirdPedFlags unsigned int bDonePositionOutOfCollision : 1; unsigned int bDontRender : 1; unsigned int bHasBeenAddedToPopulation : 1; @@ -175,8 +172,9 @@ class CPedFlags unsigned int bIsCached : 1; unsigned int bPushOtherPeds : 1; // GETS RESET EVERY FRAME - SET IN TASK: want to push other peds around (eg. leader of a group or ped trying to // get in a car) - unsigned int bHasBulletProofVest : 1; + // m_nFourthPedFlags + unsigned int bHasBulletProofVest : 1; unsigned int bUsingMobilePhone : 1; unsigned int bUpperBodyDamageAnimsOnly : 1; unsigned int bStuckUnderCar : 1; @@ -199,73 +197,109 @@ class CPedFlags unsigned int bJustGotOffTrain : 1; unsigned int bDeathPickupsPersist : 1; unsigned int bTestForShotInVehicle : 1; - // #ifdef GTA_REPLAY unsigned int bUsedForReplay : 1; // This ped is controlled by replay and should be removed when replay is done. - // #endif -}; - -class CPedWeaponAudioEntitySAInterface -{ -public: }; class CVehicleSAInterface; -class CPedSAInterface : public CPhysicalSAInterface // +1420 = current vehicle 312 first byte +class CPedSAInterface : public CPhysicalSAInterface { public: - // current weapon slot 1184 ( and +1816?) - // CPedIKSAInterface pedIK; // 528 - // CWeaponSAInterface Weapons[9]; // 1032 - BYTE bPad[348]; - CPedSoundSAInterface pedSound; - BYTE bPad11[256 - sizeof(CPedSoundSAInterface)]; + CPedSoundEntitySAInterface pedAudio; // CAEPedAudioEntity + CPedSoundSAInterface pedSound; // CAEPedSpeechAudioEntity CPedWeaponAudioEntitySAInterface weaponAudioEntity; - BYTE bPad12[216 - sizeof(CPedWeaponAudioEntitySAInterface)]; - CPedFlags pedFlags; // 1132 (16 bytes long including alignment probably) + std::uint8_t unk_43C[36]; + std::uint8_t unk_460[8]; + int unk_468; + CPedFlags pedFlags; CPedIntelligenceSAInterface* pPedIntelligence; - CPlayerPedDataSAInterface* pPlayerData; // 1152 - BYTE bPad4a[4]; - void* pedNodes[19]; - int iMoveAnimGroup; // 1236 - BYTE bPad4b[52]; - CPedIKSAInterface pedIK; // 1292 (length 32 bytes) - int bPad5[5]; - - float fHealth; - int iUnknown121; - float fArmor; - - int iUnknown313[3]; // +1356 - // +1368 = rotation - float fCurrentRotation; - float fTargetRotation; - float fRotationSpeed; - float fMoveAnim; - CEntitySAInterface* pContactEntity; - CVector unk_56C; - CVector unk_578; - - CEntitySAInterface* pLastContactEntity; - CVehicleSAInterface* pLastVehicle; - CVehicleSAInterface* pVehicle; - - int unk_590; - int unk_594; - BYTE bPedType; // ped type? 0 = player, >1 = ped? // 1432 - BYTE bPad9[7]; - CWeaponSAInterface Weapons[WEAPONSLOT_MAX]; - // weapons at +1440 ends at +1804 - BYTE bPad4[12]; - BYTE bCurrentWeaponSlot; // is actually here - BYTE bPad6[20]; - BYTE bFightingStyle; // 1837 - BYTE bFightingStyleExtra; - BYTE bPad7[1]; - CFireSAInterface* pFireOnPed; - BYTE bPad10[104]; - CEntitySAInterface* pTargetedEntity; // 1948 + CPlayerPedDataSAInterface* pPlayerData; + std::uint8_t createdBy; + std::uint8_t _pad0[3]; + void* pedNodes[19]; // AnimBlendFrameData* + int iMoveAnimGroup; + CVector2D vecAnimMovingShiftLocal; + std::uint8_t pedAcquaintance[20]; // CPedAcquaintance + RpClump* pWeaponObject; + RwFrame* pGunflashObject; + RpClump* pGogglesObject; + bool* pGogglesState; + std::int16_t weaponGunflashStateLeftHand; + std::int16_t unk_506; + std::int16_t weaponGunflashStateRightHand; + std::int16_t unk_50A; + CPedIKSAInterface pedIK; + int unk_52C; + int pedState; + int moveState; + int swimmingMoveState; + int unk_53C; + float fHealth; + float fMaxHealth; + float fArmor; + DWORD dwTimeTillWeNeedThisPed; + CVector2D vecAnimMovingShift; + float fCurrentRotation; + float fTargetRotation; + float fRotationSpeed; + float fMoveAnim; + CEntitySAInterface* pContactEntity; + CVector unk_56C; + CVector unk_578; + CEntitySAInterface* pLastContactEntity; + CVehicleSAInterface* pLastVehicle; + CVehicleSAInterface* pVehicle; + int unk_590; + int unk_594; + int bPedType; // ped type? 0 = player, >1 = ped? + void* pPedStats; + CWeaponSAInterface Weapons[WEAPONSLOT_MAX]; + int savedWeapon; + int delayedWeapon; + DWORD dwDelayedWeaponAmmo; + std::uint8_t bCurrentWeaponSlot; + std::uint8_t weaponShootingRate; + std::uint8_t weaponAccuracy; + std::uint8_t _pad; + CEntitySAInterface* pTargetedObject; + int unk_720; + int unk_724; + int unk_728; + std::uint8_t weaponSkill; + std::uint8_t bFightingStyle; + std::uint8_t bFightingStyleExtra; + std::uint8_t bPad7; + CFireSAInterface* pFireOnPed; + int unk_734; + CEntitySAInterface* pLookAtEntity; + float fLookHeading; + DWORD dwWeaponModelID; + int unk_744; + DWORD dwLookTime; + int unk_74C; + DWORD dwTimeWhenDead; // death time in MS + std::uint8_t bodyPartToRemove; + std::int16_t unk_755; + std::int16_t moneyCount; + std::int16_t unk_758; + int unk_75C; + std::uint8_t lastWeaponDamage; + std::uint8_t unk_761[3]; + CEntitySAInterface* pTargetedEntity; + std::int16_t unk_768; + CVector vecTurretOffset; + float fTurretAngleA; + float fTurretAngleB; + DWORD dwTurretPosnMode; + DWORD dwTurretAmmo; + void* pCoverPoint; // CCoverPoint* + void* pEnex; // CEntryExit* + float fRemovalDistMultiplier; + std::int16_t specialModelIndex; + std::int16_t unk_796; + int unk_798; }; +//static_assert(sizeof(CPedSAInterface) == 0x79C, "Invalid size for CPedSAInterface"); class CPedSA : public virtual CPed, public virtual CPhysicalSA { @@ -278,134 +312,132 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA CPedSAInterface* m_pPedInterface{}; CPedSoundSA* m_pPedSound{}; - short m_sDefaultVoiceType; - short m_sDefaultVoiceID; + std::int16_t m_sDefaultVoiceType; + std::int16_t m_sDefaultVoiceID; DWORD m_dwType; - unsigned char m_ucOccupiedSeat; + std::uint8_t m_ucOccupiedSeat; protected: int m_iCustomMoveAnim{ 0 }; public: - CPedSA(CPedSAInterface* pedInterface = nullptr) noexcept; + CPedSA(CPedSAInterface* pedInterface = nullptr); ~CPedSA(); - void SetInterface(CEntitySAInterface* intInterface); - CPedSAInterface* GetPedInterface() { return (CPedSAInterface*)GetInterface(); } + void SetInterface(CEntitySAInterface* intInterface) noexcept { m_pInterface = intInterface; } + CPedSAInterface* GetPedInterface() noexcept { return static_cast(m_pInterface); } void Init(); - void SetModelIndex(DWORD dwModelIndex); + void SetModelIndex(DWORD modelIndex); void RemoveGeometryRef(); - void AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, - bool bChangeCamera); + void AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera); void DetachPedFromEntity(); CVehicle* GetVehicle(); - void Respawn(CVector* position, bool bCameraCut); - bool AddProjectile(eWeaponType eWeapon, CVector vecOrigin, float fForce, CVector* target, CEntity* targetEntity); + void Respawn(CVector* position, bool cameraCut); + bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity); - float GetHealth(); - void SetHealth(float fHealth); + float GetHealth() { return GetPedInterface()->fHealth; } + void SetHealth(float health) { GetPedInterface()->fHealth = health; } - float GetArmor(); - void SetArmor(float fArmor); + float GetArmor() { return GetPedInterface()->fArmor; } + void SetArmor(float armor) { GetPedInterface()->fArmor = armor; } float GetOxygenLevel(); - void SetOxygenLevel(float fOxygen); + void SetOxygenLevel(float oxygen); - CWeapon* GiveWeapon(eWeaponType weaponType, unsigned int uiAmmo, eWeaponSkill skill); + CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill); CWeapon* GetWeapon(eWeaponSlot weaponSlot); CWeapon* GetWeapon(eWeaponType weaponType); void ClearWeapons(); - void RemoveWeaponModel(int iModel); + void RemoveWeaponModel(int model); void ClearWeapon(eWeaponType weaponType); - void SetIsStanding(bool bStanding); + void SetIsStanding(bool standing); CPedIntelligence* GetPedIntelligence() { return m_pPedIntelligence; } CPedSound* GetPedSound() { return m_pPedSound; } - DWORD GetType(); - void SetType(DWORD dwType); + DWORD GetType() { return m_dwType; } + void SetType(DWORD type) { m_dwType = type; } virtual void RestoreLastGoodPhysicsState(); - float GetCurrentRotation(); - float GetTargetRotation(); - void SetCurrentRotation(float fRotation); - void SetTargetRotation(float fRotation); + float GetCurrentRotation() { return GetPedInterface()->fCurrentRotation; } + float GetTargetRotation() { return GetPedInterface()->fTargetRotation; } + void SetCurrentRotation(float rotation); + void SetTargetRotation(float rotation) { GetPedInterface()->fTargetRotation = rotation; } - eWeaponSlot GetCurrentWeaponSlot(); + eWeaponSlot GetCurrentWeaponSlot() { return static_cast(GetPedInterface()->bCurrentWeaponSlot); } void SetCurrentWeaponSlot(eWeaponSlot weaponSlot); - CVector* GetBonePosition(eBone bone, CVector* vecPosition); - CVector* GetTransformedBonePosition(eBone bone, CVector* vecPosition); + CVector* GetBonePosition(eBone bone, CVector* position); + CVector* GetTransformedBonePosition(eBone bone, CVector* position); void ApplySwimAndSlopeRotations(); - bool IsDucking(); - void SetDucking(bool bDuck); + bool IsDucking() { return GetPedInterface()->pedFlags.bIsDucking; } + void SetDucking(bool duck) { GetPedInterface()->pedFlags.bIsDucking = duck; } bool IsInWater(); - int GetCantBeKnockedOffBike(); - void SetCantBeKnockedOffBike(int iCantBeKnockedOffBike); - void QuitEnteringCar(CVehicle* vehicle, int iSeat, bool bUnknown); + int GetCantBeKnockedOffBike() { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } + void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) { GetPedInterface()->pedFlags.CantBeKnockedOffBike = cantBeKnockedOffBike; } - bool IsWearingGoggles(); - void SetGogglesState(bool bIsWearingThem); + bool IsWearingGoggles() { return GetPedInterface()->pGogglesObject != nullptr; } + void SetGogglesState(bool isWearingThem); - void SetClothesTextureAndModel(const char* szTexture, const char* szModel, int textureType); + void SetClothesTextureAndModel(const char* texture, const char* model, int textureType); void RebuildPlayer(); - eFightingStyle GetFightingStyle(); - void SetFightingStyle(eFightingStyle style, BYTE bStyleExtra = 6); + eFightingStyle GetFightingStyle() { return static_cast(GetPedInterface()->bFightingStyle); } + void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6); CEntity* GetContactEntity(); - unsigned char GetRunState(); + std::uint8_t GetRunState() { return static_cast(GetPedInterface()->moveState); } CEntity* GetTargetedEntity(); - void SetTargetedEntity(CEntity* pEntity); + void SetTargetedEntity(CEntity* targetEntity); - bool GetCanBeShotInVehicle(); - bool GetTestForShotInVehicle(); + bool GetCanBeShotInVehicle() { return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } + bool GetTestForShotInVehicle() { return GetPedInterface()->pedFlags.bTestForShotInVehicle; } - void SetCanBeShotInVehicle(bool bShot); - void SetTestForShotInVehicle(bool bTest); + void SetCanBeShotInVehicle(bool shot) { GetPedInterface()->pedFlags.bCanBeShotInVehicle = shot; } + void SetTestForShotInVehicle(bool test) { GetPedInterface()->pedFlags.bTestForShotInVehicle = test; } bool InternalAttachEntityToEntity(DWORD dwEntityInterface, const CVector* vecPosition, const CVector* vecRotation); - BYTE GetOccupiedSeat() { return m_ucOccupiedSeat; } - void SetOccupiedSeat(BYTE seat) { m_ucOccupiedSeat = seat; } + std::uint8_t GetOccupiedSeat() const noexcept { return m_ucOccupiedSeat; } + void SetOccupiedSeat(std::uint8_t seat) noexcept { m_ucOccupiedSeat = seat; } - void RemoveBodyPart(int i, char c); + void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction); - void SetFootBlood(unsigned int uiFootBlood); - unsigned int GetFootBlood(); + void SetFootBlood(std::uint32_t footBlood); + std::uint32_t GetFootBlood(); - bool IsBleeding(); - void SetBleeding(bool bBleeding); + bool IsBleeding() { return GetPedInterface()->pedFlags.bPedIsBleeding; } + void SetBleeding(bool bleeding) { GetPedInterface()->pedFlags.bPedIsBleeding = bleeding; } - bool IsOnFire(); - void SetOnFire(bool bOnFire); + bool IsOnFire() { return GetPedInterface()->pFireOnPed != nullptr; } + void SetOnFire(bool onFire); bool GetStayInSamePlace() { return GetPedInterface()->pedFlags.bStayInSamePlace; } - void SetStayInSamePlace(bool bStay); - - void GetVoice(short* psVoiceType, short* psVoiceID); - void GetVoice(const char** pszVoiceType, const char** pszVoice); - void SetVoice(short sVoiceType, short sVoiceID); - void SetVoice(const char* szVoiceType, const char* szVoice); - void ResetVoice(); - void SetLanding(bool bIsLanding) { GetPedInterface()->pedFlags.bIsLanding = bIsLanding; } + void SetStayInSamePlace(bool stay) { GetPedInterface()->pedFlags.bStayInSamePlace = stay; } + + void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID); + void GetVoice(const char** voiceType, const char** voice); + void SetVoice(std::int16_t voiceType, std::int16_t voiceID); + void SetVoice(const char* voiceType, const char* voice); + void ResetVoice() { SetVoice(m_sDefaultVoiceType, m_sDefaultVoiceID); } + void SetLanding(bool isLanding) { GetPedInterface()->pedFlags.bIsLanding = isLanding; } void SetUpdateMetricsRequired(bool required) { GetPedInterface()->pedFlags.bUpdateMatricesRequired = required; } CWeaponStat* GetCurrentWeaponStat(); float GetCurrentWeaponRange(); void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType); - virtual int GetCustomMoveAnim(); + virtual int GetCustomMoveAnim() { return m_iCustomMoveAnim; } bool IsDoingGangDriveby(); - CPedIKSAInterface* GetPedIKInterface() { return &reinterpret_cast(m_pInterface)->pedIK; } - void* GetPedNodeInterface(std::int32_t nodeId) { return reinterpret_cast(m_pInterface)->pedNodes[nodeId]; } + CPedIKSAInterface* GetPedIKInterface() { return &GetPedInterface()->pedIK; } + void* GetPedNodeInterface(std::int32_t nodeId) { return GetPedInterface()->pedNodes[nodeId]; } std::unique_ptr GetPedIK() { return std::make_unique(GetPedIKInterface()); } static void StaticSetHooks(); diff --git a/Client/game_sa/CPedSoundSA.h b/Client/game_sa/CPedSoundSA.h index 140706b85c6..56c25e710ca 100644 --- a/Client/game_sa/CPedSoundSA.h +++ b/Client/game_sa/CPedSoundSA.h @@ -12,6 +12,8 @@ #pragma once #include +#include "CAudioEngineSA.h" +#include "CAEVehicleAudioEntitySA.h" #define FUNC_CAEPedSound__GetVoice 0x4E3CD0 // 4E3CD0 ; public: static short __cdecl CAEPedSound::GetVoice(char *,short) #define FUNC_CAEPedSound__GetAudioPedType 0x4E3C60 // 4E3C60 ; public: static short __cdecl CAEPedSound::GetAudioPedType(char *) @@ -50,15 +52,62 @@ typedef struct char szName[20]; } SPedVoiceName; -class CPedSoundSAInterface +// CAEPedSpeechAudioEntity +class CPedSoundSAInterface : public CAEAudioEntity { public: - BYTE ucPad1[0x92]; - short m_sVoiceType; - short m_sVoiceID; - short m_bIsFemale; - BYTE ucPad2[1]; - bool m_bDisabled; + std::uint8_t unk_7C[14]; + std::int8_t unk_90; + std::uint8_t unk_91; + std::int16_t m_sVoiceType; + std::int16_t m_sVoiceID; + std::int16_t m_bIsFemale; // 0 = male, 1 = female + bool m_bTalking; + bool m_bDisabled; // m_bEnableSpeech + bool m_bEnableSpeechForScripts; + std::uint8_t m_vocalEnableFlag; + std::uint8_t unk_9C[4]; // From 9C to 9F + CAESound* m_pSound; // CSound* + std::int16_t m_soundId; + std::int16_t m_bankId; + std::int16_t m_pedSpeechSlotIndex; + std::uint8_t unk_A4[4]; + float m_fVoiceVolume; + std::int16_t m_sPhraseId; + std::int16_t unk_B2; + std::uint8_t unk_B4[76]; +}; + +// CAEPedAudioEntity +class CPedSoundEntitySAInterface : public CAEAudioEntity +{ +public: + std::uint8_t unk_7C[24]; // from 7C to 8C + CEntitySAInterface* ped; + std::uint8_t unk_98[16]; // from 98 to A8 + CAETwinLoopSoundEntity twinLoopSoundEntity; + std::uint8_t unk_150[12]; // from 150 to 15C +}; + +// CAEPedWeaponAudioEntity +class CPedWeaponAudioEntitySAInterface : public CAEAudioEntity +{ +public: + bool playedMiniGunFireSound; + bool unk_7D; // CAEWeaponAudioEntity::PlayMiniGunFireSounds + std::uint8_t unk_7E[2]; // from 7E to 7F + std::uint8_t chainsawSoundState; + std::uint8_t unk_81[3]; // from 81 to 83 + std::uint32_t flameThrowerLastPlayedTime; + std::uint32_t spraycanLastPlayedTime; + std::uint32_t extinguisherLastPlayedTime; + std::uint32_t miniGunFireSoundPlayedTime; + std::uint32_t timeChainsaw; + std::uint32_t timeLastFired; + void* sounds; + bool active; + std::uint8_t unk_A1[3]; // from A1 to A3 + CEntitySAInterface* ped; }; class CPedSoundSA : public CPedSound diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 29bbf601049..e3347ed2f88 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -188,91 +188,90 @@ class CPed : public virtual CPhysical virtual void DetachPedFromEntity() = 0; virtual CVehicle* GetVehicle() = 0; - virtual void Respawn(CVector* position, bool bCameraCut) = 0; + virtual void Respawn(CVector* position, bool cameraCut) = 0; - virtual void SetModelIndex(unsigned long ulModel) = 0; + virtual void SetModelIndex(DWORD modelIndex) = 0; virtual void RemoveGeometryRef() = 0; virtual float GetHealth() = 0; - virtual void SetHealth(float fHealth) = 0; + virtual void SetHealth(float health) = 0; virtual float GetArmor() = 0; - virtual void SetArmor(float fArmor) = 0; + virtual void SetArmor(float armor) = 0; virtual float GetOxygenLevel() = 0; - virtual void SetOxygenLevel(float fOxygen) = 0; - virtual bool AddProjectile(eWeaponType eWeapon, CVector vecOrigin, float fForce, CVector* target, CEntity* targetEntity) = 0; - virtual CWeapon* GiveWeapon(eWeaponType weaponType, unsigned int uiAmmo, eWeaponSkill weaponSkill) = 0; + virtual void SetOxygenLevel(float oxyggen) = 0; + virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) = 0; + virtual CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill weaponSkill) = 0; virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) = 0; virtual CWeapon* GetWeapon(eWeaponType weaponType) = 0; virtual void ClearWeapons() = 0; - virtual void RemoveWeaponModel(int iModel) = 0; + virtual void RemoveWeaponModel(int model) = 0; virtual void ClearWeapon(eWeaponType weaponType) = 0; - virtual void SetIsStanding(bool bStanding) = 0; + virtual void SetIsStanding(bool standing) = 0; virtual DWORD GetType() = 0; virtual CPedIntelligence* GetPedIntelligence() = 0; virtual CPedSound* GetPedSound() = 0; virtual float GetCurrentRotation() = 0; virtual float GetTargetRotation() = 0; - virtual void SetCurrentRotation(float fRotation) = 0; - virtual void SetTargetRotation(float fRotation) = 0; + virtual void SetCurrentRotation(float rotation) = 0; + virtual void SetTargetRotation(float rotation) = 0; virtual eWeaponSlot GetCurrentWeaponSlot() = 0; virtual void SetCurrentWeaponSlot(eWeaponSlot weaponSlot) = 0; - virtual CVector* GetBonePosition(eBone bone, CVector* vecPosition) = 0; - virtual CVector* GetTransformedBonePosition(eBone bone, CVector* vecPosition) = 0; + virtual CVector* GetBonePosition(eBone bone, CVector* position) = 0; + virtual CVector* GetTransformedBonePosition(eBone bone, CVector* position) = 0; virtual bool IsDucking() = 0; - virtual void SetDucking(bool bDuck) = 0; + virtual void SetDucking(bool duck) = 0; virtual bool IsInWater() = 0; virtual int GetCantBeKnockedOffBike() = 0; - virtual void SetCantBeKnockedOffBike(int iCantBeKnockedOffBike) = 0; - virtual void QuitEnteringCar(CVehicle* vehicle, int iSeat, bool bUnknown) = 0; + virtual void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) = 0; - virtual void SetBleeding(bool bBleeding) = 0; + virtual void SetBleeding(bool bleeding) = 0; virtual bool IsWearingGoggles() = 0; - virtual void SetGogglesState(bool bIsWearingThem) = 0; + virtual void SetGogglesState(bool isWearingThem) = 0; - virtual void SetClothesTextureAndModel(const char* szModel, const char* szModelLocationName, int iTexture) = 0; + virtual void SetClothesTextureAndModel(const char* texture, const char* model, int textureType) = 0; virtual void RebuildPlayer() = 0; virtual eFightingStyle GetFightingStyle() = 0; - virtual void SetFightingStyle(eFightingStyle style, BYTE bStyleExtra) = 0; + virtual void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) = 0; virtual CEntity* GetContactEntity() = 0; - virtual unsigned char GetRunState() = 0; + virtual std::uint8_t GetRunState() = 0; virtual CEntity* GetTargetedEntity() = 0; - virtual void SetTargetedEntity(CEntity* pEntity) = 0; + virtual void SetTargetedEntity(CEntity* targetEntity) = 0; virtual bool GetCanBeShotInVehicle() = 0; virtual bool GetTestForShotInVehicle() = 0; - virtual void SetCanBeShotInVehicle(bool bShot) = 0; - virtual void SetTestForShotInVehicle(bool bTest) = 0; + virtual void SetCanBeShotInVehicle(bool shot) = 0; + virtual void SetTestForShotInVehicle(bool test) = 0; - virtual BYTE GetOccupiedSeat() = 0; - virtual void SetOccupiedSeat(BYTE seat) = 0; + virtual std::uint8_t GetOccupiedSeat() const noexcept = 0; + virtual void SetOccupiedSeat(std::uint8_t seat) noexcept = 0; - virtual void RemoveBodyPart(int i, char c) = 0; + virtual void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) = 0; - virtual void SetFootBlood(unsigned int uiFootBlood) = 0; - virtual unsigned int GetFootBlood() = 0; + virtual void SetFootBlood(std::uint32_t footBlood) = 0; + virtual std::uint32_t GetFootBlood() = 0; virtual bool IsOnFire() = 0; - virtual void SetOnFire(bool bOnFire) = 0; + virtual void SetOnFire(bool onFire) = 0; virtual bool GetStayInSamePlace() = 0; - virtual void SetStayInSamePlace(bool bStay) = 0; + virtual void SetStayInSamePlace(bool stay) = 0; - virtual void GetVoice(short* psVoiceType, short* psVoiceID) = 0; - virtual void GetVoice(const char** pszVoiceType, const char** pszVoice) = 0; - virtual void SetVoice(short sVoiceType, short sVoiceID) = 0; - virtual void SetVoice(const char* szVoiceType, const char* szVoice) = 0; + virtual void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) = 0; + virtual void GetVoice(const char** voiceType, const char** voice) = 0; + virtual void SetVoice(std::int16_t voiceType, std::int16_t voiceID) = 0; + virtual void SetVoice(const char* voiceType, const char* voice) = 0; virtual void ResetVoice() = 0; - virtual void SetLanding(bool bIsLanding) = 0; + virtual void SetLanding(bool isLanding) = 0; virtual void SetUpdateMetricsRequired(bool required) = 0; virtual CWeaponStat* GetCurrentWeaponStat() = 0; From b8cb523d91115c5c3a74f6e9cf33f14997d2412c Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 17 Aug 2024 16:19:06 +0200 Subject: [PATCH 02/12] Cleanups --- Client/game_sa/CPedSA.cpp | 14 ++++++-------- Client/game_sa/CPedSA.h | 26 +++++++++++--------------- Client/sdk/game/CPed.h | 6 +----- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 7b3ad0d1332..d9d4b8e2790 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -37,9 +37,7 @@ CPedSA::~CPedSA() SAFE_DELETE(m_pPedSound); for (std::uint8_t i = 0; i < WEAPONSLOT_MAX; i++) - { SAFE_DELETE(m_pWeapons[i]); - } // Make sure this ped is not refed in the flame shot info array CFlameShotInfo* info = (CFlameShotInfo*)ARRAY_CFlameShotInfo; @@ -136,27 +134,27 @@ void CPedSA::DetachPedFromEntity() ((void(__thiscall*)(CEntitySAInterface*))FUNC_DetachPedFromEntity)(m_pInterface); } -bool CPedSA::InternalAttachEntityToEntity(DWORD dwEntityInterface, const CVector* vecPosition, const CVector* vecRotation) +bool CPedSA::InternalAttachEntityToEntity(DWORD entityInteface, const CVector* position, const CVector* rotation) { - AttachPedToEntity(dwEntityInterface, const_cast(vecPosition), 0, 0.0f, WEAPONTYPE_UNARMED, false); + AttachPedToEntity(entityInteface, const_cast(position), 0, 0.0f, WEAPONTYPE_UNARMED, false); return true; } -void CPedSA::AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera) +void CPedSA::AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint16_t direction, float rotationLimit, eWeaponType weaponType, bool changeCamera) { // sDirection and fRotationLimit only apply to first-person shooting (bChangeCamera) CPedSAInterface* pedInterface = GetPedInterface(); std::uint8_t pedType = pedInterface->bPedType; // Hack the CPed type(?) to non-player so the camera doesn't get changed - if (!bChangeCamera) + if (!changeCamera) pedInterface->bPedType = 2; // CEntity *__thiscall CPed::AttachPedToEntity(CPed *this, CEntity *a2, float arg4, float a4, float a5, __int16 a6, int a7, eWeaponType a3) - ((CEntitySAInterface*(__thiscall*)(CEntitySAInterface*, CEntitySAInterface*, float, float, float, std::uint16_t, float, std::uint8_t))FUNC_AttachPedToEntity)(m_pInterface, reinterpret_cast(dwEntityInterface), vector->fX, vector->fY, vector->fZ, sDirection, fRotationLimit, static_cast(weaponType)); + ((CEntitySAInterface*(__thiscall*)(CEntitySAInterface*, CEntitySAInterface*, float, float, float, std::uint16_t, float, std::uint8_t))FUNC_AttachPedToEntity)(m_pInterface, reinterpret_cast(entityInteface), vector->fX, vector->fY, vector->fZ, direction, rotationLimit, static_cast(weaponType)); // Hack the CPed type(?) to whatever it was set to - if (!bChangeCamera) + if (!changeCamera) pedInterface->bPedType = pedType; } diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index b5492bd4d04..84ddc590810 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -9,8 +9,6 @@ * *****************************************************************************/ -class CPedSA; - #pragma once #include @@ -22,11 +20,11 @@ class CPedSA; #include "CPhysicalSA.h" #include "CPedSoundSA.h" #include "CPoolsSA.h" -#include "CVehicleSA.h" #include "CWeaponSA.h" #include "CPedIntelligenceSA.h" class CPlayerPedDataSAInterface; +class CVehicleSAInterface; // CPed #define FUNC_AttachPedToEntity 0x5E7CB0 // CPed::AttachPedToEntity @@ -200,13 +198,11 @@ class CPedFlags unsigned int bUsedForReplay : 1; // This ped is controlled by replay and should be removed when replay is done. }; -class CVehicleSAInterface; - class CPedSAInterface : public CPhysicalSAInterface { public: - CPedSoundEntitySAInterface pedAudio; // CAEPedAudioEntity - CPedSoundSAInterface pedSound; // CAEPedSpeechAudioEntity + CPedSoundEntitySAInterface pedAudio; // CAEPedAudioEntity + CPedSoundSAInterface pedSound; // CAEPedSpeechAudioEntity CPedWeaponAudioEntitySAInterface weaponAudioEntity; std::uint8_t unk_43C[36]; std::uint8_t unk_460[8]; @@ -216,10 +212,10 @@ class CPedSAInterface : public CPhysicalSAInterface CPlayerPedDataSAInterface* pPlayerData; std::uint8_t createdBy; std::uint8_t _pad0[3]; - void* pedNodes[19]; // AnimBlendFrameData* + void* pedNodes[19]; // AnimBlendFrameData* int iMoveAnimGroup; CVector2D vecAnimMovingShiftLocal; - std::uint8_t pedAcquaintance[20]; // CPedAcquaintance + std::uint8_t pedAcquaintance[20]; // CPedAcquaintance RpClump* pWeaponObject; RwFrame* pGunflashObject; RpClump* pGogglesObject; @@ -277,7 +273,7 @@ class CPedSAInterface : public CPhysicalSAInterface int unk_744; DWORD dwLookTime; int unk_74C; - DWORD dwTimeWhenDead; // death time in MS + DWORD dwTimeWhenDead; // death time in MS std::uint8_t bodyPartToRemove; std::int16_t unk_755; std::int16_t moneyCount; @@ -292,14 +288,14 @@ class CPedSAInterface : public CPhysicalSAInterface float fTurretAngleB; DWORD dwTurretPosnMode; DWORD dwTurretAmmo; - void* pCoverPoint; // CCoverPoint* - void* pEnex; // CEntryExit* + void* pCoverPoint; // CCoverPoint* + void* pEnex; // CEntryExit* float fRemovalDistMultiplier; std::int16_t specialModelIndex; std::int16_t unk_796; int unk_798; }; -//static_assert(sizeof(CPedSAInterface) == 0x79C, "Invalid size for CPedSAInterface"); +static_assert(sizeof(CPedSAInterface) == 0x79C, "Invalid size for CPedSAInterface"); class CPedSA : public virtual CPed, public virtual CPhysicalSA { @@ -330,7 +326,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void Init(); void SetModelIndex(DWORD modelIndex); void RemoveGeometryRef(); - void AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera); + void AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint16_t direction, float rotationLimit, eWeaponType weaponType, bool changeCamera); void DetachPedFromEntity(); CVehicle* GetVehicle(); @@ -402,7 +398,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void SetCanBeShotInVehicle(bool shot) { GetPedInterface()->pedFlags.bCanBeShotInVehicle = shot; } void SetTestForShotInVehicle(bool test) { GetPedInterface()->pedFlags.bTestForShotInVehicle = test; } - bool InternalAttachEntityToEntity(DWORD dwEntityInterface, const CVector* vecPosition, const CVector* vecRotation); + bool InternalAttachEntityToEntity(DWORD entityInterface, const CVector* position, const CVector* rotation) override; std::uint8_t GetOccupiedSeat() const noexcept { return m_ucOccupiedSeat; } void SetOccupiedSeat(std::uint8_t seat) noexcept { m_ucOccupiedSeat = seat; } diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index e3347ed2f88..853b6261045 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -10,13 +10,9 @@ *****************************************************************************/ #pragma once - -#include -#include "Common.h" #include "CPhysical.h" #include "CWeaponInfo.h" -class CObject; class CPedIK; class CPedIKSAInterface; class CPedIntelligence; @@ -151,7 +147,7 @@ enum eLandedPedFoot LANDED_PED_LEFT_FOOT = 1, }; -inline bool IsValidMoveAnim(uint iMoveAnim) +inline bool IsValidMoveAnim(std::uint32_t iMoveAnim) { return (iMoveAnim == MOVE_DEFAULT) || (iMoveAnim >= MOVE_PLAYER && iMoveAnim <= MOVE_JETPACK) || (iMoveAnim >= MOVE_MAN && iMoveAnim <= MOVE_SKATE); } From 0d63071438b2d3a3267bbc6c3ccf077875f98889 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 17 Aug 2024 20:20:53 +0200 Subject: [PATCH 03/12] Cleanups #2 --- Client/game_sa/CPedSA.cpp | 23 +++++++++++------------ Client/game_sa/CPedSoundSA.h | 6 ++++-- Client/sdk/game/CPed.h | 4 ++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index d9d4b8e2790..7447a96db14 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -23,7 +23,7 @@ extern CGameSA* pGame; -int g_onlyUpdateRotations = false; +static bool g_onlyUpdateRotations = false; CPedSA::CPedSA(CPedSAInterface* pPedInterface) : m_pPedInterface(pPedInterface) @@ -683,12 +683,10 @@ void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const #define HOOKSIZE_CPed_PreRenderAfterTest 15 static constexpr DWORD RETURN_CPed_PreRenderAfterTest = 0x5E65AF; static constexpr DWORD RETURN_CPed_PreRenderAfterTestSkip = 0x5E6658; -void _declspec(naked) HOOK_CPed_PreRenderAfterTest() +static void _declspec(naked) HOOK_CPed_PreRenderAfterTest() { _asm { - mov eax, [ecx+46Ch] - // Replaced code sub esp,70h push ebx @@ -699,7 +697,8 @@ void _declspec(naked) HOOK_CPed_PreRenderAfterTest() push edi // Check what to do - test eax, 0x00000400 + mov eax, [ebp+474h] // Load m_nThirdPedFlags + test eax, 400h // check bCalledPreRender flag jnz skip_rotation_update // Run code at start of CPed::PreRenderAfterTest @@ -723,23 +722,23 @@ void _declspec(naked) HOOK_CPed_PreRenderAfterTest() #define HOOKSIZE_CPed_PreRenderAfterTest_Mid 5 static constexpr DWORD RETURN_CPed_PreRenderAfterTest_Mid = 0x5E666E; static constexpr DWORD RETURN_CPed_PreRenderAfterTest_MidSkip = 0x5E766F; -void _declspec(naked) HOOK_CPed_PreRenderAfterTest_Mid() +static void _declspec(naked) HOOK_CPed_PreRenderAfterTest_Mid() { _asm { // Check what to do - mov eax, g_onlyUpdateRotations - cmp eax, 0 - jnz skip_tail + movzx eax, byte ptr g_onlyUpdateRotations + test eax, eax + jnz skip_tail // Replaced code - mov al,byte ptr ds:[00B7CB89h] + mov al, byte ptr ds:[00B7CB89h] // Run code at mid of CPed::PreRenderAfterTest - jmp RETURN_CPed_PreRenderAfterTest_Mid + jmp RETURN_CPed_PreRenderAfterTest_Mid skip_tail: // Skip code at mid of CPed::PreRenderAfterTest - jmp RETURN_CPed_PreRenderAfterTest_MidSkip + jmp RETURN_CPed_PreRenderAfterTest_MidSkip } } diff --git a/Client/game_sa/CPedSoundSA.h b/Client/game_sa/CPedSoundSA.h index 56c25e710ca..d0d4e9c071b 100644 --- a/Client/game_sa/CPedSoundSA.h +++ b/Client/game_sa/CPedSoundSA.h @@ -15,6 +15,8 @@ #include "CAudioEngineSA.h" #include "CAEVehicleAudioEntitySA.h" +class CPedSAInterface; + #define FUNC_CAEPedSound__GetVoice 0x4E3CD0 // 4E3CD0 ; public: static short __cdecl CAEPedSound::GetVoice(char *,short) #define FUNC_CAEPedSound__GetAudioPedType 0x4E3C60 // 4E3C60 ; public: static short __cdecl CAEPedSound::GetAudioPedType(char *) #define FUNC_CAEPedSound__SetPed 0x4E68D0 // 4E69D0 ; public: void __thiscall CAEPedSound::SetPed(CPedSAInterface *) @@ -83,7 +85,7 @@ class CPedSoundEntitySAInterface : public CAEAudioEntity { public: std::uint8_t unk_7C[24]; // from 7C to 8C - CEntitySAInterface* ped; + CPedSAInterface* ped; std::uint8_t unk_98[16]; // from 98 to A8 CAETwinLoopSoundEntity twinLoopSoundEntity; std::uint8_t unk_150[12]; // from 150 to 15C @@ -107,7 +109,7 @@ class CPedWeaponAudioEntitySAInterface : public CAEAudioEntity void* sounds; bool active; std::uint8_t unk_A1[3]; // from A1 to A3 - CEntitySAInterface* ped; + CPedSAInterface* ped; }; class CPedSoundSA : public CPedSound diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 853b6261045..3202d634c12 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -13,6 +13,10 @@ #include "CPhysical.h" #include "CWeaponInfo.h" +// To avoid VS intellisense highlight errors +#include +#include + class CPedIK; class CPedIKSAInterface; class CPedIntelligence; From 36940ca35d94e8b05ed4214feeaabf6356783690 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 18 Aug 2024 01:21:04 +0200 Subject: [PATCH 04/12] Review --- Client/game_sa/CPedSA.cpp | 112 +++++++++++++++----------------------- Client/game_sa/CPedSA.h | 71 ++++++++++++------------ Client/sdk/game/CPed.h | 64 +++++++++++----------- 3 files changed, 112 insertions(+), 135 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 7447a96db14..f275018ccf2 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -41,14 +41,13 @@ CPedSA::~CPedSA() // Make sure this ped is not refed in the flame shot info array CFlameShotInfo* info = (CFlameShotInfo*)ARRAY_CFlameShotInfo; - for (std::uint8_t i = 0; i < MAX_FLAME_SHOT_INFOS; i++) + for (std::uint8_t i = 0; i < MAX_FLAME_SHOT_INFOS; i++, info++) { - if (info->pInstigator == m_pInterface) - { - info->pInstigator = nullptr; - info->ucFlag1 = 0; - } - info++; + if (info->pInstigator != m_pInterface) + continue; + + info->pInstigator = nullptr; + info->ucFlag1 = 0; } } @@ -62,8 +61,8 @@ void CPedSA::Init() auto* pedIntelligenceInterface = static_cast(pedInterface->pPedIntelligence); m_pPedIntelligence = new CPedIntelligenceSA(pedIntelligenceInterface, this); - m_pPedSound = new CPedSoundSA(&pedInterface->pedSound); + m_pPedSound = new CPedSoundSA(&pedInterface->pedSound); m_sDefaultVoiceType = m_pPedSound->GetVoiceTypeID(); m_sDefaultVoiceID = m_pPedSound->GetVoiceID(); @@ -107,25 +106,19 @@ void CPedSA::RemoveGeometryRef() geometry->refs--; } -bool CPedSA::IsInWater() +bool CPedSA::IsInWater() noexcept { - if (!m_pPedIntelligence) - return false; - - CTask* pTask = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); - if (!pTask) - return false; - - return pTask->GetTaskType() == TASK_COMPLEX_IN_WATER; + CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); + return (task && task->GetTaskType() == TASK_COMPLEX_IN_WATER); } -bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) +bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity) { CProjectileInfo* projectileInfo = pGame->GetProjectileInfo(); if (!projectileInfo) return false; - return projectileInfo->AddProjectile(static_cast(this), weaponType, origin, force, target, targetEntity); + return projectileInfo->AddProjectile(static_cast(this), weaponType, origin, force, const_cast(target), const_cast(targetEntity)); } void CPedSA::DetachPedFromEntity() @@ -168,14 +161,15 @@ CVehicle* CPedSA::GetVehicle() if (!vehicleInterface) return nullptr; - SClientEntity* vehicleClientEntity = pGame->GetPools()->GetVehicle(reinterpret_cast(vehicleInterface)); + auto* vehicleClientEntity = pGame->GetPools()->GetVehicle(reinterpret_cast(vehicleInterface)); return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; } -void CPedSA::Respawn(CVector* position, bool cameraCut) +void CPedSA::Respawn(const CVector* position, bool cameraCut) { if (!cameraCut) - // DISABLE call to CCamera::RestoreWithJumpCut when respawning + // CGameLogic::RestorePlayerStuffDuringResurrection + // Disable calls to CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString & CCamera::RestoreWithJumpCut MemSet((void*)0x4422EA, 0x90, 20); // void __cdecl CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *player, __int128 a2) @@ -192,7 +186,8 @@ void CPedSA::Respawn(CVector* position, bool cameraCut) ((std::uint8_t*(__thiscall*)(CEntitySAInterface*))FUNC_RemoveGogglesModel)(m_pInterface); if (!cameraCut) - // RE-ENABLE call to CCamera::RestoreWithJumpCut when respawning + // Re-enable calls to CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString & CCamera::RestoreWithJumpCut + // Restore original bytes MemCpy((void*)0x4422EA, "\xB9\x28\xF0\xB6\x00\xE8\x4C\x9A\x0C\x00\xB9\x28\xF0\xB6\x00\xE8\xB2\x97\x0C\x00", 20); } @@ -243,31 +238,27 @@ CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponS // Last argument is unused eWeaponSlot weaponSlot = ((eWeaponSlot(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint32_t, std::uint8_t))FUNC_GiveWeapon)(m_pInterface, weaponType, ammo, 1); - CWeapon* weapon = GetWeapon(weaponSlot); - return weapon; + return GetWeapon(weaponSlot); } -CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) +CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) const noexcept { if (weaponType >= WEAPONTYPE_LAST_WEAPONTYPE) return nullptr; CWeapon* weapon = GetWeapon(pGame->GetWeaponInfo(weaponType)->GetSlot()); - if (!weapon || weapon->GetType() != weaponType) - return nullptr; - - return weapon; + return (weapon && weapon->GetType() == weaponType) ? weapon : nullptr; } -CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) +CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) const noexcept { return (weaponSlot >= 0 && weaponSlot < WEAPONSLOT_MAX) ? m_pWeapons[weaponSlot] : nullptr; } -void CPedSA::ClearWeapons() +void CPedSA::ClearWeapons() noexcept { // Remove all the weapons - for (CWeaponSA* weapon : m_pWeapons) + for (auto& weapon : m_pWeapons) { weapon->SetAmmoInClip(0); weapon->SetAmmoTotal(0); @@ -282,17 +273,6 @@ void CPedSA::RestoreLastGoodPhysicsState() SetTargetRotation(0); } -void CPedSA::SetCurrentRotation(float fRotation) -{ - GetPedInterface()->fCurrentRotation = fRotation; - - #ifdef DEBUG_CurrentRotation - char szDebug[255] = {'\0'}; - sprintf(szDebug,"CurrentRotate Offset: %d", ((DWORD)&((CPedSAInterface *)GetInterface())->CurrentRotate) - (DWORD)GetInterface()); - OutputDebugString(szDebug); - #endif -} - void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) { if (weaponSlot >= WEAPONSLOT_MAX) @@ -317,19 +297,21 @@ void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) // is the player the local player? CPed* localPlayer = pGame->GetPools()->GetPedFromRef(static_cast(1)); + std::uintptr_t changeWeaponFunc; + if (localPlayer == this) { auto* playerInfo = static_cast(pGame->GetPlayerInfo()); playerInfo->GetInterface()->PlayerPedData.m_nChosenWeapon = weaponSlot; // void __thiscall CPlayerPed::MakeChangesForNewWeapon(CPlayerPed *this, int a3) - ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_MakeChangesForNewWeapon_Slot)(m_pInterface, static_cast(weaponSlot)); + changeWeaponFunc = FUNC_MakeChangesForNewWeapon_Slot; } else - { // void __thiscall CPed::SetCurrentWeapon(CPed *this, int slot) - ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_SetCurrentWeapon)(m_pInterface, static_cast(weaponSlot)); - } + changeWeaponFunc = FUNC_SetCurrentWeapon; + + ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))changeWeaponFunc)(m_pInterface, static_cast(weaponSlot)); } CVector* CPedSA::GetBonePosition(eBone bone, CVector* position) @@ -425,7 +407,7 @@ void CPedSA::SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) pedInterface->bFightingStyleExtra |= (1 << (styleExtra - 1)); } -CEntity* CPedSA::GetContactEntity() +CEntity* CPedSA::GetContactEntity() noexcept { CEntitySAInterface* contactInterface = GetPedInterface()->pContactEntity; if (!contactInterface) @@ -436,12 +418,12 @@ CEntity* CPedSA::GetContactEntity() { case ENTITY_TYPE_VEHICLE: { - SClientEntity* vehicleClientEntity = pools->GetVehicle(reinterpret_cast(contactInterface)); + auto* vehicleClientEntity = pools->GetVehicle(reinterpret_cast(contactInterface)); return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; } case ENTITY_TYPE_OBJECT: { - SClientEntity* objectClientEntity = pools->GetObject(reinterpret_cast(contactInterface)); + auto* objectClientEntity = pools->GetObject(reinterpret_cast(contactInterface)); return objectClientEntity ? objectClientEntity->pEntity : nullptr; } default: @@ -492,9 +474,9 @@ void CPedSA::SetFootBlood(std::uint32_t footBlood) pedInterface->dwTimeWhenDead = footBlood; } -std::uint32_t CPedSA::GetFootBlood() +std::uint32_t CPedSA::GetFootBlood() const { - CPedSAInterface* pedInterface = GetPedInterface(); + const CPedSAInterface* pedInterface = GetPedInterface(); // If the foot blood flag is activated, return the amount of foot blood return pedInterface->pedFlags.bDoBloodyFootprints ? pedInterface->dwTimeWhenDead : 0; @@ -506,9 +488,7 @@ void CPedSA::SetOnFire(bool onFire) // If we are already on fire, don't apply a new fire if ((onFire && pedInterface->pFireOnPed) || (!onFire && !pedInterface->pFireOnPed)) - { return; - } CFireManagerSA* fireManager = static_cast(pGame->GetFireManager()); if (!fireManager) @@ -537,7 +517,7 @@ void CPedSA::SetOnFire(bool onFire) } } -void CPedSA::GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) +void CPedSA::GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const { if (!m_pPedSound) return; @@ -549,7 +529,7 @@ void CPedSA::GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) *voiceID = m_pPedSound->GetVoiceID(); } -void CPedSA::GetVoice(const char** voiceType, const char** voice) +void CPedSA::GetVoice(const char** voiceType, const char** voice) const { std::int16_t sVoiceType, sVoiceID; GetVoice(&sVoiceType, &sVoiceID); @@ -583,7 +563,7 @@ void CPedSA::SetVoice(const char* voiceType, const char* voice) } // GetCurrentWeaponStat will only work if the game ped context is currently set to this ped -CWeaponStat* CPedSA::GetCurrentWeaponStat() +CWeaponStat* CPedSA::GetCurrentWeaponStat() const noexcept { if (pGame->GetPedContext() != this) { @@ -598,12 +578,11 @@ CWeaponStat* CPedSA::GetCurrentWeaponStat() eWeaponType weaponType = weapon->GetType(); std::uint16_t weaponSkillStat = pGame->GetStats()->GetSkillStatIndex(weaponType); float skill = pGame->GetStats()->GetStatValue(weaponSkillStat); - CWeaponStat* weaponStat = pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(weaponType, skill); - return weaponStat; + return pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(weaponType, skill); } -float CPedSA::GetCurrentWeaponRange() +float CPedSA::GetCurrentWeaponRange() const noexcept { CWeaponStat* weaponStat = GetCurrentWeaponStat(); if (!weaponStat) @@ -618,19 +597,16 @@ void CPedSA::AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) ((void(__thiscall*)(CPedWeaponAudioEntitySAInterface*, std::uint16_t))FUNC_CAEPedWeaponAudioEntity__AddAudioEvent)(&GetPedInterface()->weaponAudioEntity, static_cast(audioEventType)); } -bool CPedSA::IsDoingGangDriveby() +bool CPedSA::IsDoingGangDriveby() const noexcept { if (!m_pPedIntelligence) return false; - CTask* task = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_PRIMARY); - if (!task) - return false; - - return task->GetTaskType() == TASK_SIMPLE_GANG_DRIVEBY; + CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_PRIMARY); + return (task && task->GetTaskType() == TASK_SIMPLE_GANG_DRIVEBY); } -float CPedSA::GetOxygenLevel() +float CPedSA::GetOxygenLevel() const { return GetPedInterface()->pPlayerData->m_fBreath; } diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 84ddc590810..ebd1e98ef9c 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -323,6 +323,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void SetInterface(CEntitySAInterface* intInterface) noexcept { m_pInterface = intInterface; } CPedSAInterface* GetPedInterface() noexcept { return static_cast(m_pInterface); } + const CPedSAInterface* GetPedInterface() const noexcept { return static_cast(m_pInterface); } void Init(); void SetModelIndex(DWORD modelIndex); void RemoveGeometryRef(); @@ -330,70 +331,70 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void DetachPedFromEntity(); CVehicle* GetVehicle(); - void Respawn(CVector* position, bool cameraCut); - bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity); + void Respawn(const CVector* position, bool cameraCut); + bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity); - float GetHealth() { return GetPedInterface()->fHealth; } + float GetHealth() const { return GetPedInterface()->fHealth; } void SetHealth(float health) { GetPedInterface()->fHealth = health; } - float GetArmor() { return GetPedInterface()->fArmor; } + float GetArmor() const { return GetPedInterface()->fArmor; } void SetArmor(float armor) { GetPedInterface()->fArmor = armor; } - float GetOxygenLevel(); + float GetOxygenLevel() const; void SetOxygenLevel(float oxygen); CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill); - CWeapon* GetWeapon(eWeaponSlot weaponSlot); - CWeapon* GetWeapon(eWeaponType weaponType); - void ClearWeapons(); + CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept; + CWeapon* GetWeapon(eWeaponType weaponType) const noexcept; + void ClearWeapons() noexcept; void RemoveWeaponModel(int model); void ClearWeapon(eWeaponType weaponType); void SetIsStanding(bool standing); - CPedIntelligence* GetPedIntelligence() { return m_pPedIntelligence; } - CPedSound* GetPedSound() { return m_pPedSound; } - DWORD GetType() { return m_dwType; } - void SetType(DWORD type) { m_dwType = type; } + CPedIntelligence* GetPedIntelligence() const noexcept { return m_pPedIntelligence; } + CPedSound* GetPedSound() const noexcept { return m_pPedSound; } + DWORD GetType() const noexcept { return m_dwType; } + void SetType(DWORD type) noexcept { m_dwType = type; } virtual void RestoreLastGoodPhysicsState(); - float GetCurrentRotation() { return GetPedInterface()->fCurrentRotation; } - float GetTargetRotation() { return GetPedInterface()->fTargetRotation; } - void SetCurrentRotation(float rotation); + float GetCurrentRotation() const { return GetPedInterface()->fCurrentRotation; } + float GetTargetRotation() const { return GetPedInterface()->fTargetRotation; } + void SetCurrentRotation(float rotation) { GetPedInterface()->fCurrentRotation = rotation; } void SetTargetRotation(float rotation) { GetPedInterface()->fTargetRotation = rotation; } - eWeaponSlot GetCurrentWeaponSlot() { return static_cast(GetPedInterface()->bCurrentWeaponSlot); } + eWeaponSlot GetCurrentWeaponSlot() const { return static_cast(GetPedInterface()->bCurrentWeaponSlot); } void SetCurrentWeaponSlot(eWeaponSlot weaponSlot); CVector* GetBonePosition(eBone bone, CVector* position); CVector* GetTransformedBonePosition(eBone bone, CVector* position); void ApplySwimAndSlopeRotations(); - bool IsDucking() { return GetPedInterface()->pedFlags.bIsDucking; } + bool IsDucking() const { return GetPedInterface()->pedFlags.bIsDucking; } void SetDucking(bool duck) { GetPedInterface()->pedFlags.bIsDucking = duck; } - bool IsInWater(); + bool IsInWater() noexcept; - int GetCantBeKnockedOffBike() { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } + int GetCantBeKnockedOffBike() const { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) { GetPedInterface()->pedFlags.CantBeKnockedOffBike = cantBeKnockedOffBike; } - bool IsWearingGoggles() { return GetPedInterface()->pGogglesObject != nullptr; } + bool IsWearingGoggles() const { return GetPedInterface()->pGogglesObject != nullptr; } void SetGogglesState(bool isWearingThem); void SetClothesTextureAndModel(const char* texture, const char* model, int textureType); void RebuildPlayer(); - eFightingStyle GetFightingStyle() { return static_cast(GetPedInterface()->bFightingStyle); } + eFightingStyle GetFightingStyle() const { return static_cast(GetPedInterface()->bFightingStyle); } void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6); - CEntity* GetContactEntity(); + CEntity* GetContactEntity() noexcept; - std::uint8_t GetRunState() { return static_cast(GetPedInterface()->moveState); } + std::uint8_t GetRunState() const { return static_cast(GetPedInterface()->moveState); } CEntity* GetTargetedEntity(); void SetTargetedEntity(CEntity* targetEntity); - bool GetCanBeShotInVehicle() { return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } - bool GetTestForShotInVehicle() { return GetPedInterface()->pedFlags.bTestForShotInVehicle; } + bool GetCanBeShotInVehicle() const { return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } + bool GetTestForShotInVehicle() const { return GetPedInterface()->pedFlags.bTestForShotInVehicle; } void SetCanBeShotInVehicle(bool shot) { GetPedInterface()->pedFlags.bCanBeShotInVehicle = shot; } void SetTestForShotInVehicle(bool test) { GetPedInterface()->pedFlags.bTestForShotInVehicle = test; } @@ -406,31 +407,31 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction); void SetFootBlood(std::uint32_t footBlood); - std::uint32_t GetFootBlood(); + std::uint32_t GetFootBlood() const; - bool IsBleeding() { return GetPedInterface()->pedFlags.bPedIsBleeding; } + bool IsBleeding() const { return GetPedInterface()->pedFlags.bPedIsBleeding; } void SetBleeding(bool bleeding) { GetPedInterface()->pedFlags.bPedIsBleeding = bleeding; } - bool IsOnFire() { return GetPedInterface()->pFireOnPed != nullptr; } + bool IsOnFire() const { return GetPedInterface()->pFireOnPed != nullptr; } void SetOnFire(bool onFire); - bool GetStayInSamePlace() { return GetPedInterface()->pedFlags.bStayInSamePlace; } + bool GetStayInSamePlace() const { return GetPedInterface()->pedFlags.bStayInSamePlace; } void SetStayInSamePlace(bool stay) { GetPedInterface()->pedFlags.bStayInSamePlace = stay; } - void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID); - void GetVoice(const char** voiceType, const char** voice); + void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const; + void GetVoice(const char** voiceType, const char** voice) const; void SetVoice(std::int16_t voiceType, std::int16_t voiceID); void SetVoice(const char* voiceType, const char* voice); void ResetVoice() { SetVoice(m_sDefaultVoiceType, m_sDefaultVoiceID); } void SetLanding(bool isLanding) { GetPedInterface()->pedFlags.bIsLanding = isLanding; } void SetUpdateMetricsRequired(bool required) { GetPedInterface()->pedFlags.bUpdateMatricesRequired = required; } - CWeaponStat* GetCurrentWeaponStat(); - float GetCurrentWeaponRange(); + CWeaponStat* GetCurrentWeaponStat() const noexcept; + float GetCurrentWeaponRange() const noexcept; void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType); - virtual int GetCustomMoveAnim() { return m_iCustomMoveAnim; } - bool IsDoingGangDriveby(); + virtual int GetCustomMoveAnim() const noexcept { return m_iCustomMoveAnim; } + bool IsDoingGangDriveby() const noexcept; CPedIKSAInterface* GetPedIKInterface() { return &GetPedInterface()->pedIK; } void* GetPedNodeInterface(std::int32_t nodeId) { return GetPedInterface()->pedNodes[nodeId]; } diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 3202d634c12..a72b99eb1bd 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -188,66 +188,66 @@ class CPed : public virtual CPhysical virtual void DetachPedFromEntity() = 0; virtual CVehicle* GetVehicle() = 0; - virtual void Respawn(CVector* position, bool cameraCut) = 0; + virtual void Respawn(const CVector* position, bool cameraCut) = 0; virtual void SetModelIndex(DWORD modelIndex) = 0; virtual void RemoveGeometryRef() = 0; - virtual float GetHealth() = 0; + virtual float GetHealth() const = 0; virtual void SetHealth(float health) = 0; - virtual float GetArmor() = 0; + virtual float GetArmor() const = 0; virtual void SetArmor(float armor) = 0; - virtual float GetOxygenLevel() = 0; + virtual float GetOxygenLevel() const = 0; virtual void SetOxygenLevel(float oxyggen) = 0; - virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) = 0; + virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity) = 0; virtual CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill weaponSkill) = 0; - virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) = 0; - virtual CWeapon* GetWeapon(eWeaponType weaponType) = 0; - virtual void ClearWeapons() = 0; + virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept = 0; + virtual CWeapon* GetWeapon(eWeaponType weaponType) const noexcept = 0; + virtual void ClearWeapons() noexcept = 0; virtual void RemoveWeaponModel(int model) = 0; virtual void ClearWeapon(eWeaponType weaponType) = 0; virtual void SetIsStanding(bool standing) = 0; - virtual DWORD GetType() = 0; - virtual CPedIntelligence* GetPedIntelligence() = 0; - virtual CPedSound* GetPedSound() = 0; + virtual DWORD GetType() const noexcept = 0; + virtual CPedIntelligence* GetPedIntelligence() const noexcept = 0; + virtual CPedSound* GetPedSound() const noexcept = 0; - virtual float GetCurrentRotation() = 0; - virtual float GetTargetRotation() = 0; + virtual float GetCurrentRotation() const = 0; + virtual float GetTargetRotation() const = 0; virtual void SetCurrentRotation(float rotation) = 0; virtual void SetTargetRotation(float rotation) = 0; - virtual eWeaponSlot GetCurrentWeaponSlot() = 0; + virtual eWeaponSlot GetCurrentWeaponSlot() const = 0; virtual void SetCurrentWeaponSlot(eWeaponSlot weaponSlot) = 0; virtual CVector* GetBonePosition(eBone bone, CVector* position) = 0; virtual CVector* GetTransformedBonePosition(eBone bone, CVector* position) = 0; - virtual bool IsDucking() = 0; + virtual bool IsDucking() const = 0; virtual void SetDucking(bool duck) = 0; - virtual bool IsInWater() = 0; - virtual int GetCantBeKnockedOffBike() = 0; + virtual bool IsInWater() noexcept = 0; + virtual int GetCantBeKnockedOffBike() const = 0; virtual void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) = 0; virtual void SetBleeding(bool bleeding) = 0; - virtual bool IsWearingGoggles() = 0; + virtual bool IsWearingGoggles() const = 0; virtual void SetGogglesState(bool isWearingThem) = 0; virtual void SetClothesTextureAndModel(const char* texture, const char* model, int textureType) = 0; virtual void RebuildPlayer() = 0; - virtual eFightingStyle GetFightingStyle() = 0; + virtual eFightingStyle GetFightingStyle() const = 0; virtual void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) = 0; - virtual CEntity* GetContactEntity() = 0; + virtual CEntity* GetContactEntity() noexcept = 0; - virtual std::uint8_t GetRunState() = 0; + virtual std::uint8_t GetRunState() const = 0; virtual CEntity* GetTargetedEntity() = 0; virtual void SetTargetedEntity(CEntity* targetEntity) = 0; - virtual bool GetCanBeShotInVehicle() = 0; - virtual bool GetTestForShotInVehicle() = 0; + virtual bool GetCanBeShotInVehicle() const = 0; + virtual bool GetTestForShotInVehicle() const = 0; virtual void SetCanBeShotInVehicle(bool shot) = 0; virtual void SetTestForShotInVehicle(bool test) = 0; @@ -258,28 +258,28 @@ class CPed : public virtual CPhysical virtual void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) = 0; virtual void SetFootBlood(std::uint32_t footBlood) = 0; - virtual std::uint32_t GetFootBlood() = 0; + virtual std::uint32_t GetFootBlood() const = 0; - virtual bool IsOnFire() = 0; + virtual bool IsOnFire() const = 0; virtual void SetOnFire(bool onFire) = 0; - virtual bool GetStayInSamePlace() = 0; + virtual bool GetStayInSamePlace() const = 0; virtual void SetStayInSamePlace(bool stay) = 0; - virtual void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) = 0; - virtual void GetVoice(const char** voiceType, const char** voice) = 0; + virtual void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const = 0; + virtual void GetVoice(const char** voiceType, const char** voice) const = 0; virtual void SetVoice(std::int16_t voiceType, std::int16_t voiceID) = 0; virtual void SetVoice(const char* voiceType, const char* voice) = 0; virtual void ResetVoice() = 0; virtual void SetLanding(bool isLanding) = 0; virtual void SetUpdateMetricsRequired(bool required) = 0; - virtual CWeaponStat* GetCurrentWeaponStat() = 0; - virtual float GetCurrentWeaponRange() = 0; + virtual CWeaponStat* GetCurrentWeaponStat() const noexcept = 0; + virtual float GetCurrentWeaponRange() const noexcept = 0; virtual void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) = 0; - virtual int GetCustomMoveAnim() = 0; - virtual bool IsDoingGangDriveby() = 0; + virtual int GetCustomMoveAnim() const noexcept = 0; + virtual bool IsDoingGangDriveby() const noexcept = 0; virtual CPedIKSAInterface* GetPedIKInterface() = 0; virtual void* GetPedNodeInterface(std::int32_t nodeId) = 0; From 06912cee7582f60697ab4ce5ed47716b4a293c10 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 18 Aug 2024 02:55:40 +0200 Subject: [PATCH 05/12] Fix typo --- Client/sdk/game/CPed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index a72b99eb1bd..b5032a9fcb8 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -198,7 +198,7 @@ class CPed : public virtual CPhysical virtual float GetArmor() const = 0; virtual void SetArmor(float armor) = 0; virtual float GetOxygenLevel() const = 0; - virtual void SetOxygenLevel(float oxyggen) = 0; + virtual void SetOxygenLevel(float oxygen) = 0; virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity) = 0; virtual CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill weaponSkill) = 0; virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept = 0; From 55a5742644e6ac395516b41a2ab74ff28ec2eb26 Mon Sep 17 00:00:00 2001 From: FileEX Date: Mon, 2 Sep 2024 10:30:42 +0200 Subject: [PATCH 06/12] Review --- Client/game_sa/CPedSA.cpp | 10 +++++----- Client/game_sa/CPedSA.h | 8 ++++---- Client/sdk/game/CPed.h | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 008d36e16cf..83e48817c61 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -88,7 +88,7 @@ void CPedSA::SetModelIndex(DWORD modelIndex) GetPedInterface()->pedSound.m_bIsFemale = (dwType == 5 || dwType == 22); } -bool CPedSA::IsInWater() noexcept +bool CPedSA::IsInWater() const noexcept { CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); return (task && task->GetTaskType() == TASK_COMPLEX_IN_WATER); @@ -133,9 +133,9 @@ void CPedSA::AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint1 pedInterface->bPedType = pedType; } -CVehicle* CPedSA::GetVehicle() +CVehicle* CPedSA::GetVehicle() const noexcept { - CPedSAInterface* pedInterface = GetPedInterface(); + const CPedSAInterface* pedInterface = GetPedInterface(); if (!pedInterface || !pedInterface->pedFlags.bInVehicle) return nullptr; @@ -389,7 +389,7 @@ void CPedSA::SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) pedInterface->bFightingStyleExtra |= (1 << (styleExtra - 1)); } -CEntity* CPedSA::GetContactEntity() noexcept +CEntity* CPedSA::GetContactEntity() const noexcept { CEntitySAInterface* contactInterface = GetPedInterface()->pContactEntity; if (!contactInterface) @@ -413,7 +413,7 @@ CEntity* CPedSA::GetContactEntity() noexcept } } -CEntity* CPedSA::GetTargetedEntity() +CEntity* CPedSA::GetTargetedEntity() const noexcept { CEntitySAInterface* targetInterface = GetPedInterface()->pTargetedEntity; if (!targetInterface) diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 9f718bf5c1c..8d2e5155bd7 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -330,7 +330,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint16_t direction, float rotationLimit, eWeaponType weaponType, bool changeCamera); void DetachPedFromEntity(); - CVehicle* GetVehicle(); + CVehicle* GetVehicle() const noexcept; void Respawn(const CVector* position, bool cameraCut); bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity); @@ -372,7 +372,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA bool IsDucking() const { return GetPedInterface()->pedFlags.bIsDucking; } void SetDucking(bool duck) { GetPedInterface()->pedFlags.bIsDucking = duck; } - bool IsInWater() noexcept; + bool IsInWater() const noexcept; int GetCantBeKnockedOffBike() const { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) { GetPedInterface()->pedFlags.CantBeKnockedOffBike = cantBeKnockedOffBike; } @@ -386,11 +386,11 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA eFightingStyle GetFightingStyle() const { return static_cast(GetPedInterface()->bFightingStyle); } void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6); - CEntity* GetContactEntity() noexcept; + CEntity* GetContactEntity() const noexcept; std::uint8_t GetRunState() const { return static_cast(GetPedInterface()->moveState); } - CEntity* GetTargetedEntity(); + CEntity* GetTargetedEntity() const noexcept; void SetTargetedEntity(CEntity* targetEntity); bool GetCanBeShotInVehicle() const { return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index d9748b938e9..5553020ec47 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -187,7 +187,7 @@ class CPed : public virtual CPhysical virtual void DetachPedFromEntity() = 0; - virtual CVehicle* GetVehicle() = 0; + virtual CVehicle* GetVehicle() const noexcept = 0; virtual void Respawn(const CVector* position, bool cameraCut) = 0; virtual void SetModelIndex(unsigned long ulModel) = 0; @@ -223,7 +223,7 @@ class CPed : public virtual CPhysical virtual bool IsDucking() const = 0; virtual void SetDucking(bool duck) = 0; - virtual bool IsInWater() noexcept = 0; + virtual bool IsInWater() const noexcept = 0; virtual int GetCantBeKnockedOffBike() const = 0; virtual void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) = 0; @@ -238,11 +238,11 @@ class CPed : public virtual CPhysical virtual eFightingStyle GetFightingStyle() const = 0; virtual void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) = 0; - virtual CEntity* GetContactEntity() noexcept = 0; + virtual CEntity* GetContactEntity() const noexcept = 0; virtual std::uint8_t GetRunState() const = 0; - virtual CEntity* GetTargetedEntity() = 0; + virtual CEntity* GetTargetedEntity() const noexcept = 0; virtual void SetTargetedEntity(CEntity* targetEntity) = 0; virtual bool GetCanBeShotInVehicle() const = 0; From 6ae2eb7fef108563b3bcf842218bbd00081a4f4b Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 24 Dec 2024 03:51:35 +0100 Subject: [PATCH 07/12] Cleanup and improvements --- Client/game_sa/CAEWeaponAudioEntitySA.h | 52 ++++ Client/game_sa/CPedSA.cpp | 238 +++++++----------- Client/game_sa/CPedSA.h | 306 ++++++++++++++---------- Client/game_sa/CPedSoundSA.cpp | 2 +- Client/game_sa/CPedSoundSA.h | 91 +++---- Client/game_sa/CWeaponSA.cpp | 2 +- Client/sdk/game/CPed.h | 112 +++++---- Client/sdk/game/CWeaponInfo.h | 2 +- 8 files changed, 439 insertions(+), 366 deletions(-) create mode 100644 Client/game_sa/CAEWeaponAudioEntitySA.h diff --git a/Client/game_sa/CAEWeaponAudioEntitySA.h b/Client/game_sa/CAEWeaponAudioEntitySA.h new file mode 100644 index 00000000000..0f35260de07 --- /dev/null +++ b/Client/game_sa/CAEWeaponAudioEntitySA.h @@ -0,0 +1,52 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CAEWeaponAudioEntitySA.h + * PURPOSE: Weapon audio entity header + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once +#include "CAudioEngineSA.h" + +enum class eMiniGunState : std::uint8_t +{ + SPINNING, + FIRING, + STOPPING, + STOPPED, +}; + +enum class eChainsawState : std::uint8_t +{ + IDLE, + ACTIVE, + CUTTING, + STOPPING, + STOPPED, +}; + +class CAEWeaponAudioEntitySAInterface : public CAEAudioEntity +{ +public: + bool m_isMiniGunSpinActive; + bool m_isMiniGunFireActive; + + std::uint8_t m_lastWeaponPlaneFrequencyIndex; + + eMiniGunState m_miniGunState; + eChainsawState m_chainsawState; + + std::uint32_t m_lastFlamethrowerFireTimeInMS; + std::uint32_t m_lastSpraycanFireTimeInMS; + std::uint32_t m_lastFireExtinguisherFireTimeInMS; + std::uint32_t m_lastMinigunFireTimeInMS; + std::uint32_t m_lastChainsawFireTimeInMS; + std::uint32_t m_lastGunFireTimeInMS; + + CAESound* m_flameThrowerIdleGasLoopSound{}; +}; +static_assert(sizeof(CAEWeaponAudioEntitySAInterface) == 0xA0, "Invalid size for CAEWeaponAudioEntitySAInterface"); diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 83e48817c61..09270a2f0ff 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: game_sa/CPedSA.cpp * PURPOSE: Ped entity * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://www.multitheftauto.com/ * *****************************************************************************/ @@ -25,23 +25,11 @@ extern CGameSA* pGame; static bool g_onlyUpdateRotations = false; -CPedSA::CPedSA(CPedSAInterface* pPedInterface) - : m_pPedInterface(pPedInterface) -{ - MemSetFast(m_pWeapons, 0, sizeof(CWeaponSA*) * WEAPONSLOT_MAX); -} - CPedSA::~CPedSA() { - SAFE_DELETE(m_pPedIntelligence); - SAFE_DELETE(m_pPedSound); - - for (std::uint8_t i = 0; i < WEAPONSLOT_MAX; i++) - SAFE_DELETE(m_pWeapons[i]); - // Make sure this ped is not refed in the flame shot info array - CFlameShotInfo* info = (CFlameShotInfo*)ARRAY_CFlameShotInfo; - for (std::uint8_t i = 0; i < MAX_FLAME_SHOT_INFOS; i++, info++) + auto* info = reinterpret_cast(ARRAY_CFlameShotInfo); + for (std::size_t i = 0; i < MAX_FLAME_SHOT_INFOS; i++, info++) { if (info->pInstigator != m_pInterface) continue; @@ -59,42 +47,39 @@ void CPedSA::Init() { CPedSAInterface* pedInterface = GetPedInterface(); - auto* pedIntelligenceInterface = static_cast(pedInterface->pPedIntelligence); - m_pPedIntelligence = new CPedIntelligenceSA(pedIntelligenceInterface, this); + m_pedIntelligence = std::make_unique(pedInterface->pPedIntelligence, this); - m_pPedSound = new CPedSoundSA(&pedInterface->pedSound); - m_sDefaultVoiceType = m_pPedSound->GetVoiceTypeID(); - m_sDefaultVoiceID = m_pPedSound->GetVoiceID(); + m_pedSound = std::make_unique(&pedInterface->pedSound); + m_defaultVoiceType = m_pedSound->GetVoiceTypeID(); + m_defaultVoiceID = m_pedSound->GetVoiceID(); - for (std::uint8_t i = 0; i < WEAPONSLOT_MAX; i++) - m_pWeapons[i] = new CWeaponSA(&(pedInterface->Weapons[i]), this, static_cast(i)); + for (std::size_t i = 0; i < WEAPONSLOT_MAX; i++) + m_weapons[i] = std::make_unique(&(pedInterface->Weapons[i]), this, static_cast(i)); #ifdef PedIK_SA this->m_pPedIK = new Cm_pPedIKSA(&(pedInterface->m_pPedIK)); #endif } -void CPedSA::SetModelIndex(DWORD modelIndex) +void CPedSA::SetModelIndex(std::uint32_t modelIndex) { // char __thiscall CPed::SetModelIndex(void *this, int a2) ((char(__thiscall*)(CEntitySAInterface*, int))FUNC_SetModelIndex)(m_pInterface, modelIndex); // Also set the voice gender - CPedModelInfoSAInterface* modelInfo = static_cast(pGame->GetModelInfo(modelIndex)->GetInterface()); - if (!modelInfo) + CModelInfo* mi = pGame->GetModelInfo(modelIndex); + if (!mi) return; - DWORD dwType = modelInfo->pedType; - GetPedInterface()->pedSound.m_bIsFemale = (dwType == 5 || dwType == 22); -} + CPedModelInfoSAInterface* modelInfo = static_cast(mi->GetInterface()); + if (!modelInfo) + return; -bool CPedSA::IsInWater() const noexcept -{ - CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); - return (task && task->GetTaskType() == TASK_COMPLEX_IN_WATER); + std::uint32_t type = modelInfo->pedType; + GetPedInterface()->pedSound.m_bIsFemale = type == 5 || type == 22; } -bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity) +bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) { CProjectileInfo* projectileInfo = pGame->GetProjectileInfo(); if (!projectileInfo) @@ -110,32 +95,26 @@ void CPedSA::DetachPedFromEntity() } bool CPedSA::InternalAttachEntityToEntity(DWORD entityInteface, const CVector* position, const CVector* rotation) -{ - AttachPedToEntity(entityInteface, const_cast(position), 0, 0.0f, WEAPONTYPE_UNARMED, false); - return true; -} - -void CPedSA::AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint16_t direction, float rotationLimit, eWeaponType weaponType, bool changeCamera) { // sDirection and fRotationLimit only apply to first-person shooting (bChangeCamera) CPedSAInterface* pedInterface = GetPedInterface(); std::uint8_t pedType = pedInterface->bPedType; // Hack the CPed type(?) to non-player so the camera doesn't get changed - if (!changeCamera) - pedInterface->bPedType = 2; + pedInterface->bPedType = 2; // CEntity *__thiscall CPed::AttachPedToEntity(CPed *this, CEntity *a2, float arg4, float a4, float a5, __int16 a6, int a7, eWeaponType a3) - ((CEntitySAInterface*(__thiscall*)(CEntitySAInterface*, CEntitySAInterface*, float, float, float, std::uint16_t, float, std::uint8_t))FUNC_AttachPedToEntity)(m_pInterface, reinterpret_cast(entityInteface), vector->fX, vector->fY, vector->fZ, direction, rotationLimit, static_cast(weaponType)); + ((CEntitySAInterface*(__thiscall*)(CEntitySAInterface*, CEntitySAInterface*, float, float, float, std::uint16_t, int, eWeaponType))FUNC_AttachPedToEntity)(m_pInterface, reinterpret_cast(entityInteface), position->fX, position->fY, position->fZ, 0, 0, WEAPONTYPE_UNARMED); // Hack the CPed type(?) to whatever it was set to - if (!changeCamera) - pedInterface->bPedType = pedType; + pedInterface->bPedType = pedType; + + return true; } -CVehicle* CPedSA::GetVehicle() const noexcept +CVehicle* CPedSA::GetVehicle() const { - const CPedSAInterface* pedInterface = GetPedInterface(); + CPedSAInterface* pedInterface = GetPedInterface(); if (!pedInterface || !pedInterface->pedFlags.bInVehicle) return nullptr; @@ -147,7 +126,7 @@ CVehicle* CPedSA::GetVehicle() const noexcept return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; } -void CPedSA::Respawn(const CVector* position, bool cameraCut) +void CPedSA::Respawn(CVector* position, bool cameraCut) { if (!cameraCut) // CGameLogic::RestorePlayerStuffDuringResurrection @@ -173,24 +152,6 @@ void CPedSA::Respawn(const CVector* position, bool cameraCut) MemCpy((void*)0x4422EA, "\xB9\x28\xF0\xB6\x00\xE8\x4C\x9A\x0C\x00\xB9\x28\xF0\xB6\x00\xE8\xB2\x97\x0C\x00", 20); } -void CPedSA::SetIsStanding(bool standing) -{ - // int __thiscall CPed::SetIsStanding(CPed *this, unsigned __int8 a2) - ((void(__thiscall*)(CEntitySAInterface*, bool))FUNC_SetIsStanding)(m_pInterface, standing); -} - -void CPedSA::RemoveWeaponModel(int model) -{ - // void __thiscall CPed::RemoveWeaponModel(CPed *this, int modelID) - ((void(__thiscall*)(CEntitySAInterface*, int))FUNC_RemoveWeaponModel)(m_pInterface, model); -} - -void CPedSA::ClearWeapon(eWeaponType weaponType) -{ - // BYTE *__thiscall CPed::ClearWeapon(CPed *this, eWeaponType a2) - ((std::uint8_t*(__thiscall*)(CEntitySAInterface*, std::uint8_t))FUNC_ClearWeapon)(m_pInterface, static_cast(weaponType)); -} - CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill) { // Load weapon model @@ -199,17 +160,13 @@ CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponS CWeaponInfo* weaponInfo = pGame->GetWeaponInfo(weaponType, skill); if (weaponInfo) { - std::uint16_t model = weaponInfo->GetModel(); - if (model) + CModelInfo* modelInfo = pGame->GetModelInfo(static_cast(weaponInfo->GetModel())); + if (modelInfo) { - CModelInfo* modelInfo = pGame->GetModelInfo(model); - if (modelInfo) - { - modelInfo->Request(BLOCKING, "CPedSA::GiveWeapon"); - modelInfo->MakeCustomModel(); - } + modelInfo->Request(BLOCKING, "CPedSA::GiveWeapon"); + modelInfo->MakeCustomModel(); } - + // If the weapon is satchels, load the detonator too if (weaponType == WEAPONTYPE_REMOTE_SATCHEL_CHARGE) GiveWeapon(WEAPONTYPE_DETONATOR, 1, WEAPONSKILL_STD); @@ -218,12 +175,12 @@ CWeapon* CPedSA::GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponS // eWeaponType __thiscall CPed::GiveWeapon(CPed *this, eWeaponType weaponID, signed int ammo, int a4) // Last argument is unused - eWeaponSlot weaponSlot = ((eWeaponSlot(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint32_t, std::uint8_t))FUNC_GiveWeapon)(m_pInterface, weaponType, ammo, 1); + eWeaponSlot weaponSlot = ((eWeaponSlot(__thiscall*)(CEntitySAInterface*, eWeaponType, std::uint32_t, int))FUNC_GiveWeapon)(m_pInterface, weaponType, ammo, 1); return GetWeapon(weaponSlot); } -CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) const noexcept +CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) const { if (weaponType >= WEAPONTYPE_LAST_WEAPONTYPE) return nullptr; @@ -232,15 +189,15 @@ CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) const noexcept return (weapon && weapon->GetType() == weaponType) ? weapon : nullptr; } -CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) const noexcept +CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) const { - return (weaponSlot >= 0 && weaponSlot < WEAPONSLOT_MAX) ? m_pWeapons[weaponSlot] : nullptr; + return (weaponSlot >= 0 && weaponSlot < WEAPONSLOT_MAX) ? m_weapons[weaponSlot].get() : nullptr; } void CPedSA::ClearWeapons() noexcept { // Remove all the weapons - for (auto& weapon : m_pWeapons) + for (auto& weapon : m_weapons) { weapon->SetAmmoInClip(0); weapon->SetAmmoTotal(0); @@ -248,6 +205,24 @@ void CPedSA::ClearWeapons() noexcept } } +void CPedSA::RemoveWeaponModel(std::uint32_t model) +{ + // void __thiscall CPed::RemoveWeaponModel(CPed *this, int modelID) + ((void(__thiscall*)(CEntitySAInterface*, std::uint32_t))FUNC_RemoveWeaponModel)(m_pInterface, model); +} + +void CPedSA::ClearWeapon(eWeaponType weaponType) +{ + // BYTE *__thiscall CPed::ClearWeapon(CPed *this, eWeaponType a2) + ((std::uint8_t * (__thiscall*)(CEntitySAInterface*, eWeaponType)) FUNC_ClearWeapon)(m_pInterface, weaponType); +} + +void CPedSA::SetIsStanding(bool standing) +{ + // int __thiscall CPed::SetIsStanding(CPed *this, unsigned __int8 a2) + ((void(__thiscall*)(CEntitySAInterface*, bool))FUNC_SetIsStanding)(m_pInterface, standing); +} + void CPedSA::RestoreLastGoodPhysicsState() { CPhysicalSA::RestoreLastGoodPhysicsState(); @@ -272,19 +247,19 @@ void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) RemoveWeaponModel(weaponInfo->GetModel()); } - CPedSAInterface* pedInterface = GetPedInterface(); - // set the new weapon slot - pedInterface->bCurrentWeaponSlot = weaponSlot; + GetPedInterface()->bCurrentWeaponSlot = weaponSlot; // is the player the local player? - CPed* localPlayer = pGame->GetPools()->GetPedFromRef(static_cast(1)); + CPed* localPlayer = pGame->GetPedContext(); + std::uintptr_t changeWeaponFunc; if (localPlayer == this) { auto* playerInfo = static_cast(pGame->GetPlayerInfo()); - playerInfo->GetInterface()->PlayerPedData.m_nChosenWeapon = weaponSlot; + if (auto* pInfoInterface = playerInfo->GetInterface()) + pInfoInterface->PlayerPedData.m_nChosenWeapon = weaponSlot; // void __thiscall CPlayerPed::MakeChangesForNewWeapon(CPlayerPed *this, int a3) changeWeaponFunc = FUNC_MakeChangesForNewWeapon_Slot; @@ -293,7 +268,7 @@ void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) // void __thiscall CPed::SetCurrentWeapon(CPed *this, int slot) changeWeaponFunc = FUNC_SetCurrentWeapon; - ((void(__thiscall*)(CEntitySAInterface*, std::uint8_t))changeWeaponFunc)(m_pInterface, static_cast(weaponSlot)); + ((void(__thiscall*)(CEntitySAInterface*, eWeaponSlot))changeWeaponFunc)(m_pInterface, weaponSlot); } CVector* CPedSA::GetBonePosition(eBone bone, CVector* position) @@ -305,7 +280,7 @@ CVector* CPedSA::GetBonePosition(eBone bone, CVector* position) // for a broken model. if (entity->m_pRwObject) // int __thiscall CPed::GetBonePosition(CPed *this, CVector *pPoint, int bone_id, bool bDynamic) - ((int(__thiscall*)(CEntitySAInterface*, CVector*, std::uint16_t, bool))FUNC_GetBonePosition)(entity, position, bone, true); + ((void(__thiscall*)(CEntitySAInterface*, CVector*, eBone, bool))FUNC_GetBonePosition)(entity, position, bone, true); // Clamp to a sane range as this function can occasionally return massive values, // which causes ProcessLineOfSight to effectively freeze @@ -324,7 +299,7 @@ CVector* CPedSA::GetTransformedBonePosition(eBone bone, CVector* position) // for a broken model. if (entity->m_pRwObject) // RwV3D *__thiscall CPed::GetTransformedBonePosition(CPed *this, RwV3D *pointsIn, int boneId, char bUpdateBones) - ((RwV3d*(__thiscall*)(CEntitySAInterface*, CVector*, std::uint16_t, bool))FUNC_GetTransformedBonePosition)(entity, position, bone, true); + ((RwV3d*(__thiscall*)(CEntitySAInterface*, CVector*, eBone, bool))FUNC_GetTransformedBonePosition)(entity, position, bone, true); // Clamp to a sane range as this function can occasionally return massive values, // which causes ProcessLineOfSight to effectively freeze @@ -350,6 +325,12 @@ void CPedSA::ApplySwimAndSlopeRotations() g_onlyUpdateRotations = false; } +bool CPedSA::IsInWater() const +{ + CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); + return (task && task->GetTaskType() == TASK_COMPLEX_IN_WATER); +} + void CPedSA::SetGogglesState(bool isWearingThem) { // void __thiscall CPed::PutOnGoggles(CPed *this) @@ -360,13 +341,13 @@ void CPedSA::SetGogglesState(bool isWearingThem) void CPedSA::SetClothesTextureAndModel(const char* texture, const char* model, int textureType) { - DWORD* clothes = reinterpret_cast(GetPedInterface()->pPlayerData->m_pClothes); + CPedClothesDesc* clothes = GetPedInterface()->pPlayerData->m_pClothes; if (!clothes) return; // int __fastcall CPedClothesDesc::SetTextureAndModel(DWORD* this, int unknown, char* textureName, char* modelName, eClothesTexturePart texturePart) // Second argument is unused in CKeyGen::GetUppercaseKey - ((int(__fastcall*)(DWORD*, int, const char*, const char*, std::uint8_t))FUNC_CPedClothesDesc__SetTextureAndModel)(clothes, 0, texture, model, textureType); + ((void(__fastcall*)(CPedClothesDesc*, int, const char*, const char*, std::uint8_t))FUNC_CPedClothesDesc__SetTextureAndModel)(clothes, 0, texture, model, textureType); } void CPedSA::RebuildPlayer() @@ -378,42 +359,25 @@ void CPedSA::RebuildPlayer() void CPedSA::SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) { CPedSAInterface* pedInterface = GetPedInterface(); - std::uint8_t newStyle = static_cast(style); - - if (newStyle == pedInterface->bFightingStyle) + if (style == pedInterface->bFightingStyle) return; - pedInterface->bFightingStyle = newStyle; + pedInterface->bFightingStyle = style; if (styleExtra > 0 && styleExtra <= 6) pedInterface->bFightingStyleExtra |= (1 << (styleExtra - 1)); } -CEntity* CPedSA::GetContactEntity() const noexcept +CEntity* CPedSA::GetContactEntity() const { CEntitySAInterface* contactInterface = GetPedInterface()->pContactEntity; if (!contactInterface) return nullptr; - CPools* pools = pGame->GetPools(); - switch (contactInterface->nType) - { - case ENTITY_TYPE_VEHICLE: - { - auto* vehicleClientEntity = pools->GetVehicle(reinterpret_cast(contactInterface)); - return vehicleClientEntity ? vehicleClientEntity->pEntity : nullptr; - } - case ENTITY_TYPE_OBJECT: - { - auto* objectClientEntity = pools->GetObject(reinterpret_cast(contactInterface)); - return objectClientEntity ? objectClientEntity->pEntity : nullptr; - } - default: - break; - } + return pGame->GetPools()->GetEntity(reinterpret_cast(contactInterface)); } -CEntity* CPedSA::GetTargetedEntity() const noexcept +CEntity* CPedSA::GetTargetedEntity() const { CEntitySAInterface* targetInterface = GetPedInterface()->pTargetedEntity; if (!targetInterface) @@ -424,44 +388,31 @@ CEntity* CPedSA::GetTargetedEntity() const noexcept void CPedSA::SetTargetedEntity(CEntity* targetEntity) { - CEntitySAInterface* targetInterface = nullptr; - if (targetEntity) - { - CEntitySA* entity = dynamic_cast(targetEntity); - targetInterface = entity ? entity->GetInterface() : nullptr; - } - - GetPedInterface()->pTargetedEntity = targetInterface; + GetPedInterface()->pTargetedEntity = targetEntity ? targetEntity->GetInterface() : nullptr; } void CPedSA::RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) { // char __thiscall CPed::RemoveBodyPart(CPed *this, int boneID, int localDir) // second argument is unused (direction) - ((char(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint8_t))FUNC_CPed_RemoveBodyPart)(m_pInterface, boneID, direction); + ((char(__thiscall*)(CEntitySAInterface*, std::uint8_t, std::uint8_t))FUNC_CPed_RemoveBodyPart)(m_pInterface, boneID, 0); } void CPedSA::SetFootBlood(std::uint32_t footBlood) { CPedSAInterface* pedInterface = GetPedInterface(); - - if (footBlood > 0) - // Make sure the foot blood flag is activated - pedInterface->pedFlags.bDoBloodyFootprints = true; - else if (pedInterface->pedFlags.bDoBloodyFootprints) - // If the foot blood flag is activated, deactivate it - pedInterface->pedFlags.bDoBloodyFootprints = false; + pedInterface->pedFlags.bDoBloodyFootprints = footBlood > 0; // Set the amount of foot blood - pedInterface->dwTimeWhenDead = footBlood; + pedInterface->timeWhenDead = footBlood; } std::uint32_t CPedSA::GetFootBlood() const { - const CPedSAInterface* pedInterface = GetPedInterface(); + CPedSAInterface* pedInterface = GetPedInterface(); // If the foot blood flag is activated, return the amount of foot blood - return pedInterface->pedFlags.bDoBloodyFootprints ? pedInterface->dwTimeWhenDead : 0; + return pedInterface->pedFlags.bDoBloodyFootprints ? pedInterface->timeWhenDead : 0; } void CPedSA::SetOnFire(bool onFire) @@ -501,14 +452,14 @@ void CPedSA::SetOnFire(bool onFire) void CPedSA::GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const { - if (!m_pPedSound) + if (!m_pedSound) return; if (voiceType) - *voiceType = m_pPedSound->GetVoiceTypeID(); + *voiceType = m_pedSound->GetVoiceTypeID(); if (voiceID) - *voiceID = m_pPedSound->GetVoiceID(); + *voiceID = m_pedSound->GetVoiceID(); } void CPedSA::GetVoice(const char** voiceType, const char** voice) const @@ -524,11 +475,11 @@ void CPedSA::GetVoice(const char** voiceType, const char** voice) const void CPedSA::SetVoice(std::int16_t voiceType, std::int16_t voiceID) { - if (!m_pPedSound) + if (!m_pedSound) return; - m_pPedSound->SetVoiceTypeID(voiceType); - m_pPedSound->SetVoiceID(voiceID); + m_pedSound->SetVoiceTypeID(voiceType); + m_pedSound->SetVoiceID(voiceID); } void CPedSA::SetVoice(const char* voiceType, const char* voice) @@ -545,7 +496,7 @@ void CPedSA::SetVoice(const char* voiceType, const char* voice) } // GetCurrentWeaponStat will only work if the game ped context is currently set to this ped -CWeaponStat* CPedSA::GetCurrentWeaponStat() const noexcept +CWeaponStat* CPedSA::GetCurrentWeaponStat() const { if (pGame->GetPedContext() != this) { @@ -564,13 +515,10 @@ CWeaponStat* CPedSA::GetCurrentWeaponStat() const noexcept return pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(weaponType, skill); } -float CPedSA::GetCurrentWeaponRange() const noexcept +float CPedSA::GetCurrentWeaponRange() const { CWeaponStat* weaponStat = GetCurrentWeaponStat(); - if (!weaponStat) - return 1.0f; - - return weaponStat->GetWeaponRange(); + return weaponStat ? weaponStat->GetWeaponRange() : 1.0f; } void CPedSA::AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) @@ -579,9 +527,9 @@ void CPedSA::AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) ((void(__thiscall*)(CPedWeaponAudioEntitySAInterface*, std::uint16_t))FUNC_CAEPedWeaponAudioEntity__AddAudioEvent)(&GetPedInterface()->weaponAudioEntity, static_cast(audioEventType)); } -bool CPedSA::IsDoingGangDriveby() const noexcept +bool CPedSA::IsDoingGangDriveby() const { - if (!m_pPedIntelligence) + if (!m_pedIntelligence) return false; CTask* task = GetPedIntelligence()->GetTaskManager()->GetTask(TASK_PRIORITY_PRIMARY); diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 2e8794978c6..4a5df5c6613 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: game_sa/CPedSA.h * PURPOSE: Header file for ped entity base class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://www.multitheftauto.com/ * *****************************************************************************/ @@ -198,82 +198,124 @@ class CPedFlags unsigned int bUsedForReplay : 1; // This ped is controlled by replay and should be removed when replay is done. }; +class CPedAcquaintanceSAInterface +{ + int respect; + int like; + int ignore; + int dislike; + int hate; +}; +static_assert(sizeof(CPedAcquaintanceSAInterface) == 0x14, "Invalid size for CPedAcquaintanceSAInterface"); + +class CPedStatSAInterface +{ + std::uint32_t id; + char name[24]; + float fleedDistance; + float headingChangeRate; + std::uint8_t fear; + std::uint8_t temper; + std::uint8_t lawFullness; + std::uint8_t sexiness; + float attackStrength; + float defendWeakness; + std::uint16_t shootingRate; + std::uint8_t defaultDecisionMaker; +}; +static_assert(sizeof(CPedStatSAInterface) == 0x34, "Invalid size for CPedStatSAInterface"); + class CPedSAInterface : public CPhysicalSAInterface { public: CPedSoundEntitySAInterface pedAudio; // CAEPedAudioEntity CPedSoundSAInterface pedSound; // CAEPedSpeechAudioEntity - CPedWeaponAudioEntitySAInterface weaponAudioEntity; + CPedWeaponAudioEntitySAInterface weaponAudioEntity; // CAEPedWeaponAudioEntity + std::uint8_t unk_43C[36]; - std::uint8_t unk_460[8]; - int unk_468; + CPedSAInterface* roadRageWith; + std::uint8_t unk_464[8]; + CPedFlags pedFlags; CPedIntelligenceSAInterface* pPedIntelligence; CPlayerPedDataSAInterface* pPlayerData; + std::uint8_t createdBy; - std::uint8_t _pad0[3]; void* pedNodes[19]; // AnimBlendFrameData* int iMoveAnimGroup; CVector2D vecAnimMovingShiftLocal; - std::uint8_t pedAcquaintance[20]; // CPedAcquaintance + CPedAcquaintanceSAInterface pedAcquaintance; + RpClump* pWeaponObject; RwFrame* pGunflashObject; RpClump* pGogglesObject; bool* pGogglesState; - std::int16_t weaponGunflashStateLeftHand; - std::int16_t unk_506; + std::int16_t weaponGunflashStateRightHand; - std::int16_t unk_50A; + std::int16_t weaponGunFlashAlphaProgMP1; + std::int16_t weaponGunflashStateLeftHand; + std::int16_t weaponGunFlashAlphaProgMP2; + CPedIKSAInterface pedIK; int unk_52C; + int pedState; int moveState; int swimmingMoveState; + int unk_53C; float fHealth; float fMaxHealth; float fArmor; - DWORD dwTimeTillWeNeedThisPed; + + std::uint32_t timeTillWeNeedThisPed; CVector2D vecAnimMovingShift; float fCurrentRotation; float fTargetRotation; float fRotationSpeed; float fMoveAnim; + CEntitySAInterface* pContactEntity; CVector unk_56C; CVector unk_578; CEntitySAInterface* pLastContactEntity; + CVehicleSAInterface* pLastVehicle; CVehicleSAInterface* pVehicle; - int unk_590; + CVehicleSAInterface* vehicleDeadInFrontOf; + int unk_594; int bPedType; // ped type? 0 = player, >1 = ped? - void* pPedStats; + CPedStatSAInterface* pPedStats; CWeaponSAInterface Weapons[WEAPONSLOT_MAX]; - int savedWeapon; - int delayedWeapon; - DWORD dwDelayedWeaponAmmo; + eWeaponType savedWeapon; + eWeaponType delayedWeapon; + std::uint32_t delayedWeaponAmmo; std::uint8_t bCurrentWeaponSlot; std::uint8_t weaponShootingRate; std::uint8_t weaponAccuracy; - std::uint8_t _pad; + CEntitySAInterface* pTargetedObject; int unk_720; int unk_724; int unk_728; - std::uint8_t weaponSkill; - std::uint8_t bFightingStyle; + + eWeaponSkill weaponSkill; + eFightingStyle bFightingStyle; std::uint8_t bFightingStyleExtra; std::uint8_t bPad7; + CFireSAInterface* pFireOnPed; - int unk_734; + float fireDamageMult; + CEntitySAInterface* pLookAtEntity; float fLookHeading; - DWORD dwWeaponModelID; + + std::uint32_t weaponModelID; int unk_744; - DWORD dwLookTime; + std::uint32_t lookTime; int unk_74C; - DWORD dwTimeWhenDead; // death time in MS + std::uint32_t timeWhenDead; // death time in MS std::uint8_t bodyPartToRemove; std::int16_t unk_755; std::int16_t moneyCount; @@ -283,18 +325,20 @@ class CPedSAInterface : public CPhysicalSAInterface std::uint8_t unk_761[3]; CEntitySAInterface* pTargetedEntity; std::int16_t unk_768; + CVector vecTurretOffset; float fTurretAngleA; float fTurretAngleB; - DWORD dwTurretPosnMode; - DWORD dwTurretAmmo; + std::uint32_t turretPosnMode; + std::uint32_t turretAmmo; + void* pCoverPoint; // CCoverPoint* void* pEnex; // CEntryExit* float fRemovalDistMultiplier; - std::int16_t specialModelIndex; + std::int16_t specialModelIndex; // StreamedScriptBrainToLoad + std::int16_t unk_796; int unk_798; - CEntitySAInterface* pTargetedEntity; // 1948 }; static_assert(sizeof(CPedSAInterface) == 0x79C, "Invalid size for CPedSAInterface"); @@ -302,145 +346,153 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA { friend class CPoolsSA; -private: - CWeaponSA* m_pWeapons[WEAPONSLOT_MAX]{}; - CPedIKSA* m_pPedIK{}; - CPedIntelligenceSA* m_pPedIntelligence{}; - CPedSAInterface* m_pPedInterface{}; - CPedSoundSA* m_pPedSound{}; - - std::int16_t m_sDefaultVoiceType; - std::int16_t m_sDefaultVoiceID; - - DWORD m_dwType; - std::uint8_t m_ucOccupiedSeat; - -protected: - int m_iCustomMoveAnim{ 0 }; - public: - CPedSA(CPedSAInterface* pedInterface = nullptr); ~CPedSA(); void SetInterface(CEntitySAInterface* intInterface) noexcept { m_pInterface = intInterface; } - CPedSAInterface* GetPedInterface() noexcept { return static_cast(m_pInterface); } - const CPedSAInterface* GetPedInterface() const noexcept { return static_cast(m_pInterface); } - void Init(); + CPedSAInterface* GetPedInterface() noexcept override { return static_cast(m_pInterface); } + CPedSAInterface* GetPedInterface() const noexcept { return static_cast(m_pInterface); } + + void Init(); - void SetModelIndex(DWORD modelIndex); - void AttachPedToEntity(DWORD entityInteface, CVector* vector, std::uint16_t direction, float rotationLimit, eWeaponType weaponType, bool changeCamera); - void DetachPedFromEntity(); + void SetModelIndex(std::uint32_t modelIndex) override; + + bool InternalAttachEntityToEntity(DWORD entityInterface, const CVector* position, const CVector* rotation) override; + void DetachPedFromEntity() override; + + CVehicle* GetVehicle() const override; - CVehicle* GetVehicle() const noexcept; - void Respawn(const CVector* position, bool cameraCut); - bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity); + void Respawn(CVector* position, bool cameraCut) override; - float GetHealth() const { return GetPedInterface()->fHealth; } - void SetHealth(float health) { GetPedInterface()->fHealth = health; } + float GetHealth() const override { return GetPedInterface()->fHealth; } + void SetHealth(float health) override { GetPedInterface()->fHealth = health; } - float GetArmor() const { return GetPedInterface()->fArmor; } - void SetArmor(float armor) { GetPedInterface()->fArmor = armor; } + float GetArmor() const override { return GetPedInterface()->fArmor; } + void SetArmor(float armor) override { GetPedInterface()->fArmor = armor; } - float GetOxygenLevel() const; - void SetOxygenLevel(float oxygen); + float GetOxygenLevel() const override; + void SetOxygenLevel(float oxygen) override; - CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill); - CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept; - CWeapon* GetWeapon(eWeaponType weaponType) const noexcept; + bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) override; + CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill) override; + CWeapon* GetWeapon(eWeaponSlot weaponSlot) const override; + CWeapon* GetWeapon(eWeaponType weaponType) const override; void ClearWeapons() noexcept; - void RemoveWeaponModel(int model); - void ClearWeapon(eWeaponType weaponType); + void RemoveWeaponModel(std::uint32_t model) override; + void ClearWeapon(eWeaponType weaponType) override; - void SetIsStanding(bool standing); - CPedIntelligence* GetPedIntelligence() const noexcept { return m_pPedIntelligence; } - CPedSound* GetPedSound() const noexcept { return m_pPedSound; } - DWORD GetType() const noexcept { return m_dwType; } - void SetType(DWORD type) noexcept { m_dwType = type; } + void SetIsStanding(bool standing) override; + + std::uint32_t GetType() const noexcept override { return m_type; } + void SetType(std::uint32_t type) noexcept { m_type = type; } + + CPedIntelligence* GetPedIntelligence() const noexcept override { return m_pedIntelligence.get(); } + CPedSound* GetPedSound() const noexcept override { return m_pedSound.get(); } virtual void RestoreLastGoodPhysicsState(); - float GetCurrentRotation() const { return GetPedInterface()->fCurrentRotation; } - float GetTargetRotation() const { return GetPedInterface()->fTargetRotation; } - void SetCurrentRotation(float rotation) { GetPedInterface()->fCurrentRotation = rotation; } - void SetTargetRotation(float rotation) { GetPedInterface()->fTargetRotation = rotation; } - eWeaponSlot GetCurrentWeaponSlot() const { return static_cast(GetPedInterface()->bCurrentWeaponSlot); } - void SetCurrentWeaponSlot(eWeaponSlot weaponSlot); + float GetCurrentRotation() const override { return GetPedInterface()->fCurrentRotation; } + float GetTargetRotation() const override { return GetPedInterface()->fTargetRotation; } + void SetCurrentRotation(float rotation) override { GetPedInterface()->fCurrentRotation = rotation; } + void SetTargetRotation(float rotation) override { GetPedInterface()->fTargetRotation = rotation; } - CVector* GetBonePosition(eBone bone, CVector* position); - CVector* GetTransformedBonePosition(eBone bone, CVector* position); - void ApplySwimAndSlopeRotations(); + eWeaponSlot GetCurrentWeaponSlot() const override { return static_cast(GetPedInterface()->bCurrentWeaponSlot); } + void SetCurrentWeaponSlot(eWeaponSlot weaponSlot) override; - bool IsDucking() const { return GetPedInterface()->pedFlags.bIsDucking; } - void SetDucking(bool duck) { GetPedInterface()->pedFlags.bIsDucking = duck; } + CVector* GetBonePosition(eBone bone, CVector* position) override; + CVector* GetTransformedBonePosition(eBone bone, CVector* position) override; - bool IsInWater() const noexcept; + bool IsDucking() const override { return GetPedInterface()->pedFlags.bIsDucking; } + void SetDucking(bool duck) override { GetPedInterface()->pedFlags.bIsDucking = duck; } - int GetCantBeKnockedOffBike() const { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } - void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) { GetPedInterface()->pedFlags.CantBeKnockedOffBike = cantBeKnockedOffBike; } + bool IsInWater() const override; - bool IsWearingGoggles() const { return GetPedInterface()->pGogglesObject != nullptr; } - void SetGogglesState(bool isWearingThem); + std::uint32_t GetCantBeKnockedOffBike() const override { return GetPedInterface()->pedFlags.CantBeKnockedOffBike; } + void SetCantBeKnockedOffBike(std::uint32_t cantBeKnockedOffBike) override { GetPedInterface()->pedFlags.CantBeKnockedOffBike = cantBeKnockedOffBike; } - void SetClothesTextureAndModel(const char* texture, const char* model, int textureType); - void RebuildPlayer(); + bool IsWearingGoggles() const override { return GetPedInterface()->pGogglesObject != nullptr; } + void SetGogglesState(bool isWearingThem) override; - eFightingStyle GetFightingStyle() const { return static_cast(GetPedInterface()->bFightingStyle); } - void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6); + void SetClothesTextureAndModel(const char* texture, const char* model, int textureType) override; + void RebuildPlayer() override; - CEntity* GetContactEntity() const noexcept; + eFightingStyle GetFightingStyle() const override { return static_cast(GetPedInterface()->bFightingStyle); } + void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6) override; - std::uint8_t GetRunState() const { return static_cast(GetPedInterface()->moveState); } + CEntity* GetContactEntity() const override; - CEntity* GetTargetedEntity() const noexcept; - void SetTargetedEntity(CEntity* targetEntity); + int GetRunState() const override { return GetPedInterface()->moveState; } - bool GetCanBeShotInVehicle() const { return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } - bool GetTestForShotInVehicle() const { return GetPedInterface()->pedFlags.bTestForShotInVehicle; } + CEntity* GetTargetedEntity() const override; + void SetTargetedEntity(CEntity* targetEntity) override; - void SetCanBeShotInVehicle(bool shot) { GetPedInterface()->pedFlags.bCanBeShotInVehicle = shot; } - void SetTestForShotInVehicle(bool test) { GetPedInterface()->pedFlags.bTestForShotInVehicle = test; } + bool GetCanBeShotInVehicle() const override{ return GetPedInterface()->pedFlags.bCanBeShotInVehicle; } + bool GetTestForShotInVehicle() const override { return GetPedInterface()->pedFlags.bTestForShotInVehicle; } - bool InternalAttachEntityToEntity(DWORD entityInterface, const CVector* position, const CVector* rotation) override; + void SetCanBeShotInVehicle(bool shot) override { GetPedInterface()->pedFlags.bCanBeShotInVehicle = shot; } + void SetTestForShotInVehicle(bool test) override { GetPedInterface()->pedFlags.bTestForShotInVehicle = test; } - std::uint8_t GetOccupiedSeat() const noexcept { return m_ucOccupiedSeat; } - void SetOccupiedSeat(std::uint8_t seat) noexcept { m_ucOccupiedSeat = seat; } + std::uint8_t GetOccupiedSeat() const noexcept override { return m_occupiedSeat; } + void SetOccupiedSeat(std::uint8_t seat) noexcept override { m_occupiedSeat = seat; } - void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction); + void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) override; - void SetFootBlood(std::uint32_t footBlood); - std::uint32_t GetFootBlood() const; + void SetFootBlood(std::uint32_t footBlood) override; + std::uint32_t GetFootBlood() const override; - bool IsBleeding() const { return GetPedInterface()->pedFlags.bPedIsBleeding; } - void SetBleeding(bool bleeding) { GetPedInterface()->pedFlags.bPedIsBleeding = bleeding; } + bool IsBleeding() const override { return GetPedInterface()->pedFlags.bPedIsBleeding; } + void SetBleeding(bool bleeding) override { GetPedInterface()->pedFlags.bPedIsBleeding = bleeding; } - bool IsOnFire() const { return GetPedInterface()->pFireOnPed != nullptr; } - void SetOnFire(bool onFire); + bool IsOnFire() const override { return GetPedInterface()->pFireOnPed != nullptr; } + void SetOnFire(bool onFire) override; - bool GetStayInSamePlace() const { return GetPedInterface()->pedFlags.bStayInSamePlace; } - void SetStayInSamePlace(bool stay) { GetPedInterface()->pedFlags.bStayInSamePlace = stay; } + bool GetStayInSamePlace() const override { return GetPedInterface()->pedFlags.bStayInSamePlace; } + void SetStayInSamePlace(bool stay) override { GetPedInterface()->pedFlags.bStayInSamePlace = stay; } - void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const; - void GetVoice(const char** voiceType, const char** voice) const; - void SetVoice(std::int16_t voiceType, std::int16_t voiceID); - void SetVoice(const char* voiceType, const char* voice); - void ResetVoice() { SetVoice(m_sDefaultVoiceType, m_sDefaultVoiceID); } - void SetLanding(bool isLanding) { GetPedInterface()->pedFlags.bIsLanding = isLanding; } - void SetUpdateMetricsRequired(bool required) { GetPedInterface()->pedFlags.bUpdateMatricesRequired = required; } + void GetVoice(std::int16_t* voiceType, std::int16_t* voiceID) const override; + void GetVoice(const char** voiceType, const char** voice) const override; + void SetVoice(std::int16_t voiceType, std::int16_t voiceID) override; + void SetVoice(const char* voiceType, const char* voice) override; + void ResetVoice() override { SetVoice(m_defaultVoiceType, m_defaultVoiceID); } - CWeaponStat* GetCurrentWeaponStat() const noexcept; - float GetCurrentWeaponRange() const noexcept; - void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType); + void SetLanding(bool isLanding) override { GetPedInterface()->pedFlags.bIsLanding = isLanding; } + void SetUpdateMetricsRequired(bool required) override { GetPedInterface()->pedFlags.bUpdateMatricesRequired = required; } - virtual int GetCustomMoveAnim() const noexcept { return m_iCustomMoveAnim; } - bool IsDoingGangDriveby() const noexcept; + CWeaponStat* GetCurrentWeaponStat() const override; + float GetCurrentWeaponRange() const override; + void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) override; - CPedIKSAInterface* GetPedIKInterface() { return &GetPedInterface()->pedIK; } - void* GetPedNodeInterface(std::int32_t nodeId) { return GetPedInterface()->pedNodes[nodeId]; } - std::unique_ptr GetPedIK() { return std::make_unique(GetPedIKInterface()); } - static void StaticSetHooks(); + int GetCustomMoveAnim() const noexcept override { return m_iCustomMoveAnim; } - CEntitySAInterface* GetTargetedObject() { return GetPedInterface()->pTargetedObject; } - ePedState GetPedState() { return GetPedInterface()->pedState; } + bool IsDoingGangDriveby() const override; + + CPedIKSAInterface* GetPedIKInterface() override { return &GetPedInterface()->pedIK; } + void* GetPedNodeInterface(std::int32_t nodeId) override { return GetPedInterface()->pedNodes[nodeId]; } + std::unique_ptr GetPedIK() override { return std::make_unique(GetPedIKInterface()); } + + CEntitySAInterface* GetTargetedObject() const override { return GetPedInterface()->pTargetedObject; } + ePedState GetPedState() const override { return static_cast(GetPedInterface()->pedState); } void GetAttachedSatchels(std::vector &satchelsList) const override; + + static void StaticSetHooks(); + +private: + void ApplySwimAndSlopeRotations(); + +protected: + int m_iCustomMoveAnim{0}; + +private: + std::array, WEAPONSLOT_MAX> m_weapons{}; + + std::unique_ptr m_pedIntelligence{}; + std::unique_ptr m_pedSound{}; + + std::int16_t m_defaultVoiceType; + std::int16_t m_defaultVoiceID; + + std::uint32_t m_type{PLAYER_PED}; + std::uint8_t m_occupiedSeat; + }; diff --git a/Client/game_sa/CPedSoundSA.cpp b/Client/game_sa/CPedSoundSA.cpp index 4fd4ef1b16e..2bce3857180 100644 --- a/Client/game_sa/CPedSoundSA.cpp +++ b/Client/game_sa/CPedSoundSA.cpp @@ -30,7 +30,7 @@ short CPedSoundSA::GetVoiceID() void CPedSoundSA::SetVoiceTypeID(short sVoiceType) { - m_pInterface->m_sVoiceType = sVoiceType; + m_pInterface->m_sVoiceType = static_cast(sVoiceType); } void CPedSoundSA::SetVoiceID(short sVoiceID) diff --git a/Client/game_sa/CPedSoundSA.h b/Client/game_sa/CPedSoundSA.h index d0d4e9c071b..9ed6ae13e00 100644 --- a/Client/game_sa/CPedSoundSA.h +++ b/Client/game_sa/CPedSoundSA.h @@ -14,6 +14,7 @@ #include #include "CAudioEngineSA.h" #include "CAEVehicleAudioEntitySA.h" +#include "CAEWeaponAudioEntitySA.h" class CPedSAInterface; @@ -34,13 +35,14 @@ class CPedSAInterface; #define NUM_PED_VOICE_TYPES 5 -enum +enum ePedVoiceType : std::uint16_t { PED_TYPE_GEN, PED_TYPE_EMG, PED_TYPE_PLAYER, PED_TYPE_GANG, - PED_TYPE_GFD + PED_TYPE_GFD, + PED_TYPE_SPC }; #define NUM_GEN_VOICES 209 @@ -58,59 +60,64 @@ typedef struct class CPedSoundSAInterface : public CAEAudioEntity { public: - std::uint8_t unk_7C[14]; - std::int8_t unk_90; - std::uint8_t unk_91; - std::int16_t m_sVoiceType; - std::int16_t m_sVoiceID; - std::int16_t m_bIsFemale; // 0 = male, 1 = female - bool m_bTalking; - bool m_bDisabled; // m_bEnableSpeech - bool m_bEnableSpeechForScripts; - std::uint8_t m_vocalEnableFlag; - std::uint8_t unk_9C[4]; // From 9C to 9F - CAESound* m_pSound; // CSound* - std::int16_t m_soundId; - std::int16_t m_bankId; - std::int16_t m_pedSpeechSlotIndex; - std::uint8_t unk_A4[4]; - float m_fVoiceVolume; - std::int16_t m_sPhraseId; - std::int16_t unk_B2; - std::uint8_t unk_B4[76]; + CAESound* sounds[5]; + bool isInitialised; + ePedVoiceType m_sVoiceType; + std::uint16_t m_sVoiceID; + std::uint16_t m_bIsFemale; + bool m_bTalking; + bool m_bDisabled; + bool m_bDisabledSpeechForScripts; + bool m_bIsFrontend; + bool m_bIsForcedAudible; + CAESound* m_sound; + std::int16_t m_soundId; + std::int16_t m_bankId; + std::int16_t m_pedSpeechSlotIndex; + float m_fVoiceVolume; + std::int16_t m_sPhraseId; + std::uint32_t m_nextTimeCanSay[19]; }; +static_assert(sizeof(CPedSoundSAInterface) == 0x100, "Invalid size for CPedSoundSAInterface"); // CAEPedAudioEntity class CPedSoundEntitySAInterface : public CAEAudioEntity { public: - std::uint8_t unk_7C[24]; // from 7C to 8C - CPedSAInterface* ped; - std::uint8_t unk_98[16]; // from 98 to A8 + bool canAddEvent; + + std::uint8_t field_7D; + std::int16_t sfxId; + std::uint32_t timeInMS; + + float volume1; + float volume2; + float volume3; + float jetpackSoundSpeedMult; + + CPedSAInterface* ped; + + bool jetpackSoundPlaying; + CAESound* jetpackSound1; + CAESound* jetpackSound2; + CAESound* jetpackSound3; + CAETwinLoopSoundEntity twinLoopSoundEntity; - std::uint8_t unk_150[12]; // from 150 to 15C + CAESound* field_150; + + std::uint8_t field_154[4]; + std::uint8_t field_158[4]; }; +static_assert(sizeof(CPedSoundEntitySAInterface) == 0x15C, "Invalid size for CPedSoundEntitySAInterface"); // CAEPedWeaponAudioEntity -class CPedWeaponAudioEntitySAInterface : public CAEAudioEntity +class CPedWeaponAudioEntitySAInterface : public CAEWeaponAudioEntitySAInterface { public: - bool playedMiniGunFireSound; - bool unk_7D; // CAEWeaponAudioEntity::PlayMiniGunFireSounds - std::uint8_t unk_7E[2]; // from 7E to 7F - std::uint8_t chainsawSoundState; - std::uint8_t unk_81[3]; // from 81 to 83 - std::uint32_t flameThrowerLastPlayedTime; - std::uint32_t spraycanLastPlayedTime; - std::uint32_t extinguisherLastPlayedTime; - std::uint32_t miniGunFireSoundPlayedTime; - std::uint32_t timeChainsaw; - std::uint32_t timeLastFired; - void* sounds; - bool active; - std::uint8_t unk_A1[3]; // from A1 to A3 - CPedSAInterface* ped; + bool m_bIsInitialised; + CPedSAInterface* m_ped; }; +static_assert(sizeof(CPedWeaponAudioEntitySAInterface) == 0xA8, "Invalid size for CPedWeaponAudioEntitySAInterface"); class CPedSoundSA : public CPedSound { diff --git a/Client/game_sa/CWeaponSA.cpp b/Client/game_sa/CWeaponSA.cpp index d419734b8ee..95bb64e6d42 100644 --- a/Client/game_sa/CWeaponSA.cpp +++ b/Client/game_sa/CWeaponSA.cpp @@ -283,7 +283,7 @@ bool CWeaponSA::FireBullet(CEntity* pFiringEntity, const CVector& vecOrigin, con // Fire sound if (pFiringPlayerPed) - pFiringPlayerPed->AddWeaponAudioEvent(EPedWeaponAudioEvent::FIRE); + pFiringPlayerPed->AddWeaponAudioEvent(EPedWeaponAudioEventType::FIRE); // Do post shot lag compensation reset & script events if (pGame->m_pPostWeaponFireHandler && pFiringPlayerPed) diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index bd8bb5e2f73..180e9676b14 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: sdk/game/CPed.h * PURPOSE: Ped entity interface * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://www.multitheftauto.com/ * *****************************************************************************/ @@ -91,7 +91,7 @@ enum ATTACH_DIRECTION_RIGHT }; -enum eFightingStyle +enum eFightingStyle : std::uint8_t { STYLE_STANDARD = 4, STYLE_BOXING, @@ -151,25 +151,24 @@ enum eLandedPedFoot LANDED_PED_LEFT_FOOT = 1, }; -inline bool IsValidMoveAnim(std::uint32_t iMoveAnim) -{ - return (iMoveAnim == MOVE_DEFAULT) || (iMoveAnim >= MOVE_PLAYER && iMoveAnim <= MOVE_JETPACK) || (iMoveAnim >= MOVE_MAN && iMoveAnim <= MOVE_SKATE); -} - -enum +enum ePedEntityType { PLAYER_PED, CIVILIAN_PED }; -namespace EPedWeaponAudioEvent +enum class EPedWeaponAudioEventType { - enum EPedWeaponAudioEventType - { - FIRE = 0x91, - }; -} -using EPedWeaponAudioEvent::EPedWeaponAudioEventType; + FIRE = 0x91, + RELOAD_A = 0x92, + RELOAD_B = 0x93, + FIRE_MINIGUN_AMMO = 0x96, + FIRE_MINIGUN_NO_AMMO = 0x97, + CHAINSAW_IDLE = 0x99, + CHAINSAW_ACTIVE = 0x9A, + CHAINSAW_CUTTING = 0x9B, + STEALTH_KILL = 0x9C, +}; struct SSatchelsData { @@ -178,43 +177,54 @@ struct SSatchelsData CVector* vecAttachedRotation; }; +inline bool IsValidMoveAnim(std::uint32_t iMoveAnim) noexcept +{ + return (iMoveAnim == MOVE_DEFAULT) || (iMoveAnim >= MOVE_PLAYER && iMoveAnim <= MOVE_JETPACK) || (iMoveAnim >= MOVE_MAN && iMoveAnim <= MOVE_SKATE); +} + class CPed : public virtual CPhysical { public: virtual ~CPed(){}; - virtual class CPedSAInterface* GetPedInterface() = 0; + virtual class CPedSAInterface* GetPedInterface() noexcept = 0; + + virtual void SetModelIndex(std::uint32_t modelIndex) = 0; virtual void DetachPedFromEntity() = 0; - virtual CVehicle* GetVehicle() const noexcept = 0; - virtual void Respawn(const CVector* position, bool cameraCut) = 0; + virtual CVehicle* GetVehicle() const = 0; + + virtual void Respawn(CVector* position, bool cameraCut) = 0; + + virtual float GetHealth() const = 0; + virtual void SetHealth(float health) = 0; - virtual void SetModelIndex(unsigned long ulModel) = 0; + virtual float GetArmor() const = 0; + virtual void SetArmor(float armor) = 0; - virtual float GetHealth() const = 0; - virtual void SetHealth(float health) = 0; - virtual float GetArmor() const = 0; - virtual void SetArmor(float armor) = 0; - virtual float GetOxygenLevel() const = 0; - virtual void SetOxygenLevel(float oxygen) = 0; - virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, const CVector* target, const CEntity* targetEntity) = 0; + virtual float GetOxygenLevel() const = 0; + virtual void SetOxygenLevel(float oxygen) = 0; + + virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) = 0; virtual CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill weaponSkill) = 0; - virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept = 0; - virtual CWeapon* GetWeapon(eWeaponType weaponType) const noexcept = 0; + virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const = 0; + virtual CWeapon* GetWeapon(eWeaponType weaponType) const = 0; virtual void ClearWeapons() noexcept = 0; - virtual void RemoveWeaponModel(int model) = 0; + virtual void RemoveWeaponModel(std::uint32_t model) = 0; virtual void ClearWeapon(eWeaponType weaponType) = 0; - virtual void SetIsStanding(bool standing) = 0; - virtual DWORD GetType() const noexcept = 0; + virtual void SetIsStanding(bool standing) = 0; + + virtual std::uint32_t GetType() const noexcept = 0; virtual CPedIntelligence* GetPedIntelligence() const noexcept = 0; virtual CPedSound* GetPedSound() const noexcept = 0; - virtual float GetCurrentRotation() const = 0; - virtual float GetTargetRotation() const = 0; - virtual void SetCurrentRotation(float rotation) = 0; - virtual void SetTargetRotation(float rotation) = 0; + virtual float GetCurrentRotation() const = 0; + virtual float GetTargetRotation() const = 0; + virtual void SetCurrentRotation(float rotation) = 0; + virtual void SetTargetRotation(float rotation) = 0; + virtual eWeaponSlot GetCurrentWeaponSlot() const = 0; virtual void SetCurrentWeaponSlot(eWeaponSlot weaponSlot) = 0; @@ -223,11 +233,11 @@ class CPed : public virtual CPhysical virtual bool IsDucking() const = 0; virtual void SetDucking(bool duck) = 0; - virtual bool IsInWater() const noexcept = 0; - virtual int GetCantBeKnockedOffBike() const = 0; - virtual void SetCantBeKnockedOffBike(int cantBeKnockedOffBike) = 0; - virtual void SetBleeding(bool bleeding) = 0; + virtual bool IsInWater() const = 0; + + virtual std::uint32_t GetCantBeKnockedOffBike() const = 0; + virtual void SetCantBeKnockedOffBike(std::uint32_t cantBeKnockedOffBike) = 0; virtual bool IsWearingGoggles() const = 0; virtual void SetGogglesState(bool isWearingThem) = 0; @@ -238,11 +248,11 @@ class CPed : public virtual CPhysical virtual eFightingStyle GetFightingStyle() const = 0; virtual void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) = 0; - virtual CEntity* GetContactEntity() const noexcept = 0; + virtual CEntity* GetContactEntity() const = 0; - virtual std::uint8_t GetRunState() const = 0; + virtual int GetRunState() const = 0; - virtual CEntity* GetTargetedEntity() const noexcept = 0; + virtual CEntity* GetTargetedEntity() const = 0; virtual void SetTargetedEntity(CEntity* targetEntity) = 0; virtual bool GetCanBeShotInVehicle() const = 0; @@ -256,9 +266,12 @@ class CPed : public virtual CPhysical virtual void RemoveBodyPart(std::uint8_t boneID, std::uint8_t direction) = 0; - virtual void SetFootBlood(std::uint32_t footBlood) = 0; + virtual void SetFootBlood(std::uint32_t footBlood) = 0; virtual std::uint32_t GetFootBlood() const = 0; + virtual bool IsBleeding() const = 0; + virtual void SetBleeding(bool bleeding) = 0; + virtual bool IsOnFire() const = 0; virtual void SetOnFire(bool onFire) = 0; @@ -270,22 +283,23 @@ class CPed : public virtual CPhysical virtual void SetVoice(std::int16_t voiceType, std::int16_t voiceID) = 0; virtual void SetVoice(const char* voiceType, const char* voice) = 0; virtual void ResetVoice() = 0; + virtual void SetLanding(bool isLanding) = 0; virtual void SetUpdateMetricsRequired(bool required) = 0; - virtual CWeaponStat* GetCurrentWeaponStat() const noexcept = 0; - virtual float GetCurrentWeaponRange() const noexcept = 0; + virtual CWeaponStat* GetCurrentWeaponStat() const = 0; + virtual float GetCurrentWeaponRange() const = 0; virtual void AddWeaponAudioEvent(EPedWeaponAudioEventType audioEventType) = 0; virtual int GetCustomMoveAnim() const noexcept = 0; - virtual bool IsDoingGangDriveby() const noexcept = 0; + virtual bool IsDoingGangDriveby() const = 0; virtual CPedIKSAInterface* GetPedIKInterface() = 0; virtual void* GetPedNodeInterface(std::int32_t nodeId) = 0; virtual std::unique_ptr GetPedIK() = 0; - virtual CEntitySAInterface* GetTargetedObject() = 0; - virtual ePedState GetPedState() = 0; + virtual CEntitySAInterface* GetTargetedObject() const = 0; + virtual ePedState GetPedState() const = 0; virtual void GetAttachedSatchels(std::vector &satchelsList) const = 0; }; diff --git a/Client/sdk/game/CWeaponInfo.h b/Client/sdk/game/CWeaponInfo.h index edd308663b7..16567a0b64a 100644 --- a/Client/sdk/game/CWeaponInfo.h +++ b/Client/sdk/game/CWeaponInfo.h @@ -15,7 +15,7 @@ class CVector; -enum eWeaponSkill +enum eWeaponSkill : std::uint8_t { WEAPONSKILL_POOR = 0, WEAPONSKILL_STD, From 305ceb73f9a1f162d1f1687b04519456743bfc51 Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 24 Dec 2024 04:15:37 +0100 Subject: [PATCH 08/12] Little changes --- Client/game_sa/CPedSA.cpp | 14 ++++++++------ Client/sdk/game/CPed.h | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 09270a2f0ff..4d8dece9b4e 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -549,15 +549,17 @@ void CPedSA::SetOxygenLevel(float oxygen) void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const { // Array of projectiles objects - CProjectileSAInterface** projectilesArray = (CProjectileSAInterface**)ARRAY_CProjectile; - CProjectileSAInterface* projectileInterface; + auto** projectilesArray = reinterpret_cast(ARRAY_CProjectile); + CProjectileSAInterface* projectileInterface = nullptr; // Array of projectiles infos - CProjectileInfoSAInterface* projectilesInfoArray = (CProjectileInfoSAInterface*)ARRAY_CProjectileInfo; - CProjectileInfoSAInterface* projectileInfoInterface; + auto* projectilesInfoArray = reinterpret_cast(ARRAY_CProjectileInfo); + CProjectileInfoSAInterface* projectileInfoInterface = nullptr; + + satchelsList.reserve(PROJECTILE_COUNT); // Loop through all projectiles - for (std::uint8_t i = 0; i < PROJECTILE_COUNT; i++) + for (std::size_t i = 0; i < PROJECTILE_COUNT; i++) { projectileInterface = projectilesArray[i]; @@ -573,7 +575,7 @@ void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const continue; // Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges - satchelsList.push_back({projectileInterface, &projectileInterface->m_vecAttachedOffset, &projectileInterface->m_vecAttachedRotation}); + satchelsList.emplace_back(projectileInterface, &projectileInterface->m_vecAttachedOffset, &projectileInterface->m_vecAttachedRotation); } } diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 180e9676b14..7faf70edcf1 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -175,6 +175,8 @@ struct SSatchelsData CProjectileSAInterface* pProjectileInterface; CVector* vecAttachedOffsets; CVector* vecAttachedRotation; + + SSatchelsData(CProjectileSAInterface* proj, CVector* offset, CVector* rotation) : pProjectileInterface(proj), vecAttachedOffsets(offset), vecAttachedRotation(rotation) {} }; inline bool IsValidMoveAnim(std::uint32_t iMoveAnim) noexcept From eed615c82779c4aa94a0ba04ddf7ce28d8d4f135 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 16 Feb 2025 14:17:55 +0100 Subject: [PATCH 09/12] Small changes --- Client/game_sa/CPedSA.cpp | 21 +++++++++++++-------- Client/game_sa/CPedSA.h | 4 ++-- Client/sdk/game/CPed.h | 4 ++-- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index f15ee4ada1a..7b0281deca3 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -189,12 +189,12 @@ CWeapon* CPedSA::GetWeapon(eWeaponType weaponType) const return (weapon && weapon->GetType() == weaponType) ? weapon : nullptr; } -CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) const +CWeapon* CPedSA::GetWeapon(eWeaponSlot weaponSlot) const noexcept { return (weaponSlot >= 0 && weaponSlot < WEAPONSLOT_MAX) ? m_weapons[weaponSlot].get() : nullptr; } -void CPedSA::ClearWeapons() noexcept +void CPedSA::ClearWeapons() { // Remove all the weapons for (auto& weapon : m_weapons) @@ -258,8 +258,11 @@ void CPedSA::SetCurrentWeaponSlot(eWeaponSlot weaponSlot) if (localPlayer == this) { auto* playerInfo = static_cast(pGame->GetPlayerInfo()); - if (auto* pInfoInterface = playerInfo->GetInterface()) - pInfoInterface->PlayerPedData.m_nChosenWeapon = weaponSlot; + if (!playerInfo) + return; + + if (auto* infoInterface = playerInfo->GetInterface()) + infoInterface->PlayerPedData.m_nChosenWeapon = weaponSlot; // void __thiscall CPlayerPed::MakeChangesForNewWeapon(CPlayerPed *this, int a3) changeWeaponFunc = FUNC_MakeChangesForNewWeapon_Slot; @@ -422,6 +425,8 @@ bool CPedSA::SetOnFire(bool onFire) return false; auto* fireManager = static_cast(pGame->GetFireManager()); + if (!fireManager) + return false; if (onFire) { @@ -589,8 +594,8 @@ void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const //////////////////////////////////////////////////////////////// #define HOOKPOS_CPed_PreRenderAfterTest 0x5E65A0 #define HOOKSIZE_CPed_PreRenderAfterTest 15 -static constexpr DWORD RETURN_CPed_PreRenderAfterTest = 0x5E65AF; -static constexpr DWORD RETURN_CPed_PreRenderAfterTestSkip = 0x5E6658; +static constexpr std::uintptr_t RETURN_CPed_PreRenderAfterTest = 0x5E65AF; +static constexpr std::uintptr_t RETURN_CPed_PreRenderAfterTestSkip = 0x5E6658; static void _declspec(naked) HOOK_CPed_PreRenderAfterTest() { _asm @@ -628,8 +633,8 @@ static void _declspec(naked) HOOK_CPed_PreRenderAfterTest() //////////////////////////////////////////////////////////////// #define HOOKPOS_CPed_PreRenderAfterTest_Mid 0x5E6669 #define HOOKSIZE_CPed_PreRenderAfterTest_Mid 5 -static constexpr DWORD RETURN_CPed_PreRenderAfterTest_Mid = 0x5E666E; -static constexpr DWORD RETURN_CPed_PreRenderAfterTest_MidSkip = 0x5E766F; +static constexpr std::uintptr_t RETURN_CPed_PreRenderAfterTest_Mid = 0x5E666E; +static constexpr std::uintptr_t RETURN_CPed_PreRenderAfterTest_MidSkip = 0x5E766F; static void _declspec(naked) HOOK_CPed_PreRenderAfterTest_Mid() { _asm diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 97c39096f27..a8c7421d633 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -375,9 +375,9 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) override; CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill) override; - CWeapon* GetWeapon(eWeaponSlot weaponSlot) const override; + CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept override; CWeapon* GetWeapon(eWeaponType weaponType) const override; - void ClearWeapons() noexcept; + void ClearWeapons(); void RemoveWeaponModel(std::uint32_t model) override; void ClearWeapon(eWeaponType weaponType) override; diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 7faf70edcf1..cb071183cf7 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -210,9 +210,9 @@ class CPed : public virtual CPhysical virtual bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) = 0; virtual CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill weaponSkill) = 0; - virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const = 0; + virtual CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept = 0; virtual CWeapon* GetWeapon(eWeaponType weaponType) const = 0; - virtual void ClearWeapons() noexcept = 0; + virtual void ClearWeapons() = 0; virtual void RemoveWeaponModel(std::uint32_t model) = 0; virtual void ClearWeapon(eWeaponType weaponType) = 0; From b71626d9d1b63416815f58a79a8f62e8f04b825f Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 16 Feb 2025 14:20:55 +0100 Subject: [PATCH 10/12] Update CPed.h --- Client/sdk/game/CPed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index cb071183cf7..d6d7dae180f 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -275,7 +275,7 @@ class CPed : public virtual CPhysical virtual void SetBleeding(bool bleeding) = 0; virtual bool IsOnFire() const = 0; - virtual void SetOnFire(bool onFire) = 0; + virtual bool SetOnFire(bool onFire) = 0; virtual bool GetStayInSamePlace() const = 0; virtual void SetStayInSamePlace(bool stay) = 0; From b6f341a2e5dc7ab5e91af8bf1a81a9843d0e9f87 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 16 Feb 2025 14:21:06 +0100 Subject: [PATCH 11/12] Update CPedSA.h --- Client/game_sa/CPedSA.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index a8c7421d633..795f176f570 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -443,7 +443,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA bool IsBleeding() const override { return GetPedInterface()->pedFlags.bPedIsBleeding; } void SetBleeding(bool bleeding) override { GetPedInterface()->pedFlags.bPedIsBleeding = bleeding; } - bool IsOnFire() override { return GetPedInterface()->pFireOnPed != nullptr; } + bool IsOnFire() const override { return GetPedInterface()->pFireOnPed != nullptr; } bool SetOnFire(bool onFire) override; bool GetStayInSamePlace() const override { return GetPedInterface()->pedFlags.bStayInSamePlace; } From 86b0202d076f68e724a6ae17018386239c6c9440 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 1 Mar 2025 17:58:19 +0100 Subject: [PATCH 12/12] Fix build --- Client/game_sa/CPedSA.cpp | 31 ------------------------------- Client/game_sa/CWeaponSA.cpp | 4 ++-- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 4780c5f5e50..0601cabcf71 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -671,34 +671,3 @@ void CPedSA::StaticSetHooks() EZHookInstall(CPed_PreRenderAfterTest); EZHookInstall(CPed_PreRenderAfterTest_Mid); } - -void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const -{ - // Array of projectiles objects - CProjectileSAInterface** projectilesArray = (CProjectileSAInterface**)ARRAY_CProjectile; - CProjectileSAInterface* pProjectileInterface; - - // Array of projectiles infos - CProjectileInfoSAInterface* projectilesInfoArray = (CProjectileInfoSAInterface*)ARRAY_CProjectileInfo; - CProjectileInfoSAInterface* pProjectileInfoInterface; - - // Loop through all projectiles - for (size_t i = 0; i < PROJECTILE_COUNT; i++) - { - pProjectileInterface = projectilesArray[i]; - - // is attached to our ped? - if (!pProjectileInterface || pProjectileInterface->m_pAttachedEntity != m_pInterface) - continue; - - // index is always the same for both arrays - pProjectileInfoInterface = &projectilesInfoArray[i]; - - // We are only interested in satchels - if (!pProjectileInfoInterface || pProjectileInfoInterface->dwProjectileType != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE) - continue; - - // Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges - satchelsList.push_back({pProjectileInterface, &pProjectileInterface->m_vecAttachedOffset, &pProjectileInterface->m_vecAttachedRotation}); - } -} diff --git a/Client/game_sa/CWeaponSA.cpp b/Client/game_sa/CWeaponSA.cpp index c6cf9916e0a..d0fcc3785f1 100644 --- a/Client/game_sa/CWeaponSA.cpp +++ b/Client/game_sa/CWeaponSA.cpp @@ -133,8 +133,8 @@ bool CWeaponSA::FireBullet(CEntity* firingEntity, const CVector& vecOrigin, cons FireInstantHit(firingEntity, &vecOrigin, &vecGunMuzzle, nullptr, &vecTarget, nullptr, false, true); // Fire sound - if (pFiringPlayerPed) - pFiringPlayerPed->AddWeaponAudioEvent(EPedWeaponAudioEventType::FIRE); + if (firingPlayerPed) + firingPlayerPed->AddWeaponAudioEvent(EPedWeaponAudioEventType::FIRE); // Do post shot lag compensation reset & script events if (pGame->m_pPostWeaponFireHandler && firingPlayerPed)