aboutsummaryrefslogtreecommitdiffstats
path: root/src/peds/PedFight.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds/PedFight.cpp')
-rw-r--r--src/peds/PedFight.cpp2841
1 files changed, 1886 insertions, 955 deletions
diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp
index 13d3930c..20df6553 100644
--- a/src/peds/PedFight.cpp
+++ b/src/peds/PedFight.cpp
@@ -22,37 +22,47 @@
#include "Automobile.h"
#include "WaterLevel.h"
#include "World.h"
+#include "Bike.h"
+#include "Glass.h"
+#include "SpecialFX.h"
uint16 nPlayerInComboMove;
+RpClump* flyingClumpTemp;
-RpClump *flyingClumpTemp;
-
-// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
-FightMove tFightMoves[NUM_FIGHTMOVES] = {
- {ANIM_STD_NUM, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_PUNCH, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0},
- {ANIM_STD_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_FIGHT_SHUFFLE_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0},
- {ANIM_STD_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0},
- {ANIM_STD_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0},
- {ANIM_STD_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0},
- {ANIM_STD_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0},
- {ANIM_STD_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_STD_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_STD_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0},
- {ANIM_STD_KICKGROUND, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0},
- {ANIM_STD_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_FLOOR, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_STD_FIGHT_2IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+FightMove tFightMoves[NUM_FIGHTMOVES] =
+{
+ { ANIM_STD_NUM, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_PUNCH, 0.2f, 8.f/30.f, 0.0f, 0.3f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_STD_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_FIGHT_SHUFFLE_F, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_FIGHT_KNEE, 4.f/30.f, 0.2f, 0.0f, 0.6f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_STD_FIGHT_LHOOK, 8.f/30.f, 10.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_HIGH, 3, 0 },
+ { ANIM_STD_FIGHT_JAB, 4.f/30.f, 0.2f, 0.0f, 0.7f, 1.0f, HITLEVEL_HIGH, 3, 0 },
+ { ANIM_STD_FIGHT_PUNCH, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_STD_FIGHT_LONGKICK, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },
+ { ANIM_STD_FIGHT_ROUNDHOUSE, 8.f/30.f, 10.f/30.f, 0.0f, 0.6f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },
+ { ANIM_STD_FIGHT_KICK, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_HIGH, 2, 0 },
+ { ANIM_STD_FIGHT_HEAD, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_STD_FIGHT_BKICK_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_STD_FIGHT_BKICK_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_STD_FIGHT_ELBOW_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_STD_FIGHT_BKICK_R, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_STD_FIGHT_ELBOW_R, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_HIGH, 2, 0 },
+ { ANIM_STD_KICKGROUND, 10.f/30.f, 14.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_GROUND, 1, 0 },
+ { ANIM_STD_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_FLOOR, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_STD_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_ATTACK_1, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_ATTACK_2, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_ATTACK_3, 4.f / 30.f, 7.f / 30.f, 10.f / 30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_STD_FIGHT_2IDLE, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 }
};
static PedOnGroundState
@@ -151,14 +161,13 @@ void
CPed::SetPointGunAt(CEntity *to)
{
if (to) {
- SetLookFlag(to, true);
+ SetLookFlag(to, true, true);
SetAimFlag(to);
-#ifdef VC_PED_PORTS
SetLookTimer(INT32_MAX);
-#endif
}
- if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ CWeaponInfo* curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (m_nPedState == PED_AIM_GUN || (bIsDucking && !IsPlayer()) || m_nWaitState == WAITSTATE_PLAYANIM_DUCK || curWeapon->m_AnimToPlay == ASSOCGRP_STD)
return;
if (m_nPedState != PED_ATTACK)
@@ -166,26 +175,27 @@ CPed::SetPointGunAt(CEntity *to)
SetPedState(PED_AIM_GUN);
bIsPointingGunAt = true;
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- SetMoveState(PEDMOVE_NONE);
+ SetMoveState(PEDMOVE_STILL);
CAnimBlendAssociation *aimAssoc;
- if (bCrouchWhenShooting)
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay);
- else
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay);
+ if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
+ } else {
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ }
if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
- if (bCrouchWhenShooting)
- aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
- else
- aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay);
+ if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
+ aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);
+ } else {
+ aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE);
+ }
aimAssoc->blendAmount = 0.0f;
aimAssoc->blendDelta = 8.0f;
}
- if (to)
+ if (to && !IsPlayer())
Say(SOUND_PED_ATTACK);
}
@@ -193,14 +203,22 @@ void
CPed::PointGunAt(void)
{
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f)
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
+ float animLoopStart = weaponInfo->m_fAnimLoopStart;
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) {
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));
+ animLoopStart = weaponInfo->m_fAnim2LoopStart;
+ }
+ }
- if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
- weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
+ if (weaponAssoc && weaponAssoc->currentTime > animLoopStart * 0.4f) {
+ weaponAssoc->SetCurrentTime(animLoopStart);
weaponAssoc->flags &= ~ASSOC_RUNNING;
+ if (bIsDucking)
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+
if (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))
m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
@@ -217,51 +235,38 @@ CPed::ClearPointGunAt(void)
ClearLookFlag();
ClearAimFlag();
bIsPointingGunAt = false;
-#ifndef VC_PED_PORTS
- if (m_nPedState == PED_AIM_GUN) {
- RestorePreviousState();
-#else
if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
SetPedState(PED_IDLE);
RestorePreviousState();
}
-#endif
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (!animAssoc || animAssoc->blendDelta < 0.0f) {
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));
}
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -4.0f;
- }
-#ifndef VC_PED_PORTS
}
-#endif
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -4.0f;
+ }
}
void
CPed::SetAttack(CEntity *victim)
{
CPed *victimPed = nil;
+ CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *animAssoc;
+
if (victim && victim->IsPed())
victimPed = (CPed*)victim;
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_BIGGUN);
- if (animAssoc) {
- animAssoc->blendDelta = -1000.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE)
+ if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE || (bIsDucking && !bCrouchWhenShooting))
return;
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HGUN_RELOAD)) {
- bIsAttacking = false;
- return;
- }
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_AK_RELOAD)) {
+ if (curWeapon->IsFlagSet(WEAPONFLAG_RELOAD) &&
+ (RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(curWeapon)) || RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(curWeapon)))) {
if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
bIsAttacking = false;
else
@@ -270,20 +275,16 @@ CPed::SetAttack(CEntity *victim)
return;
}
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) {
- if (GetWeapon()->HitsGround(this, nil, victim))
- return;
- }
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->IsFlagSet(WEAPONFLAG_FIGHTMODE) || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) {
if (IsPlayer() ||
- (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
+ (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL
+ && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS) && curWeapon->IsFlagSet(WEAPONFLAG_PARTIALATTACK))) {
if (m_nPedState != PED_ATTACK) {
SetPedState(PED_ATTACK);
bIsAttacking = false;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
+
+ CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);
animAssoc->SetRun();
if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
animAssoc->SetCurrentTime(0.0f);
@@ -291,38 +292,69 @@ CPed::SetAttack(CEntity *victim)
animAssoc->SetFinishCallback(FinishedAttackCB, this);
}
} else {
- StartFightAttack(CGeneral::GetRandomNumber() % 256);
+ StartFightAttack(CGeneral::GetRandomNumber());
}
return;
}
+ if (curWeapon->IsFlagSet(WEAPONFLAG_PARTIALATTACK) &&
+ (IsPlayer() && ((CPlayerPed*)this)->m_fMoveSpeed >= 1.0f ||
+ m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN)) {
+
+ if (m_nPedState != PED_ATTACK) {
+ SetPedState(PED_ATTACK);
+ bIsAttacking = false;
+ CAnimBlendAssociation* animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ return;
+ }
+
+ if (m_pSeekTarget)
+ m_pSeekTarget->CleanUpOldReference(&m_pSeekTarget);
m_pSeekTarget = victim;
if (m_pSeekTarget)
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
if (curWeapon->IsFlagSet(WEAPONFLAG_CANAIM)) {
CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();
+ aimPos += GetUp() * 0.35f;
CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
- if (obstacle)
- return;
+ if (obstacle) {
+ if(gaTempSphereColPoints[0].surfaceB != SURFACE_TRANSPARENT_CLOTH && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_CHAIN_FENCE &&
+ gaTempSphereColPoints[0].surfaceB != SURFACE_WOOD_BENCH && gaTempSphereColPoints[0].surfaceB != SURFACE_SCAFFOLD_POLE) {
+ if (!IsPlayer()) {
+ bObstacleShowedUpDuringKillObjective = true;
+ m_shootTimer = 0;
+ SetAttackTimer(1500);
+ m_shotTime = CTimer::GetTimeInMilliseconds();
+ }
+ return;
+ }
+ }
m_pLookTarget = victim;
if (victim) {
m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
}
+
if (m_pLookTarget) {
SetAimFlag(m_pLookTarget);
- } else {
+ } else if (this == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+ SetAimFlag(m_fRotationCur);
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+ } else if (curWeapon->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) {
SetAimFlag(m_fRotationCur);
-
- if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
}
}
#ifdef FIX_BUGS
- // fix aiming for flamethrower while using PC controls
- else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && TheCamera.Cams[0].Using3rdPersonMouseCam() && this == FindPlayerPed())
+ // fix aiming for flamethrower and minigun while using PC controls
+ else if (curWeapon->m_AnimToPlay == ASSOCGRP_FLAMETHROWER && TheCamera.Cams[0].Using3rdPersonMouseCam() && this == FindPlayerPed())
{
SetAimFlag(m_fRotationCur);
((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
@@ -333,7 +365,7 @@ CPed::SetAttack(CEntity *victim)
return;
}
- if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
+ if (IsPlayer() || (!victimPed || victimPed->IsPedInControl())) {
if (IsPlayer())
CPad::GetPad(0)->ResetAverageWeapon();
@@ -347,7 +379,7 @@ CPed::SetAttack(CEntity *victim)
ClearAimFlag();
// This condition is pointless
- if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
+ if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed && (IsPlayer() || !m_carInObjective))
StartFightAttack(200);
} else {
if (!curWeapon->IsFlagSet(WEAPONFLAG_CANAIM))
@@ -358,19 +390,40 @@ CPed::SetAttack(CEntity *victim)
SetPedState(PED_ATTACK);
SetMoveState(PEDMOVE_NONE);
- if (bCrouchWhenShooting) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_RBLOCK_SHOOT, 4.0f);
+ if (bCrouchWhenShooting && bIsDucking && curWeapon->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {
+ CAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
+ if (curMoveAssoc) {
+ if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon))->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) {
+ delete curMoveAssoc;
+ }
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 8.0f);
} else {
float animDelta = 8.0f;
if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)
animDelta = 1000.0f;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT
- || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta);
+ AnimationId fireAnim;
+ if (curWeapon->IsFlagSet(WEAPONFLAG_THROW))
+ fireAnim = ANIM_THROWABLE_START_THROW;
+ else if (CGame::nastyGame && (curWeapon->IsFlagSet(WEAPONFLAG_GROUND_2ND) || curWeapon->IsFlagSet(WEAPONFLAG_GROUND_3RD))) {
+ PedOnGroundState pedOnGround = CheckForPedsOnGroundToAttack(this, nil);
+ if (pedOnGround > PED_IN_FRONT_OF_ATTACKER || pedOnGround == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle()) {
+ fireAnim = GetFireAnimGround(curWeapon, false);
+ } else {
+ fireAnim = GetFireAnimNotDucking(curWeapon);
+ }
} else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
+ fireAnim = GetFireAnimNotDucking(curWeapon);
}
+
+ CAnimBlendAssociation* curFireAssoc = RpAnimBlendClumpGetAssociation(GetClump(), fireAnim);
+ if (curFireAssoc) {
+ if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, fireAnim)->hierarchy->name, curFireAssoc->hierarchy->name) != 0) {
+ delete curFireAssoc;
+ }
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, fireAnim, animDelta);
}
animAssoc->SetRun();
@@ -385,24 +438,19 @@ CPed::SetAttack(CEntity *victim)
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
SetWaitState(WAITSTATE_SURPRISE, nil);
- SetLookFlag(victim, false);
+ SetLookFlag(victim, true, true);
SetLookTimer(100);
}
void
CPed::ClearAttack(void)
{
- if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ if (m_nPedState != PED_ATTACK || (bIsDucking && !IsPlayer()) || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
return;
-#ifdef VC_PED_PORTS
- // VC uses CCamera::Using1stPersonWeaponMode
- if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
- TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
+ if (FindPlayerPed() == this && TheCamera.Using1stPersonWeaponMode()) {
SetPointGunAt(nil);
- } else
-#endif
- if (bIsPointingGunAt) {
+ } else if (bIsPointingGunAt) {
if (m_pLookTarget)
SetPointGunAt(m_pLookTarget);
else
@@ -417,70 +465,148 @@ CPed::ClearAttack(void)
void
CPed::ClearAttackByRemovingAnim(void)
{
- if (m_nPedState != PED_ATTACK || bIsDucking)
+ if (m_nPedState != PED_ATTACK)
return;
CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay);
- if (!weaponAssoc) {
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay);
-
- if (!weaponAssoc && weapon->IsFlagSet(WEAPONFLAG_THROW))
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_THROW_UNDER);
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weapon));
- if (!weaponAssoc) {
- ClearAttack();
- return;
- }
+ if (!weaponAssoc) {
+ if (GetCrouchFireAnim(weapon))
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (!weaponAssoc) {
+ if(GetFinishingAttackAnim(weapon))
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFinishingAttackAnim(weapon));
+ }
+ if (!weaponAssoc) {
+ if(GetSecondFireAnim(weapon))
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(weapon));
+ }
+ if (!weaponAssoc) {
+ if(Get3rdFireAnim(weapon))
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(weapon));
+ }
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = -8.0f;
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
+ } else {
+ ClearAttack();
}
- weaponAssoc->blendDelta = -8.0f;
- weaponAssoc->flags &= ~ASSOC_RUNNING;
- weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
}
void
CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
{
- CWeaponInfo *currentWeapon;
- CAnimBlendAssociation *newAnim;
+ CAnimBlendAssociation *newAnim, *reloadAnimAssoc = nil;
CPed *ped = (CPed*)arg;
+ CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
- if (attackAssoc) {
- switch (attackAssoc->animId) {
- case ANIM_STD_START_THROW:
- // what?!
- if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_THROW_UNDER);
- } else {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_WEAPON_THROW);
+ if (ped->m_nPedState != PED_ATTACK) {
+ if (ped->bIsDucking && ped->IsPedInControl()) {
+ if (GetCrouchReloadAnim(currentWeapon)) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));
+ }
+ if (GetCrouchFireAnim(currentWeapon) && attackAssoc) {
+ if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {
+ newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);
+ newAnim->SetCurrentTime(newAnim->hierarchy->totalLength);
+ newAnim->flags &= ~ASSOC_RUNNING;
}
+ }
+ }
+ } else if (attackAssoc && attackAssoc->animId == ANIM_THROWABLE_START_THROW && currentWeapon->m_AnimToPlay == ASSOCGRP_THROW) {
+ if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
+ attackAssoc->blendDelta = -1000.0f;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROWU);
+ } else {
+ attackAssoc->blendDelta = -1000.0;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROW);
+ }
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
- newAnim->SetFinishCallback(FinishedAttackCB, ped);
- return;
+ } else if (ped->bIsDucking && ped->bCrouchWhenShooting) {
+ if (GetCrouchReloadAnim(currentWeapon)) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));
+ }
+ if (GetCrouchFireAnim(currentWeapon) && attackAssoc) {
+ if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {
+ newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);
+ newAnim->SetCurrentTime(newAnim->hierarchy->totalLength);
+ newAnim->flags &= ~ASSOC_RUNNING;
+ }
+ }
- case ANIM_STD_PARTIAL_PUNCH:
- attackAssoc->blendDelta = -8.0f;
- attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ped->ClearAttack();
- return;
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
- case ANIM_STD_WEAPON_THROW:
- case ANIM_STD_THROW_UNDER:
- if (ped->GetWeapon()->m_nAmmoTotal > 0) {
- currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
+ } else if (GetSecondFireAnim(currentWeapon) && ped->bIsAttacking && currentWeapon->m_AnimToPlay != ASSOCGRP_THROW) {
+ AnimationId groundAnim = GetFireAnimGround(currentWeapon);
+ CAnimBlendAssociation *groundAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), groundAnim);
+ if (!(groundAnimAssoc && (groundAnimAssoc->blendAmount > 0.95f || groundAnimAssoc->blendDelta > 0.0f))) {
+ if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK) {
+ newAnim = CAnimManager::BlendAnimation(
+ ped->GetClump(), currentWeapon->m_AnimToPlay, GetSecondFireAnim(currentWeapon), 8.0f);
+ } else {
+ newAnim = CAnimManager::BlendAnimation(
+ ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK, 8.0f);
+ }
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
+ }
+ } else {
+ if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK && currentWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) {
+ attackAssoc->blendDelta = -8.0f;
+ attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ped->ClearAttack();
+ return;
+ }
+ if (attackAssoc) {
+ if (currentWeapon->m_AnimToPlay == ASSOCGRP_THROW) {
+ if ((attackAssoc->animId == ANIM_THROWABLE_THROW || attackAssoc->animId == ANIM_THROWABLE_THROWU) && ped->GetWeapon()->m_nAmmoTotal > 0) {
+ ped->RemoveWeaponModel(currentWeapon->m_nModelId);
ped->AddWeaponModel(currentWeapon->m_nModelId);
}
- break;
- default:
- break;
+ }
}
+
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
}
+}
+
+void
+CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
- if (!ped->bIsAttacking)
- ped->ClearAttack();
+ if (ped->DyingOrDead())
+ return;
+
+ if (ped->bIsDucking && ped->bCrouchWhenShooting) {
+ CAnimBlendAssociation *crouchFireAssoc = nil;
+ if (weapon->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {
+ crouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (weapon->IsFlagSet(WEAPONFLAG_RELOAD) && reloadAssoc) {
+ if (reloadAssoc->animId == GetCrouchReloadAnim(weapon) && !crouchFireAssoc) {
+ CAnimBlendAssociation *crouchAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);
+ crouchAssoc->SetCurrentTime(crouchAssoc->hierarchy->totalLength);
+ crouchAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ }
+ } else if (weapon->IsFlagSet(WEAPONFLAG_RELOAD_LOOP2START) && ped->bIsAttacking) {
+ CAnimBlendAssociation *fireAssoc =
+ CAnimManager::BlendAnimation(ped->GetClump(), weapon->m_AnimToPlay, GetPrimaryFireAnim(weapon), 8.0f);
+ fireAssoc->SetFinishCallback(FinishedAttackCB, ped);
+ fireAssoc->SetRun();
+ if (fireAssoc->currentTime == reloadAssoc->hierarchy->totalLength)
+ fireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));
+ else if (fireAssoc->currentTime < weapon->m_fAnimLoopStart)
+ fireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));
+ }
}
uint8
@@ -496,7 +622,7 @@ CPed::CheckForPointBlankPeds(CPed *pedToVerify)
if (!pedToVerify || pedToVerify == nearPed) {
CVector diff = nearPed->GetPosition() - GetPosition();
- if (diff.Magnitude() < pbDistance) {
+ if (diff.MagnitudeSqr() < SQR(pbDistance)) {
float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
nearPed->GetPosition().x, nearPed->GetPosition().y,
@@ -509,7 +635,9 @@ CPed::CheckForPointBlankPeds(CPed *pedToVerify)
if (neededTurn > PI)
neededTurn = 2*PI - neededTurn;
- if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY)
+ PedState nearPedState = nearPed->m_nPedState;
+
+ if (nearPedState == PED_FALL || nearPedState == PED_GETUP || nearPedState == PED_DIE || nearPedState == PED_DEAD || nearPedState == PED_DIVE_AWAY)
return NO_POINT_BLANK_PED;
if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
@@ -529,63 +657,135 @@ CPed::Attack(void)
{
CAnimBlendAssociation *weaponAnimAssoc;
int32 weaponAnim;
- float animStart;
float weaponAnimTime;
float animLoopEnd;
CWeaponInfo *ourWeapon;
bool attackShouldContinue;
- AnimationId reloadAnim;
CAnimBlendAssociation *reloadAnimAssoc;
+ CAnimBlendAssociation *throwAssoc;
float delayBetweenAnimAndFire;
+ float animLoopStart;
CVector firePos;
ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
- attackShouldContinue = bIsAttacking;
+ weaponAnimAssoc = nil;
+ attackShouldContinue = !!bIsAttacking;
reloadAnimAssoc = nil;
- reloadAnim = ANIM_STD_NUM;
+ throwAssoc = nil;
+ animLoopStart = ourWeapon->m_fAnimLoopStart;
+ animLoopEnd = ourWeapon->m_fAnimLoopEnd;
delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;
weaponAnim = ourWeapon->m_AnimToPlay;
- if (weaponAnim == ANIM_STD_WEAPON_HGUN_BODY)
- reloadAnim = ANIM_STD_HGUN_RELOAD;
- else if (weaponAnim == ANIM_STD_WEAPON_AK_BODY)
- reloadAnim = ANIM_STD_AK_RELOAD;
+ if (bIsDucking) {
+ if(GetCrouchFireAnim(ourWeapon) && bCrouchWhenShooting) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+ }
+ }
+ } else if (m_nPedType == PEDTYPE_COP && Get3rdFireAnim(ourWeapon)){
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = 11.f/30.f;
+ animLoopEnd = 19.f/30.f;
+ delayBetweenAnimAndFire = 14.f/30.f;
+ }
+ } else {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(ourWeapon));
+ }
- if (reloadAnim != ANIM_STD_NUM)
- reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
+ if (GetReloadAnim(ourWeapon)) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(ourWeapon));
+ }
- if (bIsDucking)
- return;
+ if (GetCrouchReloadAnim(ourWeapon) && !reloadAnimAssoc) {
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(ourWeapon));
+ }
- if (reloadAnimAssoc) {
+ if ( reloadAnimAssoc && reloadAnimAssoc->IsRunning() ) {
if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
ClearAttack();
-
return;
}
- if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ if ( reloadAnimAssoc ) {
+ reloadAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if ( reloadAnimAssoc->blendDelta >= 0.0f )
+ reloadAnimAssoc->blendDelta = -8.0f;
+ }
+
+ if (GetThrowAnim(ourWeapon)) {
+ throwAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetThrowAnim(ourWeapon));
+ }
+
+ if ( CTimer::GetTimeInMilliseconds() < m_shootTimer )
attackShouldContinue = true;
+ bool meleeAttackStarted = false;
+ if ( !weaponAnimAssoc ) {
+ if (GetMeleeStartAnim(ourWeapon)) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetMeleeStartAnim(ourWeapon));
+ if ( weaponAnimAssoc ) {
+ if ( IsPlayer() )
+ meleeAttackStarted = true;
+
+ switch ( ourWeapon->m_AnimToPlay ) {
+ case ASSOCGRP_UNARMED:
+ case ASSOCGRP_SCREWDRIVER:
+ case ASSOCGRP_KNIFE:
+ case ASSOCGRP_BASEBALLBAT:
+ case ASSOCGRP_GOLFCLUB:
+ case ASSOCGRP_CHAINSAW:
+ delayBetweenAnimAndFire = 0.2f;
+ animLoopStart = 0.1f;
+ break;
+ default:
+ break;
+ }
+ animLoopEnd = 99.9f;
+ }
+ }
+ }
if (!weaponAnimAssoc) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
- delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
-
- // Long throw granade, molotov
- if (!weaponAnimAssoc && ourWeapon->IsFlagSet(WEAPONFLAG_THROW)) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_THROW_UNDER);
- delayBetweenAnimAndFire = 0.2f;
+ if (GetSecondFireAnim(ourWeapon)) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+ }
}
+ }
+ if (!weaponAnimAssoc) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(ourWeapon));
+ if (weaponAnimAssoc) {
+ animLoopStart = ourWeapon->m_fAnim2LoopStart;
+ animLoopEnd = ourWeapon->m_fAnim2LoopEnd;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+ }
+ }
- if (!weaponAnimAssoc) {
+ if (!weaponAnimAssoc) {
+ if (!throwAssoc) {
if (attackShouldContinue) {
if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
- if (!CGame::nastyGame || ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
- }
- else {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(ourWeapon)) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f);
+
+ } else if(GetSecondFireAnim(ourWeapon) && CGeneral::GetRandomNumber() & 1){
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);
+
+ } else if(!CGame::nastyGame || ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE ||
+ !GetFireAnimGround(ourWeapon, false) ||
+ CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
+
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimNotDucking(ourWeapon), 8.0f);
+
+ } else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimGround(ourWeapon, false), 8.0f);
}
weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
@@ -602,79 +802,122 @@ CPed::Attack(void)
} else
FinishedAttackCB(nil, this);
- return;
}
+ return;
}
- animStart = ourWeapon->m_fAnimLoopStart;
+ if (meleeAttackStarted && IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bHaveTargetSelected || ((CPlayerPed*)this)->m_fMoveSpeed < 0.5f) {
+ weaponAnimAssoc->SetRun();
+ } else {
+ if (weaponAnimAssoc->currentTime > animLoopStart && weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= animLoopStart)
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ }
+
+ float animStart = animLoopStart * 0.4f;
weaponAnimTime = weaponAnimAssoc->currentTime;
if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
- if (ourWeapon->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))
+ if (!bIsDucking && !GetFireAnimNotDucking(ourWeapon) && ourWeapon->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))
m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
- if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
- if (weaponAnimAssoc->speed < 1.0f)
- weaponAnimAssoc->speed = 1.0f;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_CHAINSAW
+ || !meleeAttackStarted && delayBetweenAnimAndFire - 0.5f >= weaponAnimAssoc->currentTime
+ || weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire) {
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_IDLE, 0.0f);
+ } else if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
+ if (weaponAnimAssoc->speed < 1.0f)
+ weaponAnimAssoc->speed = 1.0f;
- } else {
- firePos = ourWeapon->m_vecFireOffset;
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) {
- if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
-
- firePos = GetMatrix() * firePos;
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_STD_KICKGROUND ? PED_FOOTR : PED_HANDR);
} else {
- firePos = GetMatrix() * firePos;
- }
-
- GetWeapon()->Fire(this, &firePos);
+ firePos = ourWeapon->m_vecFireOffset;
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_MOLOTOV || GetWeapon()->m_eWeaponType == WEAPONTYPE_GRENADE) {
- RemoveWeaponModel(ourWeapon->m_nModelId);
- }
- if (!GetWeapon()->m_nAmmoTotal && ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
- SelectGunIfArmed();
- }
+ if(ourWeapon->m_AnimToPlay != ASSOCGRP_BASEBALLBAT && ourWeapon->m_AnimToPlay != ASSOCGRP_GOLFCLUB) {
+ if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE) {
+ TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR);
+ } else {
+ firePos = GetMatrix() * firePos;
+ }
+ } else {
+ if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND)
+ firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
- if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) {
- // If reloading just began, start the animation
- // Last condition will always return true, even IDA hides it
- if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != ANIM_STD_NUM /* && !reloadAnimAssoc*/) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f);
- ClearLookFlag();
- ClearAimFlag();
- bIsAttacking = false;
- bIsPointingGunAt = false;
- m_shootTimer = CTimer::GetTimeInMilliseconds();
- return;
+ firePos = GetMatrix() * firePos;
}
- } else {
- if (weaponAnimAssoc->animId == ANIM_STD_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_STD_WEAPON_BAT_H) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
- } else if (weaponAnimAssoc->animId == ANIM_STD_PARTIAL_PUNCH) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+
+ GetWeapon()->Fire(this, &firePos);
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_MOLOTOV || GetWeapon()->m_eWeaponType == WEAPONTYPE_GRENADE || GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_TEARGAS) {
+ RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);
+ }
+ if (GetWeapon()->m_nAmmoTotal == 0 && ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
+ SelectGunIfArmed();
}
- weaponAnimAssoc->speed = 0.5f;
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) {
+ int damagerType = ENTITY_TYPE_NOTHING;
+ if (m_pDamageEntity && (m_fDamageImpulse == 0.0f || !m_pDamageEntity->IsBuilding())) {
+ damagerType = m_pDamageEntity->GetType();
+ }
+ switch (ourWeapon->m_AnimToPlay) {
+ case ASSOCGRP_UNARMED:
+ if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
+ break;
+ case ASSOCGRP_KNIFE:
+ case ASSOCGRP_BASEBALLBAT:
+ case ASSOCGRP_GOLFCLUB:
+ case ASSOCGRP_CHAINSAW:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
+ break;
+ default:
+ break;
+ }
- if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
- weaponAnimAssoc->callbackType = 0;
+ if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
+ weaponAnimAssoc->callbackType = 0;
+ }
}
+
+ attackShouldContinue = false;
}
+ } else {
+ CVector firePos = ourWeapon->m_vecFireOffset;
+
+ if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND)
+ firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
+ firePos = GetMatrix() * firePos;
+ GetWeapon()->Fire(this, &firePos);
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) {
+ int damagerType = ENTITY_TYPE_PED;
+ if (m_pDamageEntity)
+ damagerType = m_pDamageEntity->GetType();
+
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_MADECONTACT, (float)damagerType);
+ if (IsPlayer()) {
+ CPad::GetPad(0)->StartShake(240, 180);
+ }
+ } else {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_ATTACK, 0.0f);
+ if (IsPlayer()) {
+ CPad::GetPad(0)->StartShake(240, 90);
+ }
+ }
attackShouldContinue = false;
}
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) {
+ if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && ourWeapon->m_AnimToPlay == ASSOCGRP_SHOTGUN) {
weaponAnimTime = weaponAnimAssoc->currentTime;
- firePos = ourWeapon->m_vecFireOffset;
if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
+ firePos = ourWeapon->m_vecFireOffset;
TransformToNode(firePos, PED_HANDR);
CVector gunshellPos(
@@ -692,70 +935,94 @@ CPed::Attack(void)
GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
}
}
-#ifdef VC_PED_PORTS
+
+ if (IsPlayer()) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT || GetWeapon()->m_eWeaponType == WEAPONTYPE_GOLFCLUB || GetWeapon()->m_eWeaponType == WEAPONTYPE_KATANA) {
+ float loopEndWithDelay = animLoopEnd;
+ if (loopEndWithDelay >= 98.0f)
+ loopEndWithDelay = (14.0f / 30.0f) + delayBetweenAnimAndFire;
+ if (weaponAnimAssoc->flags & ASSOC_RUNNING) {
+ if (weaponAnimAssoc->currentTime >= animLoopStart && weaponAnimAssoc->currentTime <= loopEndWithDelay)
+ CSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);
+ }
+ }
+ }
+
+ // Anim breakout on running
if (IsPlayer()) {
if (CPad::GetPad(0)->GetSprint()) {
- // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line.
- float animBreakOut = ((GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f);
- if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) {
+ if (!attackShouldContinue && weaponAnimAssoc->currentTime > ourWeapon->m_fAnimBreakout) {
weaponAnimAssoc->blendDelta = -4.0f;
FinishedAttackCB(nil, this);
return;
}
}
}
-#endif
- animLoopEnd = ourWeapon->m_fAnimLoopEnd;
- if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- animLoopEnd = 3.4f/6.0f;
weaponAnimTime = weaponAnimAssoc->currentTime;
// Anim loop end, either start the loop again or finish the attack
if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE) {
-
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING) {
+ if (GetReloadAnim(ourWeapon) && !reloadAnimAssoc) {
+ if (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) {
+ CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(
+ GetClump(), ourWeapon->m_AnimToPlay,
+ bIsDucking && GetCrouchReloadAnim(ourWeapon) ? GetCrouchReloadAnim(ourWeapon) : GetReloadAnim(ourWeapon),
+ 8.0f);
+ newReloadAssoc->SetFinishCallback(FinishedReloadCB, this);
+ }
+ ClearLookFlag();
+ ClearAimFlag();
+ bIsAttacking = false;
+ bIsPointingGunAt = false;
+ m_shootTimer = CTimer::GetTimeInMilliseconds();
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
+ return;
+ }
+ }
if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
&& (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
- && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
+ && (GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)) {
- weaponAnim = weaponAnimAssoc->animId;
- if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_STD_RBLOCK_SHOOT) {
- weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart);
+ PedOnGroundState pedOnGroundState;
+ if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE &&
+ (CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER)
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
+
+ AnimationId fireAnim = GetFireAnimGround(ourWeapon, false);
+ if (weaponAnimAssoc->animId == fireAnim)
+ weaponAnimAssoc->SetCurrentTime(0.1f);
+ else {
+ if (GetFireAnimGround(ourWeapon, false)) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, fireAnim, 8.0f);
+ } else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_KICKGROUND, 8.0f);
+ }
+ }
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
+ } else if (GetSecondFireAnim(ourWeapon)) {
+ if (weaponAnimAssoc->animId == GetSecondFireAnim(ourWeapon)) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE, 8.0f);
} else {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);
}
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
} else {
- if (weaponAnim == ourWeapon->m_Anim2ToPlay)
- weaponAnimAssoc->SetCurrentTime(0.1f);
- else
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ weaponAnimAssoc->SetCurrentTime(animLoopStart);
+ weaponAnimAssoc->SetRun();
}
-#ifdef VC_PED_PORTS
} else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
- weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd);
+ weaponAnimAssoc->SetCurrentTime(animLoopEnd);
weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
SetPointGunAt(m_pPointGunAt);
-#endif
} else {
ClearAimFlag();
// Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
- if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) {
- switch (GetWeapon()->m_eWeaponType) {
- case WEAPONTYPE_UZI:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
- break;
- case WEAPONTYPE_AK47:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
- break;
- case WEAPONTYPE_M16:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
- break;
- default:
- break;
- }
- }
+ if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
// Fun fact: removing this part leds to reloading flamethrower
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
@@ -765,6 +1032,7 @@ CPed::Attack(void)
}
}
}
+
if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)
attackShouldContinue = false;
@@ -774,7 +1042,7 @@ CPed::Attack(void)
void
CPed::StartFightAttack(uint8 buttonPressure)
{
- if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
+ if (!IsPedInControl() || (m_attackTimer > CTimer::GetTimeInMilliseconds() && buttonPressure != 0))
return;
if (m_nPedState == PED_FIGHT) {
@@ -786,57 +1054,75 @@ CPed::StartFightAttack(uint8 buttonPressure)
SetStoredState();
if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
RestoreHeadingRate();
}
- SetPedState(PED_FIGHT);
- m_fightButtonPressure = 0;
- RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_STARTWALK);
-
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
- }
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP1);
+ CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP1);
if (!animAssoc)
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP2);
if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
RestoreHeadingRate();
}
-
SetMoveState(PEDMOVE_NONE);
m_nStoredMoveState = PEDMOVE_NONE;
-
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE)->blendAmount = 1.0f;
-
- CPed *pedOnGround = nil;
- if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) {
- m_curFightMove = FIGHTMOVE_GROUNDKICK;
- } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
- m_curFightMove = FIGHTMOVE_ROUNDHOUSE;
+ bool fightWithWeapon = false;
+ CAnimBlendAssociation *fightIdleAssoc;
+
+ CWeaponInfo* weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ if (GetFightIdleWithMeleeAnim(weaponInfo)) {
+ fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo), 1000.0f);
+ fightWithWeapon = true;
+ } else {
+ fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE, 1000.0f);
+ }
} else {
- m_curFightMove = FIGHTMOVE_STDPUNCH;
+ fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE, 1000.0f);
}
+ m_lastFightMove = FIGHTMOVE_IDLE;
+ m_curFightMove = IsPlayer() ? ChooseAttackPlayer(buttonPressure, fightWithWeapon) : ChooseAttackAI(buttonPressure, fightWithWeapon);
- if (pedOnGround && IsPlayer()) {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
- GetPosition().x, GetPosition().y);
+ SetPedState(PED_FIGHT);
+ m_fightButtonPressure = 0;
- m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
+ if (m_curFightMove > FIGHTMOVE_NULL && m_curFightMove != FIGHTMOVE_IDLE) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay,
+ tFightMoves[m_curFightMove].animId, 8.0f);
+
+ if (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE && m_curFightMove >= FIGHTMOVE_MELEE1) {
+ switch (GetWeapon()->m_eWeaponType) {
+ case WEAPONTYPE_SCREWDRIVER:
+ case WEAPONTYPE_KNIFE:
+ animAssoc->speed = 1.05f;
+ break;
+ case WEAPONTYPE_GOLFCLUB:
+ case WEAPONTYPE_NIGHTSTICK:
+ case WEAPONTYPE_BASEBALLBAT:
+ case WEAPONTYPE_HAMMER:
+ case WEAPONTYPE_KATANA:
+ animAssoc->speed = 0.8f;
+ break;
+ case WEAPONTYPE_CLEAVER:
+ case WEAPONTYPE_MACHETE:
+ animAssoc->speed = 0.9f;
+ break;
+ }
+ } else {
+ if (m_curFightMove == FIGHTMOVE_BACKKICK)
+ animAssoc->speed = 1.15f;
+ else
+ animAssoc->speed = 0.8f;
+ }
+ if (IsPlayer())
+ animAssoc->SetCurrentTime(0.08f);
+
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ } else {
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
}
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+
m_fightState = FIGHTSTATE_NO_MOVE;
m_takeAStepAfterAttack = false;
bIsAttacking = true;
@@ -885,13 +1171,9 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
} else if (IsPedInControl()) {
if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
|| (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
-#ifndef VC_PED_PORTS
- if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
- if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
-#else
+
if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
-#endif
AnimationId shotAnim;
switch (direction) {
case 1:
@@ -919,22 +1201,6 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
}
} else {
-#ifndef VC_PED_PORTS
- switch (direction) {
- case 1:
- SetFall(500, ANIM_STD_HIGHIMPACT_LEFT, false);
- break;
- case 2:
- SetFall(500, ANIM_STD_HIGHIMPACT_BACK, false);
- break;
- case 3:
- SetFall(500, ANIM_STD_HIGHIMPACT_RIGHT, false);
- break;
- default:
- SetFall(500, ANIM_STD_KO_SHOT_STOMACH, false);
- break;
- }
-#else
bool fall = true;
AnimationId hitAnim;
switch (direction) {
@@ -977,7 +1243,6 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
hitAssoc->SetRun();
hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
}
-#endif
}
Say(SOUND_PED_DEFEND);
} else {
@@ -987,20 +1252,15 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
m_curFightMove = FIGHTMOVE_HITONFLOOR;
break;
case HITLEVEL_LOW:
-#ifndef VC_PED_PORTS
- if (direction == 2) {
- SetFall(1000, ANIM_STD_HIGHIMPACT_BACK, false);
- return;
- }
-#else
if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
SetFall(1000, ANIM_STD_HIGHIMPACT_BACK, false);
+ Say(SOUND_PED_DEFEND);
return;
} else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
SetFall(1000, ANIM_STD_KO_SHOT_STOMACH, false);
+ Say(SOUND_PED_DEFEND);
return;
}
-#endif
m_curFightMove = FIGHTMOVE_HITBODY;
break;
case HITLEVEL_HIGH:
@@ -1050,24 +1310,28 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
moveAssoc->SetCurrentTime(0.0f);
moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
if (IsPlayer())
- moveAssoc->speed = 1.3f;
+ moveAssoc->speed = 1.2f;
m_takeAStepAfterAttack = false;
m_fightButtonPressure = 0;
- } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
+
+ } else if (IsPlayer() && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&
+ !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_FIGHTMODE)) {
CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->speed = 1.3f;
+ moveAssoc->speed = 1.2f;
+
} else {
if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
SetStoredState();
if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
RestoreHeadingRate();
}
SetPedState(PED_FIGHT);
m_fightButtonPressure = 0;
+ m_lastFightMove = FIGHTMOVE_IDLE;
RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_STARTWALK);
if (walkStartAssoc) {
@@ -1084,13 +1348,28 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
}
SetMoveState(PEDMOVE_NONE);
m_nStoredMoveState = PEDMOVE_NONE;
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE)->blendAmount = 1.0f;
+ CAnimBlendAssociation *fightIdleAssoc;
+
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (GetFightIdleWithMeleeAnim(weaponInfo)) {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo));
+ } else {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE);
+ }
+ } else {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE);
+ }
+ fightIdleAssoc->blendAmount = 1.0f;
CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
m_fightState = FIGHTSTATE_NO_MOVE;
m_takeAStepAfterAttack = false;
bIsAttacking = true;
}
+
+ if (m_pedInObjective && m_pedInObjective->IsPlayer() && !IsPlayer())
+ ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
}
}
}
@@ -1099,10 +1378,20 @@ void
CPed::Fight(void)
{
CAnimBlendAssociation *currentAssoc, *animAssoc;
- bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse;
- float angleToFace, nextAngle;
- bool goForward = false;
- int nextFightMove;
+ bool fightWithWeapon = false;
+
+ eWeaponType weapon = GetWeapon()->m_eWeaponType;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);
+
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE) && weapon != WEAPONTYPE_UNARMED) {
+ fightWithWeapon = true;
+ tFightMoves[FIGHTMOVE_MELEE1].startFireTime = weaponInfo->m_fAnimFrameFire;
+ tFightMoves[FIGHTMOVE_MELEE1].endFireTime = weaponInfo->m_fAnimLoopEnd;
+ tFightMoves[FIGHTMOVE_MELEE2].startFireTime = weaponInfo->m_fAnim2FrameFire;
+ tFightMoves[FIGHTMOVE_MELEE2].endFireTime = weaponInfo->m_fAnim2LoopEnd;
+ tFightMoves[FIGHTMOVE_MELEE3].startFireTime = weaponInfo->m_fAnim2FrameFire;
+ tFightMoves[FIGHTMOVE_MELEE3].endFireTime = weaponInfo->m_fAnim2LoopEnd;
+ }
switch (m_curFightMove) {
case FIGHTMOVE_NULL:
@@ -1122,6 +1411,20 @@ CPed::Fight(void)
break;
}
+ if (m_curFightMove == FIGHTMOVE_SHUFFLE_F && !currentAssoc)
+ currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_SHUFFLE_B);
+
+ if (IsPlayer() && currentAssoc && weapon == WEAPONTYPE_KATANA) {
+ if (m_curFightMove == FIGHTMOVE_MELEE1 || m_curFightMove == FIGHTMOVE_MELEE2) {
+ static float streakDelay = 0.2f;
+
+ if (tFightMoves[m_curFightMove].startFireTime - streakDelay < currentAssoc->currentTime &&
+ streakDelay + tFightMoves[m_curFightMove].endFireTime > currentAssoc->currentTime) {
+ CSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);
+ }
+ }
+ }
+
if (!bIsAttacking && IsPlayer()) {
if (currentAssoc) {
currentAssoc->blendDelta = -1000.0f;
@@ -1138,272 +1441,123 @@ CPed::Fight(void)
FightMove &curMove = tFightMoves[m_curFightMove];
if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
+ if (animTime > curMove.startFireTime && animTime - currentAssoc->timeStep < curMove.startFireTime &&
+ (IsPlayer() || weapon != WEAPONTYPE_UNARMED)) {
+
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_MELEE_ATTACK_START, weapon << 8);
+ }
+
CVector touchingNodePos(0.0f, 0.0f, 0.0f);
switch (m_curFightMove) {
- case FIGHTMOVE_STDPUNCH:
- case FIGHTMOVE_PUNCHHOOK:
- case FIGHTMOVE_BODYBLOW:
- TransformToNode(touchingNodePos, PED_HANDR);
- break;
- case FIGHTMOVE_IDLE:
- case FIGHTMOVE_SHUFFLE_F:
- break;
case FIGHTMOVE_KNEE:
TransformToNode(touchingNodePos, PED_LOWERLEGR);
break;
- case FIGHTMOVE_HEADBUTT:
- TransformToNode(touchingNodePos, PED_HEAD);
- break;
+ case FIGHTMOVE_PUNCHHOOK:
case FIGHTMOVE_PUNCHJAB:
TransformToNode(touchingNodePos, PED_HANDL);
break;
- case FIGHTMOVE_KICK:
case FIGHTMOVE_LONGKICK:
case FIGHTMOVE_ROUNDHOUSE:
+ case FIGHTMOVE_FWDLEFT:
+ case FIGHTMOVE_BACKRIGHT:
case FIGHTMOVE_GROUNDKICK:
TransformToNode(touchingNodePos, PED_FOOTR);
break;
+ case FIGHTMOVE_FWDRIGHT:
+ TransformToNode(touchingNodePos, PED_HEAD);
+ break;
+ case FIGHTMOVE_BACKKICK:
+ case FIGHTMOVE_BACKFLIP:
+ TransformToNode(touchingNodePos, PED_FOOTL);
+ break;
+ case FIGHTMOVE_BACKLEFT:
+ TransformToNode(touchingNodePos, PED_UPPERARML);
+ break;
+ default:
+ TransformToNode(touchingNodePos, PED_HANDR);
+ break;
}
- if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
- touchingNodePos += 0.1f * GetForward();
- } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) {
- touchingNodePos += 0.22f * GetForward();
- }
- FightStrike(touchingNodePos);
+ FightStrike(touchingNodePos, fightWithWeapon);
m_fightButtonPressure = 0;
return;
}
if (curMove.hitLevel != HITLEVEL_NULL) {
- if (animTime > curMove.endFireTime) {
+ if (animTime > curMove.endFireTime && weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE) {
if (IsPlayer())
currentAssoc->speed = 1.0f;
else
currentAssoc->speed = 0.8f;
}
- if (IsPlayer() && !nPlayerInComboMove) {
+ if (IsPlayer() && !nPlayerInComboMove && !fightWithWeapon) {
if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {
+ m_lastFightMove = m_curFightMove;
// Notice that it increases fight move index, because we're in combo!
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);
animAssoc->SetFinishCallback(FinishFightMoveCB, this);
animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);
+ animAssoc->speed = 0.8f;
m_fightButtonPressure = 0;
nPlayerInComboMove = 1;
}
}
- } else {
- if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) {
- if (IsPlayer())
- currentAssoc->speed = 1.3f;
- else
- currentAssoc->speed = 0.8f;
- }
}
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+
+ } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && !fightWithWeapon) {
EndFight(ENDFIGHT_FAST);
} else if (m_fightButtonPressure != 0) {
- bool canAffectMultiplePeople = true;
- nextAngle = m_fRotationCur;
- bool kickGround = false;
- float angleForGroundKick = 0.0f;
- CPed *pedOnGround = nil;
-
- Say(SOUND_PED_ATTACK);
-
- if (IsPlayer()) {
- canRoundhouse = false;
- punchOnly = false;
- canKick = true;
- nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- hasShoppingBags = false;
- canKneeHead = true;
- nPlayerInComboMove = 0;
- } else {
- nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- uint16 pedFeatures = m_pedStats->m_flags;
- punchOnly = pedFeatures & STAT_PUNCH_ONLY;
- canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
- canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD;
- canKick = pedFeatures & STAT_CAN_KICK;
- hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS;
- }
-
- // Attack isn't scripted, find the victim
- if (IsPlayer() || !m_pedInObjective) {
-
- for (int i = 0; i < m_numNearPeds; i++) {
-
- CPed *nearPed = m_nearPeds[i];
- float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude();
- if (nearPedDist < 3.0f) {
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- nearPed->GetPosition().x, nearPed->GetPosition().y,
- GetPosition().x, GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- float neededTurn = Abs(nextAngle - m_fRotationCur);
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- if (!nearPed->OnGroundOrGettingUp()) {
+ if (!IsPlayer())
+ Say(SOUND_PED_ATTACK);
- if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) {
- canAffectMultiplePeople = false;
- } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) {
+ if (m_curFightMove != FIGHTMOVE_IDLE)
+ m_lastFightMove = m_curFightMove;
- if (nearPedDist < 1.7f
- && neededTurn < DEGTORAD(35.0f)
- && (canKick || hasShoppingBags)) {
+ m_curFightMove = IsPlayer() ? ChooseAttackPlayer(m_fightButtonPressure, fightWithWeapon) : ChooseAttackAI(m_fightButtonPressure, fightWithWeapon);
- nextFightMove = FIGHTMOVE_KICK;
- if (hasShoppingBags) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- }
- canAffectMultiplePeople = false;
- } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_LONGKICK;
- } else if (neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- if (punchOnly)
- nextFightMove = FIGHTMOVE_PUNCHJAB;
-
- canAffectMultiplePeople = false;
- }
- } else if (!CGame::nastyGame
- || nearPedDist >= 1.3f
- || neededTurn >= DEGTORAD(55.0f)
- || punchOnly) {
-
- if (nearPedDist > 0.8f
- && nearPedDist < 3.0f
- && neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
-
- } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) {
- if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- }
-
- } else {
- pedOnGround = nearPed;
- kickGround = true;
- angleForGroundKick = nextAngle;
- }
- }
-
- if (!canAffectMultiplePeople) {
- m_fRotationDest = nextAngle;
- if (IsPlayer()) {
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(nearPed, true);
- SetLookTimer(1500);
- }
- break;
- }
- }
- } else {
- // Because we're in a scripted fight with some particular ped.
- canAffectMultiplePeople = false;
+ if (m_curFightMove != FIGHTMOVE_IDLE) {
- float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude();
- if (hasShoppingBags) {
- if (fightingPedDist >= 1.7f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- else
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay,
+ tFightMoves[m_curFightMove].animId, 8.0f);
- } else if (punchOnly) {
- if (fightingPedDist >= 1.3f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ if (weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE || m_curFightMove < FIGHTMOVE_MELEE1) {
+ if (m_curFightMove == FIGHTMOVE_BACKKICK)
+ animAssoc->speed = 1.15f;
else
- nextFightMove = FIGHTMOVE_PUNCHJAB;
-
- } else if (fightingPedDist >= 3.0f) {
- nextFightMove = FIGHTMOVE_STDPUNCH;
-
+ animAssoc->speed = 0.8f;
} else {
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- m_pedInObjective->GetPosition().x,
- m_pedInObjective->GetPosition().y,
- GetPosition().x,
- GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationDest = nextAngle;
- m_fRotationCur = m_fRotationDest;
- if (!m_pedInObjective->OnGroundOrGettingUp()) {
-
- if (fightingPedDist >= 0.8f || !canKneeHead) {
-
- if (fightingPedDist >= 1.3f) {
-
- if (fightingPedDist < 1.7f && canKick) {
- nextFightMove = FIGHTMOVE_KICK;
- if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
-
- } else if (fightingPedDist < 2.0f && canKick) {
- nextFightMove += 5; // Makes it 9 or 10
-
- } else {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
-
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- }
- }
- } else if (!CGame::nastyGame
- || fightingPedDist >= 1.3f
- || m_pedInObjective->IsPlayer()
- || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) {
- nextFightMove = FIGHTMOVE_IDLE;
- } else {
- nextFightMove = FIGHTMOVE_GROUNDKICK;
+ switch (GetWeapon()->m_eWeaponType) {
+ case WEAPONTYPE_SCREWDRIVER:
+ case WEAPONTYPE_KNIFE:
+ animAssoc->speed = 1.05f;
+ break;
+ case WEAPONTYPE_GOLFCLUB:
+ case WEAPONTYPE_NIGHTSTICK:
+ case WEAPONTYPE_BASEBALLBAT:
+ case WEAPONTYPE_HAMMER:
+ case WEAPONTYPE_KATANA:
+ animAssoc->speed = 0.8f;
+ break;
+ case WEAPONTYPE_CLEAVER:
+ case WEAPONTYPE_MACHETE:
+ animAssoc->speed = 0.9f;
+ break;
}
}
- }
- if (canAffectMultiplePeople) {
- if (kickGround && IsPlayer()) {
- m_fRotationDest = angleForGroundKick;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
- } else if (goForward) {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- } else {
- nextFightMove = FIGHTMOVE_STDPUNCH;
- }
- }
-
- if (nextFightMove != FIGHTMOVE_IDLE) {
- m_curFightMove = nextFightMove;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
-
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
- animAssoc->SetCurrentTime(0.0f);
animAssoc->SetRun();
+ if (!IsPlayer())
+ animAssoc->SetCurrentTime(0.0f);
}
+ if (IsPlayer())
+ animAssoc->SetCurrentTime(0.08f);
+
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
m_fightButtonPressure = 0;
}
m_fightState = FIGHTSTATE_NO_MOVE;
@@ -1413,6 +1567,7 @@ CPed::Fight(void)
#else
&& CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {
#endif
+ m_lastFightMove = m_curFightMove;
m_curFightMove = FIGHTMOVE_SHUFFLE_F;
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
@@ -1437,6 +1592,7 @@ CPed::Fight(void)
}
} else {
+ m_lastFightMove = m_curFightMove;
m_curFightMove = FIGHTMOVE_IDLE;
if (IsPlayer())
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
@@ -1445,6 +1601,332 @@ CPed::Fight(void)
}
}
+int32
+CPed::ChooseAttackAI(uint8 buttonPressure, bool fightWithWeapon)
+{
+ eWeaponType weapon = GetWeapon()->m_eWeaponType;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);
+ if (!fightWithWeapon && weapon != WEAPONTYPE_UNARMED && weapon != WEAPONTYPE_BRASSKNUCKLE) {
+ return FIGHTMOVE_PUNCH;
+ }
+
+ if (!m_pedInObjective)
+ return FIGHTMOVE_IDLE;
+ if (buttonPressure == 0)
+ return FIGHTMOVE_IDLE;
+
+ uint16 pedFeatures = m_pedStats->m_flags;
+ bool punchOnly = !!(pedFeatures & STAT_PUNCH_ONLY);
+ bool canRoundhouse = !!(pedFeatures & STAT_CAN_ROUNDHOUSE);
+ bool canKneeHead = !!(pedFeatures & STAT_CAN_KNEE_HEAD);
+ bool canKick = !!(pedFeatures & STAT_CAN_KICK);
+ bool hasShoppingBags = !!(pedFeatures & STAT_SHOPPING_BAGS);
+
+ CVector distVec(m_pedInObjective->GetPosition() - GetPosition());
+ float dist = distVec.Magnitude();
+ m_fRotationDest = CGeneral::LimitRadianAngle(distVec.Heading());
+ m_fRotationCur = m_fRotationDest;
+
+ if (fightWithWeapon) {
+ if (m_pedInObjective->OnGroundOrGettingUp()) {
+ if (CGame::nastyGame && dist < 1.2f && !m_pedInObjective->IsPlayer()
+ && (m_pedInObjective->m_nPedState == PED_DEAD || !m_pedInObjective->IsPedHeadAbovePos(-0.3f))) {
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_2ND))
+ return FIGHTMOVE_MELEE2;
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_3RD))
+ return FIGHTMOVE_MELEE3;
+
+ return FIGHTMOVE_GROUNDKICK;
+ } else {
+ return FIGHTMOVE_IDLE;
+ }
+ }
+ if (dist < 2.f) {
+ if (m_curFightMove == FIGHTMOVE_MELEE1) {
+ if (GetSecondFireAnim(weaponInfo))
+ return FIGHTMOVE_MELEE2;
+ }
+ if (m_curFightMove == FIGHTMOVE_MELEE2) {
+ if (GetFinishingAttackAnim(weaponInfo))
+ return FIGHTMOVE_MELEE3;
+ }
+ return FIGHTMOVE_MELEE1;
+ }
+ return FIGHTMOVE_SHUFFLE_F;
+ }
+ if (!hasShoppingBags) {
+ if (punchOnly) {
+ if (dist < 1.4f)
+ return FIGHTMOVE_PUNCH;
+ } else {
+ if (m_pedInObjective->OnGroundOrGettingUp()) {
+ if (CGame::nastyGame && dist < 1.2f && !m_pedInObjective->IsPlayer()
+ && (m_pedInObjective->m_nPedState == PED_DEAD || !m_pedInObjective->IsPedHeadAbovePos(-0.3f))) {
+
+ return FIGHTMOVE_GROUNDKICK;
+ } else {
+ return FIGHTMOVE_IDLE;
+ }
+ }
+ if (dist < 0.95f && canKneeHead)
+ return FIGHTMOVE_KNEE;
+ if (dist < 1.4f)
+ return FIGHTMOVE_PUNCH;
+ if (dist < 2.f && canKick) {
+ int nextMove = FIGHTMOVE_LONGKICK;
+ if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
+ nextMove = FIGHTMOVE_ROUNDHOUSE;
+ return nextMove;
+ }
+ }
+ return FIGHTMOVE_SHUFFLE_F;
+ }
+ if (dist < 2.f)
+ return FIGHTMOVE_ROUNDHOUSE;
+ else
+ return FIGHTMOVE_SHUFFLE_F;
+}
+
+int32
+CPed::ChooseAttackPlayer(uint8 buttonPressure, bool fightWithWeapon)
+{
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ const float maxAttackDist = 2.7f;
+ float weaponAttackDist = 2.0f;
+ CPed *victimPed = nil;
+ CPed *walkUpTo = nil;
+ CPed *groundAttackDeadPed = nil;
+ CPed *groundAttackAlivePed = nil;
+ if (fightWithWeapon)
+ weaponAttackDist = weaponInfo->m_fRange;
+
+ bool willWalkUp = false;
+ PedFightMoves choosenMove = FIGHTMOVE_IDLE;
+ int numPedsWeCanReach = 0;
+ if (m_takeAStepAfterAttack)
+ willWalkUp = true;
+
+ float groundAttackDeadAngle, groundAttackAliveAngle, walkAngle, victimAngle, distToVictim;
+
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
+ CVector distVec(nearPed->GetPosition() - GetPosition());
+ float dist = distVec.Magnitude();
+ if (dist < maxAttackDist) {
+ float nearPedAngle = CGeneral::LimitRadianAngle(distVec.Heading());
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float neededTurn = Abs(nearPedAngle - m_fRotationCur);
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ if (!nearPed->OnGroundOrGettingUp() && nearPed->m_nWaitState != WAITSTATE_SUN_BATHE_IDLE) {
+ if (!willWalkUp || neededTurn <= DEGTORAD(45.0f)) {
+
+ if (neededTurn <= DEGTORAD(30.0f) || nearPed->m_pedInObjective == this
+ && (nearPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || nearPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) {
+
+ if (dist < weaponAttackDist) {
+ if (!victimPed
+ || nearPed->m_attackTimer < victimPed->m_attackTimer && nearPed->m_attackTimer > CTimer::GetTimeInMilliseconds() - 100) {
+ victimPed = nearPed;
+ victimAngle = nearPedAngle;
+ distToVictim = dist;
+ }
+ ++numPedsWeCanReach;
+
+ } else {
+ if (neededTurn < DEGTORAD(30.0f)) {
+ walkUpTo = nearPed;
+ walkAngle = nearPedAngle;
+ }
+ }
+ }
+ }
+ } else if (CGame::nastyGame && dist < 1.2f && neededTurn < DEGTORAD(55.0f)) {
+ if (!nearPed->DyingOrDead() || groundAttackDeadPed) {
+ if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
+ groundAttackAlivePed = nearPed;
+ groundAttackAliveAngle = nearPedAngle;
+ }
+ } else {
+ groundAttackDeadPed = nearPed;
+ groundAttackDeadAngle = nearPedAngle;
+ }
+ ++numPedsWeCanReach;
+
+ } else if (dist > 1.4f && dist < maxAttackDist && neededTurn < DEGTORAD(30.0f)) {
+ if (!walkUpTo) {
+ walkUpTo = nearPed;
+ walkAngle = nearPedAngle;
+ }
+#ifdef FIX_BUGS
+ if(dist < 2.1f)
+#endif
+ ++numPedsWeCanReach;
+ }
+ }
+ }
+
+ if (victimPed) {
+ float adjustedAngleDiff = victimAngle - m_fRotationCur + DEGTORAD(30.0f);
+ if (adjustedAngleDiff < 0.0f)
+ adjustedAngleDiff += TWOPI;
+
+ int16 dir = Floor(adjustedAngleDiff / DEGTORAD(60.0f));
+
+ // Just focus on who we're fighting with, don't care peds on ground
+ if (numPedsWeCanReach < 2 || fightWithWeapon) {
+ float angleDiff = Abs(victimAngle - m_fRotationCur);
+ if (angleDiff > PI)
+ angleDiff = TWOPI - angleDiff;
+
+ if (angleDiff < DEGTORAD(60.0f))
+ dir = 0; // forward
+ }
+ int16 randVal = CGeneral::GetRandomNumber() & 3;
+ switch (dir) {
+ case 0: // forward
+ if (fightWithWeapon) {
+ if (distToVictim < 0.95f - 0.2f && m_nPedState == PED_FIGHT) {
+ choosenMove = FIGHTMOVE_KNEE;
+ } else {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CLEAVER) {
+ if (distToVictim < 0.85f * weaponInfo->m_fRange)
+ choosenMove = FIGHTMOVE_MELEE1;
+ else
+ choosenMove = FIGHTMOVE_SHUFFLE_F;
+ } else {
+ float weaponRange = weaponInfo->m_fRange;
+ if (distToVictim < 0.75f * weaponRange && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER) {
+ if (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) {
+ choosenMove = FIGHTMOVE_MELEE2;
+ } else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) {
+ choosenMove = FIGHTMOVE_MELEE3;
+ } else {
+ choosenMove = FIGHTMOVE_MELEE1;
+ }
+ } else if (distToVictim < weaponRange && GetFinishingAttackAnim(weaponInfo)) {
+ choosenMove = FIGHTMOVE_MELEE3;
+ } else {
+ choosenMove = FIGHTMOVE_SHUFFLE_F;
+ }
+ }
+ }
+ } else if (distToVictim < 0.95f && m_nPedState == PED_FIGHT) {
+ choosenMove = FIGHTMOVE_KNEE;
+
+ } else if (distToVictim < 1.4f) {
+ if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
+ choosenMove = FIGHTMOVE_PUNCH;
+
+ } else if (m_curFightMove != FIGHTMOVE_PUNCH || randVal != 1) {
+ if (randVal == 2)
+ choosenMove = FIGHTMOVE_PUNCH;
+ else
+ choosenMove = FIGHTMOVE_PUNCHJAB;
+ } else {
+ choosenMove = FIGHTMOVE_LONGKICK;
+ }
+ } else {
+ choosenMove = FIGHTMOVE_LONGKICK;
+ }
+ break;
+ case 1:
+ choosenMove = FIGHTMOVE_FWDLEFT;
+ break;
+ case 2:
+ choosenMove = FIGHTMOVE_BACKLEFT;
+ break;
+ case 3:
+ choosenMove = FIGHTMOVE_BACKKICK;
+ break;
+ case 4:
+ choosenMove = FIGHTMOVE_BACKRIGHT;
+ break;
+ default:
+ choosenMove = FIGHTMOVE_FWDRIGHT;
+ break;
+ }
+
+ // forward
+ if (dir == 0) {
+ m_fRotationDest = CGeneral::LimitRadianAngle(victimAngle);
+ } else {
+ m_fRotationDest = victimAngle - dir * DEGTORAD(60.0f);
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ }
+
+ m_fRotationCur = m_fRotationDest;
+ Say(SOUND_PED_ATTACK);
+
+ } else if (groundAttackAlivePed || groundAttackDeadPed) {
+ if (fightWithWeapon && weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_2ND)) {
+ choosenMove = FIGHTMOVE_MELEE2;
+ } else if (fightWithWeapon && weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_3RD)) {
+ choosenMove = FIGHTMOVE_MELEE3;
+ } else {
+ choosenMove = FIGHTMOVE_GROUNDKICK;
+ }
+ if (groundAttackAlivePed)
+ m_fRotationDest = groundAttackAliveAngle;
+ else
+ m_fRotationDest = groundAttackDeadAngle;
+
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ if (groundAttackAlivePed)
+ SetLookFlag(groundAttackAlivePed, 1, 0);
+ else
+ SetLookFlag(groundAttackDeadPed, 1, 0);
+
+ SetLookTimer(1500u);
+
+ } else if (walkUpTo) {
+ choosenMove = FIGHTMOVE_SHUFFLE_F;
+ m_fRotationCur = m_fRotationDest = walkAngle;
+ m_lookTimer = 0;
+ SetLookFlag(walkUpTo, true);
+ SetLookTimer(1500);
+
+ } else if (fightWithWeapon) {
+ // No enemy, fight with space
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SCREWDRIVER) {
+ choosenMove = FIGHTMOVE_MELEE3;
+ } else {
+ if (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) {
+ choosenMove = FIGHTMOVE_MELEE2;
+ } else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) {
+ choosenMove = FIGHTMOVE_MELEE3;
+ } else {
+ choosenMove = FIGHTMOVE_MELEE1;
+ }
+ }
+ } else {
+ // Max number GetRandomNumberInRange returns is max-1
+#ifdef FIX_BUGS
+ switch (CGeneral::GetRandomNumberInRange(0,4)) {
+#else
+ switch (CGeneral::GetRandomNumberInRange(0,3)) {
+#endif
+ case 0:
+ choosenMove = FIGHTMOVE_PUNCHJAB;
+ break;
+ case 1:
+ choosenMove = FIGHTMOVE_PUNCH;
+ break;
+ case 2:
+ choosenMove = FIGHTMOVE_LONGKICK;
+ break;
+ case 3:
+ choosenMove = FIGHTMOVE_KNEE;
+ break;
+ default:
+ break;
+ }
+ }
+ return choosenMove;
+}
+
void
CPed::EndFight(uint8 endType)
{
@@ -1454,6 +1936,9 @@ CPed::EndFight(uint8 endType)
m_curFightMove = FIGHTMOVE_NULL;
RestorePreviousState();
CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);
+
if (animAssoc)
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
@@ -1476,49 +1961,66 @@ CPed::EndFight(uint8 endType)
m_nWaitTimer = 0;
}
-
void
CPed::PlayHitSound(CPed *hitTo)
{
// That was very complicated to reverse for me...
- // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
+ // First index is our fight move ID (from 1 to 17, total 17), second is the one of we fight with (from 18 to 27, total 10).
enum {
- S33 = SOUND_FIGHT_PUNCH_33,
- S34 = SOUND_FIGHT_KICK_34,
- S35 = SOUND_FIGHT_HEADBUTT_35,
- S36 = SOUND_FIGHT_PUNCH_36,
- S37 = SOUND_FIGHT_PUNCH_37,
- S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
- S39 = SOUND_FIGHT_PUNCH_39,
- S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
- S41 = SOUND_FIGHT_PUNCH_41,
- S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
- S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
- S44 = SOUND_FIGHT_KICK_44,
+ S37 = SOUND_FIGHT_37,
+ S38 = SOUND_FIGHT_38,
+ S39 = SOUND_FIGHT_39,
+ S40 = SOUND_FIGHT_40,
+ S41 = SOUND_FIGHT_41,
+ S42 = SOUND_FIGHT_42,
+ S43 = SOUND_FIGHT_43,
+ S44 = SOUND_FIGHT_44,
+ S45 = SOUND_FIGHT_45,
+ S46 = SOUND_FIGHT_46,
+ S47 = SOUND_FIGHT_47,
+ S48 = SOUND_FIGHT_48,
NO_SND = SOUND_NO_SOUND
};
- uint16 hitSoundsByFightMoves[12][10] = {
- {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39},
- {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39},
- {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39},
- {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40},
- {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40},
- {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33}
+ const uint16 hitSoundsByFightMoves[17][10] = {
+ { S37, S46, S41, S41, S46, S46, S40, S41, S43, S40 },
+ { NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND },
+ { NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND },
+ { S46, S46, S46, S46, S37, S47, S37, S38, S43, S38 },
+ { S46, S46, S46, S46, S46, S46, S40, S41, S43, S46 },
+ { S46, S46, S46, S46, S46, S46, S40, S41, S43, S40 },
+ { S46, S46, S46, S46, S46, S46, S40, S41, S43, S40 },
+ { S46, S46, S37, S46, S37, S47, S40, S47, S43, S37 },
+ { S46, S46, S46, S46, S46, S46, S43, S44, S43, S43 },
+ { S37, S46, S46, S46, S38, S47, S40, S38, S43, S46 },
+ { S46, S37, S46, S37, S39, S46, S40, S39, S43, S37 },
+ { S46, S37, S46, S46, S38, S47, S40, S38, S43, S46 },
+ { S37, S37, S46, S46, S38, S47, S48, S38, S43, S37 },
+ { S46, S46, S46, S46, S37, S46, S40, S38, S43, S46 },
+ { S46, S46, S46, S37, S39, S46, S40, S39, S43, S46 },
+ { S37, S46, S46, S46, S37, S46, S40, S37, S43, S46 },
+ { S43, S43, S43, S43, S43, S43, S43, S43, S43, S43 }
};
- // This is why first dimension is between FightMove 1 and 12.
- if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
+ eWeaponType weapon = GetWeapon()->m_eWeaponType;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);
+ if (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE) {
+ if (m_curFightMove >= FIGHTMOVE_MELEE1) {
+ if (m_curFightMove == FIGHTMOVE_MELEE3) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
+ } else {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
+ }
+ return;
+ }
+ }
+
+ // This is why first dimension is between FightMove 1 and 17.
+ if (m_curFightMove <= FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
return;
uint16 soundId;
- // And this is why second dimension is between 13 and 22.
+ // And this is why second dimension is between 18 and 27.
if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {
soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];
@@ -1531,171 +2033,252 @@ CPed::PlayHitSound(CPed *hitTo)
}
if (soundId != NO_SND)
- DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | ENTITY_TYPE_PED);
}
bool
-CPed::FightStrike(CVector &touchedNodePos)
+CPed::FightStrike(CVector &touchedNodePos, bool fightWithWeapon)
{
- CColModel *ourCol;
+ CColModel *hisCol;
CVector attackDistance;
- ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
- float maxDistanceToBeBeaten;
+ float maxDistanceToBeat;
CPed *nearPed;
- int state = m_fightState;
- bool pedFound = false;
+ CVector extendedTouchPoint;
+
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float radius = tFightMoves[m_curFightMove].strikeRadius;
+ if (fightWithWeapon)
+ radius = weaponInfo->m_fRadius;
- if (state == FIGHTSTATE_JUST_ATTACKED)
+ if (m_fightState == FIGHTSTATE_JUST_ATTACKED)
return false;
- // Pointless code
- if (state > FIGHTSTATE_NO_MOVE)
- attackDistance = touchedNodePos - m_vecHitLastPos;
+ if (this == FindPlayerPed() && fightWithWeapon && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
+ CGlass::BreakGlassPhysically(touchedNodePos, radius);
for (int i = 0; i < m_numNearPeds; i++) {
+ int8 pedFound = 0;
nearPed = m_nearPeds[i];
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f;
+ if (!fightWithWeapon && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE)
+ maxDistanceToBeat = nearPed->GetBoundRadius() + radius + 0.1f;
else
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius;
+ maxDistanceToBeat = nearPed->GetBoundRadius() + radius;
- if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
+ if ((nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) && (m_pedInObjective != FindPlayerPed() || nearPed == FindPlayerPed())) {
CVector nearPedCentre;
+
+ // Have to animate a skinned clump because the initial col model is useless
+ hisCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(nearPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(nearPed->GetClump());
+
nearPed->GetBoundCentre(nearPedCentre);
CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
// He can beat us
- if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
-
-#ifdef PED_SKIN
- // Have to animate a skinned clump because the initial col model is useless
- if(IsClumpSkinned(GetClump()))
- ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump());
- else
-#endif
- if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) {
- ourCol = &CTempColModels::ms_colModelPedGroundHit;
- } else {
-#ifdef ANIMATE_PED_COL_MODEL
- ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(),
- RpClumpGetFrame(GetClump()));
-#else
- ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
-#endif
- }
+ if (sq(maxDistanceToBeat) > potentialAttackDistance.MagnitudeSqr()) {
- for (int j = 0; j < ourCol->numSpheres; j++) {
- attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
+ for (int j = 0; j < hisCol->numSpheres; j++) {
+ attackDistance = hisCol->spheres[j].center;
attackDistance -= touchedNodePos;
- CColSphere *ourPieces = ourCol->spheres;
- float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
+ CColSphere *hisPieces = hisCol->spheres;
+ maxDistanceToBeat = hisPieces[j].radius + radius;
// We can beat him too
if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
- pedFound = true;
- closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
+ FightHitPed(nearPed, touchedNodePos, attackDistance, hisPieces[j].piece);
+ pedFound = 1;
break;
}
}
}
+ if (!pedFound && !fightWithWeapon) {
+ extendedTouchPoint = touchedNodePos - GetPosition();
+ if (DotProduct(touchedNodePos - GetPosition(), nearPed->GetPosition() - GetPosition()) > 0.f) {
+ if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
+ extendedTouchPoint += tFightMoves[FIGHTMOVE_GROUNDKICK].extendReachMultiplier * GetForward();
+ } else {
+ extendedTouchPoint.x *= tFightMoves[m_curFightMove].extendReachMultiplier;
+ extendedTouchPoint.y *= tFightMoves[m_curFightMove].extendReachMultiplier;
+ }
+ pedFound = -1;
+ extendedTouchPoint += GetPosition();
+ }
+ }
+ if (pedFound == -1) {
+ CVector nearPedCentre = nearPed->GetBoundCentre();
+ if (sq(maxDistanceToBeat) > (nearPedCentre - extendedTouchPoint).MagnitudeSqr()) {
+
+ for (int j = 0; j < hisCol->numSpheres; j++) {
+ attackDistance = hisCol->spheres[j].center;
+ attackDistance -= extendedTouchPoint;
+ CColSphere* hisPieces = hisCol->spheres;
+ float maxDistanceToBeat2 = hisPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
+
+ // We can beat him too
+ if (sq(maxDistanceToBeat2) > attackDistance.MagnitudeSqr()) {
+ FightHitPed(nearPed, extendedTouchPoint, attackDistance, hisPieces[j].piece);
+ break;
+ }
+ }
+ }
+ }
}
- if (pedFound)
- break;
}
- if (pedFound) {
- if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP)
- return false;
- float oldVictimHealth = nearPed->m_fHealth;
- CVector bloodPos = 0.5f * attackDistance + touchedNodePos;
- int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+ if (m_fightState == FIGHTSTATE_NO_MOVE)
+ m_fightState = FIGHTSTATE_1;
+
+ m_vecHitLastPos = touchedNodePos;
+ return false;
+}
- CVector2D diff (GetPosition() - nearPed->GetPosition());
- int direction = nearPed->GetLocalDirection(diff);
- if (IsPlayer()) {
- if (((CPlayerPed*)this)->m_bAdrenalineActive)
- damageMult = 20;
- } else {
- damageMult *= m_pedStats->m_attackStrength;
+void
+CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dir, int16 piece)
+{
+ if (victim->IsPlayer() && victim->m_nPedState == PED_GETUP)
+ return;
+
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ bool fightingWithWeapon = false;
+ int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+
+ if (weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE)) {
+ fightingWithWeapon = true;
+ if (m_curFightMove >= FIGHTMOVE_MELEE1) {
+ damageMult = weaponInfo->m_nDamage;
+ if (m_curFightMove == FIGHTMOVE_MELEE3 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER)
+ damageMult *= 5;
}
+ }
- // Change direction if we used kick.
- if (m_curFightMove == FIGHTMOVE_KICK) {
- if (CGeneral::GetRandomNumber() & 1) {
- direction++;
- if (direction > 3)
- direction -= 4;
- }
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ damageMult = 20;
+ } else if (!fightingWithWeapon) {
+ damageMult *= m_pedStats->m_attackStrength;
+ }
+
+ float oldVictimHealth = victim->m_fHealth;
+ CVector bloodPos = 0.5f * dir + touchPoint;
+ CVector2D diff(GetPosition() - victim->GetPosition());
+ int direction = victim->GetLocalDirection(diff);
+
+ bool brassKnucklePunch = false;
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) {
+ if (m_curFightMove == FIGHTMOVE_PUNCHHOOK || m_curFightMove == FIGHTMOVE_PUNCHJAB || m_curFightMove == FIGHTMOVE_BACKLEFT ||
+ m_curFightMove == FIGHTMOVE_STDPUNCH || m_curFightMove == FIGHTMOVE_PUNCH) {
+ brassKnucklePunch = true;
+ damageMult *= 1.5f;
}
- nearPed->ReactToAttack(this);
+ }
+ victim->ReactToAttack(this);
+
+ // Mostly unused. if > 5, ANIM_HIT_BIGSTEP will be run, that's it.
+ int unk2;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&
+ !victim->IsPlayer() && !fightingWithWeapon)
+ unk2 = 101;
+ else
+ unk2 = damageMult;
+
+ victim->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
+ PlayHitSound(victim);
+ m_fightState = FIGHTSTATE_JUST_ATTACKED;
+ RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
- // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
- int unk2;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
- unk2 = 101;
+ if (!victim->DyingOrDead()) {
+ if(fightingWithWeapon)
+ victim->InflictDamage(this, GetWeapon()->m_eWeaponType, damageMult, (ePedPieceTypes)piece, direction);
else
- unk2 = damageMult;
+ victim->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, (ePedPieceTypes)piece, direction);
+ }
- nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
- PlayHitSound(nearPed);
- m_fightState = FIGHTSTATE_JUST_ATTACKED;
- RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
- if (!nearPed->DyingOrDead()) {
- nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
- }
+ if (CGame::nastyGame && weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE && m_curFightMove >= FIGHTMOVE_MELEE1
+ && victim->GetIsOnScreen()) {
- if (CGame::nastyGame
- && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM
- && nearPed->m_nPedState == PED_DIE
- && nearPed->GetIsOnScreen()) {
+ static float particleRightLen = 0.05f;
+ static float particleUpLen = 0.05f;
- // Just for blood particle. We will restore it below.
- attackDistance /= (10.0f * attackDistance.Magnitude());
- for(int i=0; i<4; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0);
- }
+ // Just for particles. We will restore it below.
+ dir /= (20.0f * dir.Magnitude());
+ if (m_curFightMove == FIGHTMOVE_MELEE1) {
+ float rightMult = -particleRightLen;
+ dir += particleUpLen * GetUp() + rightMult * GetRight();
+
+ } else if (m_curFightMove == FIGHTMOVE_MELEE2) {
+ float upMult = 2.0f * particleUpLen;
+ dir += particleRightLen * GetRight() + upMult * GetUp();
+ }
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
+ if (IsPlayer()) {
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
+ CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
}
- if (!nearPed->OnGround()) {
- float curVictimHealth = nearPed->m_fHealth;
+ if (!(CGeneral::GetRandomNumber() & 3)) {
+ CParticle::AddParticle(PARTICLE_TEST, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ } else if (CGame::nastyGame && (tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM || fightingWithWeapon)
+ && victim->GetIsOnScreen()) {
+
+ // Just for particles. We will restore it below.
+ dir /= (10.0f * dir.Magnitude());
+ for (int i = 0; i < 4; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (!fightingWithWeapon) {
+ if (!victim->OnGround()) {
+ float curVictimHealth = victim->m_fHealth;
if (curVictimHealth > 0.0f
- && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer()
- || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f
- || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer()
- || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) {
+ && (curVictimHealth < 30.0f && oldVictimHealth > 30.0f
+ || weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BRASSKNUCKLE && IsPlayer()
+ || victim->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN || brassKnucklePunch)) {
- nearPed->SetFall(0, (AnimationId)(direction + ANIM_STD_HIGHIMPACT_FRONT), 0);
- if (nearPed->m_nPedState == PED_FALL)
- nearPed->bIsStanding = false;
+ victim->SetFall(0, (AnimationId)(direction + ANIM_STD_HIGHIMPACT_FRONT), 0);
+ if (victim->m_nPedState == PED_FALL)
+ victim->bIsStanding = false;
}
}
- if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
- attackDistance = nearPed->GetPosition() - GetPosition();
- attackDistance.Normalise();
- attackDistance.z = 1.0f;
- nearPed->bIsStanding = false;
+ }
- float moveMult;
- if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
- moveMult = Min(damageMult * 0.6f, 4.0f);
+ if (victim->m_nPedState == PED_DIE || !victim->bIsStanding) {
+ dir = victim->GetPosition() - GetPosition();
+ dir.Normalise();
+ dir.z = 1.0f;
+ victim->bIsStanding = false;
+
+ float moveMult;
+ if (fightingWithWeapon) {
+ moveMult = Min(damageMult * 0.02f, 1.0f);
+ } else if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
+ moveMult = Min(damageMult * 0.6f, 4.0f);
+ } else {
+ if (victim->m_nPedState != PED_DIE || damageMult >= 20) {
+ moveMult = damageMult;
} else {
- if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
- moveMult = damageMult;
- } else {
- moveMult = Min(damageMult * 2.0f, 14.0f);
- }
+ moveMult = Min(damageMult * 2.0f, 14.0f);
}
-
- nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance);
}
- CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
+
+ victim->ApplyMoveForce(moveMult * 0.6 * dir);
}
- if (m_fightState == FIGHTSTATE_NO_MOVE)
- m_fightState = FIGHTSTATE_1;
+ if (weaponType != WEAPONTYPE_KNIFE && weaponType != WEAPONTYPE_MACHETE
+ && weaponType != WEAPONTYPE_KATANA && weaponType != WEAPONTYPE_CHAINSAW) {
- m_vecHitLastPos = touchedNodePos;
- return false;
+ if (victim->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victim, this, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victim, this, 2000);
+ } else {
+ if (victim->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victim, this, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victim, this, 2000);
+ }
}
void
@@ -1712,7 +2295,7 @@ CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
void
CPed::LoadFightData(void)
{
- float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
+ float startFireTime, endFireTime, comboFollowOnTime, strikeRadius, extendReachMultiplier;
int damage, flags;
char line[256], moveName[32], animName[32], hitLevel;
int moveId = 0;
@@ -1741,12 +2324,13 @@ CPed::LoadFightData(void)
sscanf(
&line[lp],
- "%s %f %f %f %f %c %s %d %d",
+ "%s %f %f %f %f %f %c %s %d %d",
moveName,
&startFireTime,
&endFireTime,
&comboFollowOnTime,
&strikeRadius,
+ &extendReachMultiplier,
&hitLevel,
animName,
&damage,
@@ -1759,6 +2343,7 @@ CPed::LoadFightData(void)
tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
tFightMoves[moveId].strikeRadius = strikeRadius;
+ tFightMoves[moveId].extendReachMultiplier = extendReachMultiplier;
tFightMoves[moveId].damage = damage;
tFightMoves[moveId].flags = flags;
@@ -1782,11 +2367,13 @@ CPed::LoadFightData(void)
break;
}
- if (strcmp(animName, "null") != 0) {
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
- tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
- } else {
- tFightMoves[moveId].animId = ANIM_STD_WALK;
+ if (strcmp(animName, "default") != 0) {
+ if (strcmp(animName, "null") != 0) {
+ animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
+ tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
+ } else {
+ tFightMoves[moveId].animId = ANIM_STD_WALK;
+ }
}
moveId++;
}
@@ -1827,7 +2414,7 @@ CPed::InvestigateEvent(void)
if (CTimer::GetTimeInMilliseconds() > m_chatTimer) {
if (m_chatTimer) {
- if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
+ if (m_eventType < EVENT_UNK)
SetWaitState(WAITSTATE_TURN180, nil);
m_chatTimer = 0;
@@ -1887,7 +2474,8 @@ CPed::InvestigateEvent(void)
} else if (CGeneral::GetRandomNumber() & 3) {
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_CAM, 4.0f);
SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
- Say(SOUND_PED_CHAT_EVENT);
+ if (!CGame::germanGame)
+ Say(SOUND_PED_CHAT_EVENT);
} else {
m_chatTimer = 0;
@@ -1936,7 +2524,8 @@ CPed::InvestigateEvent(void)
CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
}
- Say(SOUND_PED_CHAT_EVENT);
+ if (!CGame::germanGame)
+ Say(SOUND_PED_CHAT_EVENT);
}
break;
case EVENT_ICECREAM:
@@ -2003,14 +2592,17 @@ CPed::InvestigateEvent(void)
return;
}
+ bool willStandStill = false;
for (int i = 0; i < m_numNearPeds; i++) {
if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {
SetMoveState(PEDMOVE_STILL);
- return;
+ willStandStill = true;
+ break;
}
}
- SetMoveState(PEDMOVE_WALK);
+ if (!willStandStill)
+ SetMoveState(PEDMOVE_WALK);
}
}
@@ -2050,17 +2642,29 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
bool willLinger = false;
int random;
+ if (damagedBy == FindPlayerPed() && damagedBy != this && damage > 3.0f)
+ ++CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel;
+
if (player == this) {
if (!player->m_bCanBeDamaged)
return false;
+ if (damagedBy && damagedBy->IsPed() && ((CPed*)damagedBy)->m_nPedType == PEDTYPE_GANG7)
+ return false;
+
+ if ((method == WEAPONTYPE_FLAMETHROWER || method == WEAPONTYPE_MOLOTOV) && CWorld::Players[CWorld::PlayerInFocus].m_bFireproof)
+ return false;
+
player->AnnoyPlayerPed(false);
}
if (DyingOrDead())
return false;
- if (!bUsesCollision && method != WEAPONTYPE_DROWNING)
+ if (method == WEAPONTYPE_DROWNING && !bDrownsInWater)
+ return false;
+
+ if (!bUsesCollision && (!bInVehicle || m_nPedState != PED_DRIVING) && method != WEAPONTYPE_DROWNING)
return false;
if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&
@@ -2073,8 +2677,12 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
else
healthImpact = damage * m_pedStats->m_defendWeakness;
+ if (!IsPlayer() &&
+ (method == WEAPONTYPE_SCREWDRIVER || method == WEAPONTYPE_KNIFE || (method >= WEAPONTYPE_CLEAVER && method <= WEAPONTYPE_CHAINSAW)))
+ m_bleedCounter = 200;
+
bool detectDieAnim = true;
- if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
+ if (m_nPedState == PED_GETUP) {
if (!IsPedHeadAbovePos(-0.3f)) {
if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
dieAnim = ANIM_STD_HIT_FLOOR_FRONT;
@@ -2083,14 +2691,30 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
dieDelta *= 2.0f;
dieSpeed = 0.5f;
detectDieAnim = false;
- } else if (m_nPedState == PED_FALL) {
- dieAnim = ANIM_STD_NUM;
- detectDieAnim = false;
}
+ } else if (m_nPedState == PED_FALL) {
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);
+ if (!fallAssoc || fallAssoc->IsRunning()) {
+ if (fallAssoc && fallAssoc->blendDelta >= 0.0f)
+ dieAnim = ANIM_STD_NUM;
+ else
+ dieAnim = ANIM_STD_KO_FRONT;
+ } else {
+ if (fallAssoc->flags & ASSOC_FRONTAL)
+ dieAnim = ANIM_STD_HIT_FLOOR_FRONT;
+ else
+ dieAnim = ANIM_STD_HIT_FLOOR;
+
+ dieDelta *= 2.0f;
+ dieSpeed = 0.5f;
+ }
+ detectDieAnim = false;
}
+
if (detectDieAnim) {
switch (method) {
case WEAPONTYPE_UNARMED:
+ case WEAPONTYPE_BRASSKNUCKLE:
if (bMeleeProof)
return false;
@@ -2124,68 +2748,97 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
}
}
break;
+ case WEAPONTYPE_SCREWDRIVER:
+ case WEAPONTYPE_GOLFCLUB:
+ case WEAPONTYPE_NIGHTSTICK:
+ case WEAPONTYPE_KNIFE:
case WEAPONTYPE_BASEBALLBAT:
+ case WEAPONTYPE_HAMMER:
+ case WEAPONTYPE_CLEAVER:
+ case WEAPONTYPE_MACHETE:
+ case WEAPONTYPE_KATANA:
+ case WEAPONTYPE_CHAINSAW:
if (bMeleeProof)
return false;
- if (m_nPedState == PED_FALL) {
- if (IsPedHeadAbovePos(-0.3f)) {
- dieAnim = ANIM_STD_NUM;
+ if (method != WEAPONTYPE_KATANA ||
+ damagedBy != FindPlayerPed()
+ || FindPlayerPed()->m_nPedState != PED_FIGHT
+ || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE1 && FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2
+ || CGeneral::GetRandomNumber() & 3) {
+
+ if (m_nPedState == PED_FALL) {
+ if (IsPedHeadAbovePos(-0.3f)) {
+ dieAnim = ANIM_STD_NUM;
+ } else {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_STD_HIT_FLOOR_FRONT;
+ else
+ dieAnim = ANIM_STD_HIT_FLOOR;
+ dieDelta = dieDelta * 2.0f;
+ dieSpeed = 0.5f;
+ }
+ } else if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2) {
+ if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE3) {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_STD_HIGHIMPACT_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_STD_HIGHIMPACT_LEFT;
+ break;
+ case 2:
+ dieAnim = ANIM_STD_HIGHIMPACT_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_STD_HIGHIMPACT_RIGHT;
+ break;
+ default:
+ break;
+ }
+ } else {
+ dieAnim = ANIM_STD_KO_SHOT_STOMACH;
+ }
} else {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_STD_HIT_FLOOR_FRONT;
- else
- dieAnim = ANIM_STD_HIT_FLOOR;
- dieDelta = dieDelta * 2.0f;
- dieSpeed = 0.5f;
+ dieAnim = ANIM_STD_KO_SHOT_FACE;
}
} else {
- switch (direction) {
- case 0:
- dieAnim = ANIM_STD_HIGHIMPACT_FRONT;
- break;
- case 1:
- dieAnim = ANIM_STD_HIGHIMPACT_LEFT;
- break;
- case 2:
- dieAnim = ANIM_STD_HIGHIMPACT_BACK;
- break;
- case 3:
- dieAnim = ANIM_STD_HIGHIMPACT_RIGHT;
- break;
- default:
- break;
- }
+ dieAnim = ANIM_STD_KO_SHOT_FACE;
+ RemoveBodyPart(PED_HEAD, direction);
+ headShot = true;
+ willLinger = true;
}
break;
case WEAPONTYPE_COLT45:
- case WEAPONTYPE_UZI:
case WEAPONTYPE_SHOTGUN:
- case WEAPONTYPE_AK47:
- case WEAPONTYPE_M16:
+ case WEAPONTYPE_STUBBY_SHOTGUN:
+ case WEAPONTYPE_SPAS12_SHOTGUN:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
+ case WEAPONTYPE_M4:
+ case WEAPONTYPE_RUGER:
case WEAPONTYPE_SNIPERRIFLE:
+ case WEAPONTYPE_LASERSCOPE:
+ case WEAPONTYPE_M60:
+ case WEAPONTYPE_MINIGUN:
+ case WEAPONTYPE_UZI_DRIVEBY:
+
if (bBulletProof)
return false;
bool dontRemoveLimb;
if (IsPlayer() || bNoCriticalHits)
dontRemoveLimb = true;
- else {
- switch (method) {
- case WEAPONTYPE_SNIPERRIFLE:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_M16:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_SHOTGUN:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
- break;
- default:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
- break;
- }
- }
+ else if (method != WEAPONTYPE_M4 && method != WEAPONTYPE_RUGER && method != WEAPONTYPE_SNIPERRIFLE &&
+ method != WEAPONTYPE_LASERSCOPE) {
+ if (method == WEAPONTYPE_SHOTGUN)
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
+ else
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
+ } else
+ dontRemoveLimb = false;
if (dontRemoveLimb) {
if (method == WEAPONTYPE_SHOTGUN) {
@@ -2250,8 +2903,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
}
}
break;
- case WEAPONTYPE_ROCKETLAUNCHER:
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_ROCKETLAUNCHER:
case WEAPONTYPE_EXPLOSION:
if (bExplosionProof)
return false;
@@ -2348,7 +3001,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
default:
break;
}
- if (damagedBy) {
+ if (damagedBy && pedPiece != PEDPIECE_TORSO) {
CVehicle *vehicle = (CVehicle*)damagedBy;
if (method == WEAPONTYPE_RAMMEDBYCAR) {
float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
@@ -2407,6 +3060,16 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();
m_lastWepDam = method;
+ m_lastDamEntity = damagedBy;
+ }
+
+ if (method == WEAPONTYPE_FALL) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_LHS)) {
+ if (m_fHealth >= 1.0 && m_fHealth - healthImpact < 5.0f) {
+ m_fHealth = Min(m_fHealth, 5.0f);
+ return false;
+ }
+ }
}
if (m_fHealth - healthImpact >= 1.0f && !willLinger) {
@@ -2416,40 +3079,49 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
if (bInVehicle) {
if (method != WEAPONTYPE_DROWNING) {
-#ifdef VC_PED_PORTS
if (m_pMyVehicle) {
- if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) {
- if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
- }
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
- m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
- }
- if (m_pMyVehicle->CanPedExitCar()) {
- SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
- } else {
+ CVehicle* pVehicle = m_pMyVehicle;
+ bool bDone = false;
+ if (m_pMyVehicle->IsBike()) {
m_fHealth = 0.0f;
- if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
- SetRadioStation();
- m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ ((CBike*)m_pMyVehicle)->KnockOffRider(method, direction, this, false);
+ bDone = true;
+ } else {
+ if (m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR) {
+ if (m_pMyVehicle->pDriver == this) {
+ if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ }
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
+ m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
+ }
}
- SetDie(dieAnim, dieDelta, dieSpeed);
- /*
- if (damagedBy == FindPlayerPed() && damagedBy != this) {
- // PlayerInfo stuff
+ if (m_pMyVehicle->CanPedExitCar(true)) {
+ SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
+ } else {
+ m_fHealth = 0.0f;
+ if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
+ SetRadioStation();
+ m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ }
+ SetDie(dieAnim, dieDelta, dieSpeed);
+
+ if (damagedBy == FindPlayerPed() && damagedBy != this) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 10;
+ CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 5.f;
+ }
}
- */
}
- for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) {
- CPed* passenger = m_pMyVehicle->pPassengers[i];
+ for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) {
+ CPed* passenger = pVehicle->pPassengers[i];
if (passenger && passenger != this && damagedBy)
passenger->ReactToAttack(damagedBy);
}
- CPed *driverOfVeh = m_pMyVehicle->pDriver;
+ CPed *driverOfVeh = pVehicle->pDriver;
if (driverOfVeh && driverOfVeh != this && damagedBy)
driverOfVeh->ReactToAttack(damagedBy);
@@ -2459,8 +3131,9 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
} else {
CDarkel::RegisterKillNotByPlayer(this, method);
}
+ if (bDone)
+ return true;
}
-#endif
m_fHealth = 1.0f;
return false;
}
@@ -2475,15 +3148,18 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
SetDie(dieAnim, dieDelta, dieSpeed);
if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {
-
- // There are PlayerInfo stuff here in VC
CDarkel::RegisterKillByPlayer(this, method, headShot);
+ CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 10;
+ CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 5.f;
m_threatEntity = player;
} else {
CDarkel::RegisterKillNotByPlayer(this, method);
}
- if (method == WEAPONTYPE_DROWNING)
+ if (method == WEAPONTYPE_DROWNING) {
bIsInTheAir = false;
+ if (FindPlayerPed() == this)
+ CStats::TimesDrowned++;
+ }
return true;
}
@@ -2535,25 +3211,8 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
frame = m_pFrames[nodeId]->frame;
if (frame) {
if (CGame::nastyGame) {
-#ifdef PED_SKIN
- if(!IsClumpSkinned(GetClump()))
-#endif
- {
-#ifdef DEBUGMENU
- if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
-#else
- if (nodeId != PED_HEAD)
-#endif
- SpawnFlyingComponent(nodeId, direction);
-
- RecurseFrameChildrenVisibilityCB(frame, nil);
- }
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- TransformToNode(pos, PED_HEAD);
-
if (CEntity::GetIsOnScreen()) {
+ m_pedIK.GetComponentPosition(pos, nodeId);
CParticle::AddParticle(PARTICLE_TEST, pos,
CVector(0.0f, 0.0f, 0.0f),
nil, 0.1f, 0, 0, 0, 0);
@@ -2576,87 +3235,11 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
CObject*
CPed::SpawnFlyingComponent(int pedNode, int8 direction)
{
- if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
- return nil;
-
-#ifdef PED_SKIN
- assert(!IsClumpSkinned(GetClump()));
-#endif
-
- CObject *obj = new CObject();
- if (!obj)
- return nil;
-
- RwFrame *frame = RwFrameCreate();
- RpClump *clump = RpClumpCreate();
- RpClumpSetFrame(clump, frame);
- RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame);
- *RwFrameGetMatrix(frame) = *matrix;
-
- flyingClumpTemp = clump;
- RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame);
- RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame);
- flyingClumpTemp = nil;
- switch (pedNode) {
- case PED_HEAD:
- // So popping head would have wheel collision. They disabled it anyway
- obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
- break;
- case PED_UPPERARML:
- case PED_UPPERARMR:
- obj->SetModelIndexNoCreate(MI_BODYPARTB);
- obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
- break;
- case PED_UPPERLEGL:
- case PED_UPPERLEGR:
- obj->SetModelIndexNoCreate(MI_BODYPARTA);
- obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
- break;
- default:
- break;
- }
- obj->RefModelInfo(GetModelIndex());
- obj->AttachToRwObject((RwObject*)clump);
- obj->m_fMass = 15.0f;
- obj->m_fTurnMass = 5.0f;
- obj->m_fAirResistance = 0.99f;
- obj->m_fElasticity = 0.03f;
- obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
- obj->ObjectCreatedBy = TEMP_OBJECT;
- obj->SetIsStatic(false);
- obj->bIsPickup = false;
- obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX;
-
- // life time - the more objects the are, the shorter this one will live
- CObject::nNoTempObjects++;
- if (CObject::nNoTempObjects > 20)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
- else if (CObject::nNoTempObjects > 10)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
- else
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
-
- CVector localForcePos, forceDir;
-
- if (direction == 2) {
- obj->m_vecMoveSpeed = 0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = GetForward();
- } else {
- obj->m_vecMoveSpeed = -0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = -GetForward();
- }
- obj->ApplyTurnForce(forceDir, localForcePos);
- CWorld::Add(obj);
-
- return obj;
+ // VC doesn't have detachable limbs :shrug:
+ return nil;
}
+// III leftover and unused
void
CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
{
@@ -2671,12 +3254,13 @@ CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
// BUG: This condition will always return true. Even fixing it won't work, because these states are unused.
// if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
- SetDie(ANIM_STD_KO_FRONT, 4.0f, 0.0f);
+ SetDie();
// }
bBodyPartJustCameOff = true;
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;
+ RemoveBodyPart(PED_HEAD, 0);
CParticle::AddParticle(PARTICLE_TEST, pos2,
CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);
@@ -2697,30 +3281,6 @@ CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
}
}
-uint8
-CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
-{
-#ifdef FIX_BUGS
- return 1;
-#else
- uint8 retVal = 2;
-
- float headZ = GetNodePosition(PED_HEAD).z;
-
- if (m_nPedState == PED_FALL)
- retVal = 1;
-
- float colZ = colPoint.point.z;
- if (colZ < headZ)
- retVal = 1;
-
- if (headZ + 0.2f <= colZ)
- retVal = 0;
-
- return retVal;
-#endif
-}
-
bool
CPed::IsPedHeadAbovePos(float zOffset)
{
@@ -2790,6 +3350,15 @@ CPed::CollideWithPed(CPed *collideWith)
int waitTime = 0;
if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
+ if (m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {
+ SetGetUp();
+ return;
+ }
+ if (collideWith->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {
+ collideWith->SetGetUp();
+ return;
+ }
+
bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
@@ -2797,10 +3366,8 @@ CPed::CollideWithPed(CPed *collideWith)
if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
&& (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
-#ifdef VC_PED_PORTS
|| m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith
- || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
-#endif
+ || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
)) {
if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
@@ -2829,14 +3396,55 @@ CPed::CollideWithPed(CPed *collideWith)
SetDirectionToWalkAroundObject(collideWith);
}
} else {
- if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
- || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
- (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
- SetDirectionToWalkAroundObject(collideWith);
- if (!weAreMissionChar)
- Say(SOUND_PED_CHAT);
+ if (FindPlayerPed() != m_pedInObjective
+ || m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ || collideWith == m_pedInObjective) {
+
+ if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
+ || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
+ (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
+ SetDirectionToWalkAroundObject(collideWith);
+ if (!weAreMissionChar)
+ Say(SOUND_PED_CHAT);
+ } else {
+ SetEvasiveStep(collideWith, 2);
+ }
+ } else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee()
+ && collideWith->m_pedInObjective == m_pedInObjective) {
+
+ int colliderIndexAtPlayersKillList = -1;
+ int ourIndexAtPlayersKillList = -1;
+ for (int i = 0; i < ARRAY_SIZE(((CPlayerPed*)m_pedInObjective)->m_pMeleeList); i++) {
+ CPed *pedInKillList = ((CPlayerPed*)m_pedInObjective)->m_pMeleeList[i];
+ if (pedInKillList == this) {
+ ourIndexAtPlayersKillList = i;
+ } else if (pedInKillList == collideWith) {
+ colliderIndexAtPlayersKillList = i;
+ }
+ }
+ bool weAreCloserToTargetThenCollider = false;
+ if ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D())
+ weAreCloserToTargetThenCollider = true;
+
+ if (ourIndexAtPlayersKillList > 0 && !weAreCloserToTargetThenCollider) {
+ if (colliderIndexAtPlayersKillList > 0) {
+ int time = 300;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+
+ } else if (collideWith->m_pedInObjective == FindPlayerPed()) {
+ ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
+ int time = 500;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ } else if (!weAreCloserToTargetThenCollider) {
+ int time = 300;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
} else {
- SetEvasiveStep(collideWith, 2);
+ SetDirectionToWalkAroundObject(collideWith);
}
}
} else {
@@ -2851,20 +3459,14 @@ CPed::CollideWithPed(CPed *collideWith)
} else {
TurnBody();
SetAttack(collideWith);
-#ifdef VC_PED_PORTS
m_fRotationCur = 0.3f + m_fRotationCur;
m_fRotationDest = m_fRotationCur;
-#endif
}
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
}
}
} else {
-#ifdef VC_PED_PORTS
if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#else
- if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#endif
if (heLooksToUs) {
SetEvasiveStep(collideWith, 1);
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
@@ -2873,11 +3475,8 @@ CPed::CollideWithPed(CPed *collideWith)
if (m_pedStats != collideWith->m_pedStats) {
- if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper
-#ifdef VC_PED_PORTS
- || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer
-#endif
- ) {
+ if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper || collideWith->IsPlayer()
+ || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) {
if (collideWith->IsPlayer()) {
// He's on our right side
@@ -2897,9 +3496,7 @@ CPed::CollideWithPed(CPed *collideWith)
TurnBody();
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PARTIAL_PUNCH, 8.0f);
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
-#ifdef VC_PED_PORTS
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
-#endif
if (!heIsMissionChar) {
CVector2D posDiff2D(posDiff);
int direction = collideWith->GetLocalDirection(posDiff2D);
@@ -2909,11 +3506,9 @@ CPed::CollideWithPed(CPed *collideWith)
}
}
}
- } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
-#ifdef VC_PED_PORTS
- || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
-#endif
- ) {
+ } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar ||
+ m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness) {
+
// He looks us and we're not at his right side
if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
CVector moveForce = GetRight();
@@ -2943,7 +3538,7 @@ CPed::CollideWithPed(CPed *collideWith)
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
if (m_nPedState == PED_ATTACK)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);
}
} else {
// We're at his right side
@@ -2966,7 +3561,7 @@ CPed::CollideWithPed(CPed *collideWith)
}
if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);
collideWith->SetFall(3000, animToPlay, 0);
}
@@ -3019,8 +3614,8 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
eWeaponType killMethod;
if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
- if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
- this->m_pCollidingEntity = car;
+ if (!m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
+ m_pCollidingEntity = car;
return;
}
@@ -3028,7 +3623,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
return;
if (m_pCurSurface) {
- if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
+ if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->IsBoat()|| IsPlayer()))
return;
}
@@ -3090,7 +3685,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
// carFrontAndDistDotProd <= 0.0 car looks to us
- if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
+ if ((carFrontAndDistDotProd <= 0.1 || randVal <= 1) && randVal != 0) {
killMethod = WEAPONTYPE_RUNOVERBYCAR;
nodeToDamage = PED_HEAD;
m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
@@ -3135,7 +3730,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
// TODO: What are we doing down here?
float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
- // After this point, distVec isn't distVec anymore.
+ // After this point distVec isn't really distVec.
distVec = car->m_vecMoveSpeed;
distVec.Normalise();
distVec *= 0.2 * unknown;
@@ -3150,7 +3745,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
if (damageDir > 3)
damageDir = damageDir - 4;
- if (car->m_vehType == VEHICLE_TYPE_CAR) {
+ if (car->IsCar()) {
CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
if (bonnet) {
@@ -3199,9 +3794,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
distVec.Normalise();
-#ifdef VC_PED_PORTS
distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
car->ApplyMoveForce(distVec * -100.0f);
Say(SOUND_PED_DEFEND);
@@ -3220,7 +3813,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
SetFall(1000, (AnimationId)(fallDirection + ANIM_STD_HIGHIMPACT_FRONT), true);
if (OnGround() && !m_pCollidingEntity &&
- (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
+ (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
m_pCollidingEntity = car;
}
@@ -3231,15 +3824,11 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
}
m_vecMoveSpeed.z = 0.0f;
distVec.Normalise();
-#ifdef VC_PED_PORTS
distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
car->ApplyMoveForce(distVec * -60.0f);
Say(SOUND_PED_DEFEND);
}
-#ifdef VC_PED_PORTS
- // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
if (IsGangMember()) {
CPed *driver = car->pDriver;
if (driver && driver->IsPlayer()
@@ -3250,5 +3839,347 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
RegisterThreatWithGangPeds(driver);
}
}
-#endif
-} \ No newline at end of file
+}
+
+void
+CPed::DriveVehicle(void)
+{
+ if (bOffscreen)
+ return;
+
+ CVehicle *veh = m_pMyVehicle;
+ if (veh->IsBike()) {
+ CBike *bike = (CBike*)veh;
+ float blendDelta = 1.0f;
+ float targetUDLean = 0.0f;
+ CAnimBlendAssociation *leftAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEFT);
+ CAnimBlendAssociation *rightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_RIGHT);
+ CAnimBlendAssociation *stillAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_READY);
+ CAnimBlendAssociation *fwdAssoc, *backAssoc;
+ if (IsPlayer()) {
+ fwdAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEANF);
+ backAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEANB);
+ }
+ CAnimBlendAssociation *walkbackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_WALKBACK);
+ CAnimBlendAssociation *drivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_LHS);
+ if (!drivebyAssoc)
+ drivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_RHS);
+ if (!drivebyAssoc)
+ drivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);
+
+ float velocityFwdDotProd = DotProduct(bike->m_vecMoveSpeed, bike->GetForward());
+ if (m_vecTurnSpeed.MagnitudeSqr() > 0.09f) {
+ bike->KnockOffRider(WEAPONTYPE_FALL, 2, this, false);
+ if (bike->pPassengers[0])
+ bike->KnockOffRider(WEAPONTYPE_FALL, 2, bike->pPassengers[0], false);
+ return;
+ }
+ if (!drivebyAssoc && Abs(velocityFwdDotProd) < 0.02f) {
+ if (!stillAssoc || stillAssoc->blendAmount < 1.0 && stillAssoc->blendDelta <= 0.0) {
+ stillAssoc = CAnimManager::BlendAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_READY, 2.0f);
+ }
+ } else {
+ if (velocityFwdDotProd >= 0.0f) {
+ if (stillAssoc && stillAssoc->blendDelta >= 0.0f)
+ stillAssoc->blendDelta = -4.0f;
+ if (walkbackAssoc && walkbackAssoc->blendDelta >= 0.0f)
+ walkbackAssoc->blendDelta = -4.0f;
+ } else {
+ float maxReverseSpeed = bike->pHandling->Transmission.fMaxReverseVelocity;
+ if (3.5f * maxReverseSpeed > velocityFwdDotProd && (bike->m_nWheelsOnGround || bike->GetUp().z < -0.5f)) {
+ bike->KnockOffRider(WEAPONTYPE_FALL, 2, this, false);
+ if (bike->pPassengers[0])
+ bike->KnockOffRider(WEAPONTYPE_FALL, 2, bike->pPassengers[0], false);
+ return;
+ }
+ if (bike->m_fGasPedal >= 0.0 || velocityFwdDotProd <= maxReverseSpeed * 1.5) {
+ if (IsPlayer() && velocityFwdDotProd < maxReverseSpeed * 1.5)
+ targetUDLean = -1.0f;
+
+ if (stillAssoc && stillAssoc->blendDelta >= 0.0f)
+ stillAssoc->blendDelta = -4.0f;
+
+ if (walkbackAssoc && walkbackAssoc->blendDelta >= 0.0f) {
+ walkbackAssoc->blendDelta = -4.0f;
+ }
+ } else if (!walkbackAssoc || walkbackAssoc->blendAmount < 1.0f && walkbackAssoc->blendDelta <= 0.0f) {
+ walkbackAssoc = CAnimManager::BlendAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_WALKBACK, 4.0f);
+ }
+ }
+ }
+ if (stillAssoc)
+ blendDelta -= Min(1.0f, CTimer::GetTimeStepNonClipped() * 0.02f * stillAssoc->blendDelta + stillAssoc->blendAmount);
+
+ if (drivebyAssoc)
+ blendDelta -= Min(blendDelta, CTimer::GetTimeStepNonClipped() * 0.02f * drivebyAssoc->blendDelta + drivebyAssoc->blendAmount);
+
+ if (walkbackAssoc)
+ blendDelta -= Min(blendDelta, CTimer::GetTimeStepNonClipped() * 0.02f * walkbackAssoc->blendDelta + walkbackAssoc->blendAmount);
+
+ float targetLRLean, timeBlend, neededAngForWheelie, stoppieAng;
+
+ // Smooth the lean amount
+ if (targetUDLean == -1.0f) {
+ targetLRLean = 0.0f;
+ timeBlend = Pow(0.86f, CTimer::GetTimeStep());
+ } else {
+ targetLRLean = Clamp(bike->m_fLeanLRAngle / bike->pBikeHandling->fFullAnimLean, -1.0f, 1.0f);
+ timeBlend = Pow(0.86f, CTimer::GetTimeStep());
+ }
+
+ bike->m_fPedLeanAmountLR = bike->m_fPedLeanAmountLR * timeBlend + (1.0 - timeBlend) * targetLRLean;
+
+ if (!IsPlayer()) {
+ targetUDLean = 0.0f;
+
+ } else if (targetUDLean > -1.0f) {
+ targetUDLean = bike->m_fLeanInput;
+ bike->bWheelieCam = false;
+ neededAngForWheelie = 1.0f;
+ if (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f || bike->GetForward().z <= 0.0f ||
+ (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) {
+
+ if (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3] &&
+ (bike->GetForward().z < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) {
+
+ stoppieAng = bike->pBikeHandling->fStoppieAng;
+ if (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng)
+ bike->bWheelieCam = true;
+ }
+ } else {
+ float wheelieAng = bike->pBikeHandling->fWheelieAng;
+ neededAngForWheelie = wheelieAng - bike->GetForward().z;
+ if (neededAngForWheelie < wheelieAng / 2.f)
+ bike->bWheelieCam = true;
+ }
+ if (neededAngForWheelie >= 0.15f) {
+ if (bike->m_fBrakePedal <= 0.5f || velocityFwdDotProd <= 0.01f) {
+ if (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fMaxCruiseVelocity > velocityFwdDotProd) {
+ targetUDLean = Min(0.1f, targetUDLean);
+ }
+ } else {
+ targetUDLean = Max(0.1f, targetUDLean);
+ }
+ } else {
+ targetUDLean = Max(0.25f, targetUDLean);
+ }
+ float targetLRLeanABS = Abs(targetLRLean);
+ if (targetLRLeanABS > 0.3f) {
+ // Yes, UD
+ targetUDLean *= Max(0.0f, 1.0f - (targetLRLeanABS - 0.3f) * 50.f / 13.f);
+ }
+ }
+ if (IsPlayer()) {
+ float timeBlend = Pow(0.89f, CTimer::GetTimeStep());
+ bike->m_fPedLeanAmountUD = (timeBlend * bike->m_fPedLeanAmountUD) + ((1.0f - timeBlend) * targetUDLean);
+ } else {
+ bike->m_fPedLeanAmountUD = 0.0f;
+ }
+
+ float fwdBackLeanAmount, leftRightLeanAmount;
+ if (Abs(bike->m_fPedLeanAmountLR) <= 0.56f && IsPlayer()) {
+
+ if (Abs(bike->m_fPedLeanAmountUD) <= 0.56f) {
+ CVector2D smoothedLean(bike->m_fPedLeanAmountLR, bike->m_fPedLeanAmountUD);
+ float smoothLeanMag = smoothedLean.Magnitude();
+ if (smoothLeanMag <= 0.01f) {
+ fwdBackLeanAmount = Abs(smoothedLean.y);
+ leftRightLeanAmount = Abs(smoothedLean.x);
+ } else {
+ fwdBackLeanAmount = Abs(smoothedLean.y / smoothLeanMag);
+ leftRightLeanAmount = Abs(smoothedLean.x / smoothLeanMag);
+ }
+ } else {
+ fwdBackLeanAmount = 1.0f;
+ leftRightLeanAmount = 0.0f;
+ }
+ } else {
+ fwdBackLeanAmount = 0.0f;
+ leftRightLeanAmount = 1.0f;
+ }
+ float fwdBackBlend = fwdBackLeanAmount * blendDelta;
+ float leftRightBlend = leftRightLeanAmount * blendDelta;
+ if (IsPlayer()) {
+ if (!fwdAssoc)
+ fwdAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEANF);
+ if (!backAssoc)
+ backAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEANB);
+
+ if (bike->m_fPedLeanAmountUD < 0.0f) {
+ backAssoc->blendAmount = fwdBackBlend;
+ backAssoc->SetCurrentTime(-(bike->m_fPedLeanAmountUD * backAssoc->hierarchy->totalLength));
+ backAssoc->flags &= ~ASSOC_RUNNING;
+ fwdAssoc->blendAmount = 0.0f;
+ } else {
+ fwdAssoc->blendAmount = fwdBackBlend;
+ fwdAssoc->SetCurrentTime(bike->m_fPedLeanAmountUD* fwdAssoc->hierarchy->totalLength);
+ fwdAssoc->flags &= ~ASSOC_RUNNING;
+ backAssoc->blendAmount = 0.0f;
+ }
+ }
+ if (!leftAssoc)
+ leftAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEFT);
+ if (!rightAssoc)
+ rightAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_RIGHT);
+
+ if (bike->m_fPedLeanAmountLR < 0.0f) {
+ leftAssoc->blendAmount = leftRightBlend;
+ leftAssoc->SetCurrentTime(-(bike->m_fPedLeanAmountLR * leftAssoc->hierarchy->totalLength));
+ leftAssoc->flags &= ~ASSOC_RUNNING;
+ rightAssoc->blendAmount = 0.0f;
+ } else {
+ rightAssoc->blendAmount = leftRightBlend;
+ rightAssoc->SetCurrentTime(bike->m_fPedLeanAmountLR* rightAssoc->hierarchy->totalLength);
+ rightAssoc->flags &= ~ASSOC_RUNNING;
+ leftAssoc->blendAmount = 0.0f;
+ }
+ if (velocityFwdDotProd > 0.3f) {
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+ RwV3d Yaxis = { 0.0f, 1.0f, 0.0f };
+ RtQuatRotate(&m_pFrames[PED_HEAD]->hanimFrame->q, &Xaxis, CGeneral::GetRandomNumberInRange(-6.0f * velocityFwdDotProd, 6.0f * velocityFwdDotProd), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_HEAD]->hanimFrame->q, &Yaxis, CGeneral::GetRandomNumberInRange(-6.0f * velocityFwdDotProd, 6.0f * velocityFwdDotProd), rwCOMBINEPOSTCONCAT);
+ bDontAcceptIKLookAts = true;
+ }
+ return;
+ }
+
+ if (!IsPlayer())
+ return;
+
+ float steerAngle = m_pMyVehicle->m_fSteerAngle;
+ CAnimBlendAssociation* lDriveAssoc;
+ CAnimBlendAssociation* rDriveAssoc;
+ CAnimBlendAssociation* lbAssoc;
+ CAnimBlendAssociation* sitAssoc;
+ if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE);
+
+ if (!sitAssoc || sitAssoc->blendAmount < 1.0f) {
+ return;
+ }
+
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE_LEFT);
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE_RIGHT);
+ lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_LOOKBEHIND);
+ } else if (m_pMyVehicle->bLowVehicle) {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_LO);
+
+ if (!sitAssoc || sitAssoc->blendAmount < 1.0f) {
+ return;
+ }
+
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_LEFT_LO);
+ lbAssoc = nil;
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_RIGHT_LO);
+ } else {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT);
+
+ if (!sitAssoc || sitAssoc->blendAmount < 1.0f) {
+ return;
+ }
+
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_LEFT);
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_RIGHT);
+ lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_LOOKBEHIND);
+ }
+
+ if (lbAssoc &&
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON
+ && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) {
+ lbAssoc->blendDelta = -1000.0f;
+ }
+
+ CAnimBlendAssociation* driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT);
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT);
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT_LO);
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT_LO);
+
+ if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc ||
+ m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) {
+ if (steerAngle == 0.0f || driveByAssoc) {
+ if (lDriveAssoc)
+ lDriveAssoc->blendAmount = 0.0f;
+ if (rDriveAssoc)
+ rDriveAssoc->blendAmount = 0.0f;
+
+ } else if (steerAngle <= 0.0f) {
+ if (lDriveAssoc)
+ lDriveAssoc->blendAmount = 0.0f;
+
+ if (rDriveAssoc)
+ rDriveAssoc->blendAmount = Clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f);
+ else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE_RIGHT);
+ else if (m_pMyVehicle->bLowVehicle)
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_RIGHT_LO);
+ else
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_RIGHT);
+
+ } else {
+ if (rDriveAssoc)
+ rDriveAssoc->blendAmount = 0.0f;
+
+ if (lDriveAssoc)
+ lDriveAssoc->blendAmount = Clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f);
+ else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE_LEFT);
+ else if (m_pMyVehicle->bLowVehicle)
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_LEFT_LO);
+ else
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_LEFT);
+ }
+
+ if (lbAssoc)
+ lbAssoc->blendDelta = -4.0f;
+ } else {
+
+ if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON
+ || TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT)
+ && (!lbAssoc || lbAssoc->blendAmount < 1.0f && lbAssoc->blendDelta <= 0.0f)) {
+
+ if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_LOOKBEHIND, 4.0f);
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_LOOKBEHIND, 4.0f);
+ }
+ }
+}
+
+void
+CPed::RemoveWeaponAnims(int unused, float animDelta)
+{
+ CAnimBlendAssociation *weaponAssoc;
+ //CWeaponInfo::GetWeaponInfo(unused);
+
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_2ND);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_3RD);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_RELOAD);
+ if (weaponAssoc) {
+ weaponAssoc->blendDelta = animDelta;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);
+ if (weaponAssoc) {
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (weaponAssoc->flags & ASSOC_PARTIAL)
+ weaponAssoc->blendDelta = animDelta;
+ else
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, -animDelta);
+ }
+}