aboutsummaryrefslogtreecommitdiffstats
path: root/src/peds/PlayerPed.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds/PlayerPed.cpp')
-rw-r--r--src/peds/PlayerPed.cpp1108
1 files changed, 907 insertions, 201 deletions
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 416fb949..1d96ba6d 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -16,17 +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
+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;
@@ -45,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);
@@ -55,23 +75,33 @@ 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");
}
-void CPlayerPed::ClearWeaponTarget()
+void
+CPlayerPed::ClearWeaponTarget()
{
if (m_nPedType == PEDTYPE_PLAYER1) {
SetWeaponLockOnTarget(nil);
@@ -97,11 +127,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;
}
@@ -152,6 +178,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
@@ -183,20 +214,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;
@@ -205,6 +238,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 };
@@ -226,13 +266,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;
@@ -244,13 +287,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;
@@ -258,6 +302,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
@@ -284,6 +333,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()))) {
@@ -300,7 +351,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);
@@ -314,7 +365,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);
@@ -325,11 +376,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);
@@ -354,7 +405,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;
@@ -399,7 +453,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;
@@ -416,7 +470,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;
@@ -462,6 +516,8 @@ CPlayerPed::SetRealMoveAnim(void)
curRunAssoc->blendAmount = 1.0f;
m_nMoveState = PEDMOVE_RUN;
}
+ curWalkAssoc->blendDelta = 0.0f;
+ curRunAssoc->blendDelta = 0.0f;
}
}
}
@@ -488,6 +544,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;
}
}
@@ -498,20 +559,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(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
@@ -529,14 +627,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;
}
@@ -559,8 +649,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;
@@ -574,7 +667,7 @@ CPlayerPed::IsThisPedAttackingPlayer(CPed *suspect)
default:
break;
}
- return false;
+ return suspect->m_nPedState == PED_ABSEIL;
}
void
@@ -583,78 +676,123 @@ 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;
- if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt) {
+ 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()) {
+ goto spentAmmoCheck;
+ }
}
+ m_nSelectedWepSlot = 0;
}
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- }
- } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt) {
- 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;
- }
+ } 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);
}
}
- // 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) {
+#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);
+ }
}
}
@@ -664,17 +802,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
@@ -729,14 +884,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) {
@@ -747,6 +909,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
@@ -755,7 +923,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);
@@ -799,17 +967,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) {
@@ -838,7 +1004,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) {
@@ -850,6 +1016,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;
@@ -863,25 +1060,30 @@ CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft)
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) && 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);
+ bDontAllowWeaponChange = true;
SetPointGunAt(nextTarget);
return true;
}
@@ -908,26 +1110,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);
+ bDontAllowWeaponChange = true;
SetPointGunAt(nextTarget);
+ Say(SOUND_PED_AIMING);
return true;
}
@@ -935,7 +1143,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()
@@ -945,17 +1152,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;
}
@@ -965,9 +1184,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 a 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 {
@@ -994,44 +1223,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;
@@ -1042,12 +1303,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 {
@@ -1060,33 +1328,35 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
#ifdef FREE_CAM
static int8 changedHeadingRate = 0;
+ static int8 pointedGun = 0;
if (changedHeadingRate == 2) changedHeadingRate = 1;
+ if (pointedGun == 2) pointedGun = 1;
// Rotate player/arm when shooting. We don't have auto-rotation anymore
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);
// On this one we can rotate arm.
- if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) {
+ if (CAN_AIM_WITH_ARM) {
if (!padUsed->GetWeapon()) { // making this State != ATTACK still stops it after attack. Re-start it immediately!
SetPointGunAt(nil);
bIsPointingGunAt = false; // to not stop after attack
}
-
+ pointedGun = 2;
SetLookFlag(limitedCam, true);
SetAimFlag(limitedCam);
-#ifdef VC_PED_PORTS
SetLookTimer(INT32_MAX); // removing this makes head move for real, but I experinced some bugs.
-#endif
+
} else {
m_fRotationDest = limitedCam;
changedHeadingRate = 2;
- m_headingRate = 50.0f;
+ m_headingRate = 12.5f;
// Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)
if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM) && padUsed->WeaponJustDown()) {
@@ -1102,17 +1372,21 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
m_fRotationCur += (limitedRotDest - m_fRotationCur) / 2;
}
}
- } else if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) && m_nPedState != PED_ATTACK)
- ClearPointGunAt();
+ }
}
+#undef CAN_AIM_WITH_ARM
}
if (changedHeadingRate == 1) {
changedHeadingRate = 0;
RestoreHeadingRate();
}
+ if (pointedGun == 1 && m_nPedState != PED_ATTACK) {
+ pointedGun = 0;
+ ClearPointGunAt();
+ }
#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
@@ -1120,15 +1394,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);
@@ -1137,13 +1426,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) {
@@ -1151,16 +1436,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 {
@@ -1170,17 +1451,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 {
@@ -1188,7 +1480,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed)
}
#ifdef FREE_CAM
- if(TheCamera.Cams[0].Using3rdPersonMouseCam() && doSmoothSpray) {
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam() && smoothSprayRate > 0.0f) {
padMoveInGameUnit = 0.0f;
smoothSprayWithoutMove = false;
}
@@ -1197,12 +1489,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;
}
@@ -1228,13 +1516,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();
@@ -1246,34 +1541,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);
@@ -1291,27 +1720,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);
+ }
}
}
}
@@ -1321,11 +1752,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);
@@ -1340,8 +1771,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
@@ -1357,7 +1793,7 @@ CPlayerPed::ProcessControl(void)
PlayerControlZelda(padUsed);
}
}
- if (IsPedInControl() && padUsed)
+ if (IsPedInControl() && m_nPedState != PED_ANSWER_MOBILE && padUsed)
ProcessPlayerWeapon(padUsed);
break;
case PED_SEEK_ENTITY:
@@ -1386,12 +1822,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:
@@ -1442,9 +1878,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) {
@@ -1454,12 +1890,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;
@@ -1490,10 +1927,279 @@ CPlayerPed::ProcessControl(void)
m_bSpeedTimerFlag = false;
}
-#ifdef PED_SKIN
- if (!bIsVisible && IsClumpSkinned(GetClump()))
+ if (bDontAllowWeaponChange && FindPlayerPed() == this) {
+ if (!CPad::GetPad(0)->GetTarget())
+ bDontAllowWeaponChange = false;
+ }
+
+ 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
@@ -1510,7 +2216,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
@@ -1524,7 +2230,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