summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/PlayerInfo.h2
-rw-r--r--src/peds/Ped.cpp1244
-rw-r--r--src/peds/Ped.h50
-rw-r--r--src/peds/PedIK.cpp1
-rw-r--r--src/peds/PedIK.h1
5 files changed, 1192 insertions, 106 deletions
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index decfb24c..5edbc8d0 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -26,7 +26,7 @@ public:
int32 m_nVisibleMoney;
int32 m_nCollectedPackages;
int32 m_nTotalPackages;
- int32 field_188;
+ uint32 m_nLastBumpPlayerCarTimer;
int32 m_nSwitchTaxiTime;
bool m_bSwitchTaxi;
int8 field_197;
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index a590c1ed..be90473b 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -37,10 +37,10 @@
#include "RwHelper.h"
#include "Font.h"
#include "Text.h"
+#include "CopPed.h"
WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
-WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); }
WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); }
WRAPPER void CPed::Render(void) { EAXJMP(0x4D03F0); }
WRAPPER int32 CPed::ProcessEntityCollision(CEntity*, CColPoint*) { EAXJMP(0x4CBB30); }
@@ -54,6 +54,16 @@ WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); }
WRAPPER void CPed::SetDirectionToWalkAroundObject(CEntity*) { EAXJMP(0x4CCEB0); }
WRAPPER void CPed::SetRadioStation(void) { EAXJMP(0x4D7BC0); }
WRAPPER void CPed::ProcessObjective(void) { EAXJMP(0x4D94E0); }
+WRAPPER void CPed::ProcessBuoyancy(void) { EAXJMP(0x4C7FF0); }
+WRAPPER bool CPed::ServiceTalkingWhenDead(void) { EAXJMP(0x4E5850); }
+WRAPPER void CPed::ServiceTalking(void) { EAXJMP(0x4E5870); }
+WRAPPER void CPed::SetJump(void) { EAXJMP(0x4D73D0); }
+WRAPPER void CPed::UpdatePosition(void) { EAXJMP(0x4C7A00); }
+WRAPPER void CPed::WanderRange(void) { EAXJMP(0x4D26C0); }
+WRAPPER void CPed::WanderPath(void) { EAXJMP(0x4D28D0); }
+WRAPPER void CPed::ReactToPointGun(CEntity*) { EAXJMP(0x4DD980); }
+WRAPPER void CPed::SeekCar(void) { EAXJMP(0x4D3F90); }
+WRAPPER void CPed::SeekBoatPosition(void) { EAXJMP(0x4E4C70); }
CPed *gapTempPedList[50];
uint16 gnNumTempPedList;
@@ -80,7 +90,7 @@ CVector &vecPedQuickDraggedOutCarAnimOffset = *(CVector*)0x62E06C;
CVector &vecPedDraggedOutCarAnimOffset = *(CVector*)0x62E060;
CVector &vecPedTrainDoorAnimOffset = *(CVector*)0x62E054;
-CVector2D &CPed::ms_vec2DFleePosition = *(CVector2D*)0x6EDF70;
+CVector2D CPed::ms_vec2DFleePosition; // = *(CVector2D*)0x6EDF70;
void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); }
void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); }
@@ -242,7 +252,6 @@ static char WaitStateText[21][16] = {
"Finish Flee",
};
-
#ifndef MASTER
int nDisplayDebugInfo = 0;
bool CPed::bUnusedFightThingOnPlayer = false;
@@ -383,7 +392,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_timerUnused = 0;
m_lookTimer = 0;
m_standardTimer = 0;
- m_lastHitTime = 0;
+ m_shootTimer = 0;
m_hitRecoverTimer = 0;
m_duckAndCoverTimer = 0;
m_moved = CVector2D(0.0f, 0.0f);
@@ -451,7 +460,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bIsInTheAir = false;
bIsLanding = false;
bIsRunning = false;
- m_ped_flagB40 = false;
+ bHitSomethingLastFrame = false;
m_ped_flagB80 = false;
m_ped_flagC1 = false;
@@ -481,7 +490,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bDoBloodyFootprints = false;
m_ped_flagE80 = false;
- m_ped_flagF1 = false;
+ bWanderPathAfterExitingCar = false;
m_ped_flagF2 = false;
m_ped_flagF4 = false;
m_ped_flagF8 = false;
@@ -493,11 +502,11 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_ped_flagG1 = false;
m_ped_flagG2 = true;
m_ped_flagG4 = false;
- m_ped_flagG8 = false;
+ bStartWanderPathOnFoot = false;
m_ped_flagG10 = false;
m_ped_flagG20 = false;
m_ped_flagG40 = false;
- m_ped_flagG80 = false;
+ bFadeOut = false;
m_ped_flagH1 = false;
m_ped_flagH2 = false;
@@ -689,7 +698,7 @@ CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)
bool
CPed::IsPlayer(void)
{
- return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType== PEDTYPE_PLAYER2 ||
+ return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||
m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;
}
@@ -1073,7 +1082,7 @@ CPed::Attack(void)
eWeaponFire ourWeaponFire;
float animLoopEnd;
CWeaponInfo *ourWeapon;
- bool lastReloadWasInFuture;
+ bool attackShouldContinue;
AnimationId reloadAnim;
CAnimBlendAssociation *reloadAnimAssoc;
float delayBetweenAnimAndFire;
@@ -1083,7 +1092,7 @@ CPed::Attack(void)
ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
ourWeaponFire = ourWeapon->m_eWeaponFire;
weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
- lastReloadWasInFuture = bIsAttacking;
+ attackShouldContinue = bIsAttacking;
reloadAnimAssoc = nil;
reloadAnim = NUM_ANIMS;
delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;
@@ -1107,9 +1116,8 @@ CPed::Attack(void)
return;
}
- // BUG: We currently don't know any situation this cond. could be true.
- if (CTimer::GetTimeInMilliseconds() < m_lastHitTime)
- lastReloadWasInFuture = true;
+ if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ attackShouldContinue = true;
if (!weaponAnimAssoc) {
weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
@@ -1122,7 +1130,7 @@ CPed::Attack(void)
}
if (!weaponAnimAssoc) {
- if (lastReloadWasInFuture) {
+ if (attackShouldContinue) {
if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->field_1380) {
if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
@@ -1198,7 +1206,7 @@ CPed::Attack(void)
ClearAimFlag();
bIsAttacking = false;
bIsPointingGunAt = false;
- m_lastHitTime = CTimer::GetTimeInMilliseconds();
+ m_shootTimer = CTimer::GetTimeInMilliseconds();
return;
}
} else {
@@ -1210,12 +1218,12 @@ CPed::Attack(void)
weaponAnimAssoc->speed = 0.5f;
- if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_lastHitTime) {
+ if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
weaponAnimAssoc->callbackType = 0;
}
}
- lastReloadWasInFuture = false;
+ attackShouldContinue = false;
}
if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
@@ -1251,7 +1259,7 @@ CPed::Attack(void)
if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) {
if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
- && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_lastHitTime)
+ && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
&& GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
weaponAnim = weaponAnimAssoc->animId;
@@ -1296,9 +1304,9 @@ CPed::Attack(void)
}
}
if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)
- lastReloadWasInFuture = false;
+ attackShouldContinue = false;
- bIsAttacking = lastReloadWasInFuture;
+ bIsAttacking = attackShouldContinue;
}
void
@@ -1351,7 +1359,7 @@ CPed::Duck(void)
void
CPed::ClearDuck(void)
{
- CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
@@ -1391,7 +1399,7 @@ CPed::ClearPointGunAt(void)
}
if (animAssoc) {
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -4.0;
+ animAssoc->blendDelta = -4.0f;
}
}
}
@@ -2273,7 +2281,7 @@ CPed::CalculateNewVelocity(void)
}
CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- CAnimBlendAssociation* fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
LimbOrientation newUpperLegs;
@@ -2325,9 +2333,10 @@ CPed::CanPedDriveOff(void)
return true;
}
-// I couldn't find where it is used.
+
+// TODO: Make this function actually work.
bool
-CPed::CanPedJumpThis(int32 unused)
+CPed::CanPedJumpThis(CEntity *unused)
{
CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
CVector pos = GetPosition();
@@ -2643,7 +2652,7 @@ CPed::SetObjective(eObjective newObj)
if ((m_objective == OBJECTIVE_LEAVE_VEHICLE || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
&& IsPedInControl()) {
- m_ped_flagG8 = true;
+ bStartWanderPathOnFoot = true;
return;
}
// Unused code from assembly...
@@ -2809,7 +2818,7 @@ CPed::QuitEnteringCar(void)
if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD) {
animAssoc = m_pVehicleAnim;
if (animAssoc) {
- animAssoc->blendDelta = -4.0;
+ animAssoc->blendDelta = -4.0f;
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
animAssoc = m_pVehicleAnim;
animAssoc->flags &= ~ASSOC_RUNNING;
@@ -3251,7 +3260,7 @@ CPed::ClearAttackByRemovingAnim(void)
void
CPed::StopNonPartialAnims(void)
{
- CAnimBlendAssociation* assoc;
+ CAnimBlendAssociation *assoc;
for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
if (!assoc->IsPartial())
@@ -3330,7 +3339,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed)
}
bool
-CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
+CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
{
CPlayerPed *player = FindPlayerPed();
float dieDelta = 4.0f;
@@ -3768,7 +3777,7 @@ CPed::SetGetUp(void)
m_nPedState = PED_GETUP;
}
- CVehicle* collidingVeh = (CVehicle*)m_pCollidingEntity;
+ CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;
CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());
if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE ||
collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE
@@ -3874,7 +3883,7 @@ CPed::ClearObjective(void)
if (m_pMyVehicle->pDriver != this) {
- m_ped_flagF1 = true;
+ bWanderPathAfterExitingCar = true;
SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
}
} else {
@@ -3942,7 +3951,7 @@ CPed::SetWanderPath(int8 pathStateDest)
}
} else {
m_nPathState = pathStateDest;
- m_ped_flagG8 = true;
+ bStartWanderPathOnFoot = true;
return false;
}
}
@@ -3989,7 +3998,7 @@ CPed::RestoreHeadingRate(void)
}
void
-CPed::RestoreHeadingRateCB(CAnimBlendAssociation* assoc, void* arg)
+CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)
{
((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate;
}
@@ -4208,12 +4217,12 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
}
void
-CPed::SetEvasiveDive(CPhysical* reason, uint8 onlyRandomJump)
+CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
{
if (!IsPedInControl() || !bRespondsToThreats)
return;
- CAnimBlendAssociation* animAssoc;
+ CAnimBlendAssociation *animAssoc;
float angleToFace, neededTurn;
bool handsUp = false;
@@ -4320,7 +4329,7 @@ CPed::SetEvasiveDive(CPhysical* reason, uint8 onlyRandomJump)
}
void
-CPed::SetAttack(CEntity* victim)
+CPed::SetAttack(CEntity *victim)
{
CPed *victimPed = nil;
if (victim && victim->IsPed())
@@ -4525,7 +4534,7 @@ CPed::StartFightAttack(uint8 buttonPressure)
}
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f);
animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightUnk2 = 0;
+ m_fightState = FIGHTSTATE_NO_MOVE;
m_takeAStepAfterAttack = false;
#ifndef MASTER
m_takeAStepAfterAttack = IsPlayer() && bUnusedFightThingOnPlayer;
@@ -4545,7 +4554,7 @@ CPed::LoadFightData(void)
char line[256], moveName[32], animName[32], hitLevel;
int moveId = 0;
- CAnimBlendAssociation* animAssoc;
+ CAnimBlendAssociation *animAssoc;
int bp, buflen;
int lp, linelen;
@@ -4637,18 +4646,19 @@ CPed::GetLocalDirection(const CVector2D &posOffset)
bool
CPed::FightStrike(CVector &touchedNodePos)
{
- CColModel* ourCol;
+ CColModel *ourCol;
CVector attackDistance;
ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
float maxDistanceToBeBeaten;
CPed *nearPed;
- int unk = m_fightUnk2;
+ int state = m_fightState;
bool pedFound = false;
- if (unk == -1)
+ if (state == FIGHTSTATE_JUST_ATTACKED)
return false;
- if (unk > 0)
+ // Pointless code
+ if (state > FIGHTSTATE_NO_MOVE)
attackDistance = touchedNodePos - m_vecHitLastPos;
for (int i = 0; i < m_numNearPeds; i++) {
@@ -4733,7 +4743,7 @@ CPed::FightStrike(CVector &touchedNodePos)
nearPed->StartFightDefend(direction, tFightMoves[m_lastFightMove].hitLevel, unk2);
PlayHitSound(nearPed);
- m_fightUnk2 = -1;
+ m_fightState = FIGHTSTATE_JUST_ATTACKED;
RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[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);
@@ -4785,8 +4795,8 @@ CPed::FightStrike(CVector &touchedNodePos)
CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
}
- if (!m_fightUnk2)
- m_fightUnk2 = 1;
+ if (!m_fightState)
+ m_fightState = FIGHTSTATE_1;
m_vecHitLastPos = *touchedNodePos;
return false;
@@ -4836,7 +4846,7 @@ CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
}
void
-CPed::SetFlee(CEntity* fleeFrom, int time)
+CPed::SetFlee(CEntity *fleeFrom, int time)
{
if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)
return;
@@ -5443,7 +5453,7 @@ void
CPed::SetAttackTimer(uint32 time)
{
if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
- m_attackTimer = max(m_lastHitTime, CTimer::GetTimeInMilliseconds()) + time;
+ m_attackTimer = max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
}
void
@@ -5491,6 +5501,20 @@ CPed::SetBuyIceCream(void)
if (!m_carInObjective)
return;
+#ifdef FIX_ICECREAM
+
+ // Simulating BuyIceCream
+ CPed* driver = m_carInObjective->pDriver;
+ if (driver) {
+ m_nPedState = PED_BUY_ICECREAM;
+ bFindNewNodeAfterStateRestore = true;
+ SetObjectiveTimer(8000);
+ SetChat(driver, 8000);
+ driver->SetChat(this, 8000);
+ return;
+ }
+#endif
+
// Side of the Ice Cream van
m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
@@ -5501,7 +5525,7 @@ CPed::SetBuyIceCream(void)
}
void
-CPed::SetChat(CEntity* chatWith, uint32 time)
+CPed::SetChat(CEntity *chatWith, uint32 time)
{
if(m_nPedState != PED_CHAT)
SetStoredState();
@@ -5537,7 +5561,7 @@ CPed::SetDead(void)
// BUG: Is this count or timer?!
m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds();
- m_deadBleeding = 0;
+ m_deadBleeding = false;
bDoBloodyFootprints = false;
m_ped_flagI4 = false;
CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
@@ -5604,7 +5628,7 @@ CPed::DeadPedMakesTyresBloody(void)
for (int curY = minY; curY <= maxY; curY++) {
for (int curX = minX; curX <= maxX; curX++) {
- CSector* sector = CWorld::GetSector(curX, curY);
+ CSector *sector = CWorld::GetSector(curX, curY);
MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]);
MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
}
@@ -5675,7 +5699,7 @@ CPed::DuckAndCover(void)
if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
CVector pos = GetPosition();
int16 lastVehicle;
- CEntity* vehicles[8];
+ CEntity *vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for (int i = 0; i < lastVehicle; i++) {
@@ -5807,7 +5831,7 @@ void
CPed::EnterCar(void)
{
if (m_pMyVehicle && m_pMyVehicle->m_status != STATUS_WRECKED && m_fHealth > 0.0f) {
- CVehicle* veh = (CVehicle*)m_pSeekTarget;
+ CVehicle *veh = (CVehicle*)m_pSeekTarget;
// Not used.
// CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
@@ -5906,7 +5930,7 @@ void
CPed::LineUpPedWithTrain(void)
{
CVector lineUpPos;
- CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pMyVehicle->m_modelIndex);
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pMyVehicle->m_modelIndex);
CVector enterOffset(1.5f, 0.0f, -0.2f);
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
@@ -6035,10 +6059,10 @@ CPed::Fight(void)
else
EndFight(ENDFIGHT_FAST);
- } else if (currentAssoc && m_fightUnk2 > -2) {
+ } else if (currentAssoc && m_fightState != FIGHTSTATE_MOVE_FINISHED) {
float animTime = currentAssoc->currentTime;
FightMove &curMove = tFightMoves[m_lastFightMove];
- if (curMove.hitLevel != 0 && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightUnk2 >= 0) {
+ if (curMove.hitLevel != 0 && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
CVector touchingNodePos(0.0f, 0.0f, 0.0f);
RwFrame *touchingFrame = nil;
@@ -6307,13 +6331,13 @@ CPed::Fight(void)
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f);
animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- if (m_fightUnk2 == -2 && animAssoc->currentTime != 0.0f) {
+ if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
animAssoc->SetCurrentTime(0.0f);
animAssoc->SetRun();
}
m_fightButtonPressure = 0;
}
- m_fightUnk2 = 0;
+ m_fightState = FIGHTSTATE_NO_MOVE;
} else if (m_takeAStepAfterAttack && m_lastFightMove != FIGHTMOVE_SHUFFLE_F
#ifndef FIX_BUGS
&& CheckForPedsOnGroundToAttack(this, nil) == 4) {
@@ -6331,7 +6355,7 @@ CPed::Fight(void)
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 32.0f);
}
animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightUnk2 = 0;
+ m_fightState = FIGHTSTATE_NO_MOVE;
m_fightButtonPressure = 0;
m_takeAStepAfterAttack = false;
@@ -6435,7 +6459,7 @@ CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
CPed *ped = (CPed*)arg;
if (tFightMoves[ped->m_lastFightMove].animId == animAssoc->animId) {
- ped->m_fightUnk2 = -2;
+ ped->m_fightState = FIGHTSTATE_MOVE_FINISHED;
animAssoc->blendDelta = -1000.0f;
}
}
@@ -6459,7 +6483,7 @@ CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)
void
CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- CPed* ped = (CPed*)arg;
+ CPed *ped = (CPed*)arg;
ped->m_ped_flagG4 = true;
ped->bIsLanding = false;
@@ -6545,7 +6569,7 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
255, 255, 0, 0, 4.0f, 3000, 1.0f);
bloodPos = CVector(0.0f, 0.0f, 0.0f);
- for (RwFrame* j = ped->GetNodeFrame(PED_FOOTR); j; j = RwFrameGetParent(j))
+ for (RwFrame *j = ped->GetNodeFrame(PED_FOOTR); j; j = RwFrameGetParent(j))
RwV3dTransformPoints(bloodPos, bloodPos, 1, RwFrameGetMatrix(j));
bloodPos.z -= 0.1f;
@@ -6569,7 +6593,7 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
void
CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- CPed* ped = (CPed*)arg;
+ CPed *ped = (CPed*)arg;
ped->m_nWaitTimer = 0;
ped->RestoreHeadingRate();
@@ -7552,7 +7576,7 @@ CPed::Idle(void)
}
CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
- CAnimBlendAssociation* unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
int waitTime;
if (m_nMoveState == PEDMOVE_STILL) {
@@ -7661,7 +7685,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedDraggedOutCarAnimOffset = lastFrame->translation;
}
}
@@ -7673,7 +7697,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedCarDoorAnimOffset = lastFrame->translation;
}
}
@@ -7685,7 +7709,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedCarDoorLoAnimOffset = lastFrame->translation;
}
}
@@ -7697,7 +7721,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
}
}
@@ -7709,7 +7733,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedVanRearDoorAnimOffset = lastFrame->translation;
}
}
@@ -7721,7 +7745,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
- KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
vecPedTrainDoorAnimOffset = lastFrame->translation;
}
}
@@ -7966,10 +7990,10 @@ CPed::IsRoomToBeCarJacked(void)
}
void
-CPed::KillPedWithCar(CVehicle* car, float impulse)
+CPed::KillPedWithCar(CVehicle *car, float impulse)
{
- CVehicleModelInfo* vehModel;
- CColModel* vehColModel;
+ CVehicleModelInfo *vehModel;
+ CColModel *vehColModel;
uint8 damageDir;
PedNode nodeToDamage;
eWeaponType killMethod;
@@ -8014,7 +8038,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
killMethod = WEAPONTYPE_RUNOVERBYCAR;
nodeToDamage = PED_HEAD;
m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0;
+ m_vecMoveSpeed.z = 0.0f;
if (damageDir == 1 || damageDir == 3)
damageDir = 2;
if (CGame::nastyGame)
@@ -8034,7 +8058,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
killMethod = WEAPONTYPE_RUNOVERBYCAR;
m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0;
+ m_vecMoveSpeed.z = 0.0f;
if (damageDir == 1 || damageDir == 3)
damageDir = 2;
if (CGame::nastyGame)
@@ -8049,7 +8073,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
killMethod = WEAPONTYPE_RUNOVERBYCAR;
nodeToDamage = PED_HEAD;
m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0;
+ m_vecMoveSpeed.z = 0.0f;
if (damageDir == 1 || damageDir == 3)
damageDir = 2;
@@ -8232,7 +8256,7 @@ CPed::LookForInterestingNodes(void)
for (int curY = minY; curY <= maxY && !found; curY++) {
for (int curX = minX; curX <= maxX && !found; curX++) {
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CVehicle* veh = (CVehicle*)ptrNode->item;
+ CVehicle *veh = (CVehicle*)ptrNode->item;
model = veh->GetModelInfo();
if (model->m_num2dEffects != 0) {
for (int e = 0; e < model->m_num2dEffects; e++) {
@@ -8250,7 +8274,7 @@ CPed::LookForInterestingNodes(void)
}
}
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CObject* obj = (CObject*)ptrNode->item;
+ CObject *obj = (CObject*)ptrNode->item;
model = CModelInfo::GetModelInfo(obj->m_modelIndex);
if (model->m_num2dEffects != 0) {
for (int e = 0; e < model->m_num2dEffects; e++) {
@@ -8268,7 +8292,7 @@ CPed::LookForInterestingNodes(void)
}
}
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding* building = (CBuilding*)ptrNode->item;
+ CBuilding *building = (CBuilding*)ptrNode->item;
model = CModelInfo::GetModelInfo(building->m_modelIndex);
if (model->m_num2dEffects != 0) {
for (int e = 0; e < model->m_num2dEffects; e++) {
@@ -8286,7 +8310,7 @@ CPed::LookForInterestingNodes(void)
}
}
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding* building = (CBuilding*)ptrNode->item;
+ CBuilding *building = (CBuilding*)ptrNode->item;
model = CModelInfo::GetModelInfo(building->m_modelIndex);
if (model->m_num2dEffects != 0) {
for (int e = 0; e < model->m_num2dEffects; e++) {
@@ -8416,8 +8440,8 @@ CPed::LookForSexyPeds(void)
void
CPed::MakeTyresMuddySectorList(CPtrList &list)
{
- for (CPtrNode* node = list.first; node; node = node->next) {
- CVehicle* veh = (CVehicle*)node->item;
+ for (CPtrNode *node = list.first; node; node = node->next) {
+ CVehicle *veh = (CVehicle*)node->item;
if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) {
veh->m_scanCode = CWorld::GetCurrentScanCode();
@@ -8513,7 +8537,7 @@ CPed::MoveHeadToLook(void)
if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- CAnimBlendAssociation* fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
+ CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
if (fuckUAssoc) {
float animTime = fuckUAssoc->currentTime;
@@ -8615,9 +8639,9 @@ CPed::MoveHeadToLook(void)
}
void
-FinishFuckUCB(CAnimBlendAssociation* animAssoc, void* arg)
+FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- CPed* ped = (CPed*)arg;
+ CPed *ped = (CPed*)arg;
if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
ped->RemoveWeaponModel(0);
@@ -8631,9 +8655,9 @@ CPed::Pause(void) {
}
void
-CPed::PedAnimAlignCB(CAnimBlendAssociation* animAssoc, void* arg)
+CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- CPed* ped = (CPed*)arg;
+ CPed *ped = (CPed*)arg;
CVehicle *veh = ped->m_pMyVehicle;
if (animAssoc)
@@ -8747,6 +8771,1044 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation* animAssoc, void* arg)
}
}
+void
+CPed::ProcessControl(void)
+{
+ CColPoint foundCol;
+ CEntity *foundEnt = nil;
+
+ if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
+ return;
+
+ int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
+ if (!bFadeOut) {
+ if (alpha < 255) {
+ alpha += 16;
+ if (alpha > 255)
+ alpha = 255;
+ }
+ } else {
+ alpha -= 8;
+ if (alpha < 0)
+ alpha = 0;
+ }
+
+ CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha);
+ m_ped_flagC40 = false;
+ BuildPedLists();
+ bIsInWater = false;
+ ProcessBuoyancy();
+
+ if (m_nPedState != PED_ARRESTED) {
+ if (m_nPedState == PED_DEAD) {
+ DeadPedMakesTyresBloody();
+ if (CGame::nastyGame) {
+ uint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCount;
+ float timeDependentDist;
+ if (remainingBloodyFpTime >= 2000) {
+ if (remainingBloodyFpTime <= 7000)
+ timeDependentDist = (remainingBloodyFpTime - 2000) / 5000 * 0.75f;
+ else
+ timeDependentDist = 0.75f;
+ } else {
+ timeDependentDist = 0.0f;
+ }
+
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
+ PedState nearPedState = nearPed->m_nPedState;
+ if (nearPedState != PED_DIE && nearPedState != PED_DEAD) {
+ CVector dist = nearPed->GetPosition() - GetPosition();
+ if (dist.MagnitudeSqr() < sq(timeDependentDist)) {
+ nearPed->m_bloodyFootprintCount = 200;
+ nearPed->bDoBloodyFootprints = true;
+ if (nearPed->IsPlayer()) {
+ if (!nearPed->bIsLooking && nearPedState != PED_ATTACK) {
+ int16 camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
+ if (camMode != CCam::MODE_SNIPER
+ && camMode != CCam::MODE_ROCKET
+ && camMode != CCam::MODE_M16FIRSTPERSON_34
+ && camMode != CCam::MODE_FIRSTPERSON
+ && camMode != CCam::MODE_M16FIRSTPERSON_44
+ && !TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn()) {
+
+ nearPed->SetLookFlag(this, true);
+ nearPed->SetLookTimer(500);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (remainingBloodyFpTime > 2000) {
+ CVector bloodPos = GetPosition();
+ if (remainingBloodyFpTime - 2000 >= 5000) {
+ if (!m_deadBleeding) {
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ 0.75f, 0.0f, 0.0f, -0.75f, 255, 255, 0, 0, 4.0f, 40000, 1.0f);
+ m_deadBleeding = true;
+ }
+ } else {
+ CShadows::StoreStaticShadow(
+ (uintptr)this + 17, SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ (remainingBloodyFpTime - 2000) / 5000 * 0.75f, 0.0f,
+ 0.0f, (remainingBloodyFpTime - 2000) / 5000 * -0.75f,
+ 255, 255, 0, 0, 4.0f, 1.0f, 40.0f, false, 0.0f);
+ }
+ }
+ }
+ if (ServiceTalkingWhenDead())
+ ServiceTalking();
+ return;
+ }
+
+ m_ped_flagA2 = false;
+ if (bIsStanding) {
+ if (!CWorld::bForceProcessControl) {
+ if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->bIsInSafePosition) {
+ bWasPostponed = true;
+ return;
+ }
+ }
+ }
+
+ if (!IsPedInControl() || m_nWaitState != WAITSTATE_FALSE || 0.01f * CTimer::GetTimeStep() <= m_fDistanceTravelled
+ || (m_nStoredMoveState != PEDMOVE_WALK && m_nStoredMoveState != PEDMOVE_RUN && m_nStoredMoveState != PEDMOVE_SPRINT))
+ m_panicCounter = 0;
+ else if (m_panicCounter < 50)
+ ++m_panicCounter;
+
+ if (m_fHealth <= 1.0f && m_nPedState <= PED_STATES_NO_AI && !bIsInTheAir && !bIsLanding)
+ SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+
+ m_ped_flagH20 = false;
+
+ CEntity *collidingEnt = m_pDamageEntity;
+ if (!bUsesCollision || m_fDamageImpulse <= 0.0f || m_nPedState == PED_DIE || !collidingEnt) {
+ bHitSomethingLastFrame = false;
+ if (m_nPedStateTimer <= 500 && bIsInTheAir) {
+ if (m_nPedStateTimer)
+ m_nPedStateTimer--;
+ } else if (m_nPedStateTimer < 1001) {
+ m_nPedStateTimer = 0;
+ }
+ } else {
+ if (m_panicCounter == 50 && IsPedInControl()) {
+ SetWaitState(WAITSTATE_STUCK, nil);
+ // Leftover
+ /*
+ if (m_nPedType < PEDTYPE_COP) {
+
+ } else {
+
+ }
+ */
+ } else {
+
+ switch (collidingEnt->m_type)
+ {
+ case ENTITY_TYPE_BUILDING:
+ case ENTITY_TYPE_OBJECT:
+ {
+ CBaseModelInfo *collidingModel = CModelInfo::GetModelInfo(collidingEnt->m_modelIndex);
+ CColModel *collidingCol = collidingModel->GetColModel();
+ if (collidingEnt->IsObject() && ((CObject*)collidingEnt)->m_nSpecialCollisionResponseCases != COLLRESPONSE_CHANGE_THEN_SMASH
+ || collidingCol->boundingBox.max.x < 3.0f
+ && collidingCol->boundingBox.max.y < 3.0f) {
+
+ if (!IsPlayer()) {
+ SetDirectionToWalkAroundObject(collidingEnt);
+ break;
+ }
+ }
+ if (IsPlayer()) {
+ bHitSomethingLastFrame = true;
+ break;
+ }
+
+ float angleToFlee = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x,
+ GetPosition().y,
+ m_vecDamageNormal.x + GetPosition().x,
+ m_vecDamageNormal.y + GetPosition().y);
+
+ float neededTurn = Abs(m_fRotationCur - angleToFlee);
+
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ float oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest);
+
+ if (m_pedInObjective &&
+ (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) {
+
+ if (m_pedInObjective->IsPlayer()
+ && (neededTurn < DEGTORAD(20.0f) || m_panicCounter > 10)) {
+ if (CanPedJumpThis(collidingEnt)) {
+ SetJump();
+ } else if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {
+ SetWaitState(WAITSTATE_LOOK_ABOUT, nil);
+ } else {
+ SetWaitState(WAITSTATE_PLAYANIM_TAXI, nil);
+ m_headingRate = 0.0f;
+ SetLookFlag(m_pedInObjective, true);
+ SetLookTimer(3000);
+ Say(SOUND_PED_TAXI_CALL);
+ }
+ } else {
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ } else {
+ if (m_nPedType != PEDTYPE_COP && neededTurn < DEGTORAD(15.0f) && m_nWaitState == WAITSTATE_FALSE) {
+ if ((m_nStoredMoveState == PEDMOVE_RUN || m_nStoredMoveState == PEDMOVE_SPRINT) && m_vecDamageNormal.z < 0.3f) {
+ CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN);
+ if (!runAssoc)
+ runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
+
+ if (runAssoc && runAssoc->blendAmount > 0.9f && runAssoc->IsRunning()) {
+ SetWaitState(WAITSTATE_HITWALL, nil);
+ }
+ }
+ }
+ if (m_nPedState == PED_FLEE_POS) {
+ CVector2D fleePos = collidingEnt->GetPosition();
+ uint32 oldFleeTimer = m_fleeTimer;
+ SetFlee(fleePos, 5000);
+ if (oldFleeTimer != m_fleeTimer)
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500;
+
+ } else {
+ if (m_nPedState == PED_FLEE_ENTITY && (neededTurn < DEGTORAD(25.0f) || m_panicCounter > 10)) {
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ m_collidingEntityWhileFleeing = collidingEnt;
+ m_collidingEntityWhileFleeing->RegisterReference((CEntity **) &m_collidingEntityWhileFleeing);
+
+ uint8 currentDir = floorf((PI + m_fRotationCur) / DEGTORAD(45.0f));
+ uint8 nextDir;
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, currentDir, &nextDir);
+
+ } else {
+ if (neededTurn < DEGTORAD(60.0f)) {
+ CVector posToHead = m_vecDamageNormal * 4.0f;
+ posToHead.z = 0.0f;
+ posToHead += GetPosition();
+ int closestNodeId = ThePaths.FindNodeClosestToCoors(posToHead, PATH_PED,
+ 999999.9f, false, false);
+ float angleToFace;
+
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ if (m_nPedState != PED_SEEK_POS && m_nPedState != PED_SEEK_CAR) {
+ if (m_nPedState == PED_WANDER_PATH) {
+ m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId];
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ m_pNextPathNode->pos.x, m_pNextPathNode->pos.y,
+ GetPosition().x, GetPosition().y);
+ } else {
+ if (ThePaths.m_pathNodes[closestNodeId].pos.x == 0.0f
+ || ThePaths.m_pathNodes[closestNodeId].pos.y == 0.0f) {
+ posToHead = (3.0f * m_vecDamageNormal) + GetPosition();
+ posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
+ posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
+ } else {
+ posToHead.x = ThePaths.m_pathNodes[closestNodeId].pos.x;
+ posToHead.y = ThePaths.m_pathNodes[closestNodeId].pos.y;
+ }
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ posToHead.x, posToHead.y,
+ GetPosition().x, GetPosition().y);
+
+ if (m_nPedState != PED_FOLLOW_PATH)
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500;
+ }
+ } else {
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ ThePaths.m_pathNodes[closestNodeId].pos.x,
+ ThePaths.m_pathNodes[closestNodeId].pos.y,
+ GetPosition().x,
+ GetPosition().y);
+
+ CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].pos - GetPosition();
+ CVector2D distToSeekPos = m_vecSeekPos - GetPosition();
+
+ if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) {
+ m_fRotationCur = m_fRotationDest;
+ break;
+ }
+ }
+ } else {
+ float angleToFaceAwayDamage = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecDamageNormal.x,
+ m_vecDamageNormal.y,
+ 0.0f,
+ 0.0f);
+
+ if (angleToFaceAwayDamage < m_fRotationCur)
+ angleToFaceAwayDamage += TWOPI;
+
+ float neededTurn = angleToFaceAwayDamage - m_fRotationCur;
+
+ if (neededTurn <= PI) {
+ angleToFace = 0.5f * neededTurn + m_fRotationCur;
+ m_fRotationCur += DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f;
+ } else {
+ angleToFace = m_fRotationCur - (TWOPI - neededTurn) * 0.5f;
+ m_fRotationCur -= DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f;
+ }
+
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200;
+ if (m_nPedType == PEDTYPE_COP) {
+ if (m_pedInObjective) {
+ float angleToLookCriminal = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x,
+ m_pedInObjective->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ angleToLookCriminal = CGeneral::LimitRadianAngle(angleToLookCriminal);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+
+ if (angleToLookCriminal < angleToFace)
+ angleToLookCriminal += TWOPI;
+
+ float neededTurnToCriminal = angleToLookCriminal - angleToFace;
+
+ if (neededTurnToCriminal > DEGTORAD(150.0f) && neededTurnToCriminal < DEGTORAD(210.0f)) {
+ ((CCopPed*)this)->m_bZoneDisabledButClose = true;
+ }
+ }
+ }
+ }
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
+
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ m_fRotationDest += TWOPI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ m_fRotationDest -= TWOPI;
+ }
+
+ if (oldDestRot == m_fRotationDest && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200;
+ m_fRotationDest += HALFPI;
+ }
+ }
+ }
+ }
+ }
+
+ if (m_nPedState != PED_WANDER_PATH && m_nPedState != PED_FLEE_ENTITY)
+ m_pNextPathNode = nil;
+
+ bHitSomethingLastFrame = true;
+ break;
+ }
+ case ENTITY_TYPE_VEHICLE:
+ {
+ CVehicle *collidingVeh = ((CVehicle*)collidingEnt);
+ float collidingVehSpeedSqr = collidingVeh->m_vecMoveSpeed.MagnitudeSqr();
+
+ if (collidingVeh == m_pMyVehicle)
+ m_ped_flagH20 = true;
+
+ if (collidingVehSpeedSqr <= 1.0f / 400.0f) {
+ if (!IsPedInControl()
+ || IsPlayer()
+ && m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT
+ && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER
+ && m_objective != OBJECTIVE_RUN_TO_AREA) {
+
+ if (IsPlayer() && !bIsInTheAir) {
+
+ if (IsPedInControl()
+ && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f
+ && !bIsLooking
+ && CTimer::GetTimeInMilliseconds() > m_lookTimer
+ && collidingVeh->pDriver) {
+
+ ((CPlayerPed*)this)->AnnoyPlayerPed(false);
+ SetLookFlag(collidingVeh, true);
+ SetLookTimer(1300);
+
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (weaponType == WEAPONTYPE_UNARMED
+ || weaponType == WEAPONTYPE_BASEBALLBAT
+ || weaponType == WEAPONTYPE_COLT45
+ || weaponType == WEAPONTYPE_UZI) {
+ bShakeFist = true;
+ }
+ } else {
+ SetLookFlag(collidingVeh, true);
+ SetLookTimer(500);
+ }
+ }
+ } else if (!m_ped_flagB80) {
+
+ // I don't remember any condition that we were STATUS_PLAYER.
+ if (collidingVeh->m_status != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) {
+
+ SetDirectionToWalkAroundObject(collidingVeh);
+
+ } else if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer
+ || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) {
+
+ CPed::SetDirectionToWalkAroundObject(collidingVeh);
+ CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
+
+ } else if (m_fleeFrom != collidingVeh) {
+ SetFlee(collidingVeh, 4000);
+ bUsePedNodeSeek = false;
+ SetMoveState(PEDMOVE_WALK);
+ }
+ }
+ } else {
+ DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, 142, m_fDamageImpulse);
+ if (IsPlayer()) {
+ CColModel *collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel();
+ CVector colMinVec = collidingCol->boundingBox.min;
+ CVector colMaxVec = collidingCol->boundingBox.max;
+
+ CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition();
+
+ // TLVC = To look vehicle center
+
+ float angleToVehFront = collidingVeh->GetForward().Heading();
+ float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading();
+ angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC);
+
+ // Not sure about this one
+ float minNeededTurnTLVC = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y);
+
+ CVector vehDist = GetPosition() - collidingVeh->GetPosition();
+ vehDist.Normalise();
+
+ float vehRightVecAndSpeedDotProd;
+
+ if (Abs(angleDiffFromLookingFrontTLVC) >= minNeededTurnTLVC && Abs(angleDiffFromLookingFrontTLVC) < PI - minNeededTurnTLVC) {
+ if (angleDiffFromLookingFrontTLVC <= 0.0f) {
+ vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);
+
+ // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right?
+ if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) {
+
+ // Car's right faces towards us and isn't coming directly to us
+ if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f
+ && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) {
+ SetEvasiveStep(collidingVeh, 1);
+ }
+ }
+ } else {
+ vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);
+
+ if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) {
+ if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f
+ && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) {
+ SetEvasiveStep(collidingVeh, 1);
+ }
+ }
+ }
+ } else {
+ vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed);
+ }
+
+ if (vehRightVecAndSpeedDotProd <= 0.1f) {
+ if (m_nPedState != PED_FIGHT) {
+ SetLookFlag(collidingVeh, true);
+ SetLookTimer(700);
+ }
+ } else {
+ bIsStanding = false;
+ CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed;
+ int dir = GetLocalDirection(collidingEntMoveDir);
+ SetFall(1000, (AnimationId)(dir + 25), false);
+ CPed *driver = collidingVeh->pDriver;
+
+ float damage;
+ if (driver && driver->IsPlayer()) {
+ damage = vehRightVecAndSpeedDotProd * 1000.0f;
+ } else if (collidingVeh->m_modelIndex == MI_TRAIN) {
+ damage = 50.0f;
+ } else {
+ damage = 20.0f;
+ }
+
+ InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir);
+ Say(SOUND_PED_DAMAGE);
+ }
+ } else {
+ KillPedWithCar(collidingVeh, m_fDamageImpulse);
+ }
+ }
+ break;
+ }
+ case ENTITY_TYPE_PED:
+ {
+ CollideWithPed((CPed*)collidingEnt);
+ if (((CPed*)collidingEnt)->IsPlayer()) {
+ CPlayerPed *player = ((CPlayerPed*)collidingEnt);
+ Say(SOUND_PED_CHAT);
+ if (m_nMoveState > PEDMOVE_STILL && player->IsPedInControl()) {
+ if (player->m_fMoveSpeed < 1.0f) {
+ if (!player->bIsLooking) {
+ if (CTimer::GetTimeInMilliseconds() > player->m_lookTimer) {
+ player->AnnoyPlayerPed(false);
+ player->SetLookFlag(this, true);
+ player->SetLookTimer(1300);
+ eWeaponType weapon = player->GetWeapon()->m_eWeaponType;
+ if (weapon == WEAPONTYPE_UNARMED
+ || weapon == WEAPONTYPE_BASEBALLBAT
+ || weapon == WEAPONTYPE_COLT45
+ || weapon == WEAPONTYPE_UZI) {
+ player->bShakeFist = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ CVector forceDir;
+ if (!bIsInTheAir && m_nPedState != PED_JUMP) {
+ forceDir = m_vecDamageNormal;
+ forceDir.z = 0.0f;
+ if (!bIsStanding) {
+ forceDir *= 4.0f;
+ } else {
+ forceDir *= 0.5f;
+ }
+
+ ApplyMoveForce(forceDir);
+ }
+ if (bIsInTheAir && m_nPedState != PED_DIE && m_nPedState != PED_DEAD) {
+ if (m_nPedStateTimer <= 1000 && m_nPedStateTimer) {
+ forceDir = GetPosition() - m_vecHitLastPos;
+ } else {
+ m_nPedStateTimer = 0;
+ m_vecHitLastPos = GetPosition();
+ forceDir = CVector(0.0f, 0.0f, 0.0f);
+ }
+
+ CVector offsetToCheck;
+ m_nPedStateTimer++;
+
+ float adjustedTs = max(CTimer::GetTimeStep(), 0.01f);
+
+ CPad *pad0 = CPad::GetPad(0);
+ if ((m_nPedStateTimer <= 50.0f / (4.0f * adjustedTs) || m_nPedStateTimer * 0.01f <= forceDir.MagnitudeSqr())
+ && (m_nCollisionRecords <= 1 || m_nPedStateTimer <= 50.0f / (2.0f * adjustedTs) || m_nPedStateTimer * 1.0f / 250.0f <= Abs(forceDir.z))) {
+
+ if (m_nCollisionRecords == 1 && m_aCollisionRecords[0] != nil && m_aCollisionRecords[0]->m_type == ENTITY_TYPE_BUILDING
+ && m_nPedStateTimer > 50.0f / (2.0f * adjustedTs) && m_nPedStateTimer * 1.0f / 250.0f > Abs(forceDir.z)) {
+ offsetToCheck.x = -forceDir.y;
+ offsetToCheck.z = 0.0f;
+ offsetToCheck.y = forceDir.x;
+ offsetToCheck.Normalise();
+
+ CVector posToCheck = GetPosition() + offsetToCheck;
+ float lastCollidingColZ;
+
+ if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, foundCol, foundEnt, true, false, false, false, false, false, false)) {
+ lastCollidingColZ = foundCol.point.z;
+ } else {
+ lastCollidingColZ = 500.0f;
+ }
+
+ posToCheck = GetPosition() - offsetToCheck;
+ float lastCollidingColInOtherDirZ;
+
+ if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, foundCol, foundEnt, true, false, false, false, false, false, false)) {
+ lastCollidingColInOtherDirZ = foundCol.point.z;
+ } else {
+ lastCollidingColInOtherDirZ = 501.0f;
+ }
+
+ if (lastCollidingColZ < lastCollidingColInOtherDirZ) {
+ offsetToCheck *= -1.0f;
+ }
+ offsetToCheck.z = 1.0f;
+ forceDir = 4.0f * offsetToCheck;
+ forceDir.z = 4.0f;
+ ApplyMoveForce(forceDir);
+
+ GetPosition() += 0.25f * offsetToCheck;
+
+ m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(offsetToCheck.x, offsetToCheck.y, 0.0f, 0.0f);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ m_fRotationDest = m_fRotationCur;
+ CVector pos = GetPosition();
+ GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur);
+ GetPosition() += pos;
+
+ if (m_nPedState != PED_FALL && !bIsPedDieAnimPlaying) {
+ CPed::SetFall(1000, ANIM_KO_SKID_BACK, true);
+ }
+ bIsInTheAir = false;
+ } else if (m_vecDamageNormal.z > 0.4f) {
+ forceDir = m_vecDamageNormal;
+ forceDir.z = 0.0f;
+ forceDir.Normalise();
+ ApplyMoveForce(2.0f * forceDir);
+ }
+ } else if ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 3) & 7) {
+ if (IsPlayer() && m_nPedState != PED_JUMP && pad0->JumpJustDown()) {
+ int16 padWalkX = pad0->GetPedWalkLeftRight();
+ int16 padWalkY = pad0->GetPedWalkUpDown();
+ if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY);
+ m_fRotationDest -= TheCamera.Orientation;
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ m_fRotationCur = m_fRotationDest;
+ CVector pos = GetPosition();
+ GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur);
+ GetPosition() += pos;
+ }
+ SetJump();
+ m_nPedStateTimer = 0;
+ m_vecHitLastPos = GetPosition();
+
+ // Why? forceDir is unused after this point.
+ forceDir = CVector(0.0f, 0.0f, 0.0f);
+ } else if (IsPlayer()) {
+ int16 padWalkX = pad0->GetPedWalkLeftRight();
+ int16 padWalkY = pad0->GetPedWalkUpDown();
+ if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0, 0.0, -padWalkX, padWalkY);
+ m_fRotationDest -= TheCamera.Orientation;
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ m_fRotationCur = m_fRotationDest;
+ CVector pos = GetPosition();
+ GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur);
+ GetPosition() += pos;
+ }
+ CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE);
+
+ if (!jumpAssoc)
+ jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE);
+
+ if (jumpAssoc) {
+ jumpAssoc->blendDelta = -3.0f;
+ jumpAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ if (m_nPedState == PED_JUMP)
+ m_nPedState = PED_IDLE;
+ } else {
+ CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE);
+
+ if (!jumpAssoc)
+ jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE);
+
+ if (jumpAssoc) {
+ jumpAssoc->blendDelta = -3.0f;
+ jumpAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ } else {
+ offsetToCheck = GetPosition();
+ offsetToCheck.z += 0.5f;
+
+ if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - 1.04f, foundCol, foundEnt, true, true, false, true, false, false, false)) {
+ GetPosition().z = 1.04f + foundCol.point.z;
+ GetMatrix().UpdateRW();
+ SetLanding();
+ bIsStanding = true;
+ }
+ }
+ } else if (m_nPedStateTimer < 1001) {
+ m_nPedStateTimer = 0;
+ }
+ }
+
+ if (bIsDucking)
+ Duck();
+
+ if (bStartWanderPathOnFoot) {
+ if (IsPedInControl()) {
+ ClearAll();
+ SetWanderPath(m_nPathState);
+ bStartWanderPathOnFoot = false;
+ } else if (m_nPedState == PED_DRIVING) {
+ bWanderPathAfterExitingCar = true;
+ SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
+ }
+ }
+
+ if (!bIsStanding && m_vecMoveSpeed.z > 0.25f) {
+ double airResistance = Pow(0.95, CTimer::GetTimeStep());
+
+ m_vecMoveSpeed *= airResistance;
+ }
+
+ CPhysical::ProcessControl();
+ if (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) {
+ if (m_nPedState != PED_DEAD) {
+ CalculateNewVelocity();
+ CalculateNewOrientation();
+ }
+ UpdatePosition();
+ PlayFootSteps();
+ if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) {
+ SetInTheAir();
+ }
+
+ ProcessObjective();
+ if (!bIsAimingGun) {
+ if (bIsRestoringGun)
+ RestoreGunPosition();
+ } else {
+ AimGun();
+ }
+
+ if (bIsLooking) {
+ MoveHeadToLook();
+ } else if (bIsRestoringLook) {
+ RestoreHeadPosition();
+ }
+
+ if (bIsInTheAir)
+ InTheAir();
+
+ if (bUpdateAnimHeading) {
+ if (m_nPedState != PED_GETUP && m_nPedState != PED_FALL) {
+ m_fRotationCur -= HALFPI;
+ m_fRotationDest = m_fRotationCur;
+ bUpdateAnimHeading = false;
+ }
+ }
+
+ if (m_nWaitState != WAITSTATE_FALSE)
+ Wait();
+
+ if (m_nPedState != PED_IDLE) {
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
+ if(idleAssoc) {
+ idleAssoc->blendDelta = -8.0f;
+ idleAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+
+ switch (m_nPedState) {
+ case PED_IDLE:
+ Idle();
+ break;
+ case PED_LOOK_ENTITY:
+ case PED_LOOK_HEADING:
+ Look();
+ break;
+ case PED_WANDER_RANGE:
+ WanderRange();
+ CheckAroundForPossibleCollisions();
+ break;
+ case PED_WANDER_PATH:
+ WanderPath();
+ break;
+ case PED_SEEK_POS:
+ case PED_SEEK_ENTITY:
+ case PED_PURSUE:
+ case PED_SNIPER_MODE:
+ case PED_ROCKET_ODE:
+ case PED_DUMMY:
+ case PED_FACE_PHONE:
+ case PED_MAKE_CALL:
+ case PED_MUG:
+ case PED_AI_CONTROL:
+ case PED_FOLLOW_ROUTE:
+ case PED_CPR:
+ case PED_SOLICIT:
+ case PED_BUY_ICECREAM:
+ case PED_STEP_AWAY:
+ case PED_UNKNOWN:
+ case PED_STATES_NO_AI:
+ case PED_JUMP:
+ case PED_STAGGER:
+ case PED_DIVE_AWAY:
+ case PED_STATES_NO_ST:
+ case PED_ARREST_PLAYER:
+ case PED_PASSENGER:
+ case PED_TAXI_PASSENGER:
+ case PED_OPEN_DOOR:
+ case PED_DEAD:
+ case PED_CARJACK:
+ case PED_DRAG_FROM_CAR:
+ case PED_ENTER_CAR:
+ case PED_STEAL_CAR:
+ case PED_EXIT_CAR:
+ break;
+ case PED_FLEE_POS:
+ ms_vec2DFleePosition.x = m_fleeFromPosX;
+ ms_vec2DFleePosition.y = m_fleeFromPosY;
+ Flee();
+ break;
+ case PED_FLEE_ENTITY:
+ if (!m_fleeFrom) {
+ SetIdle();
+ break;
+ }
+
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
+ break;
+
+ ms_vec2DFleePosition = m_fleeFrom->GetPosition();
+ Flee();
+ break;
+ case PED_FOLLOW_PATH:
+ CPed::FollowPath();
+ break;
+ case PED_PAUSE:
+ CPed::Pause();
+ break;
+ case PED_ATTACK:
+ CPed::Attack();
+ break;
+ case PED_FIGHT:
+ CPed::Fight();
+ break;
+ case PED_CHAT:
+ CPed::Chat();
+ break;
+ case PED_AIM_GUN:
+ if (m_pPointGunAt && m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->CanSeeEntity(this, DEGTORAD(120.0f))) {
+ ((CPed*)m_pPointGunAt)->ReactToPointGun(this);
+ }
+ PointGunAt();
+ break;
+ case PED_SEEK_CAR:
+ SeekCar();
+ break;
+ case PED_SEEK_IN_BOAT:
+ SeekBoatPosition();
+ break;
+ case PED_INVESTIGATE:
+ InvestigateEvent();
+ break;
+ case PED_ON_FIRE:
+ if (IsPlayer())
+ break;
+
+ if (CTimer::GetTimeInMilliseconds() <= m_fleeTimer) {
+ if (m_fleeFrom) {
+ ms_vec2DFleePosition = m_fleeFrom->GetPosition();
+ } else {
+ ms_vec2DFleePosition.x = m_fleeFromPosX;
+ ms_vec2DFleePosition.y = m_fleeFromPosY;
+ }
+ Flee();
+ } else {
+ if (m_pFire)
+ m_pFire->Extinguish();
+ }
+ break;
+ case PED_FALL:
+ Fall();
+ break;
+ case PED_GETUP:
+ SetGetUp();
+ break;
+ case PED_ENTER_TRAIN:
+ EnterTrain();
+ break;
+ case PED_EXIT_TRAIN:
+ ExitTrain();
+ break;
+ case PED_DRIVING:
+ {
+ if (!m_pMyVehicle) {
+ bInVehicle = false;
+ FlagToDestroyWhenNextProcessed();
+ return;
+ }
+
+ if (m_pMyVehicle->pDriver != this || m_pMyVehicle->IsBoat()) {
+ LookForSexyPeds();
+ LookForSexyCars();
+ break;
+ }
+
+ if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE || !m_pMyVehicle->pDriver->IsPlayer()) {
+ break;
+ }
+
+ float steerAngle = m_pMyVehicle->m_fSteerAngle;
+ CAnimBlendAssociation *lDriveAssoc;
+ CAnimBlendAssociation *rDriveAssoc;
+ CAnimBlendAssociation *lbAssoc;
+ CAnimBlendAssociation *sitAssoc;
+ if (m_pMyVehicle->bLowVehicle) {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
+
+ if (!sitAssoc || sitAssoc->blendAmount >= 1.0f) {
+ break;
+ }
+
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L);
+ lbAssoc = nil;
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R);
+ } else {
+ sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
+
+ if (!sitAssoc || sitAssoc->blendAmount >= 1.0f) {
+ break;
+ }
+ lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L);
+ rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R);
+ lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB);
+ }
+ if (lbAssoc) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON
+ && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) {
+ lbAssoc->blendDelta = -1000.0f;
+ }
+ }
+
+ CAnimBlendAssociation *driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
+
+ if (!driveByAssoc)
+ driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
+
+ if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc) {
+ if (steerAngle == 0.0f || driveByAssoc) {
+ if (lDriveAssoc)
+ lDriveAssoc->blendAmount = 0.0f;
+ if (rDriveAssoc)
+ rDriveAssoc->blendAmount = 0.0f;
+ if (lbAssoc)
+ lbAssoc->blendDelta = -4.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->bLowVehicle)
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_R);
+ else
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_R);
+
+ if (lbAssoc)
+ lbAssoc->blendDelta = -4.0f;
+ } 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->bLowVehicle)
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_L);
+ else
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_L);
+
+ if (lbAssoc)
+ lbAssoc->blendDelta = -4.0f;
+ }
+ } else {
+
+ if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_FIRSTPERSON
+ || TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT)
+ && (!lbAssoc || lbAssoc->blendAmount < 1.0f)) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f);
+ }
+ }
+ break;
+ }
+ case PED_DIE:
+ Die();
+ break;
+ case PED_HANDS_UP:
+ if (m_pedStats->m_temper <= 50) {
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSCOWER)) {
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER);
+ Say(SOUND_PED_HANDS_COWER);
+ }
+ } else if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP)) {
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP);
+ Say(SOUND_PED_HANDS_UP);
+ }
+ break;
+ }
+ SetMoveAnim();
+ if (m_ped_flagD4) {
+ if (CGame::nastyGame) {
+ if (!(CTimer::GetFrameCounter() & 3)) {
+ CVector cameraDist = GetPosition() - TheCamera.GetPosition();
+ if (cameraDist.MagnitudeSqr() < 2500.0f) {
+
+ float length = (CGeneral::GetRandomNumber() & 127) * 0.0015f + 0.15f;
+ CVector bloodPos(
+ ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f,
+ ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f,
+ 1.0f);
+ bloodPos += GetPosition();
+
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, length, 0.0f,
+ 0.0f, -length, 255, 255, 0, 0, 4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f);
+ }
+ }
+ }
+ }
+ ServiceTalking();
+ if (bInVehicle && !m_pMyVehicle)
+ bInVehicle = false;
+ m_pCurrentPhysSurface = nil;
+ } else {
+ if (bIsStanding && (!m_pCurrentPhysSurface || IsPlayer())
+ || bIsInWater || !bUsesCollision) {
+ SetDead();
+ }
+ m_pCurrentPhysSurface = nil;
+ }
+ }
+}
+
+void
+CPed::SetInTheAir(void)
+{
+ if (bIsInTheAir)
+ return;
+
+ bIsInTheAir = true;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f);
+
+ if (m_nPedState == PED_ATTACK) {
+ ClearAttack();
+ ClearPointGunAt();
+ } else if (m_nPedState == PED_FIGHT) {
+ EndFight(ENDFIGHT_FAST);
+ }
+
+}
+
+void
+CPed::RestoreHeadPosition(void)
+{
+ if (m_pedIK.RestoreLookAt()) {
+ bIsRestoringLook = false;
+ }
+}
+
+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);
+
+ if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
+ weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+
+ if (weaponInfo->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+ }
+}
+
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); }
@@ -8757,8 +9819,8 @@ WRAPPER void CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg) {
WRAPPER void CPed::SetInCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CF220); }
WRAPPER void CPed::PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8F0); }
WRAPPER void CPed::PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF5C0); }
-WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2480); }
-WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2920); }
+WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); }
+WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); }
WRAPPER void CPed::PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E3290); }
WRAPPER void CPed::PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E36E0); }
WRAPPER void CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E4B90); }
@@ -8767,7 +9829,7 @@ WRAPPER void CPed::PedLandCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0
class CPed_ : public CPed
{
public:
- CPed* ctor(uint32 pedType) { return ::new (this) CPed(pedType); }
+ CPed *ctor(uint32 pedType) { return ::new (this) CPed(pedType); }
void dtor(void) { CPed::~CPed(); }
void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); }
@@ -8775,6 +9837,7 @@ public:
bool SetupLighting_(void) { return CPed::SetupLighting(); }
void RemoveLighting_(bool reset) { CPed::RemoveLighting(reset); }
void Teleport_(CVector pos) { CPed::Teleport(pos); }
+ void ProcessControl_(void) { CPed::ProcessControl(); }
};
STARTPATCHES
@@ -8785,6 +9848,7 @@ STARTPATCHES
InjectHook(0x4A7D30, &CPed_::SetupLighting_, PATCH_JUMP);
InjectHook(0x4A7DC0, &CPed_::RemoveLighting_, PATCH_JUMP);
InjectHook(0x4D3E70, &CPed_::Teleport_, PATCH_JUMP);
+ InjectHook(0x4C8910, &CPed_::ProcessControl_, PATCH_JUMP);
InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP);
InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP);
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index c1e93fdc..b30b4808 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -23,6 +23,13 @@ struct CPedAudioData
int m_nMaxRandomDelayTime;
};
+enum FightState : int8 {
+ FIGHTSTATE_MOVE_FINISHED = -2,
+ FIGHTSTATE_JUST_ATTACKED,
+ FIGHTSTATE_NO_MOVE,
+ FIGHTSTATE_1
+};
+
enum
{
ENDFIGHT_NORMAL,
@@ -256,7 +263,7 @@ public:
// cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPed.h from R*
uint8 bIsStanding : 1;
uint8 m_ped_flagA2 : 1;
- uint8 bIsAttacking : 1; // doesn't reset after fist fight, also stores (CTimer::GetTimeInMilliseconds() < m_lastHitTime)
+ uint8 bIsAttacking : 1; // doesn't reset after fist fight
uint8 bIsPointingGunAt : 1;
uint8 bIsLooking : 1;
uint8 bKeepTryingToLook : 1; // if we can't look somewhere due to unreachable angles
@@ -268,9 +275,9 @@ public:
uint8 bIsTalking : 1;
uint8 bIsInTheAir : 1;
uint8 bIsLanding : 1;
- uint8 bIsRunning : 1; // not fleeing
- uint8 m_ped_flagB40 : 1;
- uint8 m_ped_flagB80 : 1;
+ uint8 bIsRunning : 1; // on some conditions
+ uint8 bHitSomethingLastFrame : 1;
+ uint8 m_ped_flagB80 : 1; // something related with reaction to colliding vehicle
uint8 m_ped_flagC1 : 1;
uint8 bRespondsToThreats : 1;
@@ -283,7 +290,7 @@ public:
uint8 m_ped_flagD1 : 1; // so far only used for reaction type to fire/explosion
uint8 m_ped_flagD2 : 1; // set when event has been seen
- uint8 m_ped_flagD4 : 1;
+ uint8 m_ped_flagD4 : 1; // so far only creates blood pool in hands up state
uint8 m_ped_flagD8 : 1;
uint8 bIsPedDieAnimPlaying : 1;
uint8 bUsePedNodeSeek : 1;
@@ -294,12 +301,12 @@ public:
uint8 m_ped_flagE2 : 1;
uint8 bNotAllowedToDuck : 1;
uint8 bCrouchWhenShooting : 1;
- uint8 bIsDucking : 1; // set if you don't want ped to attack
+ uint8 bIsDucking : 1;
uint8 bGetUpAnimStarted : 1;
uint8 bDoBloodyFootprints : 1;
uint8 m_ped_flagE80 : 1;
- uint8 m_ped_flagF1 : 1;
+ uint8 bWanderPathAfterExitingCar : 1;
uint8 m_ped_flagF2 : 1;
uint8 m_ped_flagF4 : 1;
uint8 m_ped_flagF8 : 1;
@@ -311,18 +318,18 @@ public:
uint8 m_ped_flagG1 : 1;
uint8 m_ped_flagG2 : 1;
uint8 m_ped_flagG4 : 1;
- uint8 m_ped_flagG8 : 1; // ped starts to go somewhere when set
+ uint8 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found
uint8 m_ped_flagG10 : 1;
uint8 m_ped_flagG20 : 1;
uint8 m_ped_flagG40 : 1;
- uint8 m_ped_flagG80 : 1;
+ uint8 bFadeOut : 1;
uint8 m_ped_flagH1 : 1;
uint8 m_ped_flagH2 : 1;
uint8 m_ped_flagH4 : 1;
uint8 bClearObjective : 1;
uint8 m_ped_flagH10 : 1;
- uint8 m_ped_flagH20 : 1;
+ uint8 m_ped_flagH20 : 1; // set if our own vehicle damaged us. I don't know how is that possible
uint8 m_ped_flagH40 : 1;
uint8 m_ped_flagH80 : 1;
@@ -430,7 +437,7 @@ public:
CVector m_vecHitLastPos;
PedFightMoves m_lastFightMove;
uint8 m_fightButtonPressure;
- int8 m_fightUnk2; // TODO
+ FightState m_fightState;
bool m_takeAStepAfterAttack;
uint8 pad_4B3;
CFire *m_pFire;
@@ -442,14 +449,14 @@ public:
uint32 m_lookTimer;
uint32 m_standardTimer;
uint32 m_attackTimer;
- uint32 m_lastHitTime; // obviously not correct
+ uint32 m_shootTimer; // shooting is a part of attack
uint32 m_hitRecoverTimer;
uint32 m_objectiveTimer;
uint32 m_duckTimer;
uint32 m_duckAndCoverTimer;
int32 m_bloodyFootprintCount;
uint8 m_panicCounter;
- uint8 m_deadBleeding;
+ bool m_deadBleeding;
int8 m_bodyPartBleeding; // PedNode
uint8 m_field_4F3;
CPed *m_nearPeds[10];
@@ -519,7 +526,7 @@ public:
void CalculateNewOrientation(void);
float WorkOutHeadingForMovingFirstPerson(float);
void CalculateNewVelocity(void);
- bool CanPedJumpThis(int32);
+ bool CanPedJumpThis(CEntity*);
bool CanSeeEntity(CEntity*, float);
void RestorePreviousObjective(void);
void SetIdle(void);
@@ -629,6 +636,16 @@ public:
void Mug(void);
void MoveHeadToLook(void);
void Pause(void);
+ void ProcessBuoyancy(void);
+ bool ServiceTalkingWhenDead(void);
+ void ServiceTalking(void);
+ void SetJump(void);
+ void UpdatePosition(void);
+ void WanderRange(void);
+ void WanderPath(void);
+ void ReactToPointGun(CEntity*);
+ void SeekCar(void);
+ void SeekBoatPosition(void);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@@ -694,6 +711,9 @@ public:
void Fall(void);
bool IsPedShootable(void);
void Look(void);
+ void SetInTheAir(void);
+ void RestoreHeadPosition(void);
+ void PointGunAt(void);
bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
@@ -708,7 +728,7 @@ public:
static bool &bNastyLimbsCheat;
static bool &bPedCheat2;
static bool &bPedCheat3;
- static CVector2D &ms_vec2DFleePosition;
+ static CVector2D ms_vec2DFleePosition;
static CPedAudioData (&CommentWaitTime)[38];
#ifndef MASTER
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index d4e4f96e..f1da5d66 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -8,6 +8,7 @@ WRAPPER bool CPedIK::PointGunInDirection(float phi, float theta) { EAXJMP(0x4ED9
WRAPPER bool CPedIK::PointGunAtPosition(CVector *position) { EAXJMP(0x4ED920); }
WRAPPER void CPedIK::ExtractYawAndPitchLocal(RwMatrixTag*, float*, float*) { EAXJMP(0x4ED2C0); }
WRAPPER void CPedIK::ExtractYawAndPitchWorld(RwMatrixTag*, float*, float*) { EAXJMP(0x4ED140); }
+WRAPPER bool CPedIK::RestoreLookAt(void) { EAXJMP(0x4ED810); }
// TODO: These are hardcoded into exe, reverse it.
LimbMovementInfo &CPedIK::ms_torsoInfo = *(LimbMovementInfo*)0x5F9F8C;
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index 21f8cce4..080cd103 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -57,5 +57,6 @@ public:
bool RestoreGunPosn(void);
bool LookInDirection(float phi, float theta);
bool LookAtPosition(CVector const& pos);
+ bool RestoreLookAt(void);
};
static_assert(sizeof(CPedIK) == 0x28, "CPedIK: error");