summaryrefslogtreecommitdiffstats
path: root/src/peds/PedAI.cpp
diff options
context:
space:
mode:
authorSergeanur <s.anureev@yandex.ua>2020-11-20 00:18:37 +0100
committerSergeanur <s.anureev@yandex.ua>2020-11-20 00:18:37 +0100
commitfe40f65703052e4fb4f54fd8a2eec08b26e4313a (patch)
treee64f666fa49a815012cbb1f9facc465d7131a64e /src/peds/PedAI.cpp
parentFix mouse lock/high-dpi (diff)
downloadre3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar.gz
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar.bz2
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar.lz
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar.xz
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.tar.zst
re3-fe40f65703052e4fb4f54fd8a2eec08b26e4313a.zip
Diffstat (limited to 'src/peds/PedAI.cpp')
-rw-r--r--src/peds/PedAI.cpp6954
1 files changed, 6954 insertions, 0 deletions
diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp
new file mode 100644
index 00000000..8c7847a7
--- /dev/null
+++ b/src/peds/PedAI.cpp
@@ -0,0 +1,6954 @@
+#include "common.h"
+
+#include "main.h"
+#include "Particle.h"
+#include "RpAnimBlend.h"
+#include "Ped.h"
+#include "Wanted.h"
+#include "AnimBlendAssociation.h"
+#include "DMAudio.h"
+#include "General.h"
+#include "HandlingMgr.h"
+#include "Replay.h"
+#include "Camera.h"
+#include "PedPlacement.h"
+#include "ZoneCull.h"
+#include "Pad.h"
+#include "Pickups.h"
+#include "Train.h"
+#include "PedRoutes.h"
+#include "CopPed.h"
+#include "Script.h"
+#include "CarCtrl.h"
+#include "WaterLevel.h"
+#include "CarAI.h"
+#include "Zones.h"
+#include "Cranes.h"
+#include "PedAttractor.h"
+#include "Bike.h"
+#include "Weather.h"
+#include "GameLogic.h"
+#include "Streaming.h"
+
+//--MIAMI: file done
+
+CVector vecPedCarDoorAnimOffset;
+CVector vecPedCarDoorLoAnimOffset;
+CVector vecPedVanRearDoorAnimOffset;
+CVector vecPedQuickDraggedOutCarAnimOffset;
+CVector vecPedDraggedOutCarAnimOffset;
+CVector vecPedTrainDoorAnimOffset;
+CVector vecPedStdBikeJumpRhsAnimOffset;
+CVector vecPedVespaBikeJumpRhsAnimOffset;
+CVector vecPedHarleyBikeJumpRhsAnimOffset;
+CVector vecPedDirtBikeJumpRhsAnimOffset;
+CVector vecPedBikeKickAnimOffset;
+
+// --MIAMI: Done
+void
+CPed::SetObjectiveTimer(int time)
+{
+ if (time == 0) {
+ m_objectiveTimer = 0;
+ } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetStoredObjective(void)
+{
+ if (m_objective == m_prevObjective)
+ return;
+
+ switch (m_objective) {
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ case OBJECTIVE_SPRINT_TO_AREA:
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ return;
+ default:
+ m_prevObjective = m_objective;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ForceStoredObjective(eObjective objective)
+{
+ if (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ m_prevObjective = m_objective;
+ return;
+ }
+
+ switch (m_objective) {
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ case OBJECTIVE_SPRINT_TO_AREA:
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ return;
+ default:
+ m_prevObjective = m_objective;
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::IsTemporaryObjective(eObjective objective)
+{
+ return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||
+ objective == OBJECTIVE_LEAVE_CAR_AND_DIE || objective == OBJECTIVE_ENTER_CAR_AS_DRIVER ||
+ objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+}
+
+// --MIAMI: Done
+void
+CPed::SetObjective(eObjective newObj)
+{
+ if (DyingOrDead() || m_attachedTo)
+ return;
+
+ if (newObj == OBJECTIVE_NONE) {
+ if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER
+ || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) && !IsPlayer() && !IsPedInControl()) {
+
+ bStartWanderPathOnFoot = true;
+ } else {
+ m_objective = OBJECTIVE_NONE;
+ m_prevObjective = OBJECTIVE_NONE;
+ }
+ } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) {
+ SetObjectiveTimer(0);
+
+ if (m_objective == newObj)
+ return;
+
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+ bObjectiveCompleted = false;
+
+ switch (newObj) {
+ case OBJECTIVE_NONE:
+ m_prevObjective = OBJECTIVE_NONE;
+ break;
+ case OBJECTIVE_HAIL_TAXI:
+ m_nWaitTimer = 0;
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetObjective(eObjective newObj, void *entity)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
+ return;
+
+ if (entity == this)
+ return;
+
+ if (m_attachedTo && newObj != OBJECTIVE_KILL_CHAR_ON_FOOT && newObj != OBJECTIVE_KILL_CHAR_ANY_MEANS && newObj != OBJECTIVE_DESTROY_OBJECT && newObj != OBJECTIVE_DESTROY_CAR)
+ return;
+
+ if (m_objective == newObj) {
+ switch (newObj) {
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GUARD_ATTACK:
+ case OBJECTIVE_KILL_CHAR_ON_BOAT:
+ case OBJECTIVE_SOLICIT_FOOT:
+ if (m_pedInObjective == entity)
+ return;
+ break;
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_FLEE_CAR:
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+ return;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_DESTROY_CAR:
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ case OBJECTIVE_BUY_ICE_CREAM:
+ if (m_carInObjective == entity)
+ return;
+
+ if (newObj == OBJECTIVE_BUY_ICE_CREAM && bBoughtIceCream)
+ return;
+
+ break;
+ case OBJECTIVE_SET_LEADER:
+ if (m_leader == entity)
+ return;
+ break;
+ case OBJECTIVE_AIM_GUN_AT:
+ if (m_pedInObjective == entity)
+ return;
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (newObj != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && (newObj == OBJECTIVE_LEAVE_CAR || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ && !bInVehicle)
+ return;
+ }
+
+ bObjectiveCompleted = false;
+ ClearPointGunAt();
+ m_objectiveTimer = 0;
+ if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj) {
+ if (IsTemporaryObjective(newObj))
+ ForceStoredObjective(newObj);
+ else
+ SetStoredObjective();
+ }
+ m_objective = newObj;
+ }
+
+ switch (newObj) {
+ case OBJECTIVE_WAIT_ON_FOOT_FOR_COP:
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ SetIdle();
+ SetLook(m_pedInObjective);
+ break;
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+
+ // In this special case, entity parameter isn't CEntity, but int.
+ SetObjectiveTimer((uintptr)entity);
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_MUG_CHAR:
+ case OBJECTIVE_KILL_CHAR_ON_BOAT:
+ m_pNextPathNode = nil;
+ bUsePedNodeSeek = false;
+
+ if (m_pedInObjective)
+ m_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective);
+ if (m_pLookTarget)
+ m_pLookTarget->CleanUpOldReference(&m_pLookTarget);
+
+ m_pLookTarget = (CEntity*)entity;
+ m_pedInObjective = (CPed*)entity;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ // m_pLookTarget = (CEntity*)entity; // duplicate
+ m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
+ break;
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ case OBJECTIVE_GUARD_ATTACK:
+
+ if (m_pedInObjective)
+ m_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective);
+ m_pedInObjective = (CPed*)entity;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ break;
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ m_pedFormation = FORMATION_REAR;
+ break;
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+ case OBJECTIVE_FLEE_CAR:
+ m_carInObjective = (CVehicle*)entity;
+ m_carInObjective->RegisterReference((CEntity **)&m_carInObjective);
+ if (m_carInObjective->bIsBus && m_leaveCarTimer == 0) {
+ for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) {
+ if (m_carInObjective->pPassengers[i] == this) {
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i;
+ break;
+ }
+ }
+ }
+
+ break;
+ case OBJECTIVE_DESTROY_OBJECT:
+ if (m_pPointGunAt)
+ m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
+ m_pPointGunAt = (CPed*)entity;
+ if (entity)
+ ((CEntity*)entity)->RegisterReference((CEntity**) &m_pPointGunAt);
+ break;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_nMoveState == PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_RUN);
+
+ if (((CVehicle*)entity)->IsBoat() && !IsPlayer() && m_pCurrentPhysSurface != entity) {
+ RestorePreviousObjective();
+ break;
+ }
+ // fall through
+ case OBJECTIVE_DESTROY_CAR:
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ case OBJECTIVE_BUY_ICE_CREAM:
+ m_carInObjective = (CVehicle*)entity;
+ m_carInObjective->RegisterReference((CEntity**)&m_carInObjective);
+ m_pSeekTarget = m_carInObjective;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ if (newObj == OBJECTIVE_SOLICIT_VEHICLE) {
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR &&
+ (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) {
+ SetObjectiveTimer(14000);
+ } else {
+ m_objectiveTimer = 0;
+ }
+ break;
+ case OBJECTIVE_SET_LEADER:
+ SetLeader((CEntity*)entity);
+ RestorePreviousObjective();
+ break;
+ case OBJECTIVE_AIM_GUN_AT:
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ break;
+ case OBJECTIVE_SOLICIT_FOOT:
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ break;
+ default:
+ break;
+ }
+}
+
+// --MIAMI: Done
+// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode
+// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call...
+void
+CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
+ return;
+
+ if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
+ return;
+
+ ClearPointGunAt();
+ SetObjectiveTimer(0);
+
+ bObjectiveCompleted = false;
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+
+ if (newObj == OBJECTIVE_FOLLOW_ROUTE) {
+ SetFollowRoute(routePoint, routeType);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetObjective(eObjective newObj, CVector dest)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ return;
+
+ if (m_objective == newObj) {
+ if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA || newObj == OBJECTIVE_SPRINT_TO_AREA) {
+ if (m_nextRoutePointPos == dest)
+ return;
+ } else if (newObj == OBJECTIVE_GUARD_SPOT) {
+ if (m_vecSpotToGuard == dest)
+ return;
+ }
+ }
+
+ ClearPointGunAt();
+ m_objectiveTimer = 0;
+ bObjectiveCompleted = false;
+ switch (newObj) {
+ case OBJECTIVE_GUARD_SPOT:
+ m_vecSpotToGuard = dest;
+ m_radiusToGuard = 5.0f;
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ case OBJECTIVE_GUARD_AREA:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case OBJECTIVE_DESTROY_OBJECT:
+ case OBJECTIVE_DESTROY_CAR:
+ case OBJECTIVE_GOTO_AREA_IN_CAR:
+ case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ case OBJECTIVE_GUARD_ATTACK:
+ case OBJECTIVE_SET_LEADER:
+ case OBJECTIVE_FOLLOW_ROUTE:
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ case OBJECTIVE_HAIL_TAXI:
+ case OBJECTIVE_CATCH_TRAIN:
+ case OBJECTIVE_BUY_ICE_CREAM:
+ case OBJECTIVE_STEAL_ANY_CAR:
+ case OBJECTIVE_STEAL_ANY_MISSION_CAR:
+ case OBJECTIVE_MUG_CHAR:
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+ case OBJECTIVE_FLEE_CAR:
+ case OBJECTIVE_SUN_BATHE:
+ case OBJECTIVE_AIM_GUN_AT:
+ case OBJECTIVE_WANDER:
+ case OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER:
+ case OBJECTIVE_KILL_CHAR_ON_BOAT:
+ case OBJECTIVE_SOLICIT_FOOT:
+ case OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP:
+ break;
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ bIsRunning = false;
+ m_pNextPathNode = nil;
+ m_nextRoutePointPos = dest;
+ m_vecSeekPos = m_nextRoutePointPos;
+ m_distanceToCountSeekDone = 0.5f;
+ if (newObj == OBJECTIVE_GOTO_ATM_ON_FOOT) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (newObj == OBJECTIVE_GOTO_SEAT_ON_FOOT) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (newObj == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (newObj == OBJECTIVE_GOTO_PIZZA_ON_FOOT) {
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (newObj == OBJECTIVE_GOTO_SHELTER_ON_FOOT) {
+ bIsRunning = true;
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ if (newObj == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) {
+ bIsRunning = true;
+ m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
+ m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
+ }
+ bUsePedNodeSeek = false;
+ if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) {
+ if (!IsUseAttractorObjective(m_objective))
+ return;
+ if (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset)
+ return;
+ }
+ break;
+ case OBJECTIVE_RUN_TO_AREA:
+ case OBJECTIVE_SPRINT_TO_AREA:
+ bIsRunning = true;
+ m_pNextPathNode = nil;
+ m_nextRoutePointPos = dest;
+ m_vecSeekPos = m_nextRoutePointPos;
+ m_distanceToCountSeekDone = 0.5f;
+ bUsePedNodeSeek = true;
+ if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D())
+ return;
+ break;
+ default: break;
+ }
+
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetObjective(eObjective newObj, float heading, const CVector& pos)
+{
+ switch (newObj) {
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ ClearPointGunAt();
+ SetObjective(newObj, pos);
+ m_attractorHeading = heading;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ClearObjective(void)
+{
+ if (IsPedInControl() || m_nPedState == PED_DRIVING) {
+ m_objective = OBJECTIVE_NONE;
+ m_pedInObjective = nil;
+ m_carInObjective = nil;
+
+ if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
+ if (m_pMyVehicle->pDriver != this) {
+ if(!IsPlayer())
+ bWanderPathAfterExitingCar = true;
+
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ m_nLastPedState = PED_NONE;
+ } else {
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ } else {
+ bClearObjective = true;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ClearLeader(void)
+{
+ if (!m_leader)
+ return;
+
+ m_leader = nil;
+ if (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ if (CharCreatedBy == MISSION_CHAR) {
+ SetIdle();
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0,8));
+ }
+ } else if (m_objective != OBJECTIVE_NONE) {
+ bClearObjective = true;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::UpdateFromLeader(void)
+{
+ if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer)
+ return;
+
+ if (!m_leader)
+ return;
+
+ CVector leaderDist;
+ if (m_leader->InVehicle())
+ leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition();
+ else
+ leaderDist = m_leader->GetPosition() - GetPosition();
+
+ if (leaderDist.Magnitude() > 30.0f) {
+ if (bWaitForLeaderToComeCloser) {
+ if (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ return;
+ }
+ bWaitForLeaderToComeCloser = true;
+ } else
+ bWaitForLeaderToComeCloser = false;
+
+ if (IsPedInControl()) {
+ if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI)
+ WarpPedToNearLeaderOffScreen();
+
+ if (m_leader->m_nPedState == PED_DEAD) {
+ SetLeader(nil);
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ return;
+ }
+ if (!m_leader->bInVehicle) {
+ if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (bInVehicle) {
+ if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+
+ return;
+ }
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) {
+ SetLeader(nil);
+ return;
+ }
+ }
+ if (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) {
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers)
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle);
+ }
+ } else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT)
+ || m_objective == m_leader->m_objective) {
+
+ if (m_leader->m_nPedState == PED_ATTACK && !bDontFight) {
+ CEntity *lookTargetOfLeader = m_leader->m_pLookTarget;
+
+ if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader);
+ SetObjectiveTimer(8000);
+ SetLookFlag(m_leader->m_pLookTarget, false);
+ SetLookTimer(500);
+ }
+ } else {
+ if (IsPedInControl() && m_nPedState != PED_ATTACK) {
+ if (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) {
+ SetObjective(OBJECTIVE_NONE);
+ } else {
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ }
+ }
+ if (m_nPedState == PED_IDLE && m_leader->IsPlayer() && !bDontFight) {
+ if (ScanForThreats() && m_threatEntity) {
+ m_pLookTarget = m_threatEntity;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
+ if (m_pPointGunAt)
+ m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
+ m_pPointGunAt = m_threatEntity;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
+ SetAttack(m_threatEntity);
+ }
+ }
+ }
+ }
+ } else {
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_WAIT_ON_FOOT:
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_FOLLOW_ROUTE:
+ SetObjective(m_leader->m_objective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSpotToGuard);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ if (m_leader->m_pedInObjective) {
+ SetObjective(m_leader->m_objective, m_leader->m_pedInObjective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ }
+ break;
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_leader->m_carInObjective) {
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 150;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective);
+ return;
+ }
+ break;
+ case OBJECTIVE_GUARD_ATTACK:
+ return;
+ case OBJECTIVE_HAIL_TAXI:
+ m_leader = nil;
+ SetObjective(OBJECTIVE_NONE);
+ break;
+ default:
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+ break;
+ }
+ }
+ } else if (bInVehicle) {
+ if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
+
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective)
+ break;
+
+ // fall through
+ default:
+ if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) {
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::RestorePreviousObjective(void)
+{
+ if (m_objective == OBJECTIVE_NONE)
+ return;
+
+ if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER
+ && m_nPedState != PED_CARJACK)
+ m_pedInObjective = nil;
+
+ if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {
+ m_objective = OBJECTIVE_NONE;
+ if (m_pMyVehicle)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+
+ } else {
+ m_objective = m_prevObjective;
+ m_prevObjective = OBJECTIVE_NONE;
+ }
+ bObjectiveCompleted = false;
+}
+
+// --MIAMI: Done
+void
+CPed::ProcessObjective(void)
+{
+ if (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
+ ClearObjective();
+ bClearObjective = false;
+ }
+ UpdateFromLeader();
+
+ CVector carOrOurPos;
+ CVector targetCarOrHisPos;
+ CVector distWithTarget;
+
+ if (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) {
+ if (bInVehicle) {
+ if (!m_pMyVehicle) {
+ bInVehicle = false;
+ return;
+ }
+ carOrOurPos = m_pMyVehicle->GetPosition();
+ } else {
+ carOrOurPos = GetPosition();
+ }
+
+ if (m_pedInObjective) {
+ if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition();
+ } else {
+ targetCarOrHisPos = m_pedInObjective->GetPosition();
+ }
+ distWithTarget = targetCarOrHisPos - carOrOurPos;
+ } else if (m_carInObjective) {
+ targetCarOrHisPos = m_carInObjective->GetPosition();
+ distWithTarget = targetCarOrHisPos - carOrOurPos;
+ }
+
+ switch (m_objective) {
+ case OBJECTIVE_WAIT_ON_FOOT:
+ if (GetPedState() == PED_DRIVING)
+ m_objective = OBJECTIVE_NONE;
+ else {
+ SetIdle();
+ if (m_attractor) {
+ if (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
+ m_objectiveTimer = 0;
+ }
+ } else {
+ m_objective = OBJECTIVE_NONE;
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT_FOR_COP:
+ if (!m_pedInObjective) {
+ m_objective = OBJECTIVE_NONE;
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));
+ } else if (m_pedInObjective->m_nPedType == PEDTYPE_COP && m_pedInObjective->m_nPedState == PED_DEAD) {
+ m_objective = OBJECTIVE_NONE;
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));
+ m_pedInObjective = nil;
+ }
+ break;
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ if (m_leaveCarTimer >= CTimer::GetTimeInMilliseconds())
+ break;
+
+ if (InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ bFleeAfterExitingCar = true;
+ } else if (m_nPedState != PED_FLEE_POS) {
+ CVector2D fleePos = GetPosition();
+ SetFlee(fleePos, 10000);
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ {
+ distWithTarget = m_vecSpotToGuard - GetPosition();
+ if (m_pedInObjective) {
+ SetLookFlag(m_pedInObjective, true);
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (2.0f * m_radiusToGuard >= distWithTargetSc) {
+ if (m_pedInObjective && m_pedInObjective->m_nPedState != PED_DEAD) {
+ if (distWithTargetSc <= m_radiusToGuard)
+ SetIdle();
+ else {
+ CVector seekPos = m_vecSpotToGuard;
+ SetSeek(seekPos, m_radiusToGuard);
+ }
+ } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ int threatType = ScanForThreats();
+ SetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500));
+
+ // Second condition is pointless and isn't there in Mobile.
+ if (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) {
+ if (m_threatEntity->IsPed())
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
+ }
+ }
+ } else {
+ CVector seekPos = m_vecSpotToGuard;
+ SetSeek(seekPos, m_radiusToGuard);
+ }
+ break;
+ }
+ case OBJECTIVE_WAIT_IN_CAR:
+ SetPedState(PED_DRIVING);
+ break;
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+ SetPedState(PED_DRIVING);
+ break;
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ {
+ if (m_pedInObjective) {
+ if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR
+ && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0
+ && !bKindaStayInSamePlace) {
+
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ break;
+ }
+ if (InVehicle()) {
+ if (distWithTarget.Magnitude() >= 20.0f || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) {
+
+ if (((m_pMyVehicle->pDriver == this && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE) || m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)
+ && !m_pMyVehicle->m_nGettingInFlags) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
+ if (m_nPedType == PEDTYPE_COP) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
+ m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
+ } else {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ }
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ } else {
+ bool targetHasVeh = m_pedInObjective->bInVehicle;
+ if (!targetHasVeh || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar(false)) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ }
+ break;
+ }
+ if (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ } else {
+ float closestVehDist = 60.0f;
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ CVehicle *foundVeh = nil;
+ for(int i = 0; i < lastVehicle; i++) {
+ CVehicle *nearVeh = (CVehicle*)vehicles[i];
+ /*
+ Not used.
+ CVector vehSpeed = nearVeh->GetSpeed();
+ CVector ourSpeed = GetSpeed();
+ */
+ CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
+ if (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh
+ && nearVeh->CanPedOpenLocks(this) && nearVeh->m_fHealth > 250.f) {
+
+ foundVeh = nearVeh;
+ closestVehDist = vehDistVec.Magnitude();
+ }
+ }
+ m_pMyVehicle = foundVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ } else if (!GetIsOnScreen()) {
+ CVector ourPos = GetPosition();
+ int closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f);
+ if (closestNode >= 0) {
+ int16 colliding;
+ CWorld::FindObjectsKindaColliding(
+ ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CZoneInfo zoneInfo;
+ int chosenCarClass;
+ CTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo);
+ int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &chosenCarClass);
+ CVehicle *newVeh = nil;
+ if (chosenModel != -1) {
+ if (CModelInfo::IsBikeModel(chosenModel)) {
+ newVeh = new CBike(chosenModel, RANDOM_VEHICLE);
+ } else {
+ newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE);
+ }
+ }
+ if (newVeh) {
+ newVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();
+ newVeh->GetMatrix().GetPosition().z += 4.0f;
+ newVeh->SetHeading(DEGTORAD(200.0f));
+ newVeh->SetStatus(STATUS_ABANDONED);
+ newVeh->m_nDoorLock = CARLOCK_UNLOCKED;
+ CWorld::Add(newVeh);
+ m_pMyVehicle = newVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ } else {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ }
+ }
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ {
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ break;
+ }
+ if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
+ bObjectiveCompleted = true;
+ ClearLookFlag();
+ SetMoveAnim();
+ break;
+ }
+ if (m_pedInObjective) {
+ int status;
+ if (GetWeapon()->IsTypeMelee())
+ status = KillCharOnFootMelee(carOrOurPos, targetCarOrHisPos, distWithTarget);
+ else
+ status = KillCharOnFootArmed(carOrOurPos, targetCarOrHisPos, distWithTarget);
+
+ if (status == WATCH_UNTIL_HE_DISAPPEARS)
+ return;
+ if (status == CANT_ATTACK)
+ break;
+ }
+ SetMoveAnim();
+ break;
+ }
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:
+ {
+ if (InVehicle()) {
+ if (m_nPedState == PED_DRIVING)
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ } else if (m_nPedState != PED_FLEE_ENTITY) {
+ int time;
+ if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
+ time = 0;
+ else
+ time = 6000;
+
+ SetFindPathAndFlee(m_pedInObjective, time);
+ if (m_pedStats == CPedStats::ms_apPedStats[PEDSTAT_FIREMAN])
+ bMakeFleeScream = true;
+ }
+ break;
+ }
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:
+ case OBJECTIVE_HASSLE_CHAR:
+ {
+ if (m_pedInObjective) {
+ float safeDistance = 2.0f;
+ if (m_pedInObjective->bInVehicle)
+ safeDistance = 3.0f;
+ if (m_objective == OBJECTIVE_HASSLE_CHAR)
+ safeDistance = 1.0f;
+
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
+ if (distWithTargetSc <= safeDistance) {
+ bScriptObjectiveCompleted = true;
+ if (m_nPedState != PED_ATTACK) {
+ SetIdle();
+ if (m_pLookTarget)
+ m_pLookTarget->CleanUpOldReference(&m_pLookTarget);
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ if (distWithTargetSc > 2.0f)
+ SetMoveState(m_pedInObjective->m_nMoveState);
+ else
+ SetMoveState(PEDMOVE_STILL);
+
+ if (m_objective == OBJECTIVE_HASSLE_CHAR) {
+ Say(SOUND_PED_COP_REACTION);
+ m_pedInObjective->Say(SOUND_PED_UNK_126);
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ m_pedInObjective->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ SetObjective(OBJECTIVE_WANDER);
+ m_pedInObjective->SetObjective(OBJECTIVE_WANDER);
+ CVector2D dist = GetPosition() - m_pedInObjective->GetPosition();
+ m_nPathDir = CGeneral::GetNodeHeadingFromVector(dist.x, dist.y);
+ m_pedInObjective->m_nPathDir = CGeneral::GetNodeHeadingFromVector(-dist.x, -dist.y);
+ }
+ } else {
+ SetSeek(m_pedInObjective, safeDistance);
+ if (distWithTargetSc >= 5.0f) {
+ if (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT)
+ SetMoveState(PEDMOVE_SPRINT);
+ else
+ SetMoveState(PEDMOVE_RUN);
+ } else {
+ if (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL
+ && m_leader->m_nMoveState != PEDMOVE_NONE) {
+ if (m_leader->IsPlayer()) {
+ if (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f)
+ SetMoveState(PEDMOVE_RUN);
+ else
+ SetMoveState(PEDMOVE_WALK);
+ } else {
+ SetMoveState(m_leader->m_nMoveState);
+ }
+ } else if (distWithTargetSc <= 3.0f) {
+ SetMoveState(PEDMOVE_WALK);
+ } else {
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING && m_nMoveState > PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_WALK);
+ }
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ }
+ break;
+ }
+ case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:
+ {
+ if (m_pedInObjective) {
+ CVector posToGo = GetFormationPosition();
+ distWithTarget = posToGo - carOrOurPos;
+ SetSeek(posToGo, 1.0f);
+ if (distWithTarget.Magnitude() <= 3.0f) {
+ SetSeek(posToGo, 1.0f);
+ if (m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ SetMoveState(m_pedInObjective->m_nMoveState);
+ } else {
+ SetSeek(posToGo, 1.0f);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ }
+ break;
+ }
+ case OBJECTIVE_ENTER_CAR_AS_PASSENGER:
+ {
+ if (m_carInObjective) {
+ if (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+
+ break;
+ }
+
+ if (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) {
+ RestorePreviousObjective();
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ bIsRunning = false;
+ break;
+ }
+ if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) {
+ if (!EnteringCar()) {
+ bool foundSeat = false;
+ if (m_carInObjective->IsBike()) {
+ if (!m_carInObjective->pPassengers[0] && !(m_carInObjective->m_nGettingInFlags & (CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR))) {
+ m_vehEnterType = CAR_DOOR_RR;
+ foundSeat = true;
+ }
+ } else {
+ if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
+ if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
+ if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
+ foundSeat = false;
+ } else {
+ m_vehEnterType = CAR_DOOR_RR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_LR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ }
+ for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {
+ if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ }
+ if (foundSeat) {
+ SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType));
+ SetEnterCar(m_carInObjective, m_vehEnterType);
+ }
+ }
+ m_objectiveTimer = 0;
+ }
+ }
+ // fall through
+ }
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ {
+ if (!m_carInObjective || bInVehicle) {
+ if (bInVehicle && m_pMyVehicle != m_carInObjective) {
+ SetExitCar(m_pMyVehicle, 0);
+ } else {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ RestorePreviousState();
+ }
+ } else {
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) {
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ }
+ if (IsPedInControl()) {
+ if (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ if (distWithTarget.Magnitude() < 20.0f) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ return;
+ }
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (m_carInObjective->pDriver && !IsPlayer()) {
+ if (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ m_carInObjective->bIsBeingCarJacked = false;
+ }
+ }
+ }
+ } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (m_carInObjective->pDriver
+ && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)
+ ) {
+ if (m_carInObjective->pDriver->m_nPedType == m_nPedType) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ m_carInObjective->bIsBeingCarJacked = false;
+ }
+ }
+ }
+ if (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ return;
+ }
+ if (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) {
+ if (m_nPedState != PED_SEEK_CAR)
+ SetSeekCar(m_carInObjective, 0);
+ } else {
+ SetSeekBoatPosition(m_carInObjective);
+ }
+ if (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked)
+ SetMoveState(PEDMOVE_RUN);
+
+ if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) {
+ distWithTarget = m_carInObjective->GetPosition() - GetPosition();
+ if (!bInVehicle) {
+ if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) {
+ if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen())
+ WarpPedToNearEntityOffScreen(m_carInObjective);
+
+ if (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS
+ || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ } else {
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ }
+ } else if (!bInVehicle) {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_DESTROY_OBJECT:
+ if (m_pPointGunAt) {
+ if (m_nPedState != PED_ATTACK)
+ SetAttack(m_pPointGunAt);
+ } else {
+ bScriptObjectiveCompleted = true;
+ RestorePreviousObjective();
+ }
+ break;
+ case OBJECTIVE_DESTROY_CAR:
+ {
+ if (!m_carInObjective) {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ break;
+ }
+ float distWithTargetSc = distWithTarget.Magnitude();
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float wepRange = wepInfo->m_fRange;
+ m_pLookTarget = m_carInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+
+ m_pSeekTarget = m_carInObjective;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+
+ TurnBody();
+ if (m_carInObjective->m_fHealth <= 0.0f) {
+ ClearLookFlag();
+ bScriptObjectiveCompleted = true;
+ break;
+ }
+
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange) {
+ // I hope so
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ CVector maxShotPos = m_carInObjective->GetPosition() - ourHead;
+ maxShotPos.Normalise();
+ maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
+ true, true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = false;
+ if (foundEnt == m_carInObjective) {
+ SetAttack(m_carInObjective);
+ if (m_pPointGunAt)
+ m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt);
+ m_pPointGunAt = m_carInObjective;
+ if (m_pPointGunAt)
+ m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+ if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {
+ if (wepRange <= 5.0f) {
+ if (Abs(distWithTarget.x) > wepRange || Abs(distWithTarget.y) > wepRange ||
+ (distWithTarget.z > -1.0f && distWithTarget.z < 0.3)) {
+ SetSeek(m_carInObjective, 3.0f);
+ SetMoveState(PEDMOVE_RUN);
+ } else {
+ SetIdle();
+ }
+ } else {
+ float safeDistance = wepRange * 0.25f;
+
+ SetSeek(m_carInObjective, safeDistance);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ SetLookFlag(m_carInObjective, false);
+ TurnBody();
+ break;
+ }
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ case OBJECTIVE_SPRINT_TO_AREA:
+ {
+ if (InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ } else {
+ distWithTarget = m_nextRoutePointPos - GetPosition();
+ distWithTarget.z = 0.0f;
+ if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ SetMoveState(PEDMOVE_STILL);
+ } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) {
+ if (bUsePedNodeSeek) {
+ CVector bestCoords(0.0f, 0.0f, 0.0f);
+ m_vecSeekPos = m_nextRoutePointPos;
+
+ if (!m_pNextPathNode) {
+ bool found = FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+ if (m_pNextPathNode) {
+ // Because it already does that if it finds better coords.
+ if (!found) {
+ bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+ }
+ if ((bestCoords - GetPosition()).Magnitude2D() < m_distanceToCountSeekDone) {
+ m_pNextPathNode = nil;
+ bUsePedNodeSeek = false;
+ }
+ }
+ }
+ if (m_pNextPathNode)
+ m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+ }
+ CVector seekPos = m_vecSeekPos;
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ }
+ }
+
+ break;
+ }
+ case OBJECTIVE_GUARD_ATTACK:
+ {
+ if (m_pedInObjective) {
+ SetLookFlag(m_pedInObjective, true);
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ m_lookTimer = m_attackTimer;
+ TurnBody();
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (distWithTargetSc >= 20.0f) {
+ RestorePreviousObjective();
+ } else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
+ if (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) {
+ SetSeek(m_pedInObjective, 1.0f);
+ } else {
+ SetAttack(m_pedInObjective);
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f));
+ }
+ SetAttackTimer(1000);
+ }
+ } else {
+ RestorePreviousObjective();
+ }
+ break;
+ }
+ case OBJECTIVE_FOLLOW_ROUTE:
+ if (HaveReachedNextPointOnRoute(1.0f)) {
+ int nextPoint = GetNextPointOnRoute();
+ m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint);
+ } else {
+ CVector seekPos = m_nextRoutePointPos;
+ SetSeek(seekPos, 0.8f);
+ }
+ break;
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ if (m_carInObjective) {
+ if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {
+ if (!bInVehicle) {
+ SetObjective(OBJECTIVE_NONE);
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ } else {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)
+ SetSeekCar(m_carInObjective, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ break;
+ case OBJECTIVE_HAIL_TAXI:
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ Say(SOUND_PED_TAXI_WAIT);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ break;
+ case OBJECTIVE_CATCH_TRAIN:
+ {
+ if (m_carInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ } else {
+ CVehicle* trainToEnter = nil;
+ float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+
+ CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
+ if (nearVeh->IsTrain()) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)
+ {
+ trainToEnter = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ if (trainToEnter) {
+ m_carInObjective = trainToEnter;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_BUY_ICE_CREAM:
+ if (m_carInObjective) {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM && m_nPedState != PED_CHAT)
+ SetSeekCar(m_carInObjective, 0);
+ }
+ break;
+ case OBJECTIVE_STEAL_ANY_CAR:
+ case OBJECTIVE_STEAL_ANY_MISSION_CAR:
+ {
+ if (bInVehicle) {
+ bScriptObjectiveCompleted = true;
+ RestorePreviousObjective();
+ } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
+ CVehicle *carToSteal = nil;
+ float closestCarDist = nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+
+ CWorld::FindObjectsInRange(pos, closestCarDist, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ for(int i = 0; i < lastVehicle; i++) {
+ CVehicle *nearVeh = (CVehicle*)vehicles[i];
+ if (m_objective == OBJECTIVE_STEAL_ANY_MISSION_CAR || nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {
+ if (nearVeh->CanPedOpenLocks(this)) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist) {
+ carToSteal = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ }
+ }
+ if (carToSteal) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_MUG_CHAR:
+ {
+ if (m_pedInObjective) {
+ if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);
+ SetMoveState(PEDMOVE_SPRINT);
+ return;
+ }
+ if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this
+ || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {
+ ClearObjective();
+ SetFindPathAndFlee(m_pedInObjective, 15000, true);
+ return;
+ }
+ float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
+ if (distWithTargetScSqr <= sq(10.0f)) {
+ if (distWithTargetScSqr <= sq(1.4f)) {
+ CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ if (reloadAssoc || !m_pedInObjective->IsPedShootable()) {
+ if (reloadAssoc &&
+ (!reloadAssoc->IsRunning() || reloadAssoc->GetProgress() > 0.8f)) {
+ CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
+ punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ CVector2D offset(distWithTarget.x, distWithTarget.y);
+ int dir = m_pedInObjective->GetLocalDirection(offset);
+ m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
+ m_pedInObjective->ReactToAttack(this);
+ m_pedInObjective->Say(SOUND_PED_ROBBED);
+ Say(SOUND_PED_MUGGING);
+ bRichFromMugging = true;
+
+ // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call
+ CPed *victim = m_pedInObjective;
+ ClearObjective();
+ if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ || victim->m_pedInObjective != this) {
+ SetFindPathAndFlee(victim, 15000, true);
+ m_nLastPedState = PED_WANDER_PATH;
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);
+ SetMoveState(PEDMOVE_SPRINT);
+ m_nLastPedState = PED_WANDER_PATH;
+ }
+ }
+ } else {
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+
+ CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FUCKU, 8.0f);
+ newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+ } else {
+ SetSeek(m_pedInObjective, 1.0f);
+ CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+
+ if (walkAssoc)
+ walkAssoc->speed = 1.3f;
+ }
+ } else {
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ } else {
+ m_objective = OBJECTIVE_NONE;
+ ClearObjective();
+ }
+ }
+ // fall through
+ case OBJECTIVE_WANDER:
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer && !bInVehicle) {
+ m_leaveCarTimer = 0;
+ m_objective = OBJECTIVE_NONE;
+ SetWanderPath(m_nPathDir);
+ }
+ break;
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+ {
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+ if (InVehicle()) {
+ if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) {
+ if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+ else if (m_pMyVehicle->bIsBus)
+ SetExitCar(m_pMyVehicle, 0);
+ else {
+ eCarNodes doorNode = CAR_DOOR_LF;
+ if (m_pMyVehicle->pDriver != this) {
+ if (m_pMyVehicle->pPassengers[0] == this) {
+ doorNode = CAR_DOOR_RF;
+ } else if (m_pMyVehicle->pPassengers[1] == this) {
+ doorNode = CAR_DOOR_LR;
+ } else if (m_pMyVehicle->pPassengers[2] == this) {
+ doorNode = CAR_DOOR_RR;
+ }
+ }
+ SetBeingDraggedFromCar(m_pMyVehicle, doorNode, false);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ {
+ distWithTarget = m_nextRoutePointPos - GetPosition();
+ distWithTarget.z = 0.0f;
+ if (InVehicle()) {
+ CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos);
+ CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle);
+ if (distWithTarget.MagnitudeSqr() < sq(20.0f)) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS);
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ break;
+ }
+ if (distWithTarget.Magnitude() > 30.0f) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ } else {
+ float closestVehDist = SQR(60.0f);
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ // NB: 25.0f in here is prolly a forgotten setting, all other places now use 30.0f (ENTER_CAR_MAX_DIST)
+ CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ CVehicle* foundVeh = nil;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
+ /*
+ Not used.
+ CVector vehSpeed = nearVeh->GetSpeed();
+ CVector ourSpeed = GetSpeed();
+ */
+ CVector vehDistVec = nearVeh->GetPosition() - GetPosition();
+ if (vehDistVec.MagnitudeSqr() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh) {
+ foundVeh = nearVeh;
+ closestVehDist = vehDistVec.MagnitudeSqr();
+ }
+ }
+ m_pMyVehicle = foundVeh;
+ if (m_pMyVehicle) {
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+ break;
+ }
+ // Falls to different objectives in III and VC
+#ifdef FIX_BUGS
+ break;
+#else
+ // fall through
+#endif
+ }
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ m_objectiveTimer = 0;
+ if (m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ } else {
+ CVector distance = m_nextRoutePointPos - GetPosition();
+ distance.z = 0.0f;
+ if (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) {
+ if (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(2.0f)) {
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ }
+ if (CWeather::Rain < 0.2f && m_attractor) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ }
+ else if (m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) {
+ if (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(4.0f)) {
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ }
+ CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());
+ if (0.01f * CTimer::GetTimeStep() * 5.0f < pIceCreamVan->m_fDistanceTravelled) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (!pIceCreamVan->pDriver ||
+ !pIceCreamVan->pDriver->IsPlayer() ||
+ pIceCreamVan->pDriver->GetPedState() == PED_ARRESTED ||
+ pIceCreamVan->pDriver->GetPedState() == PED_DEAD) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (!pIceCreamVan->m_bSirenOrAlarm) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ if (pIceCreamVan->GetStatus() == STATUS_WRECKED) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return;
+ }
+ }
+ if (sq(m_distanceToCountSeekDone) < distance.MagnitudeSqr()) {
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || GetPedState() != PED_SEEK_POS) {
+ m_vecSeekPos = m_nextRoutePointPos;
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ }
+ }
+ else {
+ if (!bReachedAttractorHeadingTarget) {
+ float fHeadingDistance = m_fRotationCur - m_attractorHeading;
+ float fSinHeading = Sin(fHeadingDistance);
+ float fCosHeading = Cos(fHeadingDistance);
+ if (fSinHeading > 0.0f) {
+ if (fCosHeading > 0.0f)
+ m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
+ else
+ m_attractorHeading = m_fRotationCur - Acos(fCosHeading);
+ }
+ else {
+ if (fCosHeading > 0.0f)
+ m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
+ else
+ m_attractorHeading = m_fRotationCur + Acos(fCosHeading);
+ }
+ m_fRotationDest = m_attractorHeading;
+ m_headingRate = 3.5f;
+ bReachedAttractorHeadingTarget = true;
+ bTurnedAroundOnAttractor = false;
+ }
+ if (Abs(m_fRotationCur - m_attractorHeading) >= m_acceptableHeadingOffset &&
+ Abs(m_fRotationCur - m_attractorHeading + TWOPI) >= m_acceptableHeadingOffset &&
+ Abs(m_fRotationCur - m_attractorHeading - TWOPI) >= m_acceptableHeadingOffset)
+ SetMoveState(PEDMOVE_STILL);
+ else {
+ m_fRotationDest = m_fRotationCur;
+ bReachedAttractorHeadingTarget = false;
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ RestoreHeadingRate();
+ GetPedAttractorManager()->BroadcastArrival(this, m_attractor);
+ if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) {
+ switch (m_objective) {
+ case OBJECTIVE_GOTO_SEAT_ON_FOOT:
+ if (!bTurnedAroundOnAttractor) {
+ ClearObjective();
+ SetWaitState(WAITSTATE_SIT_DOWN, 0);
+ }
+ else {
+ ClearObjective();
+ SetWaitState(WAITSTATE_SIT_DOWN_RVRS, 0);
+ }
+ break;
+ case OBJECTIVE_GOTO_ATM_ON_FOOT:
+ ClearObjective();
+ SetWaitState(WAITSTATE_USE_ATM, 0);
+ break;
+ case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:
+ ClearObjective();
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP);
+ break;
+ case OBJECTIVE_GOTO_PIZZA_ON_FOOT:
+ ClearObjective();
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT);
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + m_attractor->GetHeadOfQueueWaitTime();
+ break;
+ case OBJECTIVE_GOTO_SHELTER_ON_FOOT:
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER);
+ break;
+ case OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN);
+ break;
+ }
+ } else {
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT);
+ m_objectiveTimer = 0;
+ }
+ }
+ }
+ }
+ return;
+ case OBJECTIVE_FLEE_CAR:
+ if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) {
+ RestorePreviousObjective();
+ SetFlee(m_pMyVehicle, 6000);
+ break;
+ }
+ // fall through
+ case OBJECTIVE_LEAVE_CAR:
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+ if (InVehicle() &&
+ (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() || bBusJacked)) {
+
+ if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN
+ && (m_nPedType != PEDTYPE_COP
+ || m_pMyVehicle->IsBoat()
+ || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {
+#ifdef GTA_TRAIN
+ if (m_pMyVehicle->IsTrain())
+ SetExitTrain(m_pMyVehicle);
+ else
+#endif
+ if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+ else
+ SetExitCar(m_pMyVehicle, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ }
+ }
+ if (bHeldHostageInCar) {
+ if (CTheScripts::IsPlayerOnAMission()) {
+ CVehicle *playerVeh = FindPlayerVehicle();
+ if (playerVeh && playerVeh->IsPassenger(this)) {
+ if (m_leaveCarTimer != 0)
+ m_leaveCarTimer = 0;
+ }
+ }
+ }
+ break;
+ case OBJECTIVE_AIM_GUN_AT:
+ if (m_pedInObjective) {
+ if (!bObstacleShowedUpDuringKillObjective)
+ SetPointGunAt(m_pedInObjective);
+
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
+ SetLookFlag(m_pedInObjective, false);
+ TurnBody();
+ }
+ } else {
+ ClearObjective();
+ }
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER:
+ SetIdle();
+ if (m_attractor && CWeather::Rain < 0.2f)
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ break;
+ case OBJECTIVE_KILL_CHAR_ON_BOAT:
+ SetPedStats(PEDSTAT_TOUGH_GUY);
+ if (bInVehicle) {
+ if (m_pedInObjective && m_pedInObjective->m_pCurrentPhysSurface != m_pMyVehicle) {
+ bObjectiveCompleted = true;
+ ClearObjective();
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ } else {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+ } else if (m_pedInObjective && !m_pedInObjective->DyingOrDead() &&
+ (!m_pCurrentPhysSurface || !m_pedInObjective->m_pCurrentPhysSurface ||
+ m_pedInObjective->m_pCurrentPhysSurface == m_pCurrentPhysSurface)) {
+
+ CBoat *boatWeAreOn = nil;
+ if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())
+ boatWeAreOn = (CBoat*)m_pCurrentPhysSurface;
+
+ if (boatWeAreOn) {
+ SetObjective(OBJECTIVE_RUN_TO_AREA, boatWeAreOn->GetPosition() - (boatWeAreOn->GetForward() * 10.f));
+ } else if (m_pedInObjective) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, m_pedInObjective);
+ }
+ SetMoveAnim();
+ } else {
+ ClearLookFlag();
+ SetMoveAnim();
+ if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle())
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pCurrentPhysSurface);
+ }
+ break;
+ case OBJECTIVE_SOLICIT_FOOT:
+ if (m_pedInObjective) {
+ if (m_objectiveTimer < CTimer::GetTimeInMilliseconds())
+ bScriptObjectiveCompleted = true;
+ } else {
+ bScriptObjectiveCompleted = true;
+ }
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP:
+ SetIdle();
+ if (m_attractor) {
+ float left = GetPosition().x - 10.0f;
+ float right = GetPosition().x + 10.0f;
+ float top = GetPosition().y - 10.0f;
+ float bottom = GetPosition().y + 10.0f;
+ int xstart = Max(0, CWorld::GetSectorIndexX(left));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
+ int ystart = Max(0, CWorld::GetSectorIndexY(top));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
+ assert(xstart <= xend);
+ assert(ystart <= yend);
+
+ float minDistance = SQR(10.0f);
+ CVehicle* pBus = nil;
+
+ for (int y = ystart; y <= yend; y++) {
+ for (int x = xstart; x <= xend; x++) {
+ CSector* s = CWorld::GetSector(x, y);
+ for (CPtrNode* pNode = s->m_lists[ENTITYLIST_VEHICLES].first; pNode != nil; pNode = pNode->next) {
+ CEntity* pEntity = (CEntity*)pNode->item;
+ if (!pEntity->IsVehicle())
+ continue;
+ CVehicle* pVehicle = (CVehicle*)pEntity;
+ if (!pVehicle->bIsBus)
+ continue;
+ if (pVehicle->GetMoveSpeed().MagnitudeSqr() >= SQR(0.005f))
+ continue;
+ float distanceSq = (GetPosition() - pVehicle->GetPosition()).MagnitudeSqr();
+ if (distanceSq < minDistance) {
+ minDistance = distanceSq;
+ pBus = pVehicle;
+ }
+ }
+ }
+ }
+
+ if (pBus) {
+ if (pBus->m_nNumPassengers >= pBus->m_nNumMaxPassengers - 1)
+ SetObjective(OBJECTIVE_WAIT_ON_FOOT);
+ else {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus);
+ bDontDragMeOutCar = true;
+ bRemoveMeWhenIGotIntoCar = true;
+ CPlayerPed *player = FindPlayerPed();
+ if (pBus->IsPassenger(player) || pBus->IsDriver(player)) {
+ bCollectBusFare = true;
+ }
+ }
+ }
+ }
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN:
+ {
+ SetIdle();
+ CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());
+ if (m_attractor && m_nWaitState != WAITSTATE_PLAYANIM_CHAT && pIceCreamVan && pIceCreamVan->pDriver && pIceCreamVan->pDriver->IsPlayer()) {
+ int time = 5000;
+ SetWaitState(WAITSTATE_PLAYANIM_CHAT, &time);
+ break;
+ }
+ if (!m_attractor)
+ break;
+ CVehicle* pVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());
+ if (!pVan)
+ break;
+ if (0.01f * CTimer::GetTimeStep() * 5.0f < pVan->m_fDistanceTravelled) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ break;
+ }
+ if (!pVan->pDriver || !pVan->pDriver->IsPlayer() || pVan->pDriver->GetPedState() == PED_ARRESTED || pVan->pDriver->GetPedState() == PED_DEAD) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ break;
+ }
+ if (!pVan->m_bSirenOrAlarm) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return; // Why?
+ }
+ if (pVan->GetStatus() == STATUS_WRECKED) {
+ GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
+ return; // Why?
+ }
+ break;
+ }
+ }
+ if (bObjectiveCompleted
+ || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
+ RestorePreviousObjective();
+ if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer)
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1;
+
+ if (CharCreatedBy != RANDOM_CHAR || bInVehicle) {
+ if (IsPedInControl())
+ RestorePreviousState();
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ ClearAimFlag();
+ ClearLookFlag();
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetFollowRoute(int16 currentPoint, int16 routeType)
+{
+ m_routeLastPoint = currentPoint;
+ m_routeType = routeType;
+ m_routePointsBeingPassed = 1;
+ m_routePointsPassed = 0;
+ m_objective = OBJECTIVE_FOLLOW_ROUTE;
+ m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
+ m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());
+}
+
+// --MIAMI: Done
+int
+CPed::GetNextPointOnRoute(void)
+{
+ int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+
+ // Route is complete
+ if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {
+
+ switch (m_routeType) {
+ case PEDROUTE_STOP_WHEN_DONE:
+ nextPoint = -1;
+ break;
+ case PEDROUTE_GO_BACKWARD_WHEN_DONE:
+ m_routePointsBeingPassed = -m_routePointsBeingPassed;
+ nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+ break;
+ case PEDROUTE_GO_TO_START_WHEN_DONE:
+ m_routePointsPassed = -1;
+ nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
+ break;
+ default:
+ break;
+ }
+ }
+ return nextPoint;
+}
+
+// --MIAMI: Done
+bool
+CPed::HaveReachedNextPointOnRoute(float distToCountReached)
+{
+ if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() < distToCountReached) {
+ m_routePointsPassed += m_routePointsBeingPassed;
+ return true;
+ }
+ return false;
+}
+
+// --MIAMI: Done
+bool
+CPed::CanSeeEntity(CEntity *entity, float threshold)
+{
+ float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
+ entity->GetPosition().x,
+ entity->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ if (neededAngle < 0.0f)
+ neededAngle += TWOPI;
+ else if (neededAngle > TWOPI)
+ neededAngle -= TWOPI;
+
+ float ourAngle = m_fRotationCur;
+ if (ourAngle < 0.0f)
+ ourAngle += TWOPI;
+ else if (ourAngle > TWOPI)
+ ourAngle -= TWOPI;
+
+ float neededTurn = Abs(neededAngle - ourAngle);
+
+ return neededTurn < threshold || TWOPI - threshold < neededTurn;
+}
+
+// --MIAMI: Done
+// Only used while deciding which gun ped should switch to, if no ammo left.
+bool
+CPed::SelectGunIfArmed(void)
+{
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+ if (GetWeapon(i).m_nAmmoTotal > 0) {
+ eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
+
+ if (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
+ weaponType == WEAPONTYPE_SPAS12_SHOTGUN || weaponType == WEAPONTYPE_STUBBY_SHOTGUN ||
+ weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M4 || weaponType == WEAPONTYPE_MP5 ||
+ weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) {
+ SetCurrentWeapon(i);
+ return true;
+ }
+ }
+ }
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+ return false;
+}
+// --MIAMI: Done
+void
+CPed::ReactToPointGun(CEntity *entWithGun)
+{
+ CPed *pedWithGun = (CPed*)entWithGun;
+ int waitTime;
+
+ if (IsPlayer() || !IsPedInControl() || (CharCreatedBy == MISSION_CHAR && !bCrouchWhenScared))
+ return;
+
+ if (m_leader == pedWithGun)
+ return;
+
+ if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||
+ (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f || (m_nPedType == PEDTYPE_GANG7 && pedWithGun == FindPlayerPed()))
+ return;
+
+ if (m_leader) {
+ if (FindPlayerPed() == m_leader)
+ return;
+
+ ClearLeader();
+ }
+ if (m_pedStats->m_flags & STAT_GUN_PANIC
+ && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
+ && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) {
+
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
+ SetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime);
+ Say(SOUND_PED_HANDS_COWER);
+ m_pLookTarget = pedWithGun;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ SetMoveState(PEDMOVE_NONE);
+
+ } else if (m_nPedType != pedWithGun->m_nPedType) {
+ if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
+ RegisterThreatWithGangPeds(pedWithGun);
+ }
+
+ if (m_nPedType == PEDTYPE_COP) {
+ if (pedWithGun->IsPlayer()) {
+ ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2);
+ if (bCrouchWhenShooting || bKindaStayInSamePlace) {
+ SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));
+ return;
+ }
+ }
+ }
+
+ if (m_nPedType != PEDTYPE_COP
+ && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())
+ && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun)
+ && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 6000);
+ SetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime);
+ Say(SOUND_PED_HANDS_UP);
+ m_pLookTarget = pedWithGun;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ SetMoveState(PEDMOVE_NONE);
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ m_fleeFrom = pedWithGun;
+ m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
+ }
+
+ if (FindPlayerPed() == pedWithGun && bRichFromMugging) {
+ int money = CGeneral::GetRandomNumberInRange(100, 300);
+ int pickupCount = money / 40 + 1;
+ int moneyPerPickup = money / pickupCount;
+
+ for (int i = 0; i < pickupCount; i++) {
+ float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x;
+ float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y;
+ bool found = false;
+ float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;
+ if (found) {
+ CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
+ }
+ }
+ bRichFromMugging = false;
+ }
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ReactToAttack(CEntity *attacker)
+{
+ if (IsPlayer() && attacker->IsPed()) {
+ InformMyGangOfAttack(attacker);
+ SetLookFlag(attacker, true);
+ SetLookTimer(700);
+ return;
+ }
+
+ if (m_nPedType == PEDTYPE_GANG7 && attacker->IsPed() && ((CPed*)attacker)->IsPlayer()) {
+ if (m_nPedState != PED_FALL) {
+ SetFall(15000, (AnimationId)(ANIM_KO_SHOT_FRONT1 + CGeneral::GetRandomNumberInRange(0, 5)), 0);
+ }
+
+ } else if (m_nPedState == PED_DRIVING && InVehicle()
+ && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {
+
+ if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE
+ && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)
+ && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {
+
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ }
+
+ } else if ((IsPedInControl() || m_nPedState == PED_DRIVING) && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
+ if (m_leader != attacker && (!m_leader || FindPlayerPed() != m_leader) && attacker->IsPed()) {
+
+ CPed *attackerPed = (CPed*)attacker;
+ if (bNotAllowedToDuck) {
+ if (!attackerPed->GetWeapon()->IsTypeMelee()) {
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ } else if (bCrouchWhenShooting || bKindaStayInSamePlace) {
+ SetDuck(CGeneral::GetRandomNumberInRange(1000,3000));
+ return;
+ }
+
+ if (m_nWaitState == WAITSTATE_STRIPPER) {
+ ClearWaitState();
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);
+ SetObjectiveTimer(20000);
+
+ } else {
+ if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) {
+ if (m_pedStats != attackerPed->m_pedStats) {
+ if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
+ RegisterThreatWithGangPeds(attackerPed);
+ }
+ if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker);
+ SetMoveState(PEDMOVE_RUN);
+ } else {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);
+ SetObjectiveTimer(20000);
+ }
+ }
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed);
+ SetMoveState(PEDMOVE_RUN);
+ if (attackerPed->GetWeapon()->IsTypeMelee())
+ Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+ if (!ped->EnteringCar()) {
+ if (ped->m_nPedState != PED_DRIVING)
+ ped->QuitEnteringCar();
+
+ return;
+ }
+
+ if (!ped->m_vehEnterType) {
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ if (ped->m_fHealth == 0.0f) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ bool itsVan = !!veh->bIsVan;
+ bool itsBus = !!veh->bIsBus;
+ bool itsLow = !!veh->bLowVehicle;
+ eDoors enterDoor;
+
+ 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->IsBike()) {
+ CPed *pedToDragOut = nil;
+ if (veh->GetStatus() == STATUS_ABANDONED) {
+ if (ped->m_vehEnterType == CAR_WINDSCREEN) {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_KICK, 6.0f);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+
+ } else if (veh->GetRight().z >= 0.5f || veh->GetRight().z <= -0.5f || veh->GetUp().z <= 0.0f) {
+ if (enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_REAR_LEFT) {
+ if (veh->GetRight().z > 0.0f)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_BIKE_PICKUP_R);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_BIKE_PULLUP_R);
+
+ } else {
+ if (veh->GetRight().z < 0.0f)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_BIKE_PICKUP_L);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_BIKE_PULLUP_L);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType,
+ enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ }
+ } else if (ped->m_vehEnterType == CAR_WINDSCREEN) {
+ if (veh->pDriver->m_nPedState != PED_DRIVING || veh->pDriver->bDontDragMeOutCar) {
+ ped->QuitEnteringCar();
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_KICK, 6.0f);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ pedToDragOut = veh->pDriver;
+ }
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ } else {
+ if (enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_FRONT_RIGHT) {
+ if (veh->pDriver) {
+ if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {
+ ped->QuitEnteringCar();
+ ped->SetFall(1000, ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_LR ? ANIM_KO_SPIN_L : ANIM_KO_SPIN_R, false);
+ return;
+ }
+ if (veh->pDriver->m_nPedState != PED_DRIVING || veh->pDriver->bDontDragMeOutCar) {
+ ped->QuitEnteringCar();
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterDoor == DOOR_FRONT_LEFT ? ANIM_BIKE_ELBOW_R : ANIM_BIKE_ELBOW_L);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ pedToDragOut = veh->pDriver;
+ }
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_FRONT_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ }
+ } else {
+ if (veh->pPassengers[0]) {
+ if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {
+ ped->QuitEnteringCar();
+ ped->SetFall(1000, ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_LR ? ANIM_KO_SPIN_L : ANIM_KO_SPIN_R, false);
+ return;
+ }
+ if (veh->pPassengers[0]->m_nPedState != PED_DRIVING || veh->pPassengers[0]->bDontDragMeOutCar) {
+ ped->QuitEnteringCar();
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD,
+ enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_ELBOW_R : ANIM_BIKE_ELBOW_L);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ pedToDragOut = veh->pPassengers[0];
+ }
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(),
+ ((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ }
+ }
+ }
+
+ if (pedToDragOut) {
+ pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
+ if (pedToDragOut->IsGangMember())
+ pedToDragOut->RegisterThreatWithGangPeds(ped);
+
+ if (ped->m_nPedType == PEDTYPE_COP && pedToDragOut == FindPlayerPed() && veh->IsBike())
+ ((CCopPed*)ped)->m_bDragsPlayerFromCar = 1;
+
+ if (pedToDragOut == veh->pDriver) {
+ if (veh->pPassengers[0])
+ veh->pPassengers[0]->SetBeingDraggedFromCar(veh, CAR_DOOR_LR, false);
+ }
+ }
+ return;
+ }
+
+ if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (ped->m_nPedState == PED_CARJACK || veh->m_nNumMaxPassengers == 0 && veh->pDriver && enterDoor == DOOR_FRONT_RIGHT) {
+ ped->PedAnimDoorOpenCB(nil, ped);
+ return;
+ }
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_R);
+ } else if (itsLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
+ }
+ } else if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN_L);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_L);
+ } else if (itsLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+ }
+ 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_VAN, ANIM_VAN_OPEN);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, 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_VAN, ANIM_VAN_OPEN_L);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, 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);
+
+ CPlayerPed *player = nil;
+ CCopPed *cop = nil;
+ veh->MakeNonDraggedPedsLeaveVehicle(veh->pDriver, ped, player, cop);
+ if (player && cop) {
+ cop->QuitEnteringCar();
+ cop->SetArrestPlayer(player);
+ }
+
+ if (player != veh->pDriver) {
+ veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
+ if (veh->pDriver->IsGangMember())
+ veh->pDriver->RegisterThreatWithGangPeds(ped);
+ }
+ return;
+ }
+ }
+ if (veh->IsOpenTopCar() && !veh->pDriver && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_JUMPIN_LHS);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ return;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+
+ } else {
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS);
+
+ ped->bCancelEnteringCar = true;
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+ if (!ped->EnteringCar()) {
+ if(ped->m_nPedState != PED_DRIVING)
+ ped->QuitEnteringCar();
+
+ return;
+ }
+
+ eDoors door;
+ CPed *pedInSeat = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ pedInSeat = veh->pPassengers[0];
+ if (!veh->pPassengers[0] && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
+ pedInSeat = veh->pDriver;
+ break;
+ case CAR_DOOR_RR:
+ door = DOOR_REAR_RIGHT;
+ pedInSeat = veh->pPassengers[2];
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ pedInSeat = veh->pDriver;
+ if (veh->bIsBus && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+ pedInSeat = nil;
+ break;
+ case CAR_DOOR_LR:
+ door = DOOR_REAR_LEFT;
+ pedInSeat = veh->pPassengers[1];
+ break;
+ default: assert(0);
+ }
+
+ if (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) {
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ bool isVan = veh->bIsVan;
+ bool isBus = veh->bIsBus;
+ bool isLow = veh->bLowVehicle;
+ bool vehUpsideDown = veh->IsUpsideDown();
+ if (ped->bCancelEnteringCar) {
+ if (ped->IsPlayer()) {
+ if (veh->pDriver) {
+ if (veh->pDriver->m_nPedType == PEDTYPE_COP) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+ }
+#ifdef CANCELLABLE_CAR_ENTER
+ if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+#endif
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ ped->bCancelEnteringCar = false;
+ return;
+ }
+ if (!veh->IsDoorMissing(door) && veh->IsCar()) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+
+ if (veh->m_vecMoveSpeed.Magnitude() > 0.2f ||
+ veh->IsCar() && veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI && ((CAutomobile*)veh)->m_nWheelsOnGround == 0) {
+ ped->QuitEnteringCar();
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR)
+ ped->SetFall(1000, ANIM_KO_SPIN_R, false);
+ else
+ ped->SetFall(1000, ANIM_KO_SPIN_L, false);
+
+ return;
+ }
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f);
+
+ if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF)
+ isVan = false;
+
+ if (ped->m_nPedState != PED_CARJACK || isBus) {
+
+ if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_LR) {
+ if (veh->IsBike()) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_R);
+ } else if (isVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN_L);
+ } else if (isBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_L);
+ } else if (isLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+ }
+ } else {
+ if (veh->IsBike()) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_L);
+ } else if (isVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETIN);
+ } else if (isBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_COACH_IN_R);
+ } else if (isLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
+ }
+
+ if (ped->m_vehEnterType == CAR_DOOR_RF && pedInSeat && veh->IsCar())
+ pedInSeat->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ }
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ CPed *pedToDragOut = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;
+ case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;
+ case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;
+ case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;
+ default: assert(0);
+ }
+
+ if (vehUpsideDown) {
+ ped->QuitEnteringCar();
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ }
+
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+
+ if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
+ if (pedToDragOut->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else if (ped->m_nPedType == PEDTYPE_COP) {
+ ped->QuitEnteringCar();
+ if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+
+ if (ped->m_pedInObjective->IsPlayer()) {
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ } else {
+ ped->ClearObjective();
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));
+ }
+
+ } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);
+ }
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+ } else if (pedToDragOut) {
+
+ if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+
+ if (pedToDragOut) {
+ CPlayerPed* player = nil;
+ CCopPed* cop = nil;
+ veh->MakeNonDraggedPedsLeaveVehicle(pedToDragOut, ped, player, cop);
+ if (player && cop) {
+ cop->QuitEnteringCar();
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ cop->SetArrestPlayer(player);
+ }
+
+ if (player != pedToDragOut) {
+ pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
+ if (pedToDragOut->IsGangMember())
+ pedToDragOut->RegisterThreatWithGangPeds(ped);
+ }
+ }
+ }
+ return;
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (ped->EnteringCar()) {
+ if (!ped->IsNotInWreckedVehicle())
+ return;
+
+#ifdef CANCELLABLE_CAR_ENTER
+ if (ped->bCancelEnteringCar) {
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ ped->bCancelEnteringCar = false;
+ return;
+ }
+#endif
+
+ bool isLow = !!veh->bLowVehicle;
+
+ int padNo;
+ if (ped->IsPlayer()) {
+
+ // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
+ switch (ped->m_nPedType) {
+ case PEDTYPE_PLAYER1:
+ padNo = 0;
+ break;
+ case PEDTYPE_PLAYER2:
+ padNo = 1;
+ break;
+ case PEDTYPE_PLAYER3:
+ padNo = 2;
+ break;
+ case PEDTYPE_PLAYER4:
+ padNo = 3;
+ break;
+ }
+ CPad *pad = CPad::GetPad(padNo);
+
+ if (!pad->ArePlayerControlsDisabled()) {
+
+ if (pad->GetTarget()
+ || pad->NewState.LeftStickX
+ || pad->NewState.LeftStickY
+ || pad->NewState.DPadUp
+ || pad->NewState.DPadDown
+ || pad->NewState.DPadLeft
+ || pad->NewState.DPadRight) {
+ ped->QuitEnteringCar();
+ ped->RestorePreviousObjective();
+ return;
+ }
+ }
+ }
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_LR) {
+ if (veh->IsBike())
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_R);
+ else if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+ } else {
+ if (veh->IsBike())
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_L);
+ else if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_RHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ ped->QuitEnteringCar();
+ }
+ } else if(ped->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*) arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ if (!ped->EnteringCar()) {
+ if(ped->m_nPedState != PED_DRIVING)
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ ped->RemoveWeaponWhenEnteringVehicle();
+ if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {
+ PedSetInCarCB(nil, ped);
+ ped->m_nLastPedState = ped->m_nPedState;
+ ped->SetPedState(PED_ARRESTED);
+ ped->bGonnaKillTheCarJacker = false;
+ if (veh) {
+ veh->m_nNumGettingIn = 0;
+ veh->m_nGettingInFlags = 0;
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ return;
+ }
+ if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF
+ && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
+ && veh->IsCar() && !veh->pDriver) {
+
+ if (!animAssoc || animAssoc->animId != ANIM_CAR_JUMPIN_LHS)
+ if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING)
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+
+ PedSetInCarCB(nil, ped);
+ return;
+ }
+ if (veh->IsBike()) {
+ ped->PedSetInCarCB(nil, ped);
+ return;
+ }
+ bool isVan = !!veh->bIsVan;
+ bool isBus = !!veh->bIsBus;
+ bool isLow = !!veh->bLowVehicle;
+ eDoors enterDoor;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ bool doorClosed = true;
+ if (veh->IsOpenTopCar() && enterDoor == DOOR_FRONT_LEFT && veh->IsDoorClosed(DOOR_FRONT_LEFT)) {
+ doorClosed = false;
+
+ } else if (!veh->IsDoorMissing(enterDoor)) {
+ if (veh->IsCar())
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);
+ }
+
+ CPed *driver = veh->pDriver;
+ if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
+ if (veh->bIsBus) {
+ driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (driver->IsPlayer()) {
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ driver->bBusJacked = true;
+ veh->bIsBeingCarJacked = false;
+ PedSetInCarCB(nil, ped);
+ if (ped->m_nPedType == PEDTYPE_COP
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ }
+ ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;
+ return;
+ }
+ if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) {
+ if (!driver->IsPlayer()) {
+ driver->bUsePedNodeSeek = true;
+ driver->m_pLastPathNode = nil;
+ if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear
+ || driver->CharCreatedBy == MISSION_CHAR
+ || veh->VehicleCreatedBy == MISSION_VEHICLE) {
+ driver->bFleeAfterExitingCar = true;
+ } else {
+ driver->bGonnaKillTheCarJacker = true;
+ veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);
+
+ if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+ }
+ if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)
+ && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {
+ veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ veh->pDriver->Say(SOUND_PED_CAR_JACKED);
+ veh->pDriver->SetRadioStation();
+ if (veh->m_nDoorLock == CARLOCK_UNLOCKED)
+ ped->Say(SOUND_PED_CAR_JACKING);
+
+ } else {
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ }
+ }
+ }
+ if (veh->IsDoorMissing(enterDoor) || !doorClosed || isBus) {
+ PedAnimDoorCloseCB(nil, ped);
+ } else {
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (isVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_CLOSE);
+ } else if (isLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LOW_RHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_RHS);
+ }
+ } else if (isVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_VAN_CLOSE_L);
+ } else if (isLow) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LOW_LHS);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSEDOOR_LHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedShuffle(void)
+{
+ if (m_pMyVehicle->pPassengers[0] == this) {
+ CPed *driver = m_pMyVehicle->pDriver;
+ if (!driver || driver->m_objective == OBJECTIVE_LEAVE_CAR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, m_pMyVehicle->bLowVehicle ? ANIM_CAR_LSHUFFLE_RHS : ANIM_CAR_SHUFFLE_RHS);
+ m_objective = OBJECTIVE_ENTER_CAR_AS_DRIVER;
+ m_pMyVehicle->RemovePassenger(this);
+ bInVehicle = false;
+ m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ if (ped->EnteringCar()) {
+ bool isLow = !!veh->bLowVehicle;
+
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f);
+
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
+ case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
+ case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
+ case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
+ default: assert(0);
+ }
+
+ if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);
+
+ if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus || veh->m_nNumMaxPassengers == 0) {
+ PedSetInCarCB(nil, ped);
+ } else if (ped->m_vehEnterType == CAR_DOOR_RF
+ && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||
+ (veh->pDriver != nil &&
+ (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR
+ && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE
+ || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)
+ veh->bIsBeingCarJacked = false;
+
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ PedSetInCarCB(nil, ped);
+
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (!ped->IsPlayer())
+ ped->bFleeAfterExitingCar = true;
+
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+
+ } else {
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
+ }
+ } else if (ped->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimShuffleCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+ if (ped->EnteringCar()) {
+ PedSetInCarCB(nil, ped);
+ } else if (ped->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetFormation(eFormation type)
+{
+ // FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7.
+ // To not change the behaviour, range in here tweaked by 1 with the use of enum.
+
+ switch (m_pedFormation) {
+ case FORMATION_REAR:
+ case FORMATION_REAR_LEFT:
+ case FORMATION_REAR_RIGHT:
+ case FORMATION_FRONT_LEFT:
+ case FORMATION_FRONT_RIGHT:
+ case FORMATION_LEFT:
+ case FORMATION_RIGHT:
+ case FORMATION_FRONT:
+ break;
+ default:
+ Error("Unknown formation type, PedAI.cpp");
+ break;
+ }
+ m_pedFormation = type;
+}
+
+// --MIAMI: Done
+CVector
+CPed::GetFormationPosition(void)
+{
+ if (!m_pedInObjective)
+ return GetPosition();
+
+ if (m_pedInObjective->m_nPedState == PED_DEAD) {
+ if (!m_pedInObjective->m_pedInObjective) {
+ m_pedInObjective = nil;
+ return GetPosition();
+ }
+ m_pedInObjective = m_pedInObjective->m_pedInObjective;
+ }
+
+ CVector formationOffset;
+ float offset = CGeneral::GetRandomNumberInRange(1.f, 1.25f) * 1.75f;
+ switch (m_pedFormation) {
+ case FORMATION_REAR:
+ formationOffset = CVector(0.0f, -offset, 0.0f);
+ break;
+ case FORMATION_REAR_LEFT:
+ formationOffset = CVector(-offset, -offset, 0.0f);
+ break;
+ case FORMATION_REAR_RIGHT:
+ formationOffset = CVector(offset, -offset, 0.0f);
+ break;
+ case FORMATION_FRONT_LEFT:
+ formationOffset = CVector(-offset, offset, 0.0f);
+ break;
+ case FORMATION_FRONT_RIGHT:
+ formationOffset = CVector(offset, offset, 0.0f);
+ break;
+ case FORMATION_LEFT:
+ formationOffset = CVector(-offset, 0.0f, 0.0f);
+ break;
+ case FORMATION_RIGHT:
+ formationOffset = CVector(offset, 0.0f, 0.0f);
+ break;
+ case FORMATION_FRONT:
+ formationOffset = CVector(0.0f, offset, 0.0f);
+ break;
+ default:
+ formationOffset = CVector(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ return m_pedInObjective->GetMatrix() * formationOffset;
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+ if (animAssoc) {
+ if ((animAssoc->animId == ANIM_CAR_ROLLOUT_LHS || animAssoc->animId == ANIM_CAR_ROLLOUT_RHS) && ped && ped->m_nPedState == PED_FALL) {
+ ped->RestoreHeadingRate();
+ return;
+ }
+ animAssoc->blendDelta = -1000.0f;
+ if (animAssoc->animId == ANIM_BIKE_GETOFF_BACK)
+ ped->RestoreHeadingRate();
+ }
+
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+ CVector posForZ = ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posForZ);
+ if (ped->GetPosition().z - 0.5f > posForZ.z) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+
+ veh->m_nStaticFrames = 0;
+ veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);
+ veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f);
+
+ /*
+ // Duplicate and only in PC for some reason
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+ */
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ bool closeDoor = !veh->IsDoorMissing(door);
+
+ int padNo;
+ if (ped->IsPlayer()) {
+
+ // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
+ switch (ped->m_nPedType) {
+ case PEDTYPE_PLAYER1:
+ padNo = 0;
+ break;
+ case PEDTYPE_PLAYER2:
+ padNo = 1;
+ break;
+ case PEDTYPE_PLAYER3:
+ padNo = 2;
+ break;
+ case PEDTYPE_PLAYER4:
+ padNo = 3;
+ break;
+ }
+ CPad* pad = CPad::GetPad(padNo);
+ bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225;
+ if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS
+ && (pad->GetTarget()
+ || pad->NewState.LeftStickX
+ || pad->NewState.LeftStickY
+ || pad->NewState.DPadUp
+ || pad->NewState.DPadDown
+ || pad->NewState.DPadLeft
+ || pad->NewState.DPadRight)
+ || veh->bIsBus
+ || veh->m_pCarFire
+ || engineIsIntact) {
+ closeDoor = false;
+ }
+ }
+
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ closeDoor = false;
+
+ if (!closeDoor) {
+ if (!veh->IsDoorMissing(door) && !veh->bIsBus) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+
+ if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {
+ // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa?
+ if (!veh->IsDoorMissing(door))
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+ } else {
+ switch (door) {
+ case DOOR_FRONT_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_FRONT_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ case DOOR_REAR_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_REAR_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
+ return;
+}
+
+// --MIAMI: Done
+void
+CPed::LineUpPedWithCar(PedLineUpPhase phase)
+{
+ bool vehIsUpsideDown = false;
+ int vehAnim;
+ float seatPosMult = 0.0f;
+ float currentZ;
+ float adjustedTimeStep;
+ CVector autoZPos;
+
+ if (CReplay::IsPlayingBack())
+ return;
+
+ if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
+ if (m_pMyVehicle->IsBike()) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_RIDE) ||
+ RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_PASSENGER)) {
+ SetPedPositionInCar();
+ return;
+ }
+ } else {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
+ SetPedPositionInCar();
+ return;
+ }
+ }
+ bChangedSeat = true;
+ }
+ if (phase == LINE_UP_TO_CAR_FALL) {
+ SetPedPositionInCar();
+ autoZPos = GetPosition();
+ CPedPlacement::FindZCoorForPed(&autoZPos);
+ if (m_pVehicleAnim && (m_pVehicleAnim->animId == ANIM_CAR_ROLLOUT_LHS || m_pVehicleAnim->animId == ANIM_CAR_ROLLOUT_RHS)
+ && autoZPos.z > GetPosition().z) {
+ m_matrix.GetPosition().z = autoZPos.z;
+ }
+ if (m_pVehicleAnim && m_pVehicleAnim->animId == ANIM_BIKE_HIT) {
+ if (autoZPos.z > GetPosition().z)
+ m_matrix.GetPosition().z += m_pVehicleAnim->GetProgress() * (autoZPos.z - GetPosition().z);
+
+ } else if (m_pVehicleAnim) {
+ if (m_pVehicleAnim->animId == ANIM_BIKE_GETOFF_BACK) {
+ if (autoZPos.z > GetPosition().z) {
+ m_matrix.GetPosition().z += (m_pVehicleAnim->currentTime * (20.f / 7.f)) * (autoZPos.z - GetPosition().z);
+ }
+ }
+ }
+ return;
+ }
+ if (phase == LINE_UP_TO_CAR_START) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ CVehicle *veh = m_pMyVehicle;
+
+ // Not quite right, IsUpsideDown func. checks for <= -0.9f.
+ if (veh->GetUp().z <= -0.8f)
+ vehIsUpsideDown = true;
+
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = -PI + veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else {
+ // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.
+
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else if (m_vehEnterType == CAR_WINDSCREEN) {
+ m_fRotationDest = veh->GetForward().Heading() + PI;
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ }
+
+ bool multExtractedFromAnim = false;
+ bool multExtractedFromAnimBus = false;
+ float zBlend;
+ if (m_pVehicleAnim) {
+ vehAnim = m_pVehicleAnim->animId;
+
+ switch (vehAnim) {
+ case ANIM_CAR_JACKED_RHS:
+ case ANIM_CAR_LJACKED_RHS:
+ case ANIM_CAR_JACKED_LHS:
+ case ANIM_CAR_LJACKED_LHS:
+ case ANIM_VAN_GETIN_L:
+ case ANIM_VAN_GETIN:
+ multExtractedFromAnim = true;
+ zBlend = Max(m_pVehicleAnim->GetProgress() - 0.3f, 0.0f) / (1.0f - 0.3f);
+ // fall through
+
+ case ANIM_CAR_QJACKED:
+ case ANIM_CAR_GETOUT_LHS:
+ case ANIM_CAR_GETOUT_LOW_LHS:
+ case ANIM_CAR_GETOUT_RHS:
+ case ANIM_CAR_GETOUT_LOW_RHS:
+
+ if (!multExtractedFromAnim) {
+ multExtractedFromAnim = true;
+ zBlend = Max(m_pVehicleAnim->GetProgress() - 0.5f, 0.0f) / (1.0f - 0.5f);
+ }
+ // fall through
+
+ case ANIM_CAR_CRAWLOUT_RHS:
+ case ANIM_CAR_CRAWLOUT_RHS2:
+ case ANIM_VAN_GETOUT_L:
+ case ANIM_VAN_GETOUT:
+ case ANIM_BIKE_GETOFF_RHS:
+ case ANIM_BIKE_GETOFF_LHS:
+ seatPosMult = m_pVehicleAnim->GetProgress();
+ break;
+ case ANIM_CAR_GETIN_RHS:
+ case ANIM_CAR_GETIN_LHS:
+ if (veh && veh->IsCar() && veh->bIsBus) {
+ multExtractedFromAnimBus = true;
+ zBlend = Min(m_pVehicleAnim->GetProgress(), 0.5f) / 0.5f;
+ }
+ // fall through
+
+ case ANIM_CAR_QJACK:
+ case ANIM_CAR_GETIN_LOW_LHS:
+ case ANIM_CAR_GETIN_LOW_RHS:
+ case ANIM_DRIVE_BOAT:
+ seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ break;
+ case ANIM_CAR_CLOSEDOOR_LHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_LHS:
+ case ANIM_CAR_CLOSEDOOR_RHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_RHS:
+ case ANIM_CAR_SHUFFLE_RHS:
+ case ANIM_CAR_LSHUFFLE_RHS:
+ seatPosMult = 0.0f;
+ break;
+ case ANIM_CAR_JUMPIN_LHS:
+ {
+ float animLength = m_pVehicleAnim->hierarchy->totalLength;
+ seatPosMult = Max(0.0f, 0.5f * animLength - m_pVehicleAnim->currentTime) / animLength;
+ break;
+ }
+ case ANIM_CAR_CLOSE_LHS:
+ case ANIM_CAR_CLOSE_RHS:
+ case ANIM_COACH_OPEN_L:
+ case ANIM_COACH_OPEN_R:
+ case ANIM_COACH_IN_L:
+ case ANIM_COACH_IN_R:
+ case ANIM_COACH_OUT_L:
+ seatPosMult = 1.0f;
+ break;
+ default:
+ if (veh->IsBike()) {
+ seatPosMult = 0.0f;
+ } else {
+ if (bInVehicle)
+ seatPosMult = 0.0f;
+ else
+ seatPosMult = 1.0f;
+ }
+ break;
+ }
+ } else {
+ if (veh->IsBike()) {
+ seatPosMult = 0.0f;
+ } else {
+ if (bInVehicle)
+ seatPosMult = 0.0f;
+ else
+ seatPosMult = 1.0f;
+ }
+ }
+
+ CVector neededPos;
+
+ if (phase == LINE_UP_TO_CAR_2) {
+ neededPos = GetPosition();
+ } else {
+ neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
+ }
+
+ autoZPos = neededPos;
+
+ if (veh->bIsInWater) {
+ if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown())
+ autoZPos.z += 1.0f;
+ } else {
+ CPedPlacement::FindZCoorForPed(&autoZPos);
+ }
+
+ if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) {
+ neededPos.z = GetPosition().z;
+
+ // Getting out
+ if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {
+ float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();
+
+ // If we're not in ground at next step, apply animation
+ if (neededPos.z + nextZSpeed >= autoZPos.z) {
+ m_vecMoveSpeed.z = nextZSpeed;
+ ApplyMoveSpeed();
+ // Removing below line breaks the animation
+ neededPos.z = GetPosition().z;
+ } else {
+ neededPos.z = autoZPos.z;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ if (autoZPos.z > neededPos.z) {
+ vehAnim = m_pVehicleAnim->animId;
+ if (veh->IsBike() && (m_pVehicleAnim && vehAnim != ANIM_BIKE_KICK)) {
+ float zBlend;
+ if (vehAnim != ANIM_BIKE_GETOFF_RHS && vehAnim != ANIM_BIKE_GETOFF_LHS) {
+ if (vehAnim != ANIM_BIKE_JUMPON_R && vehAnim != ANIM_BIKE_JUMPON_L) {
+ zBlend = 0.0f;
+ } else {
+ float animLength = m_pVehicleAnim->hierarchy->totalLength;
+ zBlend = Min(1.0f, 2.0f * m_pVehicleAnim->currentTime / animLength);
+ }
+ } else {
+ zBlend = 1.0f - seatPosMult;
+ }
+ float curZ = veh->GetPosition().z + FEET_OFFSET;
+ neededPos.z = ((curZ - autoZPos.z) - veh->GetHeightAboveRoad()) * zBlend + autoZPos.z;
+ } else if (multExtractedFromAnim) {
+ neededPos.z += (autoZPos.z - neededPos.z) * zBlend;
+ } else {
+ currentZ = GetPosition().z;
+ if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) {
+ neededPos.z = autoZPos.z;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);
+ }
+ }
+ } else {
+ // We may need to raise up the ped
+ if (phase == LINE_UP_TO_CAR_START) {
+ currentZ = GetPosition().z;
+
+ if (neededPos.z > currentZ) {
+ if (multExtractedFromAnimBus) {
+ neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;
+ } else {
+ if (m_pVehicleAnim &&
+ (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS
+ || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
+ } else if (EnteringCar() || m_nPedState == PED_DRIVING && veh->IsBike()) {
+ neededPos.z = Max(currentZ, autoZPos.z);
+ }
+ }
+ }
+ }
+ }
+
+ bool stillGettingInOut = false;
+ if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
+ stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;
+
+ if (!stillGettingInOut) {
+ m_fRotationCur = m_fRotationDest;
+ } else {
+ float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;
+
+ if (timeUntilStateChange <= 0.0f) {
+ m_vecOffsetSeek.x = 0.0f;
+ m_vecOffsetSeek.y = 0.0f;
+ }
+ m_vecOffsetSeek.z = 0.0f;
+
+ neededPos -= timeUntilStateChange * m_vecOffsetSeek;
+
+ if (PI + m_fRotationCur < limitedDest) {
+ limitedDest -= 2 * PI;
+ } else if (m_fRotationCur - PI > limitedDest) {
+ limitedDest += 2 * PI;
+ }
+ m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);
+ }
+
+ if (seatPosMult > 0.2f || vehIsUpsideDown || veh->IsBike()) {
+ SetPosition(neededPos);
+ SetHeading(m_fRotationCur);
+ } else {
+ CMatrix vehDoorMat(veh->GetMatrix());
+ vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
+
+ if (m_vehEnterType == CAR_WINDSCREEN || veh->bIsBus) {
+ CMatrix correctionMat;
+ if (veh->bIsBus && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR))
+ correctionMat.SetRotateZ(-HALFPI);
+ else if (veh->bIsBus && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR))
+ correctionMat.SetRotateZ(HALFPI);
+ else
+ correctionMat.SetRotateZ(PI);
+
+ vehDoorMat = vehDoorMat * correctionMat;
+ }
+ GetMatrix() = vehDoorMat;
+ }
+
+}
+
+// --MIAMI: Done
+void
+CPed::SetCarJack(CVehicle* car)
+{
+ uint8 doorFlag;
+ eDoors door;
+ CPed *pedInSeat = nil;
+
+ if (car->IsBoat())
+ return;
+
+ if (car->IsBike()) {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ pedInSeat = car->pDriver;
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ pedInSeat = car->pPassengers[0];
+ break;
+ case CAR_DOOR_LF:
+ case CAR_WINDSCREEN:
+ doorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_LEFT;
+ pedInSeat = car->pDriver;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_LEFT;
+ pedInSeat = car->pPassengers[0];
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+ } else {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ if (car->pPassengers[0]) {
+ pedInSeat = car->pPassengers[0];
+ }
+ else if (m_nPedType == PEDTYPE_COP) {
+ pedInSeat = car->pDriver;
+ }
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ pedInSeat = car->pPassengers[2];
+ break;
+ case CAR_DOOR_LF:
+ doorFlag = CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ pedInSeat = car->pDriver;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ pedInSeat = car->pPassengers[1];
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+ }
+
+ if(car->bIsBus)
+ pedInSeat = car->pDriver;
+
+ if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||
+ CharCreatedBy == MISSION_CHAR || (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))
+ if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
+ if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
+ if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
+ if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
+ SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
+}
+
+// --MIAMI: Done
+void
+CPed::SetCarJack_AllClear(CVehicle* car, uint32 doorNode, uint32 doorFlag)
+{
+ if (m_nPedState != PED_SEEK_CAR)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ SetPedState(PED_CARJACK);
+ car->bIsBeingCarJacked = true;
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+
+ if (m_nPedType == PEDTYPE_COP)
+ Say(SOUND_PED_ARREST_COP);
+ else if (car->m_nDoorLock == CARLOCK_UNLOCKED)
+ Say(SOUND_PED_CAR_JACKING, 1000);
+
+ CVector carEnterPos;
+ carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ car->m_nGettingInFlags |= doorFlag;
+ m_vecOffsetSeek = carEnterPos - GetPosition();
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
+
+ if(car->IsBike()){
+ bUsesCollision = false;
+ PedAnimAlignCB(nil, this);
+ } else {
+ float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);
+ bUsesCollision = false;
+
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f);
+
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
+{
+ if (m_nPedState == PED_DRAG_FROM_CAR)
+ return;
+
+ bUsesCollision = false;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_nLastPedState = PED_IDLE;
+ SetMoveState(PEDMOVE_STILL);
+ m_pSeekTarget = veh;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+
+ if (veh->IsBike()) {
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ if (veh->pPassengers[0] != this && (vehEnterType != CAR_WINDSCREEN || veh->pPassengers[0]))
+ m_vehEnterType = CAR_DOOR_LF;
+ else
+ m_vehEnterType = CAR_DOOR_LR;
+ } else {
+ m_vehEnterType = vehEnterType;
+ }
+
+ if (m_vehEnterType == CAR_DOOR_LF) {
+ if (veh->pDriver && veh->pDriver->IsPlayer())
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ else
+ veh->SetStatus(STATUS_ABANDONED);
+ }
+ RemoveInCarAnims();
+ SetMoveState(PEDMOVE_NONE);
+ LineUpPedWithCar(veh->IsBike() ? LINE_UP_TO_CAR_FALL : LINE_UP_TO_CAR_START);
+ m_pVehicleAnim = nil;
+ SetPedState(PED_DRAG_FROM_CAR);
+ bChangedSeat = false;
+ bWillBeQuickJacked = quickJack;
+
+ SetHeading(m_fRotationCur);
+
+ Say(SOUND_PED_CAR_JACKED);
+ SetRadioStation();
+
+ if(veh->IsBike())
+ veh->m_nGettingOutFlags |= GetBikeDoorFlagInclJumpInFromFront(m_vehEnterType);
+ else
+ veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
+}
+
+// --MIAMI: Done
+void
+CPed::BeingDraggedFromCar(void)
+{
+ AnimationId enterAnim;
+ bool dontRunAnim = false;
+
+ if (!m_pVehicleAnim) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1000.0f);
+
+ AssocGroupId assocGroup;
+ if (m_pMyVehicle && m_pMyVehicle->IsBike()) {
+ enterAnim = ANIM_BIKE_HIT;
+ assocGroup = ((CBike*)m_pMyVehicle)->m_bikeAnimType;
+
+ } else {
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (bWillBeQuickJacked && m_vehEnterType == CAR_DOOR_LF) {
+ enterAnim = ANIM_CAR_QJACKED;
+ } else if (m_pMyVehicle->bLowVehicle) {
+ enterAnim = ANIM_CAR_LJACKED_LHS;
+ } else {
+ enterAnim = ANIM_CAR_JACKED_LHS;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (m_pMyVehicle->bLowVehicle)
+ enterAnim = ANIM_CAR_LJACKED_RHS;
+ else
+ enterAnim = ANIM_CAR_JACKED_RHS;
+ } else
+ dontRunAnim = true;
+
+ assocGroup = ASSOCGRP_STD;
+ }
+
+ if (!dontRunAnim)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), assocGroup, enterAnim);
+
+ m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
+
+ if (m_pMyVehicle && m_pMyVehicle->IsBike()) {
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ }
+ return;
+
+ } else if (m_pVehicleAnim->animId == ANIM_BIKE_HIT) {
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+
+ } else if (m_pVehicleAnim->currentTime <= 1.4f) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_2);
+ }
+
+ static float mult = 5.f;
+ if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * mult);
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetEnterCar(CVehicle *car, uint32 unused)
+{
+ if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
+ RestorePreviousState();
+ RestorePreviousObjective();
+ } else {
+ uint8 doorFlag;
+ eDoors door;
+ if (car->IsBike()) {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_WING_LF:
+ case CAR_WING_LR:
+ case CAR_BONNET:
+ case CAR_BOOT:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ case CAR_DOOR_LF:
+ case CAR_WINDSCREEN:
+ doorFlag = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ break;
+ }
+ } else {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ if(car->m_nNumMaxPassengers != 0)
+ doorFlag = CAR_DOOR_FLAG_LF;
+ else
+ doorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;
+
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ if (car->m_nNumMaxPassengers != 0)
+ doorFlag = CAR_DOOR_FLAG_LR;
+ else
+ doorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;
+
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+ }
+ if (!IsPedInControl() || m_fHealth <= 0.0f
+ || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
+ || car->bIsBeingCarJacked || m_pVehicleAnim
+ || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
+ SetMoveState(PEDMOVE_STILL);
+ else
+ SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+{
+ float zDiff = 0.0f;
+ car->m_nGettingInFlags |= doorFlag;
+ bVehEnterDoorIsBlocked = false;
+ if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_vehEnterType = doorNode;
+ SetPedState(PED_ENTER_CAR);
+ if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && !car->IsBike()) {
+ car->bIsBeingCarJacked = true;
+ }
+
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+ bUsesCollision = false;
+ CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ // Because buses have stairs
+ if (!m_pMyVehicle->bIsBus)
+ zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);
+
+ m_vecOffsetSeek = doorOpenPos - GetPosition();
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
+
+ if (car->IsBoat()) {
+ if (car->pHandling->Flags & HANDLING_SIT_IN_BOAT)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+
+ PedSetInCarCB(nil, this);
+ bVehExitWillBeInstant = true;
+
+ } else if (car->IsBike()) {
+ PedAnimAlignCB(0, this);
+ car->AutoPilot.m_nCruiseSpeed = 0;
+
+ } else {
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::EnterCar(void)
+{
+ if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
+ CVehicle *veh = m_pMyVehicle;
+
+ // Not used.
+ // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
+
+ if (veh->CanPedOpenLocks(this)) {
+ if (m_vehEnterType && m_pVehicleAnim) {
+ veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime);
+ }
+ }
+ bIsInTheAir = false;
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ if (veh->IsBike()) {
+ CBike *bike = (CBike*)veh;
+ if (bike->GetStatus() == STATUS_ABANDONED && !bike->bIsBeingPickedUp && m_pVehicleAnim) {
+ int anim = m_pVehicleAnim->animId;
+
+ // One is pickup and other one is pullup, not same :p
+ if ((anim == ANIM_BIKE_PICKUP_R || anim == ANIM_BIKE_PICKUP_L) && m_pVehicleAnim->currentTime > 0.4667f)
+ bike->bIsBeingPickedUp = true;
+ else if ((anim == ANIM_BIKE_PULLUP_R || anim == ANIM_BIKE_PULLUP_L) && m_pVehicleAnim->currentTime > 0.4667f)
+ bike->bIsBeingPickedUp = true;
+ } else if (m_nPedState == PED_CARJACK && m_pVehicleAnim) {
+ if (m_pVehicleAnim->currentTime > 0.4f && m_pVehicleAnim->currentTime - m_pVehicleAnim->timeStep <= 0.4f) {
+ int anim = m_pVehicleAnim->animId;
+ if (anim == ANIM_BIKE_KICK) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_187, 3.0f);
+ } else if (anim == ANIM_BIKE_ELBOW_R || anim == ANIM_BIKE_ELBOW_L) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_186, 3.0f);
+ }
+ }
+ }
+ }
+ } else {
+ QuitEnteringCar();
+ SetDie();
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::QuitEnteringCar(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (m_pVehicleAnim)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+
+ RestartNonPartialAnims();
+
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+
+ if (veh) {
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
+ veh->bIsBeingCarJacked = false;
+
+ if (veh->m_nNumGettingIn != 0)
+ veh->m_nNumGettingIn--;
+
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+ RestorePreviousObjective();
+
+ if (veh->IsBike()) {
+ veh->m_nGettingInFlags &= ~GetBikeDoorFlag(m_vehEnterType);
+ ((CBike*)veh)->bIsBeingPickedUp = false;
+ } else
+ veh->m_nGettingInFlags &= ~GetEnterCarDoorFlag(m_vehEnterType, veh->m_nNumMaxPassengers);
+ }
+
+ bUsesCollision = true;
+
+ if (DyingOrDead()) {
+ if (m_pVehicleAnim) {
+ m_pVehicleAnim->blendDelta = -4.0f;
+ m_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT;
+ m_pVehicleAnim->flags &= ~ASSOC_RUNNING;
+ }
+ } else
+ SetIdle();
+
+ m_pVehicleAnim = nil;
+
+ if (veh) {
+ if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::SetExitBoat(CVehicle *boat)
+{
+ SetPedState(PED_IDLE);
+ CVector newPos = GetPosition();
+ RemoveInCarAnims();
+ CColModel* boatCol = boat->GetColModel();
+ if (boat->IsUpsideDown()) {
+ newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z };
+ newPos = boat->GetMatrix() * newPos;
+ newPos.z += 1.0f;
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ } else {
+ if (boat->m_modelIndex == MI_SKIMMER) {
+ if (!boat->bIsInWater) {
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ SetMoveState(PEDMOVE_STILL);
+ bTryingToReachDryLand = true;
+ float upMult = 1.04f + boatCol->boundingBox.min.z;
+ float rightMult = 0.6f * boatCol->boundingBox.max.x;
+ newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();
+ SetPosition(newPos);
+ if (m_pMyVehicle) {
+ PositionPedOutOfCollision();
+ } else {
+ m_pMyVehicle = boat;
+ PositionPedOutOfCollision();
+ m_pMyVehicle = nil;
+ }
+ return;
+ }
+
+ newPos.z += 2.0f;
+ }
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ CColPoint foundCol;
+ CEntity *foundEnt = nil;
+ if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))
+ newPos.z = FEET_OFFSET + foundCol.point.z;
+ }
+ SetPosition(newPos);
+ SetMoveState(PEDMOVE_STILL);
+ m_vecMoveSpeed = boat->m_vecMoveSpeed;
+}
+
+// --MIAMI: Done
+// wantedDoorNode = 0 means that func. will determine it
+void
+CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
+{
+ uint32 optedDoorNode = wantedDoorNode;
+ bool teleportNeeded = false;
+ bool isLow = !!veh->bLowVehicle;
+
+ bool canJumpOut = false;
+ if (!veh->CanPedExitCar(false) && !bBusJacked) {
+ if (IsPlayer()) {
+ canJumpOut = veh->IsBike() ? veh->CanPedJumpOffBike() : veh->CanPedJumpOutCar();
+ }
+ if (!canJumpOut) {
+ if (veh->pDriver) {
+ if (veh->pDriver->IsPlayer()) {
+ if (veh->pDriver != this) {
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ bHeldHostageInCar = true;
+ }
+ } else {
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ veh->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
+ }
+ return;
+ }
+ }
+
+ if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ return;
+
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ if (wantedDoorNode == 0) {
+ optedDoorNode = CAR_DOOR_LF;
+ if (veh->IsBike()) {
+ if (canJumpOut) {
+ optedDoorNode = veh->pPassengers[0] == this ? CAR_BUMP_REAR : CAR_BOOT;
+ } else if (veh->pPassengers[0] == this) {
+ optedDoorNode = CAR_DOOR_LR;
+ } else {
+ optedDoorNode = CAR_DOOR_LF;
+ }
+ } else if (veh->bIsBus) {
+ optedDoorNode = CAR_DOOR_LF;
+ } else if (veh->pDriver == this) {
+ optedDoorNode = CAR_DOOR_LF;
+ } else if (veh->pPassengers[0] == this) {
+ optedDoorNode = CAR_DOOR_RF;
+ } else if (veh->pPassengers[1] == this) {
+ optedDoorNode = CAR_DOOR_LR;
+ } else if (veh->pPassengers[2] == this) {
+ optedDoorNode = CAR_DOOR_RR;
+ } else {
+ for (int i = 3; i < veh->m_nNumMaxPassengers; ++i) {
+ if (veh->pPassengers[i] == this) {
+ if (i & 1)
+ optedDoorNode = CAR_DOOR_RR;
+ else
+ optedDoorNode = CAR_DOOR_LR;
+
+ break;
+ }
+ }
+ }
+ }
+ bool someoneExitsFromOurExitDoor = false;
+ bool someoneEntersFromOurExitDoor = false;
+ if (veh->IsBike()) {
+ switch (optedDoorNode) {
+ case CAR_BUMP_REAR:
+ case CAR_DOOR_RR:
+ case CAR_DOOR_LR:
+ if (veh->m_nGettingInFlags & (CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR))
+ someoneEntersFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_RF:
+ case CAR_DOOR_LF:
+ case CAR_BOOT:
+ if (veh->m_nGettingInFlags & (CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF))
+ someoneEntersFromOurExitDoor = true;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_RR:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_LF:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ case CAR_DOOR_LR:
+ if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ someoneEntersFromOurExitDoor = true;
+ if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR)
+ someoneExitsFromOurExitDoor = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) {
+ RestorePreviousObjective();
+ return;
+ }
+ if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {
+#if defined GTAVC_JP_PATCH || defined FIX_BUGS
+ if (veh->pDriver == this && !IsPlayer() && veh == CGameLogic::pShortCutTaxi) {
+ m_objective = OBJECTIVE_NONE;
+ return;
+ }
+#endif
+ bool thereIsRoom;
+ if (canJumpOut) {
+ thereIsRoom = 1;
+ } else {
+ // Again, unused...
+ // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
+ thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
+ }
+
+ if (!thereIsRoom) {
+ bool trySideSeat = false;
+ CPed *pedOnSideSeat;
+ int firstOptedDoor = optedDoorNode;
+ if (veh->IsBike()) {
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ optedDoorNode = CAR_DOOR_LF;
+ break;
+ case CAR_DOOR_RR:
+ optedDoorNode = CAR_DOOR_LR;
+ break;
+ case CAR_DOOR_LF:
+ optedDoorNode = CAR_DOOR_RF;
+ break;
+ case CAR_DOOR_LR:
+ optedDoorNode = CAR_DOOR_RR;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ if (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) {
+ pedOnSideSeat = veh->pDriver;
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_LF;
+
+ break;
+ case CAR_DOOR_RR:
+ if (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
+ pedOnSideSeat = veh->pPassengers[1];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_LR;
+
+ break;
+ case CAR_DOOR_LF:
+ if (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
+ pedOnSideSeat = veh->pPassengers[0];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_RF;
+
+ break;
+ case CAR_DOOR_LR:
+ if (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
+ pedOnSideSeat = (CPed*)veh->pPassengers[2];
+ trySideSeat = true;
+ } else
+ optedDoorNode = CAR_DOOR_RR;
+
+ break;
+ default:
+ break;
+ }
+ }
+ if (trySideSeat) {
+ if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR)
+ return;
+
+ switch (optedDoorNode) {
+ case CAR_DOOR_RF:
+ optedDoorNode = CAR_DOOR_LF;
+ break;
+ case CAR_DOOR_RR:
+ optedDoorNode = CAR_DOOR_LR;
+ break;
+ case CAR_DOOR_LF:
+ optedDoorNode = CAR_DOOR_RF;
+ break;
+ case CAR_DOOR_LR:
+ optedDoorNode = CAR_DOOR_RR;
+ break;
+ default:
+ break;
+ }
+ }
+ // ...
+ // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
+ if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) {
+ if (!IsPlayer() && CharCreatedBy != MISSION_CHAR)
+ return;
+
+ // needed for PositionPedOutOfCollision()
+ optedDoorNode = firstOptedDoor;
+ m_vehEnterType = firstOptedDoor;
+ PositionPedOutOfCollision();
+ teleportNeeded = true;
+ }
+ }
+
+ if (!teleportNeeded && veh->IsOnItsSide()) {
+ m_vehEnterType = optedDoorNode;
+ PositionPedOutOfCollision();
+ teleportNeeded = true;
+ }
+
+ if (m_nPedState == PED_FLEE_POS) {
+ m_nLastPedState = PED_FLEE_POS;
+ m_nPrevMoveState = PEDMOVE_RUN;
+ SetMoveState(PEDMOVE_SPRINT);
+ } else {
+ m_nLastPedState = PED_IDLE;
+ m_nPrevMoveState = PEDMOVE_STILL;
+ SetMoveState(PEDMOVE_STILL);
+ }
+
+ bUsesCollision = false;
+ m_pSeekTarget = veh;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_vehEnterType = optedDoorNode;
+ SetPedState(PED_EXIT_CAR);
+ if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+ RemoveInCarAnims();
+ SetMoveState(PEDMOVE_NONE);
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+
+ if (teleportNeeded) {
+ PedSetOutCarCB(nil, this);
+ } else {
+ if (veh->GetUp().z <= -0.8f && !veh->IsBike()) {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2);
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS);
+ }
+ m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
+
+ } else if (veh->IsBike()) {
+ CBike* bike = (CBike*)veh;
+ switch (m_vehEnterType) {
+ case CAR_BUMP_REAR:
+ case CAR_BOOT:
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_BACK);
+ break;
+ case CAR_DOOR_RF:
+ case CAR_DOOR_RR:
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_LHS);
+ break;
+ case CAR_DOOR_LF:
+ case CAR_DOOR_LR:
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_RHS);
+ break;
+ default:
+ break;
+ }
+ int8 exitFlags = 0;
+
+ // Bike door flags incl. passenger jump off
+ switch (m_vehEnterType) {
+ case CAR_BUMP_REAR:
+ case CAR_DOOR_RR:
+ case CAR_DOOR_LR:
+ exitFlags = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;
+ break;
+ case CAR_DOOR_RF:
+ case CAR_DOOR_LF:
+ case CAR_BOOT:
+ exitFlags = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;
+ break;
+ }
+
+ // Passenger get off
+ if (m_vehEnterType == CAR_BUMP_REAR || m_vehEnterType == CAR_BOOT) {
+ m_pVehicleAnim->SetFinishCallback(RestoreHeadingRateCB, this);
+ m_headingRate = 0.0f;
+
+ } else {
+ veh->m_nGettingOutFlags |= exitFlags;
+ m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
+ }
+
+ } else {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ if (canJumpOut) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLOUT_RHS);
+ } else if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ }
+ break;
+ case CAR_DOOR_RR:
+ if (canJumpOut) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLOUT_RHS);
+ } else if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETOUT);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ }
+ break;
+ case CAR_DOOR_LF:
+ if (canJumpOut) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLOUT_LHS);
+ } else if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ }
+ break;
+ case CAR_DOOR_LR:
+ if (canJumpOut) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLOUT_LHS);
+ } else if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_VAN_GETOUT_L);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ }
+ break;
+ default:
+ break;
+ }
+ if (!bBusJacked && !canJumpOut) {
+ veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
+ }
+ m_pVehicleAnim->SetFinishCallback(canJumpOut ? RestoreHeadingRateCB : PedAnimStepOutCarCB, this);
+ }
+ }
+ bChangedSeat = false;
+ if (veh->bIsBus)
+ bRenderPedInCar = true;
+
+ SetRadioStation();
+ if (veh->pDriver == this) {
+ if (IsPlayer())
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ else
+ veh->SetStatus(STATUS_ABANDONED);
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ExitCar(void)
+{
+ if (!m_pVehicleAnim) {
+ if (InVehicle()) {
+ if (m_pMyVehicle->IsBike()) {
+ if (m_vehEnterType == CAR_BOOT || m_vehEnterType == CAR_BUMP_REAR) {
+ ((CBike*)m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNARMED, 0, this, false);
+ }
+ } else if (m_pMyVehicle->IsCar()) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLOUT_LHS)) {
+ ((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_LF, this);
+ } else if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLOUT_RHS)) {
+ ((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_RF, this);
+ }
+ }
+ }
+ return;
+ }
+
+ AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;
+ float animTime = m_pVehicleAnim->currentTime;
+
+ if (exitAnim == ANIM_BIKE_GETOFF_BACK) {
+ if (animTime > 0.35f && m_pMyVehicle && m_pMyVehicle->IsBike())
+ ((CBike*)m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNARMED, 0, this, false);
+ else
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+
+ } else if (exitAnim == ANIM_CAR_ROLLOUT_LHS || exitAnim == ANIM_CAR_ROLLOUT_RHS) {
+ if (animTime > 0.07f && m_pMyVehicle && m_pMyVehicle->IsCar()) {
+ if (exitAnim == ANIM_CAR_ROLLOUT_LHS) {
+ ((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_LF, this);
+ } else {
+ ((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_RF, this);
+ }
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+ }
+ } else {
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime);
+
+ if (m_pSeekTarget) {
+ // Car is upside down
+ if (m_pMyVehicle->GetUp().z > -0.8f) {
+ if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f)
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ else
+ LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));
+ }
+ else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ }
+ }
+
+ // If there is someone in front of the door, make him fall while we exit.
+ if (m_nPedState == PED_EXIT_CAR) {
+ CPed* foundPed = nil;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < SQR(0.2f)) {
+ foundPed = m_nearPeds[i];
+ break;
+ }
+ }
+ if(foundPed && (!foundPed->IsPlayer() || m_nPedType == PEDTYPE_COP || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS))
+ if (animTime > 0.4f && foundPed->IsPedInControl())
+ foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1);
+ }
+ }
+}
+
+// --MIAMI: Done
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
+{
+ CVector vehDoorPos = GetPositionToOpenCarDoor(veh, component, 1.0f);
+
+/*
+ // Unused
+ vehDoorPosWithoutOffset = veh->GetMatrix() * localVehDoorPos;
+*/
+ return vehDoorPos;
+}
+
+// --MIAMI: Done
+void
+CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector *enterOffset = nil;
+ if (veh->IsBike()) {
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+
+ // If bike didn't fall to ground
+ if (Abs(veh->GetRight().z) < 0.1f) {
+ float angleDiff = (GetPosition() - veh->GetPosition()).Heading() - veh->GetForward().Heading();
+
+ if (angleDiff > PI)
+ angleDiff -= TWOPI;
+ else if (angleDiff < -PI)
+ angleDiff += TWOPI;
+
+ if (Abs(angleDiff) < DEGTORAD(30.f)
+ && (IsPlayer() && ((CPlayerPed*)this)->m_fMoveSpeed > 1.5f && !m_vehEnterType ||
+ !IsPlayer() && m_nPedType != PEDTYPE_COP && m_nMoveState == PEDMOVE_RUN
+ && m_pedStats->m_temper > 65
+ && !m_vehEnterType || m_vehEnterType == CAR_WINDSCREEN)) {
+ m_vehEnterType = CAR_WINDSCREEN;
+ posToOpen = GetPositionToOpenCarDoor(veh, CAR_WINDSCREEN);
+ return;
+ }
+ }
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver && !veh->bLowVehicle && !veh->bIsBus) {
+ enterOffset = &vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);
+ CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+
+ // Left front door is closer
+ if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+
+ CPed *rfPassenger = veh->pPassengers[0];
+ if (rfPassenger && !veh->IsBike()
+ && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar ||
+ veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)
+ || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ }
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector rfPos, lrPos, rrPos;
+ bool canEnter = false;
+
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
+
+ switch (veh->GetModelIndex()) {
+ case MI_BUS:
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ return true;
+ case MI_RHINO:
+ default:
+ break;
+ }
+
+ CVector2D rfPosDist(999.0f, 999.0f);
+ CVector2D lrPosDist(999.0f, 999.0f);
+ CVector2D rrPosDist(999.0f, 999.0f);
+
+ if (veh->IsBike()) {
+ if (!veh->pPassengers[0]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
+ lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
+ canEnter = true;
+ lrPosDist = lrPos - GetPosition();
+ }
+ if (!veh->pPassengers[0]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
+ rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
+ canEnter = true;
+ rrPosDist = rrPos - GetPosition();
+ }
+ } else if (!veh->pPassengers[0]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {
+
+ rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ canEnter = true;
+ rfPosDist = rfPos - GetPosition();
+ }
+
+ if (vehModel->m_numDoors == 4) {
+ if (!veh->pPassengers[1]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
+ lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
+ canEnter = true;
+ lrPosDist = lrPos - GetPosition();
+ }
+ if (!veh->pPassengers[2]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
+ rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
+ canEnter = true;
+ rrPosDist = rrPos - GetPosition();
+ }
+
+ // When the door we should enter is blocked by some object.
+ if (!canEnter)
+ veh->ShufflePassengersToMakeSpace();
+ }
+
+ CVector2D nextToCompare = rfPosDist;
+ posToOpen = rfPos;
+ m_vehEnterType = CAR_DOOR_RF;
+ if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_LR;
+ posToOpen = lrPos;
+ nextToCompare = lrPosDist;
+ }
+
+ if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_RR;
+ posToOpen = rrPos;
+ }
+ return canEnter;
+}
+
+// --MIAMI: Done
+void
+CPed::GoToNearestDoor(CVehicle *veh)
+{
+ CVector posToOpen;
+ GetNearestDoor(veh, posToOpen);
+ SetSeek(posToOpen, 0.5f);
+ SetMoveState(PEDMOVE_RUN);
+}
+
+// --MIAMI: Done
+// Unused
+void CPed::PedSetGetInCarPositionCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ CPed* pPed = (CPed*)arg;
+ CMatrix mat(pPed->GetMatrix());
+ CVehicle* pVehicle = pPed->m_pMyVehicle;
+ const CVector& offset = (pVehicle->bIsVan && (pPed->m_vehEnterType == CAR_DOOR_RR || pPed->m_vehEnterType == CAR_DOOR_LR)) ? vecPedVanRearDoorAnimOffset : vecPedCarDoorAnimOffset;
+ CVector position = Multiply3x3(mat, offset) + pPed->GetPosition();
+ CPedPlacement::FindZCoorForPed(&position);
+ pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ pPed->SetPosition(position);
+}
+
+// --MIAMI: Done
+void
+CPed::SetAnimOffsetForEnterOrExitVehicle(void)
+{
+ // FIX_BUGS: If there were no translations on enter anims, there were overflows all over this function.
+
+ int vanBlock = CAnimManager::GetAnimationBlockIndex("van");
+ int bikesBlock = CAnimManager::GetAnimationBlockIndex("bikes");
+ int bikevBlock = CAnimManager::GetAnimationBlockIndex("bikev");
+ int bikehBlock = CAnimManager::GetAnimationBlockIndex("bikeh");
+ int bikedBlock = CAnimManager::GetAnimationBlockIndex("biked");
+ CStreaming::RequestAnim(vanBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::RequestAnim(bikesBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::RequestAnim(bikevBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::RequestAnim(bikehBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::RequestAnim(bikedBlock, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ CAnimManager::AddAnimBlockRef(vanBlock);
+ CAnimManager::AddAnimBlockRef(bikesBlock);
+ CAnimManager::AddAnimBlockRef(bikevBlock);
+ CAnimManager::AddAnimBlockRef(bikehBlock);
+ CAnimManager::AddAnimBlockRef(bikedBlock);
+
+ CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
+ CAnimBlendSequence *seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorLoAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_VAN, ANIM_VAN_GETIN_L)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedVanRearDoorAnimOffset = lastFrame->translation;
+ }
+ }
+ // I think this is leftover and ANIM_TRAIN_GETOUT
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_IDLE_STANCE3)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedTrainDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_STANDARD, ANIM_BIKE_JUMPON_R)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedStdBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedStdBikeJumpRhsAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_VESPA, ANIM_BIKE_JUMPON_R)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedVespaBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedVespaBikeJumpRhsAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_HARLEY, ANIM_BIKE_JUMPON_R)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedHarleyBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedHarleyBikeJumpRhsAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_DIRT, ANIM_BIKE_JUMPON_R)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedDirtBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedDirtBikeJumpRhsAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_HARLEY, ANIM_BIKE_KICK)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedBikeKickAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedBikeKickAnimOffset = lastFrame->translation;
+ }
+ }
+
+ CAnimManager::RemoveAnimBlockRef(vanBlock);
+ CAnimManager::RemoveAnimBlockRef(bikesBlock);
+ CAnimManager::RemoveAnimBlockRef(bikevBlock);
+ CAnimManager::RemoveAnimBlockRef(bikehBlock);
+ CAnimManager::RemoveAnimBlockRef(bikedBlock);
+}
+
+// --MIAMI: Done
+void
+CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ CVector finalPos;
+ CVector draggedOutOffset;
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->bUsesCollision = true;
+ ped->RestartNonPartialAnims();
+ draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ draggedOutOffset.x = -draggedOutOffset.x;
+
+ finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&finalPos);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(finalPos);
+
+ if (veh) {
+ ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;
+ ped->m_fRotationCur = ped->m_fRotationDest;
+ ped->CalculateNewOrientation();
+
+ if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset))
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ ped->SetIdle();
+ if (veh) {
+ if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(veh->GetPosition(), 14000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ ped->bGonnaKillTheCarJacker = false;
+ if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) {
+ if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective);
+
+ } else {
+ CPed *driver = veh->pDriver;
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->SetFlee(veh->GetPosition(), 14000);
+ } else {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+ }
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
+ && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
+ && veh->pDriver && veh->pDriver->IsPlayer()
+ && !CTheScripts::IsPlayerOnAMission()) {
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
+ && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
+ && !veh->pDriver && FindPlayerPed()->m_carInObjective == veh
+ && !CTheScripts::IsPlayerOnAMission()) {
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+
+ } else {
+ ped->SetFindPathAndFlee(veh->GetPosition(), 10000);
+ if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
+ ped->SetMoveState(PEDMOVE_SPRINT);
+ ped->Say(SOUND_PED_FLEE_SPRINT);
+ } else {
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+ if (ped->m_nLastPedState == PED_IDLE)
+ ped->m_nLastPedState = PED_WANDER_PATH;
+}
+
+// --MIAMI: Done
+void
+CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ ped->bUsesCollision = true;
+ ped->RestartNonPartialAnims();
+
+ CMatrix pedMat(ped->GetMatrix());
+ CVector draggedOutOffset;
+ if (ped->m_pMyVehicle && ped->m_pMyVehicle->IsBike()) {
+ AssocGroupId animGroup = ((CBike*)ped->m_pMyVehicle)->m_bikeAnimType;
+ switch (animGroup) {
+ case ASSOCGRP_BIKE_VESPA:
+ draggedOutOffset = vecPedVespaBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_HARLEY:
+ draggedOutOffset = vecPedHarleyBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_DIRT:
+ draggedOutOffset = vecPedDirtBikeJumpRhsAnimOffset;
+ break;
+ default:
+ draggedOutOffset = vecPedStdBikeJumpRhsAnimOffset;
+ break;
+ }
+ } else {
+ draggedOutOffset = vecPedDraggedOutCarAnimOffset;
+ }
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ draggedOutOffset.x = -draggedOutOffset.x;
+
+ CVector posAfterBeingDragged = Multiply3x3(pedMat, draggedOutOffset);
+ posAfterBeingDragged += ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posAfterBeingDragged);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterBeingDragged);
+
+ if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsBike() && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) {
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ if (!ped->m_pMyVehicle) {
+ ped->SetIdle();
+ ped->SetGetUp();
+ return;
+ }
+
+ CPed *driver = ped->m_pMyVehicle->pDriver;
+
+ if (ped->IsPlayer()) {
+ ped->SetIdle();
+
+ } else if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ // Kill objective is already set at this point.
+
+ ped->bGonnaKillTheCarJacker = false;
+ if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) {
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->SetPedState(PED_NONE);
+ ped->m_nLastPedState = PED_NONE;
+ ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
+ } else {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+ }
+ }
+
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
+ && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver
+ && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) {
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR
+ && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver
+ && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission())
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+ else {
+ ped->SetPedState(PED_NONE);
+ ped->m_nLastPedState = PED_NONE;
+ ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000);
+ }
+ ped->SetGetUp();
+}
+
+// --MIAMI: Done
+uint8
+CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)
+{
+ GetNearestTrainPedPosition(train, doorPos);
+/*
+ // Not used.
+ CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex);
+ CMatrix trainMat = CMatrix(train->GetMatrix());
+
+ doorPos = trainModel->m_positions[m_vehEnterType];
+ doorPos.x -= 1.5f;
+ doorPos = Multiply3x3(trainMat, doorPos);
+ doorPos += train->GetPosition();
+*/
+ return 1;
+}
+
+// --MIAMI: Done
+uint8
+CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos)
+{
+ CVector enterStepOffset;
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex());
+ CMatrix trainMat = CMatrix(train->GetMatrix());
+ CVector leftEntryPos, rightEntryPos, midEntryPos;
+ float distLeftEntry, distRightEntry, distMidEntry;
+
+ // enterStepOffset = vecPedCarDoorAnimOffset;
+ enterStepOffset = CVector(1.5f, 0.0f, 0.0f);
+
+ if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) {
+ distLeftEntry = 999.0f;
+ } else {
+ leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset;
+ leftEntryPos = Multiply3x3(trainMat, leftEntryPos);
+ leftEntryPos += train->GetPosition();
+ distLeftEntry = (leftEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (train->pPassengers[TRAIN_POS_MID_ENTRY]) {
+ distMidEntry = 999.0f;
+ } else {
+ midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset;
+ midEntryPos = Multiply3x3(trainMat, midEntryPos);
+ midEntryPos += train->GetPosition();
+ distMidEntry = (midEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) {
+ distRightEntry = 999.0f;
+ } else {
+ rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset;
+ rightEntryPos = Multiply3x3(trainMat, rightEntryPos);
+ rightEntryPos += train->GetPosition();
+ distRightEntry = (rightEntryPos - GetPosition()).Magnitude();
+ }
+
+ if (distMidEntry < distLeftEntry) {
+ if (distMidEntry < distRightEntry) {
+ enterPos = midEntryPos;
+ m_vehEnterType = TRAIN_POS_MID_ENTRY;
+ } else {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ }
+ } else if (distRightEntry < distLeftEntry) {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ } else {
+ enterPos = leftEntryPos;
+ m_vehEnterType = TRAIN_POS_LEFT_ENTRY;
+ }
+
+ return 1;
+}
+
+// --MIAMI: Done :D
+void
+CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+ CTrain *veh = (CTrain*)ped->m_pMyVehicle;
+
+ if (!veh)
+ return;
+
+ ped->bInVehicle = true;
+ ped->SetPedState(PED_DRIVING);
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+ veh->AddPassenger(ped);
+}
+
+#ifdef GTA_TRAIN
+void
+CPed::SetEnterTrain(CVehicle *train, uint32 unused)
+{
+ if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector enterPos;
+ GetNearestTrainPedPosition(train, enterPos);
+ */
+ m_fRotationCur = train->GetForward().Heading() - HALFPI;
+ m_pMyVehicle = train;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+
+ m_nPedState = PED_ENTER_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ ((CPlayerPed*)this)->ClearAdrenaline();
+ }
+}
+
+void
+CPed::EnterTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::SetPedPositionInTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::LineUpPedWithTrain(void)
+{
+ CVector lineUpPos;
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());
+ CVector enterOffset(1.5f, 0.0f, -0.2f);
+
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;
+ m_fRotationDest = m_fRotationCur;
+
+ if (!bInVehicle) {
+ GetNearestTrainDoor(m_pMyVehicle, lineUpPos);
+ lineUpPos.z += 0.2f;
+ } else {
+ if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset;
+ }
+ lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos);
+ lineUpPos += m_pMyVehicle->GetPosition();
+ }
+
+ if (m_pVehicleAnim) {
+ float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ lineUpPos += (GetPosition() - lineUpPos) * percentageLeft;
+ }
+
+ SetPosition(lineUpPos);
+ SetHeading(m_fRotationCur);
+}
+
+void
+CPed::SetExitTrain(CVehicle* train)
+{
+ if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector exitPos;
+ GetNearestTrainPedPosition(train, exitPos);
+ */
+ m_nPedState = PED_EXIT_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+}
+
+void
+CPed::ExitTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->blendDelta = -1000.0f;
+
+ ped->bUsesCollision = true;
+ ped->m_pVehicleAnim = nil;
+ ped->bInVehicle = false;
+ ped->m_nPedState = PED_IDLE;
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->m_fRotationCur = HALFPI + veh->GetForward().Heading();
+ ped->m_fRotationDest = ped->m_fRotationCur;
+ CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);
+ posAfterExit += ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posAfterExit);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterExit);
+ ped->SetHeading(ped->m_fRotationCur);
+ veh->RemovePassenger(ped);
+}
+#endif
+
+// --MIAMI: Done
+void
+CPed::RegisterThreatWithGangPeds(CEntity *attacker)
+{
+ CPed *attackerPed = nil;
+ if ((CharCreatedBy == MISSION_CHAR && bIsPlayerFriend && (attacker == FindPlayerPed() || attacker == FindPlayerVehicle()))
+ || (attacker && m_leader == attacker)
+ || (m_nPedType == PEDTYPE_GANG7 && attacker == FindPlayerPed()))
+ return;
+
+ if (attacker) {
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ if (attacker->IsPed()) {
+ attackerPed = (CPed*)attacker;
+ } else if (attacker->IsVehicle()) {
+ attackerPed = ((CVehicle*)attacker)->pDriver;
+ if (!attackerPed)
+ return;
+ } else
+ return;
+
+ if (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) {
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->IsPointerValid()) {
+ if (nearPed->CharCreatedBy == RANDOM_CHAR && nearPed != this && nearPed->m_nPedType == m_nPedType)
+ nearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType);
+ }
+ }
+ }
+ }
+ }
+
+ if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) {
+ if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOPFUN) {
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), 30.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ if (lastVehicle > 8)
+ lastVehicle = 8;
+
+ for (int j = 0; j < lastVehicle; ++j) {
+ CVehicle *nearVeh = (CVehicle*) vehicles[j];
+
+ if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
+ CPed *nearVehDriver = nearVeh->pDriver;
+
+ if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType && nearVehDriver->CharCreatedBy == RANDOM_CHAR) {
+
+ if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
+ nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ nearVeh->SetStatus(STATUS_PHYSICS);
+ nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// --MIAMI: Done
+// Some helper function which doesn't exist in og game.
+inline void
+SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3)
+{
+ for (int i = 0; i < node->numLinks; i++) {
+
+ CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
+
+ if (testNode && testNode != closeNode && testNode != closeNode2) {
+ CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
+ float dist = posDiff.MagnitudeSqr();
+
+ if (farDist.MagnitudeSqr() > dist) {
+
+ if (closeDist.MagnitudeSqr() > dist) {
+ ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);
+ farDist = posDiff;
+ } else {
+ ped->m_pNextPathNode = closeNode;
+ closeDist = posDiff;
+ }
+ }
+
+ if (--runCount > 0)
+ SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount);
+ }
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
+{
+ if (m_pNextPathNode || !bUsePedNodeSeek)
+ return false;
+
+ const CVector &ourPos = GetPosition();
+
+ int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f);
+
+ CVector seekObjPos = m_vecSeekPos;
+ seekObjPos.z += 1.0f;
+
+ if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false))
+ return false;
+
+ m_pNextPathNode = nil;
+
+ CVector2D seekPosDist (m_vecSeekPos - ourPos);
+
+ CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];
+ CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());
+
+ SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);
+
+ if (m_pNextPathNode) {
+
+ // Function above decided that directly going to next node makes more sense then seeking the object.
+ CVector correctedCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+
+ if ((correctedCoords - ourPos).MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
+ *bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+ return true;
+ }
+ m_pNextPathNode = nil;
+ }
+
+ return false;
+}
+
+// --MIAMI: Done
+bool
+CPed::DuckAndCover(void)
+{
+ if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer)
+ return false;
+
+ if (bKindaStayInSamePlace){
+
+ if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) {
+ if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ }
+ if (!bIsAimingGun)
+ SetAimFlag(m_pedInObjective);
+
+ } else {
+ bKindaStayInSamePlace = false;
+ if (bIsDucking)
+ ClearDuck(true);
+
+ bCrouchWhenShooting = false;
+ bDuckAndCover = false;
+ m_headingRate = 10.0f;
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000);
+ if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
+ ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--;
+ }
+ return false;
+ }
+
+ int16 lastVehicle = 0;
+ CEntity* vehicles[8];
+
+ bool justDucked = false;
+ CVehicle *foundVeh = nil;
+ float maxDist = 225.0f;
+ if (bIsDucking)
+ ClearDuck(true);
+
+ bCrouchWhenShooting = false;
+ bool duckingWithoutVeh = false;
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+
+ for(int i = 0; i < 6; i++) {
+ CPlayerPed *player = (CPlayerPed*)m_pedInObjective;
+
+ if (player->m_pPedAtSafePos[i] == this) {
+ duckingWithoutVeh = true;
+ CVector &safePos = player->m_vecSafePos[i];
+ bool notRunningToSafePos = false;
+
+ if (m_vecSeekPos.x != safePos.x && m_vecSeekPos.y != safePos.y && m_vecSeekPos.z != safePos.z)
+ notRunningToSafePos = true;
+
+ if (!notRunningToSafePos) {
+ CVector target = player->m_vecSafePos[i];
+ SetSeek(target, 1.0f);
+ duckingWithoutVeh = true;
+ m_attackTimer = CTimer::GetTimeInMilliseconds() + 6000;
+ bDuckAndCover = true;
+ }
+ break;
+ }
+ }
+ if (!duckingWithoutVeh) {
+ for (int i = 0; i < 6; i++) {
+ CPlayerPed* player = (CPlayerPed*)m_pedInObjective;
+ if (!player->m_pPedAtSafePos[i] && player->m_vecSafePos[i].x != 0.0f) {
+ player->m_pPedAtSafePos[i] = this;
+ CVector target = player->m_vecSafePos[i];
+ SetSeek(target, 1.0f);
+ m_headingRate = 15.0f;
+ ClearPointGunAt();
+ duckingWithoutVeh = 1;
+ bIsRunning = true;
+ bDuckAndCover = true;
+ justDucked = true;
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;
+ break;
+ }
+ }
+ }
+ if (!duckingWithoutVeh) {
+ CVector pos = GetPosition();
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ }
+
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle *veh = (CVehicle*) vehicles[i];
+ if (veh->IsCar() && veh->m_vecMoveSpeed.Magnitude() <= 0.02f
+ && !veh->bIsBus && !veh->bIsVan && !veh->bIsBig
+ && veh->m_numPedsUseItAsCover < 3) {
+
+ float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr();
+ if (dist < maxDist) {
+ maxDist = dist;
+ foundVeh = veh;
+ }
+ }
+ }
+ if (foundVeh) {
+ // Unused.
+ // CVector lfWheelPos, rfWheelPos;
+ // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos);
+ // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos);
+ CVector rightSide, leftSide;
+
+ // 3 persons can use the car as cover. Found the correct position for us.
+ if (foundVeh->m_numPedsUseItAsCover == 2) {
+ rightSide = CVector(1.5f, -0.5f, 0.0f);
+ leftSide = CVector(-1.5f, -0.5f, 0.0f);
+ } else if (foundVeh->m_numPedsUseItAsCover == 1) {
+ rightSide = CVector(1.5f, 0.5f, 0.0f);
+ leftSide = CVector(-1.5f, 0.5f, 0.0f);
+ } else if (foundVeh->m_numPedsUseItAsCover == 0) {
+ rightSide = CVector(1.5f, 0.0f, 0.0f);
+ leftSide = CVector(-1.5f, 0.0f, 0.0f);
+ }
+
+ CMatrix vehMatrix(foundVeh->GetMatrix());
+ CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition();
+
+ CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition();
+
+ CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide;
+ CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide;
+
+ CVector duckPos;
+ if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr())
+ duckPos = duckAtLeftSide;
+ else
+ duckPos = duckAtRightSide;
+
+ if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false)) {
+ SetSeek(duckPos, 1.0f);
+ m_headingRate = 15.0f;
+ bIsRunning = true;
+ bDuckAndCover = true;
+ justDucked = true;
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;
+ if (foundVeh->bIsLawEnforcer) {
+ m_carInObjective = foundVeh;
+ m_carInObjective->RegisterReference((CEntity**)&m_carInObjective);
+ }
+ m_pSeekTarget = foundVeh;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ ClearPointGunAt();
+ } else {
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);
+ bDuckAndCover = false;
+ }
+ } else if (!duckingWithoutVeh) {
+ bDuckAndCover = false;
+ }
+ }
+
+ if (!justDucked && !bDuckAndCover)
+ return false;
+
+ if (!Seek()) {
+ if (m_nMoveState == PEDMOVE_STILL) {
+ bDuckAndCover = false;
+ return false;
+ } else
+ return true;
+ }
+
+ bKindaStayInSamePlace = true;
+ bDuckAndCover = false;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ if (m_pSeekTarget && m_pSeekTarget->IsVehicle())
+ ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++;
+
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ }
+
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000);
+ bCrouchWhenShooting = true;
+ SetDuck(CGeneral::GetRandomNumberInRange(2000, 5000), true);
+ return false;
+}
+
+// --MIAMI: Done
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
+{
+ CVector doorPos;
+ CMatrix vehMat(veh->GetMatrix());
+
+ if (veh->IsBike()) {
+ CVehicleModelInfo* vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->GetModelIndex());
+ CVector vehDoorOffset;
+ CBike* bike = (CBike*)veh;
+ doorPos = vehModel->GetFrontSeatPosn();
+
+ if (component == CAR_WINDSCREEN) {
+ return bike->GetMatrix() * (doorPos + vecPedBikeKickAnimOffset);
+ } else {
+ switch (bike->m_bikeAnimType) {
+ case ASSOCGRP_BIKE_VESPA:
+ vehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_HARLEY:
+ vehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_DIRT:
+ vehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;
+ break;
+ default:
+ vehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;
+ break;
+ }
+ vehDoorOffset.x += offset * bike->pHandling->fSeatOffsetDistance;
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {
+ doorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ }
+
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_LF)
+ vehDoorOffset.x *= -1.f;
+
+ CVector correctedPos;
+ bike->GetCorrectedWorldDoorPosition(correctedPos, vehDoorOffset, doorPos);
+ return correctedPos;
+ }
+ }
+ doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
+
+ return veh->GetPosition() + doorPos;
+}
+
+// --MIAMI: Done
+CVector
+CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)
+{
+ CVehicleModelInfo *vehModel;
+ CVector vehDoorPos;
+ CVector vehDoorOffset;
+ float seatOffset;
+
+ vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
+
+ if (veh->IsBike()) {
+ CBike *bike = (CBike*)veh;
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+
+ if (component == CAR_WINDSCREEN) {
+ return bike->GetMatrix() * (vehDoorPos + vecPedBikeKickAnimOffset);
+ } else {
+ switch (bike->m_bikeAnimType) {
+ case ASSOCGRP_BIKE_VESPA:
+ vehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_HARLEY:
+ vehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_DIRT:
+ vehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;
+ break;
+ default:
+ vehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;
+ break;
+ }
+ float xOffsetFromAnim = vehDoorOffset.x + seatPosMult * bike->pHandling->fSeatOffsetDistance;
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ }
+
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_LF)
+ xOffsetFromAnim *= -1.f;
+
+ return bike->GetMatrix() * (vehDoorPos + CVector(xOffsetFromAnim, vehDoorOffset.y, vehDoorOffset.z));
+ }
+ } else {
+ if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
+ seatOffset = 0.0f;
+ vehDoorOffset = vecPedVanRearDoorAnimOffset;
+ } else {
+ seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult;
+ if (veh->bLowVehicle) {
+ vehDoorOffset = vecPedCarDoorLoAnimOffset;
+ } else {
+ vehDoorOffset = vecPedCarDoorAnimOffset;
+ }
+ }
+
+ switch (component) {
+ case CAR_DOOR_RF:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorPos.x += seatOffset;
+ vehDoorOffset.x = -vehDoorOffset.x;
+ break;
+
+ case CAR_DOOR_RR:
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ vehDoorPos.x += seatOffset;
+ vehDoorOffset.x = -vehDoorOffset.x;
+ break;
+
+ case CAR_DOOR_LF:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorPos.x = -(vehDoorPos.x + seatOffset);
+ break;
+
+ case CAR_DOOR_LR:
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ vehDoorPos.x = -(vehDoorPos.x + seatOffset);
+ break;
+
+ default:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorOffset = CVector(0.0f, 0.0f, 0.0f);
+ }
+ return vehDoorPos - vehDoorOffset;
+ }
+}
+
+// --MIAMI: Done, but what is this parameter for?
+void
+CPed::SetDuck(uint32 time, bool sth)
+{
+ if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer && !sth) {
+ if (sth && CTimer::GetTimeInMilliseconds() + time > m_duckTimer)
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ return;
+ }
+
+ CAnimBlendAssociation *duckAssoc;
+ if (bCrouchWhenShooting) {
+ duckAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 4.0f);
+ duckAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ } else {
+ CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::Duck(void)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
+ ClearDuck();
+ else if (bIsDucking && bCrouchWhenShooting) {
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+ if (!attackAssoc) {
+ if(!!weapon->m_bCrouchFire)
+ attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));
+ }
+ if (!attackAssoc) {
+ if(!!weapon->m_bReload)
+ attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(weapon));
+ }
+ if (!attackAssoc) {
+ bIsDucking = false;
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::ClearDuck(bool clearTimer)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+ }
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+ }
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -4.0f;
+ }
+ bIsDucking = false;
+
+ if (clearTimer) {
+ m_duckTimer = 0;
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::InformMyGangOfAttack(CEntity *attacker)
+{
+ CPed *attackerPed;
+
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)
+ return;
+
+ if (attacker->IsPed()) {
+ attackerPed = (CPed*)attacker;
+ } else {
+ if (!attacker->IsVehicle())
+ return;
+
+ attackerPed = ((CVehicle*)attacker)->pDriver;
+ if (!attackerPed)
+ return;
+ }
+
+ if (attackerPed->m_nPedType == PEDTYPE_COP)
+ return;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed && nearPed != this) {
+ CPed *leader = nearPed->m_leader;
+ if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) {
+ nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed);
+ nearPed->SetObjectiveTimer(30000);
+ }
+ }
+ }
+}
+
+// --MIAMI: Done
+void
+CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle);
+
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (veh->bLowVehicle) {
+ veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f);
+ } else {
+ veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f);
+ }
+
+ veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;
+
+ if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);
+}
+
+// --MIAMI: Done
+void
+CPed::SetSeekBoatPosition(CVehicle *boat)
+{
+ if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver || !IsPedInControl())
+ return;
+
+ SetStoredState();
+ m_carInObjective = boat;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_pMyVehicle = boat;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_distanceToCountSeekDone = 0.5f;
+ SetPedState(PED_SEEK_IN_BOAT);
+}
+
+// --MIAMI: Done
+void
+CPed::SeekBoatPosition(void)
+{
+ if (m_carInObjective && !m_carInObjective->pDriver) {
+ CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();
+
+ CVector enterOffset;
+ enterOffset = boatModel->GetFrontSeatPosn();
+ enterOffset.x = 0.0f;
+ CMatrix boatMat(m_carInObjective->GetMatrix());
+ SetMoveState(PEDMOVE_WALK);
+ m_vecSeekPos = boatMat * enterOffset;
+ if (Seek()) {
+ // We arrived to the boat
+ m_vehEnterType = 0;
+ SetEnterCar(m_carInObjective, 0);
+ }
+ } else
+ RestorePreviousState();
+}
+
+// --MIAMI: Done
+bool
+CPed::IsRoomToBeCarJacked(void)
+{
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector offset;
+ if (m_pMyVehicle->IsBike()) {
+ offset = vecPedStdBikeJumpRhsAnimOffset;
+ } else if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {
+ offset = vecPedDraggedOutCarAnimOffset;
+ } else {
+ offset = vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ offset.z = 0.0f;
+ if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) {
+ return true;
+ }
+
+ return false;
+}
+
+// --MIAMI: Done
+void
+CPed::AddInCarAnims(CVehicle* car, bool isDriver)
+{
+ if (car->IsBoat()) {
+ if (car->pHandling->Flags & HANDLING_SIT_IN_BOAT) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ } else {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ }
+ } else if (car->IsBike()) {
+ if (isDriver) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ((CBike*)car)->m_bikeAnimType, ANIM_BIKE_RIDE, 100.0f);
+ } else {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ((CBike*)car)->m_bikeAnimType, ANIM_BIKE_PASSENGER, 100.0f);
+ }
+ } else {
+ if (isDriver) {
+ if (car->bLowVehicle) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
+ } else {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ }
+ } else {
+ if (car->bLowVehicle) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f);
+ } else {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f);
+ }
+ }
+ }
+
+ StopNonPartialAnims();
+}
+
+// --MIAMI: Done
+void
+CPed::RemoveDrivebyAnims()
+{
+ CAnimBlendAssociation *animAssoc;
+
+ AnimationId LeftAnim = ANIM_DRIVEBY_L;
+ AnimationId RightAnim = ANIM_DRIVEBY_R;
+
+ if (m_pMyVehicle->pHandling->Flags & HANDLING_IS_BIKE) {
+ LeftAnim = ANIM_BIKE_DRIVEBY_LHS;
+ RightAnim = ANIM_BIKE_DRIVEBY_RHS;
+ } else if (m_pMyVehicle->bLowVehicle) {
+ LeftAnim = ANIM_DRIVEBY_LOW_L;
+ RightAnim = ANIM_DRIVEBY_LOW_R;
+ }
+
+ animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_LHS);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_RHS);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_FT);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+}
+
+// --MIAMI: Done
+void
+CPed::RemoveInCarAnims(void)
+{
+ CAnimBlendAssociation* assoc;
+
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_DRIVING); assoc;
+ assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_DRIVING)) {
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ assoc->blendDelta = -1000.0f;
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::PositionPedOutOfCollision(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (!veh)
+ return false;
+
+ if (bDonePositionOutOfCollision)
+ return true;
+
+ bool foundAPos = false;
+ CColModel *vehCol = veh->GetColModel();
+ CVector vehPos = veh->GetPosition();
+ CVector ourPos = GetPosition();
+ CVector newPos = ourPos;
+ CWorld::pIgnoreEntity = veh;
+ bUsesCollision = false;
+ bJustCheckCollision = true;
+ m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);
+ if (veh->IsOnItsSide()) {
+ // Top of the veh.
+ newPos = vehPos;
+ newPos.z = FEET_OFFSET + vehCol->boundingBox.max.x + vehPos.z;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+
+ } else if (m_vehEnterType != 0) {
+ // Try the normal way
+ CVector pos = GetPositionToOpenCarDoor(m_pMyVehicle, m_vehEnterType);
+ newPos = pos;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+
+ float vehRelativeExitX = vehCol->boundingBox.min.x - 0.355f;
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
+ vehRelativeExitX = 0.355f + vehCol->boundingBox.max.x;
+
+ if (!foundAPos) {
+ // Check sides of veh., respective to seat column-veh. center difference(why?)
+ float exitOffset = vehRelativeExitX - DotProduct(ourPos - vehPos, veh->GetRight());
+ newPos = exitOffset * veh->GetRight() + ourPos;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ if (!foundAPos) {
+ // Iterate through sections of veh. length + static offset on X
+ float minY = vehCol->boundingBox.min.y;
+ float ySection = (vehCol->boundingBox.max.y - minY) / 3.f;
+ for (int i = 0; i < 4; i++) {
+ float fwdMult = i * ySection + minY;
+ newPos = vehRelativeExitX * veh->GetRight() + fwdMult * veh->GetForward() + vehPos;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) {
+ foundAPos = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!foundAPos) {
+ // Back of veh.
+ newPos = (vehCol->boundingBox.min.y - 0.355f) * veh->GetForward() + vehPos;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ if (!foundAPos) {
+ // Front of veh.
+ newPos = (0.355f + vehCol->boundingBox.max.y) * veh->GetForward() + vehPos;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ if (!foundAPos) {
+ // Opposite X side + back
+ newPos = vehCol->boundingBox.min.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight();
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ if (!foundAPos) {
+ // Opposite X side + front
+ newPos = vehCol->boundingBox.max.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight();
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ if (!foundAPos) {
+ // Top of veh.
+ if (veh->m_vehType == 0) {
+ newPos = vehCol->boundingBox.max.z * veh->GetUp() + vehPos;
+ newPos.z += FEET_OFFSET;
+ GetMatrix().SetTranslate(newPos);
+ if (!CheckCollision()) {
+ if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))
+ foundAPos = true;
+ }
+ }
+ }
+ m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);
+ m_vecTurnSpeed = CVector(0.f, 0.f, 0.f);
+ veh->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);
+ veh->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f);
+ CWorld::pIgnoreEntity = nil;
+ bUsesCollision = true;
+ bJustCheckCollision = false;
+ bDonePositionOutOfCollision = true;
+ if (foundAPos)
+ return true;
+ int foundNode = ThePaths.FindNodeClosestToCoors(vehPos, PATH_PED, 999999.9f, true, false, false, false);
+ if (foundNode < 0)
+ return false;
+ newPos = ThePaths.m_pathNodes[foundNode].GetPosition();
+ CPedPlacement::FindZCoorForPed(&newPos);
+ GetMatrix().SetTranslate(newPos);
+ SetHeading(m_pMyVehicle->GetForward().Heading());
+ return true;
+}
+
+// --MIAMI: Done
+// "Any" means he shouldn't have to be in vehicle.
+bool
+CPed::PositionAnyPedOutOfCollision(void)
+{
+ CVehicle *veh;
+ CVector posNearVeh;
+ CVector posSomewhereClose;
+ bool putNearVeh = false;
+ bool putSomewhereClose = false;
+ int smallestDistNearVeh = 999;
+ int smallestDistSomewhereClose = 999;
+
+ CVector vehPos = m_pMyVehicle->GetPosition();
+ CVector potentialPos;
+ potentialPos.y = GetPosition().y - 3.5f;
+ potentialPos.z = GetPosition().z;
+
+ for (int yTry = 0; yTry < 15; yTry++) {
+ potentialPos.x = GetPosition().x - 3.5f;
+
+ for (int xTry = 0; xTry < 15; xTry++) {
+ CPedPlacement::FindZCoorForPed(&potentialPos);
+ if (!CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) {
+ float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr();
+ veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false);
+ if (veh) {
+ if (potentialChangeSqr < smallestDistNearVeh) {
+ posNearVeh = potentialPos;
+ putNearVeh = true;
+ smallestDistNearVeh = potentialChangeSqr;
+ }
+ } else if (potentialChangeSqr < smallestDistSomewhereClose) {
+ smallestDistSomewhereClose = potentialChangeSqr;
+ posSomewhereClose = potentialPos;
+ putSomewhereClose = true;
+ }
+ }
+ potentialPos.x += 0.5f;
+ }
+ potentialPos.y += 0.5f;
+ }
+
+ if (!putSomewhereClose && !putNearVeh)
+ return false;
+
+ // We refrain from using posNearVeh, probably because of it may be top of the vehicle.
+ if (putSomewhereClose) {
+ SetPosition(posSomewhereClose);
+ } else {
+ CVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max;
+ posNearVeh.z += vehSize.z;
+ SetPosition(posNearVeh);
+ }
+ return true;
+}
+
+// --MIAMI: Done
+bool
+CPed::WarpPedToNearLeaderOffScreen(void)
+{
+ bool teleported = false;
+ if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
+ return false;
+
+ CVector warpToPos = m_leader->GetPosition();
+ CVector distVec = warpToPos - GetPosition();
+ float halfOfDist = distVec.Magnitude() * 0.5f;
+ CVector halfNormalizedDist = distVec / halfOfDist;
+
+ CVector appropriatePos = GetPosition();
+ int tryCount = Min(10, (int)halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CVector zCorrectedPos = appropriatePos;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) < 3.0f || Abs(zCorrectedPos.z - appropriatePos.z) < 3.0f) {
+ appropriatePos.z = zCorrectedPos.z;
+ if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f)
+ && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
+ && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
+ teleported = true;
+ Teleport(appropriatePos);
+ }
+ }
+ }
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ return teleported;
+}
+
+// --MIAMI: Done
+bool
+CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)
+{
+ bool teleported = false;
+ if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
+ return false;
+
+ CVector warpToPos = warpTo->GetPosition();
+ CVector distVec = warpToPos - GetPosition();
+ float halfOfDist = distVec.Magnitude() * 0.5f;
+ CVector halfNormalizedDist = distVec / halfOfDist;
+
+ CVector appropriatePos = GetPosition();
+ int tryCount = Min(10, (int)halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CVector zCorrectedPos = appropriatePos;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) < 3.0f || Abs(zCorrectedPos.z - appropriatePos.z) < 3.0f) {
+ appropriatePos.z = zCorrectedPos.z;
+ if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
+ && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
+ && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
+ teleported = true;
+ Teleport(appropriatePos);
+ }
+ }
+ }
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ return teleported;
+}
+
+// --MIAMI: Done
+int32
+CPed::KillCharOnFootArmed(CVector &ourPos, CVector &targetPos, CVector &distWithTarget)
+{
+ bool killPlayerInNoPoliceZone = false;
+ if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())
+ killPlayerInNoPoliceZone = true;
+
+ if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {
+ if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee())
+ bNotAllowedToDuck = true;
+ } else {
+ if (!m_pedInObjective->bInVehicle) {
+ if (m_pedInObjective->GetWeapon()->IsTypeMelee()) {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ } else if (DuckAndCover()) {
+ return CANT_ATTACK;
+ }
+ } else {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ }
+ }
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
+ SetMoveState(PEDMOVE_STILL);
+ return CANT_ATTACK;
+ }
+ if (m_pedInObjective->IsPlayer()) {
+ CPlayerPed *player = FindPlayerPed();
+ if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops
+ || player->m_pWanted->m_bIgnoredByEveryone
+ || m_pedInObjective->bIsInWater
+ || m_pedInObjective->m_nPedState == PED_ARRESTED) {
+
+ if (m_nPedState != PED_ARREST_PLAYER)
+ SetIdle();
+
+ return CANT_ATTACK;
+ }
+ }
+ if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP
+ && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+
+ return CANT_ATTACK;
+ }
+ if (m_pedInObjective->m_fHealth <= 0.0f) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ return CANT_ATTACK;
+ }
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float wepRange = wepInfo->m_fRange;
+ float wepRangeAdjusted = wepRange / 3.f;
+
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;
+ if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED
+ || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {
+ SetIdle();
+ return WATCH_UNTIL_HE_DISAPPEARS;
+ }
+ SetLookFlag(vehOfTarget, false);
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl())
+ TurnBody();
+
+ if (m_nPedState != PED_CARJACK) {
+ if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {
+
+ SetAttack(vehOfTarget);
+ if (m_pPointGunAt)
+ m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
+
+ m_pPointGunAt = vehOfTarget;
+ if (vehOfTarget)
+ vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+
+ CVector2D dirVehGoing = vehOfTarget->m_vecMoveSpeed;
+ if (dirVehGoing.Magnitude() > 0.2f) {
+ CVector2D vehDist = GetPosition() - vehOfTarget->GetPosition();
+ vehDist.Normalise();
+ dirVehGoing.Normalise();
+ if (DotProduct2D(vehDist, dirVehGoing) > 0.8f) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
+ SetMoveState(PEDMOVE_STILL);
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+ if (distWithTargetSc <= m_distanceToCountSeekDone) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
+ SetMoveState(PEDMOVE_STILL);
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ }
+ return ATTACK_IN_PROGRESS;
+ } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
+ if (vehOfTarget) {
+ if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
+ GoToNearestDoor(vehOfTarget);
+ } else {
+ m_vehEnterType = 0;
+ if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
+ m_vehEnterType = CAR_DOOR_LF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
+ m_vehEnterType = CAR_DOOR_RF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
+ m_vehEnterType = CAR_DOOR_LR;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
+ m_vehEnterType = CAR_DOOR_RR;
+ }
+ // Unused
+ // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
+ SetSeekCar(vehOfTarget, m_vehEnterType);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ }
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
+ SetLookFlag(m_pedInObjective, false);
+ TurnBody();
+ }
+ if (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) {
+ float maxArrestDist = 1.5f;
+ if (((CCopPed*)this)->m_bDragsPlayerFromCar) {
+ if (m_nPedState == PED_FALL) {
+ maxArrestDist = 3.5f;
+ } else if (m_nPedState != PED_DRAG_FROM_CAR) {
+ ((CCopPed*)this)->m_bDragsPlayerFromCar = 0;
+ }
+ }
+
+ if (distWithTargetSc < maxArrestDist) {
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
+
+ ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
+ return WATCH_UNTIL_HE_DISAPPEARS;
+ }
+ }
+ }
+ /*
+ if (distWithTargetSc > 0.1f) {
+ junk code
+ } */
+
+ if (m_shotTime != 0 && m_ceaseAttackTimer != 0) {
+ if (CTimer::GetTimeInMilliseconds() > m_ceaseAttackTimer + m_shotTime) {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ m_shotTime = 0;
+ return CANT_ATTACK;
+ }
+ }
+
+ if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !bDuckAndCover && !killPlayerInNoPoliceZone) {
+ if (distWithTargetSc > wepRange
+ || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_ARRESTED
+ || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f) {
+
+ if (m_pedInObjective->EnteringCar())
+ wepRangeAdjusted = 2.0f;
+
+ if (bUsePedNodeSeek) {
+ CVector bestCoords(0.0f, 0.0f, 0.0f);
+ m_vecSeekPos = m_pedInObjective->GetPosition();
+
+ if (!m_pNextPathNode)
+ FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+
+ if (m_pNextPathNode)
+ m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ } else {
+ SetSeek(m_pedInObjective, wepRangeAdjusted);
+ }
+ if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {
+ bStopAndShoot = true;
+ b158_8 = true;
+ SetMoveState(PEDMOVE_STILL);
+ } else if (b158_8) {
+ bStopAndShoot = false;
+ b158_8 = false;
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+ }
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds()
+ && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+
+ if (bIsDucking && !bCrouchWhenShooting) {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim)
+ duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+ if (!duckAnim)
+ duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+
+ if (duckAnim) {
+ duckAnim->flags |= ASSOC_DELETEFADEDOUT;
+ duckAnim->blendDelta = -4.0f;
+ }
+ bIsDucking = false;
+ return CANT_ATTACK;
+ }
+ bObstacleShowedUpDuringKillObjective = false;
+ SetAttack(m_pedInObjective);
+ if (m_pPointGunAt)
+ m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);
+
+ m_pPointGunAt = m_pedInObjective;
+ if (m_pedInObjective)
+ m_pedInObjective->RegisterReference((CEntity**)&m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(600.0f, 1500.0f));
+
+ int time;
+ if (distWithTargetSc <= wepRangeAdjusted)
+ time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);
+ else
+ time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
+
+ SetAttackTimer(time);
+ } else {
+ if (!m_pedInObjective->m_pCurrentPhysSurface && b158_8) {
+ b158_8 = false;
+ bStopAndShoot = false;
+ }
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
+ if (bNotAllowedToDuck && bKindaStayInSamePlace && !bIsDucking && bCrouchWhenShooting) {
+ SetDuck(CGeneral::GetRandomNumberInRange(1000, 5000), false);
+ return CANT_ATTACK;
+ }
+ if (bObstacleShowedUpDuringKillObjective) {
+ if (m_nPedType == PEDTYPE_COP) {
+ if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45
+ || m_fleeFrom && m_fleeFrom->IsObject()) {
+ wepRangeAdjusted = 6.0f;
+ } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) {
+ wepRangeAdjusted = 4.0f;
+ } else {
+ wepRangeAdjusted = 2.0f;
+ }
+ } else {
+ wepRangeAdjusted = 2.0f;
+ }
+ }
+ if (distWithTargetSc <= wepRangeAdjusted) {
+ SetMoveState(PEDMOVE_STILL);
+ bIsPointingGunAt = true;
+ if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) {
+ m_attackTimer = CTimer::GetTimeInMilliseconds();
+ SetIdle();
+ }
+ } else {
+ if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS
+ && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {
+ Say(SOUND_PED_ATTACK);
+ SetSeek(m_pedInObjective, wepRangeAdjusted);
+ bIsRunning = true;
+ if (m_nPedType == PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops > 1) {
+ if (CGeneral::GetRandomNumber() & 1)
+ Say(SOUND_PED_GUNAIMEDAT3);
+ else
+ Say(SOUND_PED_GUNAIMEDAT2);
+ }
+ }
+ }
+ }
+ }
+
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);
+
+ return ATTACK_IN_PROGRESS;
+}
+
+// --MIAMI: Done
+int32
+CPed::KillCharOnFootMelee(CVector &ourPos, CVector &targetPos, CVector &distWithTarget)
+{
+ bool killPlayerInNoPoliceZone = false;
+ float distWithTargetSc = distWithTarget.Magnitude();
+ CPlayerPed *victimPlayer = nil;
+ if (m_pedInObjective->IsPlayer())
+ victimPlayer = (CPlayerPed*)m_pedInObjective;
+
+ if (victimPlayer) {
+ if (CCullZones::NoPolice()
+ || m_pedInObjective->m_pCurrentPhysSurface
+ && m_pedInObjective->m_pCurrentPhysSurface != m_pCurrentPhysSurface
+ && distWithTargetSc < 5.f) {
+
+ if (victimPlayer && victimPlayer->m_bSpeedTimerFlag && (IsGangMember() || m_nPedType == PEDTYPE_COP)
+ && CharCreatedBy != MISSION_CHAR) {
+ GiveWeapon(WEAPONTYPE_COLT45, 1000, 1);
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ SetMoveState(PEDMOVE_STILL);
+ bStopAndShoot = true;
+ b158_8 = true;
+ return CANT_ATTACK;
+ }
+ killPlayerInNoPoliceZone = true;
+ }
+ }
+ bNotAllowedToDuck = false;
+ bStopAndShoot = false;
+ b158_8 = false;
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
+ SetMoveState(PEDMOVE_STILL);
+ return CANT_ATTACK;
+ }
+ if (victimPlayer) {
+ CPlayerPed *player = FindPlayerPed();
+ if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops
+ || player->m_pWanted->m_bIgnoredByEveryone
+ || m_pedInObjective->bIsInWater
+ || m_pedInObjective->m_nPedState == PED_ARRESTED) {
+
+ if (m_nPedState != PED_ARREST_PLAYER)
+ SetIdle();
+
+ return CANT_ATTACK;
+ }
+ }
+ if (victimPlayer && m_nPedType != PEDTYPE_COP && CharCreatedBy != MISSION_CHAR
+ && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+
+ return CANT_ATTACK;
+ }
+ if (m_pedInObjective->m_fHealth <= 0.0f) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ return ATTACK_IN_PROGRESS;
+ }
+ bool canReachVictim = false;
+ uint32 endOfAttack = 0;
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+
+ // Already calculated at the start
+ // float distWithTargetSc = distWithTarget.Magnitude();
+ float wepRange = 0.3f;
+ float wepRangeAdjusted = wepInfo->m_fRange / 2.f;
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
+ wepRangeAdjusted -= 0.3f;
+
+ if (distWithTargetSc <= 5.f && victimPlayer && !victimPlayer->m_bDrunkVisualsWearOff) {
+
+ if (m_pedInObjective->EnteringCar() && wepRangeAdjusted > 2.f) {
+ m_vecSeekPos = m_pedInObjective->GetPosition();
+ wepRangeAdjusted = 1.0f;
+ wepRange = 0.5f;
+ } else {
+ int8 attackDir = victimPlayer->FindMeleeAttackPoint(this, distWithTarget, endOfAttack);
+ if (attackDir == -1) {
+ m_vecSeekPos = victimPlayer->GetPosition();
+ wepRange = 4.0f;
+ } else {
+ victimPlayer->GetMeleeAttackCoords(m_vecSeekPos, attackDir, wepRangeAdjusted);
+ distWithTargetSc = (m_vecSeekPos - GetPosition()).Magnitude();
+ canReachVictim = true;
+ }
+ }
+ } else {
+ m_vecSeekPos = m_pedInObjective->GetPosition();
+ wepRange = Max(0.8f, 0.9f * wepRangeAdjusted);
+ wepRangeAdjusted = 1.1f * wepRangeAdjusted;
+ if (victimPlayer && victimPlayer->m_bDrunkVisualsWearOff)
+ victimPlayer = nil;
+ }
+
+ if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+ CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;
+
+ if (vehOfTarget){
+ if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED
+ || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {
+ SetIdle();
+ return WATCH_UNTIL_HE_DISAPPEARS;
+ }
+ SetLookFlag(vehOfTarget, false);
+
+ if (m_nPedState != PED_CARJACK) {
+ if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
+ if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
+
+ if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
+ GoToNearestDoor(vehOfTarget);
+ } else {
+ m_vehEnterType = 0;
+ if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
+ m_vehEnterType = CAR_DOOR_LF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
+ m_vehEnterType = CAR_DOOR_RF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
+ m_vehEnterType = CAR_DOOR_LR;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
+ m_vehEnterType = CAR_DOOR_RR;
+ }
+ // Unused
+ // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
+ SetSeekCar(vehOfTarget, m_vehEnterType);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ }
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
+ SetLookFlag(m_pedInObjective, false);
+ if(m_nPedState == PED_IDLE || m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT)
+ TurnBody();
+ }
+ if (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) {
+ float maxArrestDist = 1.5f;
+ if (((CCopPed*)this)->m_bDragsPlayerFromCar) {
+ if (m_nPedState == PED_FALL) {
+ maxArrestDist = 3.5f;
+ } else if (m_nPedState != PED_DRAG_FROM_CAR) {
+ ((CCopPed*)this)->m_bDragsPlayerFromCar = 0;
+ }
+ }
+
+ if (distWithTargetSc < maxArrestDist) {
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
+
+ ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
+ return WATCH_UNTIL_HE_DISAPPEARS;
+ }
+ }
+ }
+
+ if (distWithTargetSc > wepRange && !bKindaStayInSamePlace && m_nPedState != PED_ATTACK &&
+ (m_nPedState != PED_FIGHT || m_curFightMove == FIGHTMOVE_IDLE) && !killPlayerInNoPoliceZone) {
+
+ bool goForward = false;
+
+ if (m_nPedState == PED_FIGHT) {
+ if (canReachVictim) {
+ CVector attackAndVictimDist = m_vecSeekPos - m_pedInObjective->GetPosition();
+ CVector victimFarness = attackAndVictimDist / wepRangeAdjusted;
+ CVector distVec = GetPosition() - m_pedInObjective->GetPosition();
+ float distSqr = distVec.MagnitudeSqr();
+ if (sq(wepRangeAdjusted) > distSqr && distSqr > 0.05f) {
+ distVec.Normalise();
+ if (DotProduct2D(victimFarness, distVec) > Cos(DEGTORAD(30.f)))
+ goForward = true;
+ }
+ }
+ }
+ if (goForward) {
+ m_curFightMove = FIGHTMOVE_SHUFFLE_F;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_SH_BACK, 16.f)->SetFinishCallback(FinishFightMoveCB,this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_fightButtonPressure = 0;
+ m_takeAStepAfterAttack = false;
+
+ } else if (bUsePedNodeSeek && !canReachVictim) {
+ CVector bestCoords(0.0f, 0.0f, 0.0f);
+
+ if (!m_pNextPathNode)
+ FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+
+ if (m_pNextPathNode)
+ m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ } else {
+ if (canReachVictim)
+ SetSeek(m_vecSeekPos, wepRange);
+ else
+ SetSeek(m_pedInObjective, wepRange);
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds()
+ && distWithTargetSc < wepRangeAdjusted && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {
+
+ if (bIsDucking) {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim)
+ duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+ if (!duckAnim)
+ duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH);
+
+ if (duckAnim) {
+ duckAnim->flags |= ASSOC_DELETEFADEDOUT;
+ duckAnim->blendDelta = -4.0f;
+ }
+ bIsDucking = false;
+ return CANT_ATTACK;
+ }
+
+ if (canReachVictim || !victimPlayer) {
+ SetMoveState(PEDMOVE_STILL);
+ SetAttack(m_pedInObjective);
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ SetShootTimer(CGeneral::GetRandomNumberInRange(0.f, 500.f));
+
+ int time;
+ if (endOfAttack <= CTimer::GetTimeInMilliseconds())
+ time = CGeneral::GetRandomNumberInRange(100.0f, 1500.0f);
+ else
+ time = endOfAttack - CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(400.0f, 1500.0f);
+
+ SetAttackTimer(time);
+ bObstacleShowedUpDuringKillObjective = false;
+ }
+ return ATTACK_IN_PROGRESS;
+ } else {
+ if (!m_pedInObjective->m_pCurrentPhysSurface && m_pCurrentPhysSurface && b158_8) {
+ b158_8 = false;
+ bStopAndShoot = false;
+ }
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
+ SetMoveState(PEDMOVE_STILL);
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ StartFightAttack(0);
+ }
+ return ATTACK_IN_PROGRESS;
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::CanBeDamagedByThisGangMember(CPed* who)
+{
+ return m_gangFlags & (1 << (who->m_nPedType - PEDTYPE_GANG1));
+} \ No newline at end of file