From 0a7120b6220a2efad0564dd1dac7961a7c11e639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 21 Jun 2019 21:16:51 +0300 Subject: Shotgun fix, CPed, CWeaponInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: eray orçunus --- src/entities/Ped.cpp | 144 ++++++++++++++++++++++++++++++++++++++++++++++----- src/entities/Ped.h | 29 ++++++----- 2 files changed, 149 insertions(+), 24 deletions(-) (limited to 'src/entities') diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 81534915..35e8e957 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -9,6 +9,7 @@ #include "Ped.h" #include "PlayerPed.h" #include "General.h" +#include "VisibilityPlugins.h" bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -23,8 +24,6 @@ WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4 WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); } WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); } -WRAPPER void CPed::SelectGunIfArmed(void) { EAXJMP(0x4DD920); } -WRAPPER void CPed::RemoveWeaponModel(int) { EAXJMP(0x4CF980); } static char ObjectiveText[34][28] = { "No Obj", @@ -181,6 +180,18 @@ static char WaitStateText[21][16] = { "Finish Flee", }; +static RwObject* +RemoveAllModelCB(RwObject *object, void *data) +{ + RpAtomic* atomic = (RpAtomic*)object; + if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) + { + RpClumpRemoveAtomic(atomic->clump, atomic); + RpAtomicDestroy(atomic); + } + return object; +} + static PedOnGroundState CheckForPedsOnGroundToAttack(CPlayerPed *player, CPed **pedOnGround) { @@ -718,7 +729,7 @@ CPed::Attack(void) } else { firePos = GetMatrix() * firePos; } - + GetWeapon()->Fire(this, &firePos); if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) { @@ -752,29 +763,32 @@ CPed::Attack(void) if (m_ped_flagA4 || CTimer::GetTimeInMilliseconds() < m_lastHitTime) { weaponAnimAssoc->callbackType = 0; } - - lastReloadWasInFuture = false; } + + lastReloadWasInFuture = false; } if (ourWeaponType == WEAPONTYPE_SHOTGUN) { weaponAnimTime = weaponAnimAssoc->currentTime; + firePos = ourWeapon->m_vecFireOffset; + if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) { for (i = GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) - RwV3dTransformPoints((RwV3d*)ourWeapon->m_vecFireOffset, (RwV3d*)ourWeapon->m_vecFireOffset, 1, &i->modelling); + RwV3dTransformPoints((RwV3d*)firePos, (RwV3d*)firePos, 1, &i->modelling); CVector gunshellPos( - ourWeapon->m_vecFireOffset.x - 0.6f * GetForward().x, - ourWeapon->m_vecFireOffset.y - 0.6f * GetForward().y, - ourWeapon->m_vecFireOffset.z - 0.15f * GetUp().z + firePos.x - 0.6f * GetForward().x, + firePos.y - 0.6f * GetForward().y, + firePos.z - 0.15f * GetUp().z ); + CVector2D gunshellRot( GetRight().x, GetRight().y ); gunshellRot.Normalise(); - CWeapon::AddGunshell(this, gunshellPos, gunshellRot, 0.025f); + GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f); } } animEnd = ourWeapon->m_fAnimLoopEnd; @@ -787,7 +801,6 @@ CPed::Attack(void) if (weaponAnimTime > animEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) { if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animEnd - // BUG: We currently don't know any situation this cond. could be true. && (m_ped_flagA4 || CTimer::GetTimeInMilliseconds() < m_lastHitTime) && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) { @@ -830,7 +843,7 @@ CPed::Attack(void) if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) { weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT; weaponAnimAssoc->flags &= ~ASSOC_RUNNING; - weaponAnimAssoc->blendDelta = -4.0; + weaponAnimAssoc->blendDelta = -4.0f; } } } @@ -865,6 +878,107 @@ CPed::Attack(void) CPed::FinishedAttackCB(0, this); } +void +CPed::RemoveWeaponModel(int modelId) +{ + // modelId is not used!! This function just removes the current weapon. + RwFrameForAllObjects(GetNodeFrame(PED_HANDR),RemoveAllModelCB,0); + m_wepModelID = -1; +} + +void +CPed::SetCurrentWeapon(eWeaponType weaponType) +{ + CWeaponInfo* weaponInfo; + + if (HasWeapon(weaponType)) { + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(weaponInfo->m_nModelId); + + m_currentWeapon = weaponType; + + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + AddWeaponModel(weaponInfo->m_nModelId); + } +} + +// Only used while deciding which gun ped should switch to, if no ammo left. +bool +CPed::SelectGunIfArmed(void) +{ + eWeaponType weaponType; + + for (int i = 0; i < m_maxWeaponTypeAllowed; i++) { + + if (m_weapons[i].m_nAmmoTotal > 0) { + weaponType = m_weapons[i].m_eWeaponType; + + // Original condition was ridiculous + // if (weaponType == WEAPONTYPE_COLT45 || weaponType < WEAPONTYPE_M16 || weaponType < WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_FLAMETHROWER) + if (weaponType < WEAPONTYPE_MOLOTOV) { + SetCurrentWeapon(weaponType); + return true; + } + } + } + SetCurrentWeapon(WEAPONTYPE_UNARMED); + return false; +} + +void +CPed::Duck(void) +{ + if (CTimer::GetTimeInMilliseconds() > m_duckTimer) + ClearDuck(); +} + +void +CPed::ClearDuck(void) +{ + CAnimBlendAssociation *animAssoc; + + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_DUCK_DOWN); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_DUCK_LOW); + + if (animAssoc) { + + if (m_ped_flagE8) { + + if (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN) { + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RBLOCK_CSHOOT); + if (!animAssoc || animAssoc->blendDelta < 0.0f) { + CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + } + } + } + } else + m_ped_flagE10 = false; +} + +void +CPed::ClearPointGunAt(void) +{ + CAnimBlendAssociation *animAssoc; + CWeaponInfo *weaponInfo; + + ClearLookFlag(); + ClearAimFlag(); + m_ped_flagA8 = false; + if (m_nPedState == PED_AIM_GUN) { + RestorePreviousState(); + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_AnimToPlay); + if (!animAssoc || animAssoc->blendDelta < 0.0f) { + animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_Anim2ToPlay); + } + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -4.0; + } + } +} + STARTPATCHES InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); @@ -881,4 +995,10 @@ STARTPATCHES InjectHook(0x4E68A0, &CPed::FinishedAttackCB, PATCH_JUMP); InjectHook(0x4E5BD0, &CheckForPedsOnGroundToAttack, PATCH_JUMP); InjectHook(0x4E6BA0, &CPed::Attack, PATCH_JUMP); + InjectHook(0x4CF980, &CPed::RemoveWeaponModel, PATCH_JUMP); + InjectHook(0x4CFA60, &CPed::SetCurrentWeapon, PATCH_JUMP); + InjectHook(0x4DD920, &CPed::SelectGunIfArmed, PATCH_JUMP); + InjectHook(0x4E4A10, &CPed::Duck, PATCH_JUMP); + InjectHook(0x4E4A30, &CPed::ClearDuck, PATCH_JUMP); + InjectHook(0x4E6180, &CPed::ClearPointGunAt, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Ped.h b/src/entities/Ped.h index 45251d46..660f3462 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -12,10 +12,6 @@ struct CPathNode; -enum { - PED_MAX_WEAPONS = 13 -}; - enum PedOnGroundState { NO_PED, PED_BELOW_PLAYER, @@ -138,7 +134,7 @@ public: uint8 m_ped_flagE1 : 1; uint8 m_ped_flagE2 : 1; uint8 m_ped_flagE4 : 1; - uint8 m_ped_flagE8 : 1; + uint8 m_ped_flagE8 : 1; // can duck? uint8 m_ped_flagE10 : 1; // can't attack if it's set uint8 m_ped_flagE20 : 1; uint8 m_ped_flagE40 : 1; @@ -225,10 +221,11 @@ public: uint8 stuff5[24]; CEntity *m_pCollidingEntity; uint8 stuff6[12]; - CWeapon m_weapons[PED_MAX_WEAPONS]; + CWeapon m_weapons[NUM_PED_WEAPONTYPES]; int32 stuff7; - uint8 m_currentWeapon; - uint8 stuff[3]; + uint8 m_currentWeapon; // eWeaponType + uint8 m_maxWeaponTypeAllowed; // eWeaponType + uint8 stuff[2]; int32 m_pPointGunAt; CVector m_vecHitLastPos; uint8 stuff8[12]; @@ -241,8 +238,11 @@ public: uint32 m_standardTimer; uint32 m_attackTimer; uint32 m_lastHitTime; - uint8 stuff9[22]; - uint8 m_bodyPartBleeding; + uint32 m_hitRecoverTimer; + uint32 field_4E0; + uint32 m_duckTimer; + uint8 stuff9[10]; + uint8 m_bodyPartBleeding; // PedNode uint8 m_field_4F3; CPed *m_nearPeds[10]; uint16 m_numNearPeds; @@ -272,12 +272,17 @@ public: void RestorePreviousState(void); void ClearAttack(void); bool IsPedHeadAbovePos(float zOffset); - void RemoveWeaponModel(int); - void SelectGunIfArmed(void); + void RemoveWeaponModel(int modelId); + void SetCurrentWeapon(eWeaponType weaponType); + bool SelectGunIfArmed(void); + void Duck(void); + void ClearDuck(void); + void ClearPointGunAt(void); static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data); static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data); static void FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg); + bool HasWeapon(eWeaponType weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } -- cgit v1.2.3