summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio/DMAudio.h18
-rw-r--r--src/math/Matrix.h1
-rw-r--r--src/math/math.cpp6
-rw-r--r--src/peds/Ped.cpp793
-rw-r--r--src/peds/Ped.h28
-rw-r--r--src/peds/PlayerPed.cpp2
-rw-r--r--src/peds/PlayerPed.h2
7 files changed, 755 insertions, 95 deletions
diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h
index 42dd9ef4..fe120576 100644
--- a/src/audio/DMAudio.h
+++ b/src/audio/DMAudio.h
@@ -101,25 +101,25 @@ enum eSound : int16
SOUND_EVIDENCE_PICKUP = 94,
SOUND_UNLOAD_GOLD = 95,
SOUND_PAGER = 96,
- SOUND_PED_DEATH = 97,
- SOUND_PED_DAMAGE = 98,
- SOUND_PED_HIT = 99,
- SOUND_PED_LAND = 100,
+ SOUND_PED_DEATH = 97, // 103 in VC
+ SOUND_PED_DAMAGE = 98, // 104 in VC
+ SOUND_PED_HIT = 99, // 105 in VC
+ SOUND_PED_LAND = 100, // hopefully 106 in VC
SOUND_PED_BULLET_HIT = 101,
SOUND_PED_BOMBER = 102,
- SOUND_PED_BURNING = 103,
+ SOUND_PED_BURNING = 103, // 108 in VC
SOUND_PED_ARREST_FBI = 104,
SOUND_PED_ARREST_SWAT = 105,
SOUND_PED_ARREST_COP = 106,
SOUND_PED_HELI_PLAYER_FOUND = 107,
SOUND_PED_HANDS_UP = 108,
SOUND_PED_HANDS_COWER = 109,
- SOUND_PED_FLEE_SPRINT = 110,
+ SOUND_PED_FLEE_SPRINT = 110, // 120 in VC
SOUND_PED_CAR_JACKING = 111,
SOUND_PED_MUGGING = 112,
SOUND_PED_CAR_JACKED = 113,
SOUND_PED_ROBBED = 114,
- SOUND_PED_TAXI_WAIT = 115,
+ SOUND_PED_TAXI_WAIT = 115, // 137 in VC
SOUND_PED_ATTACK = 116,
SOUND_PED_DEFEND = 117,
SOUND_PED_PURSUIT_ARMY = 118,
@@ -129,9 +129,9 @@ enum eSound : int16
SOUND_PED_HEALING = 122,
SOUND_PED_7B = 123,
SOUND_PED_LEAVE_VEHICLE = 124,
- SOUND_PED_EVADE = 125,
+ SOUND_PED_EVADE = 125, // 142 in VC
SOUND_PED_FLEE_RUN = 126,
- SOUND_PED_CAR_COLLISION = 127,
+ SOUND_PED_CAR_COLLISION = 127, // 144-145-146 in VC
SOUND_PED_SOLICIT = 128,
SOUND_PED_EXTINGUISHING_FIRE = 129,
SOUND_PED_WAIT_DOUBLEBACK = 130,
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index 7d8c02ab..5a3473ad 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -213,6 +213,7 @@ public:
void SetRotate(float xAngle, float yAngle, float zAngle);
void Rotate(float x, float y, float z);
void RotateX(float x);
+ void RotateZ(float z);
void Reorthogonalise(void);
void CopyOnlyMatrix(CMatrix *other){
diff --git a/src/math/math.cpp b/src/math/math.cpp
index 66260709..0707e3d2 100644
--- a/src/math/math.cpp
+++ b/src/math/math.cpp
@@ -47,6 +47,12 @@ CMatrix::RotateX(float x)
}
void
+CMatrix::RotateZ(float z)
+{
+ Rotate(0.0f, 0.0f, z);
+}
+
+void
CMatrix::Reorthogonalise(void)
{
CVector &r = GetRight();
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 94b45cd6..be0ebd45 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -54,7 +54,6 @@ WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); }
WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); }
WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); }
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::ProcessBuoyancy(void) { EAXJMP(0x4C7FF0); }
WRAPPER void CPed::ServiceTalking(void) { EAXJMP(0x4E5870); }
@@ -69,6 +68,8 @@ WRAPPER void CPed::SetEnterCar(CVehicle*, uint32) { EAXJMP(0x4E0920); }
WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); }
WRAPPER void CPed::SetExitCar(CVehicle*, uint32) { EAXJMP(0x4E1010); }
+#define NEW_WALK_AROUND_ALGORITHM
+
CPed *gapTempPedList[50];
uint16 gnNumTempPedList;
@@ -486,11 +487,11 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bHasACamera = false;
m_ped_flagD2 = false;
- m_ped_flagD4 = false;
- m_ped_flagD8 = false;
+ bPedIsBleeding = false;
+ bStopAndShoot = false;
bIsPedDieAnimPlaying = false;
bUsePedNodeSeek = false;
- m_ped_flagD40 = false;
+ bObjectiveCompleted = false;
bScriptObjectiveCompleted = false;
bKindaStayInSamePlace = false;
@@ -508,7 +509,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_ped_flagF8 = false;
bWillBeQuickJacked = false;
bCancelEnteringCar = false;
- m_ped_flagF40 = false;
+ bObstacleShowedUpDuringKillObjective = false;
bDuckAndCover = false;
m_ped_flagG1 = false;
@@ -1695,7 +1696,6 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
CVehicle *veh = m_pMyVehicle;
// Not quite right, IsUpsideDown func. checks for <= -0.9f.
- // Since that function is also used in this file, doesn't this variable indicate upsidedownness?!
if (veh->GetUp().z <= -0.8f)
vehIsUpsideDown = true;
@@ -2396,29 +2396,51 @@ CPed::CanPedDriveOff(void)
return true;
}
+#ifdef VC_PED_PORTS
bool
+CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil)
+{
+ if (m_nSurfaceTouched == SURFACE_PUDDLE)
+ return true;
+
+ CVector pos = GetPosition();
+ CVector forwardOffset = GetForward();
+ if (damageNormal && damageNormal->z > 0.17f) {
+ if (damageNormal->z > 0.9f)
+ return false;
+
+ CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
+ pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;
+ pos.z = pos.z + 0.05f;
+ float collPower = damageNormal->Magnitude2D();
+ if (damageNormal->z <= 0.5f) {
+ forwardOffset += collPower * ourCol->spheres->radius * forwardOffset;
+ } else {
+ CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);
+ invDamageNormal *= 1.0f / collPower;
+ CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;
+ forwardOffset = estimatedJumpDist * min(2.0f / collPower, 4.0f);
+ }
+ } else {
+ pos.z -= 0.15f;
+ }
+
+ CVector forwardPos = pos + forwardOffset;
+ return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
+}
+#else
CPed::CanPedJumpThis(CEntity *unused)
{
-#ifndef VC_PED_PORTS
CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
CVector pos = GetPosition();
CVector forwardPos(
forward.x + pos.x,
forward.y + pos.y,
pos.z);
-#else
- if (m_nSurfaceTouched == SURFACE_PUDDLE)
- return true;
-
- // VC makes some other calculations if there is a CVector passed with function, which isn't possible here.
-
- CVector pos = GetPosition();
- pos.z -= 0.15f;
- CVector forwardPos = pos + GetForward();
-#endif
return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
}
+#endif
bool
CPed::CanPedReturnToState(void)
@@ -2551,7 +2573,7 @@ CPed::RestorePreviousObjective(void)
m_objective = m_prevObjective;
m_prevObjective = OBJECTIVE_NONE;
}
- m_ped_flagD40 = false;
+ bObjectiveCompleted = false;
}
void
@@ -2623,7 +2645,7 @@ CPed::SetObjective(eObjective newObj, void *entity)
return;
}
- m_ped_flagD40 = false;
+ bObjectiveCompleted = false;
if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) {
if (m_objective != newObj) {
if (IsTemporaryObjective(newObj))
@@ -2775,7 +2797,7 @@ CPed::SetObjective(eObjective newObj)
m_objective = newObj;
}
- m_ped_flagD40 = false;
+ bObjectiveCompleted = false;
switch (newObj) {
case OBJECTIVE_NONE:
@@ -2808,7 +2830,7 @@ CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
return;
- m_ped_flagD40 = false;
+ bObjectiveCompleted = false;
if (IsTemporaryObjective(m_objective)) {
m_prevObjective = newObj;
} else {
@@ -4796,7 +4818,7 @@ CPed::GetLocalDirection(const CVector2D &posOffset)
for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4);
- // Should be 0-east, 1-north, 2-west, 3-south. Not sure about order.
+ // 0-forward, 1-left, 2-backward, 3-right.
return direction;
}
@@ -5263,6 +5285,8 @@ CPed::Say(uint16 audio)
uint16 audioToPlay = audio;
if (IsPlayer()) {
+
+ // Ofc this part isn't in VC.
switch (audio) {
case SOUND_PED_DEATH:
audioToPlay = SOUND_PED_DAMAGE;
@@ -5284,14 +5308,27 @@ CPed::Say(uint16 audio)
return;
if (TheCamera.m_CameraAverageSpeed > 1.65f) {
- return;
+#ifdef VC_PED_PORTS
+ if (audio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND)
+#endif
+ return;
+
} else if (TheCamera.m_CameraAverageSpeed > 1.25f) {
- if (audio != SOUND_PED_DEATH && audio != SOUND_PED_TAXI_WAIT && audio != SOUND_PED_EVADE)
+ if (audio != SOUND_PED_DEATH &&
+#ifdef VC_PED_PORTS
+ audio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND &&
+#endif
+ audio != SOUND_PED_TAXI_WAIT && audio != SOUND_PED_EVADE)
return;
} else if (TheCamera.m_CameraAverageSpeed > 0.9f) {
switch (audio) {
case SOUND_PED_DEATH:
+#ifdef VC_PED_PORTS
+ case SOUND_PED_DAMAGE:
+ case SOUND_PED_HIT:
+ case SOUND_PED_LAND:
+#endif
case SOUND_PED_BURNING:
case SOUND_PED_FLEE_SPRINT:
case SOUND_PED_TAXI_WAIT:
@@ -5332,7 +5369,12 @@ CPed::CollideWithPed(CPed *collideWith)
if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
- && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT)) {
+ && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
+#ifdef VC_PED_PORTS
+ || m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_pedInObjective == collideWith
+ || collideWith->m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && collideWith->m_pedInObjective == this
+#endif
+ )) {
if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
@@ -5359,14 +5401,62 @@ CPed::CollideWithPed(CPed *collideWith)
} else if (collideWith->m_nMoveState == PEDMOVE_STILL) {
SetDirectionToWalkAroundObject(collideWith);
}
- } else if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
- || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
- (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
- SetDirectionToWalkAroundObject(collideWith);
- if (!weAreMissionChar)
- Say(SOUND_PED_CHAT);
} else {
- SetEvasiveStep(collideWith, 2);
+#ifdef VC_PED_PORTS
+ if (FindPlayerPed() != m_pedInObjective
+ || m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ || collideWith == m_pedInObjective) {
+#endif
+ if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
+ || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
+ (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
+ SetDirectionToWalkAroundObject(collideWith);
+ if (!weAreMissionChar)
+ Say(SOUND_PED_CHAT);
+ } else {
+ SetEvasiveStep(collideWith, 2);
+ }
+#ifdef VC_PED_PORTS
+ } else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee()
+ && collideWith->m_pedInObjective == m_pedInObjective) {
+
+ int colliderIsAtPlayerSafePosID = -1;
+ int weAreAtPlayerSafePosID = -1;
+ for (int i = 0; i < 6; i++) {
+ CPed *pedAtSafePos = ((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos[i];
+ if (pedAtSafePos == this) {
+ weAreAtPlayerSafePosID = i;
+ } else if (pedAtSafePos == collideWith) {
+ colliderIsAtPlayerSafePosID = i;
+ }
+ }
+ bool weAreCloserToTargetThenCollider = false;
+ if ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D())
+ weAreCloserToTargetThenCollider = true;
+
+ if (weAreAtPlayerSafePosID <= 0 || weAreCloserToTargetThenCollider) {
+ if (!weAreCloserToTargetThenCollider) {
+ int time = 300;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ } else if (colliderIsAtPlayerSafePosID <= 0) {
+ if (collideWith->m_pedInObjective == FindPlayerPed()) {
+ // VC specific
+ // ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
+ int time = 500;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ } else {
+ int time = 300;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ } else {
+ SetDirectionToWalkAroundObject(collideWith);
+ }
+#endif
}
} else {
if (m_pedStats->m_temper <= m_pedStats->m_fear
@@ -5423,7 +5513,11 @@ CPed::CollideWithPed(CPed *collideWith)
}
}
}
- } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar) {
+ } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
+#ifdef VC_PED_PORTS
+ || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
+#endif
+ ) {
// He looks us and we're not at his right side
if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
CVector moveForce = GetRight();
@@ -7378,8 +7472,8 @@ CPed::Flee(void)
double angleToFleeDamagingThing = CGeneral::GetRadianAngleBetweenPoints(
m_vecDamageNormal.x,
m_vecDamageNormal.y,
- 0.0,
- 0.0);
+ 0.0f,
+ 0.0f);
angleToFleeDamagingThing = CGeneral::LimitRadianAngle(angleToFleeDamagingThing);
if (angleToFleeEntity - PI > angleToFleeDamagingThing)
@@ -9150,19 +9244,30 @@ CPed::ProcessControl(void)
break;
}
- float angleToFlee = CGeneral::GetRadianAngleBetweenPoints(
+ float angleToFaceWhenHit = CGeneral::GetRadianAngleBetweenPoints(
GetPosition().x,
GetPosition().y,
m_vecDamageNormal.x + GetPosition().x,
m_vecDamageNormal.y + GetPosition().y);
- float neededTurn = Abs(m_fRotationCur - angleToFlee);
+ float neededTurn = Abs(m_fRotationCur - angleToFaceWhenHit);
if (neededTurn > PI)
neededTurn = TWOPI - neededTurn;
float oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest);
+#ifdef VC_PED_PORTS
+ if (m_nPedState == PED_FOLLOW_PATH) {
+ if (DotProduct(m_vecDamageNormal, GetForward()) < -0.866f && CanPedJumpThis(collidingEnt, &m_vecDamageNormal)) {
+ SetJump();
+
+ // Moved break into here, for compatibility with III
+ break;
+ }
+ // break;
+ }
+#endif
if (m_pedInObjective &&
(m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) {
@@ -9410,7 +9515,6 @@ CPed::ProcessControl(void)
DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, adjustedImpulse);
if (IsPlayer()) {
- /* VC specific
if (adjustedImpulse > 20.0f)
adjustedImpulse = 20.0f;
@@ -9418,9 +9522,9 @@ CPed::ProcessControl(void)
if (adjustedImpulse <= 13.0f)
playerSufferSound = true;
else
- Say(104);
+ Say(SOUND_PED_DAMAGE);
}
- */
+
CColModel* collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel();
CVector colMinVec = collidingCol->boundingBox.min;
CVector colMaxVec = collidingCol->boundingBox.max;
@@ -9433,15 +9537,15 @@ CPed::ProcessControl(void)
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);
+ // I don't know why do we use that
+ float vehTopRightHeading = 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 (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) {
if (angleDiffFromLookingFrontTLVC <= 0.0f) {
vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);
@@ -9494,13 +9598,12 @@ CPed::ProcessControl(void)
}
/* VC specific
- bPushedAlongByCar = true;
+ if (m_pCollidingEntity != collidingEnt)
+ bPushedAlongByCar = true;
*/
}
- /* VC specific
if (m_fHealth < oldHealth && playerSufferSound)
- Say(105);
- */
+ Say(SOUND_PED_HIT);
#else
if (collidingVehSpeedSqr <= 1.0f / 400.0f) {
if (!IsPedInControl()
@@ -9566,15 +9669,15 @@ CPed::ProcessControl(void)
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);
+ // I don't know why do we use that
+ float vehTopRightHeading = 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 (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) {
if (angleDiffFromLookingFrontTLVC <= 0.0f) {
vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);
@@ -9792,7 +9895,7 @@ CPed::ProcessControl(void)
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 = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY);
m_fRotationDest -= TheCamera.Orientation;
m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
m_fRotationCur = m_fRotationDest;
@@ -10191,7 +10294,7 @@ CPed::ProcessControl(void)
break;
}
SetMoveAnim();
- if (m_ped_flagD4) {
+ if (bPedIsBleeding) {
if (CGame::nastyGame) {
if (!(CTimer::GetFrameCounter() & 3)) {
CVector cameraDist = GetPosition() - TheCamera.GetPosition();
@@ -12266,7 +12369,7 @@ CPed::ProcessObjective(void)
}
} else {
ClearLookFlag();
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
}
}
case OBJECTIVE_KILL_CHAR_ON_FOOT:
@@ -12279,7 +12382,7 @@ CPed::ProcessObjective(void)
if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
ClearLookFlag();
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
SetMoveAnim();
break;
}
@@ -12342,7 +12445,7 @@ CPed::ProcessObjective(void)
break;
}
if (m_pedInObjective->m_fHealth <= 0.0f) {
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
bScriptObjectiveCompleted = true;
SetMoveAnim();
break;
@@ -12427,7 +12530,7 @@ CPed::ProcessObjective(void)
return;
}
}
- if (!bKindaStayInSamePlace && !m_ped_flagD8 && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
+ if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
if (distWithTargetSc > wepRange
|| m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
|| m_pedInObjective->m_nPedState == PED_ARRESTED
@@ -12462,13 +12565,13 @@ CPed::ProcessObjective(void)
SetCurrentWeapon(WEAPONTYPE_COLT45);
}
} else {
- m_ped_flagD8 = true;
+ bStopAndShoot = true;
}
SetMoveState(PEDMOVE_STILL);
SetMoveAnim();
break;
}
- m_ped_flagD8 = false;
+ bStopAndShoot = false;
SetMoveAnim();
break;
}
@@ -12490,7 +12593,7 @@ CPed::ProcessObjective(void)
GetPosition().x, GetPosition().y);
SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f));
SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f));
- m_ped_flagF40 = false;
+ bObstacleShowedUpDuringKillObjective = false;
} else {
CVector target;
@@ -12527,22 +12630,22 @@ CPed::ProcessObjective(void)
time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
SetAttackTimer(time);
- m_ped_flagF40 = false;
+ bObstacleShowedUpDuringKillObjective = false;
} else if (foundEnt) {
if (foundEnt->IsPed()) {
SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));
- m_ped_flagF40 = false;
+ bObstacleShowedUpDuringKillObjective = false;
} else {
if (foundEnt->IsObject()) {
SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f));
- m_ped_flagF40 = true;
+ bObstacleShowedUpDuringKillObjective = true;
} else if (foundEnt->IsVehicle()) {
SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f));
- m_ped_flagF40 = true;
+ bObstacleShowedUpDuringKillObjective = true;
} else {
SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f));
- m_ped_flagF40 = true;
+ bObstacleShowedUpDuringKillObjective = true;
}
}
@@ -12553,7 +12656,7 @@ CPed::ProcessObjective(void)
}
} else {
if (!m_pedInObjective->m_pCurrentPhysSurface)
- m_ped_flagD8 = false;
+ bStopAndShoot = false;
if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
@@ -12575,7 +12678,7 @@ CPed::ProcessObjective(void)
}
}
}
- if (m_ped_flagF40) {
+ if (bObstacleShowedUpDuringKillObjective) {
if (m_nPedType == PEDTYPE_COP) {
if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45
|| m_fleeFrom && m_fleeFrom->IsObject()) {
@@ -12598,7 +12701,7 @@ CPed::ProcessObjective(void)
}
} else {
if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS
- && !m_ped_flagD8 && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {
+ && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {
Say(SOUND_PED_ATTACK);
SetSeek(m_pedInObjective, wepRangeAdjusted);
bIsRunning = true;
@@ -12770,7 +12873,7 @@ CPed::ProcessObjective(void)
case OBJECTIVE_ENTER_CAR_AS_DRIVER:
{
if (!m_carInObjective || bInVehicle) {
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
bScriptObjectiveCompleted = true;
RestorePreviousState();
} else {
@@ -12847,7 +12950,7 @@ CPed::ProcessObjective(void)
{
if (!m_carInObjective) {
ClearLookFlag();
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
break;
}
float distWithTargetSc = distWithTarget.Magnitude();
@@ -12969,7 +13072,7 @@ CPed::ProcessObjective(void)
distWithTarget = m_nextRoutePointPos - GetPosition();
distWithTarget.z = 0.0f;
if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) {
- m_ped_flagD40 = true;
+ bObjectiveCompleted = true;
bScriptObjectiveCompleted = true;
SetMoveState(PEDMOVE_STILL);
} else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) {
@@ -13270,7 +13373,7 @@ CPed::ProcessObjective(void)
}
#endif
}
- if (m_ped_flagD40
+ if (bObjectiveCompleted
|| m_objectiveTimer != 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
RestorePreviousObjective();
if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer)
@@ -13349,6 +13452,552 @@ CPed::SetExitTrain(CVehicle* train)
}
}
+#ifdef NEW_WALK_AROUND_ALGORITHM
+CVector
+LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround) {
+ switch (walkAround) {
+ case 0:
+ case 1:
+ return CVector(colMin.x, colMax.y, 0.0f);
+ case 2:
+ case 3:
+ return CVector(colMax.x, colMax.y, 0.0f);
+ case 4:
+ case 5:
+ return CVector(colMax.x, colMin.y, 0.0f);
+ case 6:
+ case 7:
+ return CVector(colMin.x, colMin.y, 0.0f);
+ default:
+ // case 9:
+ return CVector(0.0f, 0.0f, 0.0f); // just a placeholder, supposed to be -GetForward();
+ }
+}
+#endif
+
+// This function looks completely same on VC.
+void
+CPed::SetDirectionToWalkAroundObject(CEntity *obj)
+{
+ float distLimitForTimer = 8.0f;
+ CColModel *objCol = CModelInfo::GetModelInfo(obj->m_modelIndex)->GetColModel();
+ CVector objColMin = objCol->boundingBox.min;
+ CVector objColMax = objCol->boundingBox.max;
+ CVector objColCenter = (objColMin + objColMax) / 2.0f;
+ CMatrix objMat(obj->GetMatrix());
+ float dirToSet = obj->GetForward().Heading();
+ bool objIsSeekTargetAndVan = false;
+ bool objIsSeekTarget = false;
+ bool objUpsideDown = false;
+
+ float checkIntervalInDist = (objColMax.y - objColMin.y) * 0.1f;
+ float checkIntervalInTime;
+
+ if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
+ return;
+
+ if (CharCreatedBy != MISSION_CHAR && obj->m_modelIndex == MI_PHONEBOOTH1) {
+ bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;
+ SetFlee(obj, 5000);
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ if (!isRunning)
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+ CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f);
+ CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f);
+
+ checkIntervalInDist = max(checkIntervalInDist, 0.5f);
+ checkIntervalInDist = min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f);
+ checkIntervalInDist = min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f);
+
+ if (objMat.GetUp().z < 0.0f)
+ objUpsideDown = true;
+
+ if (obj->m_modelIndex != MI_TRAFFICLIGHTS && obj->m_modelIndex != MI_SINGLESTREETLIGHTS1 && obj->m_modelIndex != MI_SINGLESTREETLIGHTS2) {
+ objColCenter = obj->GetMatrix() * objColCenter;
+ } else {
+ checkIntervalInDist = 0.4f;
+ if (objMat.GetUp().z <= 0.57f) {
+
+ // Specific calculations for traffic lights, didn't get a bit.
+ adjustedColMin.x = 1.2f * (adjustedColMin.x < adjustedColMin.y ? adjustedColMin.x : adjustedColMin.y);
+ adjustedColMax.x = 1.2f * (adjustedColMax.x > adjustedColMax.y ? adjustedColMax.x : adjustedColMax.y);
+ adjustedColMin.y = 1.2f * objColMin.z;
+ adjustedColMax.y = 1.2f * objColMax.z;
+ dirToSet = objMat.GetUp().Heading();
+ objMat.SetUnity();
+ objMat.RotateZ(dirToSet);
+ objMat.GetPosition() += obj->GetPosition();
+ objColCenter = obj->GetPosition();
+ } else {
+ objColCenter.x = adjustedColMax.x - 0.25f;
+ objColCenter = obj->GetMatrix() * objColCenter;
+ distLimitForTimer = 0.75f;
+ }
+ objUpsideDown = false;
+ }
+ float oldRotDest = m_fRotationDest;
+ float angleToFaceObjCenter = (objColCenter - GetPosition()).Heading();
+ float angleDiffBtwObjCenterAndForward = CGeneral::LimitRadianAngle(dirToSet - angleToFaceObjCenter);
+
+ // What is the purpose of using this?
+ float objTopRightHeading = Atan2(adjustedColMax.x - adjustedColMin.x, adjustedColMax.y - adjustedColMin.y);
+
+ if (IsPlayer()) {
+ if (FindPlayerPed()->m_fMoveSpeed <= 0.0f)
+ checkIntervalInTime = 0.0f;
+ else
+ checkIntervalInTime = 2.0f / FindPlayerPed()->m_fMoveSpeed;
+ } else {
+ switch (m_nMoveState) {
+ case PEDMOVE_WALK:
+ checkIntervalInTime = 2.0f;
+ break;
+ case PEDMOVE_RUN:
+ checkIntervalInTime = 0.5f;
+ break;
+ case PEDMOVE_SPRINT:
+ checkIntervalInTime = 0.5f;
+ break;
+ default:
+ checkIntervalInTime = 0.0f;
+ break;
+ }
+ }
+ if (m_pSeekTarget == obj && obj->IsVehicle()) {
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER
+ || m_objective == OBJECTIVE_SOLICIT) {
+ objIsSeekTarget = true;
+ if (IsPlayer())
+ checkIntervalInTime = 0.0f;
+
+ if (((CVehicle*)obj)->bIsVan)
+ objIsSeekTargetAndVan = true;
+ }
+ }
+
+ int entityOnTopLeftOfObj = 0;
+ int entityOnBottomLeftOfObj = 0;
+ int entityOnTopRightOfObj = 0;
+ int entityOnBottomRightOfObj = 0;
+
+ if (CTimer::GetTimeInMilliseconds() > m_collidingThingTimer || m_collidingEntityWhileFleeing != obj) {
+ bool collidingThingChanged = true;
+ CEntity *obstacle;
+
+#ifndef NEW_WALK_AROUND_ALGORITHM
+ if (!obj->IsVehicle() || objUpsideDown) {
+ collidingThingChanged = false;
+ } else {
+#else
+ CVector cornerToGo;
+ int dirToGo;
+ m_walkAroundType = 0;
+#endif
+ float adjustedCheckInterval = 0.7f * checkIntervalInDist;
+ CVector posToCheck;
+
+ // Top left of obj
+ posToCheck.x = adjustedColMin.x + adjustedCheckInterval;
+ posToCheck.y = adjustedColMax.y - adjustedCheckInterval;
+ posToCheck.z = 0.0f;
+ posToCheck = objMat * posToCheck;
+ posToCheck.z += 0.6f;
+ obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,
+ true, true, false, true, false, false);
+ if (obstacle) {
+ if (obstacle->IsBuilding()) {
+ entityOnTopLeftOfObj = 1;
+ } else if (obstacle->IsVehicle()) {
+ entityOnTopLeftOfObj = 2;
+ } else {
+ entityOnTopLeftOfObj = 3;
+ }
+ }
+#ifdef NEW_WALK_AROUND_ALGORITHM
+ else {
+ CVector tl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMax.y, 0.0f) - GetPosition();
+ cornerToGo = tl;
+ dirToGo = GetLocalDirection(tl);
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
+ m_walkAroundType = 1;
+ } else {
+ if (dirToGo == 1)
+ m_walkAroundType = 0; // ALL of the next turns will be right turn
+ else if (dirToGo == 3)
+ m_walkAroundType = 1; // ALL of the next turns will be left turn
+ }
+ }
+#endif
+
+ // Top right of obj
+ posToCheck.x = adjustedColMax.x - adjustedCheckInterval;
+ posToCheck.y = adjustedColMax.y - adjustedCheckInterval;
+ posToCheck.z = 0.0f;
+ posToCheck = objMat * posToCheck;
+ posToCheck.z += 0.6f;
+ obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,
+ true, true, false, true, false, false);
+ if (obstacle) {
+ if (obstacle->IsBuilding()) {
+ entityOnTopRightOfObj = 1;
+ } else if (obstacle->IsVehicle()) {
+ entityOnTopRightOfObj = 2;
+ } else {
+ entityOnTopRightOfObj = 3;
+ }
+ }
+#ifdef NEW_WALK_AROUND_ALGORITHM
+ else {
+ CVector tr = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMax.y, 0.0f) - GetPosition();
+ if (tr.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ cornerToGo = tr;
+ dirToGo = GetLocalDirection(tr);
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
+ m_walkAroundType = 2;
+ } else {
+ if (dirToGo == 1)
+ m_walkAroundType = 2; // ALL of the next turns will be right turn
+ else if (dirToGo == 3)
+ m_walkAroundType = 3; // ALL of the next turns will be left turn
+ }
+ }
+ }
+#endif
+
+ // Bottom right of obj
+ posToCheck.x = adjustedColMax.x - adjustedCheckInterval;
+ posToCheck.y = adjustedColMin.y + adjustedCheckInterval;
+ posToCheck.z = 0.0f;
+ posToCheck = objMat * posToCheck;
+ posToCheck.z += 0.6f;
+ obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,
+ true, true, false, true, false, false);
+ if (obstacle) {
+ if (obstacle->IsBuilding()) {
+ entityOnBottomRightOfObj = 1;
+ } else if (obstacle->IsVehicle()) {
+ entityOnBottomRightOfObj = 2;
+ } else {
+ entityOnBottomRightOfObj = 3;
+ }
+ }
+#ifdef NEW_WALK_AROUND_ALGORITHM
+ else {
+ CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition();
+ if (br.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ cornerToGo = br;
+ dirToGo = GetLocalDirection(br);
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
+ m_walkAroundType = 5;
+ } else {
+ if (dirToGo == 1)
+ m_walkAroundType = 4; // ALL of the next turns will be right turn
+ else if (dirToGo == 3)
+ m_walkAroundType = 5; // ALL of the next turns will be left turn
+ }
+ }
+ }
+#endif
+
+ // Bottom left of obj
+ posToCheck.x = adjustedColMin.x + adjustedCheckInterval;
+ posToCheck.y = adjustedColMin.y + adjustedCheckInterval;
+ posToCheck.z = 0.0f;
+ posToCheck = objMat * posToCheck;
+ posToCheck.z += 0.6f;
+ obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,
+ true, true, false, true, false, false);
+ if (obstacle) {
+ if (obstacle->IsBuilding()) {
+ entityOnBottomLeftOfObj = 1;
+ } else if (obstacle->IsVehicle()) {
+ entityOnBottomLeftOfObj = 2;
+ } else {
+ entityOnBottomLeftOfObj = 3;
+ }
+ }
+#ifdef NEW_WALK_AROUND_ALGORITHM
+ else {
+ CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition();
+ if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ cornerToGo = bl;
+ dirToGo = GetLocalDirection(bl);
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
+ m_walkAroundType = 6;
+ } else {
+ if (dirToGo == 1)
+ m_walkAroundType = 6; // ALL of the next turns will be right turn
+ else if (dirToGo == 3)
+ m_walkAroundType = 7; // ALL of the next turns will be left turn
+ }
+ }
+ }
+#else
+ }
+#endif
+ if (entityOnTopLeftOfObj && entityOnTopRightOfObj && entityOnBottomRightOfObj && entityOnBottomLeftOfObj) {
+ collidingThingChanged = false;
+ entityOnTopLeftOfObj = 0;
+ entityOnBottomLeftOfObj = 0;
+ entityOnTopRightOfObj = 0;
+ entityOnBottomRightOfObj = 0;
+ }
+
+#ifndef NEW_WALK_AROUND_ALGORITHM
+ if (!collidingThingChanged) {
+ m_walkAroundType = 0;
+ } else {
+ if (Abs(angleDiffBtwObjCenterAndForward) >= objTopRightHeading) {
+ if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) {
+ if ((angleDiffBtwObjCenterAndForward <= 0.0f || objUpsideDown) && (angleDiffBtwObjCenterAndForward < 0.0f || !objUpsideDown)) {
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
+ m_walkAroundType = 0;
+ } else {
+ if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) >= 0.0f) {
+ if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {
+ m_walkAroundType = 1;
+ } else if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {
+ m_walkAroundType = 1;
+ }
+ } else {
+ if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 4;
+ } else if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 4;
+ }
+ }
+ }
+ } else {
+ if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
+ m_walkAroundType = 0;
+ } else {
+ if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f) {
+ if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {
+ m_walkAroundType = 2;
+ } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {
+ m_walkAroundType = 2;
+ }
+ } else {
+ if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 3;
+ } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 3;
+ }
+ }
+ }
+ }
+ } else if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) < 0.0f) {
+ if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) {
+ m_walkAroundType = 3;
+ }
+ } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 4;
+ }
+ } else if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {
+ if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) {
+ m_walkAroundType = 2;
+ }
+ } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) {
+ m_walkAroundType = 1;
+ } else {
+ m_walkAroundType = 0;
+ }
+ }
+#endif
+ }
+ m_collidingEntityWhileFleeing = obj;
+ m_collidingEntityWhileFleeing->RegisterReference((CEntity**) &m_collidingEntityWhileFleeing);
+
+ // TODO: This random may need to be changed.
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 512 + CGeneral::GetRandomNumber();
+
+ CVector localPosToHead;
+
+#ifdef NEW_WALK_AROUND_ALGORITHM
+ int nextWalkAround = m_walkAroundType;
+ if (m_walkAroundType % 2 == 0) {
+ nextWalkAround += 2;
+ if (nextWalkAround > 6)
+ nextWalkAround = 0;
+ } else {
+ nextWalkAround -= 2;
+ if (nextWalkAround < 0)
+ nextWalkAround = 7;
+ }
+
+ if (CGeneral::GetRandomNumber() & 1){
+ bool nextRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, nextWalkAround),
+ true, true, true, true, true, true, false);
+ if(nextRouteIsClear)
+ m_walkAroundType = nextWalkAround;
+ } else {
+ bool currentRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType),
+ true, true, true, true, true, true, false);
+ if (!currentRouteIsClear) {
+ // Change both target and direction (involves changing even/oddness)
+ if (m_walkAroundType % 2 == 0) {
+ m_walkAroundType -= 2;
+ if (m_walkAroundType < 0)
+ m_walkAroundType = 7;
+ else
+ m_walkAroundType += 1;
+ } else {
+ m_walkAroundType += 2;
+ if (m_walkAroundType > 6)
+ m_walkAroundType = 0;
+ else
+ m_walkAroundType -= 1;
+ }
+ }
+ }
+
+ localPosToHead = LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType);
+#else
+ if (Abs(angleDiffBtwObjCenterAndForward) < objTopRightHeading) {
+ if (objIsSeekTarget) {
+ if (objIsSeekTargetAndVan) {
+ if (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR)
+ return;
+ }
+ if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnBottomRightOfObj || entityOnBottomLeftOfObj)) {
+ m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ }
+ } else {
+ if (m_walkAroundType != 1 && m_walkAroundType != 4
+ && (m_walkAroundType || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f)) {
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ }
+ }
+ } else {
+ if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) {
+ if (angleDiffBtwObjCenterAndForward <= 0.0f) {
+ if (!objIsSeekTarget || !objIsSeekTargetAndVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR) {
+ if (objIsSeekTarget) {
+ if (m_vehEnterType == CAR_DOOR_RF || (m_vehEnterType == CAR_DOOR_RR && !objIsSeekTargetAndVan))
+ return;
+ }
+ if (m_walkAroundType == 4 || m_walkAroundType == 3
+ || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ } else {
+ m_fRotationDest = dirToSet;
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ }
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ }
+ } else if (objIsSeekTarget && objIsSeekTargetAndVan && (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR)) {
+ m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ } else {
+ if (objIsSeekTarget) {
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR && !objIsSeekTargetAndVan)
+ return;
+ }
+ if (m_walkAroundType == 1 || m_walkAroundType == 2
+ || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {
+
+ m_fRotationDest = dirToSet;
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMin.y;
+ }
+ }
+ } else {
+ if (objIsSeekTarget && (!objIsSeekTargetAndVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR)) {
+ if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnTopRightOfObj || entityOnTopLeftOfObj)) {
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ }
+ } else {
+ if (m_walkAroundType == 2 || m_walkAroundType == 3
+ || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);
+ localPosToHead.x = adjustedColMax.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);
+ localPosToHead.x = adjustedColMin.x;
+ localPosToHead.z = 0.0f;
+ localPosToHead.y = adjustedColMax.y;
+ }
+ }
+ }
+ }
+#endif
+ if (objUpsideDown)
+ localPosToHead.x = localPosToHead.x * -1.0f;
+
+ localPosToHead = objMat * localPosToHead;
+ m_actionX = localPosToHead.x;
+ m_actionY = localPosToHead.y;
+ localPosToHead -= GetPosition();
+ m_fRotationDest = CGeneral::LimitRadianAngle(localPosToHead.Heading());
+ if (m_fRotationDest != m_fRotationCur && bHitSomethingLastFrame) {
+ if (m_fRotationDest == oldRotDest) {
+ m_fRotationDest = oldRotDest;
+ } else {
+ m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);
+ }
+ }
+
+ float dist = localPosToHead.Magnitude2D();
+ if (dist < 0.5f)
+ dist = 0.5f;
+
+ if (dist > distLimitForTimer)
+ dist = distLimitForTimer;
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime;
+}
+
class CPed_ : public CPed
{
public:
@@ -13408,7 +14057,6 @@ STARTPATCHES
InjectHook(0x4C7EA0, &CPed::CalculateNewOrientation, PATCH_JUMP);
InjectHook(0x4C78F0, &CPed::WorkOutHeadingForMovingFirstPerson, PATCH_JUMP);
InjectHook(0x4C73F0, &CPed::CalculateNewVelocity, PATCH_JUMP);
- InjectHook(0x4D72F0, &CPed::CanPedJumpThis, PATCH_JUMP);
InjectHook(0x4DD820, &CPed::CanSeeEntity, PATCH_JUMP);
InjectHook(0x4D9460, &CPed::RestorePreviousObjective, PATCH_JUMP);
InjectHook(0x4D82C0, (void (CPed::*)(eObjective)) &CPed::SetObjective, PATCH_JUMP);
@@ -13550,4 +14198,5 @@ STARTPATCHES
InjectHook(0x4E4F30, &CPed::PositionPedOutOfCollision, PATCH_JUMP);
InjectHook(0x4D6A00, &CPed::PossiblyFindBetterPosToSeekCar, PATCH_JUMP);
InjectHook(0x4D94E0, &CPed::ProcessObjective, PATCH_JUMP);
+ InjectHook(0x4CCEB0, &CPed::SetDirectionToWalkAroundObject, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 29916bf4..91cd8f99 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -266,7 +266,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 m_ped_flagA2 : 1; // bWasStanding?
uint8 bIsAttacking : 1; // doesn't reset after fist fight
uint8 bIsPointingGunAt : 1;
uint8 bIsLooking : 1;
@@ -281,9 +281,9 @@ public:
uint8 bIsLanding : 1;
uint8 bIsRunning : 1; // on some conditions
uint8 bHitSomethingLastFrame : 1;
- uint8 m_ped_flagB80 : 1; // bIsNearCar? something related with reaction to colliding vehicle
+ uint8 m_ped_flagB80 : 1; // bIsNearCar? it's sure that it's related with cars and used for deciding whether we should move
- uint8 m_ped_flagC1 : 1;
+ uint8 m_ped_flagC1 : 1; // bCanPedEnterSeekedCar?
uint8 bRespondsToThreats : 1;
uint8 bRenderPedInCar : 1;
uint8 bChangedSeat : 1;
@@ -294,15 +294,15 @@ public:
uint8 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion
uint8 m_ped_flagD2 : 1; // set when ped witnessed an event
- uint8 m_ped_flagD4 : 1; // bPedIsBleeding? so far only creates blood pool in hands up state
- uint8 m_ped_flagD8 : 1;
+ uint8 bPedIsBleeding : 1;
+ uint8 bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun
uint8 bIsPedDieAnimPlaying : 1;
uint8 bUsePedNodeSeek : 1;
- uint8 m_ped_flagD40 : 1; // reset when objective changes
+ uint8 bObjectiveCompleted : 1;
uint8 bScriptObjectiveCompleted : 1;
uint8 bKindaStayInSamePlace : 1;
- uint8 m_ped_flagE2 : 1;
+ uint8 m_ped_flagE2 : 1; // bBeingChasedByPolice?
uint8 bNotAllowedToDuck : 1;
uint8 bCrouchWhenShooting : 1;
uint8 bIsDucking : 1;
@@ -316,7 +316,7 @@ public:
uint8 m_ped_flagF8 : 1;
uint8 bWillBeQuickJacked : 1;
uint8 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked
- uint8 m_ped_flagF40 : 1;
+ uint8 bObstacleShowedUpDuringKillObjective : 1;
uint8 bDuckAndCover : 1;
uint8 m_ped_flagG1 : 1;
@@ -328,7 +328,7 @@ public:
uint8 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door
uint8 bFadeOut : 1;
- uint8 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision
+ uint8 bKnockedUpIntoAir : 1; // NOT CERTAIN - has ped been knocked up into the air by a car collision
uint8 m_ped_flagH2 : 1;
uint8 m_ped_flagH4 : 1;
uint8 bClearObjective : 1;
@@ -339,7 +339,7 @@ public:
uint8 bShakeFist : 1; // test shake hand at look entity
uint8 bNoCriticalHits : 1; // if set, limbs won't came off
- uint8 m_ped_flagI4 : 1;
+ uint8 m_ped_flagI4 : 1; // seems like related with cars
uint8 bHasAlreadyBeenRecorded : 1;
uint8 bFallenDown : 1;
uint8 m_ped_flagI20 : 1;
@@ -402,7 +402,7 @@ public:
float m_fRotationDest;
float m_headingRate;
uint16 m_vehEnterType; // TODO: this is more like a door, not a type
- uint16 m_walkAroundType;
+ int16 m_walkAroundType;
CEntity *m_pCurrentPhysSurface;
CVector m_vecOffsetFromPhysSurface;
CEntity *m_pCurSurface;
@@ -530,7 +530,6 @@ public:
void CalculateNewOrientation(void);
float WorkOutHeadingForMovingFirstPerson(float);
void CalculateNewVelocity(void);
- bool CanPedJumpThis(CEntity*);
bool CanSeeEntity(CEntity*, float);
void RestorePreviousObjective(void);
void SetIdle(void);
@@ -732,6 +731,11 @@ public:
void SetSeekCar(CVehicle*, uint32);
void SetSeekBoatPosition(CVehicle*);
void SetExitTrain(CVehicle*);
+#ifdef VC_PED_PORTS
+ bool CanPedJumpThis(CEntity*, CVector*);
+#else
+ bool CanPedJumpThis(CEntity*);
+#endif
bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index ceee0bd2..668a6011 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -51,7 +51,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
field_1413 = 0;
for (int i = 0; i < 6; i++) {
m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);
- field_1488[i] = 0;
+ m_pPedAtSafePos[i] = nil;
}
}
diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h
index 16fc65ee..136fcc48 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -35,7 +35,7 @@ public:
int8 field_1414;
int8 field_1415;
CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree
- int32 field_1488[6]; // m_pPedAtSafePos?
+ CPed *m_pPedAtSafePos[6];
float m_fWalkAngle;
float m_fFPSMoveHeading;