summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/EventList.h7
-rw-r--r--src/math/Matrix.h1
-rw-r--r--src/math/math.cpp6
-rw-r--r--src/peds/Ped.cpp742
-rw-r--r--src/peds/Ped.h26
-rw-r--r--src/peds/PedIK.cpp85
-rw-r--r--src/peds/PedIK.h16
-rw-r--r--src/peds/PlayerPed.cpp8
8 files changed, 764 insertions, 127 deletions
diff --git a/src/core/EventList.h b/src/core/EventList.h
index 9f5756be..2799fca4 100644
--- a/src/core/EventList.h
+++ b/src/core/EventList.h
@@ -22,13 +22,12 @@ enum eEventType
EVENT_PED_SET_ON_FIRE,
EVENT_COP_SET_ON_FIRE,
EVENT_CAR_SET_ON_FIRE,
- EVENT_ASSAULT_NASTYWEAPON,
- EVENT_ASSAULT_NASTYWEAPON_POLICE,
+ EVENT_ASSAULT_NASTYWEAPON, // not sure
EVENT_ICECREAM,
EVENT_ATM,
- EVENT_SHOPSTALL,
+ EVENT_SHOPSTALL, // used on graffitis
EVENT_SHOPWINDOW,
- EVENT_LAST_EVENT
+ EVENT_LAST_EVENT // may be above one
};
enum eEventEntity
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index bfe85afa..7d8c02ab 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -212,6 +212,7 @@ public:
}
void SetRotate(float xAngle, float yAngle, float zAngle);
void Rotate(float x, float y, float z);
+ void RotateX(float x);
void Reorthogonalise(void);
void CopyOnlyMatrix(CMatrix *other){
diff --git a/src/math/math.cpp b/src/math/math.cpp
index e8b7d933..66260709 100644
--- a/src/math/math.cpp
+++ b/src/math/math.cpp
@@ -41,6 +41,12 @@ CMatrix::Rotate(float x, float y, float z)
}
void
+CMatrix::RotateX(float x)
+{
+ Rotate(x, 0.0f, 0.0f);
+}
+
+void
CMatrix::Reorthogonalise(void)
{
CVector &r = GetRight();
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 51781569..53d94d86 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -24,7 +24,6 @@
#include "PointLights.h"
#include "Pad.h"
#include "Phones.h"
-#include "EventList.h"
#include "Darkel.h"
#include "PathFind.h"
#include "ModelIndices.h"
@@ -54,7 +53,6 @@ WRAPPER void CPed::RemoveInCarAnims(void) { EAXJMP(0x4E4E20); }
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::MakeTyresMuddySectorList(CPtrList&) { EAXJMP(0x53CFD0); }
WRAPPER void CPed::ProcessObjective(void) { EAXJMP(0x4D94E0); }
CPed *gapTempPedList[50];
@@ -443,7 +441,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bIsAttacking = false;
bIsPointingGunAt = false;
bIsLooking = false;
- m_ped_flagA20 = false;
+ bKeepTryingToLook = false;
bIsRestoringLook = false;
bIsAimingGun = false;
@@ -463,7 +461,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bUpdateAnimHeading = false;
bBodyPartJustCameOff = false;
m_ped_flagC40 = false;
- m_ped_flagC80 = false;
+ bFindNewNodeAfterStateRestore = false;
m_ped_flagD1 = false;
m_ped_flagD2 = false;
@@ -514,7 +512,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bNoCriticalHits = false;
m_ped_flagI4 = false;
bHasAlreadyBeenRecorded = false;
- bIsFell = false;
+ bFallenDown = false;
#ifdef KANGAROO_CHEAT
m_ped_flagI80 = false;
#endif
@@ -759,7 +757,7 @@ CPed::AimGun(void)
bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(&vector);
if (m_pLookTarget != m_pSeekTarget) {
- SetLookFlag(m_pSeekTarget, 1);
+ SetLookFlag(m_pSeekTarget, true);
}
} else {
@@ -780,7 +778,7 @@ CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
pos.z + 0.1f
);
- if (!CPed::IsPlayer() || evenOnPlayer) {
+ if (!IsPlayer() || evenOnPlayer) {
++CStats::HeadsPopped;
// BUG: This condition will always return true.
@@ -868,7 +866,7 @@ CPed::RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data)
}
void
-CPed::SetLookFlag(CEntity *target, bool unknown)
+CPed::SetLookFlag(CEntity *target, bool keepTryingToLook)
{
if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
bIsLooking = true;
@@ -877,15 +875,15 @@ CPed::SetLookFlag(CEntity *target, bool unknown)
m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
m_fLookDirection = 999999.0f;
m_lookTimer = 0;
- m_ped_flagA20 = unknown;
+ bKeepTryingToLook = keepTryingToLook;
if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::FLAG_2;
+ m_pedIK.m_flags &= ~CPedIK::LOOKING;
}
}
}
void
-CPed::SetLookFlag(float direction, bool unknown)
+CPed::SetLookFlag(float direction, bool keepTryingToLook)
{
if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
bIsLooking = true;
@@ -893,9 +891,9 @@ CPed::SetLookFlag(float direction, bool unknown)
m_pLookTarget = nil;
m_fLookDirection = direction;
m_lookTimer = 0;
- m_ped_flagA20 = unknown;
+ bKeepTryingToLook = keepTryingToLook;
if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::FLAG_2;
+ m_pedIK.m_flags &= ~CPedIK::LOOKING;
}
}
}
@@ -968,7 +966,7 @@ CPed::Avoid(void)
m_fRotationDest += DEGTORAD(45.0f);
if (!bIsLooking) {
- CPed::SetLookFlag(nearestPed, 0);
+ CPed::SetLookFlag(nearestPed, false);
CPed::SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));
}
}
@@ -984,7 +982,7 @@ CPed::ClearAimFlag(void)
if (bIsAimingGun) {
bIsAimingGun = false;
bIsRestoringGun = true;
- m_pedIK.m_flags &= ~CPedIK:: FLAG_4;
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
if (IsPlayer())
@@ -998,7 +996,7 @@ CPed::ClearLookFlag(void) {
bIsRestoringLook = true;
bShakeFist = false;
- m_pedIK.m_flags &= ~CPedIK::FLAG_2;
+ m_pedIK.m_flags &= ~CPedIK::LOOKING;
if (IsPlayer())
m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;
else
@@ -1103,7 +1101,7 @@ CPed::Attack(void)
return;
if (reloadAnimAssoc) {
- if (!CPed::IsPlayer() || ((CPlayerPed*)this)->field_1380)
+ if (!IsPlayer() || ((CPlayerPed*)this)->field_1380)
ClearAttack();
return;
@@ -1155,9 +1153,9 @@ CPed::Attack(void)
weaponAnimTime = weaponAnimAssoc->currentTime;
if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
if (ourWeapon->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::FLAG_4;
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
- m_pedIK.m_flags &= ~CPedIK::FLAG_4;
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
@@ -2078,10 +2076,10 @@ CPed::BuildPedLists(void)
} else {
CVector centre = CEntity::GetBoundCentre();
CRect rect(
- (centre.x - 20.0f) * 0.025f + 50.0f,
- (centre.y - 20.0f) * 0.025f + 50.0f,
- (centre.x + 20.0f) * 0.025f + 50.0f,
- (centre.y + 20.0f) * 0.025f + 50.0f);
+ CWorld::GetSectorX(centre.x - 20.0f),
+ CWorld::GetSectorY(centre.y - 20.0f),
+ CWorld::GetSectorX(centre.x + 20.0f),
+ CWorld::GetSectorY(centre.y + 20.0f));
gnNumTempPedList = 0;
for(int y = rect.top; y <= rect.bottom; y++) {
@@ -2832,7 +2830,7 @@ CPed::ReactToAttack(CEntity *attacker)
{
if (IsPlayer() && attacker->IsPed()) {
InformMyGangOfAttack(attacker);
- SetLookFlag(attacker, 1);
+ SetLookFlag(attacker, true);
SetLookTimer(700);
return;
}
@@ -3022,7 +3020,7 @@ CPed::FacePhone(void)
GetPosition().x,
GetPosition().y);
- SetLookFlag(phoneDir, 0);
+ SetLookFlag(phoneDir, false);
phoneDir = CGeneral::LimitRadianAngle(phoneDir);
m_moved = CVector2D(0.0f, 0.0f);
@@ -3111,7 +3109,7 @@ CPed::CheckForGunShots(void)
if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {
int pedHandle = gaEvent[event].entityRef;
if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {
- // Is that a bug?!?
+ // Is that a bug?!? (same on VC)
m_ped_flagD2 = false;
return CPools::GetPed(pedHandle);
}
@@ -3268,7 +3266,7 @@ CPed::SetStoredState(void)
return;
if (m_nPedState == PED_WANDER_PATH) {
- m_ped_flagC80 = true;
+ bFindNewNodeAfterStateRestore = true;
if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
m_nMoveState = PEDMOVE_WALK;
}
@@ -3974,7 +3972,7 @@ void
CPed::RestoreGunPosition(void)
{
if (bIsLooking) {
- m_pedIK.m_flags &= ~CPedIK::FLAG_2;
+ m_pedIK.m_flags &= ~CPedIK::LOOKING;
bIsRestoringGun = false;
} else if (m_pedIK.RestoreGunPosn()) {
bIsRestoringGun = false;
@@ -4025,7 +4023,7 @@ CPed::RestorePreviousState(void)
case PED_WANDER_PATH:
m_nPedState = PED_WANDER_PATH;
bIsRunning = false;
- if (!m_ped_flagC80) {
+ if (!bFindNewNodeAfterStateRestore) {
if (m_pNextPathNode) {
CVector diff = m_pNextPathNode->pos - GetPosition();
if (diff.MagnitudeSqr() < 49.0f) {
@@ -4067,16 +4065,16 @@ CPed::SetAimFlag(float angle)
m_pLookTarget = nil;
m_pSeekTarget = nil;
if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::FLAG_4;
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
else
- m_pedIK.m_flags &= ~CPedIK::FLAG_4;
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
void
CPed::SetPointGunAt(CEntity *to)
{
if (to) {
- SetLookFlag(to,1);
+ SetLookFlag(to, true);
SetAimFlag(to);
}
@@ -4161,7 +4159,7 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
}
}
if (neededTurn <= DEGTORAD(90.0f) || veh->m_modelIndex == MI_RCBANDIT || vehPressedHorn || animType != 0) {
- SetLookFlag(veh, 1);
+ SetLookFlag(veh, true);
if ((CGeneral::GetRandomNumber() & 1) && veh->m_modelIndex != MI_RCBANDIT && animType == 0) {
stepAnim = ANIM_IDLE_TAXI;
} else {
@@ -4292,7 +4290,7 @@ CPed::SetEvasiveDive(CPhysical* reason, uint8 onlyRandomJump)
m_fRotationCur = angleToFace;
ClearLookFlag();
ClearAimFlag();
- SetLookFlag(reason, 1);
+ SetLookFlag(reason, true);
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
if (animAssoc)
return;
@@ -4457,7 +4455,7 @@ CPed::SetAttack(CEntity* victim)
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
SetWaitState(WAITSTATE_SURPRISE, nil);
- SetLookFlag(victim, 0);
+ SetLookFlag(victim, false);
SetLookTimer(100);
}
@@ -4522,7 +4520,7 @@ CPed::StartFightAttack(uint8 buttonPressure)
m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
m_fRotationCur = m_fRotationDest;
m_lookTimer = 0;
- SetLookFlag(pedOnGround, 1);
+ SetLookFlag(pedOnGround, true);
SetLookTimer(1500);
}
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f);
@@ -4834,7 +4832,7 @@ CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
+ 1000
+ ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
}
- bIsFell = true;
+ bFallenDown = true;
}
void
@@ -5153,7 +5151,7 @@ void
CPed::CollideWithPed(CPed *collideWith)
{
CAnimBlendAssociation *animAssoc;
- AnimationId animToRun;
+ AnimationId animToPlay;
bool weAreMissionChar = CharCreatedBy == MISSION_CHAR;
bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;
@@ -5245,7 +5243,7 @@ CPed::CollideWithPed(CPed *collideWith)
m_fRotationCur += m_headingRate;
}
} else {
- SetLookFlag(collideWith, 0);
+ SetLookFlag(collideWith, false);
TurnBody();
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
@@ -5265,26 +5263,26 @@ CPed::CollideWithPed(CPed *collideWith)
moveForce.z += 0.1f;
ApplyMoveForce(moveForce);
if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToRun = ANIM_HIT_LEFT;
+ animToPlay = ANIM_HIT_LEFT;
else
- animToRun = ANIM_SHOT_LEFT_PARTIAL;
+ animToPlay = ANIM_SHOT_LEFT_PARTIAL;
} else if (heLooksToUs) {
CVector moveForce = GetRight() * -1.0f;
moveForce.z += 0.1f;
ApplyMoveForce(moveForce);
if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToRun = ANIM_HIT_RIGHT;
+ animToPlay = ANIM_HIT_RIGHT;
else
- animToRun = ANIM_SHOT_RIGHT_PARTIAL;
+ animToPlay = ANIM_SHOT_RIGHT_PARTIAL;
} else {
if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToRun = ANIM_HIT_BACK;
+ animToPlay = ANIM_HIT_BACK;
else
- animToRun = ANIM_SHOT_BACK_PARTIAL;
+ animToPlay = ANIM_SHOT_BACK_PARTIAL;
}
if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {
- animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToRun, 8.0f);
+ animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
if (m_nPedState == PED_ATTACK)
@@ -5297,23 +5295,23 @@ CPed::CollideWithPed(CPed *collideWith)
moveForce.z += 0.1f;
ApplyMoveForce(moveForce);
if (heLooksToUs)
- animToRun = ANIM_KO_SPIN_L;
+ animToPlay = ANIM_KO_SPIN_L;
else
- animToRun = ANIM_KD_RIGHT;
+ animToPlay = ANIM_KD_RIGHT;
} else {
CVector moveForce = GetRight();
moveForce.z += 0.1f;
ApplyMoveForce(moveForce);
if (heLooksToUs)
- animToRun = ANIM_KO_SPIN_R;
+ animToPlay = ANIM_KO_SPIN_R;
else
- animToRun = ANIM_KD_LEFT;
+ animToPlay = ANIM_KD_LEFT;
}
if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
- collideWith->SetFall(3000, animToRun, 0);
+ collideWith->SetFall(3000, animToPlay, 0);
}
} else {
if (!IsPedInControl())
@@ -5345,7 +5343,7 @@ CPed::CollideWithPed(CPed *collideWith)
}
if (IsPlayer()) {
- SetLookFlag(collideWith, 1);
+ SetLookFlag(collideWith, true);
SetLookTimer(800);
}
} else {
@@ -5510,7 +5508,7 @@ CPed::SetChat(CEntity* chatWith, uint32 time)
m_nPedState = PED_CHAT;
SetMoveState(PEDMOVE_STILL);
- SetLookFlag(chatWith, 1);
+ SetLookFlag(chatWith, true);
m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
}
@@ -6219,7 +6217,7 @@ CPed::Fight(void)
if (IsPlayer()) {
m_fRotationCur = m_fRotationDest;
m_lookTimer = 0;
- SetLookFlag(nearPed, 1);
+ SetLookFlag(nearPed, true);
SetLookTimer(1500);
}
break;
@@ -6295,7 +6293,7 @@ CPed::Fight(void)
nextFightMove = FIGHTMOVE_GROUNDKICK;
m_fRotationCur = m_fRotationDest;
m_lookTimer = 0;
- SetLookFlag(pedOnGround, 1);
+ SetLookFlag(pedOnGround, true);
SetLookTimer(1500);
} else if (goForward) {
nextFightMove = FIGHTMOVE_SHUFFLE_F;
@@ -6709,28 +6707,28 @@ CPed::Wait(void)
}
}
- AnimationId animToRun;
+ AnimationId animToPlay;
switch (CGeneral::GetRandomNumber() & 3) {
case 0:
- animToRun = ANIM_ROAD_CROSS;
+ animToPlay = ANIM_ROAD_CROSS;
break;
case 1:
- animToRun = ANIM_IDLE_TIRED;
+ animToPlay = ANIM_IDLE_TIRED;
break;
case 2:
- animToRun = ANIM_XPRESS_SCRATCH;
+ animToPlay = ANIM_XPRESS_SCRATCH;
break;
case 3:
- animToRun = ANIM_TURN_180;
+ animToPlay = ANIM_TURN_180;
break;
default:
break;
}
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToRun, 4.0f);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- if (animToRun == ANIM_TURN_180)
+ if (animToPlay == ANIM_TURN_180)
animAssoc->SetFinishCallback(FinishedWaitCB, this);
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);
@@ -7771,7 +7769,7 @@ CPed::InvestigateEvent(void)
animAssoc->blendDelta = -8.0f;
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
if (m_pEventEntity)
- SetLookFlag(m_pEventEntity, 1);
+ SetLookFlag(m_pEventEntity, true);
SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
@@ -7854,8 +7852,8 @@ CPed::InvestigateEvent(void)
Say(SOUND_PED_CHAT_EVENT);
}
break;
- case EVENT_ASSAULT_NASTYWEAPON_POLICE:
- case EVENT_ATM:
+ case EVENT_ICECREAM:
+ case EVENT_SHOPSTALL:
m_fRotationDest = m_fAngleToEvent;
if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
@@ -7866,7 +7864,7 @@ CPed::InvestigateEvent(void)
if (animAssoc) {
animAssoc->blendDelta = -8.0f;
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (m_eventType == EVENT_ASSAULT_NASTYWEAPON_POLICE)
+ if (m_eventType == EVENT_ICECREAM)
animToPlay = ANIM_IDLE_CHAT;
else
animToPlay = ANIM_XPRESS_SCRATCH;
@@ -7903,13 +7901,13 @@ CPed::InvestigateEvent(void)
m_vecSeekPos.z = GetPosition().z;
Seek();
- if (m_eventType < EVENT_ASSAULT_NASTYWEAPON_POLICE) {
+ if (m_eventType < EVENT_ICECREAM) {
if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
SetMoveState(PEDMOVE_RUN);
return;
}
}
- if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_ATM) {
+ if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {
SetMoveState(PEDMOVE_WALK);
return;
}
@@ -8033,7 +8031,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
else
nodeToDamage = PED_UPPERARMR;
- if (fabs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
+ 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;
@@ -8064,43 +8062,43 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
float vehColMinY = vehColModel->boundingBox.min.y;
float vehColMaxZ = vehColModel->boundingBox.max.z;
float carFrontZ = car->GetForward().z;
-
- // Col. Z of where?
- float carColZ;
-
- // TODO: Figure out what these codes do
- float unk1, unk2;
+ float carHighestZ, carLength;
if (carFrontZ < -0.2f) {
- carColZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
- unk1 = vehColMaxY - vehColMinY;
+ // Highest point of car's back
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
+ carLength = vehColMaxY - vehColMinY;
} else if (carFrontZ > 0.1f) {
- carColZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- float colZDist = carColZ - GetPosition().z;
- if (colZDist > 0.0f) {
- GetPosition().z += 0.5f * colZDist;
- carColZ += colZDist * 0.25f;
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ float highestZDist = carHighestZ - GetPosition().z;
+ if (highestZDist > 0.0f) {
+ GetPosition().z += 0.5f * highestZDist;
+ carHighestZ += highestZDist * 0.25f;
}
- unk1 = vehColMaxY;
+ carLength = vehColMaxY;
} else {
- carColZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- unk1 = vehColMaxY;
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ carLength = vehColMaxY;
}
- unk2 = (carColZ - GetPosition().z) / (unk1 / car->m_vecMoveSpeed.Magnitude());
- float moveForce = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * unk2;
+ float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());
+
+ // TODO: What are we doing down here?
+ float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
// After this point, distVec isn't distVec anymore.
distVec = car->m_vecMoveSpeed;
distVec.Normalise();
- distVec *= 0.2 * moveForce;
+ distVec *= 0.2 * unknown;
if (damageDir != 1 && damageDir != 3)
- distVec.z += moveForce;
+ distVec.z += unknown;
else
- distVec.z += 1.5f * moveForce;
+ distVec.z += 1.5f * unknown;
m_vecMoveSpeed = distVec;
damageDir += 2;
@@ -8111,7 +8109,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
if (bonnet) {
- if (rand() & 1) {
+ if (CGeneral::GetRandomNumber() & 1) {
bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
} else {
bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
@@ -8146,8 +8144,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
CPed::InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
if ((m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
- && bIsPedDieAnimPlaying
- && !m_pCollidingEntity) {
+ && bIsPedDieAnimPlaying && !m_pCollidingEntity) {
m_pCollidingEntity = car;
}
if (nodeToDamage == PED_MID)
@@ -8157,6 +8154,7 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
distVec.Normalise();
car->ApplyMoveForce(distVec * -100.0f);
+ Say(SOUND_PED_DEFEND);
} else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
|| impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
@@ -8172,7 +8170,6 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
CPed::InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
CPed::SetFall(1000, (AnimationId)(fallDirection + 25), true);
- // float ok
if ((m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
&& !m_pCollidingEntity
&& (!IsPlayer() || m_ped_flagD2 || car->m_modelIndex == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
@@ -8187,9 +8184,9 @@ CPed::KillPedWithCar(CVehicle* car, float impulse)
m_vecMoveSpeed.z = 0.0f;
distVec.Normalise();
car->ApplyMoveForce(distVec * -60.0f);
+ Say(SOUND_PED_DEFEND);
}
- Say(SOUND_PED_DEFEND);
#ifdef FIX_BUGS
// Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
if (IsGangMember()) {
@@ -8207,6 +8204,549 @@ CPed::Look(void)
// UNUSED: This is a perfectly empty function.
}
+bool
+CPed::LookForInterestingNodes(void)
+{
+ CBaseModelInfo *model;
+ CPtrNode *ptrNode;
+ CVector effectPos;
+ CVector effectDist;
+ C2dEffect *effect;
+ CMatrix *objMat;
+
+ if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) {
+ return false;
+ }
+ bool found = false;
+ uint8 randVal = CGeneral::GetRandomNumber() % 256;
+
+ int minX = CWorld::GetSectorIndexX(GetPosition().x - 15.0f);
+ if (minX < 0) minX = 0;
+ int minY = CWorld::GetSectorIndexY(GetPosition().y - 15.0f);
+ if (minY < 0) minY = 0;
+ int maxX = CWorld::GetSectorIndexX(GetPosition().x + 15.0f);
+ if (maxX > NUMSECTORS_X) maxX = NUMSECTORS_X;
+ int maxY = CWorld::GetSectorIndexY(GetPosition().y + 15.0f);
+ if (maxY > NUMSECTORS_Y) maxY = NUMSECTORS_Y;
+
+ 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;
+ model = veh->GetModelInfo();
+ if (model->m_num2dEffects != 0) {
+ for (int e = 0; e < model->m_num2dEffects; e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &veh->GetMatrix();
+ effectPos = veh->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < 64.0f) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ 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++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &obj->GetMatrix();
+ effectPos = obj->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < 64.0f) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ 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++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < 64.0f) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ 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++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < 64.0f) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!found)
+ return false;
+
+ CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);
+ randVal = CGeneral::GetRandomNumber() % 256;
+ if (randVal <= m_randomSeed % 256) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ SetLookFlag(angleToFace, true);
+ SetLookTimer(1000);
+ return false;
+ }
+
+ switch (effect->attractor.flags) {
+ case 0:
+ SetInvestigateEvent(EVENT_ICECREAM, CVector2D(effectPos), 0.1f, 15000, angleToFace);
+ break;
+ case 1:
+ SetInvestigateEvent(EVENT_SHOPSTALL, CVector2D(effectPos), 1.0f,
+ CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),
+ angleToFace);
+ break;
+ default:
+ return true;
+ }
+ return true;
+}
+
+void
+CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)
+{
+ if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ return;
+
+ SetStoredState();
+ bFindNewNodeAfterStateRestore = false;
+ m_nPedState = PED_INVESTIGATE;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_eventType = event;
+ m_eventOrThreat = pos;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_fAngleToEvent = angle;
+
+ if (m_eventType >= EVENT_ICECREAM)
+ m_lookTimer = 0;
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f);
+
+}
+
+void
+CPed::LookForSexyCars(void)
+{
+ CEntity *vehicles[8];
+ CVehicle *veh;
+ int foundVehId = 0;
+ int bestPriceYet = 0;
+ int16 lastVehicle;
+
+ if (!IsPedInControl() && m_nPedState != PED_DRIVING)
+ return;
+
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ for (int vehId = 0; vehId < lastVehicle; vehId++) {
+ veh = (CVehicle*)vehicles[vehId];
+ if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {
+ foundVehId = vehId;
+ bestPriceYet = veh->pHandling->nMonetaryValue;
+ }
+ }
+ if (lastVehicle > 0 && bestPriceYet > 40000)
+ SetLookFlag(vehicles[foundVehId], false);
+
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+}
+
+void
+CPed::LookForSexyPeds(void)
+{
+ if ((!IsPedInControl() && m_nPedState != PED_DRIVING)
+ || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)
+ return;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+
+ if (CanSeeEntity(m_nearPeds[i], DEGTORAD(60.0f))) {
+
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
+
+ CPed *nearPed = m_nearPeds[i];
+ if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
+ && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
+
+ SetLookFlag(nearPed, true);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
+ Say(SOUND_PED_CHAT_SEXY);
+ return;
+ }
+ }
+ }
+ }
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
+}
+
+void
+CPed::MakeTyresMuddySectorList(CPtrList &list)
+{
+ 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();
+
+ if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) {
+
+ if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f
+ && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) {
+
+ for(int wheel = 0; wheel < 4; wheel++) {
+
+ if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel]
+ && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) {
+
+ CColModel *vehCol = veh->GetModelInfo()->GetColModel();
+ CVector approxWheelOffset;
+ switch (wheel) {
+ case 0:
+ approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
+ break;
+ case 1:
+ approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
+ break;
+ case 2:
+ approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
+ break;
+ case 3:
+ approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
+ break;
+ default:
+ break;
+ }
+
+ // I hope so
+ CVector wheelPos = veh->GetMatrix() * approxWheelOffset;
+ if (Abs(wheelPos.z - GetPosition().z) < 2.0f) {
+
+ if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {
+ if (CGame::nastyGame) {
+ ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true;
+ DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f);
+ }
+ veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f));
+
+ CVector vehAndWheelDist = wheelPos - veh->GetPosition();
+ veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist);
+
+ if (veh == FindPlayerVehicle()) {
+ CPad::GetPad(0)->StartShake(300, 70);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CPed::Mug(void)
+{
+ if (m_pSeekTarget && m_pSeekTarget->IsPed()) {
+
+ if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {
+ if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)
+ m_wepSkills = 50;
+
+ Say(SOUND_PED_MUGGING);
+ ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ SetFlee(m_pSeekTarget, 20000);
+ }
+
+ } else {
+ SetIdle();
+ }
+}
+
+void
+CPed::MoveHeadToLook(void)
+{
+ CVector lookPos;
+
+ if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ ClearLookFlag();
+ } else if (m_nPedState == PED_DRIVING) {
+ m_pedIK.m_flags |= CPedIK::LOOKING;
+ }
+
+ if (m_pLookTarget) {
+
+ if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+
+ CAnimBlendAssociation* fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
+ if (fuckUAssoc) {
+
+ float animTime = fuckUAssoc->currentTime;
+ if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) {
+
+ bool lookingToCop = false;
+ if (m_pLookTarget->m_modelIndex == MI_POLICE
+ || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) {
+
+ lookingToCop = true;
+ }
+
+ if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) {
+ AddWeaponModel(MI_FINGERS);
+ ((CPlayerPed*)this)->AnnoyPlayerPed(true);
+
+ } else if ((CGeneral::GetRandomNumber() & 3) == 0) {
+ AddWeaponModel(MI_FINGERS);
+ }
+ }
+ }
+ }
+
+ if (m_pLookTarget->IsPed()) {
+ ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID);
+ } else {
+ lookPos = m_pLookTarget->GetPosition();
+ }
+
+ if (!m_pedIK.LookAtPosition(lookPos)) {
+ if (!bKeepTryingToLook) {
+ ClearLookFlag();
+ }
+ return;
+ }
+
+ if (!bShakeFist || bIsAimingGun || bIsRestoringGun)
+ return;
+
+ if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)
+ return;
+
+ bool notRocketLauncher = false;
+ bool notTwoHanded = false;
+ AnimationId animToPlay = NUM_ANIMS;
+
+ if (!GetWeapon()->IsType2Handed())
+ notTwoHanded = true;
+
+ if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)
+ notRocketLauncher = true;
+
+ if (IsPlayer() && notRocketLauncher) {
+
+ if (m_pLookTarget->IsPed()) {
+
+ if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) {
+
+ // FIX: Unreachable and meaningless condition
+#ifndef FIX_BUGS
+ if (m_pedStats->m_temper < 47)
+#endif
+ animToPlay = ANIM_FIGHT_PPUNCH;
+ } else {
+ animToPlay = ANIM_FUCKU;
+ }
+ } else if (m_pedStats->m_temper > 49 || m_pLookTarget->m_modelIndex == MI_POLICE) {
+ animToPlay = ANIM_FUCKU;
+ }
+ } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) {
+ animToPlay = ANIM_FUCKU;
+ }
+
+ if (animToPlay != NUM_ANIMS) {
+ CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
+
+ if (newAssoc) {
+ newAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ newAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (newAssoc->animId == ANIM_FUCKU)
+ newAssoc->SetDeleteCallback(FinishFuckUCB, this);
+ }
+ }
+ bShakeFist = false;
+ return;
+ }
+
+ if (999999.0f == m_fLookDirection) {
+ ClearLookFlag();
+ return;
+ }
+
+ if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {
+ if (!bKeepTryingToLook) {
+ ClearLookFlag();
+ return;
+ }
+ }
+}
+
+void
+FinishFuckUCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ ped->RemoveWeaponModel(0);
+}
+
+void
+CPed::Pause(void) {
+ m_moved = CVector2D(0.0f, 0.0f);
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
+ ClearPause();
+}
+
+void
+CPed::PedAnimAlignCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (veh && veh->m_status != STATUS_WRECKED) {
+ if (ped->m_nPedState != PED_ENTER_CAR && ped->m_nPedState != PED_CARJACK) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ if (ped->m_fHealth == 0.0f) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ bool itsVan = veh->bIsVan;
+ bool itsBus = veh->bIsBus;
+ eDoors enterDoor;
+ AnimationId enterAnim;
+
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+
+ if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (ped->m_nPedState == PED_CARJACK) {
+ ped->PedAnimDoorOpenCB(nil, ped);
+ return;
+ }
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_R;
+ } else {
+ enterAnim = ANIM_CAR_GETIN_RHS;
+ }
+ } else if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN_L;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_L;
+ } else {
+ enterAnim = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+
+ } else if (veh->CanPedOpenLocks(ped)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS);
+ }
+ } else if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
+ } else {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
+
+ if (!veh->bLowVehicle
+ && veh->pDriver->CharCreatedBy != MISSION_CHAR
+ && veh->pDriver->m_nPedState == PED_DRIVING) {
+
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
+
+ if (veh->pDriver->IsGangMember())
+ veh->pDriver->RegisterThreatWithGangPeds(ped);
+ return;
+ }
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+
+ } else {
+ AnimationId animToPlay;
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
+ animToPlay = ANIM_CAR_DOORLOCKED_RHS;
+ else
+ animToPlay = ANIM_CAR_DOORLOCKED_LHS;
+
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_ped_flagF20 = true;
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+ }
+ }
+}
+
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); }
@@ -8216,7 +8756,6 @@ WRAPPER void CPed::PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg)
WRAPPER void CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF1B0); }
WRAPPER void CPed::SetInCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CF220); }
WRAPPER void CPed::PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8F0); }
-WRAPPER void CPed::PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DE130); }
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); }
@@ -8224,7 +8763,6 @@ WRAPPER void CPed::PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg) { EA
WRAPPER void CPed::PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E36E0); }
WRAPPER void CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E4B90); }
WRAPPER void CPed::PedLandCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8A0); }
-WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4C6580); }
class CPed_ : public CPed
{
@@ -8389,4 +8927,14 @@ STARTPATCHES
InjectHook(0x564BB0, &CPed::IsPedDoingDriveByShooting, PATCH_JUMP);
InjectHook(0x4E4D90, &CPed::IsRoomToBeCarJacked, PATCH_JUMP);
InjectHook(0x4EC430, &CPed::KillPedWithCar, PATCH_JUMP);
+ InjectHook(0x4E9A80, &CPed::SetInvestigateEvent, PATCH_JUMP);
+ InjectHook(0x4D5040, &CPed::LookForInterestingNodes, PATCH_JUMP);
+ InjectHook(0x4D4F50, &CPed::LookForSexyCars, PATCH_JUMP);
+ InjectHook(0x4D4DF0, &CPed::LookForSexyPeds, PATCH_JUMP);
+ InjectHook(0x53CFD0, &CPed::MakeTyresMuddySectorList, PATCH_JUMP);
+ InjectHook(0x4C6580, &FinishFuckUCB, PATCH_JUMP);
+ InjectHook(0x4D11D0, &CPed::Mug, PATCH_JUMP);
+ InjectHook(0x4DE130, &CPed::PedAnimAlignCB, PATCH_JUMP);
+ InjectHook(0x4D0980, &CPed::Pause, PATCH_JUMP);
+ InjectHook(0x4C65B0, &CPed::MoveHeadToLook, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 96767ce1..5922e0e7 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -11,6 +11,7 @@
#include "WeaponInfo.h"
#include "Fire.h"
#include "DMAudio.h"
+#include "EventList.h"
struct CPathNode;
@@ -258,7 +259,7 @@ public:
uint8 bIsAttacking : 1; // doesn't reset after fist fight, also stores (CTimer::GetTimeInMilliseconds() < m_lastHitTime)
uint8 bIsPointingGunAt : 1;
uint8 bIsLooking : 1;
- uint8 m_ped_flagA20 : 1; // "look" method? - probably missing in SA
+ uint8 bKeepTryingToLook : 1; // if we can't look somewhere due to unreachable angles
uint8 bIsRestoringLook : 1;
uint8 bIsAimingGun : 1;
@@ -278,10 +279,10 @@ public:
uint8 bUpdateAnimHeading : 1;
uint8 bBodyPartJustCameOff : 1;
uint8 m_ped_flagC40 : 1;
- uint8 m_ped_flagC80 : 1;
+ uint8 bFindNewNodeAfterStateRestore : 1;
- uint8 m_ped_flagD1 : 1;
- uint8 m_ped_flagD2 : 1; // seen an event
+ 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_flagD8 : 1;
uint8 bIsPedDieAnimPlaying : 1;
@@ -303,7 +304,7 @@ public:
uint8 m_ped_flagF4 : 1;
uint8 m_ped_flagF8 : 1;
uint8 bWillBeQuickJacked : 1;
- uint8 m_ped_flagF20 : 1;
+ uint8 m_ped_flagF20 : 1; // set when couldn't open locked car door
uint8 m_ped_flagF40 : 1;
uint8 bDuckAndCover : 1;
@@ -329,7 +330,7 @@ public:
uint8 bNoCriticalHits : 1; // if set, limbs won't came off
uint8 m_ped_flagI4 : 1;
uint8 bHasAlreadyBeenRecorded : 1;
- uint8 bIsFell : 1;
+ uint8 bFallenDown : 1;
uint8 m_ped_flagI20 : 1;
uint8 m_ped_flagI40 : 1;
uint8 m_ped_flagI80 : 1;
@@ -367,7 +368,7 @@ public:
int32 m_nPrevMoveState;
eWaitState m_nWaitState;
uint32 m_nWaitTimer;
- void *m_pPathNodesStates[8]; // seems unused
+ void *m_pPathNodesStates[8]; // seems unused, probably leftover from VC
CVector2D m_stPathNodeStates[10];
uint16 m_nPathNodes;
int16 m_nCurPathNode;
@@ -601,7 +602,7 @@ public:
void LineUpPedWithTrain(void);
void ExitCar(void);
void Fight(void);
- bool FindBestCoordsFromNodes(CVector unused, CVector* a6);
+ bool FindBestCoordsFromNodes(CVector, CVector*);
void Wait(void);
void ProcessObjective(void);
bool SeekFollowingPath(CVector*);
@@ -614,13 +615,20 @@ public:
uint8 GetPedRadioCategory(uint32);
int GetWeaponSlot(eWeaponType);
void GoToNearestDoor(CVehicle*);
- bool HaveReachedNextPointOnRoute(float a2);
+ bool HaveReachedNextPointOnRoute(float);
void Idle(void);
void InTheAir(void);
void SetLanding(void);
void InvestigateEvent(void);
bool IsPedDoingDriveByShooting(void);
bool IsRoomToBeCarJacked(void);
+ void SetInvestigateEvent(eEventType, CVector2D, float, uint16, float);
+ bool LookForInterestingNodes(void);
+ void LookForSexyCars(void);
+ void LookForSexyPeds(void);
+ void Mug(void);
+ void MoveHeadToLook(void);
+ void Pause(void);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index 8909fcc4..d4e4f96e 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -2,14 +2,16 @@
#include "patcher.h"
#include "PedIK.h"
#include "Ped.h"
+#include "General.h"
WRAPPER bool CPedIK::PointGunInDirection(float phi, float theta) { EAXJMP(0x4ED9B0); }
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); }
-// TODO: Hardcoded into exe, reverse it.
+// TODO: These are hardcoded into exe, reverse it.
LimbMovementInfo &CPedIK::ms_torsoInfo = *(LimbMovementInfo*)0x5F9F8C;
+LimbMovementInfo &CPedIK::ms_headInfo = *(LimbMovementInfo*)0x5F9F5C;
CPedIK::CPedIK(CPed *ped)
{
@@ -105,10 +107,10 @@ CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination)
return destination;
}
-uint32
+LimbMoveStatus
CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo)
{
- int result = 1;
+ LimbMoveStatus result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY;
// phi
@@ -120,11 +122,12 @@ CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, Limb
if (Abs(limb.phi - approxPhi) < moveInfo.yawD) {
limb.phi = approxPhi;
- result = 2;
+ result = ANGLES_SET_EXACTLY;
}
+
if (limb.phi > moveInfo.maxYaw || limb.phi < moveInfo.minYaw) {
limb.phi = clamp(limb.phi, moveInfo.minYaw, moveInfo.maxYaw);
- result = 0;
+ result = ANGLES_SET_TO_MAX;
}
// theta
@@ -138,11 +141,11 @@ CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, Limb
if (Abs(limb.theta - approxTheta) < moveInfo.pitchD)
limb.theta = approxTheta;
else
- result = 1;
+ result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY;
if (limb.theta > moveInfo.maxPitch || limb.theta < moveInfo.minPitch) {
limb.theta = clamp(limb.theta, moveInfo.minPitch, moveInfo.maxPitch);
- result = 0;
+ result = ANGLES_SET_TO_MAX;
}
return result;
}
@@ -150,9 +153,71 @@ CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, Limb
bool
CPedIK::RestoreGunPosn(void)
{
- int limbStatus = MoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo);
+ LimbMoveStatus limbStatus = MoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo);
RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
- return limbStatus == 2;
+ return limbStatus == ANGLES_SET_EXACTLY;
+}
+
+bool
+CPedIK::LookInDirection(float phi, float theta)
+{
+ bool success = true;
+ AnimBlendFrameData *frameData = m_ped->m_pFrames[PED_HEAD];
+ RwFrame *frame = frameData->frame;
+ RwMatrix *frameMat = RwFrameGetMatrix(frame);
+
+ if (!(frameData->flag & AnimBlendFrameData::IGNORE_ROTATION)) {
+ frameData->flag |= AnimBlendFrameData::IGNORE_ROTATION;
+ CPedIK::ExtractYawAndPitchLocal(frameMat, &m_headOrient.phi, &m_headOrient.theta);
+ }
+
+ RwMatrix *worldMat = RwMatrixCreate();
+ worldMat = CPedIK::GetWorldMatrix(RwFrameGetParent(frame), worldMat);
+
+ float alpha, beta;
+ CPedIK::ExtractYawAndPitchWorld(worldMat, &alpha, &beta);
+ RwMatrixDestroy(worldMat);
+
+ alpha += m_torsoOrient.phi;
+ float neededPhiTurn = CGeneral::LimitRadianAngle(phi - alpha);
+ beta *= cos(neededPhiTurn);
+
+ float neededThetaTurn = CGeneral::LimitRadianAngle(theta - beta);
+ LimbMoveStatus headStatus = CPedIK::MoveLimb(m_headOrient, neededPhiTurn, neededThetaTurn, ms_headInfo);
+ if (headStatus == ANGLES_SET_TO_MAX)
+ success = false;
+
+ if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKING)) {
+ float remainingTurn = CGeneral::LimitRadianAngle(phi - m_ped->m_fRotationCur);
+ if (CPedIK::MoveLimb(m_torsoOrient, remainingTurn, theta, ms_torsoInfo))
+ success = true;
+ }
+ CMatrix nextFrame = CMatrix(frameMat);
+ CVector framePos = nextFrame.GetPosition();
+
+ nextFrame.SetRotateZ(m_headOrient.theta);
+ nextFrame.RotateX(m_headOrient.phi);
+ nextFrame.GetPosition() += framePos;
+ nextFrame.UpdateRW();
+
+ if (!(m_flags & LOOKING))
+ RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);
+
+ return success;
+}
+
+bool
+CPedIK::LookAtPosition(CVector const &pos)
+{
+ float phiToFace = CGeneral::GetRadianAngleBetweenPoints(
+ pos.x, pos.y,
+ m_ped->GetPosition().x, m_ped->GetPosition().y);
+
+ float thetaToFace = CGeneral::GetRadianAngleBetweenPoints(
+ pos.z, (m_ped->GetPosition() - pos).Magnitude2D(),
+ m_ped->GetPosition().z, 0.0f);
+
+ return LookInDirection(phiToFace, thetaToFace);
}
STARTPATCHES
@@ -161,4 +226,6 @@ STARTPATCHES
InjectHook(0x4EDDB0, &CPedIK::RotateTorso, PATCH_JUMP);
InjectHook(0x4ED440, &CPedIK::MoveLimb, PATCH_JUMP);
InjectHook(0x4EDD70, &CPedIK::RestoreGunPosn, PATCH_JUMP);
+ InjectHook(0x4ED620, &CPedIK::LookInDirection, PATCH_JUMP);
+ InjectHook(0x4ED590, &CPedIK::LookAtPosition, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index a8d9c75d..21f8cce4 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -18,16 +18,21 @@ struct LimbMovementInfo {
float pitchD;
};
+enum LimbMoveStatus {
+ ANGLES_SET_TO_MAX, // because given angles were unreachable
+ ONE_ANGLE_COULDNT_BE_SET_EXACTLY, // because it can't be reached in a jiffy
+ ANGLES_SET_EXACTLY
+};
+
class CPed;
class CPedIK
{
public:
- // TODO
enum {
FLAG_1 = 1,
- FLAG_2 = 2, // related to looking somewhere
- FLAG_4 = 4, // aims with arm
+ LOOKING = 2,
+ AIMS_WITH_ARM = 4,
};
CPed *m_ped;
@@ -38,6 +43,7 @@ public:
int32 m_flags;
static LimbMovementInfo &ms_torsoInfo;
+ static LimbMovementInfo &ms_headInfo;
CPedIK(CPed *ped);
bool PointGunInDirection(float phi, float theta);
@@ -47,7 +53,9 @@ public:
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
void ExtractYawAndPitchLocal(RwMatrixTag*, float*, float*);
void ExtractYawAndPitchWorld(RwMatrixTag*, float*, float*);
- uint32 MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4);
+ LimbMoveStatus MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4);
bool RestoreGunPosn(void);
+ bool LookInDirection(float phi, float theta);
+ bool LookAtPosition(CVector const& pos);
};
static_assert(sizeof(CPedIK) == 0x28, "CPedIK: error");
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 361a9098..5ae8c4be 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -57,8 +57,8 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
void CPlayerPed::ClearWeaponTarget()
{
- if (!m_nPedType) {
- m_pPointGunAt = 0;
+ if (m_nPedType == PEDTYPE_PLAYER1) {
+ m_pPointGunAt = nil;
TheCamera.ClearPlayerWeaponMode();
CWeaponEffects::ClearCrosshair();
}
@@ -79,12 +79,12 @@ CPlayerPed::SetWantedLevelNoDrop(int32 level)
// I don't know the actual purpose of parameter
void
-CPlayerPed::AnnoyPlayerPed(bool itsPolice)
+CPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity)
{
if (m_pedStats->m_temper < 52) {
m_pedStats->m_temper++;
} else {
- if (itsPolice) {
+ if (annoyedByPassingEntity) {
if (m_pedStats->m_temper < 55) {
m_pedStats->m_temper++;
} else {