summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/Ped.cpp871
-rw-r--r--src/peds/Ped.h78
-rw-r--r--src/peds/PedIK.cpp3
-rw-r--r--src/peds/PedIK.h2
4 files changed, 821 insertions, 133 deletions
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index c0c49751..fb9b778f 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -29,6 +29,8 @@
#include "Darkel.h"
#include "PathFind.h"
#include "ModelIndices.h"
+#include "FileMgr.h"
+#include "TempColModels.h"
WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); }
WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); }
@@ -48,11 +50,16 @@ WRAPPER void CPed::SetSeek(CVector, float) { EAXJMP(0x4D14B0); }
WRAPPER bool CPed::Seek(void) { EAXJMP(0x4D1640); }
WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); }
WRAPPER void CPed::RemoveInCarAnims(void) { EAXJMP(0x4E4E20); }
+WRAPPER void CPed::SetWaitState(eWaitState, void*) { EAXJMP(0x4D58D0); }
+WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); }
+WRAPPER void CPed::PlayHitSound(CPed*) { EAXJMP(0x4E8E20); }
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
bool &CPed::bPedCheat3 = *(bool*)0x95CD59;
CColPoint &CPed::ms_tempColPoint = *(CColPoint*)0x62DB14;
+uint16 &CPed::unknownFightThing = *(uint16*)0x95CC58;
+FightMove (&CPed::ms_fightMoves)[24] = * (FightMove(*)[24]) * (uintptr*)0x5F9844;
uint16 &CPed::distanceMultToCountPedNear = *(uint16*)0x5F8C98;
@@ -339,7 +346,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_nPedState = PED_IDLE;
m_nLastPedState = PED_NONE;
m_nMoveState = PEDMOVE_STILL;
- m_nStoredActionState = 0;
+ m_nStoredMoveState = PEDMOVE_NONE;
m_pFire = nil;
m_pPointGunAt = nil;
m_pLookTarget = nil;
@@ -384,7 +391,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bRespondsToThreats = true;
bRenderPedInCar = true;
bChangedSeat = false;
- m_ped_flagC10 = false;
+ bUpdateAnimHeading = false;
bBodyPartJustCameOff = false;
m_ped_flagC40 = false;
m_ped_flagC80 = false;
@@ -398,12 +405,12 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_ped_flagD40 = false;
bScriptObjectiveCompleted = false;
- m_ped_flagE1 = false;
+ bKindaStayInSamePlace = false;
m_ped_flagE2 = false;
bNotAllowedToDuck = false;
bCrouchWhenShooting = false;
bIsDucking = false;
- m_ped_flagE20 = false;
+ bGetUpAnimStarted = false;
bDoBloodyFootprints = false;
m_ped_flagE80 = false;
@@ -428,17 +435,17 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_ped_flagH1 = false;
m_ped_flagH2 = false;
m_ped_flagH4 = false;
- m_ped_flagH8 = false;
+ bClearObjective = false;
m_ped_flagH10 = false;
m_ped_flagH20 = false;
m_ped_flagH40 = false;
m_ped_flagH80 = false;
m_ped_flagI1 = false;
- m_ped_flagI2 = false;
+ bNoCriticalHits = false;
m_ped_flagI4 = false;
bHasAlreadyBeenRecorded = false;
- m_ped_flagI10 = false;
+ bIsFell = false;
#ifdef KANGAROO_CHEAT
m_ped_flagI80 = false;
#endif
@@ -476,7 +483,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
weapon.m_nTimer = 0;
}
- m_lastHitState = 0;
+ m_lastFightMove = FIGHTMOVE_NULL;
GiveWeapon(WEAPONTYPE_UNARMED, 0);
m_wepAccuracy = 60;
m_lastWepDam = -1;
@@ -658,7 +665,7 @@ CPed::AddWeaponModel(int id)
atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
RwFrameDestroy(RpAtomicGetFrame(atm));
RpAtomicSetFrame(atm, GetNodeFrame(PED_HANDR));
- RpClumpAddAtomic((RpClump*)m_rwObject, atm);
+ RpClumpAddAtomic(GetClump(), atm);
m_wepModelID = id;
}
}
@@ -955,10 +962,10 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
case ANIM_WEAPON_START_THROW:
if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) {
attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROWU);
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU);
} else {
attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROW);
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW);
}
newAnim->SetFinishCallback(FinishedAttackCB, ped);
@@ -1007,7 +1014,7 @@ CPed::Attack(void)
ourWeaponType = GetWeapon()->m_eWeaponType;
ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
ourWeaponFire = ourWeapon->m_eWeaponFire;
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_AnimToPlay);
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
lastReloadWasInFuture = m_ped_flagA4;
reloadAnimAssoc = nil;
reloadAnim = NUM_ANIMS;
@@ -1020,7 +1027,7 @@ CPed::Attack(void)
reloadAnim = ANIM_AK_RELOAD;
if (reloadAnim != NUM_ANIMS)
- reloadAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, reloadAnim);
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
if (bIsDucking)
return;
@@ -1037,12 +1044,12 @@ CPed::Attack(void)
lastReloadWasInFuture = true;
if (!weaponAnimAssoc) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_Anim2ToPlay);
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
// Long throw granade, molotov
if (!weaponAnimAssoc && ourWeapon->m_bThrow) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_WEAPON_THROWU);
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
delayBetweenAnimAndFire = 0.2f;
}
@@ -1050,14 +1057,14 @@ CPed::Attack(void)
if (lastReloadWasInFuture) {
if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->field_1380) {
if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(((CPlayerPed*)this), nil) < PED_ON_THE_FLOOR) {
- weaponAnimAssoc = CAnimManager::BlendAnimation((RpClump*)m_rwObject, ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
}
else {
- weaponAnimAssoc = CAnimManager::BlendAnimation((RpClump*)m_rwObject, ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
}
weaponAnimAssoc->SetFinishCallback(CPed::FinishedAttackCB, this);
- weaponAnimAssoc->flags |= ASSOC_RUNNING;
+ weaponAnimAssoc->SetRun();
if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)
weaponAnimAssoc->SetCurrentTime(0.0f);
@@ -1118,7 +1125,7 @@ CPed::Attack(void)
if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) {
// If reloading just began, start the animation
if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS && !reloadAnimAssoc) {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, reloadAnim, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f);
ClearLookFlag();
ClearAimFlag();
m_ped_flagA4 = false;
@@ -1185,13 +1192,13 @@ CPed::Attack(void)
if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) {
weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart);
} else {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
}
} else {
if (weaponAnim == ourWeapon->m_Anim2ToPlay)
weaponAnimAssoc->SetCurrentTime(0.1f);
else
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
}
} else {
ClearAimFlag();
@@ -1277,9 +1284,9 @@ CPed::Duck(void)
void
CPed::ClearDuck(void)
{
- CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_DUCK_DOWN);
+ CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_DUCK_LOW);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
if (!animAssoc) {
bIsDucking = false;
@@ -1293,9 +1300,9 @@ CPed::ClearDuck(void)
if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
return;
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RBLOCK_CSHOOT);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
}
}
@@ -1311,9 +1318,9 @@ CPed::ClearPointGunAt(void)
if (m_nPedState == PED_AIM_GUN) {
RestorePreviousState();
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_AnimToPlay);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_Anim2ToPlay);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
}
if (animAssoc) {
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
@@ -1331,14 +1338,14 @@ CPed::BeingDraggedFromCar(void)
PedLineUpPhase lineUpType;
if (!m_pVehicleAnim) {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SIT);
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_LSIT);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITP);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITPLO);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
}
}
if (animAssoc)
@@ -1362,7 +1369,7 @@ CPed::BeingDraggedFromCar(void)
if (!dontRunAnim)
- m_pVehicleAnim = CAnimManager::AddAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, enterAnim);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
lineUpType = LINE_UP_TO_CAR_START;
@@ -1381,9 +1388,9 @@ CPed::RestartNonPartialAnims(void)
{
CAnimBlendAssociation *assoc;
- for (assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
if (!assoc->IsPartial())
- assoc->flags |= ASSOC_RUNNING;
+ assoc->SetRun();
}
}
@@ -1395,7 +1402,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
CPed *ped = (CPed*)arg;
eWeaponType weaponType = ped->GetWeapon()->m_eWeaponType;
- quickJackedAssoc = RpAnimBlendClumpGetAssociation((RpClump*) ped->m_rwObject, ANIM_CAR_QJACKED);
+ quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED);
if (ped->m_nPedState != PED_ARRESTED) {
ped->m_nLastPedState = PED_NONE;
if (dragAssoc)
@@ -1433,7 +1440,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
} else {
dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
if (ped->CanSetPedState())
- CAnimManager::BlendAnimation((RpClump*) ped->m_rwObject, ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
}
// Only uzi can be used on cars, so previous weapon was stored
@@ -1445,7 +1452,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
} else {
ped->AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
}
- ped->m_nStoredActionState = 0;
+ ped->m_nStoredMoveState = PEDMOVE_NONE;
ped->m_ped_flagI4 = false;
}
@@ -1566,19 +1573,19 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
return;
if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
- if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SIT)) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
SetPedPositionInCar();
return;
}
- if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_LSIT)) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
SetPedPositionInCar();
return;
}
- if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITP)) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
SetPedPositionInCar();
return;
}
- if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITPLO)) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
SetPedPositionInCar();
return;
}
@@ -1598,7 +1605,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
if (vehIsUpsideDown) {
m_fRotationDest = -PI + veh->GetForward().Heading();
} else if (veh->bIsBus) {
- m_fRotationDest = 0.5 * PI + veh->GetForward().Heading();
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
} else {
m_fRotationDest = veh->GetForward().Heading();
}
@@ -1606,7 +1613,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
if (vehIsUpsideDown) {
m_fRotationDest = veh->GetForward().Heading();
} else if (veh->bIsBus) {
- m_fRotationDest = -0.5 * PI + veh->GetForward().Heading();
+ m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
} else {
m_fRotationDest = veh->GetForward().Heading();
}
@@ -1809,7 +1816,7 @@ particleProduceFootSplash(CPed *ped, CVector *pos, float size, int times)
adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
CVector direction = ped->GetForward() * -0.05f;
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumberInRange(0, 1), 200);
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
}
}
@@ -1828,7 +1835,7 @@ CPed::PlayFootSteps(void)
if (!bIsStanding)
return;
- CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject);
+ CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());
CAnimBlendAssociation *walkRunAssoc = nil;
float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;
@@ -2042,13 +2049,13 @@ void
CPed::SetModelIndex(uint32 mi)
{
CEntity::SetModelIndex(mi);
- RpAnimBlendClumpInit((RpClump*) m_rwObject);
- RpAnimBlendClumpFillFrameArray((RpClump*) m_rwObject, m_pFrames);
+ RpAnimBlendClumpInit(GetClump());
+ RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);
CPedModelInfo *modelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);
SetPedStats((ePedStats) modelInfo->m_pedStatType);
m_headingRate = m_pedStats->m_headingChangeRate;
m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
- CAnimManager::AddAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE);
+ CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
// This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
(*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
@@ -2121,9 +2128,9 @@ CPed::WorkOutHeadingForMovingFirstPerson(float offset)
angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
} else {
if (leftRight < 0.0f)
- angle = 0.5 * PI;
+ angle = 0.5f * PI;
else if (leftRight > 0.0f)
- angle = -0.5 * PI;
+ angle = -0.5f * PI;
}
return CGeneral::LimitRadianAngle(offset + angle);
@@ -2176,9 +2183,9 @@ CPed::CalculateNewVelocity(void)
float pedSpeed = m_moved.Magnitude();
float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);
- if (localWalkAngle < -0.5 * PI) {
+ if (localWalkAngle < -0.5f * PI) {
localWalkAngle += PI;
- } else if (localWalkAngle > 0.5 * PI) {
+ } else if (localWalkAngle > 0.5f * PI) {
localWalkAngle -= PI;
}
@@ -2188,8 +2195,8 @@ CPed::CalculateNewVelocity(void)
m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;
}
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE);
- CAnimBlendAssociation* fightAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_FIGHT_IDLE);
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ CAnimBlendAssociation* fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
LimbOrientation newUpperLegs;
@@ -2638,7 +2645,7 @@ CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
void
CPed::ClearChat(void)
{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
if (animAssoc) {
animAssoc->blendDelta = -8.0f;
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
@@ -2699,8 +2706,8 @@ CPed::QuitEnteringCar(void)
RestartNonPartialAnims();
- if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE))
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
if (veh) {
if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
@@ -2763,7 +2770,7 @@ CPed::ReactToAttack(CEntity *attacker)
field_4E8 = CTimer::GetTimeInMilliseconds();
return;
}
- } else if (bCrouchWhenShooting || m_ped_flagE1) {
+ } else if (bCrouchWhenShooting || bKindaStayInSamePlace) {
SetDuck(CGeneral::GetRandomNumberInRange(1000,3000));
return;
}
@@ -2853,7 +2860,7 @@ CPed::Chat(void)
}
if (bIsTalking) {
if (CGeneral::GetRandomNumber() < 512) {
- CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT);
+ CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
if (chatAssoc) {
chatAssoc->blendDelta = -4.0f;
chatAssoc->flags |= ASSOC_FADEOUTWHENDONE;
@@ -2862,13 +2869,13 @@ CPed::Chat(void)
} else
Say(SOUND_PED_CHAT);
- } else if (!RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject, ASSOC_FLAG100)) {
+ } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG100)) {
if (CGeneral::GetRandomNumber() < 20) {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
}
if (!bIsTalking) {
- CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
+ CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
chatAssoc->SetCurrentTime(chatTime);
@@ -3147,12 +3154,12 @@ CPed::ClearAttackByRemovingAnim(void)
return;
CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weapon->m_AnimToPlay);
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay);
if (!weaponAssoc) {
- weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weapon->m_Anim2ToPlay);
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay);
if (!weaponAssoc && weapon->m_bThrow)
- weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_WEAPON_THROWU);
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
if (!weaponAssoc) {
ClearAttack();
@@ -3170,7 +3177,7 @@ CPed::StopNonPartialAnims(void)
{
CAnimBlendAssociation* assoc;
- for (assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
if (!assoc->IsPartial())
assoc->flags &= ~ASSOC_RUNNING;
}
@@ -3188,8 +3195,8 @@ CPed::SetStoredState(void)
m_nMoveState = PEDMOVE_WALK;
}
m_nLastPedState = m_nPedState;
- if (m_nMoveState >= m_nPrevActionState)
- m_nPrevActionState = m_nMoveState;
+ if (m_nMoveState >= m_nPrevMoveState)
+ m_nPrevMoveState = m_nMoveState;
}
void
@@ -3225,7 +3232,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed)
if (animId == NUM_ANIMS) {
bIsPedDieAnimPlaying = false;
} else {
- CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, animId, delta);
+ CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);
if (speed > 0.0f)
dieAssoc->speed = speed;
@@ -3283,7 +3290,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
bool detectDieAnim = true;
if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
if (!IsPedHeadAbovePos(-0.3f)) {
- if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800))
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800))
dieAnim = ANIM_FLOOR_HIT_F;
else
dieAnim = ANIM_FLOOR_HIT;
@@ -3305,7 +3312,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
if (IsPedHeadAbovePos(-0.3f)) {
dieAnim = NUM_ANIMS;
} else {
- if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800))
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800))
dieAnim = ANIM_FLOOR_HIT_F;
else
dieAnim = ANIM_FLOOR_HIT;
@@ -3339,7 +3346,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
if (IsPedHeadAbovePos(-0.3f)) {
dieAnim = NUM_ANIMS;
} else {
- if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, 0x800u))
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), 0x800u))
dieAnim = ANIM_FLOOR_HIT_F;
else
dieAnim = ANIM_FLOOR_HIT;
@@ -3375,7 +3382,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
return false;
bool dontRemoveLimb;
- if (IsPlayer() || m_ped_flagI2)
+ if (IsPlayer() || bNoCriticalHits)
dontRemoveLimb = true;
else {
switch (method)
@@ -3387,10 +3394,10 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
dontRemoveLimb = false;
break;
case WEAPONTYPE_SHOTGUN:
- dontRemoveLimb = CGeneral::GetRandomNumberInRange(0,7);
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
break;
default:
- dontRemoveLimb = CGeneral::GetRandomNumberInRange(0,15);
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
break;
}
}
@@ -3514,7 +3521,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
if (bCollisionProof)
return false;
- random = CGeneral::GetRandomNumberInRange(0, 3);
+ random = CGeneral::GetRandomNumber() & 3;
switch (random) {
case 0:
if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
@@ -3669,17 +3676,17 @@ CPed::ClearFall(void)
void
CPed::SetGetUp(void)
{
- if (m_nPedState == PED_GETUP && m_ped_flagE20)
+ if (m_nPedState == PED_GETUP && bGetUpAnimStarted)
return;
if (!CanSetPedState())
return;
if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {
- if (m_ped_flagC10) {
+ if (bUpdateAnimHeading) {
m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- m_fRotationCur -= 0.5*PI;
- m_ped_flagC10 = false;
+ m_fRotationCur -= 0.5f*PI;
+ bUpdateAnimHeading = false;
}
if (m_nPedState != PED_GETUP) {
SetStoredState();
@@ -3695,7 +3702,7 @@ CPed::SetGetUp(void)
collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(),
&ms_tempColPoint, nil, nil) > 0)) {
- m_ped_flagE20 = false;
+ bGetUpAnimStarted = false;
if (IsPlayer())
InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
else {
@@ -3706,23 +3713,23 @@ CPed::SetGetUp(void)
}
return;
}
- m_ped_flagE20 = true;
+ bGetUpAnimStarted = true;
m_pCollidingEntity = nil;
m_ped_flagH1 = false;
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_SPRINT);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
if (animAssoc) {
- if (RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RUN)) {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_RUN, 8.0f);
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f);
} else {
- CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
}
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
- if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800))
- animAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800))
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
else
- animAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
animAssoc->SetFinishCallback(PedGetupCB,this);
} else {
@@ -3734,13 +3741,13 @@ CPed::SetGetUp(void)
void
CPed::ClearInvestigateEvent(void)
{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_ROAD_CROSS);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_XPRESS_SCRATCH);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_HBHB);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
if (animAssoc) {
animAssoc->blendDelta = -8.0f;
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
@@ -3771,7 +3778,7 @@ CPed::ClearLeader(void)
SetWanderPath(CGeneral::GetRandomNumberInRange(0,8));
}
} else if (m_objective != OBJECTIVE_NONE) {
- m_ped_flagH8 = true;
+ bClearObjective = true;
}
}
@@ -3800,7 +3807,7 @@ CPed::ClearObjective(void)
SetMoveState(PEDMOVE_STILL);
}
} else {
- m_ped_flagH8 = true;
+ bClearObjective = true;
}
}
@@ -3823,7 +3830,7 @@ CPed::SetWanderPath(int8 pathStateDest)
uint8 nextPathState;
if (IsPedInControl()) {
- if (m_ped_flagE1) {
+ if (bKindaStayInSamePlace) {
SetIdle();
return false;
} else {
@@ -3919,7 +3926,7 @@ CPed::RestorePreviousState(void)
if(!CanSetPedState() || m_nPedState == PED_FALL)
return;
- if (m_nPedState == PED_GETUP && !m_ped_flagE20)
+ if (m_nPedState == PED_GETUP && !bGetUpAnimStarted)
return;
if (bInVehicle && m_pMyVehicle) {
@@ -3928,7 +3935,7 @@ CPed::RestorePreviousState(void)
} else {
if (m_nLastPedState == PED_NONE) {
if (!IsPlayer() && CharCreatedBy != MISSION_CHAR && m_objective == OBJECTIVE_NONE) {
- if (SetWanderPath(CGeneral::GetRandomNumberInRange(0, 7)) != 0)
+ if (SetWanderPath(CGeneral::GetRandomNumber() & 7) != 0)
return;
}
SetIdle();
@@ -3951,11 +3958,11 @@ CPed::RestorePreviousState(void)
}
}
}
- SetWanderPath(CGeneral::GetRandomNumberInRange(0, 7));
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
break;
default:
m_nPedState = m_nLastPedState;
- SetMoveState((eMoveState) m_nPrevActionState);
+ SetMoveState((eMoveState) m_nPrevMoveState);
break;
}
m_nLastPedState = PED_NONE;
@@ -4011,15 +4018,15 @@ CPed::SetPointGunAt(CEntity *to)
CAnimBlendAssociation *aimAssoc;
if (bCrouchWhenShooting)
- aimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, curWeapon->m_Anim2ToPlay);
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay);
else
- aimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, curWeapon->m_AnimToPlay);
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay);
if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
if (bCrouchWhenShooting)
- aimAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
+ aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
else
- aimAssoc = CAnimManager::AddAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, curWeapon->m_AnimToPlay);
+ aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay);
aimAssoc->blendAmount = 0.0f;
aimAssoc->blendDelta = 8.0f;
@@ -4080,25 +4087,29 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
}
if (neededTurn <= DEGTORAD(90.0f) || veh->m_modelIndex == MI_RCBANDIT || vehPressedHorn || animType != 0) {
SetLookFlag(veh, 1);
- if (CGeneral::GetRandomNumberInRange(0,1) && veh->m_modelIndex != MI_RCBANDIT && animType == 0) {
+ if ((CGeneral::GetRandomNumber() & 1) && veh->m_modelIndex != MI_RCBANDIT && animType == 0) {
stepAnim = ANIM_IDLE_TAXI;
} else {
- // I didn't get these things too much.
float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
0.0f, 0.0f);
- float inversedAngleToFace = angleToFace + PI;
- if (inversedAngleToFace > PI)
- inversedAngleToFace -= 2*PI;
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
- neededTurn = inversedAngleToFace - vehDirection;
- neededTurn = CGeneral::LimitRadianAngle(neededTurn);
- if (neededTurn <= 0.0)
- angleToFace = 0.5*PI + vehDirection;
+ if (angleToFace > PI)
+ angleToFace -= 2*PI;
+
+ // We don't want to run towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone <= 0.0f)
+ angleToFace = 0.5f*PI + vehDirection;
else
- angleToFace = vehDirection - 0.5*PI;
+ angleToFace = vehDirection - 0.5f*PI;
if (animType == 2)
stepAnim = ANIM_HANDSCOWER;
@@ -4107,8 +4118,8 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
else
stepAnim = NUM_ANIMS;
}
- if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, stepAnim)) {
- CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, stepAnim, 8.0f);
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {
+ CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);
stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
stepAssoc->SetFinishCallback(PedEvadeCB, this);
@@ -4123,6 +4134,623 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
}
}
+void
+CPed::SetEvasiveDive(CPhysical* reason, uint8 onlyRandomJump)
+{
+ if (!IsPedInControl() || !bRespondsToThreats)
+ return;
+
+ CAnimBlendAssociation* animAssoc;
+ float angleToFace, neededTurn;
+ bool handsUp = false;
+
+ angleToFace = m_fRotationCur;
+ CVehicle *veh = (CVehicle*) reason;
+ if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer && !IsPlayer()) {
+ onlyRandomJump = true;
+ }
+
+ if (onlyRandomJump) {
+ if (reason) {
+ // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly.
+ // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.
+
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+ angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ }
+ } else {
+ if (IsPlayer()) {
+ ((CPlayerPed*)this)->m_bShouldEvade = 5;
+ ((CPlayerPed*)this)->m_pEvadingFrom = reason;
+ reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);
+ return;
+ }
+
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ reason->GetPosition().x, reason->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted
+#ifdef FIX_BUGS
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
+
+ if (angleToFace > PI)
+ angleToFace -= 2 * PI;
+
+ // We don't want to dive towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone > 0.0f)
+ angleToFace = 0.5f * PI + vehDirection;
+ else
+ angleToFace = vehDirection - 0.5f * PI;
+#endif
+
+ neededTurn = Abs(angleToFace - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = 2 * PI - neededTurn;
+
+ if (neededTurn <= 0.5f*PI) {
+ if (CGeneral::GetRandomNumber() & 1)
+ handsUp = true;
+ } else {
+ if (CGeneral::GetRandomNumber() & 7)
+ return;
+ }
+ Say(SOUND_PED_EVADE);
+ }
+
+ if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetLookFlag(reason, 1);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
+ if (animAssoc)
+ return;
+
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f);
+ animAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ SetStoredState();
+ m_nPedState = PED_STEP_AWAY;
+ } else {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_DIVE_AWAY;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f);
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ }
+
+ if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {
+ if (veh->pDriver && veh->pDriver->IsPlayer()) {
+ CWanted *wanted = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted;
+ wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (int)this, false);
+ wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (int)this, false);
+ }
+ }
+}
+
+void
+CPed::SetAttack(CEntity* victim)
+{
+ CPed *victimPed = nil;
+ if (victim && victim->IsPed())
+ victimPed = (CPed*)victim;
+
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
+ if (animAssoc) {
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+
+ if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE)
+ return;
+
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) {
+ m_ped_flagA4 = false;
+ return;
+ }
+
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
+ if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->field_1380)
+ m_ped_flagA4 = false;
+ else
+ m_ped_flagA4 = true;
+
+ 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 (IsPlayer() ||
+ (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
+
+ if (m_nPedState != PED_ATTACK) {
+ m_nPedState = PED_ATTACK;
+ m_ped_flagA4 = false;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
+ animAssoc->SetRun();
+ if (animAssoc->currentTime != animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ } else {
+ StartFightAttack(CGeneral::GetRandomNumber() & 255);
+ }
+ return;
+ }
+
+ m_pSeekTarget = victim;
+ if (m_pSeekTarget)
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+
+ if (curWeapon->m_bCanAim) {
+ CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();
+ CEntity *foundEntity = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
+ if (foundEntity)
+ 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 {
+ SetAimFlag(m_fRotationCur);
+
+ if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+ }
+ }
+ if (m_nPedState == PED_ATTACK) {
+ m_ped_flagA4 = true;
+ return;
+ }
+
+ if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
+ if(IsPlayer())
+ CPad::GetPad(0)->ResetAverageWeapon();
+
+ if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16FIRSTPERSON_34
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_FIRSTPERSONPEDONPC_41
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUN_AROUND
+ && CheckForPointBlankPeds(victimPed) != 0) {
+ ClearAimFlag();
+
+ // This condition is pointless, we already check it in above
+ // if (CheckForPointBlankPeds(victimPed) == 1 || !victimPed)
+ StartFightAttack(200);
+ } else {
+ if (!curWeapon->m_bCanAim)
+ m_pSeekTarget = nil;
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ m_nPedState = PED_ATTACK;
+ SetMoveState(PEDMOVE_NONE);
+ if (bCrouchWhenShooting) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ } else {
+ float animDelta = 8.0f;
+ if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)
+ animDelta = 1000.0f;
+
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT
+ || CheckForPedsOnGroundToAttack((CPlayerPed*)this, nil) < PED_ON_THE_FLOOR) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta);
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
+ }
+ }
+
+ animAssoc->SetRun();
+ if (animAssoc->currentTime != animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ return;
+ }
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
+ SetWaitState(WAITSTATE_SURPRISE, nil);
+
+ SetLookFlag(victim, 0);
+ SetLookTimer(100);
+}
+
+void
+CPed::StartFightAttack(uint8 buttonPressure)
+{
+ if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
+ return;
+
+ if (m_nPedState == PED_FIGHT) {
+ m_fightButtonPressure = buttonPressure;
+ return;
+ }
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ }
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+
+ CPed *pedOnGround = nil;
+ if (IsPlayer() && CheckForPedsOnGroundToAttack((CPlayerPed*)this, &pedOnGround) > PED_BELOW_PLAYER) {
+ m_lastFightMove = FIGHTMOVE_GROUNDKICK;
+ } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
+ m_lastFightMove = FIGHTMOVE_ROUNDHOUSE;
+ } else {
+ m_lastFightMove = FIGHTMOVE_STDPUNCH;
+ }
+
+ if (pedOnGround && IsPlayer()) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(pedOnGround, 1);
+ SetLookTimer(1500);
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ms_fightMoves[m_lastFightMove].animId, 4.0f);
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightUnk2 = 0;
+ m_fightUnk1 = 0;
+ m_ped_flagA4 = true;
+
+ if (IsPlayer())
+ unknownFightThing = 0;
+}
+
+void
+CPed::LoadFightData(void)
+{
+ float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
+ int damage, flags;
+ char line[256], moveName[32], animName[32], hitLevel;
+ int moveId = 0;
+
+ CAnimBlendAssociation* animAssoc;
+
+ int bp, buflen;
+ int lp, linelen;
+
+ buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r");
+
+ for (bp = 0; bp < buflen; ) {
+ // read file line by line
+ for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) {
+ line[linelen++] = work_buff[bp];
+ }
+ bp++;
+ line[linelen] = '\0';
+
+ // skip white space
+ for (lp = 0; line[lp] <= ' '; lp++);
+
+ if (lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
+ line[lp] == '#')
+ continue;
+
+ sscanf(
+ &line[lp],
+ "%s %f %f %f %f %c %s %d %d",
+ &moveName,
+ &startFireTime,
+ &endFireTime,
+ &comboFollowOnTime,
+ &strikeRadius,
+ &hitLevel,
+ &animName,
+ &damage,
+ &flags);
+
+ if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0)
+ return;
+
+ ms_fightMoves[moveId].startFireTime = startFireTime / 30.0f;
+ ms_fightMoves[moveId].endFireTime = endFireTime / 30.0f;
+ ms_fightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
+ ms_fightMoves[moveId].strikeRadius = strikeRadius;
+ ms_fightMoves[moveId].damage = damage;
+ ms_fightMoves[moveId].flags = flags;
+
+ switch (hitLevel) {
+ case 'G':
+ ms_fightMoves[moveId].hitLevel = 1;
+ break;
+ case 'H':
+ ms_fightMoves[moveId].hitLevel = 4;
+ break;
+ case 'L':
+ ms_fightMoves[moveId].hitLevel = 2;
+ break;
+ case 'M':
+ ms_fightMoves[moveId].hitLevel = 3;
+ break;
+ case 'N':
+ ms_fightMoves[moveId].hitLevel = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (strncmp(animName, "null", 4) != 0) {
+ animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
+ ms_fightMoves[moveId].animId = (AnimationId)animAssoc->animId;
+ } else {
+ ms_fightMoves[moveId].animId = ANIM_WALK;
+ }
+ moveId++;
+ }
+}
+
+// Actually GetLocalDirectionTo(Turn/Look)
+int
+CPed::GetLocalDirection(CVector2D &posOffset)
+{
+ float direction;
+
+ for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += 2 * PI);
+
+ for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4);
+
+ // Should be 0-east, 1-north, 2-west, 3-south. Not sure about order.
+ return direction;
+}
+
+bool
+CPed::FightStrike(CVector &touchedNodePos)
+{
+ CColModel* ourCol;
+ CVector attackDistance;
+ ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
+ float maxDistanceToBeBeaten;
+ CPed *nearPed;
+ int unk = m_fightUnk2;
+ bool pedFound = false;
+
+ if (unk == -1)
+ return false;
+
+ if (unk > 0)
+ attackDistance = touchedNodePos - m_vecHitLastPos;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ nearPed = m_nearPeds[i];
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + ms_fightMoves[m_lastFightMove].strikeRadius + 0.1f;
+ else
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + ms_fightMoves[m_lastFightMove].strikeRadius;
+
+ if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
+ CVector nearPedCentre;
+ nearPed->GetBoundCentre(nearPedCentre);
+ CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
+
+ // He can beat us
+ if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
+ ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
+ if (nearPed->m_nPedState == PED_FALL
+ || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE
+ || !nearPed->IsPedHeadAbovePos(-0.3f)) {
+ ourCol = &CTempColModels::ms_colModelPedGroundHit;
+ }
+ for (int j = 0; j < ourCol->numSpheres; j++) {
+ attackDistance = nearPed->GetPosition() - ourCol->spheres[j].center;
+ attackDistance -= touchedNodePos;
+ CColSphere *ourPieces = ourCol->spheres;
+ float maxDistanceToBeat = ourPieces[j].radius + ms_fightMoves[m_lastFightMove].strikeRadius;
+
+ // We can beat him too
+ if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
+ pedFound = true;
+ closestPedPiece = (ePedPieceTypes) ourPieces[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 = ms_fightMoves[m_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+
+ 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;
+ }
+
+ // Change direction if we used kick.
+ if (m_lastFightMove == FIGHTMOVE_KICK) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ direction++;
+ if (direction > 3)
+ direction -= 4;
+ }
+ }
+ nearPed->ReactToAttack(this);
+
+ // Mostly unused.
+ int unk2;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
+ unk2 = 101;
+ else
+ unk2 = damageMult;
+
+ nearPed->StartFightDefend(direction, ms_fightMoves[m_lastFightMove].hitLevel, unk2);
+ PlayHitSound(nearPed);
+ m_fightUnk2 = -1;
+ RpAnimBlendClumpGetAssociation(GetClump(), ms_fightMoves[m_lastFightMove].animId)->speed = 0.6f;
+ if (nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) {
+ nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
+ }
+
+ if (CGame::nastyGame
+ && ms_fightMoves[m_lastFightMove].hitLevel > 3
+ && nearPed->m_nPedState == PED_DIE
+ && nearPed->GetIsOnScreen()) {
+
+ // 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);
+ }
+ }
+ if (nearPed->m_nPedState != PED_FALL && nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) {
+ float curVictimHealth = nearPed->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)) {
+
+ nearPed->SetFall(0, (AnimationId)(direction + 25), 0);
+ if (nearPed->m_nPedState == PED_FALL)
+ nearPed->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_lastFightMove == FIGHTMOVE_GROUNDKICK) {
+ moveMult = min(damageMult * 0.6f, 4.0f);
+ } else {
+ if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
+ moveMult = damageMult;
+ } else {
+ 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);
+ }
+
+ if (!m_fightUnk2)
+ m_fightUnk2 = 1;
+
+ m_vecHitLastPos = *touchedNodePos;
+ return false;
+}
+
+void
+CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
+{
+ if (!IsPedInControl() && (!evenIfNotInControl || m_nPedState == PED_DIE || m_nPedState == PED_DEAD))
+ return;
+
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_FALL;
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);
+
+ if (fallAssoc) {
+ fallAssoc->SetCurrentTime(0.0f);
+ fallAssoc->blendAmount = 0.0f;
+ fallAssoc->blendDelta = 8.0f;
+ fallAssoc->SetRun();
+ } else {
+ fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);
+ }
+
+ if (extraTime == -1) {
+ m_getUpTimer = -1;
+ } else if (fallAssoc) {
+ if (IsPlayer()) {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + 500.0f;
+ } else {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + extraTime
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ } else {
+ m_getUpTimer = extraTime
+ + CTimer::GetTimeInMilliseconds()
+ + 1000
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ bIsFell = true;
+}
+
WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); }
WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); }
WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); }
@@ -4252,4 +4880,11 @@ STARTPATCHES
InjectHook(0x4C6960, (void (CPed::*)(float)) &CPed::SetAimFlag, PATCH_JUMP);
InjectHook(0x4CFAD0, &CPed::GrantAmmo, PATCH_JUMP);
InjectHook(0x4CFB20, &CPed::SetAmmo, PATCH_JUMP);
-ENDPATCHES
+ InjectHook(0x4D33A0, &CPed::SetEvasiveDive, PATCH_JUMP);
+ InjectHook(0x4D09B0, &CPed::SetFall, PATCH_JUMP);
+ InjectHook(0x4E6220, &CPed::SetAttack, PATCH_JUMP);
+ InjectHook(0x4E7530, &CPed::StartFightAttack, PATCH_JUMP);
+ InjectHook(0x4E9870, &CPed::LoadFightData, PATCH_JUMP);
+ InjectHook(0x4E8EC0, &CPed::FightStrike, PATCH_JUMP);
+ InjectHook(0x4CCE20, &CPed::GetLocalDirection, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index f0e222a0..2ef0ebd1 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -13,6 +13,47 @@
struct CPathNode;
+struct FightMove
+{
+ AnimationId animId;
+ float startFireTime;
+ float endFireTime;
+ float comboFollowOnTime;
+ float strikeRadius;
+ uint8 hitLevel;
+ uint8 damage;
+ uint8 flags;
+};
+static_assert(sizeof(FightMove) == 0x18, "FightMove: error");
+
+enum PedFightMoves
+{
+ FIGHTMOVE_NULL,
+ FIGHTMOVE_STDPUNCH,
+ FIGHTMOVE_IDLE,
+ FIGHTMOVE_SHUFFLE_F,
+ FIGHTMOVE_KNEE,
+ FIGHTMOVE_HEADBUTT,
+ FIGHTMOVE_PUNCHJAB,
+ FIGHTMOVE_PUNCHHOOK,
+ FIGHTMOVE_KICK,
+ FIGHTMOVE_LONGKICK,
+ FIGHTMOVE_ROUNDHOUSE,
+ FIGHTMOVE_BODYBLOW,
+ FIGHTMOVE_GROUNDKICK,
+ FIGHTMOVE_HITFRONT,
+ FIGHTMOVE_HITBACK,
+ FIGHTMOVE_HITRIGHT,
+ FIGHTMOVE_HITLEFT,
+ FIGHTMOVE_HITBODY,
+ FIGHTMOVE_HITCHEST,
+ FIGHTMOVE_HITHEAD,
+ FIGHTMOVE_HITBIGSTEP,
+ FIGHTMOVE_HITONFLOOR,
+ FIGHTMOVE_HITBEHIND,
+ FIGHTMOVE_IDLE2NORM
+};
+
enum ePedPieceTypes
{
PEDPIECE_TORSO,
@@ -209,7 +250,7 @@ public:
uint8 bRespondsToThreats : 1;
uint8 bRenderPedInCar : 1;
uint8 bChangedSeat : 1;
- uint8 m_ped_flagC10 : 1; // related with phone
+ uint8 bUpdateAnimHeading : 1;
uint8 bBodyPartJustCameOff : 1;
uint8 m_ped_flagC40 : 1;
uint8 m_ped_flagC80 : 1;
@@ -223,12 +264,12 @@ public:
uint8 m_ped_flagD40 : 1; // reset when objective changes
uint8 bScriptObjectiveCompleted : 1;
- uint8 m_ped_flagE1 : 1;
+ uint8 bKindaStayInSamePlace : 1;
uint8 m_ped_flagE2 : 1;
uint8 bNotAllowedToDuck : 1;
uint8 bCrouchWhenShooting : 1;
uint8 bIsDucking : 1; // set if you don't want ped to attack
- uint8 m_ped_flagE20 : 1; // getup complete?
+ uint8 bGetUpAnimStarted : 1;
uint8 bDoBloodyFootprints : 1;
uint8 m_ped_flagE80 : 1;
@@ -253,17 +294,17 @@ public:
uint8 m_ped_flagH1 : 1;
uint8 m_ped_flagH2 : 1;
uint8 m_ped_flagH4 : 1;
- uint8 m_ped_flagH8 : 1;
+ uint8 bClearObjective : 1;
uint8 m_ped_flagH10 : 1;
uint8 m_ped_flagH20 : 1;
uint8 m_ped_flagH40 : 1;
uint8 m_ped_flagH80 : 1;
uint8 m_ped_flagI1 : 1;
- uint8 m_ped_flagI2 : 1; // if set, limbs won't came off
+ uint8 bNoCriticalHits : 1; // if set, limbs won't came off
uint8 m_ped_flagI4 : 1;
uint8 bHasAlreadyBeenRecorded : 1;
- uint8 m_ped_flagI10 : 1;
+ uint8 bIsFell : 1;
uint8 m_ped_flagI20 : 1;
uint8 m_ped_flagI40 : 1;
uint8 m_ped_flagI80 : 1;
@@ -299,8 +340,8 @@ public:
PedState m_nPedState;
PedState m_nLastPedState;
eMoveState m_nMoveState;
- int32 m_nStoredActionState;
- int32 m_nPrevActionState;
+ int32 m_nStoredMoveState;
+ int32 m_nPrevMoveState;
eWaitState m_nWaitState;
uint32 m_nWaitTimer;
void *m_pPathNodesStates[8]; // seems unused
@@ -363,10 +404,11 @@ public:
uint8 m_wepAccuracy;
CEntity *m_pPointGunAt;
CVector m_vecHitLastPos;
- uint32 m_lastHitState;
- uint8 m_fightFlags1;
- uint8 m_fightFlags2;
- uint8 pad_4B2[2];
+ PedFightMoves m_lastFightMove;
+ uint8 m_fightButtonPressure;
+ int8 m_fightUnk2; // TODO
+ uint8 m_fightUnk1; // TODO
+ uint8 pad_4B3;
CFire* m_pFire;
CEntity *m_pLookTarget;
float m_fLookDirection;
@@ -504,6 +546,16 @@ public:
void SetAmmo(eWeaponType weaponType, uint32 ammo);
void SetEvasiveStep(CEntity*, uint8);
void GrantAmmo(eWeaponType, uint32);
+ void SetEvasiveDive(CPhysical*, uint8);
+ void SetAttack(CEntity*);
+ void StartFightAttack(uint8);
+ void LoadFightData(void);
+ void SetWaitState(eWaitState, void*);
+ bool FightStrike(CVector&);
+ int GetLocalDirection(CVector2D&);
+ void StartFightDefend(uint8, uint8, uint8);
+ void PlayHitSound(CPed*);
+ void SetFall(int, AnimationId, uint8);
// Static methods
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset);
@@ -579,6 +631,8 @@ public:
static bool &bPedCheat2;
static bool &bPedCheat3;
static CColPoint &ms_tempColPoint;
+ static uint16 &unknownFightThing; // TODO
+ static FightMove (&ms_fightMoves)[24];
};
void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg);
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index 3d5bcfb5..768e0bf0 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -104,8 +104,7 @@ CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination)
return destination;
}
-// A helper function that adjusts "limb" parameter according to limitations. Doesn't move the limb.
-int8
+uint32
CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo)
{
int result = 1;
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index 5f321280..a8d9c75d 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -47,7 +47,7 @@ public:
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
void ExtractYawAndPitchLocal(RwMatrixTag*, float*, float*);
void ExtractYawAndPitchWorld(RwMatrixTag*, float*, float*);
- int8 MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4);
+ uint32 MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4);
bool RestoreGunPosn(void);
};
static_assert(sizeof(CPedIK) == 0x28, "CPedIK: error");