re3/src/peds/PedAI.cpp

6905 lines
218 KiB
C++

#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"
CVector vecPedCarDoorAnimOffset;
CVector vecPedCarDoorLoAnimOffset;
CVector vecPedVanRearDoorAnimOffset;
CVector vecPedQuickDraggedOutCarAnimOffset;
CVector vecPedDraggedOutCarAnimOffset;
CVector vecPedTrainDoorAnimOffset;
CVector vecPedStdBikeJumpRhsAnimOffset;
CVector vecPedVespaBikeJumpRhsAnimOffset;
CVector vecPedHarleyBikeJumpRhsAnimOffset;
CVector vecPedDirtBikeJumpRhsAnimOffset;
CVector vecPedBikeKickAnimOffset;
void
CPed::SetObjectiveTimer(int time)
{
if (time == 0) {
m_objectiveTimer = 0;
} else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
}
}
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;
}
}
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;
}
}
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;
}
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;
}
}
}
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:
SetWeaponLockOnTarget((CEntity*)entity);
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;
}
}
void
CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
{
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 && m_distanceToCountSeekDone == safeDist)
return;
}
else if (newObj == OBJECTIVE_GUARD_SPOT) {
if (m_vecSpotToGuard == dest && m_radiusToGuard == safeDist)
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_GUARD_SPOT) {
m_vecSpotToGuard = dest;
m_radiusToGuard = safeDist;
}
else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA || newObj == OBJECTIVE_SPRINT_TO_AREA) {
m_pNextPathNode = nil;
m_nextRoutePointPos = dest;
m_vecSeekPos = m_nextRoutePointPos;
bUsePedNodeSeek = true;
}
}
// 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);
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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()) {
SetWeaponLockOnTarget(m_threatEntity);
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;
}
}
}
}
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;
}
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->GetWantedLevel() * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity);
m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
} else {
m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity * 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_vehDoor = 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_vehDoor = CAR_DOOR_RR;
foundSeat = true;
}
} else {
m_vehDoor = CAR_DOOR_LR;
foundSeat = true;
}
} else {
m_vehDoor = 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_vehDoor = CAR_DOOR_RF;
foundSeat = true;
}
}
if (foundSeat) {
SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehDoor));
SetEnterCar(m_carInObjective, m_vehDoor);
}
}
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 *= wepInfo->m_fRange / maxShotPos.Magnitude();
maxShotPos += ourHead;
CColPoint foundCol;
CEntity *foundEnt;
CWorld::bIncludeDeadPeds = true;
CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, true, true, true, true, false, true, false);
CWorld::bIncludeDeadPeds = false;
if (foundEnt == m_carInObjective) {
SetAttack(m_carInObjective);
SetWeaponLockOnTarget(m_carInObjective);
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_STD_HAILTAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
Say(SOUND_PED_TAXI_WAIT);
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HAILTAXI, 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_carJackTimer < 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_carJackTimer = 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_STD_PARTIAL_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_STD_PARTIAL_PUNCH, 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;
// FIX: ClearObjective() clears m_pedInObjective, 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_STD_PARTIAL_FUCKU, 8.0f);
newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
}
} else {
SetSeek(m_pedInObjective, 1.0f);
CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_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.fMaxCruiseVelocity;
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();
}
}
}
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());
}
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;
}
bool
CPed::HaveReachedNextPointOnRoute(float distToCountReached)
{
if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() < distToCountReached) {
m_routePointsPassed += m_routePointsBeingPassed;
return true;
}
return false;
}
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;
}
// 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_UZI || weaponType == WEAPONTYPE_MP5 || weaponType == WEAPONTYPE_M4 ||
weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
weaponType == WEAPONTYPE_SPAS12_SHOTGUN || weaponType == WEAPONTYPE_STUBBY_SHOTGUN ||
weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_FLAMETHROWER) {
SetCurrentWeapon(i);
return true;
}
}
}
SetCurrentWeapon(WEAPONTYPE_UNARMED);
return false;
}
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;
}
}
}
}
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_STD_KO_FRONT + 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.fMaxCruiseVelocity;
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);
}
}
}
}
}
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_vehDoor) {
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_vehDoor) {
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_vehDoor == 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_STD_BIKE_PICKUP_LHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PULLUP_LHS);
} else {
if (veh->GetRight().z < 0.0f)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PICKUP_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PULLUP_RHS);
}
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_LHS : ANIM_BIKE_JUMPON_RHS);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
((CBike*)veh)->bIsBeingPickedUp = true;
}
} else if (ped->m_vehDoor == 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_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR ? ANIM_STD_HIGHIMPACT_RIGHT : ANIM_STD_HIGHIMPACT_LEFT, 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_STD_BIKE_ELBOW_LHS : ANIM_STD_BIKE_ELBOW_RHS);
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_LHS : ANIM_BIKE_JUMPON_RHS);
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_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR ? ANIM_STD_HIGHIMPACT_RIGHT : ANIM_STD_HIGHIMPACT_LEFT, 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_STD_BIKE_ELBOW_LHS : ANIM_STD_BIKE_ELBOW_RHS);
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_LHS : ANIM_BIKE_JUMPON_RHS);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
((CBike*)veh)->bIsBeingPickedUp = true;
}
}
}
if (pedToDragOut) {
pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehDoor, 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_STD_VAN_GET_IN_REAR_RHS);
} else if (itsBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_RHS);
} else if (itsLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);
}
} else if (itsVan) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_LHS);
} else if (itsBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_LHS);
} else if (itsLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_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_STD_VAN_OPEN_DOOR_REAR_RHS);
} else if (itsBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_OPEN_RHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_OPEN_DOOR_RHS);
}
} else if (itsVan) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_OPEN_DOOR_REAR_LHS);
} else if (itsBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_OPEN_LHS);
} 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_STD_QUICKJACK);
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_vehDoor, 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_STD_CAR_JUMP_IN_LO_LHS);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
return;
}
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_OPEN_DOOR_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_STD_CARDOOR_LOCKED_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CARDOOR_LOCKED_LHS);
ped->bCancelEnteringCar = true;
ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
}
}
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_vehDoor) {
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_vehDoor != CAR_DOOR_LF && ped->m_vehDoor != CAR_DOOR_LR)
ped->SetFall(1000, ANIM_STD_HIGHIMPACT_LEFT, false);
else
ped->SetFall(1000, ANIM_STD_HIGHIMPACT_RIGHT, false);
return;
}
veh->ProcessOpenDoor(ped->m_vehDoor, ANIM_STD_CAR_OPEN_DOOR_LHS, 1.0f);
if (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_RF)
isVan = false;
if (ped->m_nPedState != PED_CARJACK || isBus) {
if (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR) {
if (veh->IsBike()) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_LHS);
} else if (isVan) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_LHS);
} else if (isBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_LHS);
} else if (isLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);
}
} else {
if (veh->IsBike()) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_RHS);
} else if (isVan) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_RHS);
} else if (isBus) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_RHS);
} else if (isLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);
}
if (ped->m_vehDoor == 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_vehDoor) {
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_vehDoor != CAR_DOOR_LF && ped->m_vehDoor != 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_STD_CAR_PULL_OUT_PED_LO_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_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_STD_CAR_GET_IN_LO_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_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_STD_CAR_PULL_OUT_PED_LO_LHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_LHS);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
}
} else {
if (isLow)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_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_vehDoor, false);
if (pedToDragOut->IsGangMember())
pedToDragOut->RegisterThreatWithGangPeds(ped);
}
}
}
return;
}
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_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR) {
if (veh->IsBike())
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_LHS);
else if (isLow)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);
} else {
if (veh->IsBike())
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_RHS);
else if (isLow)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);
}
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
} else {
ped->QuitEnteringCar();
}
} else if(ped->m_nPedState != PED_DRIVING) {
ped->QuitEnteringCar();
}
}
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_vehDoor == CAR_DOOR_LF
&& (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
&& veh->IsCar() && !veh->pDriver) {
if (!animAssoc || animAssoc->animId != ANIM_STD_CAR_JUMP_IN_LO_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_vehDoor) {
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_vehDoor != 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_STD_VAN_CLOSE_DOOR_REAR_RHS);
} else if (isLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LO_RHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_RHS);
}
} else if (isVan) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS);
} else if (isLow) {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LO_LHS);
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LHS);
}
ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
}
}
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_STD_CAR_SHUFFLE_LO_RHS : ANIM_STD_CAR_SHUFFLE_RHS);
m_objective = OBJECTIVE_ENTER_CAR_AS_DRIVER;
m_pMyVehicle->RemovePassenger(this);
bInVehicle = false;
m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
}
}
}
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_vehDoor, ANIM_STD_CAR_CLOSE_DOOR_LHS, 1.0f);
eDoors door;
switch (ped->m_vehDoor) {
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_vehDoor == 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_STD_CAR_SHUFFLE_LO_RHS);
else
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SHUFFLE_RHS);
ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
}
} else if (ped->m_nPedState != PED_DRIVING) {
ped->QuitEnteringCar();
}
}
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();
}
}
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;
}
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;
}
void
CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
{
CPed* ped = (CPed*)arg;
CVehicle* veh = ped->m_pMyVehicle;
if (animAssoc) {
if ((animAssoc->animId == ANIM_STD_ROLLOUT_LHS || animAssoc->animId == ANIM_STD_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_vehDoor, ANIM_STD_GETOUT_LHS, 1.0f);
/*
// Duplicate and only in PC for some reason
if (!veh) {
PedSetOutCarCB(nil, ped);
return;
}
*/
eDoors door;
switch (ped->m_vehDoor) {
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) {
#ifdef FIX_BUGS
if (!veh->IsDoorMissing(door))
((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
PedSetOutCarCB(nil, ped);
return;
#else
if (!veh->IsDoorMissing(door))
((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
#endif
} else {
switch (door) {
case DOOR_FRONT_LEFT:
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_LHS);
break;
case DOOR_FRONT_RIGHT:
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_RHS);
break;
case DOOR_REAR_LEFT:
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_LHS);
break;
case DOOR_REAR_RIGHT:
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_RHS);
break;
default:
break;
}
}
if (ped->m_pVehicleAnim)
ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
return;
}
void
CPed::LineUpPedWithCar(PedLineUpPhase phase)
{
bool vehIsUpsideDown = false;
bool stillGettingInOut = 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_RIDE_P)) {
SetPedPositionInCar();
return;
}
} else {
if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT)) {
SetPedPositionInCar();
return;
}
if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_LO)) {
SetPedPositionInCar();
return;
}
if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_P)) {
SetPedPositionInCar();
return;
}
if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_P_LO)) {
SetPedPositionInCar();
return;
}
}
bChangedSeat = true;
}
if (phase == LINE_UP_TO_CAR_FALL) {
SetPedPositionInCar();
autoZPos = GetPosition();
CPedPlacement::FindZCoorForPed(&autoZPos);
if (m_pVehicleAnim && (m_pVehicleAnim->animId == ANIM_STD_ROLLOUT_LHS || m_pVehicleAnim->animId == ANIM_STD_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_vehDoor == CAR_DOOR_RF || m_vehDoor == 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_vehDoor == CAR_DOOR_LF || m_vehDoor == 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_vehDoor == 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_STD_JACKEDCAR_RHS:
case ANIM_STD_JACKEDCAR_LO_RHS:
case ANIM_STD_JACKEDCAR_LHS:
case ANIM_STD_JACKEDCAR_LO_LHS:
case ANIM_STD_VAN_GET_IN_REAR_LHS:
case ANIM_STD_VAN_GET_IN_REAR_RHS:
multExtractedFromAnim = true;
zBlend = Max(m_pVehicleAnim->GetProgress() - 0.3f, 0.0f) / (1.0f - 0.3f);
// fall through
case ANIM_STD_QUICKJACKED:
case ANIM_STD_GETOUT_LHS:
case ANIM_STD_GETOUT_LO_LHS:
case ANIM_STD_GETOUT_RHS:
case ANIM_STD_GETOUT_LO_RHS:
if (!multExtractedFromAnim) {
multExtractedFromAnim = true;
zBlend = Max(m_pVehicleAnim->GetProgress() - 0.5f, 0.0f) / (1.0f - 0.5f);
}
// fall through
case ANIM_STD_CRAWLOUT_LHS:
case ANIM_STD_CRAWLOUT_RHS:
case ANIM_STD_VAN_GET_OUT_REAR_LHS:
case ANIM_STD_VAN_GET_OUT_REAR_RHS:
case ANIM_BIKE_GETOFF_LHS:
case ANIM_BIKE_GETOFF_RHS:
seatPosMult = m_pVehicleAnim->GetProgress();
break;
case ANIM_STD_CAR_GET_IN_RHS:
case ANIM_STD_CAR_GET_IN_LHS:
if (veh && veh->IsCar() && veh->bIsBus) {
multExtractedFromAnimBus = true;
zBlend = Min(m_pVehicleAnim->GetProgress(), 0.5f) / 0.5f;
}
// fall through
case ANIM_STD_QUICKJACK:
case ANIM_STD_CAR_GET_IN_LO_LHS:
case ANIM_STD_CAR_GET_IN_LO_RHS:
case ANIM_STD_BOAT_DRIVE:
seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
break;
case ANIM_STD_CAR_CLOSE_DOOR_LHS:
case ANIM_STD_CAR_CLOSE_DOOR_LO_LHS:
case ANIM_STD_CAR_CLOSE_DOOR_RHS:
case ANIM_STD_CAR_CLOSE_DOOR_LO_RHS:
case ANIM_STD_CAR_SHUFFLE_RHS:
case ANIM_STD_CAR_SHUFFLE_LO_RHS:
seatPosMult = 0.0f;
break;
case ANIM_STD_CAR_JUMP_IN_LO_LHS:
{
float animLength = m_pVehicleAnim->hierarchy->totalLength;
seatPosMult = Max(0.0f, 0.5f * animLength - m_pVehicleAnim->currentTime) / animLength;
break;
}
case ANIM_STD_CAR_CLOSE_LHS:
case ANIM_STD_CAR_CLOSE_RHS:
case ANIM_STD_COACH_OPEN_LHS:
case ANIM_STD_COACH_OPEN_RHS:
case ANIM_STD_COACH_GET_IN_LHS:
case ANIM_STD_COACH_GET_IN_RHS:
case ANIM_STD_COACH_GET_OUT_LHS:
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_vehDoor, 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_LHS && vehAnim != ANIM_BIKE_GETOFF_RHS) {
if (vehAnim != ANIM_BIKE_JUMPON_LHS && vehAnim != ANIM_BIKE_JUMPON_RHS) {
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_STD_VAN_GET_IN_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS && vehAnim != ANIM_STD_VAN_GET_IN_REAR_RHS) {
neededPos.z = autoZPos.z;
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
} else if (neededPos.z < currentZ && m_pVehicleAnim && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS) {
adjustedTimeStep = Max(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_STD_CAR_GET_IN_RHS || vehAnim == ANIM_STD_CAR_GET_IN_LO_RHS || vehAnim == ANIM_STD_CAR_GET_IN_LHS || vehAnim == ANIM_STD_CAR_GET_IN_LO_LHS
|| vehAnim == ANIM_STD_QUICKJACK || vehAnim == ANIM_STD_VAN_GET_IN_REAR_LHS || vehAnim == ANIM_STD_VAN_GET_IN_REAR_RHS)) {
adjustedTimeStep = Max(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);
}
}
}
}
}
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_vehDoor, 0.0f));
if (m_vehDoor == CAR_WINDSCREEN || veh->bIsBus) {
CMatrix correctionMat;
if (veh->bIsBus && (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR))
correctionMat.SetRotateZ(-HALFPI);
else if (veh->bIsBus && (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR))
correctionMat.SetRotateZ(HALFPI);
else
correctionMat.SetRotateZ(PI);
vehDoorMat = vehDoorMat * correctionMat;
}
GetMatrix() = vehDoorMat;
}
}
void
CPed::SetCarJack(CVehicle* car)
{
uint8 doorFlag;
eDoors door;
CPed *pedInSeat = nil;
if (car->IsBoat())
return;
if (car->IsBike()) {
switch (m_vehDoor) {
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_vehDoor) {
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_vehDoor, doorFlag);
}
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_vehDoor);
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_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_LHS : ANIM_STD_CAR_ALIGN_DOOR_LHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_RHS : ANIM_STD_CAR_ALIGN_DOOR_RHS, 4.0f);
m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
}
}
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_vehDoor = CAR_DOOR_LF;
else
m_vehDoor = CAR_DOOR_LR;
} else {
m_vehDoor = vehEnterType;
}
if (m_vehDoor == 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_vehDoor);
else
veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehDoor);
}
void
CPed::BeingDraggedFromCar(void)
{
AnimationId enterAnim;
bool dontRunAnim = false;
if (!m_pVehicleAnim) {
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 1000.0f);
AssocGroupId assocGroup;
if (m_pMyVehicle && m_pMyVehicle->IsBike()) {
enterAnim = ANIM_BIKE_HIT;
assocGroup = ((CBike*)m_pMyVehicle)->m_bikeAnimType;
} else {
if (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR) {
if (bWillBeQuickJacked && m_vehDoor == CAR_DOOR_LF) {
enterAnim = ANIM_STD_QUICKJACKED;
} else if (m_pMyVehicle->bLowVehicle) {
enterAnim = ANIM_STD_JACKEDCAR_LO_LHS;
} else {
enterAnim = ANIM_STD_JACKEDCAR_LHS;
}
} else if (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR) {
if (m_pMyVehicle->bLowVehicle)
enterAnim = ANIM_STD_JACKEDCAR_LO_RHS;
else
enterAnim = ANIM_STD_JACKEDCAR_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_vehDoor, ANIM_STD_NUM, m_pVehicleAnim->currentTime * mult);
}
}
}
void
CPed::SetEnterCar(CVehicle *car, uint32 unused)
{
if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
RestorePreviousState();
RestorePreviousObjective();
} else {
uint8 doorFlag;
eDoors door;
if (car->IsBike()) {
switch (m_vehDoor) {
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_vehDoor) {
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_vehDoor, doorFlag);
}
}
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_vehDoor = doorNode;
SetPedState(PED_ENTER_CAR);
if (m_vehDoor == 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_vehDoor);
// 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_STD_CAR_SIT, 100.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE, 100.0f);
PedSetInCarCB(nil, this);
bVehExitWillBeInstant = true;
} else if (car->IsBike()) {
PedAnimAlignCB(0, this);
car->AutoPilot.m_nCruiseSpeed = 0;
} else {
if (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_RHS : ANIM_STD_CAR_ALIGN_DOOR_RHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_LHS : ANIM_STD_CAR_ALIGN_DOOR_LHS, 4.0f);
m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
}
}
void
CPed::EnterCar(void)
{
if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
CVehicle *veh = m_pMyVehicle;
// Not used.
// CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehDoor);
if (veh->CanPedOpenLocks(this)) {
if (m_vehDoor && m_pVehicleAnim) {
veh->ProcessOpenDoor(m_vehDoor, 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_STD_BIKE_PICKUP_LHS || anim == ANIM_STD_BIKE_PICKUP_RHS) && m_pVehicleAnim->currentTime > 0.4667f)
bike->bIsBeingPickedUp = true;
else if ((anim == ANIM_STD_BIKE_PULLUP_LHS || anim == ANIM_STD_BIKE_PULLUP_RHS) && 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_STD_BIKE_ELBOW_LHS || anim == ANIM_STD_BIKE_ELBOW_RHS) {
DMAudio.PlayOneShot(m_audioEntityId, SOUND_186, 3.0f);
}
}
}
}
} else {
QuitEnteringCar();
SetDie();
}
}
void
CPed::QuitEnteringCar(void)
{
CVehicle *veh = m_pMyVehicle;
if (m_pVehicleAnim)
m_pVehicleAnim->blendDelta = -1000.0f;
RestartNonPartialAnims();
if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE))
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 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_vehDoor);
((CBike*)veh)->bIsBeingPickedUp = false;
} else
veh->m_nGettingInFlags &= ~GetEnterCarDoorFlag(m_vehDoor, 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;
}
}
void
CPed::SetExitBoat(CVehicle *boat)
{
SetPedState(PED_IDLE);
CVector newPos = GetPosition();
RemoveInCarAnims();
CColModel* boatCol = boat->GetColModel();
if (boat->IsUpsideDown()) {
newPos = CVector(0.0f, 0.0f, boatCol->boundingBox.min.z);
newPos = boat->GetMatrix() * newPos;
newPos.z += 1.0f;
m_vehDoor = 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_vehDoor = 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_vehDoor = 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;
}
// 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_vehDoor = firstOptedDoor;
PositionPedOutOfCollision();
teleportNeeded = true;
}
}
if (!teleportNeeded && veh->IsOnItsSide()) {
m_vehDoor = 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_vehDoor = 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_STD_IDLE, 100.0f);
veh->AutoPilot.m_nCruiseSpeed = 0;
if (teleportNeeded) {
PedSetOutCarCB(nil, this);
} else {
if (veh->GetUp().z <= -0.8f && !veh->IsBike()) {
if (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CRAWLOUT_RHS);
} else if (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CRAWLOUT_LHS);
}
m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
} else if (veh->IsBike()) {
CBike* bike = (CBike*)veh;
switch (m_vehDoor) {
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_RHS);
break;
case CAR_DOOR_LF:
case CAR_DOOR_LR:
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_LHS);
break;
default:
break;
}
int8 exitFlags = 0;
// Bike door flags incl. passenger jump off
switch (m_vehDoor) {
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_vehDoor == CAR_BUMP_REAR || m_vehDoor == CAR_BOOT) {
m_pVehicleAnim->SetFinishCallback(RestoreHeadingRateCB, this);
m_headingRate = 0.0f;
} else {
veh->m_nGettingOutFlags |= exitFlags;
m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
}
} else {
switch (m_vehDoor) {
case CAR_DOOR_RF:
if (canJumpOut) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_RHS);
} else if (veh->bIsBus) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_OUT_LHS);
} else {
if (isLow)
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_RHS);
else
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_RHS);
}
break;
case CAR_DOOR_RR:
if (canJumpOut) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_RHS);
} else if (veh->bIsVan) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_OUT_REAR_RHS);
} else if (isLow) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_RHS);
} else {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_RHS);
}
break;
case CAR_DOOR_LF:
if (canJumpOut) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_LHS);
} else if (veh->bIsBus) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_OUT_LHS);
} else {
if (isLow)
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_LHS);
else
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LHS);
}
break;
case CAR_DOOR_LR:
if (canJumpOut) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_LHS);
} else if (veh->bIsVan) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_OUT_REAR_LHS);
} else if (isLow) {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_LHS);
} else {
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LHS);
}
break;
default:
break;
}
if (!bBusJacked && !canJumpOut) {
veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehDoor);
}
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);
}
}
}
void
CPed::ExitCar(void)
{
if (!m_pVehicleAnim) {
if (InVehicle()) {
if (m_pMyVehicle->IsBike()) {
if (m_vehDoor == CAR_BOOT || m_vehDoor == CAR_BUMP_REAR) {
((CBike*)m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNARMED, 0, this, false);
}
} else if (m_pMyVehicle->IsCar()) {
if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_LHS)) {
((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_LF, this);
} else if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_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_STD_ROLLOUT_LHS || exitAnim == ANIM_STD_ROLLOUT_RHS) {
if (animTime > 0.07f && m_pMyVehicle && m_pMyVehicle->IsCar()) {
if (exitAnim == ANIM_STD_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_vehDoor, exitAnim, animTime);
if (m_pSeekTarget) {
// Car is upside down
if (m_pMyVehicle->GetUp().z > -0.8f) {
if (exitAnim == ANIM_STD_CAR_CLOSE_RHS || exitAnim == ANIM_STD_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_STD_HIGHIMPACT_FRONT, 1);
}
}
}
CVector
CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
{
CVector vehDoorPos = GetPositionToOpenCarDoor(veh, component, 1.0f);
/*
// Unused
vehDoorPosWithoutOffset = veh->GetMatrix() * localVehDoorPos;
*/
return vehDoorPos;
}
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_vehDoor ||
!IsPlayer() && m_nPedType != PEDTYPE_COP && m_nMoveState == PEDMOVE_RUN
&& m_pedStats->m_temper > 65
&& !m_vehDoor || m_vehDoor == CAR_WINDSCREEN)) {
m_vehDoor = CAR_WINDSCREEN;
posToOpen = GetPositionToOpenCarDoor(veh, CAR_WINDSCREEN);
return;
}
}
}
} else if (m_vehDoor == 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_vehDoor = CAR_DOOR_LF;
posToOpen = lfPos;
} else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
m_vehDoor = 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_vehDoor = CAR_DOOR_LF;
posToOpen = lfPos;
} else {
m_vehDoor = CAR_DOOR_RF;
posToOpen = rfPos;
}
} else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
m_vehDoor = CAR_DOOR_LF;
posToOpen = lfPos;
}
}
}
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_vehDoor = 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_vehDoor = CAR_DOOR_RF;
if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
m_vehDoor = CAR_DOOR_LR;
posToOpen = lrPos;
nextToCompare = lrPosDist;
}
if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
m_vehDoor = CAR_DOOR_RR;
posToOpen = rrPos;
}
return canEnter;
}
void
CPed::GoToNearestDoor(CVehicle *veh)
{
CVector posToOpen;
GetNearestDoor(veh, posToOpen);
SetSeek(posToOpen, 0.5f);
SetMoveState(PEDMOVE_RUN);
}
// 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_vehDoor == CAR_DOOR_RR || pPed->m_vehDoor == 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);
}
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_STD_JACKEDCAR_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_STD_CAR_GET_IN_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_STD_CAR_GET_IN_LO_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_STD_QUICKJACKED)->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_STD_VAN_GET_IN_REAR_LHS)->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;
}
}
enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_TRAIN_GETOUT)->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_LHS)->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_LHS)->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_LHS)->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_LHS)->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);
}
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_vehDoor == CAR_DOOR_RF || ped->m_vehDoor == 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_vehDoor, &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;
}
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_vehDoor == CAR_DOOR_RF || ped->m_vehDoor == 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_vehDoor, &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();
}
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_vehDoor];
doorPos.x -= 1.5f;
doorPos = Multiply3x3(trainMat, doorPos);
doorPos += train->GetPosition();
*/
return 1;
}
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_vehDoor = TRAIN_POS_MID_ENTRY;
} else {
enterPos = rightEntryPos;
m_vehDoor = TRAIN_POS_RIGHT_ENTRY;
}
} else if (distRightEntry < distLeftEntry) {
enterPos = rightEntryPos;
m_vehDoor = TRAIN_POS_RIGHT_ENTRY;
} else {
enterPos = leftEntryPos;
m_vehDoor = TRAIN_POS_LEFT_ENTRY;
}
return 1;
}
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);
SetPedState(PED_ENTER_TRAIN);
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_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);
*/
SetPedState(PED_EXIT_TRAIN);
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_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->SetPedState(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
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.fMaxCruiseVelocity * 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;
}
}
}
}
}
}
}
// 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);
}
}
}
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;
}
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;
}
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;
}
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;
}
}
// TODO: 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_STD_DUCK_WEAPON, 4.0f);
duckAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
bIsDucking = true;
m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
} else {
CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);
if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_DOWN, 4.0f);
bIsDucking = true;
m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
}
}
}
void
CPed::Duck(void)
{
if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
ClearDuck();
else if (bIsDucking && bCrouchWhenShooting) {
CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
CAnimBlendAssociation *crouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);
if (!crouchAnim) {
if(GetCrouchFireAnim(weapon))
crouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));
}
if (!crouchAnim) {
if(GetCrouchReloadAnim(weapon))
crouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(weapon));
}
if (!crouchAnim) {
bIsDucking = false;
#if defined FIX_BUGS || defined FREE_CAM
if (IsPlayer())
bCrouchWhenShooting = false;
#endif
}
}
}
void
CPed::ClearDuck(bool clearTimer)
{
CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);
}
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);
}
if (animAssoc) {
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
animAssoc->blendDelta = -4.0f;
}
bIsDucking = false;
if (clearTimer) {
m_duckTimer = 0;
}
}
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);
}
}
}
}
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_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS, 1.0f);
} else {
veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, 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);
}
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);
}
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_vehDoor = 0;
SetEnterCar(m_carInObjective, 0);
}
} else
RestorePreviousState();
}
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;
}
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_STD_CAR_SIT, 100.0f);
} else {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE, 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_RIDE_P, 100.0f);
}
} else {
if (isDriver) {
if (car->bLowVehicle) {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_LO, 100.0f);
} else {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT, 100.0f);
}
} else {
if (car->bLowVehicle) {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_P_LO, 100.0f);
} else {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_P, 100.0f);
}
}
}
StopNonPartialAnims();
}
void
CPed::RemoveDrivebyAnims()
{
CAnimBlendAssociation *animAssoc;
AnimationId LeftAnim = ANIM_STD_CAR_DRIVEBY_LEFT;
AnimationId RightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT;
if (m_pMyVehicle->pHandling->Flags & HANDLING_IS_BIKE) {
LeftAnim = ANIM_BIKE_DRIVEBY_RHS;
RightAnim = ANIM_BIKE_DRIVEBY_LHS;
} else if (m_pMyVehicle->bLowVehicle) {
LeftAnim = ANIM_STD_CAR_DRIVEBY_LEFT_LO;
RightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT_LO;
}
animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_RHS);
if (animAssoc)
animAssoc->blendDelta = -1000.0f;
animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_LHS);
if (animAssoc)
animAssoc->blendDelta = -1000.0f;
animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_FORWARD);
if (animAssoc)
animAssoc->blendDelta = -1000.0f;
}
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;
}
}
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_vehDoor != 0) {
// Try the normal way
CVector pos = GetPositionToOpenCarDoor(m_pMyVehicle, m_vehDoor);
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_vehDoor == CAR_DOOR_RF || m_vehDoor == 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;
}
// "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 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;
}
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;
}
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;
}
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/* TODO: && !bAttacksPlayerWithCops*/) {
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);
SetWeaponLockOnTarget(vehOfTarget);
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_vehDoor = 0;
if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
m_vehDoor = CAR_DOOR_LF;
} else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
m_vehDoor = CAR_DOOR_RF;
} else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
m_vehDoor = CAR_DOOR_LR;
} else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
m_vehDoor = CAR_DOOR_RR;
}
// Unused
// GetPositionToOpenCarDoor(vehOfTarget, m_vehDoor);
SetSeekCar(vehOfTarget, m_vehDoor);
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_STD_DUCK_DOWN);
if (!duckAnim)
duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);
if (!duckAnim)
duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);
if (duckAnim) {
duckAnim->flags |= ASSOC_DELETEFADEDOUT;
duckAnim->blendDelta = -4.0f;
}
bIsDucking = false;
return CANT_ATTACK;
}
bObstacleShowedUpDuringKillObjective = false;
SetAttack(m_pedInObjective);
SetWeaponLockOnTarget(m_pedInObjective);
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;
}
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 maxDistToKeep = 0.3f;
float wepRange = wepInfo->m_fRange / 2.f;
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
wepRange -= 0.3f;
if (distWithTargetSc <= 5.f && victimPlayer && !victimPlayer->m_bNoPosForMeleeAttack) {
if (m_pedInObjective->EnteringCar() && wepRange > 2.f) {
m_vecSeekPos = m_pedInObjective->GetPosition();
wepRange = 1.0f;
maxDistToKeep = 0.5f;
} else {
int8 attackDir = victimPlayer->FindMeleeAttackPoint(this, distWithTarget, endOfAttack);
if (attackDir == -1) {
m_vecSeekPos = victimPlayer->GetPosition();
maxDistToKeep = 4.0f;
} else {
victimPlayer->GetMeleeAttackCoords(m_vecSeekPos, attackDir, wepRange);
distWithTargetSc = (m_vecSeekPos - GetPosition()).Magnitude();
canReachVictim = true;
}
}
} else {
m_vecSeekPos = m_pedInObjective->GetPosition();
maxDistToKeep = Max(0.8f, 0.9f * wepRange);
wepRange *= 1.1f;
if (victimPlayer && victimPlayer->m_bNoPosForMeleeAttack)
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_vehDoor = 0;
if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
m_vehDoor = CAR_DOOR_LF;
} else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
m_vehDoor = CAR_DOOR_RF;
} else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
m_vehDoor = CAR_DOOR_LR;
} else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
m_vehDoor = CAR_DOOR_RR;
}
// Unused
// GetPositionToOpenCarDoor(vehOfTarget, m_vehDoor);
SetSeekCar(vehOfTarget, m_vehDoor);
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 > maxDistToKeep && !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 / wepRange;
CVector distVec = GetPosition() - m_pedInObjective->GetPosition();
float distSqr = distVec.MagnitudeSqr();
if (sq(wepRange) > 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_STD_FIGHT_SHUFFLE_B, 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, maxDistToKeep);
else
SetSeek(m_pedInObjective, maxDistToKeep);
}
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) {
CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);
if (!duckAnim)
duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);
if (!duckAnim)
duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);
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;
}
}
bool
CPed::CanBeDamagedByThisGangMember(CPed* who)
{
return m_gangFlags & (1 << (who->m_nPedType - PEDTYPE_GANG1));
}