diff options
Diffstat (limited to 'src/peds/PlayerPed.cpp')
-rw-r--r-- | src/peds/PlayerPed.cpp | 1120 |
1 files changed, 903 insertions, 217 deletions
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index ef877965..b3fe0ff0 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -16,21 +16,37 @@ #include "Pools.h" #include "Darkel.h" #include "CarCtrl.h" +#include "MBlur.h" +#include "Streaming.h" +#include "Population.h" +#include "Script.h" +#include "Replay.h" +#include "PedPlacement.h" +#include "VarConsole.h" #include "SaveBuf.h" #define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f -#ifdef VC_PED_PORTS bool CPlayerPed::bDontAllowWeaponChange; +#ifndef MASTER +bool CPlayerPed::bDebugPlayerInfo; #endif const uint32 CPlayerPed::nSaveStructSize = #ifdef COMPATIBLE_SAVES - 1520; + 1752; #else sizeof(CPlayerPed); #endif +int32 idleAnimBlockIndex; + +CPad* +GetPadFromPlayer(CPlayerPed*) +{ + return CPad::GetPad(0); +} + CPlayerPed::~CPlayerPed() { delete m_pWanted; @@ -49,7 +65,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_pWanted->Initialise(); m_pArrestingCop = nil; m_currentWeapon = WEAPONTYPE_UNARMED; - m_nSelectedWepSlot = WEAPONTYPE_UNARMED; + m_nSelectedWepSlot = WEAPONSLOT_UNARMED; m_nSpeedTimer = 0; m_bSpeedTimerFlag = false; SetWeaponLockOnTarget(nil); @@ -59,23 +75,36 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) #endif m_fStaminaProgress = 0.0f; m_nEvadeAmount = 0; - field_1367 = 0; + m_pEvadingFrom = nil; m_nHitAnimDelayTimer = 0; m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; m_bHasLockOnTarget = false; m_bCanBeDamaged = true; + m_bNoPosForMeleeAttack = false; m_fWalkAngle = 0.0f; m_fFPSMoveHeading = 0.0f; + m_pMinigunTopAtomic = nil; + m_fGunSpinSpeed = 0.0; + m_fGunSpinAngle = 0.0; + m_nPadDownPressedInMilliseconds = 0; m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1; - field_1413 = 0; + unk1 = false; for (int i = 0; i < 6; i++) { m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f); m_pPedAtSafePos[i] = nil; + m_pMeleeList[i] = nil; } + m_nAttackDirToCheck = 0; + m_nLastBusFareCollected = 0; + idleAnimBlockIndex = CAnimManager::GetAnimationBlockIndex("playidles"); +#ifdef FREE_CAM + m_bFreeAimActive = false; +#endif } -void CPlayerPed::ClearWeaponTarget() +void +CPlayerPed::ClearWeaponTarget() { if (m_nPedType == PEDTYPE_PLAYER1) { SetWeaponLockOnTarget(nil); @@ -101,11 +130,7 @@ void CPlayerPed::MakeObjectTargettable(int32 handle) { for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) { - if ( -#ifdef FIX_BUGS - m_nTargettableObjects[i] == -1 || -#endif - CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) { + if (CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) { m_nTargettableObjects[i] = handle; return; } @@ -156,6 +181,11 @@ CPlayerPed::SetupPlayerPed(int32 index) CWorld::Add(player); player->m_wepAccuracy = 100; + +#ifndef MASTER + VarConsole.Add("Debug PlayerPed", &CPlayerPed::bDebugPlayerInfo, true); + VarConsole.Add("Tweak Vehicle Handling", &CVehicle::m_bDisplayHandlingInfo, true); +#endif } void @@ -187,20 +217,22 @@ CPlayerPed::UseSprintEnergy(void) } void -CPlayerPed::MakeChangesForNewWeapon(int8 weapon) +CPlayerPed::MakeChangesForNewWeapon(eWeaponType weapon) { if (m_nPedState == PED_SNIPER_MODE) { RestorePreviousState(); TheCamera.ClearPlayerWeaponMode(); } SetCurrentWeapon(weapon); + m_nSelectedWepSlot = m_currentWeapon; GetWeapon()->m_nAmmoInClip = Min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); - if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM)) + if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM)) ClearWeaponTarget(); - CAnimBlendAssociation *weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)->m_AnimToPlay); + // WEAPONTYPE_SNIPERRIFLE? Wut? + CAnimBlendAssociation* weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE))); if (weaponAnim) { weaponAnim->SetRun(); weaponAnim->flags |= ASSOC_FADEOUTWHENDONE; @@ -209,6 +241,13 @@ CPlayerPed::MakeChangesForNewWeapon(int8 weapon) } void +CPlayerPed::MakeChangesForNewWeapon(int32 slot) +{ + if(slot != -1) + MakeChangesForNewWeapon(m_weapons[slot].m_eWeaponType); +} + +void CPlayerPed::ReApplyMoveAnims(void) { static AnimationId moveAnims[] = { ANIM_STD_WALK, ANIM_STD_RUN, ANIM_STD_RUNFAST, ANIM_STD_IDLE, ANIM_STD_STARTWALK }; @@ -230,13 +269,16 @@ CPlayerPed::ReApplyMoveAnims(void) void CPlayerPed::SetInitialState(void) { + m_nDrunkenness = 0; + m_nFadeDrunkenness = 0; + CMBlur::ClearDrunkBlur(); + m_nDrunkCountdown = 0; m_bAdrenalineActive = false; m_nAdrenalineTime = 0; CTimer::SetTimeScale(1.0f); m_pSeekTarget = nil; m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - m_fleeFromPosX = 0.0f; - m_fleeFromPosY = 0.0f; + m_fleeFromPos = CVector2D(0.0f, 0.0f); m_fleeFrom = nil; m_fleeTimer = 0; m_objective = OBJECTIVE_NONE; @@ -248,13 +290,14 @@ CPlayerPed::SetInitialState(void) bRenderPedInCar = true; if (m_pFire) m_pFire->Extinguish(); + RpAnimBlendClumpRemoveAllAssociations(GetClump()); SetPedState(PED_IDLE); SetMoveState(PEDMOVE_STILL); m_nLastPedState = PED_NONE; m_animGroup = ASSOCGRP_PLAYER; m_fMoveSpeed = 0.0f; - m_nSelectedWepSlot = WEAPONTYPE_UNARMED; + m_nSelectedWepSlot = WEAPONSLOT_UNARMED; m_nEvadeAmount = 0; m_pEvadingFrom = nil; bIsPedDieAnimPlaying = false; @@ -262,6 +305,11 @@ CPlayerPed::SetInitialState(void) m_bCanBeDamaged = true; m_pedStats->m_temper = 50; m_fWalkAngle = 0.0f; + if (m_attachedTo && !bUsesCollision) + bUsesCollision = true; + + m_attachedTo = nil; + m_attachWepAmmo = 0; } void @@ -288,6 +336,8 @@ CPlayerPed::SetRealMoveAnim(void) curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED); if (!curIdleAssoc) curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE); + if (!curIdleAssoc) + curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE); if (!((curRunStopAssoc && curRunStopAssoc->IsRunning()) || (curRunStopRAssoc && curRunStopRAssoc->IsRunning()))) { @@ -304,7 +354,7 @@ CPlayerPed::SetRealMoveAnim(void) RestoreHeadingRate(); if (!curIdleAssoc) { - if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, + if (m_fCurrentStamina < 0.0f && !bIsAimingGun && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, nil, true, false, false, false, false, false)) { curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 8.0f); @@ -318,7 +368,7 @@ CPlayerPed::SetRealMoveAnim(void) } else if (m_fMoveSpeed == 0.0f && !curSprintAssoc) { if (!curIdleAssoc) { - if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, + if (m_fCurrentStamina < 0.0f && !bIsAimingGun && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, nil, true, false, false, false, false, false)) { curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f); @@ -329,11 +379,11 @@ CPlayerPed::SetRealMoveAnim(void) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000); } - if (m_fCurrentStamina > 0.0f && curIdleAssoc->animId == ANIM_STD_IDLE_TIRED) { + if ((m_fCurrentStamina > 0.0f || bIsAimingGun) && curIdleAssoc->animId == ANIM_STD_IDLE_TIRED) { CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f); } else if (m_nPedState != PED_FIGHT) { - if (m_fCurrentStamina < 0.0f && curIdleAssoc->animId != ANIM_STD_IDLE_TIRED + if (m_fCurrentStamina < 0.0f && !bIsAimingGun && curIdleAssoc->animId != ANIM_STD_IDLE_TIRED && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, nil, true, false, false, false, false, false)) { CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f); @@ -358,7 +408,10 @@ CPlayerPed::SetRealMoveAnim(void) delete curIdleAssoc; delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED); - delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE); + CAnimBlendAssociation *fightIdleAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE); + if (!fightIdleAnim) + fightIdleAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE); + delete fightIdleAnim; delete curSprintAssoc; curSprintAssoc = nil; @@ -403,7 +456,7 @@ CPlayerPed::SetRealMoveAnim(void) } else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) { if (m_fMoveSpeed < 0.4f) { AnimationId runStopAnim; - if (curSprintAssoc->currentTime / curSprintAssoc->hierarchy->totalLength < 0.5) // double + if (curSprintAssoc->GetProgress() < 0.5) // double runStopAnim = ANIM_STD_RUNSTOP1; else runStopAnim = ANIM_STD_RUNSTOP2; @@ -420,7 +473,7 @@ CPlayerPed::SetRealMoveAnim(void) curRunAssoc->blendAmount = 0.0f; curRunAssoc->blendDelta = 0.0f; - } else if (curSprintAssoc->blendDelta >= 0.0f) { + } else if (curSprintAssoc->blendDelta >= 0.0f) { // this condition is absent on mobile // Stop sprinting when tired curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT; curSprintAssoc->blendDelta = -1.0f; @@ -466,6 +519,8 @@ CPlayerPed::SetRealMoveAnim(void) curRunAssoc->blendAmount = 1.0f; m_nMoveState = PEDMOVE_RUN; } + curWalkAssoc->blendDelta = 0.0f; + curRunAssoc->blendDelta = 0.0f; } } } @@ -492,6 +547,11 @@ CPlayerPed::SetRealMoveAnim(void) if (curSprintAssoc) curSprintAssoc->speed = 2.0f; } + } else if (curSprintAssoc) { + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIXED) { + curSprintAssoc->speed = 0.7f; + } else + curSprintAssoc->speed = 1.0f; } } @@ -502,20 +562,57 @@ CPlayerPed::RestoreSprintEnergy(float restoreSpeed) m_fCurrentStamina += restoreSpeed * CTimer::GetTimeStep() * 0.5f; } -bool +float CPlayerPed::DoWeaponSmoothSpray(void) { if (m_nPedState == PED_ATTACK && !m_pPointGunAt) { - eWeaponType weapon = GetWeapon()->m_eWeaponType; + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + switch (GetWeapon()->m_eWeaponType) { + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_BASEBALLBAT: + if (GetFireAnimGround(weaponInfo, false) && RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(weaponInfo, false))) + return PI / 176.f; + else + return -1.0f; + + case WEAPONTYPE_CHAINSAW: + if (GetMeleeStartAnim(weaponInfo) && RpAnimBlendClumpGetAssociation(GetClump(), GetMeleeStartAnim(weaponInfo))) { #ifdef FREE_CAM - if(CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam() && (weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI)) - return false; + if (TheCamera.Cams[0].Using3rdPersonMouseCam()) return -1.0f; #endif - if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_SHOTGUN || - weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON) - return true; - } - return false; + return PI / 128.0f; + } + else if (GetFireAnimGround(weaponInfo, false) && RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(weaponInfo, false))) + return PI / 176.f; + else + return PI / 80.f; + + case WEAPONTYPE_PYTHON: + return PI / 112.f; + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + return PI / 112.f; + case WEAPONTYPE_UZI: + case WEAPONTYPE_MP5: + return PI / 112.f; + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + return PI / 112.f; + case WEAPONTYPE_FLAMETHROWER: + return PI / 80.f; + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: + return PI / 176.f; + default: + return -1.0f; + } + } else if (bIsDucking) + return PI / 112.f; + else + return -1.0f; } void @@ -533,14 +630,6 @@ CPlayerPed::DoesTargetHaveToBeBroken(CVector target, CWeapon *weaponUsed) if (distVec.Magnitude() > CWeaponInfo::GetWeaponInfo(weaponUsed->m_eWeaponType)->m_fRange) return true; - if (weaponUsed->m_eWeaponType != WEAPONTYPE_SHOTGUN && weaponUsed->m_eWeaponType != WEAPONTYPE_AK47) - return false; - - distVec.Normalise(); - - if (DotProduct(distVec,GetForward()) < 0.4f) - return true; - return false; } @@ -563,8 +652,11 @@ CPlayerPed::RunningLand(CPad *padUsed) } bool -CPlayerPed::IsThisPedAttackingPlayer(CPed *suspect) +CPlayerPed::IsThisPedAnAimingPriority(CPed *suspect) { + if (!suspect->bIsPlayerFriend) + return true; + if (suspect->m_pPointGunAt == this) return true; @@ -578,7 +670,7 @@ CPlayerPed::IsThisPedAttackingPlayer(CPed *suspect) default: break; } - return false; + return suspect->m_nPedState == PED_ABSEIL; } void @@ -587,86 +679,135 @@ CPlayerPed::PlayerControlSniper(CPad *padUsed) ProcessWeaponSwitch(padUsed); TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f; - if (!padUsed->GetTarget()) { + if (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) { + bCrouchWhenShooting = true; + SetDuck(60000, true); + } else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT)) { + ClearDuck(true); + bCrouchWhenShooting = false; + } + + if (!padUsed->GetTarget() && !m_attachedTo) { RestorePreviousState(); TheCamera.ClearPlayerWeaponMode(); + return; } - if (padUsed->WeaponJustDown()) { + int firingRate = GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE ? 333 : 266; + if (padUsed->WeaponJustDown() && CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer) { CVector firePos(0.0f, 0.0f, 0.6f); firePos = GetMatrix() * firePos; GetWeapon()->Fire(this, &firePos); + m_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds(); + } else if (CTimer::GetTimeInMilliseconds() > m_nPadDownPressedInMilliseconds + firingRate && + CTimer::GetTimeInMilliseconds() - CTimer::GetTimeStepInMilliseconds() < m_nPadDownPressedInMilliseconds + firingRate && padUsed->GetWeapon()) { + + if (GetWeapon()->m_nAmmoTotal > 0) { + DMAudio.PlayFrontEndSound(SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType); + } } - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); } // I think R* also used goto in here. void CPlayerPed::ProcessWeaponSwitch(CPad *padUsed) { - if (CDarkel::FrenzyOnGoing()) + if (CDarkel::FrenzyOnGoing() || m_attachedTo) goto switchDetectDone; -#ifdef VC_PED_PORTS - if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt && !bDontAllowWeaponChange) { -#else - if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt) { -#endif + if (!m_pPointGunAt && !bDontAllowWeaponChange && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR) { + if (padUsed->CycleWeaponRightJustDown()) { - if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT) { + if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) { - for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; ++m_nSelectedWepSlot) { - if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) { - goto switchDetectDone; + for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < TOTAL_WEAPON_SLOTS; ++m_nSelectedWepSlot) { + if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) { +#ifdef FIX_BUGS + goto switchDetectDone; +#else + goto spentAmmoCheck; +#endif + } } + m_nSelectedWepSlot = 0; +#ifdef FIX_BUGS + goto switchDetectDone; +#endif } - m_nSelectedWepSlot = WEAPONTYPE_UNARMED; - } -#ifdef VC_PED_PORTS - } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt && !bDontAllowWeaponChange) { -#else - } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt) { + } else if (padUsed->CycleWeaponLeftJustDown()) { + if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) { + + // I don't know what kind of loop that was + m_nSelectedWepSlot = m_currentWeapon - 1; + do { + if (m_nSelectedWepSlot < 0) + m_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1; + + if (m_nSelectedWepSlot == WEAPONSLOT_UNARMED) + break; + + if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) + break; + + --m_nSelectedWepSlot; + } while (m_nSelectedWepSlot != WEAPONSLOT_UNARMED); +#ifdef FIX_BUGS + goto switchDetectDone; #endif - if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) { - - for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) { - if (m_nSelectedWepSlot < WEAPONTYPE_UNARMED) - m_nSelectedWepSlot = WEAPONTYPE_DETONATOR; - if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) { - goto switchDetectDone; - } } } - // Out of ammo, switch to another weapon - } else if (CWeaponInfo::GetWeaponInfo((eWeaponType)m_currentWeapon)->m_eWeaponFire != WEAPON_FIRE_MELEE) { - if (GetWeapon(m_currentWeapon).m_nAmmoTotal <= 0) { + } + +spentAmmoCheck: + if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_eWeaponFire != WEAPON_FIRE_MELEE + && (!padUsed->GetWeapon() || GetWeapon()->m_eWeaponType != WEAPONTYPE_MINIGUN)) { + if (GetWeapon()->m_nAmmoTotal <= 0) { if (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER) return; - for (m_nSelectedWepSlot = m_currentWeapon - 1; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) { - if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && HasWeapon(WEAPONTYPE_BASEBALLBAT) - || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR + && GetWeapon(WEAPONSLOT_PROJECTILE).m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) + m_nSelectedWepSlot = WEAPONSLOT_PROJECTILE; + else + m_nSelectedWepSlot = m_currentWeapon - 1; + + for (; m_nSelectedWepSlot >= WEAPONSLOT_UNARMED; --m_nSelectedWepSlot) { + + // BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez +#ifdef FIX_BUGS + if (m_nSelectedWepSlot == WEAPONSLOT_MELEE || + GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && (m_nSelectedWepSlot != WEAPONSLOT_PROJECTILE || GetWeapon(WEAPONSLOT_PROJECTILE).m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE)) { +#else + if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT + || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 + && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE && m_nSelectedWepSlot != WEAPONTYPE_TEARGAS) { +#endif goto switchDetectDone; } } - m_nSelectedWepSlot = WEAPONTYPE_UNARMED; + m_nSelectedWepSlot = WEAPONSLOT_UNARMED; } } switchDetectDone: if (m_nSelectedWepSlot != m_currentWeapon) { - if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT) + if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT) { + RemoveWeaponAnims(m_currentWeapon, -1000.0f); MakeChangesForNewWeapon(m_nSelectedWepSlot); + } } } @@ -676,17 +817,34 @@ CPlayerPed::PlayerControlM16(CPad *padUsed) ProcessWeaponSwitch(padUsed); TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f; - if (!padUsed->GetTarget()) { + if (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) { + bCrouchWhenShooting = true; + SetDuck(60000, true); + } else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT)) { + ClearDuck(true); + bCrouchWhenShooting = false; + } + + if (!padUsed->GetTarget() && !m_attachedTo) { RestorePreviousState(); TheCamera.ClearPlayerWeaponMode(); } - if (padUsed->GetWeapon()) { - CVector firePos(0.0f, 0.0f, 0.6f); - firePos = GetMatrix() * firePos; - GetWeapon()->Fire(this, &firePos); + if (padUsed->GetWeapon() && CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer) { + if (GetWeapon()->m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO) { + DMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0.f); + GetWeapon()->m_nTimer = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nFiringRate + CTimer::GetTimeInMilliseconds(); + } else { + CVector firePos(0.0f, 0.0f, 0.6f); + firePos = GetMatrix() * firePos; + GetWeapon()->Fire(this, &firePos); + m_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds(); + } + } else if (CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer && + CTimer::GetTimeInMilliseconds() - CTimer::GetTimeStepInMilliseconds() < GetWeapon()->m_nTimer && GetWeapon()->m_eWeaponState != WEAPONSTATE_OUT_OF_AMMO) { + DMAudio.PlayFrontEndSound(SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType); } - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); } void @@ -741,14 +899,21 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) m_fMoveSpeed = 0.0f; } } + + if (m_nPedState == PED_ANSWER_MOBILE) { + SetRealMoveAnim(); + return; + } + if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->GetSprint()) { m_nMoveState = PEDMOVE_SPRINT; } if (m_nPedState != PED_FIGHT) SetRealMoveAnim(); - if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY)) - && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) { + if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY)) && + padUsed->JumpJustDown() && m_nPedState != PED_JUMP) { + ClearAttack(); ClearWeaponTarget(); if (m_nEvadeAmount != 0 && m_pEvadingFrom) { @@ -759,6 +924,12 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) SetJump(); } } + + // FIX: Fact that PlayIdleAnimations only called through PlayerControlZelda was making it visible to only Classic control players. This isn't fair! +#ifdef FIX_BUGS + if (m_nPedState != PED_FIGHT) + PlayIdleAnimations(padUsed); +#endif } void @@ -767,7 +938,7 @@ CPlayerPed::KeepAreaAroundPlayerClear(void) BuildPedLists(); for (int i = 0; i < m_numNearPeds; ++i) { CPed *nearPed = m_nearPeds[i]; - if (nearPed->CharCreatedBy == RANDOM_CHAR && !nearPed->DyingOrDead()) { + if (nearPed->CharCreatedBy == RANDOM_CHAR && nearPed->m_nPedState != PED_DRIVING && !nearPed->DyingOrDead()) { if (nearPed->GetIsOnScreen()) { if (nearPed->m_objective == OBJECTIVE_NONE) { nearPed->SetFindPathAndFlee(this, 5000, true); @@ -811,17 +982,15 @@ CPlayerPed::KeepAreaAroundPlayerClear(void) } void -CPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft) +CPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft, bool priority) { + // priority param is unused CVector distVec = candidate->GetPosition() - GetPosition(); if (distVec.Magnitude2D() <= distLimit) { if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) { -#ifdef VC_PED_PORTS float angleBetweenUs = CGeneral::GetATanOfXY(candidate->GetPosition().x - TheCamera.GetPosition().x, - candidate->GetPosition().y - TheCamera.GetPosition().y); -#else - float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y); -#endif + candidate->GetPosition().y - TheCamera.GetPosition().y); + angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset); float closeness; if (lookToLeft) { @@ -850,7 +1019,7 @@ CPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastC float closeness = -dist - 5.0f * Abs(angleBetweenUs); if (priority) { - closeness += 5.0f; + closeness += 30.0f; } if (closeness > *lastCloseness) { @@ -862,6 +1031,37 @@ CPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastC } bool +CPlayerPed::CanIKReachThisTarget(CVector target, CWeapon* weapon, bool zRotImportant) +{ + float angleToFace = CGeneral::GetRadianAngleBetweenPoints(target.x, target.y, GetPosition().x, GetPosition().y); + float angleDiff = CGeneral::LimitRadianAngle(angleToFace - m_fRotationCur); + + return (!zRotImportant || CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) || Abs(angleDiff) <= HALFPI) && + (CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) || Abs(target.z - GetPosition().z) <= (target - GetPosition()).Magnitude2D()); +} + +void +CPlayerPed::RotatePlayerToTrackTarget(void) +{ + if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) + return; + + float angleToFace = CGeneral::GetRadianAngleBetweenPoints( + m_pPointGunAt->GetPosition().x, m_pPointGunAt->GetPosition().y, + GetPosition().x, GetPosition().y); + + float angleDiff = CGeneral::LimitRadianAngle(m_fRotationCur - angleToFace); + if (angleDiff < -DEGTORAD(25.0f)) { + m_fRotationCur -= angleDiff + DEGTORAD(25.0f); + m_fRotationDest -= angleDiff + DEGTORAD(25.0f); + + } else if (angleDiff > DEGTORAD(25.0f)) { + m_fRotationCur -= angleDiff - DEGTORAD(25.0f); + m_fRotationDest -= angleDiff - DEGTORAD(25.0f); + } +} + +bool CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft) { CEntity *nextTarget = nil; @@ -869,38 +1069,36 @@ CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft) // nextTarget = nil; // duplicate float lastCloseness = -10000.0f; // CGeneral::GetATanOfXY(GetForward().x, GetForward().y); // unused -#ifdef VC_PED_PORTS CVector distVec = previousTarget->GetPosition() - TheCamera.GetPosition(); -#else - CVector distVec = previousTarget->GetPosition() - GetPosition(); -#endif float referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y); for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) { CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h); if (pedToCheck) { - if (pedToCheck != FindPlayerPed() && pedToCheck != previousTarget) { - if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle - && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) { + if (pedToCheck != this && pedToCheck != previousTarget) { + if (!pedToCheck->DyingOrDead() +#ifndef AIMING_VEHICLE_OCCUPANTS // Mobile thing + && (!pedToCheck->bInVehicle || (pedToCheck->m_pMyVehicle && pedToCheck->m_pMyVehicle->IsBike())) +#endif + && pedToCheck->m_leader != this && !pedToCheck->bNeverEverTargetThisPed + && OurPedCanSeeThisOne(pedToCheck, true) && CanIKReachThisTarget(pedToCheck->GetPosition(), GetWeapon(), true)) { EvaluateNeighbouringTarget(pedToCheck, &nextTarget, &lastCloseness, - weaponRange, referenceBeta, lookToLeft); + weaponRange, referenceBeta, lookToLeft, IsThisPedAnAimingPriority(pedToCheck)); } } } } for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) { CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]); - if (obj) - EvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft); + if (obj && !obj->bHasBeenDamaged && CanIKReachThisTarget(obj->GetPosition(), GetWeapon(), true)) + EvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft, true); } if (!nextTarget) return false; SetWeaponLockOnTarget(nextTarget); -#ifdef VC_PED_PORTS bDontAllowWeaponChange = true; -#endif SetPointGunAt(nextTarget); return true; } @@ -927,29 +1125,32 @@ CPlayerPed::FindWeaponLockOnTarget(void) for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) { CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h); if (pedToCheck) { - if (pedToCheck != FindPlayerPed()) { - if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle - && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) { + if (pedToCheck != this) { + if (!pedToCheck->DyingOrDead() +#ifndef AIMING_VEHICLE_OCCUPANTS // Mobile thing + && (!pedToCheck->bInVehicle || (pedToCheck->m_pMyVehicle && pedToCheck->m_pMyVehicle->IsBike())) +#endif + && pedToCheck->m_leader != this && !pedToCheck->bNeverEverTargetThisPed + && OurPedCanSeeThisOne(pedToCheck) && CanIKReachThisTarget(pedToCheck->GetPosition(), GetWeapon(), true)) { EvaluateTarget(pedToCheck, &nextTarget, &lastCloseness, - weaponRange, referenceBeta, IsThisPedAttackingPlayer(pedToCheck)); + weaponRange, referenceBeta, IsThisPedAnAimingPriority(pedToCheck)); } } } } for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) { CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]); - if (obj) - EvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, false); + if (obj && !obj->bHasBeenDamaged && CanIKReachThisTarget(obj->GetPosition(), GetWeapon(), true)) + EvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, true); } if (!nextTarget) return false; SetWeaponLockOnTarget(nextTarget); -#ifdef VC_PED_PORTS bDontAllowWeaponChange = true; -#endif SetPointGunAt(nextTarget); + Say(SOUND_PED_AIMING); return true; } @@ -957,7 +1158,6 @@ void CPlayerPed::ProcessAnimGroups(void) { AssocGroupId groupToSet; - #ifdef PC_PLAYER_CONTROLS if ((m_fWalkAngle <= -DEGTORAD(50.0f) || m_fWalkAngle >= DEGTORAD(50.0f)) && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() @@ -967,17 +1167,29 @@ CPlayerPed::ProcessAnimGroups(void) if (m_fWalkAngle > 0.0f) { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETLEFT; + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + groupToSet = ASSOCGRP_CHAINSAWLEFT; else groupToSet = ASSOCGRP_PLAYERLEFT; } else { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETRIGHT; + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + groupToSet = ASSOCGRP_CHAINSAWRIGHT; else groupToSet = ASSOCGRP_PLAYERRIGHT; } } else { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETBACK; + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + groupToSet = ASSOCGRP_CHAINSAWBACK; else groupToSet = ASSOCGRP_PLAYERBACK; } @@ -987,9 +1199,19 @@ CPlayerPed::ProcessAnimGroups(void) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) { groupToSet = ASSOCGRP_PLAYERROCKET; } else { - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT + || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE) groupToSet = ASSOCGRP_PLAYERBBBAT; - } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) { + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + groupToSet = ASSOCGRP_PLAYERCHAINSAW; + else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI + // I hope this is an inlined function... + && GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9 + && GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5 + && GetWeapon()->m_eWeaponType != WEAPONTYPE_GOLFCLUB && GetWeapon()->m_eWeaponType != WEAPONTYPE_KATANA + && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA) { if (!GetWeapon()->IsType2Handed()) { groupToSet = ASSOCGRP_PLAYER; } else { @@ -1016,44 +1238,76 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) CWeaponEffects::ClearCrossHair(); ClearPointGunAt(); } + + if (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) { +#ifdef FIX_BUGS + // fix tommy being locked into looking at the same spot if you duck just after starting to shoot + if(!m_pPointGunAt) + ClearPointGunAt(); +#endif + bCrouchWhenShooting = true; + SetDuck(60000, true); + } else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT || + padUsed->GetSprint() || padUsed->JumpJustDown() || padUsed->ExitVehicleJustDown())) { + +#ifdef FIX_BUGS + // same fix as above except for standing up + if(!m_pPointGunAt) + ClearPointGunAt(); +#endif + ClearDuck(true); + bCrouchWhenShooting = false; + } + + if(weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM)) + m_wepAccuracy = 95; + else + m_wepAccuracy = 100; + if (!m_pFire) { - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || - GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { - if (padUsed->TargetJustDown()) { - SetStoredState(); - SetPedState(PED_SNIPER_MODE); + eWeaponType weapon = GetWeapon()->m_eWeaponType; + if (weapon == WEAPONTYPE_ROCKETLAUNCHER || weapon == WEAPONTYPE_SNIPERRIFLE || + weapon == WEAPONTYPE_LASERSCOPE || weapon == WEAPONTYPE_M4 || + weapon == WEAPONTYPE_RUGER || weapon == WEAPONTYPE_M60 || + weapon == WEAPONTYPE_CAMERA) { + + if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) { #ifdef FREE_CAM if (CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) { m_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation); SetHeading(m_fRotationCur); } #endif - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) + if (weapon == WEAPONTYPE_ROCKETLAUNCHER) TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0); - else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE) + else if (weapon == WEAPONTYPE_SNIPERRIFLE || weapon == WEAPONTYPE_LASERSCOPE) TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SNIPER, 0, 0); + else if (weapon == WEAPONTYPE_CAMERA) + TheCamera.SetNewPlayerWeaponMode(CCam::MODE_CAMERA, 0, 0); else TheCamera.SetNewPlayerWeaponMode(CCam::MODE_M16_1STPERSON, 0, 0); m_fMoveSpeed = 0.0f; CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE, 1000.0f); - } - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE - || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) + SetPedState(PED_SNIPER_MODE); return; + } + if (!TheCamera.Using1stPersonWeaponMode()) + if (weapon == WEAPONTYPE_ROCKETLAUNCHER || weapon == WEAPONTYPE_SNIPERRIFLE || weapon == WEAPONTYPE_LASERSCOPE || weapon == WEAPONTYPE_CAMERA) + return; } } if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) { if (m_nSelectedWepSlot == m_currentWeapon) { if (m_pPointGunAt) { -#ifdef FREE_CAM - if (CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE && m_fMoveSpeed < 1.0f) - StartFightAttack(padUsed->GetWeapon()); - else -#endif - SetAttack(m_pPointGunAt); - } else if (m_currentWeapon != WEAPONTYPE_UNARMED) { + if (m_nPedState == PED_ATTACK) { + m_fAttackButtonCounter *= Pow(0.94f, CTimer::GetTimeStep()); + } else { + m_fAttackButtonCounter = 0.0f; + } + SetAttack(m_pPointGunAt); + } else { if (m_nPedState == PED_ATTACK) { if (padUsed->WeaponJustDown()) { m_bHaveTargetSelected = true; @@ -1064,12 +1318,19 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; } - SetAttack(nil); - } else if (padUsed->WeaponJustDown()) { - if (m_fMoveSpeed < 1.0f) - StartFightAttack(padUsed->GetWeapon()); - else - SetAttack(nil); + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && + !weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE)) { + + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE || + padUsed->WeaponJustDown()) + SetAttack(nil); + + } else if (padUsed->WeaponJustDown()) { + if (m_fMoveSpeed < 1.0f || m_nPedState == PED_FIGHT) + StartFightAttack(padUsed->GetWeapon()); + else + SetAttack(nil); + } } } } else { @@ -1090,24 +1351,23 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) if (CCamera::m_bUseMouse3rdPerson && CCamera::bFreeCam && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) { +#define CAN_AIM_WITH_ARM (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) && !bIsDucking && !bCrouchWhenShooting) // Weapons except throwable and melee ones - if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM) || weaponInfo->IsFlagSet(WEAPONFLAG_1ST_PERSON) || weaponInfo->IsFlagSet(WEAPONFLAG_EXPANDS)) { - if ((padUsed->GetTarget() && weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) || padUsed->GetWeapon()) { + if (weaponInfo->m_nWeaponSlot > 2) { + if ((padUsed->GetTarget() && CAN_AIM_WITH_ARM) || padUsed->GetWeapon()) { float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation); m_cachedCamSource = TheCamera.Cams[TheCamera.ActiveCam].Source; m_cachedCamFront = TheCamera.Cams[TheCamera.ActiveCam].Front; m_cachedCamUp = TheCamera.Cams[TheCamera.ActiveCam].Up; - + // On this one we can rotate arm. - if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) { + if (CAN_AIM_WITH_ARM) { pointedGun = 2; m_bFreeAimActive = true; - SetLookFlag(limitedCam, true); + SetLookFlag(limitedCam, true, true); SetAimFlag(limitedCam); -#ifdef VC_PED_PORTS - SetLookTimer(INT32_MAX); // removing this makes head move for real, but I experinced some bugs. -#endif + SetLookTimer(INT32_MAX); ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN) { // This is a seperate ped state just for pointing gun. Used for target button @@ -1134,6 +1394,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } } } +#undef CAN_AIM_WITH_ARM } if (changedHeadingRate == 1) { changedHeadingRate = 0; @@ -1155,7 +1416,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } #endif - if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) { + if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT && !TheCamera.Using1stPersonWeaponMode() && weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM)) { if (m_pPointGunAt) { // what?? if (!m_pPointGunAt @@ -1163,15 +1424,30 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) || (!CCamera::bFreeCam && CCamera::m_bUseMouse3rdPerson) #else || CCamera::m_bUseMouse3rdPerson +#endif + ) { + ClearWeaponTarget(); + return; + } + + if (m_pPointGunAt->IsPed() && ( +#ifndef AIMING_VEHICLE_OCCUPANTS + (((CPed*)m_pPointGunAt)->bInVehicle && (!((CPed*)m_pPointGunAt)->m_pMyVehicle || !((CPed*)m_pPointGunAt)->m_pMyVehicle->IsBike())) || #endif - || m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) { + !CGame::nastyGame && ((CPed*)m_pPointGunAt)->DyingOrDead())) { ClearWeaponTarget(); return; } - if (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon())) { + if (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon()) || + (!bCanPointGunAtTarget && !weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))) { // this line isn't on Mobile, idk why ClearWeaponTarget(); return; } + + if (m_pPointGunAt) { + RotatePlayerToTrackTarget(); + } + if (m_pPointGunAt) { if (padUsed->ShiftTargetLeftJustDown()) FindNextWeaponLockOnTarget(m_pPointGunAt, true); @@ -1180,13 +1456,9 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0); TheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition()); - } -#ifdef FREE_CAM - else if ((CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE) || (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM) && !CCamera::m_bUseMouse3rdPerson)) { -#else - else if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM) && !CCamera::m_bUseMouse3rdPerson) { -#endif - if (padUsed->TargetJustDown()) + + } else if (!CCamera::m_bUseMouse3rdPerson) { + if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) FindWeaponLockOnTarget(); } } else if (m_pPointGunAt) { @@ -1194,16 +1466,12 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } if (m_pPointGunAt) { -#ifndef VC_PED_PORTS - CVector markPos = m_pPointGunAt->GetPosition(); -#else CVector markPos; if (m_pPointGunAt->IsPed()) { ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition(markPos, PED_MID); } else { markPos = m_pPointGunAt->GetPosition(); } -#endif if (bCanPointGunAtTarget) { CWeaponEffects::MarkTarget(markPos, 64, 0, 0, 255, 0.8f); } else { @@ -1213,17 +1481,28 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) m_bHasLockOnTarget = m_pPointGunAt != nil; } +bool +CPlayerPed::MovementDisabledBecauseOfTargeting(void) +{ + return m_pPointGunAt && !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM); +} + void CPlayerPed::PlayerControlZelda(CPad *padUsed) { - bool doSmoothSpray = DoWeaponSmoothSpray(); + float smoothSprayRate = DoWeaponSmoothSpray(); float camOrientation = TheCamera.Orientation; float leftRight = padUsed->GetPedWalkLeftRight(); float upDown = padUsed->GetPedWalkUpDown(); float padMoveInGameUnit; bool smoothSprayWithoutMove = false; - if (doSmoothSpray && upDown > 0.0f) { + if (MovementDisabledBecauseOfTargeting()) { + upDown = 0.0f; + leftRight = 0.0f; + } + + if (smoothSprayRate > 0.0f && upDown > 0.0f) { padMoveInGameUnit = 0.0f; smoothSprayWithoutMove = true; } else { @@ -1231,7 +1510,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) } #ifdef FREE_CAM - if(CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam() && doSmoothSpray) { + if (TheCamera.Cams[0].Using3rdPersonMouseCam() && smoothSprayRate > 0.0f) { padMoveInGameUnit = 0.0f; smoothSprayWithoutMove = false; } @@ -1240,12 +1519,8 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) if (padMoveInGameUnit > 0.0f || smoothSprayWithoutMove) { float padHeading = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); float neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation); - if (doSmoothSpray) { - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45 - || GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) - m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 80.0f) * CTimer::GetTimeStep(); - else - m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 128.0f) * CTimer::GetTimeStep(); + if (smoothSprayRate > 0.0f) { + m_fRotationDest = m_fRotationCur - leftRight / 128.0f * smoothSprayRate * CTimer::GetTimeStep(); } else { m_fRotationDest = neededTurn; } @@ -1271,13 +1546,20 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) } } + if (m_nPedState == PED_ANSWER_MOBILE) { + SetRealMoveAnim(); + return; + } + if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->GetSprint()) { - m_nMoveState = PEDMOVE_SPRINT; + if (!m_pCurrentPhysSurface || (!m_pCurrentPhysSurface->bInfiniteMass || m_pCurrentPhysSurface->m_phy_flagA08)) + m_nMoveState = PEDMOVE_SPRINT; } + if (m_nPedState != PED_FIGHT) SetRealMoveAnim(); - if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY)) + if (!bIsInTheAir && !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) { ClearAttack(); ClearWeaponTarget(); @@ -1289,34 +1571,168 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) SetJump(); } } + PlayIdleAnimations(padUsed); +} + +// Finds nice positions for peds to duck and shoot player. And it's inside PlayerPed, this is treachery! +void +CPlayerPed::FindNewAttackPoints(void) +{ + for (int i=0; i<ARRAY_SIZE(m_pPedAtSafePos); i++) { + CPed *safeNeighbour = m_pPedAtSafePos[i]; + if (safeNeighbour) { + if (safeNeighbour->m_nPedState == PED_DEAD || safeNeighbour->m_pedInObjective != this) { + m_vecSafePos[i].x = 0.0f; + m_vecSafePos[i].y = 0.0f; + m_vecSafePos[i].z = 0.0f; + m_pPedAtSafePos[i] = nil; + } + } else { + m_vecSafePos[i].x = 0.0f; + m_vecSafePos[i].y = 0.0f; + m_vecSafePos[i].z = 0.0f; + } + } + CEntity *entities[6]; + int16 numEnts; + float rightMult, fwdMult; + CWorld::FindObjectsInRange(GetPosition(), 18.0f, true, &numEnts, 6, entities, true, false, false, true, false); + for (int i = 0; i < numEnts; ++i) { + CEntity *ent = entities[i]; + int16 mi = ent->GetModelIndex(); + if (!ent->IsObject() || ((CObject*)ent)->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART) + if (!IsTreeModel(mi)) + continue; + + if (mi == MI_TRAFFICLIGHTS) { + rightMult = 2.957f; + fwdMult = 0.147f; + + } else if (mi == MI_SINGLESTREETLIGHTS1) { + rightMult = 0.744f; + fwdMult = 0.0f; + + } else if (mi == MI_SINGLESTREETLIGHTS2) { + rightMult = 0.043f; + fwdMult = 0.0f; + + } else if (mi == MI_SINGLESTREETLIGHTS3) { + rightMult = 1.143f; + fwdMult = 0.145f; + + } else if (mi == MI_DOUBLESTREETLIGHTS) { + rightMult = 0.744f; + fwdMult = 0.0f; + + } else if (mi == MI_LAMPPOST1) { + rightMult = 0.744f; + fwdMult = 0.0f; + + } else if (mi == MI_TRAFFICLIGHT01) { + rightMult = 2.957f; + fwdMult = 0.147f; + + } else if (mi == MI_LITTLEHA_POLICE) { + rightMult = 0.0f; + fwdMult = 0.0f; + + } else if (mi == MI_PARKBENCH) { + rightMult = 0.0f; + fwdMult = 0.0f; + + } else if (IsTreeModel(mi)) { + rightMult = 0.0f; + fwdMult = 0.0f; + } else + continue; + + CVector entAttackPoint(rightMult * ent->GetRight().x + fwdMult * ent->GetForward().x + ent->GetPosition().x, + rightMult * ent->GetRight().y + fwdMult * ent->GetForward().y + ent->GetPosition().y, + ent->GetPosition().z); + CVector attackerPos = GetPosition() - entAttackPoint; // for now it's dist, not attackerPos + CVector dirTowardsUs = attackerPos; + dirTowardsUs.Normalise(); + dirTowardsUs *= 2.0f; + attackerPos = entAttackPoint - dirTowardsUs; // to make cop farther from us + CPedPlacement::FindZCoorForPed(&attackerPos); + if (CPedPlacement::IsPositionClearForPed(attackerPos)) + m_vecSafePos[i] = attackerPos; + } } void CPlayerPed::ProcessControl(void) { + // Mobile has some debug/abandoned cheat thing in here: "gbFrankenTommy" + if (m_nEvadeAmount != 0) --m_nEvadeAmount; if (m_nEvadeAmount == 0) m_pEvadingFrom = nil; + if (m_pWanted->GetWantedLevel() > 0) + FindNewAttackPoints(); + + UpdateMeleeAttackers(); + if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) { bTryingToReachDryLand = true; + } else if (!(((uint8)CTimer::GetFrameCounter() + m_randomSeed) & 0xF)) { - CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(GetPosition(), 7.0f, nil, - false, true, false, false, false, false); + CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(GetPosition(), 7.0f, nil, false, true, false, false, false, false); if (nearVeh && nearVeh->IsBoat()) bTryingToReachDryLand = true; else bTryingToReachDryLand = false; } + + if (m_nFadeDrunkenness) { + if (m_nDrunkenness - 1 > 0) { + --m_nDrunkenness; + } else { + m_nDrunkenness = 0; + CMBlur::ClearDrunkBlur(); + m_nFadeDrunkenness = 0; + } + } + if (m_nDrunkenness != 0) { + CMBlur::SetDrunkBlur(m_nDrunkenness / 255.f); + } CPed::ProcessControl(); + SetNearbyPedsToInteractWithPlayer(); if (bWasPostponed) return; - CPad *padUsed = CPad::GetPad(0); + CPad *padUsed = GetPadFromPlayer(this); m_pWanted->Update(); - CEntity::PruneReferences(); + PruneReferences(); + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) { + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + CAnimBlendAssociation *fireAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weaponInfo)); + if (fireAnim && fireAnim->currentTime - fireAnim->timeStep < weaponInfo->m_fAnimLoopEnd && m_nPedState == PED_ATTACK) { + if (m_fGunSpinSpeed < 0.45f) { + m_fGunSpinSpeed = Min(0.45f, m_fGunSpinSpeed + CTimer::GetTimeStep() * 0.013f); + } + + if (padUsed->GetWeapon() && GetWeapon()->m_nAmmoTotal > 0 && fireAnim->currentTime >= weaponInfo->m_fAnimLoopStart) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_ATTACK, 0.0f); + } else { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_2, m_fGunSpinSpeed * (20.f / 9)); + } + } else { + if (m_fGunSpinSpeed > 0.0f) { + if (m_fGunSpinSpeed >= 0.45f) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_3, 0.0f); + } + m_fGunSpinSpeed = Max(0.0f, m_fGunSpinSpeed - CTimer::GetTimeStep() * 0.003f); + } + } + } + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW && m_nPedState != PED_ATTACK && !bInVehicle) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_IDLE, 0.0f); + } if (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT) RestoreSprintEnergy(1.0f); @@ -1334,27 +1750,29 @@ CPlayerPed::ProcessControl(void) return; } if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_CAR) { - if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) { - CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS); - - if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || (rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS))) { - if (rollDoorAssoc) - m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, rollDoorAssoc->currentTime); + if (!CReplay::IsPlayingBack() || m_pMyVehicle) { + if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) { + CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS); - } else { - // These comparisons are wrong, they return uint16 - if (padUsed && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f || padUsed->GetBrake() != 0.0f)) { + if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || (rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS))) { if (rollDoorAssoc) m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, rollDoorAssoc->currentTime); } else { - m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; - if (m_pMyVehicle->bLowVehicle) - rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS); - else - rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS); + // These comparisons are wrong, they return uint16 + if (padUsed && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f || padUsed->GetBrake() != 0.0f)) { + if (rollDoorAssoc) + m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, rollDoorAssoc->currentTime); + + } else { + m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; + if (m_pMyVehicle->bLowVehicle) + rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS); + else + rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS); - rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this); + rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this); + } } } } @@ -1364,11 +1782,11 @@ CPlayerPed::ProcessControl(void) m_nMoveState = PEDMOVE_STILL; if (bIsLanding) RunningLand(padUsed); - if (padUsed && padUsed->WeaponJustDown() && m_nPedState != PED_SNIPER_MODE) { + if (padUsed && padUsed->WeaponJustDown() && !TheCamera.Using1stPersonWeaponMode()) { // ...Really? eWeaponType playerWeapon = FindPlayerPed()->GetWeapon()->m_eWeaponType; - if (playerWeapon == WEAPONTYPE_SNIPERRIFLE) { + if (playerWeapon == WEAPONTYPE_SNIPERRIFLE || playerWeapon == WEAPONTYPE_LASERSCOPE) { DMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0); } else if (playerWeapon == WEAPONTYPE_ROCKETLAUNCHER) { DMAudio.PlayFrontEndSound(SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM, 0); @@ -1383,8 +1801,13 @@ CPlayerPed::ProcessControl(void) case PED_ATTACK: case PED_FIGHT: case PED_AIM_GUN: - if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK)) { - if (TheCamera.Cams[0].Using3rdPersonMouseCam() + case PED_ANSWER_MOBILE: + if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK) && !m_attachedTo) { + if (TheCamera.Using1stPersonWeaponMode()) { + if (padUsed) + PlayerControlSniper(padUsed); + + } else if (TheCamera.Cams[0].Using3rdPersonMouseCam() #ifdef FREE_CAM && !CCamera::bFreeCam #endif @@ -1400,7 +1823,7 @@ CPlayerPed::ProcessControl(void) PlayerControlZelda(padUsed); } } - if (IsPedInControl() && padUsed) + if (IsPedInControl() && m_nPedState != PED_ANSWER_MOBILE && padUsed) ProcessPlayerWeapon(padUsed); break; case PED_SEEK_ENTITY: @@ -1429,12 +1852,12 @@ CPlayerPed::ProcessControl(void) } break; case PED_SNIPER_MODE: - if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE) { if (padUsed) - PlayerControlM16(padUsed); + PlayerControlSniper(padUsed); } else if (padUsed) { - PlayerControlSniper(padUsed); + PlayerControlM16(padUsed); } break; case PED_SEEK_CAR: @@ -1485,9 +1908,9 @@ CPlayerPed::ProcessControl(void) default: break; } - if (padUsed && IsPedShootable()) { + if (padUsed && IsPedShootable() && m_nPedState != PED_ANSWER_MOBILE && m_nLastPedState != PED_ANSWER_MOBILE) { ProcessWeaponSwitch(padUsed); - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, this); } ProcessAnimGroups(); if (padUsed) { @@ -1497,12 +1920,13 @@ CPlayerPed::ProcessControl(void) m_lookTimer = 0; float camAngle = CGeneral::LimitRadianAngle(TheCamera.Cams[TheCamera.ActiveCam].Front.Heading()); float angleBetweenPlayerAndCam = Abs(camAngle - m_fRotationCur); - if (m_nPedState != PED_ATTACK && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) { + if (m_nPedState != PED_ATTACK && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) { if (angleBetweenPlayerAndCam > DEGTORAD(150.0f) && angleBetweenPlayerAndCam < DEGTORAD(210.0f)) { float rightTurnAngle = CGeneral::LimitRadianAngle(m_fRotationCur - DEGTORAD(150.0f)); float leftTurnAngle = CGeneral::LimitRadianAngle(DEGTORAD(150.0f) + m_fRotationCur); - if (m_fLookDirection == 999999.0f) + + if (m_fLookDirection == 999999.0f || bIsDucking) camAngle = rightTurnAngle; else if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection)) camAngle = rightTurnAngle; @@ -1533,17 +1957,279 @@ CPlayerPed::ProcessControl(void) m_bSpeedTimerFlag = false; } -#ifdef VC_PED_PORTS if (bDontAllowWeaponChange && FindPlayerPed() == this) { if (!CPad::GetPad(0)->GetTarget()) bDontAllowWeaponChange = false; } -#endif -#ifdef PED_SKIN - if (!bIsVisible && IsClumpSkinned(GetClump())) + if (m_nPedState != PED_SNIPER_MODE && (GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING || m_nPedState == PED_ATTACK)) + m_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds(); + + if (!bIsVisible) UpdateRpHAnim(); +} + +bool +CPlayerPed::DoesPlayerWantNewWeapon(eWeaponType weapon, bool onlyIfSlotIsEmpty) +{ + // GetPadFromPlayer(); // unused + uint32 slot = CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot; + + if (!HasWeaponSlot(slot) || GetWeapon(slot).m_eWeaponType == weapon) + return true; + + if (onlyIfSlotIsEmpty) + return false; + + // Check if he's using that slot right now. + return m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN || slot != m_currentWeapon; +} + +void +CPlayerPed::PlayIdleAnimations(CPad *padUsed) +{ + CAnimBlendAssociation* assoc; + + if (TheCamera.m_WideScreenOn || bIsDucking) + return; + + struct animAndGroup { + AnimationId animId; + AssocGroupId groupId; + }; + + const animAndGroup idleAnims[] = { + {ANIM_PLAYER_IDLE1, ASSOCGRP_PLAYER_IDLE}, + {ANIM_PLAYER_IDLE2, ASSOCGRP_PLAYER_IDLE}, + {ANIM_PLAYER_IDLE3, ASSOCGRP_PLAYER_IDLE}, + {ANIM_PLAYER_IDLE4, ASSOCGRP_PLAYER_IDLE}, + {ANIM_STD_XPRESS_SCRATCH, ASSOCGRP_STD}, + }; + + static int32 lastTime = 0; + static int32 lastAnim = -1; + + bool hasIdleAnim = false; + CAnimBlock *idleAnimBlock = CAnimManager::GetAnimationBlock(idleAnimBlockIndex); + uint32 sinceLastInput = padUsed->InputHowLongAgo(); + if (sinceLastInput <= 30000) { + if (idleAnimBlock->isLoaded) { + for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + if (assoc->flags & ASSOC_IDLE) { + hasIdleAnim = true; + assoc->blendDelta = -8.0f; + } + } + if (!hasIdleAnim) + CStreaming::RemoveAnim(idleAnimBlockIndex); + } else { + lastTime = 0; + } + } else { + CStreaming::RequestAnim(idleAnimBlockIndex, STREAMFLAGS_DONT_REMOVE); + if (idleAnimBlock->isLoaded) { + for(CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + int firstIdle = idleAnimBlock->firstIndex; + int index = assoc->hierarchy - CAnimManager::GetAnimation(0); + if (index >= firstIdle && index < firstIdle + idleAnimBlock->numAnims) { + hasIdleAnim = true; + break; + } + } + + if (!hasIdleAnim && !bIsLooking && !bIsRestoringLook && sinceLastInput - lastTime > 25000) { + int anim; + do + anim = CGeneral::GetRandomNumberInRange(0, ARRAY_SIZE(idleAnims)); + while (lastAnim == anim); + + assoc = CAnimManager::BlendAnimation(GetClump(), idleAnims[anim].groupId, idleAnims[anim].animId, 8.0f); + assoc->flags |= ASSOC_IDLE; + lastAnim = anim; + lastTime = sinceLastInput; + } + } + } +} + +void +CPlayerPed::SetNearbyPedsToInteractWithPlayer(void) +{ + if (CGame::noProstitutes) + return; + + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed && nearPed->m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) { + int mi = nearPed->GetModelIndex(); + if (CPopulation::CanSolicitPlayerOnFoot(mi)) { + CVector distToMe = nearPed->GetPosition() - GetPosition(); + CVector dirToMe = GetPosition() - nearPed->GetPosition(); + dirToMe.Normalise(); + if (DotProduct(dirToMe, nearPed->GetForward()) > 0.707 && DotProduct(GetForward(), nearPed->GetForward()) < -0.707 // those are double + && distToMe.MagnitudeSqr() < 9.0f && nearPed->m_objective == OBJECTIVE_NONE) { + nearPed->SetObjective(OBJECTIVE_SOLICIT_FOOT, this); + nearPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; + nearPed->Say(SOUND_PED_SOLICIT); + } + } else if (CPopulation::CanSolicitPlayerInCar(mi)) { + if (InVehicle() && m_pMyVehicle->IsVehicleNormal()) { + if (m_pMyVehicle->IsCar()) { + CVector distToVeh = nearPed->GetPosition() - m_pMyVehicle->GetPosition(); + if (distToVeh.MagnitudeSqr() < 25.0f && m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil) && nearPed->m_objective == OBJECTIVE_NONE) { + nearPed->SetObjective(OBJECTIVE_SOLICIT_VEHICLE, m_pMyVehicle); + } + } + } + } + } + } +} + +void +CPlayerPed::UpdateMeleeAttackers(void) +{ + CVector attackCoord; + if (((CTimer::GetFrameCounter() + m_randomSeed + 7) & 3) == 0) { + GetMeleeAttackCoords(attackCoord, m_nAttackDirToCheck, 2.0f); + + // Check if there is any vehicle/building inbetween us and m_nAttackDirToCheck. Peds will be able to attack us from those available directions. + if (CWorld::GetIsLineOfSightClear(GetPosition(), attackCoord, true, true, false, true, false, false, false) + && !CWorld::TestSphereAgainstWorld(attackCoord, 0.4f, m_pMeleeList[m_nAttackDirToCheck], true, true, false, true, false, false)) { + if (m_pMeleeList[m_nAttackDirToCheck] == this) + m_pMeleeList[m_nAttackDirToCheck] = nil; // mark it as available + } else { + m_pMeleeList[m_nAttackDirToCheck] = this; // slot not available. useful for m_bNoPosForMeleeAttack + } + if (++m_nAttackDirToCheck >= ARRAY_SIZE(m_pMeleeList)) + m_nAttackDirToCheck = 0; + } + // 6 directions + for (int i = 0; i < ARRAY_SIZE(m_pMeleeList); ++i) { + CPed *victim = m_pMeleeList[i]; + if (victim && victim != this) { + if (victim->m_nPedState != PED_DEAD && victim->m_pedInObjective == this) { + if (victim->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || victim->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || victim->m_objective == OBJECTIVE_KILL_CHAR_ON_BOAT) { + GetMeleeAttackCoords(attackCoord, i, 2.0f); + if ((attackCoord - GetPosition()).MagnitudeSqr() > 12.25f) + m_pMeleeList[i] = nil; + } else { + m_pMeleeList[i] = nil; + } + } else { + m_pMeleeList[i] = nil; + } + } + } + m_bNoPosForMeleeAttack = m_pMeleeList[0] == this && m_pMeleeList[1] == this && m_pMeleeList[2] == this +#ifdef FIX_BUGS + && m_pMeleeList[3] == this #endif + && m_pMeleeList[4] == this && m_pMeleeList[5] == this; +} + +void +CPlayerPed::RemovePedFromMeleeList(CPed *ped) +{ + for (uint16 i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) { + if (m_pMeleeList[i] == ped) { + m_pMeleeList[i] = nil; + ped->m_attackTimer = 0; + return; + } + } +} + +void +CPlayerPed::GetMeleeAttackCoords(CVector& coords, int8 dir, float dist) +{ + coords = GetPosition(); + switch (dir) { + case 0: + coords.y += dist; + break; + case 1: + coords.x += Sqrt(3.f / 4.f) * dist; + coords.y += 0.5f * dist; + break; + case 2: + coords.x += Sqrt(3.f / 4.f) * dist; + coords.y -= 0.5f * dist; + break; + case 3: + coords.y -= dist; + break; + case 4: + coords.x -= Sqrt(3.f / 4.f) * dist; + coords.y -= 0.5f * dist; + break; + case 5: + coords.x -= Sqrt(3.f / 4.f) * dist; + coords.y += 0.5f * dist; + break; + default: + break; + } +} + +int32 +CPlayerPed::FindMeleeAttackPoint(CPed *victim, CVector &dist, uint32 &endOfAttackOut) +{ + endOfAttackOut = 0; + bool thereIsAnEmptySlot = false; + int dirToAttack = -1; + for (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) { + CPed* pedAtThisDir = m_pMeleeList[i]; + if (pedAtThisDir) { + if (pedAtThisDir == victim) { + dirToAttack = i; + } else { + if (pedAtThisDir->m_attackTimer > endOfAttackOut) + endOfAttackOut = pedAtThisDir->m_attackTimer; + } + } else { + thereIsAnEmptySlot = true; + } + } + + // We don't have victim ped in our melee list + if (dirToAttack == -1 && thereIsAnEmptySlot) { + float angle = Atan2(-dist.x, -dist.y); + float adjustedAngle = angle + DEGTORAD(30.0f); + if (adjustedAngle < 0.f) + adjustedAngle += TWOPI; + + int wantedDir = Floor(adjustedAngle / DEGTORAD(60.0f)); + + // And we have another ped at the direction of victim ped, so store victim to next empty direction to it's real direction. (Bollocks) + if (m_pMeleeList[wantedDir]) { + int closestDirToPreferred = -99; + int preferredDir = wantedDir; + + for (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) { + if (!m_pMeleeList[i]) { + if (Abs(i - preferredDir) < Abs(closestDirToPreferred - preferredDir)) + closestDirToPreferred = i; + } + } + if (closestDirToPreferred > 0) + dirToAttack = closestDirToPreferred; + } else { + + // Luckily the direction of victim ped is already empty, good + dirToAttack = wantedDir; + } + + if (dirToAttack != -1) { + m_pMeleeList[dirToAttack] = victim; + victim->RegisterReference((CEntity**) &m_pMeleeList[dirToAttack]); + if (endOfAttackOut > CTimer::GetTimeInMilliseconds()) + victim->m_attackTimer = endOfAttackOut + CGeneral::GetRandomNumberInRange(1000, 2000); + else + victim->m_attackTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(500, 1000); + } + } + return dirToAttack; } #ifdef COMPATIBLE_SAVES @@ -1560,7 +2246,7 @@ CPlayerPed::Save(uint8*& buf) CopyToBuf(buf, m_nTargettableObjects[1]); CopyToBuf(buf, m_nTargettableObjects[2]); CopyToBuf(buf, m_nTargettableObjects[3]); - ZeroSaveBuf(buf, 116); + ZeroSaveBuf(buf, 164); } void @@ -1574,7 +2260,7 @@ CPlayerPed::Load(uint8*& buf) CopyFromBuf(buf, m_nTargettableObjects[1]); CopyFromBuf(buf, m_nTargettableObjects[2]); CopyFromBuf(buf, m_nTargettableObjects[3]); - SkipSaveBuf(buf, 116); + SkipSaveBuf(buf, 164); } #undef CopyFromBuf #undef CopyToBuf |